JeeSite Vue3 å‰ç«¯æºç
使用 Turborepoã€Monorepoã€pnpm
å¿«é€Ÿæž„å»ºã€æ¨¡å—化ã€ä»£ç å¤ç”¨ã€é«˜æ•ˆç®¡ç†
- å•仓多包 pnpm + Turborepo 涡轮增压,æå‡ç¼–译速度,方便统一管ç†è„šæœ¬ä»»åŠ¡
- 按功能模å—进行拆分为ä¸åŒçš„åŒ…ï¼Œæ–¹ä¾¿è¿›è¡Œå›¢é˜Ÿå¼€å‘æºç 管ç†ï¼Œå¯æ ¹æ®éœ€è¦è¿›è¡Œå‘包
- 模å—之间æ¾è€¦åˆï¼Œå•ä¾èµ–,公共模å—,公共组件,公共工具,方便代ç å¤ç”¨
- 坿–¹ä¾¿ä»Žä¼ 统架构版本,å‡çº§åˆ° Monorepo 模å—化ã€åˆ†åŒ…æž¶æž„
- 官方网站:https://jeesite.com
- 使用文档:https://jeesite.com/docs
- 问题å馈:http://jeesite.net  | gitcode  | 新手必读
- è”系我们:http://s.jeesite.com
- 关注微信公众å·ï¼Œäº†è§£æœ€æ–°åЍæ€ï¼š
- QQ 群:
127515876
ã€209330483
ã€223507718
ã€709534275
ã€730390092
ã€1373527
ã€183903863(外包)
- 微信群:如果二维ç 过期,请å°è¯•点击图片并F5åˆ·æ–°ï¼Œæˆ–è€…æ·»åŠ å®¢æœå¾®ä¿¡ jeesitex 邀请您进群
- åŽç«¯æºç 仓库地å€ï¼š Gitee〠GitCode〠GitHub
- å‰ç«¯æºç 仓库地å€ï¼š Gitee〠GitCode〠GitHub
- æºç åˆé›†ä»“库地å€ï¼š GVP〠G-Star〠GitHub
-
JeeSite 快速开å‘å¹³å°ï¼Œä½Žä»£ç ,轻é‡çº§ï¼Œä¸ä»…仅是一个åŽå°å¼€å‘框架,它是一个ä¼ä¸šçº§å¿«é€Ÿå¼€å‘解决方案,åŽç«¯åŸºäºŽç»å…¸ç»„åˆ Spring Bootã€Shiroã€MyBatis,å‰ç«¯é‡‡ç”¨åˆ†ç¦»ç‰ˆ Vue3ã€Viteã€Monorepoã€Ant Design Vueã€TypeScriptã€Vben Admin æœ€å…ˆè¿›æŠ€æœ¯æ ˆï¼Œæˆ–è€… Beetlã€Bootstrapã€AdminLTE ç»å…¸å¼€å‘模å¼ã€‚
-
æä¾›åœ¨çº¿æ•°æ®æºç®¡ç†ã€æ•°æ®è¡¨å»ºæ¨¡ã€ä»£ç 生æˆç‰åŠŸèƒ½ï¼Œå¯è‡ªåŠ¨åˆ›å»ºä¸šåŠ¡æ¨¡å—代ç 工程和微æœåŠ¡æ¨¡å—代ç 工程,自动生æˆå‰ç«¯ä»£ç å’ŒåŽç«¯ä»£ç ï¼›åŒ…æ‹¬æ ¸å¿ƒåŠŸèƒ½æ¨¡å—如:组织机构ã€ç”¨æˆ·ã€è§’色ã€å²—ä½ã€ç®¡ç†å‘˜ã€æƒé™å®¡è®¡ã€èœå•åŠæŒ‰é’®æƒé™ã€æ•°æ®æƒé™ã€æ¨¡å—管ç†ã€ç³»ç»Ÿå‚æ•°ã€å—典管ç†ã€ç³»ç»Ÿç›‘æŽ§ã€æ•°æ®ç›‘控ç‰ï¼›æ‰©å±•功能如:工作æµå¼•擎ã€å†…容管ç†ã€æ¶ˆæ¯æŽ¨é€ã€å•点登录ã€ç¬¬ä¸‰æ–¹ç™»å½•ã€åœ¨çº¿ä½œä¸šè°ƒåº¦ã€å¯¹è±¡å˜å‚¨ã€å¯è§†åŒ–æ•°æ®å¤§å±ã€æŠ¥è¡¨è®¾è®¡å™¨ã€åœ¨çº¿æ–‡ä»¶é¢„览ã€å›½é™…化ã€å…¨æ–‡æ£€ç´¢ã€ç»Ÿä¸€è®¤è¯æœåŠ¡ç‰ã€‚
-
本平å°é‡‡ç”¨æ¾è€¦åˆè®¾è®¡ï¼ŒçœŸæ£çš„è½»é‡çº§ï¼Œå¾®å†…æ ¸ï¼Œå¿«é€Ÿéƒ¨ç½²ï¼Œæ’件架构,模å—增å‡ä¾¿æ·ï¼Œæ”¯æŒæ‰©å±• SaaS æž¶æž„ã€é›†ç¾¤éƒ¨ç½²ã€è¯»å†™åˆ†ç¦»ã€åˆ†åº“分表ã€Spring Cloud å¾®æœåŠ¡æž¶æž„ï¼›å¹¶å†…ç½®äº†ä¼—å¤šè´¦å·å®‰å…¨è®¾ç½®ã€å¯†ç ç–ç•¥ã€ç³»ç»Ÿè®¿é—®é™åˆ¶ç‰å®‰å…¨è§£å†³æ–¹æ¡ˆï¼Œæ”¯æŒç‰ä¿è¯„测。
-
本平å°ä¸“注于为åˆçº§ç ”å‘人员æä¾›å¼ºå¤§çš„æ”¯æŒï¼Œä½¿ä»–们能够高效ã€å¿«é€Ÿåœ°å¼€å‘å‡ºå¤æ‚çš„ä¸šåŠ¡åŠŸèƒ½ï¼ŒåŒæ—¶ä¸ºä¸é«˜çº§äººå‘˜è…¾å‡ºå®è´µçš„æ—¶é—´ï¼Œä¸“注于更具战略性和创新性的任务。我们致力于让开å‘者能够全心投入业务逻辑ä¸ï¼Œè€Œå°†ç¹ççš„æŠ€æœ¯ç»†èŠ‚äº¤ç”±å¹³å°æ¥å°è£…处ç†ã€‚è¿™ä¸ä»…é™ä½Žäº†æŠ€æœ¯å®žçŽ°çš„éš¾åº¦ï¼Œè¿˜ç¡®ä¿äº†ç³»ç»Ÿæž¶æž„的稳定性和安全性,进而帮助ä¼ä¸šèŠ‚çœäººåŠ›æˆæœ¬ã€ç¼©çŸé¡¹ç›®å‘¨æœŸï¼Œå¹¶æé«˜æ•´ä½“软件的安全性和质é‡ã€‚
-
2013 å¹´å‘布以æ¥å·²è¢«å¹¿å¤§çˆ±å¥½è€…用到了ä¼ä¸šã€æ”¿åºœã€åŒ»ç–—ã€é‡‘èžã€äº’è”网ç‰å„个领域ä¸ï¼Œæ‹¥æœ‰ï¼šç²¾è‰¯æž¶æž„ã€æ˜“于扩展ã€å¤§ä¼—æ€ç»´çš„设计模å¼ï¼Œå·¥åŒ 精神,用心打磨æ¯ä¸€ä¸ªç»†èŠ‚ï¼Œæ·±å…¥å¼€å‘者的内心,并è£èŽ·å¼€æºä¸å›½ã€Šæœ€å—欢迎ä¸å›½å¼€æºè½¯ä»¶ã€‹å¤šæ¬¡å¥–项,期间也帮助了ä¸å°‘刚毕业的大å¦ç”Ÿï¼Œæ•™å¸ˆä½œä¸ºå…¥é—¨æ•™æï¼Œå¿«é€Ÿçš„去实践。
-
2019 å¹´æ¢ä»£å‡çº§ï¼Œæˆ‘们结åˆäº†å¤šå¹´æ€»ç»“å’Œç»éªŒï¼Œä»¥åŠå„æ–¹é¢çš„应用案例,对架构完æˆäº†ä¸€æ¬¡å…¨éƒ¨é‡æž„,也纳入很多新的æ 9E88 €æƒ³ã€‚ä¸ç®¡æ˜¯ä»Žå¼€å‘者模å¼ã€åº•层架构ã€é€»è¾‘处ç†è¿˜æ˜¯åˆ°ç”¨æˆ·ç•Œé¢ï¼Œç”¨æˆ·äº¤äº’体验上都有很大的进æ¥ï¼Œåœ¨ä¸å¿˜å¦ä¹ æˆæœ¬ã€æé«˜å¼€å‘效率的情况下,安全方é¢ä¹Ÿåšå’Œå¾ˆå¤šå·¥ä½œï¼ŒåŒ…括:身份认è¯ã€å¯†ç ç–ç•¥ã€å®‰å…¨å®¡è®¡ã€æ—¥å¿—收集ç‰ä¼—多安全选项供您选择。努力为大ä¸å°å¾®ä¼ä¸šæ‰“é€ å…¨æ–¹ä½ä¼ä¸šçº§å¿«é€Ÿå¼€å‘解决方案。
-
2021 年终å‘布 Vue3 çš„å‰åŽåˆ†ç¦»ç‰ˆæœ¬ï¼Œä½¿å¾— JeeSite 拥有åŒä¸€ä¸ªåŽå°æœåŠ¡ Web æ¥æ”¯æ’‘åˆ†ç¦»ç‰ˆå’Œå…¨æ ˆç‰ˆä¸¤å¥—å‰ç«¯æŠ€æœ¯æ ˆã€‚
-
å¯¹æŽ¥å¸¸è§ AI 大模型(OpenAPIã€Ollamaã€DeepSeekç‰ï¼‰ï¼Œæ”¯æŒæ£€ç´¢å¢žå¼ºç”Ÿæˆ RAG 技术,实现ä¼ä¸šçŸ¥è¯†åº“智能对è¯ã€‚
-
支æŒå›½äº§åŒ–è½¯ç¡¬ä»¶çŽ¯å¢ƒï¼Œå¦‚å›½äº§èŠ¯ç‰‡ã€æ“ä½œç³»ç»Ÿã€æ•°æ®åº“ã€ä¸é—´ä»¶ã€å›½å¯†ç®—法ç‰ã€‚
-
JeeSite éžå¸¸æ˜“于二次开å‘ï¼Œå¯æŽ§æ€§é«˜ï¼Œæ•´ä½“æž¶æž„æ¸…æ™°ã€æŠ€æœ¯ç¨³å®šè€Œå…ˆè¿›ã€æºä»£ç 书写规范ã€ç»å…¸æŠ€æœ¯ä¼šçš„äººå¤šã€æ˜“äºŽç»´æŠ¤ã€æ˜“于扩展ã€å®‰å…¨ç¨³å®šã€‚
-
JeeSite 功能全,知识点éžå¸¸å¤šï¼Œä¹Ÿéžå¸¸å°‘ã€‚å› ä¸ºå¥¹ä½¿ç”¨çš„éƒ½æ˜¯ä¸€äº›é€šç”¨çš„æŠ€æœ¯ï¼Œé€šä¿—çš„è®¾è®¡é£Žæ ¼ï¼Œå¤§å¤šæ•°åŸºç¡€çŸ¥è¯†ç‚¹ï¼Œå¤šæ•°äººéƒ½èƒ½æŽŒæ¡ï¼Œæ‰€ä»¥æ¯ä¸€ä¸ª JeeSite 的功能点都éžå¸¸å®¹æ˜“掌æ¡ã€‚åªè¦æ‚¨å¦ä¼šä½¿ç”¨è¿™äº›åŠŸèƒ½å’Œç»„ä»¶çš„åº”ç”¨ï¼Œå°±å¯ä»¥é¡ºåˆ©åœ°å®Œæˆç³»ç»Ÿå¼€å‘了。
-
JeeSite 是一个低代ç å¼€å‘å¹³å°ï¼Œå…·æœ‰è¾ƒé«˜çš„å°è£…åº¦ã€æ‰©å±•性,å°è£…䏿˜¯é™åˆ¶æ‚¨åŽ»åšä¸€äº›äº‹æƒ…,而是在便æ·çš„åŒæ—¶ï¼Œä¹Ÿå…·æœ‰è¾ƒå¥½çš„æ‰©å±•性,在ä¸å…·å¤‡ä¸€äº›åŠŸèƒ½çš„æƒ…å†µä¸‹ï¼ŒJeeSite æä¾›äº†æ‰©å±•接å£ï¼Œæä¾›äº†åŽŸç”Ÿè°ƒç”¨æ–¹æ³•ã€‚
-
大家都在用 Spring,也在å¦ä¹ Spring 的优点,Spring æä¾›äº†è¾ƒå¥½çš„æ‰©å±•性,å¯åˆæœ‰å¤šå°‘人去修改它的æºä»£ç 呢,退一æ¥è¯´ï¼Œå¤§å®¶åŽ»ä¿®æ”¹äº† Spring çš„æºç ,å而会对未æ¥å‡çº§é€ æˆå¾ˆå¤§å›°æ‰°ï¼Œæ‚¨è¯´ä¸æ˜¯å‘¢ï¼Ÿè¿™æ ·çš„例å很多,所以ä¸è¦çº 结,我们éžå¸¸æ³¨é‡è¿™ä¸€ç‚¹ï¼ŒJeeSite ä¹Ÿä¸€æ ·å…·å¤‡å¼ºå¤§çš„æ‰©å±•æ€§ã€‚ä¸ºä½ è§£å†³å‡çº§çš„困扰。
-
为什么说 JeeSite 比较易于å¦ä¹ ?JeeSite 很好的把æ¡äº†è®¾è®¡çš„ “度â€ï¼Œé¿å…过度设计的情况。过度设计是在产å“设计过程ä¸å¿½ç•¥äº†äº§å“和用户的实际需求,å而带æ¥äº†ä¸å¿…è¦çš„夿‚性,而忽略了系统的å¦ä¹ ã€å¼€å‘å’Œç»´æŠ¤æˆæœ¬ã€‚
- 至今 JeeSite 平尿ž¶æž„å·²ç»éžå¸¸ç¨³å®šï¼Œæˆ‘们æŒç»å‡çº§ï¼Œå¹¶ä¸å¤±æž¶æž„的先进性。
- JeeSite 精益求精,用心打磨æ¯ä¸€ä¸ªç»†èŠ‚ï¼Œç•Œé¢ UI æ“作便æ·ï¼Œä½“验性好。
- JeeSite 是一个专业的平å°ï¼Œæ˜¯ä¸€ä¸ªå¯ä»¥è®©æ‚¨ä½¿ç”¨æ”¾å¿ƒçš„å¹³å°ã€‚
- 社区版基于 Apache License 2.0 å¼€æºå议,永久å…费使用。
架构特点åŠå®‰å…¨æ–¹é¢çš„优势:https://jeesite.com/docs/feature/
基于 Vue3ã€Viteã€Ant-Design-Vueã€TypeScript å’Œ Vue Vben Admin ç‰å‰æ²¿æŠ€æœ¯æ ˆæž„建,本软件采用最先进的技术架构, 帮助åˆå¦è€…快速上手并èžå…¥å›¢é˜Ÿå¼€å‘。内置组织机构ã€è§’色用户ã€èœå•授æƒã€æ•°æ®æƒé™ã€ç³»ç»Ÿå‚æ•°ç‰æ ¸å¿ƒæ¨¡å—,结åˆå¼ºå¤§çš„组件å°è£… 与数æ®é©±åŠ¨è§†å›¾è®¾è®¡ï¼Œä¸ºå¾®å°ã€ä¸å¤§åž‹é¡¹ç›®æä¾›å¼€ç®±å³ç”¨çš„解决方案和丰富的示例,助力高效开å‘。
用户界é¢ä¸“为信æ¯åŒ–管ç†åŽå°é‡èº«æ‰“é€ ï¼Œåœ¨ç•Œé¢è®¾è®¡ä¸Šç²¾ç›Šæ±‚精,æ¯ä¸€å¤„细节都彰显ç€ç²¾è‡´ï¼Œä¸ºç”¨æˆ·å¸¦æ¥ä¼˜é›…且直观的æ“作体验。 它æä¾›å¤šæ ·åŒ–çš„èœå•å¸ƒå±€ã€æ™ºèƒ½çš„页ç¾ç®¡ç†ã€é«˜æ•ˆçš„æ ‘表æ“作体验ã€å¼ºå¤§çš„è¡¨æ ¼ç»„ä»¶ã€çµæ´»çš„表å•组件设计,具备强大的扩展能力, åŒæ—¶æ”¯æŒé»‘æš—å¸ƒå±€é£Žæ ¼ï¼Œä¸ºç”¨æˆ·æä¾›é«˜æ•ˆã€çµæ´»ä¸”美观的æ“作体验,满足å„类管ç†åŽå°çš„夿‚需求。
å¦å¤–æˆ‘ä»¬è¿˜æ”¯æŒ Turborepo + Monorepo å¿«é€Ÿæž„å»ºã€æ¨¡å—化ã€ä»£ç å¤ç”¨ã€æ”¯æŒåˆ†åŒ…å¼€å‘ è¯¦è§ï¼šhttps://gitee.com/thinkgem/jeesite-vue/tree/monorepo/
定义众多组件,éžå¸¸è´´å¿ƒçš„组件属性åŠå°åŠŸèƒ½ï¼Œç¬¦åˆ JeeSite ä»¥å¾€çš„è®¾è®¡æ€æƒ³ï¼Œåˆ—表和表å•以数æ®é©±åŠ¨è§†å›¾ï¼Œ æžå¤§ç®€åŒ–了业务功能开å‘, 注释分解详è§ã€æºç è§£æžã€‘
ä¸ºä»€ä¹ˆåšæ•°æ®é©±åŠ¨è§†å›¾ï¼Ÿå‰ç«¯å‘ä¸‹å…¼å®¹ä¸€ç›´æ˜¯æœ€å¤§çš„é—®é¢˜ï¼Œæœ‰äº†ä¸€å¥—ç›¸åº”çš„æ ‡å‡†ï¼Œä¼šå¯¹æ¡†æž¶å‡çº§å¸®åŠ©å¾ˆå¤§ã€‚ æ¯”å¦‚ä½ å¯ä»¥éžå¸¸å°çš„æˆæœ¬ï¼Œä¸šåŠ¡ä»£ç æ”¹åЍéžå¸¸å°çš„æƒ…况下,去å‡çº§å‰ç«¯ï¼›æ•°æ®é©±åŠ¨è§†å›¾å¯ä»¥ä¸ºæœªæ¥è‡ªå®šä¹‰æ‹–拽表å•åšæ›´å¥½çš„铺垫, æ•°æ®å˜å‚¨ç»“构更清晰化,更利于维护。
æç¤ºï¼šè¯·ä»”细阅读æºç è§£æžï¼Œè¡¨å•è§†å›¾å’Œåˆ—è¡¨è§†å›¾ä¸Šçš„æ³¨é‡Šå“¦ï¼Œå¤æ‚表å•å¯ä»¥å¤šè¡¨å•è”åˆä½¿ç”¨ã€‚
- 地å€ï¼šhttp://vue.jeesite.com/
- VSCode - 推è IDE 集æˆå¼€å‘工具
- Node.js 18 å’Œ git - å¼€å‘环境
- Vite - 熟悉 Vite 特性
- Vue-v3 - 熟悉 Vue åŸºç¡€è¯æ³•
- TypeScript - 熟悉 TS åŸºæœ¬è¯æ³•
- ES6+ - 熟悉 ES6 åŸºæœ¬è¯æ³•
- Vue-Router-v4 - 熟悉 vue-router 基本使用
- Vue-Vben-Admin - 熟悉 UI åŠè¡¨å•列表åŠå¸¸ç”¨ç»„件使用
- Ant-Design-Vue - 熟悉 UI 基本使用
- 如果没有安装 Node.js 18+,下载地å€ï¼šhttps://nodejs.org
# 验è¯
node -v
# é…置国内æº
npm config set registry https://registry.npmmirror.com
- 如果没有安装 Pnpm 执行安装
npm i -g pnpm
# 验è¯
pnpm -v
# é…置国内æº
pnpm config set registry https://registry.npmmirror.com
- èŽ·å–æºä»£ç
git clone https://gitee.com/thinkgem/jeesite-vue.git
cd jeesite-vue
注æ„:ä¸è¦æ”¾åˆ°ä¸æ–‡æˆ–å¸¦ç©ºæ ¼çš„ç›®å½•ä¸‹ã€‚
- 安装ä¾èµ–
pnpm install
- å¼€å‘环境è¿è¡Œè®¿é—®ï¼ˆæ–¹å¼ä¸€ï¼‰
pnpm dev
å¼€å‘çŽ¯å¢ƒä¼šåŠ è½½æ–‡ä»¶è¾ƒå¤šï¼Œä¾¿äºŽè°ƒè¯•ï¼Œè¯·è€å¿ƒç‰å¾…。
- 编译打包åŽè¿è¡Œè®¿é—®ï¼ˆæ–¹å¼äºŒï¼‰
pnpm preview
编译打包åŽï¼Œä¼šæ•´åˆè¿™äº›æ–‡ä»¶ï¼Œæ‰€ä»¥è®¿é—®æ€§èƒ½ä¼šå¤§å¤§æé«˜ï¼Œç”Ÿäº§çŽ¯å¢ƒå¯ä»¥å¼€å¯ gzip
- 打包å‘布程åº
pnpm build
打包完æˆåŽï¼Œä¼šåœ¨æ ¹ç›®å½•ç”Ÿæˆ dist 文件夹,å‘布 nginx。
è¯¦è§æ–‡æ¡£ï¼šhttps://jeesite.com/docs/vue-install-deploy/#部署到æ£å¼æœåС噍
- 安装åŽå°æœåŠ¡ JeeSite v5.x
- 打开 .env.development 文件,修改åŽå°æŽ¥å£ï¼š
# 代ç†è®¾ç½®ï¼Œå¯é…置多个,ä¸èƒ½æ¢è¡Œï¼Œæ ¼å¼ï¼š[访问接å£çš„æ ¹è·¯å¾„, 代ç†åœ°å€, 是å¦ä¿æŒHost头]
# VITE_PROXY = [["/js","https://vue.jeesite.com/js",true]]
VITE_PROXY = [["/js","http://127.0.0.1:8980/js",false]]
# 访问接å£çš„æ ¹è·¯å¾„(例如:https://vue.jeesite.com)
VITE_GLOB_API_URL =
# 访问接å£çš„å‰ç¼€ï¼Œåœ¨æ ¹è·¯å¾„之åŽ
VITE_GLOB_API_URL_PREFIX = /js
- UnoCSS - UnoCSS æç¤ºæ’ä»¶
- Iconify - Iconify å›¾æ ‡æ’ä»¶
- I18n-ally - i18n æ’ä»¶
- Volar - Vue3 å¼€å‘必备(Veturç¦ç”¨ï¼‰
- ESLint - è„šæœ¬ä»£ç æ£€æŸ¥
- Prettier - ä»£ç æ ¼å¼åŒ–
- Stylelint - CSS æ ¼å¼åŒ–
- DotENV - .env 文件高亮
- Vue 版本的æµè§ˆå™¨æ”¯æŒæƒ…å†µï¼šæ”¯æŒæ‰€æœ‰çް代æµè§ˆå™¨ï¼ŒVue3 å·²ä¸å†æ”¯æŒ IE æµè§ˆå™¨ã€‚
- 为什么使用抽屉作为表å•ç»„ä»¶ï¼Œå› ä¸ºæŠ½å±‰ç©ºé—´æ›´å¤§ï¼Œå¯ä»¥å±•示更多内容,且æ“作更å‹å¥½ã€‚
- å¦‚ä½•å°†è¡¨å•æŠ½å±‰æ”¹ä¸ºå¼¹çª—ï¼Œæ›¿æ¢ list å’Œ form 页é¢çš„ Drawer 为 Modal å³å¯ï¼ŒV5.6å¢žåŠ äº†è·¯ç”±è¡¨å•和弹窗表å•的代ç 生æˆã€‚
- 打ä¸å¼€ä»£ç 生æˆå·¥å…·æ€Žä¹ˆåŠžï¼Ÿæç¤º 404,请检查 .env.development ä¸çš„代ç†é…ç½® VITE_PROXY 最åŽä¸€ä¸ªå‚数(是å¦ä¿æŒHost头),本地æœåŠ¡ 127.0.0.1 应设置为 false,远程æœåŠ¡è®¾ç½®ä¸º true。
<template>
<!-- 弹出抽屉组件,如果想改为弹窗,Drawer æ¢ä¸º Modal å³å¯å¿«é€Ÿæ›¿æ¢ -->
<BasicDrawer
v-bind="$attrs" -- ä¼ é€’æ¥è‡ªçˆ¶ç»„件的属性
:showFooter="true" -- 显示弹窗底部按钮组
:okAuth="'test:testData:edit'" -- æäº¤æŒ‰é’®æƒé™ï¼ŒæŽ§åˆ¶æŒ‰é’®æ˜¯å¦æ˜¾ç¤º
@register="registerDrawer" -- 弹窗åŽçš„回调方法
@ok="handleSubmit" -- æäº¤æŒ‰é’®è°ƒç”¨æ–¹æ³•
width="60%" -- å¼¹çª—å®½åº¦ï¼Œæ”¯æŒæŒ‰æ¯”例
>
<!-- å¼¹çª—æ ‡é¢˜ -->
<template #title>
<Icon :icon="getTitle.icon" class="pr-1 m-1" /> -- å›¾æ ‡
<span> {{ getTitle.value }} </span> -- æ ‡é¢˜åç§°
</template>
<!-- 表å•组件 -->
<BasicForm @register="registerForm">
<!-- å®šä¹‰è¡¨å•æŽ§ä»¶æ’æ§½ã€ä¸ªæ€§åŒ–è¡¨å•æŽ§ä»¶ï¼Œå¦‚ï¼šè¿™æ˜¯ä¸€ä¸ªè¡¨å•åè¡¨æ’æ§½ -->
<template #testDataChildList>
<BasicTable
@register="registerTestDataChildTable"
@row-click="handleTestDataChildRowClick"
/>
<!-- å表新增按钮 -->
<a-button class="mt-2" @click="handleTestDataChildAdd">
<Icon icon="i-ant-design:plus-circle-outlined" /> {{ t('新增') }}
</a-button>
</template>
</BasicForm>
</BasicDrawer>
</template>
<!-- script name: 当å‰ç»„ä»¶å称(与路由å一致,如果ä¸ä¸€è‡´ä¼šé¡µé¢ç¼“å˜å¤±æ•ˆï¼‰-->
<script lang="ts" setup name="ViewsTestTestDataForm">
// 导入当å‰ç”¨åˆ°çš„对象,部分çœç•¥
import { ref, unref, computed } from 'vue';
import { officeTreeData } from '/@/api/sys/office';
// 页é¢äº‹ä»¶å®šä¹‰
const emit = defineEmits(['success', 'register']);
// å›½é™…åŒ–æ–¹æ³•è°ƒç”¨ï¼Œå‚æ•°æ˜¯å›½é™…化编ç çš„æ ¹è·¯å¾„
const { t } = useI18n('test.testData');
// 消æ¯å¼¹çª—方法
const { showMessage } = useMessage();
// 路由metaä¿¡æ¯
const { meta } = unref(router.currentRoute);
// 当å‰é¡µé¢æ•°æ®è®°å½•
const record = ref<Recordable>({});
// 当å‰é¡µé¢æ ‡é¢˜å®šä¹‰ï¼Œæ¥è‡ªèœå•管ç†å®šä¹‰
const getTitle = computed(() => ({
icon: meta.icon || 'ant-design:book-outlined',
value: record.value.isNewRecord ? t('新增数æ®') : t('编辑数æ®'),
}));
// è¾“å…¥è¡¨å•æŽ§ä»¶å®šä¹‰
const inputFormSchemas: FormSchema[] = [
{
label: t('å•行文本'), // 控件å‰é¢çš„页ç¾
field: 'testInput', // å—æ®µæäº¤å‚æ•°å
component: 'Input', // 控件类型(å¯è‡ªå®šä¹‰ï¼Œæ›´å¤šæŸ¥çœ‹ componentMap.ts )
componentProps: { // 组件属性定义
maxlength: 200,
},
required: true, // 表å•验è¯ï¼Œæ˜¯å¦å¿…填(快速定义)
rules: [ // 如果ä¸åªæ˜¯å¿…填,需è¦é€šè¿‡ rules 定义,举例:
{ required: true },
{ min: 4, max: 20, message: t('请输入长度在 4 到 20 个å—符之间') },
{ pattern: /^[\u0391-\uFFE5\w]+$/, message: t('ä¸èƒ½è¾“入特殊å—符') },
{
validator(_rule, value) {
return new Promise((resolve, reject) => {
if (!value || value === '') return resolve();
// 远程验è¯ï¼Œè®¿é—®åŽå°æ ¡éªŒæ•°æ®æ˜¯å¦é‡å¤
checkTestInput(record.value.testInput || '', value)
.then((res) => (res ? resolve() : reject(t('æ•°æ®å·²å˜åœ¨'))))
.catch((err) => reject(err.message || t('验è¯å¤±è´¥')));
});
},
trigger: 'blur', // 如果是远程验è¯ï¼Œå¯ä»¥å‡å°‘请求频率
},
],
colProps: { lg: 24, md: 24 }, // æ …æ ¼å¸ƒå±€ï¼ˆéµå¾ª Ant Design é£Žæ ¼ï¼‰
},
{
label: t('下拉框'),
field: 'testSelect',
component: 'Select', // 选择框还有 RadioGroupã€CheckboxGroup
componentProps: {
dictType: 'sys_menu_type', // 下拉框选项数æ®ï¼ˆæ”¯æŒç›´æŽ¥æŒ‡å®šå—典类型)
allowClear: true, // å¯ç”¨ç©ºé€‰é¡¹ï¼Œå¯æ¸…空选择
mode: 'multiple', // 下拉框模å—,å¯ç”¨å¤šé€‰
},
},
{
label: t('日期选择'),
field: 'testDate',
component: 'DatePicker',
componentProps: {
format: 'YYYY-MM-DD', // 日期选择
showTime: false, // 关闿—¶é—´é€‰æ‹©
},
},
{
label: t('日期时间'),
field: 'testDatetime',
component: 'DatePicker',
componentProps: {
format: 'YYYY-MM-DD HH:mm', // 日期时间选择
showTime: { format: 'HH:mm' }, // è®¾ç½®æ—¶é—´çš„æ ¼å¼
},
},
{
label: t('用户选择'),
field: 'testUser.userCode',
fieldLabel: 'testUser.userName', //ã€æ”¯æŒè¿”å›žï¼Œå¦‚ä¸‹æ‹‰æ¡†æˆ–æ ‘é€‰æ‹©çš„èŠ‚ç‚¹å】
component: 'TreeSelect', // æ ‘é€‰æ‹©æŽ§ä»¶
componentProps: {
api: officeTreeData, // æ•°æ®æº API å®šä¹‰ï¼Œæ”¯æŒ ztree æ ¼å¼
params: { isLoadUser: true, userIdPrefix: '' }, // API 傿•°
canSelectParent: false, // 是å¦å…许选择父级
allowClear: true,
},
},
{
label: t('å表数æ®'),
field: 'testDataChildList',
component: 'Input',
colProps: { lg: 24, md: 24 },
slot: 'testDataChildList', // æŒ‡å®šæ’æ§½ã€ä¸ªæ€§åŒ–控件内容
},
];
// 当å‰è¡¨å•çš„å‚æ•°å®šä¹‰
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 120, // 控件å‰é¢çš„æ ‡ç¾å®½åº¦
schemas: inputFormSchemas, // 控件定义列表
baseColProps: { lg: 12, md: 24 }, // æŽ§ä»¶é»˜è®¤æ …æ ¼å¸ƒå±€æ–¹å¼ï¼ˆå“应å¼ï¼‰
});
// 当å‰è¡¨å•åè¡¨æ ¼å®šä¹‰
const [registerTestDataChildTable, testDataChildTable] = useTable({
actionColumn: { // å表的æ“作列定义
width: 60, // æ“作列宽度
actions: (record: Recordable) => [
{
icon: 'i-ant-design:delete-outlined',
color: 'error',
popConfirm: { // 是å¦éœ€è¦å¯ç”¨ç¡®è®¤æ¡†
title: '是å¦ç¡®è®¤åˆ 除',
confirm: handleTestDataChildDelete.bind(this, record),
},
auth: 'sys:empUser:edit', // 按钮æƒé™ï¼ˆå¯æŽ§åˆ¶æŒ‰é’®æ˜¯å¦æ˜¾ç¤ºï¼‰
},
],
},
rowKey: 'id', // å表主键å
pagination: false,// å…³é—分页
bordered: true, // å¼€å¯è¡¨æ ¼è¾¹æ¡†
size: 'small', // å•å…ƒæ ¼é—´è·
inset: true, // 是å¦å†…嵌(去除一些边è·ï¼‰
});
// 当å‰è¡¨å•å表自动定义
async function setTestDataChildTableData(_res: Recordable) {
testDataChildTable.setColumns([
{
title: t('å•行文本'),
dataIndex: 'testInput',
width: 230,
align: 'left',
editRow: true, // 是å¦å¯ç”¨ç¼–辑
editComponent: 'Input', // 编辑控件(å¯è‡ªå®šä¹‰ï¼Œæ›´å¤šæŸ¥çœ‹ componentMap.ts )
editRule: true, // 控件验è¯ï¼ˆæ˜¯å¦å¿…填)
},
{
title: t('下拉框'),
dataIndex: 'testSelect',
width: 130,
align: 'left',
dictType: 'sys_menu_type', // 指定å—典类型,自动显示å—å…¸æ ‡ç¾
editRow: true,
editComponent: 'Select',
editComponentProps: { // 控件属性
dictType: 'sys_menu_type', // ä¸‹æ‹‰æ¡†çš„å—æ®µç±»åž‹
allowClear: true,
},
editRule: false,
},
// 更多组件控件ä¸ä¸¾ä¾‹äº†ï¼ŒåŒè¡¨å•控件 ...
]);
// 设定å表数æ®
testDataChildTable.setTableData(record.value.testDataChildList || []);
}
// 点击行,å¯ç”¨ç¼–辑
function handleTestDataChildRowClick(record: Recordable) {
record.onEdit?.(true, false);
}
// æ·»åŠ ç¼–è¾‘è¡Œï¼Œå¯æŒ‡å®šåˆå§‹æ•°æ®
function handleTestDataChildAdd() {
testDataChildTable.insertTableDataRecord({
id: new Date().getTime(),
isNewRecord: true,
editable: true,
});
}
// åˆ é™¤ç¼–è¾‘è¡Œæ–¹æ³•
function handleTestDataChildDelete(record: Recordable) {
testDataChildTable.deleteTableDataRecord(record);
}
// 获å–å表数æ®ï¼ˆæ”¯æŒè¿”å›žåˆ é™¤æœªæäº¤çš„æ•°æ®ï¼‰
async function getTestDataChildList() {
let testDataChildListValid = true;
let testDataChildList: Recordable[] = [];
for (const record of testDataChildTable.getDataSource()) {
// éªŒè¯æŽ§ä»¶å†…å®¹ï¼Œå¹¶å–æ¶ˆè¡Œçš„编辑状æ€ï¼ˆå¦‚果验è¯å¤±è´¥è¿”回false)
if (!(await record.onEdit?.(false, true))) {
testDataChildListValid = false;
}
testDataChildList.push({
...record,
id: !!record.isNewRecord ? '' : record.id,
});
}
for (const record of testDataChildTable.getDelDataSource()) {
if (!!record.isNewRecord) continue;
testDataChildList.push({
...record,
status: '1',
});
}
// å表验è¯äº‹ä»¶ï¼ŒæŠ›å‡ºå¼‚常消æ¯
if (!testDataChildListValid) {
throw { errorFields: [{ name: ['testDataChildList'] }] };
}
return testDataChildList;
}
// 弹窗åŽçš„å›žè°ƒäº‹ä»¶ï¼Œè¿›è¡Œä¸€äº›è¡¨å•æ•°æ®åˆå§‹åŒ–ç‰æ“作
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
resetFields(); // é‡ç½®è¡¨å•æ•°æ®
setDrawerProps({ loading: true }); // æ˜¾ç¤ºåŠ è½½æ¡†
const res = await testDataForm(data); // æŸ¥è¯¢è¡¨å•æ•°æ®
record.value = (res.testData || {}) as Recordable;
setFieldsValue(record.value); // è®¾ç½®å—æ®µå€¼
setTestDataChildTableData(res); // 设置å表数æ®ï¼ˆæ²¡æœ‰å表å¯ä¸å†™ï¼‰
setDrawerProps({ loading: false }); // éšè—åŠ è½½æ¡†
});
// è¡¨å•æäº¤æŒ‰é’®æ–¹æ³•
async function handleSubmit() {
try {
const data = await validate(); // 验è¯è¡¨å•,并返回数æ®
setDrawerProps({ confirmLoading: true }); // 显示æäº¤åŠ è½½ä¸
// 设置æäº¤çš„傿•°ï¼ˆQueryString,åŽå° Controller çš„ get 接å—)
const params: any = {
isNewRecord: record.value.isNewRecord,
id: record.value.id,
};
// 获å–并设置å表数æ®
data.testDataChildList = await getTestDataChildList();
// console.log('submit', params, data, record);
// å°†æ•°æ®æäº¤ç»™åŽå°ï¼ˆå¦‚果失败跳转到 catch)
const res = await testDataSave(params, data);
showMessage(res.message); // 显示æäº¤ç»“æžœ
setTimeout(closeDrawer); // éšè—抽屉弹窗
emit('success', data); // 触å‘事件,列表数æ®åˆ·æ–°
} catch (error: any) {
if (error && error.errorFields) {
showMessage(t('æ‚¨å¡«å†™çš„ä¿¡æ¯æœ‰è¯¯ï¼Œè¯·æ ¹æ®æç¤ºä¿®æ£ã€‚'));
}
console.log('error', error);
} finally {
setDrawerProps({ confirmLoading: false }); // éšè—æäº¤åŠ è½½ä¸
}
}
</script>
<template>
<div>
<!-- è¡¨æ ¼ç»„ä»¶ -->
<BasicTable @register="registerTable">
<!-- è¡¨æ ¼æ ‡é¢˜æ’æ§½ -->
<template #tableTitle>
<Icon :icon="getTitle.icon" class="m-1 pr-1" />
<span> {{ getTitle.value }} </span>
</template>
<!-- è¡¨æ ¼å³ä¾§æŒ‰é’®æ’æ§½ï¼Œå…¶ä¸ v-auth 是按钮æƒé™æŽ§åˆ¶ -->
<template #toolbar>
<a-button type="primary" @click="handleForm({})" v-auth="'test:testData:edit'">
<Icon icon="i-fluent:add-12-filled" /> {{ t('新增') }}
</a-button>
</template>
<!-- é¦–åˆ—æ’æ§½ -->
<template #firstColumn="{ record }">
<a @click="handleForm({ id: record.id })">
{{ record.testInput }}
</a>
</template>
</BasicTable>
<!-- ç‚¹å‡»è¡¨æ ¼è¡Œè¿›å…¥çš„è¾“å…¥è¡¨å•弹窗 -->
<InputForm @register="registerDrawer" @success="handleSuccess" />
</div>
</template>
<!-- script name: 当å‰ç»„ä»¶å称(与路由å一致,如果ä¸ä¸€è‡´ä¼šé¡µé¢ç¼“å˜å¤±æ•ˆï¼‰-->
<script lang="ts" setup name="ViewsTestTestDataList">
// 导入当å‰ç”¨åˆ°çš„对象,部分çœç•¥
import InputForm from './form.vue';
// å›½é™…åŒ–æ–¹æ³•è°ƒç”¨ï¼Œå‚æ•°æ˜¯å›½é™…化编ç çš„æ ¹è·¯å¾„
const { t } = useI18n('test.testData');
// 消æ¯å¼¹çª—方法
const { showMessage } = useMessage();
// 路由metaä¿¡æ¯
const { meta } = unref(router.currentRoute);
// 当å‰é¡µé¢æ ‡é¢˜å®šä¹‰ï¼Œæ¥è‡ªèœå•管ç†å®šä¹‰
const getTitle = {
icon: meta.icon || 'ant-design:book-outlined',
value: meta.title || t('æ•°æ®ç®¡ç†'),
};
// è¡¨æ ¼æœç´¢è¡¨å•控件定义
const searchForm: FormProps = {
baseColProps: { lg: 6, md: 8 }, // è¡¨å•æ …æ ¼å¸ƒå±€
labelWidth: 90, // è¡¨å•æ ‡ç¾å®½åº¦
schemas: [
{
label: t('å•行文本'), // è¡¨å•æ ‡ç¾
field: 'testInput', // å—æ®µæäº¤å‚æ•°å
component: 'Input', // è¡¨å•æŽ§ä»¶
},
{
label: t('下拉框'),
field: 'testSelect',
component: 'Select', // 选择框还有 RadioGroupã€CheckboxGroup
componentProps: {
dictType: 'sys_menu_type', // 下拉框选项数æ®ï¼ˆæ”¯æŒç›´æŽ¥æŒ‡å®šå—典类型)
allowClear: true, // å¯ç”¨ç©ºé€‰é¡¹ï¼Œå¯æ¸…空选择
mode: 'multiple', // 下拉框模å—,å¯ç”¨å¤šé€‰
},
},
// æ›´å¤šæŽ§ä»¶ï¼Œå†æ¬¡ä¸å±•示了,和上一节表å•视图一致
],
};
// è¡¨æ ¼åˆ—å®šä¹‰
const tableColumns: BasicColumn[] = [
{
title: t('å•行文本'), // è¡¨å¤´æ ‡é¢˜
dataIndex: 'testInput', // 表列实体属性å
key: 'a.test_input', // æŽ’åºæ•°æ®åº“å—æ®µå
sorter: true, // 点击表头是å¦å¯æŽ’åº
width: 230, // 列宽
align: 'left'<
BF76
/span>, // åˆ—çš„å¯¹é½æ–¹å¼
// 个性化列,å¯å®šä¹‰æ’æ§½ï¼ˆå¦‚æ ·å¼ï¼Œå¢žåŠ æŽ§ä»¶ç‰ï¼‰
slot: 'firstColumn',
},
{
title: t('下拉框'),
dataIndex: 'testSelect',
key: 'a.test_select',
sorter: true,
width: 130,
align: 'center',
dictType: 'sys_menu_type', // å—典列,快速显示å—å…¸æ ‡ç¾
},
];
// è¡¨æ ¼æ“作列定义
const actionColumn: BasicColumn = {
width: 160, // æ“作列宽
actions: (record: Recordable) => [
{
icon: 'i-clarity:note-edit-line',
title: t('编辑数æ®'),
onClick: handleForm.bind(this, { id: record.id }),
// 按钮æƒé™æŽ§åˆ¶ï¼ŒæŒ‡å®šæƒé™å—符串
auth: 'test:testData:edit',
},
{
icon: 'i-ant-design:stop-outlined',
color: 'error',
title: t('åœç”¨æ•°æ®'),
// 是å¦éœ€è¦å¯ç”¨ç¡®è®¤æ¡†
popConfirm: {
title: t('是å¦ç¡®è®¤åœç”¨æ•°æ®'),
confirm: handleDisable.bind(this, { id: record.id }),
},
// 按钮æƒé™æŽ§åˆ¶ï¼ŒæŒ‡å®šæƒé™å—符串
auth: 'test:testData:edit',
// æŽ§åˆ¶æŒ‰é’®æ˜¯å¦æ˜¾ç¤ºï¼ˆåŒºåˆ«ï¼šshow 是显示或éšè—ï¼›ifShow 是显示或移除)
show: () => record.status === '0',
ifShow: () => record.status === '0',
},
],
// æ“作列更多按钮定义
dropDownActions: (record: Recordable) => [
{
icon: 'i-ant-design:reload-outlined',
label: t('é‡ç½®å¯†ç '),
onClick: handleResetpwd.bind(this, { userCode: record.userCode }),
auth: 'sys:empUser:resetpwd',
},
],
};
// 点击首列或编辑按钮是的抽屉弹窗定义
const [registerDrawer, { openDrawer }] = useDrawer();
// è¡¨æ ¼å®šä¹‰
const [registerTable, { reload }] = useTable({
api: testDataListData, // è¡¨æ ¼æ•°æ®æº API
beforeFetch: (params) => {
return params; // API æäº¤ä¹‹å‰çš„傿•°ä¿®æ”¹
},
columns: tableColumns, // è¡¨æ ¼åˆ—
actionColumn: actionColumn,// æ“作列
formConfig: searchForm, // æœç´¢è¡¨å•
showTableSetting: true, // æ˜¯å¦æ˜¾ç¤ºå³ä¸Šè§’的设置按钮
useSearchForm: true, // æ˜¯å¦æ˜¾ç¤ºæœç´¢è¡¨å•
canResize: true, // 是å¦è‡ªé€‚应表å•高度
});
// 弹窗æ“作方法
function handleForm(record: Recordable) {
openDrawer(true, record);
}
// æ“作列åœç”¨æŒ‰é’®æ–¹æ³•
async function handleDisable(record: Recordable) {
const res = await testDataDisable(record);
showMessage(res.message);
handleSuccess();
}
// åˆ·æ–°è¡¨æ ¼æ•°æ®ï¼ˆå«è¡¨å•回调)
function handleSuccess() {
reload();
}
</script>
- 基于 Apache License Version 2.0 åè®®å‘布,å¯ç”¨äºŽå•†ä¸šé¡¹ç›®ï¼Œä½†å¿…é¡»éµå®ˆä»¥ä¸‹è¡¥å……æ¡æ¬¾ã€‚
- ä¸å¾—将本软件应用于å±å®³å›½å®¶å®‰å…¨ã€è£èª‰å’Œåˆ©ç›Šçš„行为,ä¸èƒ½ä»¥ä»»ä½•å½¢å¼ç”¨äºŽéžæ³•为目的的行为。
- 在使用本软件时,由于它集æˆäº†ä¼—多第三方开æºè½¯ä»¶ï¼Œè¯·å…±åŒéµå®ˆè¿™äº›å¼€æºè½¯ä»¶çš„ä½¿ç”¨è®¸å¯æ¡æ¬¾è§„定。
- 在延伸的代ç ä¸ï¼ˆä¿®æ”¹å’Œæœ‰æºä»£ç è¡ç”Ÿçš„代ç ä¸ï¼‰éœ€è¦å¸¦æœ‰åŽŸæ¥ä»£ç ä¸çš„åè®®ã€ç‰ˆæƒå£°æ˜Žå’Œå…¶ä»–原作者
规定需è¦åŒ…å«çš„说明(请尊é‡åŽŸä½œè€…çš„è‘—ä½œæƒï¼Œä¸è¦åˆ 除或修改文件ä¸çš„
Copyright
和@author
ä¿¡æ¯ï¼‰ æ›´ä¸è¦ï¼Œå…¨å±€æ›¿æ¢æºä»£ç ä¸çš„ jeesite 或 ThinkGem ç‰å—æ ·ï¼Œå¦åˆ™ä½ å°†è¿å本åè®®æ¡æ¬¾æ‰¿æ‹…责任。 - 基于本软件的作å“,åªèƒ½ä½¿ç”¨ JeeSite5 作为åŽå°æœåŠ¡ï¼Œé™¤å¤–æƒ…å†µä¸å¯å•†ç”¨ä¸”ä¸å…è®¸äºŒæ¬¡åˆ†å‘æˆ–å¼€æºã€‚
- æ‚¨è‹¥å¥—ç”¨æœ¬è½¯ä»¶çš„ä¸€äº›ä»£ç æˆ–功能å‚考,请ä¿ç•™æºæ–‡ä»¶ä¸çš„版æƒå’Œä½œè€…,需è¦åœ¨æ‚¨çš„è½¯ä»¶ä»‹ç»æ˜Žæ˜¾ä½ç½® 说明出处,举例:本软件基于 JeeSite Vue 快速开å‘å¹³å°ï¼Œå¹¶é™„带链接:http://jeesite.com
- ä»»ä½•åŸºäºŽæœ¬è½¯ä»¶è€Œäº§ç”Ÿçš„ä¸€åˆ‡æ³•å¾‹çº çº·å’Œè´£ä»»ï¼Œå‡äºŽæˆ‘叿— 关。
- å¦‚æžœä½ å¯¹æœ¬è½¯ä»¶æœ‰æ”¹è¿›ï¼Œå¸Œæœ›å¯ä»¥è´¡çŒ®ç»™æˆ‘们,共åŒè¿›æ¥ã€‚
- 本项目已申请软件著作æƒï¼Œè¯·å°Šé‡å¼€æºï¼Œæ„Ÿè°¢é˜…读。
- 本软件å…费,我们也æä¾›äº†ç›¸åº”的收费æœåŠ¡ï¼Œå› ä¸ºï¼š
- 没有资金的支撑就很难得到å‘展,特别是一个好的产å“,如果 JeeSite å¸®åŠ©äº†æ‚¨ï¼Œè¯·ä¸ºæˆ‘ä»¬ç‚¹èµžã€‚æ”¯æŒæˆ‘们,您å¯ä»¥èŽ·å¾—æ›´å¤šå›žé¦ˆï¼Œæˆ‘ä»¬ä¼šæŠŠå…¬ç›Šäº‹ä¸šåšçš„æ›´å¥½ï¼Œå¼€æ”¾æ›´å¤šèµ„æºï¼Œå›žæŠ¥ç¤¾åŒºå’Œç¤¾ä¼šã€‚请给我们一些动力å§ï¼Œåœ¨æ¤éžå¸¸æ„Ÿè°¢å·²æ”¯æŒæˆ‘们的朋å‹ï¼
- è”系我们:请访问技术支æŒä¸ŽæœåС页é¢ï¼šhttp://s.jeesite.com
- ä¸»é¢˜æ ‡ç¾é¡µçš„三ç§é£Žæ ¼è‡ªç”±åˆ‡æ¢
- 业务æµç¨‹ã€æµç¨‹è®¾è®¡ã€æµç¨‹åŠžç†
- 文件管ç†ã€ä¸Šä¼ ç§’ä¼ ã€æ–‡ä»¶é¢„览
- 高级折å 表å•和个性化本地å˜å‚¨
- è¡¨æ ¼ä¸ªæ€§åŒ–è®¾ç½®å‚æ•°æœ¬åœ°å˜å‚¨
- 租户管ç†åŠŸèƒ½ã€ç§Ÿæˆ·åˆ‡æ¢
- 动æ€è®¾ç½®é¡µé¢å—体大å°
- 页ç¾å³é”®ï¼Œåœ¨æ–°çª—壿‰“å¼€
- æ¶ˆæ¯æŽ¨é€ã€æ¶ˆæ¯æé†’
- è¯è¨€å›½é™…åŒ–ã€æœ¬åœ°åŒ–
- 快速å‡çº§åˆ° Monorepo 脚本
- æ›´å¤šåŠŸèƒ½è¯¦è§æ–‡æ¡£