wwf
6 小时以前 a1d7e81859f554f3a53680cc35f0f49bf1f77098
导入项目
1个文件已修改
1,699个文件已添加
253105 ■■■■■ 已修改文件
.editorconfig 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.dev 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.local 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.prod 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.stage 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.test 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.eslintignore 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.eslintrc-auto-import.json 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.eslintrc.js 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.image/Java监控.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/MySQL.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/OA请假-列表.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/OA请假-发起.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/OA请假-详情.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/Redis.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/admin-uniapp/01.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/admin-uniapp/02.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/admin-uniapp/03.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/admin-uniapp/04.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/admin-uniapp/05.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/admin-uniapp/06.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/admin-uniapp/07.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/admin-uniapp/08.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/admin-uniapp/09.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/ai-feature.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/ai-preview.gif 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/bpm-feature.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/crm-feature.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/erp-feature.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/infra-feature.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/mall-feature.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/mall-preview.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/project-vs.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/ruoyi-vue-pro-architecture.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/ruoyi-vue-pro-biz.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/system-feature.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/yudao-cloud-architecture.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/common/yudao-roadmap.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/demo/vue3-ep.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/个人中心.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/代码生成.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/令牌管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/任务列表-审批.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/任务列表-已办.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/任务列表-待办.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/任务日志.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/商户信息.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/在线用户.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/大屏设计器-列表.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/大屏设计器-编辑.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/大屏设计器-预览.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/字典数据.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/字典类型.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/定时任务.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/岗位管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/工作流设计器-bpmn.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/工作流设计器-simple.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/应用信息-列表.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/应用信息-编辑.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/应用管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/我的流程-列表.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/我的流程-发起.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/我的流程-详情.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/报表设计器-图形报表.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/报表设计器-打印设计.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/报表设计器-数据报表.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/操作日志.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/支付订单.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/敏感词.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/数据库文档.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/文件管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/文件管理2.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/文件配置.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/日志中心.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/流程模型-列表.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/流程模型-定义.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/流程模型-设计.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/流程表单.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/生成效果.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/用户分组.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/用户管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/登录.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/登录日志.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/短信日志.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/短信模板.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/短信渠道.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/租户套餐.png 补丁 | 查看 | 原始文档 | blame | 历史
.image/租户管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/系统接口.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/菜单管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/表单构建.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/角色管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/访问日志.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/退款订单.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/通知公告.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/部门管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/配置管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/链路追踪.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/错误日志.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/错误码管理.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.image/首页.jpg 补丁 | 查看 | 原始文档 | blame | 历史
.prettierignore 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.stylelintignore 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vscode/extensions.json 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vscode/launch.json 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vscode/settings.json 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LICENSE 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md 293 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
build/vite/index.ts 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
build/vite/optimize.ts 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json 17553 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pnpm-lock.yaml 10576 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
postcss.config.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
prettier.config.js 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
public/logo.gif 补丁 | 查看 | 原始文档 | blame | 历史
src/App.vue 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/chat/conversation/index.ts 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/chat/message/index.ts 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/image/index.ts 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/knowledge/document/index.ts 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/knowledge/knowledge/index.ts 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/knowledge/segment/index.ts 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/mindmap/index.ts 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/model/apiKey/index.ts 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/model/chatRole/index.ts 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/model/model/index.ts 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/model/tool/index.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/music/index.ts 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/workflow/index.ts 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/write/index.ts 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/category/index.ts 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/definition/index.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/form/index.ts 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/leave/index.ts 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/model/index.ts 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/processExpression/index.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/processInstance/index.ts 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/processListener/index.ts 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/simple/index.ts 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/task/index.ts 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/bpm/userGroup/index.ts 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/business/index.ts 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/business/status/index.ts 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/clue/index.ts 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/contact/index.ts 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/contract/config/index.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/contract/index.ts 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/customer/index.ts 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/customer/limitConfig/index.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/customer/poolConfig/index.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/followup/index.ts 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/operateLog/index.ts 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/permission/index.ts 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/product/category/index.ts 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/product/index.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/receivable/index.ts 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/receivable/plan/index.ts 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/statistics/customer.ts 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/statistics/funnel.ts 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/statistics/performance.ts 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/statistics/portrait.ts 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/statistics/rank.ts 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/finance/account/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/finance/payment/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/finance/receipt/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/product/category/index.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/product/product/index.ts 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/product/unit/index.ts 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/purchase/in/index.ts 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/purchase/order/index.ts 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/purchase/return/index.ts 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/purchase/supplier/index.ts 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/sale/customer/index.ts 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/sale/order/index.ts 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/sale/out/index.ts 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/sale/return/index.ts 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/statistics/purchase/index.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/statistics/sale/index.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/stock/check/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/stock/in/index.ts 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/stock/move/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/stock/out/index.ts 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/stock/record/index.ts 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/stock/stock/index.ts 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/stock/warehouse/index.ts 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/apiAccessLog/index.ts 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/apiErrorLog/index.ts 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/codegen/index.ts 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/config/index.ts 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/dataSourceConfig/index.ts 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/demo/demo01/index.ts 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/demo/demo02/index.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/demo/demo03/erp/index.ts 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/demo/demo03/inner/index.ts 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/demo/demo03/normal/index.ts 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/file/index.ts 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/fileConfig/index.ts 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/job/index.ts 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/jobLog/index.ts 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/redis/index.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/infra/redis/types.ts 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/alert/config/index.ts 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/alert/record/index.ts 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/device/device/index.ts 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/device/group/index.ts 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/ota/firmware/index.ts 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/ota/task/index.ts 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/ota/task/record/index.ts 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/product/category/index.ts 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/product/product/index.ts 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/rule/data/rule/index.ts 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/rule/data/sink/index.ts 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/rule/scene/index.ts 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/statistics/index.ts 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/iot/thingmodel/index.ts 301 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/login/index.ts 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/login/oauth2/index.ts 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/login/types.ts 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/market/banner/index.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/product/brand.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/product/category.ts 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/product/comment.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/product/favorite.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/product/history.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/product/property.ts 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/product/spu.ts 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/article/index.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/articleCategory/index.ts 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/bargain/bargainActivity.ts 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/bargain/bargainHelp.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/bargain/bargainRecord.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/combination/combinationActivity.ts 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/combination/combinationRecord.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/coupon/coupon.ts 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/coupon/couponTemplate.ts 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/discount/discountActivity.ts 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/diy/page.ts 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/diy/template.ts 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/kefu/conversation/index.ts 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/kefu/message/index.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/point/index.ts 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/reward/rewardActivity.ts 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/seckill/seckillActivity.ts 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/promotion/seckill/seckillConfig.ts 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/statistics/common.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/statistics/member.ts 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/statistics/pay.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/statistics/product.ts 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/statistics/trade.ts 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/trade/afterSale/index.ts 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/trade/brokerage/record/index.ts 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/trade/brokerage/user/index.ts 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/trade/brokerage/withdraw/index.ts 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/trade/config/index.ts 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/trade/delivery/express/index.ts 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/trade/delivery/expressTemplate/index.ts 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/trade/delivery/pickUpStore/index.ts 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mall/trade/order/index.ts 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/member/address/index.ts 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/member/config/index.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/member/experience-record/index.ts 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/member/group/index.ts 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/member/level/index.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/member/point/record/index.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/member/signin/config/index.ts 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/member/signin/record/index.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/member/tag/index.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/member/user/index.ts 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/account/index.ts 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/autoReply/index.ts 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/draft/index.ts 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/freePublish/index.ts 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/material/index.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/menu/index.ts 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/message/index.ts 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/messageTemplate/index.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/statistics/index.ts 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/tag/index.ts 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mp/user/index.ts 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/app/index.ts 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/channel/index.ts 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/demo/order/index.ts 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/demo/withdraw/index.ts 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/notify/index.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/order/index.ts 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/refund/index.ts 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/transfer/index.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/wallet/balance/index.ts 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/wallet/rechargePackage/index.ts 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pay/wallet/transaction/index.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/area/index.ts 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/dept/index.ts 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/dict/dict.data.ts 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/dict/dict.type.ts 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/loginLog/index.ts 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/mail/account/index.ts 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/mail/log/index.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/mail/template/index.ts 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/menu/index.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/notice/index.ts 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/notify/message/index.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/notify/template/index.ts 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/oauth2/client.ts 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/oauth2/token.ts 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/operatelog/index.ts 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/permission/index.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/post/index.ts 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/role/index.ts 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/sms/smsChannel/index.ts 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/sms/smsLog/index.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/sms/smsTemplate/index.ts 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/social/client/index.ts 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/social/user/index.ts 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/tenant/index.ts 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/tenantPackage/index.ts 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/user/index.ts 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/user/profile.ts 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/user/socialUser.ts 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/ai/copy-style2.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/ai/copy.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/ai/dall2.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/ai/dall3.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/ai/delete.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/ai/gpt.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/ai/qingxi.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/ai/ziran.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/audio/response.mp3 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/imgs/avatar.gif 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/imgs/avatar.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/imgs/diy/app-nav-bar-mp.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/imgs/diy/statusBar.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/imgs/iot/device.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/imgs/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/imgs/profile.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/imgs/wechat.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/map/json/china.json 856 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/403.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/404.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/500.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/add-user.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/approve.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/auditor.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/cancel.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/child-process.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/condition.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/copy.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/delay.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/finish.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/parallel.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/reject.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/running.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/simple-process-bg.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/starter.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/bpm/transactor.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/icon.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/iot/card-fill.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/iot/cube.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/login-bg.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/login-box-bg.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/member_balance.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/member_expenditure_balance.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/member_level.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/member_point.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/member_recharge_balance.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/message.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/money.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/alipay_app.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/alipay_bar.svg 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/alipay_pc.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/alipay_qr.svg 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/alipay_wap.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/mock.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/wallet.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/wx_app.svg 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/wx_bar.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/wx_lite.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/wx_native.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/pay/icon/wx_pub.svg 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/peoples.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/send.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/svgs/shopping.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/AppLinkInput/AppLinkSelectDialog.vue 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/AppLinkInput/data.ts 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/AppLinkInput/index.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Backtop/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Backtop/src/Backtop.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Card/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Card/src/CardTitle.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ColorInput/index.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ConfigGlobal/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ConfigGlobal/src/ConfigGlobal.vue 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ContentDetailWrap/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ContentDetailWrap/src/ContentDetailWrap.vue 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ContentWrap/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ContentWrap/src/ContentWrap.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/CountTo/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/CountTo/src/CountTo.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Crontab/index.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Crontab/src/Crontab.vue 1015 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Cropper/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Cropper/src/CopperModal.vue 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Cropper/src/Cropper.vue 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Cropper/src/CropperAvatar.vue 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Cropper/src/types.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DeptSelectForm/index.vue 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Descriptions/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Descriptions/src/Descriptions.vue 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Descriptions/src/DescriptionsItemLabel.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Dialog/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Dialog/src/Dialog.vue 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DictTag/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DictTag/src/DictTag.vue 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/ComponentContainer.vue 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/ComponentContainerProperty.vue 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/ComponentLibrary.vue 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/Carousel/config.ts 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/Carousel/index.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/Carousel/property.vue 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/CouponCard/component.tsx 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/CouponCard/config.ts 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/CouponCard/index.vue 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/CouponCard/property.vue 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/Divider/config.ts 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/Divider/index.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/Divider/property.vue 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/FloatingActionButton/config.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/FloatingActionButton/index.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/FloatingActionButton/property.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/HotZone/components/HotZoneEditDialog/controller.ts 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/HotZone/components/HotZoneEditDialog/index.vue 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/HotZone/config.ts 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/HotZone/index.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/HotZone/property.vue 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/ImageBar/config.ts 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/ImageBar/index.vue 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/ImageBar/property.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MagicCube/config.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MagicCube/index.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MagicCube/property.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MenuGrid/config.ts 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MenuGrid/index.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MenuGrid/property.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MenuList/config.ts 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MenuList/index.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MenuList/property.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MenuSwiper/config.ts 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MenuSwiper/index.vue 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/MenuSwiper/property.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/NavigationBar/config.ts 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/NavigationBar/index.vue 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/NavigationBar/property.vue 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/NoticeBar/config.ts 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/NoticeBar/index.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/NoticeBar/property.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PageConfig/config.ts 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PageConfig/property.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/Popover/config.ts 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/Popover/index.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/Popover/property.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/ProductCard/config.ts 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/ProductCard/index.vue 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/ProductCard/property.vue 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/ProductList/config.ts 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/ProductList/index.vue 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/ProductList/property.vue 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionArticle/config.ts 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionArticle/index.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionArticle/property.vue 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionCombination/config.ts 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionCombination/index.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionCombination/property.vue 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionPoint/config.ts 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionPoint/index.vue 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionPoint/property.vue 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionSeckill/config.ts 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionSeckill/index.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/PromotionSeckill/property.vue 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/SearchBar/config.ts 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/SearchBar/index.vue 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/SearchBar/property.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/TabBar/config.ts 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/TabBar/index.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/TabBar/property.vue 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/TitleBar/config.ts 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/TitleBar/index.vue 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/TitleBar/property.vue 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserCard/config.ts 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserCard/index.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserCard/property.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserCoupon/config.ts 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserCoupon/index.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserCoupon/property.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserOrder/config.ts 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserOrder/index.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserOrder/property.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserWallet/config.ts 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserWallet/index.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/UserWallet/property.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/VideoPlayer/config.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/VideoPlayer/index.vue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/VideoPlayer/property.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/components/mobile/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/index.vue 604 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DiyEditor/util.ts 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DocAlert/index.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Draggable/index.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Echart/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Echart/src/Echart.vue 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Editor/index.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Editor/src/Editor.vue 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Error/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Error/src/Error.vue 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/index.ts 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/src/Form.vue 307 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/src/componentMap.ts 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/src/components/useRenderCheckbox.tsx 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/src/components/useRenderRadio.tsx 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/src/components/useRenderSelect.tsx 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/src/helper.ts 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Form/src/types.ts 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/components/DictSelect.vue 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/components/useApiSelect.tsx 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/config/index.ts 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/config/selectRule.ts 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/config/useDictSelectRule.ts 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/config/useEditorRule.ts 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/config/useSelectRule.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/config/useUploadFileRule.ts 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/config/useUploadImgRule.ts 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/config/useUploadImgsRule.ts 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/type/index.ts 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/useFormCreateDesigner.ts 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FormCreate/src/utils/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Highlight/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Highlight/src/Highlight.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/IFrame/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/IFrame/src/IFrame.vue 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Icon/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Icon/src/Icon.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Icon/src/IconSelect.vue 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Icon/src/data.ts 1961 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ImageViewer/index.ts 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ImageViewer/src/ImageViewer.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ImageViewer/src/types.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Infotip/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Infotip/src/Infotip.vue 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/InputPassword/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/InputPassword/src/InputPassword.vue 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/InputWithColor/index.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/JsonEditor/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/JsonEditor/src/JsonEditor.vue 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/JsonEditor/types/index.ts 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/MagicCubeEditor/index.vue 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/MagicCubeEditor/util.ts 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Map/index.vue 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/MarkdownView/index.vue 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/OperateLogV2/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/OperateLogV2/src/OperateLogV2.vue 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Pagination/index.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Qrcode/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Qrcode/src/Qrcode.vue 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/RouterSearch/index.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Search/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Search/src/Search.vue 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ShortcutDateRangePicker/index.vue 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/NodeHandler.vue 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue 237 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue 265 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/SimpleProcessViewer.vue 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/consts.ts 902 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/index.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/node.ts 617 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/ChildProcessNodeConfig.vue 610 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue 392 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/TriggerNodeConfig.vue 532 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue 1068 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue 277 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/components/ConditionDialog.vue 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/components/HttpRequestParamSetting.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/components/HttpRequestSetting.vue 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes-config/components/UserTaskListener.vue 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/ChildProcessNode.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/ParallelNode.vue 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/RouterNode.vue 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/TriggerNode.vue 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/src/utils.ts 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/theme/iconfont.ttf 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/theme/iconfont.woff 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/theme/iconfont.woff2 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss 825 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Sticky/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Sticky/src/Sticky.vue 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SummaryCard/index.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/index.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/src/Table.vue 311 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/src/TableSelectForm.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/src/helper.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/src/types.ts 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Tinyflow/Tinyflow.vue 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Tinyflow/ui/index.css 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Tinyflow/ui/index.d.ts 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Tinyflow/ui/index.js 16984 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Tinyflow/ui/index.umd.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Tooltip/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Tooltip/src/Tooltip.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UploadFile/index.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UploadFile/src/UploadFile.vue 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UploadFile/src/UploadImg.vue 272 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UploadFile/src/UploadImgs.vue 329 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UploadFile/src/useUpload.ts 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UserSelectForm/index.vue 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Verifition/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Verifition/src/Verify.vue 446 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Verifition/src/Verify/VerifyPictureWord.vue 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Verifition/src/Verify/VerifyPoints.vue 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Verifition/src/Verify/VerifySlide.vue 376 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Verifition/src/Verify/index.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Verifition/src/utils/ase.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Verifition/src/utils/util.ts 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/VerticalButtonGroup/index.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/XButton/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/XButton/src/XButton.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/XButton/src/XTextButton.vue 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue 655 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue 379 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/index.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/index2.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/contentPadProvider.js 423 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/index.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/defaultEmpty.js 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/activitiDescriptor.json 1004 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/camundaDescriptor.json 1020 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json 1493 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/activitiExtension.js 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/index.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/extension.js 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/index.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/flowableExtension.js 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/index.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/palette/CustomPalette.js 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/palette/paletteProvider.js 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/translate/customTranslate.js 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/designer/plugins/translate/zh.js 251 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/index.ts 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/custom-config/components/BoundaryEventTimer.vue 263 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue 688 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/custom-config/data.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/form/ElementForm.vue 479 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/index.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue 468 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue 510 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/listeners/template.js 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/listeners/utilSelf.ts 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue 421 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue 264 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/task/ElementTask.vue 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/task/data.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/task/task-components/CallActivity.vue 280 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/task/task-components/HttpHeaderEditor.vue 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/task/task-components/ServiceTask.vue 396 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue 470 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/time-event-config/CycleConfig.vue 285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/time-event-config/DurationConfig.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/penal/time-event-config/TimeEventConfig.vue 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/theme/element-variables.scss 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/theme/index.scss 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/theme/process-designer.scss 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/theme/process-panel.scss 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/package/utils.ts 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/src/highlight/index.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/src/modules/custom-renderer/CustomRenderer.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/src/modules/custom-renderer/index.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/src/modules/rules/CustomRules.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/src/modules/rules/index.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/src/translations.ts 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/src/utils/directive/clickOutSide.js 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/src/utils/index.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bpmnProcessDesigner/src/utils/xml2json.js 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/index.ts 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/config/axios/config.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/config/axios/errorCode.ts 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/config/axios/index.ts 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/config/axios/service.ts 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/directives/index.ts 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/directives/permission/hasPermi.ts 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/directives/permission/hasRole.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/event/useScrollTo.ts 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useCache.ts 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useConfigGlobal.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useCrudSchemas.ts 326 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useDesign.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useEmitt.ts 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useForm.ts 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useGuide.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useI18n.ts 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useIcon.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useLocale.ts 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useMessage.ts 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useNProgress.ts 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useNetwork.ts 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useNow.ts 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/usePageLoading.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useTable.ts 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useTagsView.ts 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useTimeAgo.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useTitle.ts 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useValidator.ts 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useWatermark.ts 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/Layout.vue 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/AppView.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Breadcrumb/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Breadcrumb/src/Breadcrumb.vue 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Breadcrumb/src/helper.ts 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Collapse/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Collapse/src/Collapse.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/ContextMenu/index.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/ContextMenu/src/ContextMenu.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Footer/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Footer/src/Footer.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/LocaleDropdown/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/LocaleDropdown/src/LocaleDropdown.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Logo/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Logo/src/Logo.vue 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Menu/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Menu/src/Menu.vue 272 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Menu/src/components/useRenderMenuItem.tsx 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Menu/src/components/useRenderMenuTitle.tsx 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Menu/src/helper.ts 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Message/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Message/src/Message.vue 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Screenfull/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Screenfull/src/Screenfull.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Setting/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Setting/src/Setting.vue 303 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Setting/src/components/ColorRadioPicker.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Setting/src/components/InterfaceDisplay.vue 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Setting/src/components/LayoutRadioPicker.vue 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/SizeDropdown/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/SizeDropdown/src/SizeDropdown.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TabMenu/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TabMenu/src/TabMenu.vue 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TabMenu/src/helper.ts 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TagsView/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TagsView/src/TagsView.vue 661 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TagsView/src/helper.ts 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TenantVisit/index.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/ThemeSwitch/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/ThemeSwitch/src/ThemeSwitch.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/ToolHeader.vue 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/UserInfo/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/UserInfo/src/UserInfo.vue 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/UserInfo/src/components/LockDialog.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/UserInfo/src/components/LockPage.vue 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/useRenderLayout.tsx 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en.ts 462 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN.ts 458 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.ts 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/permission.ts 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/animate.css/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/echarts/index.ts 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/elementPlus/index.ts 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/formCreate/index.ts 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/svgIcon/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/tongji/index.ts 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/unocss/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/vueI18n/helper.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/vueI18n/index.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/modules/remaining.ts 752 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/index.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/app.ts 322 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/bpm/simpleWorkflow.ts 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/dict.ts 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/locale.ts 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/lock.ts 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/mall/kefu.ts 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/permission.ts 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/tagsView.ts 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.ts 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/FormCreate/fonts/fontello.woff 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/FormCreate/index.scss 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/global.module.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/index.scss 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/theme.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/var.css 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/variables.scss 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/components.d.ts 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/configGlobal.d.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/contextMenu.d.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/descriptions.d.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/elementPlus.d.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/form.d.ts 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/icon.d.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/infoTip.d.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/layout.d.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/localeDropdown.d.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/qrcode.d.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/table.d.ts 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/theme.d.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/Logger.ts 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/auth.ts 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/color.ts 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/constants.ts 465 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/cron.ts 471 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/dateUtil.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/dict.ts 251 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/domUtils.ts 289 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/download.ts 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/encrypt.ts 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/file.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/filt.ts 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/formCreate.ts 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/formRules.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/formatTime.ts 332 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/formatter.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/index.ts 537 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/is.ts 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/jsencrypt.ts 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/permission.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/propTypes.ts 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/routerHelper.ts 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/tree.ts 403 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/tsxHelper.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Error/403.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Error/404.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Error/500.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Home/Index.vue 422 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Home/Index2.vue 319 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Home/echarts-data.ts 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Home/types.ts 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/Login.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/SocialLogin.vue 347 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/ForgetPasswordForm.vue 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/LoginForm.vue 360 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/LoginFormTitle.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/MobileForm.vue 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/QrCodeForm.vue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/RegisterForm.vue 288 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/SSOLogin.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/index.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/useLogin.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Profile/Index.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Profile/components/BasicInfo.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Profile/components/ProfileUser.vue 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Profile/components/ResetPwd.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Profile/components/UserAvatar.vue 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Profile/components/UserSocial.vue 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Profile/components/index.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Redirect/Redirect.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/conversation/ConversationList.vue 391 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/conversation/ConversationUpdateForm.vue 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/message/MessageFileUpload.vue 394 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/message/MessageFiles.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/message/MessageKnowledge.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/message/MessageList.vue 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/message/MessageListEmpty.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/message/MessageLoading.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/message/MessageNewConversation.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/message/MessageReasoning.vue 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/message/MessageWebSearch.vue 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/role/RoleCategoryList.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/role/RoleList.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/components/role/RoleRepository.vue 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/index/index.vue 630 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/manager/ChatConversationList.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/manager/ChatMessageList.vue 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/chat/manager/index.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/image/index/components/ImageCard.vue 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/image/index/components/ImageDetail.vue 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/image/index/components/ImageList.vue 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/image/index/components/common/index.vue 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/image/index/components/dall3/index.vue 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/image/index/components/midjourney/index.vue 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/image/index/components/stableDiffusion/index.vue 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/image/index/index.vue 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/image/manager/index.vue 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/image/square/index.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/knowledge/document/form/ProcessStep.vue 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/knowledge/document/form/SplitStep.vue 238 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/knowledge/document/form/UploadStep.vue 273 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/knowledge/document/form/index.vue 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/knowledge/document/index.vue 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/knowledge/knowledge/KnowledgeForm.vue 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/knowledge/knowledge/index.vue 221 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/knowledge/knowledge/retrieval/index.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/knowledge/segment/KnowledgeSegmentForm.vue 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/knowledge/segment/index.vue 242 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/mindmap/index/components/Left.vue 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/mindmap/index/components/Right.vue 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/mindmap/index/index.vue 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/mindmap/manager/index.vue 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/model/apiKey/ApiKeyForm.vue 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/model/apiKey/index.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/model/chatRole/ChatRoleForm.vue 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/model/chatRole/index.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/model/model/ModelForm.vue 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/model/model/index.vue 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/model/tool/ToolForm.vue 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/model/tool/index.vue 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/music/index/index.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/music/index/list/audioBar/index.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/music/index/list/index.vue 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/music/index/list/songCard/index.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/music/index/list/songInfo/index.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/music/index/mode/desc.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/music/index/mode/index.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/music/index/mode/lyric.vue 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/music/index/title/index.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/music/manager/index.vue 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/utils/constants.ts 470 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/utils/utils.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/workflow/form/BasicInfo.vue 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/workflow/form/WorkflowDesign.vue 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/workflow/form/index.vue 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/workflow/index.vue 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/write/index/components/Left.vue 213 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/write/index/components/Right.vue 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/write/index/components/Tag.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/write/index/index.vue 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/write/manager/index.vue 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/category/CategoryForm.vue 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/category/index.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/form/editor/index.vue 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/form/index.vue 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/group/UserGroupForm.vue 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/group/index.vue 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/CategoryDraggableModel.vue 665 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/definition/index.vue 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/BasicInfo.vue 360 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/ExtraSettings.vue 507 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/FormDesign.vue 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/PrintTemplate/Index.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/PrintTemplate/MentionModal.vue 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/PrintTemplate/index.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/PrintTemplate/module/elem-to-html.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/PrintTemplate/module/index.ts 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/PrintTemplate/module/menu/ProcessRecordMenu.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/PrintTemplate/module/parse-elem-html.ts 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/PrintTemplate/module/plugin.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/PrintTemplate/module/render-elem.ts 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/PrintTemplate/module/utils/dom.ts 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/ProcessDesign.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/editor/index.vue 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/form/index.vue 456 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/model/index.vue 228 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/oa/leave/create.vue 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/oa/leave/detail.vue 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/oa/leave/index.vue 275 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processExpression/ProcessExpressionForm.vue 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processExpression/index.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue 357 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/create/index.vue 321 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/detail/PrintDialog.vue 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue 1140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue 361 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/detail/SignDialog.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/detail/index.vue 363 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/index.vue 338 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/manager/index.vue 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processInstance/report/index.vue 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processListener/ProcessListenerForm.vue 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/processListener/index.vue 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/simple/SimpleModelDesign.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/task/copy/index.vue 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/task/done/index.vue 282 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/task/manager/index.vue 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/bpm/task/todo/index.vue 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/components/ClueFollowList.vue 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/components/ContractAuditList.vue 247 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/components/ContractRemindList.vue 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/components/CustomerFollowList.vue 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/components/CustomerPutPoolRemindList.vue 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/components/CustomerTodayContactList.vue 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/components/ReceivableAuditList.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/components/ReceivablePlanRemindList.vue 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/components/common.ts 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/index.vue 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/BusinessForm.vue 287 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/BusinessUpdateStatusForm.vue 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/components/BusinessList.vue 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/components/BusinessListModal.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/components/BusinessProductForm.vue 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/detail/BusinessDetailsHeader.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/detail/BusinessDetailsInfo.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/detail/BusinessProductList.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/detail/index.vue 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/index.vue 275 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/status/BusinessStatusForm.vue 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/business/status/index.vue 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/clue/ClueForm.vue 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/clue/detail/ClueDetailsHeader.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/clue/detail/ClueDetailsInfo.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/clue/detail/index.vue 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/clue/index.vue 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contact/ContactForm.vue 311 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contact/components/ContactList.vue 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contact/components/ContactListModal.vue 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contact/detail/ContactDetailsHeader.vue 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contact/detail/ContactDetailsInfo.vue 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contact/detail/index.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contact/index.vue 332 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/ContractForm.vue 369 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/components/ContractList.vue 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/components/ContractProductForm.vue 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/config/index.vue 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/detail/ContractDetailsHeader.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/detail/ContractDetailsInfo.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/detail/ContractProductList.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/detail/index.vue 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/index.vue 398 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/CustomerForm.vue 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/CustomerImportForm.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/detail/CustomerDetailsHeader.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/detail/CustomerDetailsInfo.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/detail/index.vue 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/index.vue 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/limitConfig/CustomerLimitConfigForm.vue 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/limitConfig/CustomerLimitConfigList.vue 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/limitConfig/index.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/pool/CustomerDistributeForm.vue 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/pool/index.vue 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/customer/poolConfig/index.vue 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/followup/FollowUpRecordForm.vue 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/followup/components/FollowUpRecordBusinessForm.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/followup/components/FollowUpRecordContactForm.vue 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/followup/index.vue 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/permission/components/PermissionForm.vue 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/permission/components/PermissionList.vue 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/permission/components/TransferForm.vue 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/product/ProductForm.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/product/category/ProductCategoryForm.vue 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/product/category/index.vue 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/product/detail/ProductDetailsHeader.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/product/detail/ProductDetailsInfo.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/product/detail/index.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/product/index.vue 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/ReceivableForm.vue 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/components/ReceivableList.vue 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/detail/ReceivableDetailsHeader.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/detail/ReceivableDetailsInfo.vue 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/detail/index.vue 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/index.vue 335 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/plan/ReceivablePlanForm.vue 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/plan/components/ReceivablePlanList.vue 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/plan/detail/ReceivablePlanDetailsHeader.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/plan/detail/ReceivablePlanDetailsInfo.vue 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/plan/detail/index.vue 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/receivable/plan/index.vue 335 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/customer/components/CustomerConversionStat.vue 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/customer/components/CustomerDealCycleByArea.vue 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/customer/components/CustomerDealCycleByProduct.vue 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/customer/components/CustomerDealCycleByUser.vue 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/customer/components/CustomerFollowUpSummary.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/customer/components/CustomerFollowUpType.vue 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/customer/components/CustomerPoolSummary.vue 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/customer/components/CustomerSummary.vue 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/customer/index.vue 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/funnel/components/BusinessInversionRateSummary.vue 307 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/funnel/components/BusinessSummary.vue 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/funnel/components/FunnelBusiness.vue 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/funnel/index.vue 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/performance/components/ContractCountPerformance.vue 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/performance/components/ContractPricePerformance.vue 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/performance/index.vue 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/portrait/components/PortraitCustomerArea.vue 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/portrait/components/PortraitCustomerIndustry.vue 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/portrait/components/PortraitCustomerLevel.vue 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/portrait/index.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/rank/components/ContactCountRank.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/rank/components/ContractCountRank.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/rank/components/ContractPriceRank.vue 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/rank/components/CustomerCountRank.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/rank/components/FollowCountRank.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/rank/components/FollowCustomerCountRank.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/rank/components/ProductSalesRank.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/rank/components/ReceivablePriceRank.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/statistics/rank/index.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/finance/account/AccountForm.vue 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/finance/account/index.vue 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/finance/payment/FinancePaymentForm.vue 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/finance/payment/components/FinancePaymentItemForm.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/finance/payment/index.vue 394 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/finance/receipt/FinanceReceiptForm.vue 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/finance/receipt/components/FinanceReceiptItemForm.vue 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/finance/receipt/index.vue 394 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/home/components/SummaryCard.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/home/components/TimeSummaryChart.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/home/index.vue 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/product/category/ProductCategoryForm.vue 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/product/category/index.vue 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/product/product/ProductForm.vue 242 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/product/product/index.vue 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/product/unit/ProductUnitForm.vue 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/product/unit/index.vue 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/in/PurchaseInForm.vue 325 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/in/components/PurchaseInItemForm.vue 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/in/components/PurchaseInPaymentEnableList.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/in/index.vue 443 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/order/PurchaseOrderForm.vue 269 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/order/components/PurchaseOrderInEnableList.vue 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/order/components/PurchaseOrderItemForm.vue 276 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/order/components/PurchaseOrderReturnEnableList.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/order/index.vue 407 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/return/PurchaseReturnForm.vue 328 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/return/components/PurchaseReturnItemForm.vue 300 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/return/components/PurchaseReturnRefundEnableList.vue 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/return/index.vue 443 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/supplier/SupplierForm.vue 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/purchase/supplier/index.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/customer/CustomerForm.vue 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/customer/index.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/order/SaleOrderForm.vue 289 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/order/components/SaleOrderItemForm.vue 271 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/order/components/SaleOrderOutEnableList.vue 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/order/components/SaleOrderReturnEnableList.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/order/index.vue 407 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/out/SaleOutForm.vue 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/out/components/SaleOutItemForm.vue 300 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/out/components/SaleOutReceiptEnableList.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/out/index.vue 438 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/return/SaleReturnForm.vue 341 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/return/components/SaleReturnItemForm.vue 300 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/return/components/SaleReturnRefundEnableList.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/return/index.vue 443 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/check/StockCheckForm.vue 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/check/components/StockCheckItemForm.vue 289 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/check/index.vue 359 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/in/StockInForm.vue 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/in/components/StockInItemForm.vue 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/in/index.vue 376 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/move/StockMoveForm.vue 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/move/components/StockMoveItemForm.vue 292 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/move/index.vue 359 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/out/StockOutForm.vue 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/out/components/StockOutItemForm.vue 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/out/index.vue 378 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/record/index.vue 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/stock/index.vue 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/warehouse/WarehouseForm.vue 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/stock/warehouse/index.vue 242 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/apiAccessLog/ApiAccessLogDetail.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/apiAccessLog/index.vue 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/apiErrorLog/ApiErrorLogDetail.vue 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/apiErrorLog/index.vue 252 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/build/index.vue 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/codegen/EditTable.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/codegen/ImportTable.vue 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/codegen/PreviewCode.vue 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/codegen/components/BasicInfoForm.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/codegen/components/ColumInfoForm.vue 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/codegen/components/GenerateInfoForm.vue 385 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/codegen/components/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/codegen/index.vue 287 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/config/ConfigForm.vue 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/config/index.vue 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/dataSourceConfig/DataSourceConfigForm.vue 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/dataSourceConfig/index.vue 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo01/Demo01ContactForm.vue 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo01/index.vue 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo02/Demo02CategoryForm.vue 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo02/index.vue 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/erp/Demo03StudentForm.vue 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/erp/components/Demo03CourseForm.vue 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/erp/components/Demo03CourseList.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/erp/components/Demo03GradeForm.vue 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/erp/components/Demo03GradeList.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/erp/index.vue 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/inner/Demo03StudentForm.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/inner/components/Demo03CourseForm.vue 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/inner/components/Demo03CourseList.vue 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/inner/components/Demo03GradeForm.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/inner/components/Demo03GradeList.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/inner/index.vue 263 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/normal/Demo03StudentForm.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/normal/components/Demo03CourseForm.vue 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/normal/components/Demo03GradeForm.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/demo/demo03/normal/index.vue 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/druid/index.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/file/FileForm.vue 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/file/index.vue 238 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/fileConfig/FileConfigForm.vue 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/fileConfig/index.vue 247 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/job/JobDetail.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/job/JobForm.vue 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/job/index.vue 332 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/job/logger/JobLogDetail.vue 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/job/logger/index.vue 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/redis/index.vue 269 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/server/index.vue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/skywalking/index.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/swagger/index.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/webSocket/index.vue 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/alert/config/AlertConfigForm.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/alert/config/index.vue 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/alert/record/index.vue 296 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/DeviceForm.vue 325 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/DeviceGroupForm.vue 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/DeviceImportForm.vue 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/components/DeviceTableSelect.vue 303 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/DeviceDetailConfig.vue 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/DeviceDetailsHeader.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/DeviceDetailsInfo.vue 197 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/DeviceDetailsMessage.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/DeviceDetailsSimulator.vue 420 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/DeviceDetailsThingModel.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/DeviceDetailsThingModelEvent.vue 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/DeviceDetailsThingModelProperty.vue 245 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/DeviceDetailsThingModelPropertyHistory.vue 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/DeviceDetailsThingModelService.vue 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/detail/index.vue 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/device/index.vue 529 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/group/DeviceGroupForm.vue 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/device/group/index.vue 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/home/components/ComparisonCard.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/home/components/DeviceCountCard.vue 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/home/components/DeviceStateCountCard.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/home/components/MessageTrendCard.vue 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/home/index.vue 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/ota/firmware/OtaFirmwareForm.vue 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/ota/firmware/detail/index.vue 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/ota/firmware/index.vue 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/ota/task/OtaTaskDetail.vue 285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/ota/task/OtaTaskForm.vue 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/ota/task/OtaTaskList.vue 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/product/category/ProductCategoryForm.vue 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/product/category/index.vue 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/product/product/ProductForm.vue 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/product/product/components/ProductTableSelect.vue 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/product/product/detail/ProductDetailsHeader.vue 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/product/product/detail/ProductDetailsInfo.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/product/product/detail/index.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/product/product/index.vue 355 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/index.vue 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/rule/DataRuleForm.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/rule/components/SourceConfigForm.vue 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/rule/index.vue 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/sink/DataSinkForm.vue 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/sink/config/HttpConfigForm.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/sink/config/KafkaMQConfigForm.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/sink/config/MqttConfigForm.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/sink/config/RabbitMQConfigForm.vue 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/sink/config/RedisStreamConfigForm.vue 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/sink/config/RocketMQConfigForm.vue 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/sink/config/components/KeyValueEditor.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/sink/config/index.ts 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/data/sink/index.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/RuleSceneForm.vue 330 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/configs/AlertConfig.vue 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/configs/ConditionConfig.vue 301 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/configs/CurrentTimeConditionConfig.vue 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/configs/DeviceControlConfig.vue 376 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue 251 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/configs/MainConditionInnerConfig.vue 340 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/configs/SubConditionGroupConfig.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/inputs/JsonParamsInput.vue 519 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/inputs/ValueInput.vue 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/sections/ActionSection.vue 272 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/sections/BasicInfoSection.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/sections/TriggerSection.vue 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/selectors/DeviceSelector.vue 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/selectors/OperatorSelector.vue 264 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/selectors/ProductSelector.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/form/selectors/PropertySelector.vue 437 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/rule/scene/index.vue 492 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/ThingModelEvent.vue 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/ThingModelForm.vue 221 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/ThingModelInputOutputParam.vue 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/ThingModelProperty.vue 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/ThingModelService.vue 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/ThingModelTSL.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/components/DataDefinition.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/components/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/dataSpecs/ThingModelArrayDataSpecs.vue 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/dataSpecs/ThingModelEnumDataSpecs.vue 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/dataSpecs/ThingModelNumberDataSpecs.vue 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/dataSpecs/ThingModelStructDataSpecs.vue 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/dataSpecs/index.ts 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/thingmodel/index.vue 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/iot/utils/constants.ts 543 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/home/components/ComparisonCard.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/home/components/MemberStatisticsCard.vue 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/home/components/OperationDataCard.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/home/components/ShortcutCard.vue 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/home/components/TradeTrendCard.vue 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/home/index.vue 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/brand/BrandForm.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/brand/index.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/category/CategoryForm.vue 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/category/components/ProductCategorySelect.vue 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/category/index.vue 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/comment/CommentForm.vue 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/comment/ReplyForm.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/comment/index.vue 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/property/PropertyForm.vue 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/property/index.vue 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/property/value/ValueForm.vue 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/property/value/index.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/components/SkuList.vue 583 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/components/SkuTableSelect.vue 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/components/SpuShowcase.vue 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/components/SpuTableSelect.vue 303 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/components/index.ts 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/form/DeliveryForm.vue 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/form/DescriptionForm.vue 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/form/InfoForm.vue 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/form/OtherForm.vue 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/form/ProductAttributes.vue 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/form/ProductPropertyAddForm.vue 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/form/SkuForm.vue 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/form/index.vue 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/product/spu/index.vue 457 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/article/ArticleForm.vue 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/article/category/ArticleCategoryForm.vue 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/article/category/index.vue 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/article/index.vue 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/banner/BannerForm.vue 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/banner/index.vue 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/bargain/activity/BargainActivityForm.vue 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/bargain/activity/bargainActivity.data.ts 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/bargain/activity/index.vue 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/bargain/record/BargainRecordListDialog.vue 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/bargain/record/index.vue 197 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/combination/activity/CombinationActivityForm.vue 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/combination/activity/combinationActivity.data.ts 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/combination/activity/index.vue 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/combination/components/CombinationShowcase.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/combination/components/CombinationTableSelect.vue 345 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/combination/record/CombinationRecordListDialog.vue 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/combination/record/index.vue 276 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/components/SpuAndSkuList.vue 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/components/SpuSelect.vue 324 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/components/index.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/coupon/components/CouponSelect.vue 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/coupon/components/CouponSendForm.vue 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/coupon/components/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/coupon/formatter.ts 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/coupon/index.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/coupon/template/CouponTemplateForm.vue 404 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/coupon/template/index.vue 284 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/discountActivity/DiscountActivityForm.vue 265 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/discountActivity/discountActivity.data.ts 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/discountActivity/index.vue 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/diy/page/DiyPageForm.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/diy/page/decorate.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/diy/page/index.vue 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/diy/template/DiyTemplateForm.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/diy/template/decorate.vue 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/diy/template/index.vue 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/KeFuConversationList.vue 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/KeFuMessageList.vue 526 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/a.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/aini.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/aixin.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/baiyan.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/bizui.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/buhaoyisi.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/bukesiyi.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/dajing.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/danao.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/daxiao.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/dianzan.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/emo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/esi.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/fadai.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/fankun.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/feiwen.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/fennu.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/ganga.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/ganmao.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/hanyan.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/haochi.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/hongxin.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/huaixiao.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/jingkong.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/jingshu.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/jingya.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/kaixin.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/keai.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/keshui.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/kun.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/lengku.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/liuhan.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/liukoushui.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/liulei.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/mengbi.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/mianwubiaoqing.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/nanguo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/outu.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/picture.svg 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/shengqi.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/shuizhuo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/tianshi.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/xiaodiaoya.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/xiaoku.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/xinsui.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/xiong.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/yiwen.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/yun.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/asserts/ziya.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/index.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/member/MemberInfo.vue 255 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/member/OrderBrowsingHistory.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/member/ProductBrowsingHistory.vue 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/message/MessageItem.vue 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/message/OrderItem.vue 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/message/ProductItem.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/tools/EmojiSelectPopover.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/tools/PictureSelectUpload.vue 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/tools/constants.ts 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/components/tools/emoji.ts 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/kefu/index.vue 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/point/activity/PointActivityForm.vue 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/point/activity/index.vue 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/point/activity/pointActivity.data.ts 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/point/components/PointShowcase.vue 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/point/components/PointTableSelect.vue 300 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/rewardActivity/RewardForm.vue 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/rewardActivity/components/RewardRule.vue 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/rewardActivity/components/RewardRuleCouponSelect.vue 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/rewardActivity/index.vue 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/seckill/activity/SeckillActivityForm.vue 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/seckill/activity/index.vue 256 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/seckill/activity/seckillActivity.data.ts 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/seckill/components/SeckillShowcase.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/seckill/components/SeckillTableSelect.vue 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/seckill/config/SeckillConfigForm.vue 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/promotion/seckill/config/index.vue 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/statistics/member/components/MemberFunnelCard.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/statistics/member/components/MemberTerminalCard.vue 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/statistics/member/index.vue 313 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/statistics/product/components/ProductRank.vue 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/statistics/product/components/ProductSummary.vue 304 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/statistics/product/index.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/statistics/trade/components/TradeStatisticValue.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/statistics/trade/index.vue 363 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/afterSale/detail/index.vue 358 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/afterSale/form/AfterSaleDisagreeForm.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/afterSale/index.vue 273 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/brokerage/record/index.vue 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/brokerage/user/BrokerageOrderListDialog.vue 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/brokerage/user/BrokerageUserCreateForm.vue 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/brokerage/user/BrokerageUserListDialog.vue 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/brokerage/user/BrokerageUserUpdateForm.vue 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/brokerage/user/index.vue 331 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/brokerage/withdraw/BrokerageWithdrawRejectForm.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/brokerage/withdraw/index.vue 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/config/index.vue 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/delivery/express/ExpressForm.vue 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/delivery/express/index.vue 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/delivery/expressTemplate/ExpressTemplateForm.vue 321 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/delivery/expressTemplate/index.vue 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/delivery/pickUpOrder/index.vue 436 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/delivery/pickUpStore/DeliveryPickUpStoreBindForm.vue 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/delivery/pickUpStore/PickUpStoreForm.vue 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/delivery/pickUpStore/components/StoreStaffTableSelect.vue 264 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/delivery/pickUpStore/index.vue 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/order/components/OrderTableColumn.vue 303 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/order/components/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/order/detail/index.vue 427 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/order/form/OrderDeliveryForm.vue 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/order/form/OrderPickUpForm.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/order/form/OrderUpdateAddressForm.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/order/form/OrderUpdatePriceForm.vue 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/order/form/OrderUpdateRemarkForm.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mall/trade/order/index.vue 357 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/config/index.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/group/GroupForm.vue 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/group/components/MemberGroupSelect.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/group/index.vue 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/level/LevelForm.vue 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/level/components/MemberLevelSelect.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/level/index.vue 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/point/record/index.vue 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/signin/config/SignInConfigForm.vue 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/signin/config/index.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/signin/record/index.vue 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/tag/TagForm.vue 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/tag/components/MemberTagSelect.vue 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/tag/index.vue 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/UserForm.vue 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/components/UserBalanceUpdateForm.vue 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/components/UserLevelUpdateForm.vue 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/components/UserPointUpdateForm.vue 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserAccountInfo.vue 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserAddressList.vue 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserAftersaleList.vue 276 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserBalanceList.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserBasicInfo.vue 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserBrokerageList.vue 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserCouponList.vue 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserExperienceRecordList.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserFavoriteList.vue 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserOrderList.vue 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserPointList.vue 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/UserSignList.vue 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/detail/index.vue 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/member/user/index.vue 317 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/account/AccountForm.vue 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/account/index.vue 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/autoReply/components/ReplyForm.vue 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/autoReply/components/ReplyTable.vue 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/autoReply/components/types.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/autoReply/index.vue 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-account-select/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-account-select/main.vue 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-location/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-location/main.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-material-select/index.ts 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-material-select/main.vue 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-material-select/types.ts 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-msg/card.scss 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-msg/comment.scss 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-msg/components/Msg.vue 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-msg/components/MsgEvent.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-msg/components/MsgList.vue 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-msg/index.ts 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-msg/main.vue 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-msg/types.ts 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-music/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-music/main.vue 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-news/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-news/main.vue 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-reply/components/TabImage.vue 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-reply/components/TabMusic.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-reply/components/TabNews.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-reply/components/TabText.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-reply/components/TabVideo.vue 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-reply/components/TabVoice.vue 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-reply/components/types.ts 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-reply/index.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-reply/main.vue 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-video-play/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-video-play/main.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-voice-play/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/components/wx-voice-play/main.vue 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/draft/components/CoverSelect.vue 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/draft/components/DraftTable.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/draft/components/NewsForm.vue 306 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/draft/components/index.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/draft/components/types.ts 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/draft/editor-config.ts 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/draft/index.vue 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/draft/mock.js 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/freePublish/index.vue 338 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/hooks/useUpload.ts 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/material/components/ImageTable.vue 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/material/components/UploadFile.vue 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/material/components/UploadVideo.vue 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/material/components/VideoTable.vue 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/material/components/VoiceTable.vue 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/material/components/upload.ts 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/material/index.vue 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/menu/assets/iphone_backImg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/menu/assets/menu_foot.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/menu/assets/menu_head.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/menu/components/MenuEditor.vue 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/menu/components/MenuPreviewer.vue 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/menu/components/menuOptions.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/menu/components/types.ts 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/menu/index.vue 403 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/message/MessageTable.vue 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/message/index.vue 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/messageTemplate/MessageTemplateSendForm.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/messageTemplate/index.vue 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/statistics/index.vue 357 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/tag/TagForm.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/tag/index.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/user/UserForm.vue 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mp/user/index.vue 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/app/components/AppForm.vue 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/app/components/channel/AlipayChannelForm.vue 351 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/app/components/channel/MockChannelForm.vue 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/app/components/channel/WalletChannelForm.vue 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/app/components/channel/WeixinChannelForm.vue 377 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/app/index.vue 372 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/cashier/index.vue 494 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/demo/order/index.vue 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/demo/withdraw/DemoWithdrawForm.vue 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/demo/withdraw/index.vue 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/notify/NotifyDetail.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/notify/index.vue 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/order/OrderDetail.vue 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/order/index.vue 275 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/refund/RefundDetail.vue 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/refund/index.vue 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/transfer/TransferDetail.vue 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/transfer/index.vue 283 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/wallet/balance/WalletForm.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/wallet/balance/index.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/wallet/rechargePackage/WalletRechargePackageForm.vue 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/wallet/rechargePackage/index.vue 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pay/wallet/transaction/WalletTransactionList.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/report/goview/index.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/report/jmreport/bi.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/report/jmreport/index.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/area/AreaForm.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/area/index.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/dept/DeptForm.vue 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/dept/index.vue 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/dict/DictTypeForm.vue 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/dict/data/DictDataForm.vue 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/dict/data/index.vue 245 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/dict/index.vue 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/loginlog/LoginLogDetail.vue 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/loginlog/index.vue 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/mail/account/MailAccountForm.vue 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/mail/account/index.vue 213 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/mail/log/MailLogDetail.vue 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/mail/log/index.vue 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/mail/template/MailTemplateForm.vue 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/mail/template/MailTemplateSendForm.vue 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/mail/template/index.vue 302 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/menu/MenuForm.vue 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/menu/index.vue 318 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/notice/NoticeForm.vue 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/notice/index.vue 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/notify/message/NotifyMessageDetail.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/notify/message/index.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/notify/my/MyNotifyMessageDetail.vue 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/notify/my/index.vue 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/notify/template/NotifyTemplateForm.vue 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/notify/template/NotifyTemplateSendForm.vue 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/notify/template/index.vue 265 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/oauth2/client/ClientForm.vue 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/oauth2/client/index.vue 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/oauth2/token/index.vue 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/operatelog/OperateLogDetail.vue 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/operatelog/index.vue 213 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/post/PostForm.vue 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/post/index.vue 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/role/RoleAssignMenuForm.vue 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/role/RoleDataPermissionForm.vue 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/role/RoleForm.vue 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/role/index.vue 299 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/sms/channel/SmsChannelForm.vue 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/sms/channel/index.vue 238 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/sms/log/SmsLogDetail.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/sms/log/index.vue 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/sms/template/SmsTemplateForm.vue 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/sms/template/SmsTemplateSendForm.vue 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/sms/template/index.vue 345 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/social/client/SocialClientForm.vue 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/social/client/index.vue 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/social/user/SocialUserDetail.vue 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/social/user/index.vue 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tenant/TenantForm.vue 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tenant/index.vue 304 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tenantPackage/TenantPackageForm.vue 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tenantPackage/index.vue 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/user/DeptTree.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/user/UserAssignRoleForm.vue 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/user/UserForm.vue 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/user/UserImportForm.vue 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/user/index.vue 397 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
stylelint.config.js 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tsconfig.json 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
types/components.d.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
types/env.d.ts 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
types/global.d.ts 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
types/router.d.ts 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
types/wangeditor-types.d.ts 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
uno.config.ts 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.ts 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web-types.json 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.editorconfig
New file
@@ -0,0 +1,12 @@
root = true
[*.{js,ts,vue}]
charset = utf-8 # è®¾ç½®æ–‡ä»¶å­—符集为 utf-8
end_of_line = lf # æŽ§åˆ¶æ¢è¡Œç±»åž‹(lf | cr | crlf)
insert_final_newline = true # å§‹ç»ˆåœ¨æ–‡ä»¶æœ«å°¾æ’入一个新行
indent_style = space # ç¼©è¿›é£Žæ ¼ï¼ˆtab | space)
indent_size = 2 # ç¼©è¿›å¤§å°
max_line_length = 100 # æœ€å¤§è¡Œé•¿åº¦
[*.md] # ä»… md æ–‡ä»¶é€‚用以下规则
max_line_length = off # å…³é—­æœ€å¤§è¡Œé•¿åº¦é™åˆ¶
trim_trailing_whitespace = false # å…³é—­æœ«å°¾ç©ºæ ¼ä¿®å‰ª
.env
New file
@@ -0,0 +1,37 @@
# æ ‡é¢˜
VITE_APP_TITLE=芋道管理系统
# é¡¹ç›®æœ¬åœ°è¿è¡Œç«¯å£å·
VITE_PORT=80
# open è¿è¡Œ npm run dev æ—¶è‡ªåŠ¨æ‰“å¼€æµè§ˆå™¨
VITE_OPEN=true
# ç§Ÿæˆ·å¼€å…³
VITE_APP_TENANT_ENABLE=true
# éªŒè¯ç çš„开关
VITE_APP_CAPTCHA_ENABLE=true
# æ–‡æ¡£åœ°å€çš„开关
VITE_APP_DOCALERT_ENABLE=true
# ç™¾åº¦ç»Ÿè®¡
VITE_APP_BAIDU_CODE = a1ff8825baa73c3a78eb96aa40325abc
# é»˜è®¤è´¦æˆ·å¯†ç 
VITE_APP_DEFAULT_LOGIN_TENANT = èŠ‹é“æºç 
VITE_APP_DEFAULT_LOGIN_USERNAME = admin
VITE_APP_DEFAULT_LOGIN_PASSWORD = admin123
# API åŠ è§£å¯†
VITE_APP_API_ENCRYPT_ENABLE = true
VITE_APP_API_ENCRYPT_HEADER = X-Api-Encrypt
VITE_APP_API_ENCRYPT_ALGORITHM = AES
VITE_APP_API_ENCRYPT_REQUEST_KEY = 52549111389893486934626385991395
VITE_APP_API_ENCRYPT_RESPONSE_KEY = 96103715984234343991809655248883
# VITE_APP_API_ENCRYPT_REQUEST_KEY = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCls2rIpnGdYnLFgz1XU13GbNQ5DloyPpvW00FPGjqn5Z6JpK+kDtVlnkhwR87iRrE5Vf2WNqRX6vzbLSgveIQY8e8oqGCb829myjf1MuI+ZzN4ghf/7tEYhZJGPI9AbfxFqBUzm+kR3/HByAI22GLT96WM26QiMK8n3tIP/yiLswIDAQAB
# VITE_APP_API_ENCRYPT_RESPONSE_KEY = MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOH8IfIFxL/MR9XIg1UDv5z1fGXQI93E8wrU4iPFovL/sEt9uSgSkjyidC2O7N+m7EKtoN6b1u7cEwXSkwf3kfK0jdWLSQaNpX5YshqXCBzbDfugDaxuyYrNA4/tIMs7mzZAk0APuRXB35Dmupou7Yw7TFW/7QhQmGfzeEKULQvnAgMBAAECgYAw8LqlQGyQoPv5p3gRxEMOCfgL0JzD3XBJKztiRd35RDh40Nx1ejgjW4dPioFwGiVWd2W8cAGHLzALdcQT2KDJh+T/tsd4SPmI6uSBBK6Ff2DkO+kFFcuYvfclQQKqxma5CaZOSqhgenacmgTMFeg2eKlY3symV6JlFNu/IKU42QJBAOhxAK/Eq3e61aYQV2JSguhMR3b8NXJJRroRs/QHEanksJtl+M+2qhkC9nQVXBmBkndnkU/l2tYcHfSBlAyFySMCQQD445tgm/J2b6qMQmuUGQAYDN8FIkHjeKmha+l/fv0igWm8NDlBAem91lNDIPBUzHL1X1+pcts5bjmq99YdOnhtAkAg2J8dN3B3idpZDiQbC8fd5bGPmdI/pSUudAP27uzLEjr2qrE/QPPGdwm2m7IZFJtK7kK1hKio6u48t/bg0iL7AkEAuUUs94h+v702Fnym+jJ2CHEkXvz2US8UDs52nWrZYiM1o1y4tfSHm8H8bv8JCAa9GHyriEawfBraILOmllFdLQJAQSRZy4wmlaG48MhVXodB85X+VZ9krGXZ2TLhz7kz9iuToy53l9jTkESt6L5BfBDCVdIwcXLYgK+8KFdHN5W7HQ==
# ç™¾åº¦åœ°å›¾
VITE_BAIDU_MAP_KEY = 'efHIw2qmH8RzHPxK0z0rbCgzDVLup9LD'
.env.dev
New file
@@ -0,0 +1,37 @@
# å¼€å‘环境:本地只启动前端项目,依赖开发环境(后端、APP)
NODE_ENV=production
VITE_DEV=true
# è¯·æ±‚路径
VITE_BASE_URL='http://101.43.143.75:48080'
# æ–‡ä»¶ä¸Šä¼ ç±»åž‹ï¼šserver - åŽç«¯ä¸Šä¼ ï¼Œ client - å‰ç«¯ç›´è¿žä¸Šä¼ ï¼Œä»…支持S3服务
VITE_UPLOAD_TYPE=server
# æŽ¥å£åœ°å€
VITE_API_URL=/admin-api
# æ˜¯å¦åˆ é™¤debugger
VITE_DROP_DEBUGGER=false
# æ˜¯å¦åˆ é™¤console.log
VITE_DROP_CONSOLE=false
# æ˜¯å¦sourcemap
VITE_SOURCEMAP=true
# æ‰“包路径
VITE_BASE_PATH=/
# è¾“出路径
VITE_OUT_DIR=dist
# å•†åŸŽH5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
# éªŒè¯ç çš„开关
VITE_APP_CAPTCHA_ENABLE=true
# GoView域名
VITE_GOVIEW_URL='http://127.0.0.1:3000'
.env.local
New file
@@ -0,0 +1,36 @@
# æœ¬åœ°å¼€å‘环境:本地启动所有项目(前端、后端、APP)时使用,不依赖外部环境
NODE_ENV=development
VITE_DEV=true
# è¯·æ±‚路径
VITE_BASE_URL='http://101.43.143.75:48080'
# VITE_BASE_URL='https://gdkw.qxueyou.com/'
# æ–‡ä»¶ä¸Šä¼ ç±»åž‹ï¼šserver - åŽç«¯ä¸Šä¼ ï¼Œ client - å‰ç«¯ç›´è¿žä¸Šä¼ ï¼Œä»…支持 S3 æœåŠ¡
VITE_UPLOAD_TYPE=server
# æŽ¥å£åœ°å€
VITE_API_URL=/admin-api
# æ˜¯å¦åˆ é™¤debugger
VITE_DROP_DEBUGGER=false
# æ˜¯å¦åˆ é™¤console.log
VITE_DROP_CONSOLE=false
# æ˜¯å¦sourcemap
VITE_SOURCEMAP=false
# æ‰“包路径
VITE_BASE_PATH=/
# å•†åŸŽH5会员端域名
VITE_MALL_H5_DOMAIN='http://localhost:3000'
# éªŒè¯ç çš„开关
VITE_APP_CAPTCHA_ENABLE=false
# GoView域名
VITE_GOVIEW_URL='http://127.0.0.1:3000'
.env.prod
New file
@@ -0,0 +1,34 @@
# ç”Ÿäº§çŽ¯å¢ƒï¼šåªåœ¨æ‰“åŒ…æ—¶ä½¿ç”¨
NODE_ENV=production
VITE_DEV=false
# è¯·æ±‚路径
VITE_BASE_URL='http://localhost:48080'
# æ–‡ä»¶ä¸Šä¼ ç±»åž‹ï¼šserver - åŽç«¯ä¸Šä¼ ï¼Œ client - å‰ç«¯ç›´è¿žä¸Šä¼ ï¼Œä»…支持S3服务
VITE_UPLOAD_TYPE=server
# æŽ¥å£åœ°å€
VITE_API_URL=/admin-api
# æ˜¯å¦åˆ é™¤debugger
VITE_DROP_DEBUGGER=true
# æ˜¯å¦åˆ é™¤console.log
VITE_DROP_CONSOLE=true
# æ˜¯å¦sourcemap
VITE_SOURCEMAP=false
# æ‰“包路径
VITE_BASE_PATH=/
# è¾“出路径
VITE_OUT_DIR=dist-prod
# å•†åŸŽH5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
# GoView域名
VITE_GOVIEW_URL='http://127.0.0.1:3000'
.env.stage
New file
@@ -0,0 +1,34 @@
# é¢„发布环境:只在打包时使用
NODE_ENV=production
VITE_DEV=false
# è¯·æ±‚路径
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
# æ–‡ä»¶ä¸Šä¼ ç±»åž‹ï¼šserver - åŽç«¯ä¸Šä¼ ï¼Œ client - å‰ç«¯ç›´è¿žä¸Šä¼ ï¼Œä»…支持S3服务
VITE_UPLOAD_TYPE=server
# æŽ¥å£åœ°å€
VITE_API_URL=/admin-api
# æ˜¯å¦åˆ é™¤debugger
VITE_DROP_DEBUGGER=true
# æ˜¯å¦åˆ é™¤console.log
VITE_DROP_CONSOLE=true
# æ˜¯å¦sourcemap
VITE_SOURCEMAP=false
# æ‰“包路径
VITE_BASE_PATH='http://static-vue3.yudao.iocoder.cn/'
# è¾“出路径
VITE_OUT_DIR=dist-stage
# å•†åŸŽH5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
# GoView域名
VITE_GOVIEW_URL='http://127.0.0.1:3000'
.env.test
New file
@@ -0,0 +1,34 @@
# æµ‹è¯•环境:只在打包时使用
NODE_ENV=production
VITE_DEV=false
# è¯·æ±‚路径
VITE_BASE_URL='http://localhost:48080'
# æ–‡ä»¶ä¸Šä¼ ç±»åž‹ï¼šserver - åŽç«¯ä¸Šä¼ ï¼Œ client - å‰ç«¯ç›´è¿žä¸Šä¼ ï¼Œä»…支持S3服务
VITE_UPLOAD_TYPE=server
# æŽ¥å£åœ°å€
VITE_API_URL=/admin-api
# æ˜¯å¦åˆ é™¤debugger
VITE_DROP_DEBUGGER=true
# æ˜¯å¦åˆ é™¤console.log
VITE_DROP_CONSOLE=true
# æ˜¯å¦sourcemap
VITE_SOURCEMAP=false
# æ‰“包路径
VITE_BASE_PATH=/admin-ui-vue3/
# è¾“出路径
VITE_OUT_DIR=dist-test
# å•†åŸŽH5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
# GoView域名
VITE_GOVIEW_URL='http://127.0.0.1:3000'
.eslintignore
New file
@@ -0,0 +1,8 @@
/build/
/config/
/dist/
/*.js
/test/unit/coverage/
/node_modules/*
/dist*
/src/main.ts
.eslintrc-auto-import.json
New file
@@ -0,0 +1,259 @@
{
  "globals": {
    "EffectScope": true,
    "ElMessage": true,
    "ElMessageBox": true,
    "ElTag": true,
    "asyncComputed": true,
    "autoResetRef": true,
    "computed": true,
    "computedAsync": true,
    "computedEager": true,
    "computedInject": true,
    "computedWithControl": true,
    "controlledComputed": true,
    "controlledRef": true,
    "createApp": true,
    "createEventHook": true,
    "createGlobalState": true,
    "createInjectionState": true,
    "createReactiveFn": true,
    "createSharedComposable": true,
    "createUnrefFn": true,
    "customRef": true,
    "debouncedRef": true,
    "debouncedWatch": true,
    "defineAsyncComponent": true,
    "defineComponent": true,
    "eagerComputed": true,
    "effectScope": true,
    "extendRef": true,
    "getCurrentInstance": true,
    "getCurrentScope": true,
    "h": true,
    "ignorableWatch": true,
    "inject": true,
    "isDefined": true,
    "isProxy": true,
    "isReactive": true,
    "isReadonly": true,
    "isRef": true,
    "makeDestructurable": true,
    "markRaw": true,
    "nextTick": true,
    "onActivated": true,
    "onBeforeMount": true,
    "onBeforeUnmount": true,
    "onBeforeUpdate": true,
    "onClickOutside": true,
    "onDeactivated": true,
    "onErrorCaptured": true,
    "onKeyStroke": true,
    "onLongPress": true,
    "onMounted": true,
    "onRenderTracked": true,
    "onRenderTriggered": true,
    "onScopeDispose": true,
    "onServerPrefetch": true,
    "onStartTyping": true,
    "onUnmounted": true,
    "onUpdated": true,
    "pausableWatch": true,
    "provide": true,
    "reactify": true,
    "reactifyObject": true,
    "reactive": true,
    "reactiveComputed": true,
    "reactiveOmit": true,
    "reactivePick": true,
    "readonly": true,
    "ref": true,
    "refAutoReset": true,
    "refDebounced": true,
    "refDefault": true,
    "refThrottled": true,
    "refWithControl": true,
    "resolveComponent": true,
    "resolveRef": true,
    "resolveUnref": true,
    "shallowReactive": true,
    "shallowReadonly": true,
    "shallowRef": true,
    "syncRef": true,
    "syncRefs": true,
    "templateRef": true,
    "throttledRef": true,
    "throttledWatch": true,
    "toRaw": true,
    "toReactive": true,
    "toRef": true,
    "toRefs": true,
    "triggerRef": true,
    "tryOnBeforeMount": true,
    "tryOnBeforeUnmount": true,
    "tryOnMounted": true,
    "tryOnScopeDispose": true,
    "tryOnUnmounted": true,
    "unref": true,
    "unrefElement": true,
    "until": true,
    "useActiveElement": true,
    "useArrayEvery": true,
    "useArrayFilter": true,
    "useArrayFind": true,
    "useArrayFindIndex": true,
    "useArrayJoin": true,
    "useArrayMap": true,
    "useArrayReduce": true,
    "useArraySome": true,
    "useAsyncQueue": true,
    "useAsyncState": true,
    "useAttrs": true,
    "useBase64": true,
    "useBattery": true,
    "useBluetooth": true,
    "useBreakpoints": true,
    "useBroadcastChannel": true,
    "useBrowserLocation": true,
    "useCached": true,
    "useClipboard": true,
    "useColorMode": true,
    "useConfirmDialog": true,
    "useCounter": true,
    "useCssModule": true,
    "useCssVar": true,
    "useCssVars": true,
    "useCurrentElement": true,
    "useCycleList": true,
    "useDark": true,
    "useDateFormat": true,
    "useDebounce": true,
    "useDebounceFn": true,
    "useDebouncedRefHistory": true,
    "useDeviceMotion": true,
    "useDeviceOrientation": true,
    "useDevicePixelRatio": true,
    "useDevicesList": true,
    "useDisplayMedia": true,
    "useDocumentVisibility": true,
    "useDraggable": true,
    "useDropZone": true,
    "useElementBounding": true,
    "useElementByPoint": true,
    "useElementHover": true,
    "useElementSize": true,
    "useElementVisibility": true,
    "useEventBus": true,
    "useEventListener": true,
    "useEventSource": true,
    "useEyeDropper": true,
    "useFavicon": true,
    "useFetch": true,
    "useFileDialog": true,
    "useFileSystemAccess": true,
    "useFocus": true,
    "useFocusWithin": true,
    "useFps": true,
    "useFullscreen": true,
    "useGamepad": true,
    "useGeolocation": true,
    "useIdle": true,
    "useImage": true,
    "useInfiniteScroll": true,
    "useIntersectionObserver": true,
    "useInterval": true,
    "useIntervalFn": true,
    "useKeyModifier": true,
    "useLastChanged": true,
    "useLocalStorage": true,
    "useMagicKeys": true,
    "useManualRefHistory": true,
    "useMediaControls": true,
    "useMediaQuery": true,
    "useMemoize": true,
    "useMemory": true,
    "useMounted": true,
    "useMouse": true,
    "useMouseInElement": true,
    "useMousePressed": true,
    "useMutationObserver": true,
    "useNavigatorLanguage": true,
    "useNetwork": true,
    "useNow": true,
    "useObjectUrl": true,
    "useOffsetPagination": true,
    "useOnline": true,
    "usePageLeave": true,
    "useParallax": true,
    "usePermission": true,
    "usePointer": true,
    "usePointerSwipe": true,
    "usePreferredColorScheme": true,
    "usePreferredDark": true,
    "usePreferredLanguages": true,
    "useRafFn": true,
    "useRefHistory": true,
    "useResizeObserver": true,
    "useRoute": true,
    "useRouter": true,
    "useScreenOrientation": true,
    "useScreenSafeArea": true,
    "useScriptTag": true,
    "useScroll": true,
    "useScrollLock": true,
    "useSessionStorage": true,
    "useShare": true,
    "useSlots": true,
    "useSpeechRecognition": true,
    "useSpeechSynthesis": true,
    "useStepper": true,
    "useStorage": true,
    "useStorageAsync": true,
    "useStyleTag": true,
    "useSupported": true,
    "useSwipe": true,
    "useTemplateRefsList": true,
    "useTextDirection": true,
    "useTextSelection": true,
    "useTextareaAutosize": true,
    "useThrottle": true,
    "useThrottleFn": true,
    "useThrottledRefHistory": true,
    "useTimeAgo": true,
    "useTimeout": true,
    "useTimeoutFn": true,
    "useTimeoutPoll": true,
    "useTimestamp": true,
    "useTitle": true,
    "useToggle": true,
    "useTransition": true,
    "useUrlSearchParams": true,
    "useUserMedia": true,
    "useVModel": true,
    "useVModels": true,
    "useVibrate": true,
    "useVirtualList": true,
    "useWakeLock": true,
    "useWebNotification": true,
    "useWebSocket": true,
    "useWebWorker": true,
    "useWebWorkerFn": true,
    "useWindowFocus": true,
    "useWindowScroll": true,
    "useWindowSize": true,
    "watch": true,
    "watchArray": true,
    "watchAtMost": true,
    "watchDebounced": true,
    "watchEffect": true,
    "watchIgnorable": true,
    "watchOnce": true,
    "watchPausable": true,
    "watchPostEffect": true,
    "watchSyncEffect": true,
    "watchThrottled": true,
    "watchTriggerable": true,
    "watchWithFilter": true,
    "whenever": true
  }
}
.eslintrc.js
New file
@@ -0,0 +1,75 @@
// @ts-check
const { defineConfig } = require('eslint-define-config')
module.exports = defineConfig({
  root: true,
  env: {
    browser: true,
    node: true,
    es6: true
  },
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    ecmaVersion: 2020,
    sourceType: 'module',
    jsxPragma: 'React',
    ecmaFeatures: {
      jsx: true
    }
  },
  extends: [
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier',
    'plugin:prettier/recommended',
    '@unocss'
  ],
  rules: {
    'vue/no-setup-props-destructure': 'off',
    'vue/script-setup-uses-vars': 'error',
    'vue/no-reserved-component-names': 'off',
    '@typescript-eslint/ban-ts-ignore': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/no-var-requires': 'off',
    '@typescript-eslint/no-empty-function': 'off',
    'vue/custom-event-name-casing': 'off',
    'no-use-before-define': 'off',
    '@typescript-eslint/no-use-before-define': 'off',
    '@typescript-eslint/ban-ts-comment': 'off',
    '@typescript-eslint/ban-types': 'off',
    '@typescript-eslint/no-non-null-assertion': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    '@typescript-eslint/no-unused-vars': 'off',
    'no-unused-vars': 'off',
    'space-before-function-paren': 'off',
    'vue/attributes-order': 'off',
    'vue/one-component-per-file': 'off',
    'vue/html-closing-bracket-newline': 'off',
    'vue/max-attributes-per-line': 'off',
    'vue/multiline-html-element-content-newline': 'off',
    'vue/singleline-html-element-content-newline': 'off',
    'vue/attribute-hyphenation': 'off',
    'vue/require-default-prop': 'off',
    'vue/require-explicit-emits': 'off',
    'vue/require-toggle-inside-transition': 'off',
    'vue/html-self-closing': [
      'error',
      {
        html: {
          void: 'always',
          normal: 'never',
          component: 'always'
        },
        svg: 'always',
        math: 'always'
      }
    ],
    'vue/multi-word-component-names': 'off',
    'vue/no-v-html': 'off',
    'prettier/prettier': 'off', // èŠ‹è‰¿ï¼šé»˜è®¤å…³é—­ prettier çš„ ESLint æ ¡éªŒï¼Œå› ä¸ºæˆ‘们使用的是 IDE çš„ Prettier æ’ä»¶
    '@unocss/order': 'off', // èŠ‹è‰¿ï¼šç¦ç”¨ unocss ã€css】顺序的提示,因为暂时不需要这么严格,警告也有点繁琐
    '@unocss/order-attributify': 'off' // èŠ‹è‰¿ï¼šç¦ç”¨ unocss ã€å±žæ€§ã€‘顺序的提示,因为暂时不需要这么严格,警告也有点繁琐
  }
})
.gitignore
New file
@@ -0,0 +1,9 @@
node_modules
.DS_Store
dist
dist-ssr
/dist*
pnpm-debug
auto-*.d.ts
.idea
.history
.image/Java¼à¿Ø.jpg
.image/MySQL.jpg
.image/OAÇë¼Ù-Áбí.jpg
.image/OAÇë¼Ù-·¢Æð.jpg
.image/OAÇë¼Ù-ÏêÇé.jpg
.image/Redis.jpg
.image/admin-uniapp/01.png
.image/admin-uniapp/02.png
.image/admin-uniapp/03.png
.image/admin-uniapp/04.png
.image/admin-uniapp/05.png
.image/admin-uniapp/06.png
.image/admin-uniapp/07.png
.image/admin-uniapp/08.png
.image/admin-uniapp/09.png
.image/common/ai-feature.png
.image/common/ai-preview.gif
.image/common/bpm-feature.png
.image/common/crm-feature.png
.image/common/erp-feature.png
.image/common/infra-feature.png
.image/common/mall-feature.png
.image/common/mall-preview.png
.image/common/project-vs.png
.image/common/ruoyi-vue-pro-architecture.png
.image/common/ruoyi-vue-pro-biz.png
.image/common/system-feature.png
.image/common/yudao-cloud-architecture.png
.image/common/yudao-roadmap.png
.image/demo/vue3-ep.png
.image/¸öÈËÖÐÐÄ.jpg
.image/´úÂëÉú³É.jpg
.image/ÁîÅÆ¹ÜÀí.jpg
.image/ÈÎÎñÁбí-ÉóÅú.jpg
.image/ÈÎÎñÁбí-ÒѰì.jpg
.image/ÈÎÎñÁбí-´ý°ì.jpg
.image/ÈÎÎñÈÕÖ¾.jpg
.image/ÉÌ»§ÐÅÏ¢.jpg
.image/ÔÚÏßÓû§.jpg
.image/´óÆÁÉè¼ÆÆ÷-Áбí.jpg
.image/´óÆÁÉè¼ÆÆ÷-±à¼­.jpg
.image/´óÆÁÉè¼ÆÆ÷-Ô¤ÀÀ.jpg
.image/×ÖµäÊý¾Ý.jpg
.image/×ÖµäÀàÐÍ.jpg
.image/¶¨Ê±ÈÎÎñ.jpg
.image/¸Úλ¹ÜÀí.jpg
.image/¹¤×÷Á÷Éè¼ÆÆ÷-bpmn.jpg
.image/¹¤×÷Á÷Éè¼ÆÆ÷-simple.jpg
.image/Ó¦ÓÃÐÅÏ¢-Áбí.jpg
.image/Ó¦ÓÃÐÅÏ¢-±à¼­.jpg
.image/Ó¦ÓùÜÀí.jpg
.image/ÎÒµÄÁ÷³Ì-Áбí.jpg
.image/ÎÒµÄÁ÷³Ì-·¢Æð.jpg
.image/ÎÒµÄÁ÷³Ì-ÏêÇé.jpg
.image/±¨±íÉè¼ÆÆ÷-ͼÐᨱí.jpg
.image/±¨±íÉè¼ÆÆ÷-´òÓ¡Éè¼Æ.jpg
.image/±¨±íÉè¼ÆÆ÷-Êý¾Ý±¨±í.jpg
.image/²Ù×÷ÈÕÖ¾.jpg
.image/Ö§¸¶¶©µ¥.jpg
.image/Ãô¸Ð´Ê.jpg
.image/Êý¾Ý¿âÎĵµ.jpg
.image/Îļþ¹ÜÀí.jpg
.image/Îļþ¹ÜÀí2.jpg
.image/ÎļþÅäÖÃ.jpg
.image/ÈÕÖ¾ÖÐÐÄ.jpg
.image/Á÷³ÌÄ£ÐÍ-Áбí.jpg
.image/Á÷³ÌÄ£ÐÍ-¶¨Òå.jpg
.image/Á÷³ÌÄ£ÐÍ-Éè¼Æ.jpg
.image/Á÷³Ì±íµ¥.jpg
.image/Éú³ÉЧ¹û.jpg
.image/Óû§·Ö×é.jpg
.image/Óû§¹ÜÀí.jpg
.image/怬.jpg
.image/µÇ¼ÈÕÖ¾.jpg
.image/¶ÌÐÅÈÕÖ¾.jpg
.image/¶ÌÐÅÄ£°å.jpg
.image/¶ÌÐÅÇþµÀ.jpg
.image/×â»§ÌײÍ.png
.image/×â»§¹ÜÀí.jpg
.image/ϵͳ½Ó¿Ú.jpg
.image/²Ëµ¥¹ÜÀí.jpg
.image/±íµ¥¹¹½¨.jpg
.image/½ÇÉ«¹ÜÀí.jpg
.image/·ÃÎÊÈÕÖ¾.jpg
.image/Í˿µ¥.jpg
.image/֪ͨ¹«¸æ.jpg
.image/²¿ÃŹÜÀí.jpg
.image/ÅäÖùÜÀí.jpg
.image/Á´Â·×·×Ù.jpg
.image/´íÎóÈÕÖ¾.jpg
.image/´íÎóÂë¹ÜÀí.jpg
.image/Ê×Ò³.jpg
.prettierignore
New file
@@ -0,0 +1,11 @@
/node_modules/**
/dist/
/dist*
/public/*
/docs/*
/vite.config.ts
/src/types/env.d.ts
/src/types/auto-components.d.ts
/src/types/auto-imports.d.ts
/docs/**/*
CHANGELOG
.stylelintignore
New file
@@ -0,0 +1,6 @@
/dist/*
/public/*
public/*
/dist*
/src/types/env.d.ts
/docs/**/*
.vscode/extensions.json
New file
@@ -0,0 +1,18 @@
{
  "recommendations": [
    "christian-kohler.path-intellisense",
    "vscode-icons-team.vscode-icons",
    "davidanson.vscode-markdownlint",
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    "mrmlnc.vscode-less",
    "lokalise.i18n-ally",
    "redhat.vscode-yaml",
    "csstools.postcss",
    "mikestead.dotenv",
    "eamodio.gitlens",
    "antfu.iconify",
    "antfu.unocss",
    "Vue.volar"
  ]
}
.vscode/launch.json
New file
@@ -0,0 +1,16 @@
{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "msedge",
      "request": "launch",
      "name": "Launch Edge against localhost",
      "url": "http://localhost",
      "webRoot": "${workspaceFolder}/src",
      "sourceMaps": true
    }
  ]
}
.vscode/settings.json
New file
@@ -0,0 +1,146 @@
{
  "typescript.tsdk": "node_modules/typescript/lib",
  "npm.packageManager": "pnpm",
  "editor.tabSize": 2,
  "prettier.printWidth": 100, // è¶…过最大值换行
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "files.eol": "\n",
  "search.exclude": {
    "**/node_modules": true,
    "**/*.log": true,
    "**/*.log*": true,
    "**/bower_components": true,
    "**/dist": true,
    "**/elehukouben": true,
    "**/.git": true,
    "**/.gitignore": true,
    "**/.svn": true,
    "**/.DS_Store": true,
    "**/.idea": true,
    "**/.vscode": false,
    "**/yarn.lock": true,
    "**/tmp": true,
    "out": true,
    "dist": true,
    "node_modules": true,
    "CHANGELOG.md": true,
    "examples": true,
    "res": true,
    "screenshots": true,
    "yarn-error.log": true,
    "**/.yarn": true
  },
  "files.exclude": {
    "**/.cache": true,
    "**/.editorconfig": true,
    "**/.eslintcache": true,
    "**/bower_components": true,
    "**/.idea": true,
    "**/tmp": true,
    "**/.git": true,
    "**/.svn": true,
    "**/.hg": true,
    "**/CVS": true,
    "**/.DS_Store": true
  },
  "files.watcherExclude": {
    "**/.git/objects/**": true,
    "**/.git/subtree-cache/**": true,
    "**/.vscode/**": true,
    "**/node_modules/**": true,
    "**/tmp/**": true,
    "**/bower_components/**": true,
    "**/dist/**": true,
    "**/yarn.lock": true
  },
  "stylelint.enable": true,
  "stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
  "path-intellisense.mappings": {
    "@/": "${workspaceRoot}/src"
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[html]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[less]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[scss]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[markdown]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.fixAll.stylelint": "explicit"
  },
  "editor.formatOnSave": true,
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "i18n-ally.localesPaths": ["src/locales"],
  "i18n-ally.keystyle": "nested",
  "i18n-ally.sortKeys": true,
  "i18n-ally.namespace": false,
  "i18n-ally.enabledParsers": ["ts"],
  "i18n-ally.sourceLanguage": "en",
  "i18n-ally.displayLanguage": "zh-CN",
  "i18n-ally.enabledFrameworks": ["vue", "react"],
  "cSpell.words": [
    "brotli",
    "browserslist",
    "codemirror",
    "commitlint",
    "cropperjs",
    "echart",
    "echarts",
    "esnext",
    "esno",
    "iconify",
    "INTLIFY",
    "lintstagedrc",
    "logicflow",
    "nprogress",
    "pinia",
    "pnpm",
    "qrcode",
    "sider",
    "sortablejs",
    "stylelint",
    "svgs",
    "unocss",
    "unplugin",
    "unref",
    "videojs",
    "VITE",
    "vitejs",
    "vueuse",
    "wangeditor",
    "xingyu",
    "yudao",
    "zxcvbn"
  ],
  // æŽ§åˆ¶ç›¸å…³æ–‡ä»¶åµŒå¥—展示
  "explorer.fileNesting.enabled": true,
  "explorer.fileNesting.expand": false,
  "explorer.fileNesting.patterns": {
    "*.ts": "$(capture).test.ts, $(capture).test.tsx",
    "*.tsx": "$(capture).test.ts, $(capture).test.tsx",
    "*.env": "$(capture).env.*",
    "package.json": "pnpm-lock.yaml,yarn.lock,LICENSE,README*,CHANGELOG*,CNAME,.gitattributes,.eslintrc-auto-import.json,.gitignore,prettier.config.js,stylelint.config.js,commitlint.config.js,.stylelintignore,.prettierignore,.gitpod.yml,.eslintrc.js,.eslintignore"
  },
  "terminal.integrated.scrollback": 10000,
  "nuxt.isNuxtApp": false
}
LICENSE
New file
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-present Archer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
README.md
@@ -1,4 +1,295 @@
## app-web-examination-yudao
**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!!**
**「我喜欢写代码,乐此不疲」**
**「我喜欢做开源,以此为乐」**
我 ðŸ¶ åœ¨ä¸Šæµ·è‰°è‹¦å¥‹æ–—,早中晚在 top3 å¤§åŽ‚è®¤çœŸæ¬ç –ï¼Œå¤œé‡Œä¸ºå¼€æºåšè´¡çŒ®ã€‚
如果这个项目让你有所收获,记得 Star å…³æ³¨å“¦ï¼Œè¿™å¯¹æˆ‘是非常不错的鼓励与支持。
## ðŸ¶ æ–°æ‰‹å¿…读
* nodejs > 16.18.0 && pnpm > 8.6.0 (强制使用pnpm)
* æ¼”示地址【Vue3 + element-plus】:<http://dashboard-vue3.yudao.iocoder.cn>
* æ¼”示地址【Vue3 + vben5.0(ant-design-vue)】:<http://dashboard-vben.yudao.iocoder.cn>
* æ¼”示地址【Vue2 + element-ui】:<http://dashboard.yudao.iocoder.cn>
* å¯åŠ¨æ–‡æ¡£ï¼š<https://doc.iocoder.cn/quick-start/>
* è§†é¢‘教程:<https://doc.iocoder.cn/video/>
## ðŸ¯ å¹³å°ç®€ä»‹
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% å…è´¹ä½¿ç”¨ã€‚
* é‡‡ç”¨ [vue-element-plus-admin](https://gitee.com/kailong110120130/vue-element-plus-admin) å®žçް
* æ”¹æ¢ saas,自动引入等功能
* ä½¿ç”¨ Element Plus å…è´¹å¼€æºçš„中后台模版,具备如下特性:
![首页](.image/demo/vue3-ep.png)
* **最新技术栈**:使用 Vue3、Vite4 ç­‰å‰ç«¯å‰æ²¿æŠ€æœ¯å¼€å‘
* **TypeScript**: åº”用程序级 JavaScript çš„语言
* **主题**: å¯é…ç½®çš„主题
* **国际化**:内置完善的国际化方案
* **权限**:内置完善的动态路由权限生成方案
* **组件**:二次封装了多个常用的组件
* **示例**:内置丰富的示例
## æŠ€æœ¯æ ˆ
| æ¡†æž¶                                                                   | è¯´æ˜Ž               | ç‰ˆæœ¬     |
|----------------------------------------------------------------------|------------------|--------|
| [Vue](https://staging-cn.vuejs.org/)                                 | Vue æ¡†æž¶           | 3.3.8  |
| [Vite](https://cn.vitejs.dev//)                                      | å¼€å‘与构建工具          | 4.5.0  |
| [Element Plus](https://element-plus.org/zh-CN/)                      | Element Plus     | 2.4.2  |
| [TypeScript](https://www.typescriptlang.org/docs/)                   | JavaScript çš„超集   | 5.2.2  |
| [pinia](https://pinia.vuejs.org/)                                    | Vue å­˜å‚¨åº“ æ›¿ä»£ vuex5 | 2.1.7  |
| [vueuse](https://vueuse.org/)                                        | å¸¸ç”¨å·¥å…·é›†            | 10.6.1 |
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | å›½é™…化              | 9.6.5  |
| [vue-router](https://router.vuejs.org/)                              | Vue è·¯ç”±           | 4.2.5  |
| [unocss](https://uno.antfu.me/)                                      | åŽŸå­ css           | 0.57.4 |
| [iconify](https://icon-sets.iconify.design/)                         | åœ¨çº¿å›¾æ ‡åº“            | 3.1.1  |
| [wangeditor](https://www.wangeditor.com/)                            | å¯Œæ–‡æœ¬ç¼–辑器           | 5.1.23 |
## å¼€å‘工具
推荐 VS Code å¼€å‘,配合插件如下:
| æ’件名                           | åŠŸèƒ½                  |
|-------------------------------|---------------------|
| Vue - Official                | Vue ä¸Ž TypeScript æ”¯æŒ |
| unocss                        | unocss for vscode   |
| Iconify IntelliSense          | Iconify é¢„览和搜索       |
| i18n Ally                     | å›½é™…化智能提示             |
| Stylelint                     | Css    æ ¼å¼åŒ–          |
| Prettier                      | ä»£ç æ ¼å¼åŒ–               |
| ESLint                        | è„šæœ¬ä»£ç æ£€æŸ¥              |
| DotENV                        | env æ–‡ä»¶é«˜äº®            |
## ðŸ”¥ åŽç«¯æž¶æž„
支持 Spring Boot、Spring Cloud ä¸¤ç§æž¶æž„:
① Spring Boot å•体架构:<https://doc.iocoder.cn>
![架构图](/.image/common/ruoyi-vue-pro-architecture.png)
② Spring Cloud å¾®æœåŠ¡æž¶æž„ï¼š<https://cloud.iocoder.cn>
![架构图](/.image/common/yudao-cloud-architecture.png)
## å†…置功能
系统内置多种多种业务功能,可以用于快速你的业务系统:
系统内置多种多种业务功能,可以用于快速你的业务系统:
![功能分层](/.image/common/ruoyi-vue-pro-biz.png)
* é€šç”¨æ¨¡å—(必选):系统功能、基础设施
* é€šç”¨æ¨¡å—(可选):工作流程、支付系统、数据报表、会员中心
* ä¸šåŠ¡ç³»ç»Ÿï¼ˆæŒ‰éœ€ï¼‰ï¼šERP ç³»ç»Ÿã€CRM ç³»ç»Ÿã€å•†åŸŽç³»ç»Ÿã€å¾®ä¿¡å…¬ä¼—号、AI å¤§æ¨¡åž‹
### ç³»ç»ŸåŠŸèƒ½
|     | åŠŸèƒ½    | æè¿°                              |
|-----|-------|---------------------------------|
|     | ç”¨æˆ·ç®¡ç†  | ç”¨æˆ·æ˜¯ç³»ç»Ÿæ“ä½œè€…,该功能主要完成系统用户配置          |
| â­ï¸  | åœ¨çº¿ç”¨æˆ·  | å½“前系统中活跃用户状态监控,支持手动踢下线           |
|     | è§’色管理  | è§’色菜单权限分配、设置角色按机构进行数据范围权限划分      |
|     | èœå•管理  | é…ç½®ç³»ç»Ÿèœå•、操作权限、按钮权限标识等,本地缓存提供性能    |
|     | éƒ¨é—¨ç®¡ç†  | é…ç½®ç³»ç»Ÿç»„织机构(公司、部门、小组),树结构展现支持数据权限  |
|     | å²—位管理  | é…ç½®ç³»ç»Ÿç”¨æˆ·æ‰€å±žæ‹…任职务                    |
| ðŸš€  | ç§Ÿæˆ·ç®¡ç†  | é…ç½®ç³»ç»Ÿç§Ÿæˆ·ï¼Œæ”¯æŒ SaaS åœºæ™¯ä¸‹çš„多租户功能        |
| ðŸš€  | ç§Ÿæˆ·å¥—餐  | é…ç½®ç§Ÿæˆ·å¥—餐,自定每个租户的菜单、操作、按钮的权限       |
|     | å­—典管理  | å¯¹ç³»ç»Ÿä¸­ç»å¸¸ä½¿ç”¨çš„一些较为固定的数据进行维护          |
| ðŸš€  | çŸ­ä¿¡ç®¡ç†  | çŸ­ä¿¡æ¸ é“、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 |
| ðŸš€  | é‚®ä»¶ç®¡ç†  | é‚®ç®±è´¦å·ã€é‚®ä»¶æ¨¡ç‰ˆã€é‚®ä»¶å‘送日志,支持所有邮件平台       |
| ðŸš€  | ç«™å†…ä¿¡   | ç³»ç»Ÿå†…的消息通知,提供站内信模版、站内信消息          |
| ðŸš€  | æ“ä½œæ—¥å¿—  | ç³»ç»Ÿæ­£å¸¸æ“ä½œæ—¥å¿—记录和查询,集成 Swagger ç”Ÿæˆæ—¥å¿—内容 |
| â­ï¸  | ç™»å½•日志  | ç³»ç»Ÿç™»å½•日志记录查询,包含登录异常               |
| ðŸš€  | é”™è¯¯ç ç®¡ç† | ç³»ç»Ÿæ‰€æœ‰é”™è¯¯ç çš„管理,可在线修改错误提示,无需重启服务     |
|     | é€šçŸ¥å…¬å‘Š  | ç³»ç»Ÿé€šçŸ¥å…¬å‘Šä¿¡æ¯å‘布维护                    |
| ðŸš€  | æ•æ„Ÿè¯   | é…ç½®ç³»ç»Ÿæ•æ„Ÿè¯ï¼Œæ”¯æŒæ ‡ç­¾åˆ†ç»„                  |
| ðŸš€  | åº”用管理  | ç®¡ç† SSO å•点登录的应用,支持多种 OAuth2 æŽˆæƒæ–¹å¼ |
| ðŸš€  | åœ°åŒºç®¡ç†  | å±•示省份、城市、区镇等城市信息,支持 IP å¯¹åº”城市      |
![功能图](/.image/common/system-feature.png)
### å·¥ä½œæµç¨‹
![功能图](/.image/common/bpm-feature.png)
基于 Flowable æž„建,可支持信创(国产)数据库,满足中国特色流程操作:
| BPMN è®¾è®¡å™¨                    | é’‰é’‰/飞书设计器                      |
|-----------------------------|-------------------------------|
| ![](.image/工作流设计器-bpmn.jpg) | ![](.image/工作流设计器-simple.jpg) |
> åŽ†ç»å¤´éƒ¨ä¼ä¸šç”Ÿäº§éªŒè¯ï¼Œå·¥ä½œæµå¼•æ“Žé¡»æ ‡é…ä»¿é’‰é’‰/飞书 + BPMN åŒè®¾è®¡å™¨ï¼ï¼ï¼
>
> å‰è€…支持轻量配置简单流程,后者实现复杂场景深度编排
| åŠŸèƒ½åˆ—è¡¨       | åŠŸèƒ½æè¿°                                                                                | æ˜¯å¦å®Œæˆ |
|------------|-------------------------------------------------------------------------------------|------|
| SIMPLE è®¾è®¡å™¨ | ä»¿é’‰é’‰/飞书设计器,支持拖拽搭建表单流程,10 åˆ†é’Ÿå¿«é€Ÿå®Œæˆå®¡æ‰¹æµç¨‹é…ç½®                                                | âœ…    |
| BPMN è®¾è®¡å™¨   | åŸºäºŽ BPMN æ ‡å‡†å¼€å‘,适配复杂业务场景,满足多层级审批及流程自动化需求                                               | âœ…    |
| ä¼šç­¾         | åŒä¸€ä¸ªå®¡æ‰¹èŠ‚ç‚¹è®¾ç½®å¤šä¸ªäººï¼ˆå¦‚ A、B、C ä¸‰äººï¼Œä¸‰äººä¼šåŒæ—¶æ”¶åˆ°å¾…办任务),需全部同意之后,审批才可到下一审批节点                            | âœ…    |
| æˆ–ç­¾         | åŒä¸€ä¸ªå®¡æ‰¹èŠ‚ç‚¹è®¾ç½®å¤šä¸ªäººï¼Œä»»æ„ä¸€ä¸ªäººå¤„ç†åŽï¼Œå°±èƒ½è¿›å…¥ä¸‹ä¸€ä¸ªèŠ‚ç‚¹                                                     | âœ…    |
| ä¾æ¬¡å®¡æ‰¹       | ï¼ˆé¡ºåºä¼šç­¾ï¼‰åŒä¸€ä¸ªå®¡æ‰¹èŠ‚ç‚¹è®¾ç½®å¤šä¸ªäººï¼ˆå¦‚ A、B、C ä¸‰äººï¼‰ï¼Œä¸‰äººæŒ‰é¡ºåºä¾æ¬¡æ”¶åˆ°å¾…办,即 A å…ˆå®¡æ‰¹ï¼ŒA æäº¤åŽ B æ‰èƒ½å®¡æ‰¹ï¼Œéœ€å…¨éƒ¨åŒæ„ä¹‹åŽï¼Œå®¡æ‰¹æ‰å¯åˆ°ä¸‹ä¸€å®¡æ‰¹èŠ‚ç‚¹ | âœ…    |
| æŠ„送         | å°†å®¡æ‰¹ç»“果通知给抄送人,同一个审批默认排重,不重复抄送给同一人                                                     | âœ…    |
| é©³å›ž         | ï¼ˆé€€å›žï¼‰å°†å®¡æ‰¹é‡ç½®å‘送给某节点,重新审批。可驳回至发起人、上一节点、任意节点                                              | âœ…    |
| è½¬åŠž         | A è½¬ç»™å…¶ B å®¡æ‰¹ï¼ŒB å®¡æ‰¹åŽï¼Œè¿›å…¥ä¸‹ä¸€èŠ‚ç‚¹                                                             | âœ…    |
| å§”æ´¾         | A è½¬ç»™å…¶ B å®¡æ‰¹ï¼ŒB å®¡æ‰¹åŽï¼Œè½¬ç»™ A,A ç»§ç»­å®¡æ‰¹åŽè¿›å…¥ä¸‹ä¸€èŠ‚ç‚¹                                                 | âœ…    |
| åŠ ç­¾         | å…è®¸å½“前审批人根据需要,自行增加当前节点的审批人,支持向前、向后加签                                                  | âœ…    |
| å‡ç­¾         | ï¼ˆå–消加签)在当前审批人操作之前,减少审批人                                                              | âœ…    |
| æ’¤é”€         | ï¼ˆå–消流程)流程发起人,可以对流程进行撤销处理                                                             | âœ…    |
| ç»ˆæ­¢         | ç³»ç»Ÿç®¡ç†å‘˜ï¼Œåœ¨ä»»æ„èŠ‚ç‚¹ç»ˆæ­¢æµç¨‹å®žä¾‹                                                                   | âœ…    |
| è¡¨å•权限       | æ”¯æŒæ‹–拉拽配置表单,每个审批节点可配置只读、编辑、隐藏权限                                                       | âœ…    |
| è¶…时审批       | é…ç½®è¶…时审批时间,超时后自动触发审批通过、不通过、驳回等操作                                                      | âœ…    |
| è‡ªåŠ¨æé†’       | é…ç½®æé†’时间,到达时间后自动触发短信、邮箱、站内信等通知提醒,支持自定义重复提醒频次                                          | âœ…    |
| çˆ¶å­æµç¨‹       | ä¸»æµç¨‹è®¾ç½®å­æµç¨‹èŠ‚ç‚¹ï¼Œå­æµç¨‹èŠ‚ç‚¹ä¼šè‡ªåŠ¨è§¦å‘å­æµç¨‹ã€‚å­æµç¨‹ç»“æŸåŽï¼Œä¸»æµç¨‹æ‰ä¼šæ‰§è¡Œï¼ˆç»§ç»­å¾€ä¸‹ä¸‹æ‰§è¡Œï¼‰ï¼Œæ”¯æŒåŒæ­¥å­æµç¨‹ã€å¼‚æ­¥å­æµç¨‹                      | âœ…    |
| æ¡ä»¶åˆ†æ”¯       | ï¼ˆæŽ’它分支)用于在流程中实现决策,即根据条件选择一个分支执行                                                      | âœ…    |
| å¹¶è¡Œåˆ†æ”¯       | å…è®¸å°†æµç¨‹åˆ†æˆå¤šæ¡åˆ†æ”¯ï¼Œä¸è¿›è¡Œæ¡ä»¶åˆ¤æ–­ï¼Œæ‰€æœ‰åˆ†æ”¯éƒ½ä¼šæ‰§è¡Œ                                                        | âœ…    |
| åŒ…容分支       | ï¼ˆæ¡ä»¶åˆ†æ”¯ + å¹¶è¡Œåˆ†æ”¯çš„结合体)允许基于条件选择多条分支执行,但如果没有任何一个分支满足条件,则可以选择默认分支                           | âœ…    |
| è·¯ç”±åˆ†æ”¯       | æ ¹æ®æ¡ä»¶é€‰æ‹©ä¸€ä¸ªåˆ†æ”¯æ‰§è¡Œï¼ˆé‡å®šå‘到指定配置节点),也可以选择默认分支执行(继续往下执行)                                        | âœ…    |
| è§¦å‘节点       | æ‰§è¡Œåˆ°è¯¥èŠ‚ç‚¹ï¼Œè§¦å‘ HTTP è¯·æ±‚、HTTP å›žè°ƒã€æ›´æ–°æ•°æ®ã€åˆ é™¤æ•°æ®ç­‰                                                | âœ…    |
| å»¶è¿ŸèŠ‚ç‚¹       | æ‰§è¡Œåˆ°è¯¥èŠ‚ç‚¹ï¼Œå®¡æ‰¹ç­‰å¾…ä¸€æ®µæ—¶é—´å†æ‰§è¡Œï¼Œæ”¯æŒå›ºå®šæ—¶é•¿ã€å›ºå®šæ—¥æœŸç­‰                                                     | âœ…    |
| æ‹“展设置       | æµç¨‹å‰ç½®/后置通知,节点(任务)前置、后置通知,流程报表,自动审批去重,自定流程编号、标题、摘要,流程报表等                              | âœ…    |
### æ”¯ä»˜ç³»ç»Ÿ
|     | åŠŸèƒ½   | æè¿°                        |
|-----|------|---------------------------|
| ðŸš€  | åº”用信息 | é…ç½®å•†æˆ·çš„应用信息,对接支付宝、微信等多个支付渠道 |
| ðŸš€  | æ”¯ä»˜è®¢å• | æŸ¥çœ‹ç”¨æˆ·å‘起的支付宝、微信等的【支付】订单     |
| ðŸš€  | é€€æ¬¾è®¢å• | æŸ¥çœ‹ç”¨æˆ·å‘起的支付宝、微信等的【退款】订单     |
| ðŸš€  | å›žè°ƒé€šçŸ¥ | æŸ¥çœ‹æ”¯ä»˜å›žè°ƒä¸šåŠ¡çš„ã€æ”¯ä»˜ã€‘ã€é€€æ¬¾ã€‘çš„é€šçŸ¥ç»“æžœ    |
| ðŸš€  | æŽ¥å…¥ç¤ºä¾‹ | æä¾›æŽ¥å…¥æ”¯ä»˜ç³»ç»Ÿçš„【支付】【退款】的功能实战    |
### åŸºç¡€è®¾æ–½
|     | åŠŸèƒ½        | æè¿°                                           |
|-----|-----------|----------------------------------------------|
| ðŸš€  | ä»£ç ç”Ÿæˆ      | å‰åŽç«¯ä»£ç çš„生成(Java、Vue、SQL、单元测试),支持 CRUD ä¸‹è½½       |
| ðŸš€  | ç³»ç»ŸæŽ¥å£      | åŸºäºŽ Swagger è‡ªåŠ¨ç”Ÿæˆç›¸å…³çš„ RESTful API æŽ¥å£æ–‡æ¡£          |
| ðŸš€  | æ•°æ®åº“文档     | åŸºäºŽ Screw è‡ªåŠ¨ç”Ÿæˆæ•°æ®åº“æ–‡æ¡£ï¼Œæ”¯æŒå¯¼å‡º Word、HTML、MD æ ¼å¼      |
|     | è¡¨å•构建      | æ‹–动表单元素生成相应的 HTML ä»£ç ï¼Œæ”¯æŒå¯¼å‡º JSON、Vue æ–‡ä»¶         |
| ðŸš€  | é…ç½®ç®¡ç†      | å¯¹ç³»ç»ŸåŠ¨æ€é…ç½®å¸¸ç”¨å‚æ•°ï¼Œæ”¯æŒ SpringBoot åŠ è½½                 |
| â­ï¸  | å®šæ—¶ä»»åŠ¡      | åœ¨çº¿ï¼ˆæ·»åŠ ã€ä¿®æ”¹ã€åˆ é™¤)任务调度包含执行结果日志                     |
| ðŸš€  | æ–‡ä»¶æœåŠ¡      | æ”¯æŒå°†æ–‡ä»¶å­˜å‚¨åˆ° S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等   |
| ðŸš€  | WebSocket | æä¾› WebSocket æŽ¥å…¥ç¤ºä¾‹ï¼Œæ”¯æŒä¸€å¯¹ä¸€ã€ä¸€å¯¹å¤šå‘送方式              |
| ðŸš€  | API æ—¥å¿—    | åŒ…括 RESTful API è®¿é—®æ—¥å¿—、异常日志两部分,方便排查 API ç›¸å…³çš„问题   |
|     | MySQL ç›‘控  | ç›‘视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈              |
|     | Redis ç›‘控  | ç›‘控 Redis æ•°æ®åº“的使用情况,使用的 Redis Key ç®¡ç†           |
| ðŸš€  | æ¶ˆæ¯é˜Ÿåˆ—      | åŸºäºŽ Redis å®žçŽ°æ¶ˆæ¯é˜Ÿåˆ—ï¼ŒStream æä¾›é›†ç¾¤æ¶ˆè´¹ï¼ŒPub/Sub æä¾›å¹¿æ’­æ¶ˆè´¹ |
| ðŸš€  | Java ç›‘控   | åŸºäºŽ Spring Boot Admin å®žçް Java åº”用的监控           |
| ðŸš€  | é“¾è·¯è¿½è¸ª      | æŽ¥å…¥ SkyWalking ç»„件,实现链路追踪                      |
| ðŸš€  | æ—¥å¿—中心      | æŽ¥å…¥ SkyWalking ç»„件,实现日志中心                      |
| ðŸš€  | æœåŠ¡ä¿éšœ      | åŸºäºŽ Redis å®žçŽ°åˆ†å¸ƒå¼é”ã€å¹‚ç­‰ã€é™æµåŠŸèƒ½ï¼Œæ»¡è¶³é«˜å¹¶å‘åœºæ™¯              |
| ðŸš€  | æ—¥å¿—服务      | è½»é‡çº§æ—¥å¿—中心,查看远程服务器的日志                           |
| ðŸš€  | å•元测试      | åŸºäºŽ JUnit + Mockito å®žçŽ°å•å…ƒæµ‹è¯•ï¼Œä¿è¯åŠŸèƒ½çš„æ­£ç¡®æ€§ã€ä»£ç çš„è´¨é‡ç­‰    |
![功能图](/.image/common/infra-feature.png)
### æ•°æ®æŠ¥è¡¨
|     | åŠŸèƒ½    | æè¿°                 |
|-----|-------|--------------------|
| ðŸš€  | æŠ¥è¡¨è®¾è®¡å™¨ | æ”¯æŒæ•°æ®æŠ¥è¡¨ã€å›¾å½¢æŠ¥è¡¨ã€æ‰“印设计等  |
| ðŸš€  | å¤§å±è®¾è®¡å™¨ | æ‹–拽生成数据大屏,内置几十种图表组件 |
### å¾®ä¿¡å…¬ä¼—号
|    | åŠŸèƒ½     | æè¿°                            |
|----|--------|-------------------------------|
| ðŸš€ | è´¦å·ç®¡ç†   | é…ç½®æŽ¥å…¥çš„微信公众号,可支持多个公众号           |
| ðŸš€ | æ•°æ®ç»Ÿè®¡   | ç»Ÿè®¡å…¬ä¼—号的用户增减、累计用户、消息概况、接口分析等数据  |
| ðŸš€ | ç²‰ä¸ç®¡ç†   | æŸ¥çœ‹å·²å…³æ³¨ã€å–关的粉丝列表,可对粉丝进行同步、打标签等操作 |
| ðŸš€ | æ¶ˆæ¯ç®¡ç†   | æŸ¥çœ‹ç²‰ä¸å‘送的消息列表,可主动回复粉丝消息         |
| ðŸš€ | æ¨¡ç‰ˆæ¶ˆæ¯   | é…ç½®å’Œå‘送模版消息,用于向粉丝推送通知类消息        |
| ðŸš€ | è‡ªåŠ¨å›žå¤   | è‡ªåŠ¨å›žå¤ç²‰ä¸å‘é€çš„æ¶ˆæ¯ï¼Œæ”¯æŒå…³æ³¨å›žå¤ã€æ¶ˆæ¯å›žå¤ã€å…³é”®å­—å›žå¤ |
| ðŸš€ | æ ‡ç­¾ç®¡ç†   | å¯¹å…¬ä¼—号的标签进行创建、查询、修改、删除等操作       |
| ðŸš€ | èœå•管理   | è‡ªå®šä¹‰å…¬ä¼—号的菜单,也可以从公众号同步菜单         |
| ðŸš€ | ç´ æç®¡ç†   | ç®¡ç†å…¬ä¼—号的图片、语音、视频等素材,支持在线播放语音、视频 |
| ðŸš€ | å›¾æ–‡è‰ç¨¿ç®±  | æ–°å¢žå¸¸ç”¨çš„图文素材到草稿箱,可发布到公众号         |
| ðŸš€ | å›¾æ–‡å‘表记录 | æŸ¥çœ‹å·²å‘布成功的图文素材,支持删除操作           |
### å•†åŸŽç³»ç»Ÿ
演示地址:<https://doc.iocoder.cn/mall-preview/>
![功能图](/.image/common/mall-feature.png)
![功能图](/.image/common/mall-preview.png)
### ERP ç³»ç»Ÿ
演示地址:<https://doc.iocoder.cn/erp-preview/>
![功能图](/.image/common/erp-feature.png)
### CRM ç³»ç»Ÿ
演示地址:<https://doc.iocoder.cn/crm-preview/>
![功能图](/.image/common/crm-feature.png)
### AI å¤§æ¨¡åž‹
演示地址:<https://doc.iocoder.cn/ai-preview/>
![功能图](/.image/common/ai-feature.png)
![功能图](/.image/common/ai-preview.gif)
## ðŸ· æ¼”示图
### ç³»ç»ŸåŠŸèƒ½
| æ¨¡å—       | biu                         | biu                       | biu                      |
|----------|-----------------------------|---------------------------|--------------------------|
| ç™»å½• & é¦–页  | ![登录](/.image/登录.jpg)       | ![首页](/.image/首页.jpg)     | ![个人中心](/.image/个人中心.jpg) |
| ç”¨æˆ· & åº”用  | ![用户管理](/.image/用户管理.jpg)   | ![令牌管理](/.image/令牌管理.jpg) | ![应用管理](/.image/应用管理.jpg) |
| ç§Ÿæˆ· & å¥—餐  | ![租户管理](/.image/租户管理.jpg)   | ![租户套餐](/.image/租户套餐.png) | -                        |
| éƒ¨é—¨ & å²—位  | ![部门管理](/.image/部门管理.jpg)   | ![岗位管理](/.image/岗位管理.jpg) | -                        |
| èœå• & è§’色  | ![菜单管理](/.image/菜单管理.jpg)   | ![角色管理](/.image/角色管理.jpg) | -                        |
| å®¡è®¡æ—¥å¿—     | ![操作日志](/.image/操作日志.jpg)   | ![登录日志](/.image/登录日志.jpg) | -                        |
| çŸ­ä¿¡       | ![短信渠道](/.image/短信渠道.jpg)   | ![短信模板](/.image/短信模板.jpg) | ![短信日志](/.image/短信日志.jpg) |
| å­—å…¸ & æ•æ„Ÿè¯ | ![字典类型](/.image/字典类型.jpg)   | ![字典数据](/.image/字典数据.jpg) | ![敏感词](/.image/敏感词.jpg)  |
| é”™è¯¯ç  & é€šçŸ¥ | ![错误码管理](/.image/错误码管理.jpg) | ![通知公告](/.image/通知公告.jpg) | -                        |
### å·¥ä½œæµç¨‹
| æ¨¡å—      | biu                             | biu                             | biu                             |
|---------|---------------------------------|---------------------------------|---------------------------------|
| æµç¨‹æ¨¡åž‹    | ![流程模型-列表](/.image/流程模型-列表.jpg) | ![流程模型-设计](/.image/流程模型-设计.jpg) | ![流程模型-定义](/.image/流程模型-定义.jpg) |
| è¡¨å• & åˆ†ç»„ | ![流程表单](/.image/流程表单.jpg)       | ![用户分组](/.image/用户分组.jpg)       | -                               |
| æˆ‘的流程    | ![我的流程-列表](/.image/我的流程-列表.jpg) | ![我的流程-发起](/.image/我的流程-发起.jpg) | ![我的流程-详情](/.image/我的流程-详情.jpg) |
| å¾…办 & å·²åŠž | ![任务列表-审批](/.image/任务列表-审批.jpg) | ![任务列表-待办](/.image/任务列表-待办.jpg) | ![任务列表-已办](/.image/任务列表-已办.jpg) |
| OA è¯·å‡   | ![OA请假-列表](/.image/OA请假-列表.jpg) | ![OA请假-发起](/.image/OA请假-发起.jpg) | ![OA请假-详情](/.image/OA请假-详情.jpg) |
### åŸºç¡€è®¾æ–½
| æ¨¡å—            | biu                           | biu                         | biu                       |
|---------------|-------------------------------|-----------------------------|---------------------------|
| ä»£ç ç”Ÿæˆ          | ![代码生成](/.image/代码生成.jpg)     | ![生成效果](/.image/生成效果.jpg)   | -                         |
| æ–‡æ¡£            | ![系统接口](/.image/系统接口.jpg)     | ![数据库文档](/.image/数据库文档.jpg) | -                         |
| æ–‡ä»¶ & é…ç½®       | ![文件配置](/.image/文件配置.jpg)     | ![文件管理](/.image/文件管理2.jpg)  | ![配置管理](/.image/配置管理.jpg) |
| å®šæ—¶ä»»åŠ¡          | ![定时任务](/.image/定时任务.jpg)     | ![任务日志](/.image/任务日志.jpg)   | -                         |
| API æ—¥å¿—        | ![访问日志](/.image/访问日志.jpg)     | ![错误日志](/.image/错误日志.jpg)   | -                         |
| MySQL & Redis | ![MySQL](/.image/MySQL.jpg)   | ![Redis](/.image/Redis.jpg) | -                         |
| ç›‘控平台          | ![Java监控](/.image/Java监控.jpg) | ![链路追踪](/.image/链路追踪.jpg)   | ![日志中心](/.image/日志中心.jpg) |
### æ”¯ä»˜ç³»ç»Ÿ
| æ¨¡å—      | biu                       | biu                             | biu                             |
|---------|---------------------------|---------------------------------|---------------------------------|
| å•†å®¶ & åº”用 | ![商户信息](/.image/商户信息.jpg) | ![应用信息-列表](/.image/应用信息-列表.jpg) | ![应用信息-编辑](/.image/应用信息-编辑.jpg) |
| æ”¯ä»˜ & é€€æ¬¾ | ![支付订单](/.image/支付订单.jpg) | ![退款订单](/.image/退款订单.jpg)       | ---                             |
### æ•°æ®æŠ¥è¡¨
| æ¨¡å—    | biu                             | biu                             | biu                                   |
|-------|---------------------------------|---------------------------------|---------------------------------------|
| æŠ¥è¡¨è®¾è®¡å™¨ | ![数据报表](/.image/报表设计器-数据报表.jpg) | ![图形报表](/.image/报表设计器-图形报表.jpg) | ![报表设计器-打印设计](/.image/报表设计器-打印设计.jpg) |
| å¤§å±è®¾è®¡å™¨ | ![大屏列表](/.image/大屏设计器-列表.jpg)   | ![大屏预览](/.image/大屏设计器-预览.jpg)   | ![大屏编辑](/.image/大屏设计器-编辑.jpg)         |
build/vite/index.ts
New file
@@ -0,0 +1,99 @@
import { resolve } from 'path'
import Vue from '@vitejs/plugin-vue'
import VueJsx from '@vitejs/plugin-vue-jsx'
import progress from 'vite-plugin-progress'
import EslintPlugin from 'vite-plugin-eslint'
import PurgeIcons from 'vite-plugin-purge-icons'
import { ViteEjsPlugin } from 'vite-plugin-ejs'
// @ts-ignore
import ElementPlus from 'unplugin-element-plus/vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import viteCompression from 'vite-plugin-compression'
import topLevelAwait from 'vite-plugin-top-level-await'
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons-ng'
import UnoCSS from 'unocss/vite'
export function createVitePlugins() {
  const root = process.cwd()
  // è·¯å¾„查找
  function pathResolve(dir: string) {
    return resolve(root, '.', dir)
  }
  return [
    Vue(),
    VueJsx(),
    UnoCSS(),
    progress(),
    PurgeIcons(),
    ElementPlus({}),
    AutoImport({
      include: [
        /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
        /\.vue$/,
        /\.vue\?vue/, // .vue
        /\.md$/ // .md
      ],
      imports: [
        'vue',
        'vue-router',
        // å¯é¢å¤–添加需要 autoImport çš„组件
        {
          '@/hooks/web/useI18n': ['useI18n'],
          '@/hooks/web/useMessage': ['useMessage'],
          '@/hooks/web/useTable': ['useTable'],
          '@/hooks/web/useCrudSchemas': ['useCrudSchemas'],
          '@/utils/formRules': ['required'],
          '@/utils/dict': ['DICT_TYPE']
        }
      ],
      dts: 'src/types/auto-imports.d.ts',
      resolvers: [ElementPlusResolver()],
      eslintrc: {
        enabled: false, // Default `false`
        filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
        globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
      }
    }),
    Components({
      // ç”Ÿæˆè‡ªå®šä¹‰ `auto-components.d.ts` å…¨å±€å£°æ˜Ž
      dts: 'src/types/auto-components.d.ts',
      // è‡ªå®šä¹‰ç»„件的解析器
      resolvers: [ElementPlusResolver()],
      globs: ["src/components/**/**.{vue, md}", '!src/components/DiyEditor/components/mobile/**']
    }),
    EslintPlugin({
      cache: false,
      include: ['src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'] // æ£€æŸ¥çš„æ–‡ä»¶
    }),
    VueI18nPlugin({
      runtimeOnly: true,
      compositionOnly: true,
      include: [resolve(__dirname, 'src/locales/**')]
    }),
    createSvgIconsPlugin({
      iconDirs: [pathResolve('src/assets/svgs')],
      symbolId: 'icon-[dir]-[name]',
    }),
    viteCompression({
      verbose: true, // æ˜¯å¦åœ¨æŽ§åˆ¶å°è¾“出压缩结果
      disable: false, // æ˜¯å¦ç¦ç”¨
      threshold: 10240, // ä½“积大于 threshold æ‰ä¼šè¢«åŽ‹ç¼©,单位 b
      algorithm: 'gzip', // åŽ‹ç¼©ç®—æ³•,可选 [ 'gzip' , 'brotliCompress' ,'deflate' , 'deflateRaw']
      ext: '.gz', // ç”Ÿæˆçš„压缩包后缀
      deleteOriginFile: false //压缩后是否删除源文件
    }),
    ViteEjsPlugin(),
    topLevelAwait({
      // https://juejin.cn/post/7152191742513512485
      // The export name of top-level await promise for each chunk module
      promiseExportName: '__tla',
      // The function to generate import names of top-level await promise in each chunk module
      promiseImportName: (i) => `__tla_${i}`
    })
  ]
}
build/vite/optimize.ts
New file
@@ -0,0 +1,124 @@
const include = [
  'qs',
  'url',
  'vue',
  'sass',
  'mitt',
  'axios',
  'pinia',
  'dayjs',
  'qrcode',
  'unocss',
  'vue-router',
  'vue-types',
  'vue-i18n',
  'crypto-js',
  'cropperjs',
  'lodash-es',
  'nprogress',
  'web-storage-cache',
  '@iconify/iconify',
  '@vueuse/core',
  '@zxcvbn-ts/core',
  'echarts/core',
  'echarts/charts',
  'echarts/components',
  'echarts/renderers',
  'echarts-wordcloud',
  '@wangeditor-next/editor',
  '@wangeditor-next/editor-for-vue',
  '@microsoft/fetch-event-source',
  'markdown-it',
  'markmap-view',
  'markmap-lib',
  'markmap-toolbar',
  'highlight.js',
  'element-plus',
  'element-plus/es',
  'element-plus/es/locale/lang/zh-cn',
  'element-plus/es/locale/lang/en',
  'element-plus/es/components/avatar/style/css',
  'element-plus/es/components/space/style/css',
  'element-plus/es/components/backtop/style/css',
  'element-plus/es/components/form/style/css',
  'element-plus/es/components/radio-group/style/css',
  'element-plus/es/components/radio/style/css',
  'element-plus/es/components/checkbox/style/css',
  'element-plus/es/components/checkbox-group/style/css',
  'element-plus/es/components/switch/style/css',
  'element-plus/es/components/time-picker/style/css',
  'element-plus/es/components/date-picker/style/css',
  'element-plus/es/components/descriptions/style/css',
  'element-plus/es/components/descriptions-item/style/css',
  'element-plus/es/components/link/style/css',
  'element-plus/es/components/tooltip/style/css',
  'element-plus/es/components/drawer/style/css',
  'element-plus/es/components/dialog/style/css',
  'element-plus/es/components/checkbox-button/style/css',
  'element-plus/es/components/option-group/style/css',
  'element-plus/es/components/radio-button/style/css',
  'element-plus/es/components/cascader/style/css',
  'element-plus/es/components/color-picker/style/css',
  'element-plus/es/components/input-number/style/css',
  'element-plus/es/components/rate/style/css',
  'element-plus/es/components/select-v2/style/css',
  'element-plus/es/components/tree-select/style/css',
  'element-plus/es/components/slider/style/css',
  'element-plus/es/components/time-select/style/css',
  'element-plus/es/components/autocomplete/style/css',
  'element-plus/es/components/image-viewer/style/css',
  'element-plus/es/components/upload/style/css',
  'element-plus/es/components/col/style/css',
  'element-plus/es/components/form-item/style/css',
  'element-plus/es/components/alert/style/css',
  'element-plus/es/components/breadcrumb/style/css',
  'element-plus/es/components/select/style/css',
  'element-plus/es/components/input/style/css',
  'element-plus/es/components/breadcrumb-item/style/css',
  'element-plus/es/components/tag/style/css',
  'element-plus/es/components/pagination/style/css',
  'element-plus/es/components/table/style/css',
  'element-plus/es/components/table-v2/style/css',
  'element-plus/es/components/table-column/style/css',
  'element-plus/es/components/card/style/css',
  'element-plus/es/components/row/style/css',
  'element-plus/es/components/button/style/css',
  'element-plus/es/components/menu/style/css',
  'element-plus/es/components/sub-menu/style/css',
  'element-plus/es/components/menu-item/style/css',
  'element-plus/es/components/option/style/css',
  'element-plus/es/components/dropdown/style/css',
  'element-plus/es/components/dropdown-menu/style/css',
  'element-plus/es/components/dropdown-item/style/css',
  'element-plus/es/components/skeleton/style/css',
  'element-plus/es/components/skeleton/style/css',
  'element-plus/es/components/backtop/style/css',
  'element-plus/es/components/menu/style/css',
  'element-plus/es/components/sub-menu/style/css',
  'element-plus/es/components/menu-item/style/css',
  'element-plus/es/components/dropdown/style/css',
  'element-plus/es/components/tree/style/css',
  'element-plus/es/components/dropdown-menu/style/css',
  'element-plus/es/components/dropdown-item/style/css',
  'element-plus/es/components/badge/style/css',
  'element-plus/es/components/breadcrumb/style/css',
  'element-plus/es/components/breadcrumb-item/style/css',
  'element-plus/es/components/image/style/css',
  'element-plus/es/components/collapse-transition/style/css',
  'element-plus/es/components/timeline/style/css',
  'element-plus/es/components/timeline-item/style/css',
  'element-plus/es/components/collapse/style/css',
  'element-plus/es/components/collapse-item/style/css',
  'element-plus/es/components/button-group/style/css',
  'element-plus/es/components/text/style/css',
  'element-plus/es/components/segmented/style/css',
  '@element-plus/icons-vue',
  'element-plus/es/components/footer/style/css',
  'element-plus/es/components/empty/style/css',
  'element-plus/es/components/mention/style/css',
  'element-plus/es/components/progress/style/css'
]
const exclude = ['@iconify/json']
export { include, exclude }
index.html
New file
@@ -0,0 +1,151 @@
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta
      name="keywords"
      content="芋道管理系统 åŸºäºŽ vue3 + CompositionAPI + typescript + vite3 + element plus çš„后台开源免费管理系统!"
    />
    <meta
      name="description"
      content="芋道管理系统 åŸºäºŽ vue3 + CompositionAPI + typescript + vite3 + element plus çš„后台开源免费管理系统!"
    />
    <title>%VITE_APP_TITLE%</title>
  </head>
  <body>
    <div id="app">
      <style>
        .app-loading {
          display: flex;
          width: 100%;
          height: 100%;
          justify-content: center;
          align-items: center;
          flex-direction: column;
          background: #f0f2f5;
        }
        .app-loading .app-loading-wrap {
          position: absolute;
          top: 50%;
          left: 50%;
          display: flex;
          -webkit-transform: translate3d(-50%, -50%, 0);
          transform: translate3d(-50%, -50%, 0);
          justify-content: center;
          align-items: center;
          flex-direction: column;
        }
        .app-loading .app-loading-title {
          margin-bottom: 30px;
          font-size: 20px;
          font-weight: bold;
          text-align: center;
        }
        .app-loading .app-loading-logo {
          width: 100px;
          margin: 0 auto 15px auto;
        }
        .app-loading .app-loading-item {
          position: relative;
          display: inline-block;
          width: 60px;
          height: 60px;
          vertical-align: middle;
          border-radius: 50%;
        }
        .app-loading .app-loading-outter {
          position: absolute;
          width: 100%;
          height: 100%;
          border: 4px solid #2d8cf0;
          border-bottom: 0;
          border-left-color: transparent;
          border-radius: 50%;
          animation: loader-outter 1s cubic-bezier(0.42, 0.61, 0.58, 0.41) infinite;
        }
        .app-loading .app-loading-inner {
          position: absolute;
          top: calc(50% - 20px);
          left: calc(50% - 20px);
          width: 40px;
          height: 40px;
          border: 4px solid #87bdff;
          border-right: 0;
          border-top-color: transparent;
          border-radius: 50%;
          animation: loader-inner 1s cubic-bezier(0.42, 0.61, 0.58, 0.41) infinite;
        }
        @-webkit-keyframes loader-outter {
          0% {
            -webkit-transform: rotate(0deg);
            transform: rotate(0deg);
          }
          100% {
            -webkit-transform: rotate(360deg);
            transform: rotate(360deg);
          }
        }
        @keyframes loader-outter {
          0% {
            -webkit-transform: rotate(0deg);
            transform: rotate(0deg);
          }
          100% {
            -webkit-transform: rotate(360deg);
            transform: rotate(360deg);
          }
        }
        @-webkit-keyframes loader-inner {
          0% {
            -webkit-transform: rotate(0deg);
            transform: rotate(0deg);
          }
          100% {
            -webkit-transform: rotate(-360deg);
            transform: rotate(-360deg);
          }
        }
        @keyframes loader-inner {
          0% {
            -webkit-transform: rotate(0deg);
            transform: rotate(0deg);
          }
          100% {
            -webkit-transform: rotate(-360deg);
            transform: rotate(-360deg);
          }
        }
      </style>
      <div class="app-loading">
        <div class="app-loading-wrap">
          <div class="app-loading-title">
            <img src="/logo.gif" class="app-loading-logo" alt="Logo" />
            <div class="app-loading-title">%VITE_APP_TITLE%</div>
          </div>
          <div class="app-loading-item">
            <div class="app-loading-outter"></div>
            <div class="app-loading-inner"></div>
          </div>
        </div>
      </div>
    </div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
package-lock.json
New file
Diff too large
package.json
New file
@@ -0,0 +1,159 @@
{
  "name": "yudao-ui-admin-vue3",
  "version": "2025.12-snapshot",
  "description": "基于vue3、vite4、element-plus、typesScript",
  "author": "xingyu",
  "private": false,
  "scripts": {
    "i": "pnpm install",
    "dev": "vite --mode env.local",
    "dev-server": "vite --mode dev",
    "ts:check": "vue-tsc --noEmit",
    "build:local": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build",
    "build:dev": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode dev",
    "build:test": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode test",
    "build:stage": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode stage",
    "build:prod": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode prod",
    "serve:dev": "vite preview --mode dev",
    "serve:prod": "vite preview --mode prod",
    "preview": "pnpm build:local && vite preview",
    "clean": "npx rimraf node_modules",
    "clean:cache": "npx rimraf node_modules/.cache",
    "lint:eslint": "eslint --fix --ext .js,.ts,.vue ./src",
    "lint:format": "prettier --write --loglevel warn \"src/**/*.{js,ts,json,tsx,css,less,scss,vue,html,md}\"",
    "lint:style": "stylelint --fix \"./src/**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
    "lint:lint-staged": "lint-staged -c "
  },
  "dependencies": {
    "@element-plus/icons-vue": "2.3.2",
    "@form-create/designer": "^3.2.6",
    "@form-create/element-ui": "^3.2.11",
    "@iconify/iconify": "^3.1.1",
    "@microsoft/fetch-event-source": "^2.0.1",
    "@videojs-player/vue": "^1.0.0",
    "@vueuse/core": "^10.9.0",
    "@wangeditor-next/editor": "^5.6.46",
    "@wangeditor-next/editor-for-vue": "^5.1.14",
    "@wangeditor-next/plugin-mention": "^1.0.16",
    "@zxcvbn-ts/core": "^3.0.4",
    "animate.css": "^4.1.1",
    "axios": "1.9.0",
    "benz-amr-recorder": "^1.1.5",
    "bpmn-js-token-simulation": "^0.36.0",
    "camunda-bpmn-moddle": "^7.0.1",
    "cropperjs": "^1.6.1",
    "crypto-js": "^4.2.0",
    "dayjs": "^1.11.10",
    "diagram-js": "^12.8.0",
    "driver.js": "^1.3.1",
    "echarts": "^5.5.0",
    "echarts-wordcloud": "^2.1.0",
    "element-plus": "2.11.1",
    "fast-xml-parser": "^4.3.2",
    "highlight.js": "^11.9.0",
    "jsencrypt": "^3.3.2",
    "jsoneditor": "^10.1.3",
    "lodash-es": "^4.17.21",
    "markdown-it": "^14.1.0",
    "markmap-common": "^0.16.0",
    "markmap-lib": "^0.16.1",
    "markmap-toolbar": "^0.17.0",
    "markmap-view": "^0.16.0",
    "min-dash": "^4.1.1",
    "mitt": "^3.0.1",
    "nprogress": "^0.2.0",
    "pinia": "^2.1.7",
    "pinia-plugin-persistedstate": "^3.2.1",
    "qrcode": "^1.5.3",
    "qs": "^6.12.0",
    "snabbdom": "^3.6.2",
    "sortablejs": "^1.15.3",
    "steady-xml": "^0.1.0",
    "url": "^0.11.3",
    "video.js": "^7.21.5",
    "vue": "3.5.12",
    "vue-dompurify-html": "^4.1.4",
    "vue-i18n": "9.10.2",
    "vue-router": "4.4.5",
    "vue-types": "^5.1.1",
    "vue3-print-nb": "^0.1.4",
    "vue3-signature": "^0.2.4",
    "vuedraggable": "^4.1.0",
    "web-storage-cache": "^1.1.1",
    "xml-js": "^1.6.11"
  },
  "devDependencies": {
    "@commitlint/cli": "^19.0.1",
    "@commitlint/config-conventional": "^19.0.0",
    "@iconify/json": "^2.2.187",
    "@intlify/unplugin-vue-i18n": "^2.0.0",
    "@purge-icons/generated": "^0.9.0",
    "@types/jsoneditor": "^9.9.5",
    "@types/lodash-es": "^4.17.12",
    "@types/node": "^20.11.21",
    "@types/nprogress": "^0.2.3",
    "@types/qrcode": "^1.5.5",
    "@types/qs": "^6.9.12",
    "@typescript-eslint/eslint-plugin": "^7.1.0",
    "@typescript-eslint/parser": "^7.1.0",
    "@unocss/eslint-config": "^0.57.4",
    "@unocss/eslint-plugin": "66.1.0-beta.5",
    "@unocss/transformer-variant-group": "^0.58.5",
    "@vitejs/plugin-legacy": "^5.3.1",
    "@vitejs/plugin-vue": "^5.0.4",
    "@vitejs/plugin-vue-jsx": "^3.1.0",
    "autoprefixer": "^10.4.17",
    "bpmn-js": "^17.9.2",
    "bpmn-js-properties-panel": "5.23.0",
    "consola": "^3.2.3",
    "eslint": "^8.57.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-define-config": "^2.1.0",
    "eslint-plugin-prettier": "^5.1.3",
    "eslint-plugin-vue": "^9.22.0",
    "lint-staged": "^15.2.2",
    "postcss": "^8.4.35",
    "postcss-html": "^1.6.0",
    "postcss-scss": "^4.0.9",
    "prettier": "^3.2.5",
    "prettier-eslint": "^16.3.0",
    "rimraf": "^5.0.5",
    "rollup": "^4.12.0",
    "sass": "^1.69.5",
    "stylelint": "^16.2.1",
    "stylelint-config-html": "^1.1.0",
    "stylelint-config-recommended": "^14.0.0",
    "stylelint-config-standard": "^36.0.0",
    "stylelint-order": "^6.0.4",
    "terser": "^5.28.1",
    "typescript": "5.3.3",
    "unocss": "^0.58.5",
    "unplugin-auto-import": "^0.16.7",
    "unplugin-element-plus": "^0.8.0",
    "unplugin-vue-components": "^0.25.2",
    "vite": "5.1.4",
    "vite-plugin-compression": "^0.5.1",
    "vite-plugin-ejs": "^1.7.0",
    "vite-plugin-eslint": "^1.8.1",
    "vite-plugin-progress": "^0.0.7",
    "vite-plugin-purge-icons": "^0.10.0",
    "vite-plugin-svg-icons-ng": "^1.3.1",
    "vite-plugin-top-level-await": "^1.4.4",
    "vue-eslint-parser": "^9.3.2",
    "vue-tsc": "^1.8.27"
  },
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://gitee.com/yudaocode/yudao-ui-admin-vue3"
  },
  "bugs": {
    "url": "https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues"
  },
  "homepage": "https://gitee.com/yudaocode/yudao-ui-admin-vue3",
  "web-types": "./web-types.json",
  "engines": {
    "node": ">= 16.0.0",
    "pnpm": ">=8.6.0"
  }
}
pnpm-lock.yaml
New file
Diff too large
postcss.config.js
New file
@@ -0,0 +1,5 @@
module.exports = {
  plugins: {
    autoprefixer: {}
  }
}
prettier.config.js
New file
@@ -0,0 +1,22 @@
module.exports = {
  printWidth: 100, // æ¯è¡Œä»£ç é•¿åº¦ï¼ˆé»˜è®¤80)
  tabWidth: 2, // æ¯ä¸ªtab相当于多少个空格(默认2)ab进行缩进(默认false)
  useTabs: false, // æ˜¯å¦ä½¿ç”¨tab
  semi: false, // å£°æ˜Žç»“尾使用分号(默认true)
  vueIndentScriptAndStyle: false,
  singleQuote: true, // ä½¿ç”¨å•引号(默认false)
  quoteProps: 'as-needed',
  bracketSpacing: true, // å¯¹è±¡å­—面量的大括号间使用空格(默认true)
  trailingComma: 'none', // å¤šè¡Œä½¿ç”¨æ‹–尾逗号(默认none)
  jsxSingleQuote: false,
  // ç®­å¤´å‡½æ•°å‚数括号 é»˜è®¤avoid å¯é€‰ avoid| always
  // avoid èƒ½çœç•¥æ‹¬å·çš„æ—¶å€™å°±çœç•¥ ä¾‹å¦‚x => x
  // always æ€»æ˜¯æœ‰æ‹¬å·
  arrowParens: 'always',
  insertPragma: false,
  requirePragma: false,
  proseWrap: 'never',
  htmlWhitespaceSensitivity: 'strict',
  endOfLine: 'auto',
  rangeStart: 0
}
public/favicon.ico
public/logo.gif
src/App.vue
New file
@@ -0,0 +1,57 @@
<script lang="ts" setup>
import { isDark } from '@/utils/is'
import { useAppStore } from '@/store/modules/app'
import { useDesign } from '@/hooks/web/useDesign'
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
import routerSearch from '@/components/RouterSearch/index.vue'
defineOptions({ name: 'APP' })
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('app')
const appStore = useAppStore()
const currentSize = computed(() => appStore.getCurrentSize)
const greyMode = computed(() => appStore.getGreyMode)
const { wsCache } = useCache()
// æ ¹æ®æµè§ˆå™¨å½“前主题设置系统主题色
const setDefaultTheme = () => {
  let isDarkTheme = wsCache.get(CACHE_KEY.IS_DARK)
  if (isDarkTheme === null) {
    isDarkTheme = isDark()
  }
  appStore.setIsDark(isDarkTheme)
}
setDefaultTheme()
</script>
<template>
  <ConfigGlobal :size="currentSize">
    <RouterView :class="greyMode ? `${prefixCls}-grey-mode` : ''" />
    <routerSearch />
  </ConfigGlobal>
</template>
<style lang="scss">
$prefix-cls: #{$namespace}-app;
.size {
  width: 100%;
  height: 100%;
}
html,
body {
  @extend .size;
  padding: 0 !important;
  margin: 0;
  overflow: hidden;
  #app {
    @extend .size;
  }
}
.#{$prefix-cls}-grey-mode {
  filter: grayscale(100%);
}
</style>
src/api/ai/chat/conversation/index.ts
New file
@@ -0,0 +1,65 @@
import request from '@/config/axios'
// AI èŠå¤©å¯¹è¯ VO
export interface ChatConversationVO {
  id: number // ID ç¼–号
  userId: number // ç”¨æˆ·ç¼–号
  title: string // å¯¹è¯æ ‡é¢˜
  pinned: boolean // æ˜¯å¦ç½®é¡¶
  roleId: number // è§’色编号
  modelId: number // æ¨¡åž‹ç¼–号
  model: string // æ¨¡åž‹æ ‡å¿—
  temperature: number // æ¸©åº¦å‚æ•°
  maxTokens: number // å•条回复的最大 Token æ•°é‡
  maxContexts: number // ä¸Šä¸‹æ–‡çš„æœ€å¤§ Message æ•°é‡
  createTime?: Date // åˆ›å»ºæ—¶é—´
  // é¢å¤–字段
  systemMessage?: string // è§’色设定
  modelName?: string // æ¨¡åž‹åå­—
  roleAvatar?: string // è§’色头像
  modelMaxTokens?: string // æ¨¡åž‹çš„单条回复的最大 Token æ•°é‡
  modelMaxContexts?: string // æ¨¡åž‹çš„上下文的最大 Message æ•°é‡
}
// AI èŠå¤©å¯¹è¯ API
export const ChatConversationApi = {
  // èŽ·å¾—ã€æˆ‘çš„ã€‘èŠå¤©å¯¹è¯
  getChatConversationMy: async (id: number) => {
    return await request.get({ url: `/ai/chat/conversation/get-my?id=${id}` })
  },
  // æ–°å¢žã€æˆ‘的】聊天对话
  createChatConversationMy: async (data?: ChatConversationVO) => {
    return await request.post({ url: `/ai/chat/conversation/create-my`, data })
  },
  // æ›´æ–°ã€æˆ‘的】聊天对话
  updateChatConversationMy: async (data: ChatConversationVO) => {
    return await request.put({ url: `/ai/chat/conversation/update-my`, data })
  },
  // åˆ é™¤ã€æˆ‘的】聊天对话
  deleteChatConversationMy: async (id: string) => {
    return await request.delete({ url: `/ai/chat/conversation/delete-my?id=${id}` })
  },
  // åˆ é™¤ã€æˆ‘的】所有对话,置顶除外
  deleteChatConversationMyByUnpinned: async () => {
    return await request.delete({ url: `/ai/chat/conversation/delete-by-unpinned` })
  },
  // èŽ·å¾—ã€æˆ‘çš„ã€‘èŠå¤©å¯¹è¯åˆ—è¡¨
  getChatConversationMyList: async () => {
    return await request.get({ url: `/ai/chat/conversation/my-list` })
  },
  // èŽ·å¾—å¯¹è¯åˆ†é¡µ
  getChatConversationPage: async (params: any) => {
    return await request.get({ url: `/ai/chat/conversation/page`, params })
  },
  // ç®¡ç†å‘˜åˆ é™¤æ¶ˆæ¯
  deleteChatConversationByAdmin: async (id: number) => {
    return await request.delete({ url: `/ai/chat/conversation/delete-by-admin?id=${id}` })
  }
}
src/api/ai/chat/message/index.ts
New file
@@ -0,0 +1,104 @@
import request from '@/config/axios'
import { fetchEventSource } from '@microsoft/fetch-event-source'
import { getAccessToken } from '@/utils/auth'
import { config } from '@/config/axios/config'
// èŠå¤©VO
export interface ChatMessageVO {
  id: number // ç¼–号
  conversationId: number // å¯¹è¯ç¼–号
  type: string // æ¶ˆæ¯ç±»åž‹
  userId: string // ç”¨æˆ·ç¼–号
  roleId: string // è§’色编号
  model: number // æ¨¡åž‹æ ‡å¿—
  modelId: number // æ¨¡åž‹ç¼–号
  content: string // èŠå¤©å†…容
  reasoningContent?: string // æŽ¨ç†å†…容
  attachmentUrls?: string[] // é™„ä»¶ URL æ•°ç»„
  tokens: number // æ¶ˆè€— Token æ•°é‡
  segmentIds?: number[] // æ®µè½ç¼–号
  segments?: {
    id: number // æ®µè½ç¼–号
    content: string // æ®µè½å†…容
    documentId: number // æ–‡æ¡£ç¼–号
    documentName: string // æ–‡æ¡£åç§°
  }[]
  webSearchPages?: {
    name: string // åç§°
    icon: string // å›¾æ ‡
    title: string // æ ‡é¢˜
    url: string // URL
    snippet: string // å†…容的简短描述
    summary: string // å†…容的文本摘要
  }[]
  createTime: Date // åˆ›å»ºæ—¶é—´
  roleAvatar: string // è§’色头像
  userAvatar: string // ç”¨æˆ·å¤´åƒ
}
// AI chat èŠå¤©
export const ChatMessageApi = {
  // æ¶ˆæ¯åˆ—表
  getChatMessageListByConversationId: async (conversationId: number | null) => {
    return await request.get({
      url: `/ai/chat/message/list-by-conversation-id?conversationId=${conversationId}`
    })
  },
  // å‘送 Stream æ¶ˆæ¯
  // ä¸ºä»€ä¹ˆä¸ç”¨ axios å‘¢ï¼Ÿå› ä¸ºå®ƒä¸æ”¯æŒ SSE è°ƒç”¨
  sendChatMessageStream: async (
    conversationId: number,
    content: string,
    ctrl,
    enableContext: boolean,
    enableWebSearch: boolean,
    onMessage,
    onError,
    onClose,
    attachmentUrls?: string[]
  ) => {
    const token = getAccessToken()
    return fetchEventSource(`${config.base_url}/ai/chat/message/send-stream`, {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`
      },
      openWhenHidden: true,
      body: JSON.stringify({
        conversationId,
        content,
        useContext: enableContext,
        useSearch: enableWebSearch,
        attachmentUrls: attachmentUrls || []
      }),
      onmessage: onMessage,
      onerror: onError,
      onclose: onClose,
      signal: ctrl.signal
    })
  },
  // åˆ é™¤æ¶ˆæ¯
  deleteChatMessage: async (id: string) => {
    return await request.delete({ url: `/ai/chat/message/delete?id=${id}` })
  },
  // åˆ é™¤æŒ‡å®šå¯¹è¯çš„æ¶ˆæ¯
  deleteByConversationId: async (conversationId: number) => {
    return await request.delete({
      url: `/ai/chat/message/delete-by-conversation-id?conversationId=${conversationId}`
    })
  },
  // èŽ·å¾—æ¶ˆæ¯åˆ†é¡µ
  getChatMessagePage: async (params: any) => {
    return await request.get({ url: '/ai/chat/message/page', params })
  },
  // ç®¡ç†å‘˜åˆ é™¤æ¶ˆæ¯
  deleteChatMessageByAdmin: async (id: number) => {
    return await request.delete({ url: `/ai/chat/message/delete-by-admin?id=${id}` })
  }
}
src/api/ai/image/index.ts
New file
@@ -0,0 +1,102 @@
import request from '@/config/axios'
// AI ç»˜å›¾ VO
export interface ImageVO {
  id: number // ç¼–号
  platform: string // å¹³å°
  model: string // æ¨¡åž‹
  prompt: string // æç¤ºè¯
  width: number // å›¾ç‰‡å®½åº¦
  height: number // å›¾ç‰‡é«˜åº¦
  status: number // çŠ¶æ€
  publicStatus: boolean // å…¬å¼€çŠ¶æ€
  picUrl: string // ä»»åŠ¡åœ°å€
  errorMessage: string // é”™è¯¯ä¿¡æ¯
  options: any // é…ç½® Map<string, string>
  taskId: number // ä»»åŠ¡ç¼–å·
  buttons: ImageMidjourneyButtonsVO[] // mj æ“ä½œæŒ‰é’®
  createTime: Date // åˆ›å»ºæ—¶é—´
  finishTime: Date // å®Œæˆæ—¶é—´
}
export interface ImageDrawReqVO {
  prompt: string // æç¤ºè¯
  modelId: number // æ¨¡åž‹
  style: string // å›¾åƒç”Ÿæˆçš„风格
  width: string // å›¾ç‰‡å®½åº¦
  height: string // å›¾ç‰‡é«˜åº¦
  options: object // ç»˜åˆ¶å‚数,Map<String, String>
}
export interface ImageMidjourneyImagineReqVO {
  prompt: string // æç¤ºè¯
  modelId: number // æ¨¡åž‹
  base64Array: string[] // size不能为空
  width: string // å›¾ç‰‡å®½åº¦
  height: string // å›¾ç‰‡é«˜åº¦
  version: string // ç‰ˆæœ¬
}
export interface ImageMidjourneyActionVO {
  id: number // å›¾ç‰‡ç¼–号
  customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 åŠ¨ä½œæ ‡è¯†
}
export interface ImageMidjourneyButtonsVO {
  customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 åŠ¨ä½œæ ‡è¯†
  emoji: string // å›¾æ ‡ emoji
  label: string // Make Variations æ–‡æœ¬
  style: number // æ ·å¼: 2(Primary)、3(Green)
}
// AI å›¾ç‰‡ API
export const ImageApi = {
  // èŽ·å–ã€æˆ‘çš„ã€‘ç»˜å›¾åˆ†é¡µ
  getImagePageMy: async (params: any) => {
    return await request.get({ url: `/ai/image/my-page`, params })
  },
  // èŽ·å–ã€æˆ‘çš„ã€‘ç»˜å›¾è®°å½•
  getImageMy: async (id: number) => {
    return await request.get({ url: `/ai/image/get-my?id=${id}` })
  },
  // èŽ·å–ã€æˆ‘çš„ã€‘ç»˜å›¾è®°å½•åˆ—è¡¨
  getImageListMyByIds: async (ids: number[]) => {
    return await request.get({ url: `/ai/image/my-list-by-ids`, params: { ids: ids.join(',') } })
  },
  // ç”Ÿæˆå›¾ç‰‡
  drawImage: async (data: ImageDrawReqVO) => {
    return await request.post({ url: `/ai/image/draw`, data })
  },
  // åˆ é™¤ã€æˆ‘的】绘画记录
  deleteImageMy: async (id: number) => {
    return await request.delete({ url: `/ai/image/delete-my?id=${id}` })
  },
  // ================ midjourney ä¸“属 ================
  // ã€Midjourney】生成图片
  midjourneyImagine: async (data: ImageMidjourneyImagineReqVO) => {
    return await request.post({ url: `/ai/image/midjourney/imagine`, data })
  },
  // ã€Midjourney】Action æ“ä½œï¼ˆäºŒæ¬¡ç”Ÿæˆå›¾ç‰‡ï¼‰
  midjourneyAction: async (data: ImageMidjourneyActionVO) => {
    return await request.post({ url: `/ai/image/midjourney/action`, data })
  },
  // ================ ç»˜å›¾ç®¡ç† ================
  // æŸ¥è¯¢ç»˜ç”»åˆ†é¡µ
  getImagePage: async (params: any) => {
    return await request.get({ url: `/ai/image/page`, params })
  },
  // æ›´æ–°ç»˜ç”»å‘布状态
  updateImage: async (data: any) => {
    return await request.put({ url: '/ai/image/update', data })
  },
  // åˆ é™¤ç»˜ç”»
  deleteImage: async (id: number) => {
    return await request.delete({ url: `/ai/image/delete?id=` + id })
  }
}
src/api/ai/knowledge/document/index.ts
New file
@@ -0,0 +1,54 @@
import request from '@/config/axios'
// AI çŸ¥è¯†åº“文档 VO
export interface KnowledgeDocumentVO {
  id: number // ç¼–号
  knowledgeId: number // çŸ¥è¯†åº“编号
  name: string // æ–‡æ¡£åç§°
  contentLength: number // å­—符数
  tokens: number // token æ•°
  segmentMaxTokens: number // åˆ†ç‰‡æœ€å¤§ token æ•°
  retrievalCount: number // å¬å›žæ¬¡æ•°
  status: number // æ˜¯å¦å¯ç”¨
}
// AI çŸ¥è¯†åº“文档 API
export const KnowledgeDocumentApi = {
  // æŸ¥è¯¢çŸ¥è¯†åº“文档分页
  getKnowledgeDocumentPage: async (params: any) => {
    return await request.get({ url: `/ai/knowledge/document/page`, params })
  },
  // æŸ¥è¯¢çŸ¥è¯†åº“文档详情
  getKnowledgeDocument: async (id: number) => {
    return await request.get({ url: `/ai/knowledge/document/get?id=` + id })
  },
  // æ–°å¢žçŸ¥è¯†åº“文档(单个)
  createKnowledgeDocument: async (data: any) => {
    return await request.post({ url: `/ai/knowledge/document/create`, data })
  },
  // æ–°å¢žçŸ¥è¯†åº“文档(多个)
  createKnowledgeDocumentList: async (data: any) => {
    return await request.post({ url: `/ai/knowledge/document/create-list`, data })
  },
  // ä¿®æ”¹çŸ¥è¯†åº“文档
  updateKnowledgeDocument: async (data: any) => {
    return await request.put({ url: `/ai/knowledge/document/update`, data })
  },
  // ä¿®æ”¹çŸ¥è¯†åº“文档状态
  updateKnowledgeDocumentStatus: async (data: any) => {
    return await request.put({
      url: `/ai/knowledge/document/update-status`,
      data
    })
  },
  // åˆ é™¤çŸ¥è¯†åº“文档
  deleteKnowledgeDocument: async (id: number) => {
    return await request.delete({ url: `/ai/knowledge/document/delete?id=` + id })
  }
}
src/api/ai/knowledge/knowledge/index.ts
New file
@@ -0,0 +1,44 @@
import request from '@/config/axios'
// AI çŸ¥è¯†åº“ VO
export interface KnowledgeVO {
  id: number // ç¼–号
  name: string // çŸ¥è¯†åº“名称
  description: string // çŸ¥è¯†åº“描述
  embeddingModelId: number // åµŒå…¥æ¨¡åž‹ç¼–号,高质量模式时维护
  topK: number // topK
  similarityThreshold: number // ç›¸ä¼¼åº¦é˜ˆå€¼
}
// AI çŸ¥è¯†åº“ API
export const KnowledgeApi = {
  // æŸ¥è¯¢çŸ¥è¯†åº“分页
  getKnowledgePage: async (params: any) => {
    return await request.get({ url: `/ai/knowledge/page`, params })
  },
  // æŸ¥è¯¢çŸ¥è¯†åº“详情
  getKnowledge: async (id: number) => {
    return await request.get({ url: `/ai/knowledge/get?id=` + id })
  },
  // æ–°å¢žçŸ¥è¯†åº“
  createKnowledge: async (data: KnowledgeVO) => {
    return await request.post({ url: `/ai/knowledge/create`, data })
  },
  // ä¿®æ”¹çŸ¥è¯†åº“
  updateKnowledge: async (data: KnowledgeVO) => {
    return await request.put({ url: `/ai/knowledge/update`, data })
  },
  // åˆ é™¤çŸ¥è¯†åº“
  deleteKnowledge: async (id: number) => {
    return await request.delete({ url: `/ai/knowledge/delete?id=` + id })
  },
  // èŽ·å–çŸ¥è¯†åº“ç®€å•åˆ—è¡¨
  getSimpleKnowledgeList: async () => {
    return await request.get({ url: `/ai/knowledge/simple-list` })
  }
}
src/api/ai/knowledge/segment/index.ts
New file
@@ -0,0 +1,75 @@
import request from '@/config/axios'
// AI çŸ¥è¯†åº“分段 VO
export interface KnowledgeSegmentVO {
  id: number // ç¼–号
  documentId: number // æ–‡æ¡£ç¼–号
  knowledgeId: number // çŸ¥è¯†åº“编号
  vectorId: string // å‘量库编号
  content: string // åˆ‡ç‰‡å†…容
  contentLength: number // åˆ‡ç‰‡å†…容长度
  tokens: number // token æ•°é‡
  retrievalCount: number // å¬å›žæ¬¡æ•°
  status: number // æ–‡æ¡£çŠ¶æ€
  createTime: number // åˆ›å»ºæ—¶é—´
}
// AI çŸ¥è¯†åº“分段 API
export const KnowledgeSegmentApi = {
  // æŸ¥è¯¢çŸ¥è¯†åº“分段分页
  getKnowledgeSegmentPage: async (params: any) => {
    return await request.get({ url: `/ai/knowledge/segment/page`, params })
  },
  // æŸ¥è¯¢çŸ¥è¯†åº“分段详情
  getKnowledgeSegment: async (id: number) => {
    return await request.get({ url: `/ai/knowledge/segment/get?id=` + id })
  },
  // åˆ é™¤çŸ¥è¯†åº“分段
  deleteKnowledgeSegment: async (id: number) => {
    return await request.delete({ url: `/ai/knowledge/segment/delete?id=` + id })
  },
  // æ–°å¢žçŸ¥è¯†åº“分段
  createKnowledgeSegment: async (data: KnowledgeSegmentVO) => {
    return await request.post({ url: `/ai/knowledge/segment/create`, data })
  },
  // ä¿®æ”¹çŸ¥è¯†åº“分段
  updateKnowledgeSegment: async (data: KnowledgeSegmentVO) => {
    return await request.put({ url: `/ai/knowledge/segment/update`, data })
  },
  // ä¿®æ”¹çŸ¥è¯†åº“分段状态
  updateKnowledgeSegmentStatus: async (data: any) => {
    return await request.put({
      url: `/ai/knowledge/segment/update-status`,
      data
    })
  },
  // åˆ‡ç‰‡å†…容
  splitContent: async (url: string, segmentMaxTokens: number) => {
    return await request.get({
      url: `/ai/knowledge/segment/split`,
      params: { url, segmentMaxTokens }
    })
  },
  // èŽ·å–æ–‡æ¡£å¤„ç†åˆ—è¡¨
  getKnowledgeSegmentProcessList: async (documentIds: number[]) => {
    return await request.get({
      url: `/ai/knowledge/segment/get-process-list`,
      params: { documentIds: documentIds.join(',') }
    })
  },
  // æœç´¢çŸ¥è¯†åº“分段
  searchKnowledgeSegment: async (params: any) => {
    return await request.get({
      url: `/ai/knowledge/segment/search`,
      params
    })
  }
}
src/api/ai/mindmap/index.ts
New file
@@ -0,0 +1,60 @@
import { getAccessToken } from '@/utils/auth'
import { fetchEventSource } from '@microsoft/fetch-event-source'
import { config } from '@/config/axios/config'
import request from '@/config/axios' // AI æ€ç»´å¯¼å›¾ VO
// AI æ€ç»´å¯¼å›¾ VO
export interface MindMapVO {
  id: number // ç¼–号
  userId: number // ç”¨æˆ·ç¼–号
  prompt: string // ç”Ÿæˆå†…容提示
  generatedContent: string // ç”Ÿæˆçš„æ€ç»´å¯¼å›¾å†…容
  platform: string // å¹³å°
  model: string // æ¨¡åž‹
  errorMessage: string // é”™è¯¯ä¿¡æ¯
}
// AI æ€ç»´å¯¼å›¾ç”Ÿæˆ VO
export interface AiMindMapGenerateReqVO {
  prompt: string
}
export const AiMindMapApi = {
  generateMindMap: ({
    data,
    onClose,
    onMessage,
    onError,
    ctrl
  }: {
    data: AiMindMapGenerateReqVO
    onMessage?: (res: any) => void
    onError?: (...args: any[]) => void
    onClose?: (...args: any[]) => void
    ctrl: AbortController
  }) => {
    const token = getAccessToken()
    return fetchEventSource(`${config.base_url}/ai/mind-map/generate-stream`, {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`
      },
      openWhenHidden: true,
      body: JSON.stringify(data),
      onmessage: onMessage,
      onerror: onError,
      onclose: onClose,
      signal: ctrl.signal
    })
  },
  // æŸ¥è¯¢æ€ç»´å¯¼å›¾åˆ†é¡µ
  getMindMapPage: async (params: any) => {
    return await request.get({ url: `/ai/mind-map/page`, params })
  },
  // åˆ é™¤æ€ç»´å¯¼å›¾
  deleteMindMap: async (id: number) => {
    return await request.delete({ url: `/ai/mind-map/delete?id=` + id })
  }
}
src/api/ai/model/apiKey/index.ts
New file
@@ -0,0 +1,44 @@
import request from '@/config/axios'
// AI API å¯†é’¥ VO
export interface ApiKeyVO {
  id: number // ç¼–号
  name: string // åç§°
  apiKey: string // å¯†é’¥
  platform: string // å¹³å°
  url: string // è‡ªå®šä¹‰ API åœ°å€
  status: number // çŠ¶æ€
}
// AI API å¯†é’¥ API
export const ApiKeyApi = {
  // æŸ¥è¯¢ API å¯†é’¥åˆ†é¡µ
  getApiKeyPage: async (params: any) => {
    return await request.get({ url: `/ai/api-key/page`, params })
  },
  // èŽ·å¾— API å¯†é’¥åˆ—表
  getApiKeySimpleList: async () => {
    return await request.get({ url: `/ai/api-key/simple-list` })
  },
  // æŸ¥è¯¢ API å¯†é’¥è¯¦æƒ…
  getApiKey: async (id: number) => {
    return await request.get({ url: `/ai/api-key/get?id=` + id })
  },
  // æ–°å¢ž API å¯†é’¥
  createApiKey: async (data: ApiKeyVO) => {
    return await request.post({ url: `/ai/api-key/create`, data })
  },
  // ä¿®æ”¹ API å¯†é’¥
  updateApiKey: async (data: ApiKeyVO) => {
    return await request.put({ url: `/ai/api-key/update`, data })
  },
  // åˆ é™¤ API å¯†é’¥
  deleteApiKey: async (id: number) => {
    return await request.delete({ url: `/ai/api-key/delete?id=` + id })
  }
}
src/api/ai/model/chatRole/index.ts
New file
@@ -0,0 +1,83 @@
import request from '@/config/axios'
// AI èŠå¤©è§’色 VO
export interface ChatRoleVO {
  id: number // è§’色编号
  modelId: number // æ¨¡åž‹ç¼–号
  name: string // è§’色名称
  avatar: string // è§’色头像
  category: string // è§’色类别
  sort: number // è§’色排序
  description: string // è§’色描述
  systemMessage: string // è§’色设定
  welcomeMessage: string // è§’色设定
  publicStatus: boolean // æ˜¯å¦å…¬å¼€
  status: number // çŠ¶æ€
  knowledgeIds?: number[] // å¼•用的知识库 ID åˆ—表
  toolIds?: number[] // å¼•用的工具 ID åˆ—表
  mcpClientNames?: string[] // å¼•用的 MCP Client åå­—列表
}
// AI èŠå¤©è§’色 åˆ†é¡µè¯·æ±‚ vo
export interface ChatRolePageReqVO {
  name?: string // è§’色名称
  category?: string // è§’色类别
  publicStatus: boolean // æ˜¯å¦å…¬å¼€
  pageNo: number // æ˜¯å¦å…¬å¼€
  pageSize: number // æ˜¯å¦å…¬å¼€
}
// AI èŠå¤©è§’色 API
export const ChatRoleApi = {
  // æŸ¥è¯¢èŠå¤©è§’色分页
  getChatRolePage: async (params: any) => {
    return await request.get({ url: `/ai/chat-role/page`, params })
  },
  // æŸ¥è¯¢èŠå¤©è§’色详情
  getChatRole: async (id: number) => {
    return await request.get({ url: `/ai/chat-role/get?id=` + id })
  },
  // æ–°å¢žèŠå¤©è§’色
  createChatRole: async (data: ChatRoleVO) => {
    return await request.post({ url: `/ai/chat-role/create`, data })
  },
  // ä¿®æ”¹èŠå¤©è§’色
  updateChatRole: async (data: ChatRoleVO) => {
    return await request.put({ url: `/ai/chat-role/update`, data })
  },
  // åˆ é™¤èŠå¤©è§’色
  deleteChatRole: async (id: number) => {
    return await request.delete({ url: `/ai/chat-role/delete?id=` + id })
  },
  // ======= chat èŠå¤©
  // èŽ·å– my role
  getMyPage: async (params: ChatRolePageReqVO) => {
    return await request.get({ url: `/ai/chat-role/my-page`, params })
  },
  // èŽ·å–è§’è‰²åˆ†ç±»
  getCategoryList: async () => {
    return await request.get({ url: `/ai/chat-role/category-list` })
  },
  // åˆ›å»ºè§’色
  createMy: async (data: ChatRoleVO) => {
    return await request.post({ url: `/ai/chat-role/create-my`, data })
  },
  // æ›´æ–°è§’色
  updateMy: async (data: ChatRoleVO) => {
    return await request.put({ url: `/ai/chat-role/update-my`, data })
  },
  // åˆ é™¤è§’色 my
  deleteMy: async (id: number) => {
    return await request.delete({ url: `/ai/chat-role/delete-my?id=` + id })
  }
}
src/api/ai/model/model/index.ts
New file
@@ -0,0 +1,54 @@
import request from '@/config/axios'
// AI æ¨¡åž‹ VO
export interface ModelVO {
  id: number // ç¼–号
  keyId: number // API ç§˜é’¥ç¼–号
  name: string // æ¨¡åž‹åå­—
  model: string // æ¨¡åž‹æ ‡è¯†
  platform: string // æ¨¡åž‹å¹³å°
  type: number // æ¨¡åž‹ç±»åž‹
  sort: number // æŽ’序
  status: number // çŠ¶æ€
  temperature?: number // æ¸©åº¦å‚æ•°
  maxTokens?: number // å•条回复的最大 Token æ•°é‡
  maxContexts?: number // ä¸Šä¸‹æ–‡çš„æœ€å¤§ Message æ•°é‡
}
// AI æ¨¡åž‹ API
export const ModelApi = {
  // æŸ¥è¯¢æ¨¡åž‹åˆ†é¡µ
  getModelPage: async (params: any) => {
    return await request.get({ url: `/ai/model/page`, params })
  },
  // èŽ·å¾—æ¨¡åž‹åˆ—è¡¨
  getModelSimpleList: async (type?: number) => {
    return await request.get({
      url: `/ai/model/simple-list`,
      params: {
        type
      }
    })
  },
  // æŸ¥è¯¢æ¨¡åž‹è¯¦æƒ…
  getModel: async (id: number) => {
    return await request.get({ url: `/ai/model/get?id=` + id })
  },
  // æ–°å¢žæ¨¡åž‹
  createModel: async (data: ModelVO) => {
    return await request.post({ url: `/ai/model/create`, data })
  },
  // ä¿®æ”¹æ¨¡åž‹
  updateModel: async (data: ModelVO) => {
    return await request.put({ url: `/ai/model/update`, data })
  },
  // åˆ é™¤æ¨¡åž‹
  deleteModel: async (id: number) => {
    return await request.delete({ url: `/ai/model/delete?id=` + id })
  }
}
src/api/ai/model/tool/index.ts
New file
@@ -0,0 +1,42 @@
import request from '@/config/axios'
// AI å·¥å…· VO
export interface ToolVO {
  id: number // å·¥å…·ç¼–号
  name: string // å·¥å…·åç§°
  description: string // å·¥å…·æè¿°
  status: number // çŠ¶æ€
}
// AI å·¥å…· API
export const ToolApi = {
  // æŸ¥è¯¢å·¥å…·åˆ†é¡µ
  getToolPage: async (params: any) => {
    return await request.get({ url: `/ai/tool/page`, params })
  },
  // æŸ¥è¯¢å·¥å…·è¯¦æƒ…
  getTool: async (id: number) => {
    return await request.get({ url: `/ai/tool/get?id=` + id })
  },
  // æ–°å¢žå·¥å…·
  createTool: async (data: ToolVO) => {
    return await request.post({ url: `/ai/tool/create`, data })
  },
  // ä¿®æ”¹å·¥å…·
  updateTool: async (data: ToolVO) => {
    return await request.put({ url: `/ai/tool/update`, data })
  },
  // åˆ é™¤å·¥å…·
  deleteTool: async (id: number) => {
    return await request.delete({ url: `/ai/tool/delete?id=` + id })
  },
  // èŽ·å–å·¥å…·ç®€å•åˆ—è¡¨
  getToolSimpleList: async () => {
    return await request.get({ url: `/ai/tool/simple-list` })
  }
}
src/api/ai/music/index.ts
New file
@@ -0,0 +1,41 @@
import request from '@/config/axios'
// AI éŸ³ä¹ VO
export interface MusicVO {
  id: number // ç¼–号
  userId: number // ç”¨æˆ·ç¼–号
  title: string // éŸ³ä¹åç§°
  lyric: string // æ­Œè¯
  imageUrl: string // å›¾ç‰‡åœ°å€
  audioUrl: string // éŸ³é¢‘地址
  videoUrl: string // è§†é¢‘地址
  status: number // éŸ³ä¹çŠ¶æ€
  gptDescriptionPrompt: string // æè¿°è¯
  prompt: string // æç¤ºè¯
  platform: string // æ¨¡åž‹å¹³å°
  model: string // æ¨¡åž‹
  generateMode: number // ç”Ÿæˆæ¨¡å¼
  tags: string // éŸ³ä¹é£Žæ ¼æ ‡ç­¾
  duration: number // éŸ³ä¹æ—¶é•¿
  publicStatus: boolean // æ˜¯å¦å‘布
  taskId: string // ä»»åŠ¡id
  errorMessage: string // é”™è¯¯ä¿¡æ¯
}
// AI éŸ³ä¹ API
export const MusicApi = {
  // æŸ¥è¯¢éŸ³ä¹åˆ†é¡µ
  getMusicPage: async (params: any) => {
    return await request.get({ url: `/ai/music/page`, params })
  },
  // æ›´æ–°éŸ³ä¹
  updateMusic: async (data: any) => {
    return await request.put({ url: '/ai/music/update', data })
  },
  // åˆ é™¤éŸ³ä¹
  deleteMusic: async (id: number) => {
    return await request.delete({ url: `/ai/music/delete?id=` + id })
  }
}
src/api/ai/workflow/index.ts
New file
@@ -0,0 +1,25 @@
import request from '@/config/axios'
export const getWorkflowPage = async (params) => {
  return await request.get({ url: '/ai/workflow/page', params })
}
export const getWorkflow = async (id) => {
  return await request.get({ url: '/ai/workflow/get?id=' + id })
}
export const createWorkflow = async (data) => {
  return await request.post({ url: '/ai/workflow/create', data })
}
export const updateWorkflow = async (data) => {
  return await request.put({ url: '/ai/workflow/update', data })
}
export const deleteWorkflow = async (id) => {
  return await request.delete({ url: '/ai/workflow/delete?id=' + id })
}
export const testWorkflow = async (data) => {
  return await request.post({ url: '/ai/workflow/test', data })
}
src/api/ai/write/index.ts
New file
@@ -0,0 +1,85 @@
import { fetchEventSource } from '@microsoft/fetch-event-source'
import { getAccessToken } from '@/utils/auth'
import { config } from '@/config/axios/config'
import { AiWriteTypeEnum } from '@/views/ai/utils/constants'
import request from '@/config/axios'
export interface WriteVO {
  type: AiWriteTypeEnum.WRITING | AiWriteTypeEnum.REPLY // 1:撰写 2:回复
  prompt: string // å†™ä½œå†…容提示 1。撰写 2回复
  originalContent: string // åŽŸæ–‡
  length: number // é•¿åº¦
  format: number // æ ¼å¼
  tone: number // è¯­æ°”
  language: number // è¯­è¨€
  userId?: number // ç”¨æˆ·ç¼–号
  platform?: string // å¹³å°
  model?: string // æ¨¡åž‹
  generatedContent?: string // ç”Ÿæˆçš„内容
  errorMessage?: string // é”™è¯¯ä¿¡æ¯
  createTime?: Date // åˆ›å»ºæ—¶é—´
}
export interface AiWritePageReqVO extends PageParam {
  userId?: number // ç”¨æˆ·ç¼–号
  type?: AiWriteTypeEnum //  å†™ä½œç±»åž‹
  platform?: string // å¹³å°
  createTime?: [string, string] // åˆ›å»ºæ—¶é—´
}
export interface AiWriteRespVo {
  id: number
  userId: number
  type: number
  platform: string
  model: string
  prompt: string
  generatedContent: string
  originalContent: string
  length: number
  format: number
  tone: number
  language: number
  errorMessage: string
  createTime: string
}
export const WriteApi = {
  writeStream: ({
    data,
    onClose,
    onMessage,
    onError,
    ctrl
  }: {
    data: WriteVO
    onMessage?: (res: any) => void
    onError?: (...args: any[]) => void
    onClose?: (...args: any[]) => void
    ctrl: AbortController
  }) => {
    const token = getAccessToken()
    return fetchEventSource(`${config.base_url}/ai/write/generate-stream`, {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`
      },
      openWhenHidden: true,
      body: JSON.stringify(data),
      onmessage: onMessage,
      onerror: onError,
      onclose: onClose,
      signal: ctrl.signal
    })
  },
  // èŽ·å–å†™ä½œåˆ—è¡¨
  getWritePage: (params: AiWritePageReqVO) => {
    return request.get<PageResult<AiWriteRespVo[]>>({ url: `/ai/write/page`, params })
  },
  // åˆ é™¤å†™ä½œ
  deleteWrite(id: number) {
    return request.delete({ url: `/ai/write/delete`, params: { id } })
  }
}
src/api/bpm/category/index.ts
New file
@@ -0,0 +1,53 @@
import request from '@/config/axios'
// BPM æµç¨‹åˆ†ç±» VO
export interface CategoryVO {
  id: number // åˆ†ç±»ç¼–号
  name: string // åˆ†ç±»å
  code: string // åˆ†ç±»æ ‡å¿—
  status: number // åˆ†ç±»çŠ¶æ€
  sort: number // åˆ†ç±»æŽ’序
}
// BPM æµç¨‹åˆ†ç±» API
export const CategoryApi = {
  // æŸ¥è¯¢æµç¨‹åˆ†ç±»åˆ†é¡µ
  getCategoryPage: async (params: any) => {
    return await request.get({ url: `/bpm/category/page`, params })
  },
  // æŸ¥è¯¢æµç¨‹åˆ†ç±»åˆ—表
  getCategorySimpleList: async () => {
    return await request.get({ url: `/bpm/category/simple-list` })
  },
  // æŸ¥è¯¢æµç¨‹åˆ†ç±»è¯¦æƒ…
  getCategory: async (id: number) => {
    return await request.get({ url: `/bpm/category/get?id=` + id })
  },
  // æ–°å¢žæµç¨‹åˆ†ç±»
  createCategory: async (data: CategoryVO) => {
    return await request.post({ url: `/bpm/category/create`, data })
  },
  // ä¿®æ”¹æµç¨‹åˆ†ç±»
  updateCategory: async (data: CategoryVO) => {
    return await request.put({ url: `/bpm/category/update`, data })
  },
  // æ‰¹é‡ä¿®æ”¹æµç¨‹åˆ†ç±»çš„æŽ’序
  updateCategorySortBatch: async (ids: number[]) => {
    return await request.put({
      url: `/bpm/category/update-sort-batch`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // åˆ é™¤æµç¨‹åˆ†ç±»
  deleteCategory: async (id: number) => {
    return await request.delete({ url: `/bpm/category/delete?id=` + id })
  }
}
src/api/bpm/definition/index.ts
New file
@@ -0,0 +1,28 @@
import request from '@/config/axios'
export const getProcessDefinition = async (id?: string, key?: string) => {
  return await request.get({
    url: '/bpm/process-definition/get',
    params: { id, key }
  })
}
export const getProcessDefinitionPage = async (params) => {
  return await request.get({
    url: '/bpm/process-definition/page',
    params
  })
}
export const getProcessDefinitionList = async (params) => {
  return await request.get({
    url: '/bpm/process-definition/list',
    params
  })
}
export const getSimpleProcessDefinitionList = async () => {
  return await request.get({
    url: '/bpm/process-definition/simple-list'
  })
}
src/api/bpm/form/index.ts
New file
@@ -0,0 +1,56 @@
import request from '@/config/axios'
export type FormVO = {
  id: number
  name: string
  conf: string
  fields: string[]
  status: number
  remark: string
  createTime: string
}
// åˆ›å»ºå·¥ä½œæµçš„表单定义
export const createForm = async (data: FormVO) => {
  return await request.post({
    url: '/bpm/form/create',
    data: data
  })
}
// æ›´æ–°å·¥ä½œæµçš„表单定义
export const updateForm = async (data: FormVO) => {
  return await request.put({
    url: '/bpm/form/update',
    data: data
  })
}
// åˆ é™¤å·¥ä½œæµçš„表单定义
export const deleteForm = async (id: number) => {
  return await request.delete({
    url: '/bpm/form/delete?id=' + id
  })
}
// èŽ·å¾—å·¥ä½œæµçš„è¡¨å•å®šä¹‰
export const getForm = async (id: number) => {
  return await request.get({
    url: '/bpm/form/get?id=' + id
  })
}
// èŽ·å¾—å·¥ä½œæµçš„è¡¨å•å®šä¹‰åˆ†é¡µ
export const getFormPage = async (params) => {
  return await request.get({
    url: '/bpm/form/page',
    params
  })
}
// èŽ·å¾—åŠ¨æ€è¡¨å•çš„ç²¾ç®€åˆ—è¡¨
export const getFormSimpleList = async () => {
  return await request.get({
    url: '/bpm/form/simple-list'
  })
}
src/api/bpm/leave/index.ts
New file
@@ -0,0 +1,27 @@
import request from '@/config/axios'
export type LeaveVO = {
  id: number
  status: number
  type: number
  reason: string
  processInstanceId: string
  startTime: string
  endTime: string
  createTime: string
}
// åˆ›å»ºè¯·å‡ç”³è¯·
export const createLeave = async (data: LeaveVO) => {
  return await request.post({ url: '/bpm/oa/leave/create', data: data })
}
// èŽ·å¾—è¯·å‡ç”³è¯·
export const getLeave = async (id: number) => {
  return await request.get({ url: '/bpm/oa/leave/get?id=' + id })
}
// èŽ·å¾—è¯·å‡ç”³è¯·åˆ†é¡µ
export const getLeavePage = async (params: PageParam) => {
  return await request.get({ url: '/bpm/oa/leave/page', params })
}
src/api/bpm/model/index.ts
New file
@@ -0,0 +1,79 @@
import request from '@/config/axios'
export type ProcessDefinitionVO = {
  id: string
  version: number
  deploymentTIme: string
  suspensionState: number
  formType?: number
  formCustomCreatePath?: string
}
export type ModelVO = {
  id: number
  formName: string
  key: string
  name: string
  description: string
  category: string
  formType: number
  formId: number
  formCustomCreatePath: string
  formCustomViewPath: string
  processDefinition: ProcessDefinitionVO
  status: number
  remark: string
  createTime: string
  bpmnXml: string
}
export const getModelList = async (name: string | undefined) => {
  return await request.get({ url: '/bpm/model/list', params: { name } })
}
export const getModel = async (id: string) => {
  return await request.get({ url: '/bpm/model/get?id=' + id })
}
export const updateModel = async (data: ModelVO) => {
  return await request.put({ url: '/bpm/model/update', data: data })
}
// æ‰¹é‡ä¿®æ”¹æµç¨‹åˆ†ç±»çš„æŽ’序
export const updateModelSortBatch = async (ids: number[]) => {
  return await request.put({
    url: `/bpm/model/update-sort-batch`,
    params: {
      ids: ids.join(',')
    }
  })
}
export const updateModelBpmn = async (data: ModelVO) => {
  return await request.put({ url: '/bpm/model/update-bpmn', data: data })
}
// ä»»åŠ¡çŠ¶æ€ä¿®æ”¹
export const updateModelState = async (id: number, state: number) => {
  const data = {
    id: id,
    state: state
  }
  return await request.put({ url: '/bpm/model/update-state', data: data })
}
export const createModel = async (data: ModelVO) => {
  return await request.post({ url: '/bpm/model/create', data: data })
}
export const deleteModel = async (id: number) => {
  return await request.delete({ url: '/bpm/model/delete?id=' + id })
}
export const deployModel = async (id: number) => {
  return await request.post({ url: '/bpm/model/deploy?id=' + id })
}
export const cleanModel = async (id: number) => {
  return await request.delete({ url: '/bpm/model/clean?id=' + id })
}
src/api/bpm/processExpression/index.ts
New file
@@ -0,0 +1,42 @@
import request from '@/config/axios'
// BPM æµç¨‹è¡¨è¾¾å¼ VO
export interface ProcessExpressionVO {
  id: number // ç¼–号
  name: string // è¡¨è¾¾å¼åå­—
  status: number // è¡¨è¾¾å¼çŠ¶æ€
  expression: string // è¡¨è¾¾å¼
}
// BPM æµç¨‹è¡¨è¾¾å¼ API
export const ProcessExpressionApi = {
  // æŸ¥è¯¢BPM æµç¨‹è¡¨è¾¾å¼åˆ†é¡µ
  getProcessExpressionPage: async (params: any) => {
    return await request.get({ url: `/bpm/process-expression/page`, params })
  },
  // æŸ¥è¯¢BPM æµç¨‹è¡¨è¾¾å¼è¯¦æƒ…
  getProcessExpression: async (id: number) => {
    return await request.get({ url: `/bpm/process-expression/get?id=` + id })
  },
  // æ–°å¢žBPM æµç¨‹è¡¨è¾¾å¼
  createProcessExpression: async (data: ProcessExpressionVO) => {
    return await request.post({ url: `/bpm/process-expression/create`, data })
  },
  // ä¿®æ”¹BPM æµç¨‹è¡¨è¾¾å¼
  updateProcessExpression: async (data: ProcessExpressionVO) => {
    return await request.put({ url: `/bpm/process-expression/update`, data })
  },
  // åˆ é™¤BPM æµç¨‹è¡¨è¾¾å¼
  deleteProcessExpression: async (id: number) => {
    return await request.delete({ url: `/bpm/process-expression/delete?id=` + id })
  },
  // å¯¼å‡ºBPM æµç¨‹è¡¨è¾¾å¼ Excel
  exportProcessExpression: async (params) => {
    return await request.download({ url: `/bpm/process-expression/export-excel`, params })
  }
}
src/api/bpm/processInstance/index.ts
New file
@@ -0,0 +1,115 @@
import request from '@/config/axios'
import { ProcessDefinitionVO } from '@/api/bpm/model'
import { NodeType, CandidateStrategy } from '@/components/SimpleProcessDesignerV2/src/consts'
export type Task = {
  id: string
  name: string
}
export type ProcessInstanceVO = {
  id: number
  name: string
  processDefinitionId: string
  category: string
  result: number
  tasks: Task[]
  fields: string[]
  status: number
  remark: string
  businessKey: string
  createTime: string
  endTime: string
  processDefinition?: ProcessDefinitionVO
}
// ç”¨æˆ·ä¿¡æ¯
export type User = {
  id: number
  nickname: string
  avatar: string
}
// å®¡æ‰¹ä»»åŠ¡ä¿¡æ¯
export type ApprovalTaskInfo = {
  id: number
  ownerUser: User
  assigneeUser: User
  status: number
  reason: string
  signPicUrl: string
}
// å®¡æ‰¹èŠ‚ç‚¹ä¿¡æ¯
export type ApprovalNodeInfo = {
  id: number
  name: string
  nodeType: NodeType
  candidateStrategy?: CandidateStrategy
  status: number
  startTime?: Date
  endTime?: Date
  processInstanceId?: string
  candidateUsers?: User[]
  tasks: ApprovalTaskInfo[]
}
export const getProcessInstanceMyPage = async (params: any) => {
  return await request.get({ url: '/bpm/process-instance/my-page', params })
}
export const getProcessInstanceManagerPage = async (params: any) => {
  return await request.get({ url: '/bpm/process-instance/manager-page', params })
}
export const createProcessInstance = async (data) => {
  return await request.post({ url: '/bpm/process-instance/create', data: data })
}
export const cancelProcessInstanceByStartUser = async (id: number, reason: string) => {
  const data = {
    id: id,
    reason: reason
  }
  return await request.delete({ url: '/bpm/process-instance/cancel-by-start-user', data: data })
}
export const cancelProcessInstanceByAdmin = async (id: number, reason: string) => {
  const data = {
    id: id,
    reason: reason
  }
  return await request.delete({ url: '/bpm/process-instance/cancel-by-admin', data: data })
}
export const getProcessInstance = async (id: string) => {
  return await request.get({ url: '/bpm/process-instance/get?id=' + id })
}
export const getProcessInstanceCopyPage = async (params: any) => {
  return await request.get({ url: '/bpm/process-instance/copy/page', params })
}
// èŽ·å–å®¡æ‰¹è¯¦æƒ…
export const getApprovalDetail = async (params: any) => {
  return await request.get({ url: '/bpm/process-instance/get-approval-detail', params })
}
// èŽ·å–ä¸‹ä¸€ä¸ªæ‰§è¡Œçš„æµç¨‹èŠ‚ç‚¹
export const getNextApprovalNodes = async (params: any) => {
  return await request.get({ url: '/bpm/process-instance/get-next-approval-nodes', params })
}
// èŽ·å–è¡¨å•å­—æ®µæƒé™
export const getFormFieldsPermission = async (params: any) => {
  return await request.get({ url: '/bpm/process-instance/get-form-fields-permission', params })
}
// èŽ·å–æµç¨‹å®žä¾‹çš„ BPMN æ¨¡åž‹è§†å›¾
export const getProcessInstanceBpmnModelView = async (id: string) => {
  return await request.get({ url: '/bpm/process-instance/get-bpmn-model-view?id=' + id })
}
// èŽ·å–æµç¨‹å®žä¾‹æ‰“å°æ•°æ®
export const getProcessInstancePrintData = async (id: string) => {
  return await request.get({ url: '/bpm/process-instance/get-print-data?processInstanceId=' + id })
}
src/api/bpm/processListener/index.ts
New file
@@ -0,0 +1,40 @@
import request from '@/config/axios'
// BPM æµç¨‹ç›‘听器 VO
export interface ProcessListenerVO {
  id: number // ç¼–号
  name: string // ç›‘听器名字
  type: string // ç›‘听器类型
  status: number // ç›‘听器状态
  event: string // ç›‘听事件
  valueType: string // ç›‘听器值类型
  value: string // ç›‘听器值
}
// BPM æµç¨‹ç›‘听器 API
export const ProcessListenerApi = {
  // æŸ¥è¯¢æµç¨‹ç›‘听器分页
  getProcessListenerPage: async (params: any) => {
    return await request.get({ url: `/bpm/process-listener/page`, params })
  },
  // æŸ¥è¯¢æµç¨‹ç›‘听器详情
  getProcessListener: async (id: number) => {
    return await request.get({ url: `/bpm/process-listener/get?id=` + id })
  },
  // æ–°å¢žæµç¨‹ç›‘听器
  createProcessListener: async (data: ProcessListenerVO) => {
    return await request.post({ url: `/bpm/process-listener/create`, data })
  },
  // ä¿®æ”¹æµç¨‹ç›‘听器
  updateProcessListener: async (data: ProcessListenerVO) => {
    return await request.put({ url: `/bpm/process-listener/update`, data })
  },
  // åˆ é™¤æµç¨‹ç›‘听器
  deleteProcessListener: async (id: number) => {
    return await request.delete({ url: `/bpm/process-listener/delete?id=` + id })
  }
}
src/api/bpm/simple/index.ts
New file
@@ -0,0 +1,15 @@
import request from '@/config/axios'
export const updateBpmSimpleModel = async (data) => {
  return await request.post({
    url: '/bpm/model/simple/update',
    data: data
  })
}
export const getBpmSimpleModel = async (id) => {
  return await request.get({
    url: '/bpm/model/simple/get?id=' + id
  })
}
src/api/bpm/task/index.ts
New file
@@ -0,0 +1,122 @@
import request from '@/config/axios'
/**
 * ä»»åŠ¡çŠ¶æ€æžšä¸¾
 */
export enum TaskStatusEnum {
  /**
   * è·³è¿‡
   */
  SKIP = -2,
  /**
   * æœªå¼€å§‹
   */
  NOT_START = -1,
  /**
   * å¾…审批
   */
  WAIT = 0,
  /**
   * å®¡æ‰¹ä¸­
   */
  RUNNING = 1,
  /**
   * å®¡æ‰¹é€šè¿‡
   */
  APPROVE = 2,
  /**
   * å®¡æ‰¹ä¸é€šè¿‡
   */
  REJECT = 3,
  /**
   * å·²å–消
   */
  CANCEL = 4,
  /**
   * å·²é€€å›ž
   */
  RETURN = 5,
  /**
   * å®¡æ‰¹é€šè¿‡ä¸­
   */
  APPROVING = 7
}
export const getTaskTodoPage = async (params: any) => {
  return await request.get({ url: '/bpm/task/todo-page', params })
}
export const getTaskDonePage = async (params: any) => {
  return await request.get({ url: '/bpm/task/done-page', params })
}
export const getTaskManagerPage = async (params: any) => {
  return await request.get({ url: '/bpm/task/manager-page', params })
}
export const approveTask = async (data: any) => {
  return await request.put({ url: '/bpm/task/approve', data })
}
export const rejectTask = async (data: any) => {
  return await request.put({ url: '/bpm/task/reject', data })
}
export const getTaskListByProcessInstanceId = async (processInstanceId: string) => {
  return await request.get({
    url: '/bpm/task/list-by-process-instance-id?processInstanceId=' + processInstanceId
  })
}
// èŽ·å–æ‰€æœ‰å¯é€€å›žçš„èŠ‚ç‚¹
export const getTaskListByReturn = async (id: string) => {
  return await request.get({ url: '/bpm/task/list-by-return', params: { id } })
}
// é€€å›ž
export const returnTask = async (data: any) => {
  return await request.put({ url: '/bpm/task/return', data })
}
// å§”æ´¾
export const delegateTask = async (data: any) => {
  return await request.put({ url: '/bpm/task/delegate', data })
}
// è½¬æ´¾
export const transferTask = async (data: any) => {
  return await request.put({ url: '/bpm/task/transfer', data })
}
// åŠ ç­¾
export const signCreateTask = async (data: any) => {
  return await request.put({ url: '/bpm/task/create-sign', data })
}
// å‡ç­¾
export const signDeleteTask = async (data: any) => {
  return await request.delete({ url: '/bpm/task/delete-sign', data })
}
// æŠ„送
export const copyTask = async (data: any) => {
  return await request.put({ url: '/bpm/task/copy', data })
}
// æ’¤å›ž
export const withdrawTask = async (taskId: string) => {
  return await request.put({ url: '/bpm/task/withdraw', params: { taskId } })
}
// èŽ·å–æˆ‘çš„å¾…åŠžä»»åŠ¡
export const myTodoTask = async (processInstanceId: string) => {
  return await request.get({ url: '/bpm/task/my-todo?processInstanceId=' + processInstanceId })
}
// èŽ·å–å‡ç­¾ä»»åŠ¡åˆ—è¡¨
export const getChildrenTaskList = async (id: string) => {
  return await request.get({ url: '/bpm/task/list-by-parent-task-id?parentTaskId=' + id })
}
src/api/bpm/userGroup/index.ts
New file
@@ -0,0 +1,47 @@
import request from '@/config/axios'
export type UserGroupVO = {
  id: number
  name: string
  description: string
  userIds: number[]
  status: number
  remark: string
  createTime: string
}
// åˆ›å»ºç”¨æˆ·ç»„
export const createUserGroup = async (data: UserGroupVO) => {
  return await request.post({
    url: '/bpm/user-group/create',
    data: data
  })
}
// æ›´æ–°ç”¨æˆ·ç»„
export const updateUserGroup = async (data: UserGroupVO) => {
  return await request.put({
    url: '/bpm/user-group/update',
    data: data
  })
}
// åˆ é™¤ç”¨æˆ·ç»„
export const deleteUserGroup = async (id: number) => {
  return await request.delete({ url: '/bpm/user-group/delete?id=' + id })
}
// èŽ·å¾—ç”¨æˆ·ç»„
export const getUserGroup = async (id: number) => {
  return await request.get({ url: '/bpm/user-group/get?id=' + id })
}
// èŽ·å¾—ç”¨æˆ·ç»„åˆ†é¡µ
export const getUserGroupPage = async (params) => {
  return await request.get({ url: '/bpm/user-group/page', params })
}
// èŽ·å–ç”¨æˆ·ç»„ç²¾ç®€ä¿¡æ¯åˆ—è¡¨
export const getUserGroupSimpleList = async (): Promise<UserGroupVO[]> => {
  return await request.get({ url: '/bpm/user-group/simple-list' })
}
src/api/crm/business/index.ts
New file
@@ -0,0 +1,98 @@
import request from '@/config/axios'
import { TransferReqVO } from '@/api/crm/permission'
export interface BusinessVO {
  id: number
  name: string
  customerId: number
  customerName?: string
  followUpStatus: boolean
  contactLastTime: Date
  contactNextTime: Date
  ownerUserId: number
  ownerUserName?: string // è´Ÿè´£äººçš„用户名称
  ownerUserDept?: string // è´Ÿè´£äººçš„部门名称
  statusTypeId: number
  statusTypeName?: string
  statusId: number
  statusName?: string
  endStatus: number
  endRemark: string
  dealTime: Date
  totalProductPrice: number
  totalPrice: number
  discountPercent: number
  remark: string
  creator: string // åˆ›å»ºäºº
  creatorName?: string // åˆ›å»ºäººåç§°
  createTime: Date // åˆ›å»ºæ—¶é—´
  updateTime: Date // æ›´æ–°æ—¶é—´
  products?: [
    {
      id: number
      productId: number
      productName: string
      productNo: string
      productUnit: number
      productPrice: number
      businessPrice: number
      count: number
      totalPrice: number
    }
  ]
}
// æŸ¥è¯¢ CRM å•†æœºåˆ—表
export const getBusinessPage = async (params) => {
  return await request.get({ url: `/crm/business/page`, params })
}
// æŸ¥è¯¢ CRM å•†æœºåˆ—表,基于指定客户
export const getBusinessPageByCustomer = async (params) => {
  return await request.get({ url: `/crm/business/page-by-customer`, params })
}
// æŸ¥è¯¢ CRM å•†æœºè¯¦æƒ…
export const getBusiness = async (id: number) => {
  return await request.get({ url: `/crm/business/get?id=` + id })
}
// èŽ·å¾— CRM å•†æœºåˆ—表(精简)
export const getSimpleBusinessList = async () => {
  return await request.get({ url: `/crm/business/simple-all-list` })
}
// æ–°å¢ž CRM å•†æœº
export const createBusiness = async (data: BusinessVO) => {
  return await request.post({ url: `/crm/business/create`, data })
}
// ä¿®æ”¹ CRM å•†æœº
export const updateBusiness = async (data: BusinessVO) => {
  return await request.put({ url: `/crm/business/update`, data })
}
// ä¿®æ”¹ CRM å•†æœºçŠ¶æ€
export const updateBusinessStatus = async (data: BusinessVO) => {
  return await request.put({ url: `/crm/business/update-status`, data })
}
// åˆ é™¤ CRM å•†æœº
export const deleteBusiness = async (id: number) => {
  return await request.delete({ url: `/crm/business/delete?id=` + id })
}
// å¯¼å‡º CRM å•†æœº Excel
export const exportBusiness = async (params) => {
  return await request.download({ url: `/crm/business/export-excel`, params })
}
// è”系人关联商机列表
export const getBusinessPageByContact = async (params) => {
  return await request.get({ url: `/crm/business/page-by-contact`, params })
}
// å•†æœºè½¬ç§»
export const transferBusiness = async (data: TransferReqVO) => {
  return await request.put({ url: '/crm/business/transfer', data })
}
src/api/crm/business/status/index.ts
New file
@@ -0,0 +1,68 @@
import request from '@/config/axios'
export interface BusinessStatusTypeVO {
  id: number
  name: string
  deptIds: number[]
  statuses?: {
    id: number
    name: string
    percent: number
  }
}
export const DEFAULT_STATUSES = [
  {
    endStatus: 1,
    key: '结束',
    name: '赢单',
    percent: 100
  },
  {
    endStatus: 2,
    key: '结束',
    name: '输单',
    percent: 0
  },
  {
    endStatus: 3,
    key: '结束',
    name: '无效',
    percent: 0
  }
]
// æŸ¥è¯¢å•†æœºçŠ¶æ€ç»„åˆ—è¡¨
export const getBusinessStatusPage = async (params: any) => {
  return await request.get({ url: `/crm/business-status/page`, params })
}
// æ–°å¢žå•†æœºçŠ¶æ€ç»„
export const createBusinessStatus = async (data: BusinessStatusTypeVO) => {
  return await request.post({ url: `/crm/business-status/create`, data })
}
// ä¿®æ”¹å•†æœºçŠ¶æ€ç»„
export const updateBusinessStatus = async (data: BusinessStatusTypeVO) => {
  return await request.put({ url: `/crm/business-status/update`, data })
}
// æŸ¥è¯¢å•†æœºçŠ¶æ€ç±»åž‹è¯¦æƒ…
export const getBusinessStatus = async (id: number) => {
  return await request.get({ url: `/crm/business-status/get?id=` + id })
}
// åˆ é™¤å•†æœºçŠ¶æ€
export const deleteBusinessStatus = async (id: number) => {
  return await request.delete({ url: `/crm/business-status/delete?id=` + id })
}
// èŽ·å¾—å•†æœºçŠ¶æ€ç»„åˆ—è¡¨
export const getBusinessStatusTypeSimpleList = async () => {
  return await request.get({ url: `/crm/business-status/type-simple-list` })
}
// èŽ·å¾—å•†æœºé˜¶æ®µåˆ—è¡¨
export const getBusinessStatusSimpleList = async (typeId: number) => {
  return await request.get({ url: `/crm/business-status/status-simple-list`, params: { typeId } })
}
src/api/crm/clue/index.ts
New file
@@ -0,0 +1,78 @@
import request from '@/config/axios'
import { TransferReqVO } from '@/api/crm/permission'
export interface ClueVO {
  id: number // ç¼–号
  name: string // çº¿ç´¢åç§°
  followUpStatus: boolean // è·Ÿè¿›çŠ¶æ€
  contactLastTime: Date // æœ€åŽè·Ÿè¿›æ—¶é—´
  contactLastContent: string // æœ€åŽè·Ÿè¿›å†…容
  contactNextTime: Date // ä¸‹æ¬¡è”系时间
  ownerUserId: number // è´Ÿè´£äººçš„用户编号
  ownerUserName?: string // è´Ÿè´£äººçš„用户名称
  ownerUserDept?: string // è´Ÿè´£äººçš„部门名称
  transformStatus: boolean // è½¬åŒ–状态
  customerId: number // å®¢æˆ·ç¼–号
  customerName?: string // å®¢æˆ·åç§°
  mobile: string // æ‰‹æœºå·
  telephone: string // ç”µè¯
  qq: string // QQ
  wechat: string // wechat
  email: string // email
  areaId: number // æ‰€åœ¨åœ°
  areaName?: string // æ‰€åœ¨åœ°åç§°
  detailAddress: string // è¯¦ç»†åœ°å€
  industryId: number // æ‰€å±žè¡Œä¸š
  level: number // å®¢æˆ·ç­‰çº§
  source: number // å®¢æˆ·æ¥æº
  remark: string // å¤‡æ³¨
  creator: string // åˆ›å»ºäºº
  creatorName?: string // åˆ›å»ºäººåç§°
  createTime: Date // åˆ›å»ºæ—¶é—´
  updateTime: Date // æ›´æ–°æ—¶é—´
}
// æŸ¥è¯¢çº¿ç´¢åˆ—表
export const getCluePage = async (params: any) => {
  return await request.get({ url: `/crm/clue/page`, params })
}
// æŸ¥è¯¢çº¿ç´¢è¯¦æƒ…
export const getClue = async (id: number) => {
  return await request.get({ url: `/crm/clue/get?id=` + id })
}
// æ–°å¢žçº¿ç´¢
export const createClue = async (data: ClueVO) => {
  return await request.post({ url: `/crm/clue/create`, data })
}
// ä¿®æ”¹çº¿ç´¢
export const updateClue = async (data: ClueVO) => {
  return await request.put({ url: `/crm/clue/update`, data })
}
// åˆ é™¤çº¿ç´¢
export const deleteClue = async (id: number) => {
  return await request.delete({ url: `/crm/clue/delete?id=` + id })
}
// å¯¼å‡ºçº¿ç´¢ Excel
export const exportClue = async (params) => {
  return await request.download({ url: `/crm/clue/export-excel`, params })
}
// çº¿ç´¢è½¬ç§»
export const transferClue = async (data: TransferReqVO) => {
  return await request.put({ url: '/crm/clue/transfer', data })
}
// çº¿ç´¢è½¬åŒ–为客户
export const transformClue = async (id: number) => {
  return await request.put({ url: '/crm/clue/transform', params: { id } })
}
// èŽ·å¾—åˆ†é…ç»™æˆ‘çš„ã€å¾…è·Ÿè¿›çš„çº¿ç´¢æ•°é‡
export const getFollowClueCount = async () => {
  return await request.get({ url: '/crm/clue/follow-count' })
}
src/api/crm/contact/index.ts
New file
@@ -0,0 +1,113 @@
import request from '@/config/axios'
import { TransferReqVO } from '@/api/crm/permission'
export interface ContactVO {
  id: number // ç¼–号
  name: string // è”系人名称
  customerId: number // å®¢æˆ·ç¼–号
  customerName?: string // å®¢æˆ·åç§°
  contactLastTime: Date // æœ€åŽè·Ÿè¿›æ—¶é—´
  contactLastContent: string // æœ€åŽè·Ÿè¿›å†…容
  contactNextTime: Date // ä¸‹æ¬¡è”系时间
  ownerUserId: number // è´Ÿè´£äººçš„用户编号
  ownerUserName?: string // è´Ÿè´£äººçš„用户名称
  ownerUserDept?: string // è´Ÿè´£äººçš„部门名称
  mobile: string // æ‰‹æœºå·
  telephone: string // ç”µè¯
  qq: string // QQ
  wechat: string // wechat
  email: string // email
  areaId: number // æ‰€åœ¨åœ°
  areaName?: string // æ‰€åœ¨åœ°åç§°
  detailAddress: string // è¯¦ç»†åœ°å€
  sex: number // æ€§åˆ«
  master: boolean // æ˜¯å¦ä¸»è”系人
  post: string // èŒåŠ¡
  parentId: number // ä¸Šçº§è”系人编号
  parentName?: string // ä¸Šçº§è”系人名称
  remark: string // å¤‡æ³¨
  creator: string // åˆ›å»ºäºº
  creatorName?: string // åˆ›å»ºäººåç§°
  createTime: Date // åˆ›å»ºæ—¶é—´
  updateTime: Date // æ›´æ–°æ—¶é—´
}
export interface ContactBusinessReqVO {
  contactId: number
  businessIds: number[]
}
export interface ContactBusiness2ReqVO {
  businessId: number
  contactIds: number[]
}
// æŸ¥è¯¢ CRM è”系人列表
export const getContactPage = async (params) => {
  return await request.get({ url: `/crm/contact/page`, params })
}
// æŸ¥è¯¢ CRM è”系人列表,基于指定客户
export const getContactPageByCustomer = async (params: any) => {
  return await request.get({ url: `/crm/contact/page-by-customer`, params })
}
// æŸ¥è¯¢ CRM è”系人列表,基于指定商机
export const getContactPageByBusiness = async (params: any) => {
  return await request.get({ url: `/crm/contact/page-by-business`, params })
}
// æŸ¥è¯¢ CRM è”系人详情
export const getContact = async (id: number) => {
  return await request.get({ url: `/crm/contact/get?id=` + id })
}
// æ–°å¢ž CRM è”系人
export const createContact = async (data: ContactVO) => {
  return await request.post({ url: `/crm/contact/create`, data })
}
// ä¿®æ”¹ CRM è”系人
export const updateContact = async (data: ContactVO) => {
  return await request.put({ url: `/crm/contact/update`, data })
}
// åˆ é™¤ CRM è”系人
export const deleteContact = async (id: number) => {
  return await request.delete({ url: `/crm/contact/delete?id=` + id })
}
// å¯¼å‡º CRM è”系人 Excel
export const exportContact = async (params) => {
  return await request.download({ url: `/crm/contact/export-excel`, params })
}
// èŽ·å¾— CRM è”系人列表(精简)
export const getSimpleContactList = async () => {
  return await request.get({ url: `/crm/contact/simple-all-list` })
}
// æ‰¹é‡æ–°å¢žè”系人商机关联
export const createContactBusinessList = async (data: ContactBusinessReqVO) => {
  return await request.post({ url: `/crm/contact/create-business-list`, data })
}
// æ‰¹é‡æ–°å¢žè”系人商机关联
export const createContactBusinessList2 = async (data: ContactBusiness2ReqVO) => {
  return await request.post({ url: `/crm/contact/create-business-list2`, data })
}
// è§£é™¤è”系人商机关联
export const deleteContactBusinessList = async (data: ContactBusinessReqVO) => {
  return await request.delete({ url: `/crm/contact/delete-business-list`, data })
}
// è§£é™¤è”系人商机关联
export const deleteContactBusinessList2 = async (data: ContactBusiness2ReqVO) => {
  return await request.delete({ url: `/crm/contact/delete-business-list2`, data })
}
// è”系人转移
export const transferContact = async (data: TransferReqVO) => {
  return await request.put({ url: '/crm/contact/transfer', data })
}
src/api/crm/contract/config/index.ts
New file
@@ -0,0 +1,16 @@
import request from '@/config/axios'
export interface ContractConfigVO {
  notifyEnabled?: boolean
  notifyDays?: number
}
// èŽ·å–åˆåŒé…ç½®
export const getContractConfig = async () => {
  return await request.get({ url: `/crm/contract-config/get` })
}
// æ›´æ–°åˆåŒé…ç½®
export const saveContractConfig = async (data: ContractConfigVO) => {
  return await request.put({ url: `/crm/contract-config/save`, data })
}
src/api/crm/contract/index.ts
New file
@@ -0,0 +1,114 @@
import request from '@/config/axios'
import { TransferReqVO } from '@/api/crm/permission'
export interface ContractVO {
  id: number
  name: string
  no: string
  customerId: number
  customerName?: string
  businessId: number
  businessName: string
  contactLastTime: Date
  ownerUserId: number
  ownerUserName?: string
  ownerUserDeptName?: string
  processInstanceId: number
  auditStatus: number
  orderDate: Date
  startTime: Date
  endTime: Date
  totalProductPrice: number
  discountPercent: number
  totalPrice: number
  totalReceivablePrice: number
  signContactId: number
  signContactName?: string
  signUserId: number
  signUserName: string
  remark: string
  createTime?: Date
  creator: string
  creatorName: string
  updateTime?: Date
  products?: [
    {
      id: number
      productId: number
      productName: string
      productNo: string
      productUnit: number
      productPrice: number
      contractPrice: number
      count: number
      totalPrice: number
    }
  ]
}
// æŸ¥è¯¢ CRM åˆåŒåˆ—表
export const getContractPage = async (params) => {
  return await request.get({ url: `/crm/contract/page`, params })
}
// æŸ¥è¯¢ CRM è”系人列表,基于指定客户
export const getContractPageByCustomer = async (params: any) => {
  return await request.get({ url: `/crm/contract/page-by-customer`, params })
}
// æŸ¥è¯¢ CRM è”系人列表,基于指定商机
export const getContractPageByBusiness = async (params: any) => {
  return await request.get({ url: `/crm/contract/page-by-business`, params })
}
// æŸ¥è¯¢ CRM åˆåŒè¯¦æƒ…
export const getContract = async (id: number) => {
  return await request.get({ url: `/crm/contract/get?id=` + id })
}
// æŸ¥è¯¢ CRM åˆåŒä¸‹æ‹‰åˆ—表
export const getContractSimpleList = async (customerId: number) => {
  return await request.get({
    url: `/crm/contract/simple-list?customerId=${customerId}`
  })
}
// æ–°å¢ž CRM åˆåŒ
export const createContract = async (data: ContractVO) => {
  return await request.post({ url: `/crm/contract/create`, data })
}
// ä¿®æ”¹ CRM åˆåŒ
export const updateContract = async (data: ContractVO) => {
  return await request.put({ url: `/crm/contract/update`, data })
}
// åˆ é™¤ CRM åˆåŒ
export const deleteContract = async (id: number) => {
  return await request.delete({ url: `/crm/contract/delete?id=` + id })
}
// å¯¼å‡º CRM åˆåŒ Excel
export const exportContract = async (params) => {
  return await request.download({ url: `/crm/contract/export-excel`, params })
}
// æäº¤å®¡æ ¸
export const submitContract = async (id: number) => {
  return await request.put({ url: `/crm/contract/submit?id=${id}` })
}
// åˆåŒè½¬ç§»
export const transferContract = async (data: TransferReqVO) => {
  return await request.put({ url: '/crm/contract/transfer', data })
}
// èŽ·å¾—å¾…å®¡æ ¸åˆåŒæ•°é‡
export const getAuditContractCount = async () => {
  return await request.get({ url: '/crm/contract/audit-count' })
}
// èŽ·å¾—å³å°†åˆ°æœŸï¼ˆæé†’ï¼‰çš„åˆåŒæ•°é‡
export const getRemindContractCount = async () => {
  return await request.get({ url: '/crm/contract/remind-count' })
}
src/api/crm/customer/index.ts
New file
@@ -0,0 +1,132 @@
import request from '@/config/axios'
import { TransferReqVO } from '@/api/crm/permission'
export interface CustomerVO {
  id: number // ç¼–号
  name: string // å®¢æˆ·åç§°
  followUpStatus: boolean // è·Ÿè¿›çŠ¶æ€
  contactLastTime: Date // æœ€åŽè·Ÿè¿›æ—¶é—´
  contactLastContent: string // æœ€åŽè·Ÿè¿›å†…容
  contactNextTime: Date // ä¸‹æ¬¡è”系时间
  ownerUserId: number // è´Ÿè´£äººçš„用户编号
  ownerUserName?: string // è´Ÿè´£äººçš„用户名称
  ownerUserDept?: string // è´Ÿè´£äººçš„部门名称
  lockStatus?: boolean
  dealStatus?: boolean
  mobile: string // æ‰‹æœºå·
  telephone: string // ç”µè¯
  qq: string // QQ
  wechat: string // wechat
  email: string // email
  areaId: number // æ‰€åœ¨åœ°
  areaName?: string // æ‰€åœ¨åœ°åç§°
  detailAddress: string // è¯¦ç»†åœ°å€
  industryId: number // æ‰€å±žè¡Œä¸š
  level: number // å®¢æˆ·ç­‰çº§
  source: number // å®¢æˆ·æ¥æº
  remark: string // å¤‡æ³¨
  creator: string // åˆ›å»ºäºº
  creatorName?: string // åˆ›å»ºäººåç§°
  createTime: Date // åˆ›å»ºæ—¶é—´
  updateTime: Date // æ›´æ–°æ—¶é—´
}
// æŸ¥è¯¢å®¢æˆ·åˆ—表
export const getCustomerPage = async (params) => {
  return await request.get({ url: `/crm/customer/page`, params })
}
// è¿›å…¥å…¬æµ·å®¢æˆ·æé†’的客户列表
export const getPutPoolRemindCustomerPage = async (params) => {
  return await request.get({ url: `/crm/customer/put-pool-remind-page`, params })
}
// èŽ·å¾—å¾…è¿›å…¥å…¬æµ·å®¢æˆ·æ•°é‡
export const getPutPoolRemindCustomerCount = async () => {
  return await request.get({ url: `/crm/customer/put-pool-remind-count` })
}
// èŽ·å¾—ä»Šæ—¥éœ€è”ç³»å®¢æˆ·æ•°é‡
export const getTodayContactCustomerCount = async () => {
  return await request.get({ url: `/crm/customer/today-contact-count` })
}
// èŽ·å¾—åˆ†é…ç»™æˆ‘ã€å¾…è·Ÿè¿›çš„çº¿ç´¢æ•°é‡çš„å®¢æˆ·æ•°é‡
export const getFollowCustomerCount = async () => {
  return await request.get({ url: `/crm/customer/follow-count` })
}
// æŸ¥è¯¢å®¢æˆ·è¯¦æƒ…
export const getCustomer = async (id: number) => {
  return await request.get({ url: `/crm/customer/get?id=` + id })
}
// æ–°å¢žå®¢æˆ·
export const createCustomer = async (data: CustomerVO) => {
  return await request.post({ url: `/crm/customer/create`, data })
}
// ä¿®æ”¹å®¢æˆ·
export const updateCustomer = async (data: CustomerVO) => {
  return await request.put({ url: `/crm/customer/update`, data })
}
// æ›´æ–°å®¢æˆ·çš„æˆäº¤çŠ¶æ€
export const updateCustomerDealStatus = async (id: number, dealStatus: boolean) => {
  return await request.put({ url: `/crm/customer/update-deal-status`, params: { id, dealStatus } })
}
// åˆ é™¤å®¢æˆ·
export const deleteCustomer = async (id: number) => {
  return await request.delete({ url: `/crm/customer/delete?id=` + id })
}
// å¯¼å‡ºå®¢æˆ· Excel
export const exportCustomer = async (params: any) => {
  return await request.download({ url: `/crm/customer/export-excel`, params })
}
// ä¸‹è½½å®¢æˆ·å¯¼å…¥æ¨¡æ¿
export const importCustomerTemplate = () => {
  return request.download({ url: '/crm/customer/get-import-template' })
}
// å¯¼å…¥å®¢æˆ·
export const handleImport = async (formData) => {
  return await request.upload({ url: `/crm/customer/import`, data: formData })
}
// å®¢æˆ·åˆ—表
export const getCustomerSimpleList = async () => {
  return await request.get({ url: `/crm/customer/simple-list` })
}
// ======================= ä¸šåŠ¡æ“ä½œ =======================
// å®¢æˆ·è½¬ç§»
export const transferCustomer = async (data: TransferReqVO) => {
  return await request.put({ url: '/crm/customer/transfer', data })
}
// é”å®š/解锁客户
export const lockCustomer = async (id: number, lockStatus: boolean) => {
  return await request.put({ url: `/crm/customer/lock`, data: { id, lockStatus } })
}
// é¢†å–公海客户
export const receiveCustomer = async (ids: any[]) => {
  return await request.put({ url: '/crm/customer/receive', params: { ids: ids.join(',') } })
}
// åˆ†é…å…¬æµ·ç»™å¯¹åº”负责人
export const distributeCustomer = async (ids: any[], ownerUserId: number) => {
  return await request.put({
    url: '/crm/customer/distribute',
    data: { ids: ids, ownerUserId }
  })
}
// å®¢æˆ·æ”¾å…¥å…¬æµ·
export const putCustomerPool = async (id: number) => {
  return await request.put({ url: `/crm/customer/put-pool?id=${id}` })
}
src/api/crm/customer/limitConfig/index.ts
New file
@@ -0,0 +1,49 @@
import request from '@/config/axios'
export interface CustomerLimitConfigVO {
  id?: number
  type?: number
  userIds?: string
  deptIds?: string
  maxCount?: number
  dealCountEnabled?: boolean
}
/**
 * å®¢æˆ·é™åˆ¶é…ç½®ç±»åž‹
 */
export enum LimitConfType {
  /**
   * æ‹¥æœ‰å®¢æˆ·æ•°é™åˆ¶
   */
  CUSTOMER_QUANTITY_LIMIT = 1,
  /**
   * é”å®šå®¢æˆ·æ•°é™åˆ¶
   */
  CUSTOMER_LOCK_LIMIT = 2
}
// æŸ¥è¯¢å®¢æˆ·é™åˆ¶é…ç½®åˆ—表
export const getCustomerLimitConfigPage = async (params) => {
  return await request.get({ url: `/crm/customer-limit-config/page`, params })
}
// æŸ¥è¯¢å®¢æˆ·é™åˆ¶é…ç½®è¯¦æƒ…
export const getCustomerLimitConfig = async (id: number) => {
  return await request.get({ url: `/crm/customer-limit-config/get?id=` + id })
}
// æ–°å¢žå®¢æˆ·é™åˆ¶é…ç½®
export const createCustomerLimitConfig = async (data: CustomerLimitConfigVO) => {
  return await request.post({ url: `/crm/customer-limit-config/create`, data })
}
// ä¿®æ”¹å®¢æˆ·é™åˆ¶é…ç½®
export const updateCustomerLimitConfig = async (data: CustomerLimitConfigVO) => {
  return await request.put({ url: `/crm/customer-limit-config/update`, data })
}
// åˆ é™¤å®¢æˆ·é™åˆ¶é…ç½®
export const deleteCustomerLimitConfig = async (id: number) => {
  return await request.delete({ url: `/crm/customer-limit-config/delete?id=` + id })
}
src/api/crm/customer/poolConfig/index.ts
New file
@@ -0,0 +1,19 @@
import request from '@/config/axios'
export interface CustomerPoolConfigVO {
  enabled?: boolean
  contactExpireDays?: number
  dealExpireDays?: number
  notifyEnabled?: boolean
  notifyDays?: number
}
// èŽ·å–å®¢æˆ·å…¬æµ·è§„åˆ™è®¾ç½®
export const getCustomerPoolConfig = async () => {
  return await request.get({ url: `/crm/customer-pool-config/get` })
}
// æ›´æ–°å®¢æˆ·å…¬æµ·è§„则设置
export const saveCustomerPoolConfig = async (data: CustomerPoolConfigVO) => {
  return await request.put({ url: `/crm/customer-pool-config/save`, data })
}
src/api/crm/followup/index.ts
New file
@@ -0,0 +1,43 @@
import request from '@/config/axios'
// è·Ÿè¿›è®°å½• VO
export interface FollowUpRecordVO {
  id: number // ç¼–号
  bizType: number // æ•°æ®ç±»åž‹
  bizId: number // æ•°æ®ç¼–号
  type: number // è·Ÿè¿›ç±»åž‹
  content: string // è·Ÿè¿›å†…容
  picUrls: string[] // å›¾ç‰‡
  fileUrls: string[] // é™„ä»¶
  nextTime: Date // ä¸‹æ¬¡è”系时间
  businessIds: number[] // å…³è”的商机编号数组
  businesses: {
    id: number
    name: string
  }[] // å…³è”的商机数组
  contactIds: number[] // å…³è”的联系人编号数组
  contacts: {
    id: number
    name: string
  }[] // å…³è”的联系人数组
  creator: string
  creatorName?: string
}
// è·Ÿè¿›è®°å½• API
export const FollowUpRecordApi = {
  // æŸ¥è¯¢è·Ÿè¿›è®°å½•分页
  getFollowUpRecordPage: async (params: any) => {
    return await request.get({ url: `/crm/follow-up-record/page`, params })
  },
  // æ–°å¢žè·Ÿè¿›è®°å½•
  createFollowUpRecord: async (data: FollowUpRecordVO) => {
    return await request.post({ url: `/crm/follow-up-record/create`, data })
  },
  // åˆ é™¤è·Ÿè¿›è®°å½•
  deleteFollowUpRecord: async (id: number) => {
    return await request.delete({ url: `/crm/follow-up-record/delete?id=` + id })
  }
}
src/api/crm/operateLog/index.ts
New file
@@ -0,0 +1,11 @@
import request from '@/config/axios'
export interface OperateLogVO extends PageParam {
  bizType: number
  bizId: number
}
// èŽ·å¾—æ“ä½œæ—¥å¿—
export const getOperateLogPage = async (params: OperateLogVO) => {
  return await request.get({ url: `/crm/operate-log/page`, params })
}
src/api/crm/permission/index.ts
New file
@@ -0,0 +1,72 @@
import request from '@/config/axios'
export interface PermissionVO {
  id?: number // æ•°æ®æƒé™ç¼–号
  userId: number // ç”¨æˆ·ç¼–号
  bizType: number // Crm ç±»åž‹
  bizId: number // Crm ç±»åž‹æ•°æ®ç¼–号
  level: number // æƒé™çº§åˆ«
  toBizTypes?: number[] // åŒæ—¶æ·»åŠ è‡³
  deptName?: string // éƒ¨é—¨åç§°
  nickname?: string // ç”¨æˆ·æ˜µç§°
  postNames?: string[] // å²—位名称数组
  createTime?: Date
  ids?: number[]
}
export interface TransferReqVO {
  id: number // æ¨¡å—编号
  newOwnerUserId: number // æ–°è´Ÿè´£äººçš„用户编号
  oldOwnerPermissionLevel?: number // è€è´Ÿè´£äººåŠ å…¥å›¢é˜ŸåŽçš„æƒé™çº§åˆ«
  toBizTypes?: number[] // è½¬ç§»å®¢æˆ·æ—¶ï¼Œéœ€è¦é¢å¤–有【联系人】【商机】【合同】的 checkbox é€‰æ‹©
}
/**
 * CRM ä¸šåŠ¡ç±»åž‹æžšä¸¾
 *
 * @author HUIHUI
 */
export enum BizTypeEnum {
  CRM_CLUE = 1, // çº¿ç´¢
  CRM_CUSTOMER = 2, // å®¢æˆ·
  CRM_CONTACT = 3, // è”系人
  CRM_BUSINESS = 4, // å•†æœº
  CRM_CONTRACT = 5, // åˆåŒ
  CRM_PRODUCT = 6, // äº§å“
  CRM_RECEIVABLE = 7, // å›žæ¬¾
  CRM_RECEIVABLE_PLAN = 8 // å›žæ¬¾è®¡åˆ’
}
/**
 * CRM æ•°æ®æƒé™çº§åˆ«æžšä¸¾
 */
export enum PermissionLevelEnum {
  OWNER = 1, // è´Ÿè´£äºº
  READ = 2, // åªè¯»
  WRITE = 3 // è¯»å†™
}
// èŽ·å¾—æ•°æ®æƒé™åˆ—è¡¨ï¼ˆæŸ¥è¯¢å›¢é˜Ÿæˆå‘˜åˆ—è¡¨ï¼‰
export const getPermissionList = async (params) => {
  return await request.get({ url: `/crm/permission/list`, params })
}
// åˆ›å»ºæ•°æ®æƒé™ï¼ˆæ–°å¢žå›¢é˜Ÿæˆå‘˜ï¼‰
export const createPermission = async (data: PermissionVO) => {
  return await request.post({ url: `/crm/permission/create`, data })
}
// ç¼–辑数据权限(修改团队成员权限级别)
export const updatePermission = async (data) => {
  return await request.put({ url: `/crm/permission/update`, data })
}
// åˆ é™¤æ•°æ®æƒé™ï¼ˆåˆ é™¤å›¢é˜Ÿæˆå‘˜ï¼‰
export const deletePermissionBatch = async (val: number[]) => {
  return await request.delete({ url: '/crm/permission/delete?ids=' + val.join(',') })
}
// åˆ é™¤è‡ªå·±çš„æ•°æ®æƒé™ï¼ˆé€€å‡ºå›¢é˜Ÿï¼‰
export const deleteSelfPermission = async (id: number) => {
  return await request.delete({ url: '/crm/permission/delete-self?id=' + id })
}
src/api/crm/product/category/index.ts
New file
@@ -0,0 +1,33 @@
import request from '@/config/axios'
// TODO @zange:挪到 product ä¸‹ï¼Œå»ºä¸ª category åŒ…,挪进去哈;
export interface ProductCategoryVO {
  id: number
  name: string
  parentId: number
}
// æŸ¥è¯¢äº§å“åˆ†ç±»è¯¦æƒ…
export const getProductCategory = async (id: number) => {
  return await request.get({ url: `/crm/product-category/get?id=` + id })
}
// æ–°å¢žäº§å“åˆ†ç±»
export const createProductCategory = async (data: ProductCategoryVO) => {
  return await request.post({ url: `/crm/product-category/create`, data })
}
// ä¿®æ”¹äº§å“åˆ†ç±»
export const updateProductCategory = async (data: ProductCategoryVO) => {
  return await request.put({ url: `/crm/product-category/update`, data })
}
// åˆ é™¤äº§å“åˆ†ç±»
export const deleteProductCategory = async (id: number) => {
  return await request.delete({ url: `/crm/product-category/delete?id=` + id })
}
// äº§å“åˆ†ç±»åˆ—表
export const getProductCategoryList = async (params) => {
  return await request.get({ url: `/crm/product-category/list`, params })
}
src/api/crm/product/index.ts
New file
@@ -0,0 +1,49 @@
import request from '@/config/axios'
export interface ProductVO {
  id: number
  name: string
  no: string
  unit: number
  price: number
  status: number
  categoryId: number
  categoryName?: string
  description: string
  ownerUserId: number
}
// æŸ¥è¯¢äº§å“åˆ—表
export const getProductPage = async (params) => {
  return await request.get({ url: `/crm/product/page`, params })
}
// èŽ·å¾—äº§å“ç²¾ç®€åˆ—è¡¨
export const getProductSimpleList = async () => {
  return await request.get({ url: `/crm/product/simple-list` })
}
// æŸ¥è¯¢äº§å“è¯¦æƒ…
export const getProduct = async (id: number) => {
  return await request.get({ url: `/crm/product/get?id=` + id })
}
// æ–°å¢žäº§å“
export const createProduct = async (data: ProductVO) => {
  return await request.post({ url: `/crm/product/create`, data })
}
// ä¿®æ”¹äº§å“
export const updateProduct = async (data: ProductVO) => {
  return await request.put({ url: `/crm/product/update`, data })
}
// åˆ é™¤äº§å“
export const deleteProduct = async (id: number) => {
  return await request.delete({ url: `/crm/product/delete?id=` + id })
}
// å¯¼å‡ºäº§å“ Excel
export const exportProduct = async (params) => {
  return await request.download({ url: `/crm/product/export-excel`, params })
}
src/api/crm/receivable/index.ts
New file
@@ -0,0 +1,73 @@
import request from '@/config/axios'
export interface ReceivableVO {
  id: number
  no: string
  planId?: number
  customerId?: number
  customerName?: string
  contractId?: number
  contract?: {
    id?: number
    name?: string
    no: string
    totalPrice: number
  }
  auditStatus: number
  processInstanceId: number
  returnTime: Date
  returnType: number
  price: number
  ownerUserId: number
  ownerUserName?: string
  remark: string
  creator: string // åˆ›å»ºäºº
  creatorName?: string // åˆ›å»ºäººåç§°
  createTime: Date // åˆ›å»ºæ—¶é—´
  updateTime: Date // æ›´æ–°æ—¶é—´
}
// æŸ¥è¯¢å›žæ¬¾åˆ—表
export const getReceivablePage = async (params) => {
  return await request.get({ url: `/crm/receivable/page`, params })
}
// æŸ¥è¯¢å›žæ¬¾åˆ—表
export const getReceivablePageByCustomer = async (params) => {
  return await request.get({ url: `/crm/receivable/page-by-customer`, params })
}
// æŸ¥è¯¢å›žæ¬¾è¯¦æƒ…
export const getReceivable = async (id: number) => {
  return await request.get({ url: `/crm/receivable/get?id=` + id })
}
// æ–°å¢žå›žæ¬¾
export const createReceivable = async (data: ReceivableVO) => {
  return await request.post({ url: `/crm/receivable/create`, data })
}
// ä¿®æ”¹å›žæ¬¾
export const updateReceivable = async (data: ReceivableVO) => {
  return await request.put({ url: `/crm/receivable/update`, data })
}
// åˆ é™¤å›žæ¬¾
export const deleteReceivable = async (id: number) => {
  return await request.delete({ url: `/crm/receivable/delete?id=` + id })
}
// å¯¼å‡ºå›žæ¬¾ Excel
export const exportReceivable = async (params) => {
  return await request.download({ url: `/crm/receivable/export-excel`, params })
}
// æäº¤å®¡æ ¸
export const submitReceivable = async (id: number) => {
  return await request.put({ url: `/crm/receivable/submit?id=${id}` })
}
// èŽ·å¾—å¾…å®¡æ ¸å›žæ¬¾æ•°é‡
export const getAuditReceivableCount = async () => {
  return await request.get({ url: '/crm/receivable/audit-count' })
}
src/api/crm/receivable/plan/index.ts
New file
@@ -0,0 +1,74 @@
import request from '@/config/axios'
export interface ReceivablePlanVO {
  id: number
  period: number
  receivableId: number
  price: number
  returnTime: Date
  remindDays: number
  returnType: number
  remindTime: Date
  customerId: number
  customerName?: string
  contractId?: number
  contractNo?: string
  ownerUserId: number
  ownerUserName?: string
  remark: string
  creator: string // åˆ›å»ºäºº
  creatorName?: string // åˆ›å»ºäººåç§°
  createTime: Date // åˆ›å»ºæ—¶é—´
  updateTime: Date // æ›´æ–°æ—¶é—´
  receivable?: {
    price: number
    returnTime: Date
  }
}
// æŸ¥è¯¢å›žæ¬¾è®¡åˆ’列表
export const getReceivablePlanPage = async (params) => {
  return await request.get({ url: `/crm/receivable-plan/page`, params })
}
// æŸ¥è¯¢å›žæ¬¾è®¡åˆ’列表
export const getReceivablePlanPageByCustomer = async (params) => {
  return await request.get({ url: `/crm/receivable-plan/page-by-customer`, params })
}
// æŸ¥è¯¢å›žæ¬¾è®¡åˆ’详情
export const getReceivablePlan = async (id: number) => {
  return await request.get({ url: `/crm/receivable-plan/get?id=` + id })
}
// æŸ¥è¯¢å›žæ¬¾è®¡åˆ’下拉数据
export const getReceivablePlanSimpleList = async (customerId: number, contractId: number) => {
  return await request.get({
    url: `/crm/receivable-plan/simple-list?customerId=${customerId}&contractId=${contractId}`
  })
}
// æ–°å¢žå›žæ¬¾è®¡åˆ’
export const createReceivablePlan = async (data: ReceivablePlanVO) => {
  return await request.post({ url: `/crm/receivable-plan/create`, data })
}
// ä¿®æ”¹å›žæ¬¾è®¡åˆ’
export const updateReceivablePlan = async (data: ReceivablePlanVO) => {
  return await request.put({ url: `/crm/receivable-plan/update`, data })
}
// åˆ é™¤å›žæ¬¾è®¡åˆ’
export const deleteReceivablePlan = async (id: number) => {
  return await request.delete({ url: `/crm/receivable-plan/delete?id=` + id })
}
// å¯¼å‡ºå›žæ¬¾è®¡åˆ’ Excel
export const exportReceivablePlan = async (params) => {
  return await request.download({ url: `/crm/receivable-plan/export-excel`, params })
}
// èŽ·å¾—å¾…å›žæ¬¾æé†’æ•°é‡
export const getReceivablePlanRemindCount = async () => {
  return await request.get({ url: '/crm/receivable-plan/remind-count' })
}
src/api/crm/statistics/customer.ts
New file
@@ -0,0 +1,168 @@
import request from '@/config/axios'
export interface CrmStatisticsCustomerSummaryByDateRespVO {
  time: string
  customerCreateCount: number
  customerDealCount: number
}
export interface CrmStatisticsCustomerSummaryByUserRespVO {
  ownerUserName: string
  customerCreateCount: number
  customerDealCount: number
  contractPrice: number
  receivablePrice: number
}
export interface CrmStatisticsFollowUpSummaryByDateRespVO {
  time: string
  followUpRecordCount: number
  followUpCustomerCount: number
}
export interface CrmStatisticsFollowUpSummaryByUserRespVO {
  ownerUserName: string
  followupRecordCount: number
  followupCustomerCount: number
}
export interface CrmStatisticsFollowUpSummaryByTypeRespVO {
  followUpType: string
  followUpRecordCount: number
}
export interface CrmStatisticsCustomerContractSummaryRespVO {
  customerName: string
  contractName: string
  totalPrice: number
  receivablePrice: number
  customerType: string
  customerSource: string
  ownerUserName: string
  creatorUserName: string
  createTime: Date
  orderDate: Date
}
export interface CrmStatisticsPoolSummaryByDateRespVO {
  time: string
  customerPutCount: number
  customerTakeCount: number
}
export interface CrmStatisticsPoolSummaryByUserRespVO {
  ownerUserName: string
  customerPutCount: number
  customerTakeCount: number
}
export interface CrmStatisticsCustomerDealCycleByDateRespVO {
  time: string
  customerDealCycle: number
}
export interface CrmStatisticsCustomerDealCycleByUserRespVO {
  ownerUserName: string
  customerDealCycle: number
  customerDealCount: number
}
export interface CrmStatisticsCustomerDealCycleByAreaRespVO {
  areaName: string
  customerDealCycle: number
  customerDealCount: number
}
export interface CrmStatisticsCustomerDealCycleByProductRespVO {
  productName: string
  customerDealCycle: number
  customerDealCount: number
}
// å®¢æˆ·åˆ†æž API
export const StatisticsCustomerApi = {
  // 1.1 å®¢æˆ·æ€»é‡åˆ†æž(按日期)
  getCustomerSummaryByDate: (params: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-customer-summary-by-date',
      params
    })
  },
  // 1.2 å®¢æˆ·æ€»é‡åˆ†æž(按用户)
  getCustomerSummaryByUser: (params: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-customer-summary-by-user',
      params
    })
  },
  // 2.1 å®¢æˆ·è·Ÿè¿›æ¬¡æ•°åˆ†æž(按日期)
  getFollowUpSummaryByDate: (params: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-follow-up-summary-by-date',
      params
    })
  },
  // 2.2 å®¢æˆ·è·Ÿè¿›æ¬¡æ•°åˆ†æž(按用户)
  getFollowUpSummaryByUser: (params: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-follow-up-summary-by-user',
      params
    })
  },
  // 3.1 èŽ·å–å®¢æˆ·è·Ÿè¿›æ–¹å¼ç»Ÿè®¡æ•°
  getFollowUpSummaryByType: (params: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-follow-up-summary-by-type',
      params
    })
  },
  // 4.1 åˆåŒæ‘˜è¦ä¿¡æ¯(客户转化率页面)
  getContractSummary: (params: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-contract-summary',
      params
    })
  },
  // 5.1 èŽ·å–å®¢æˆ·å…¬æµ·åˆ†æž(按日期)
  getPoolSummaryByDate: (param: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-pool-summary-by-date',
      params: param
    })
  },
  // 5.2 èŽ·å–å®¢æˆ·å…¬æµ·åˆ†æž(按用户)
  getPoolSummaryByUser: (param: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-pool-summary-by-user',
      params: param
    })
  },
  // 6.1 èŽ·å–å®¢æˆ·æˆäº¤å‘¨æœŸ(按日期)
  getCustomerDealCycleByDate: (params: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-customer-deal-cycle-by-date',
      params
    })
  },
  // 6.2 èŽ·å–å®¢æˆ·æˆäº¤å‘¨æœŸ(按用户)
  getCustomerDealCycleByUser: (params: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-customer-deal-cycle-by-user',
      params
    })
  },
  // 6.2 èŽ·å–å®¢æˆ·æˆäº¤å‘¨æœŸ(按用户)
  getCustomerDealCycleByArea: (params: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-customer-deal-cycle-by-area',
      params
    })
  },
  // 6.2 èŽ·å–å®¢æˆ·æˆäº¤å‘¨æœŸ(按用户)
  getCustomerDealCycleByProduct: (params: any) => {
    return request.get({
      url: '/crm/statistics-customer/get-customer-deal-cycle-by-product',
      params
    })
  }
}
src/api/crm/statistics/funnel.ts
New file
@@ -0,0 +1,58 @@
import request from '@/config/axios'
export interface CrmStatisticFunnelRespVO {
  customerCount: number // å®¢æˆ·æ•°
  businessCount: number // å•†æœºæ•°
  businessWinCount: number // èµ¢å•æ•°
}
export interface CrmStatisticsBusinessSummaryByDateRespVO {
  time: string // æ—¶é—´
  businessCreateCount: number // å•†æœºæ•°
  totalPrice: number | string // å•†æœºé‡‘额
}
export interface CrmStatisticsBusinessInversionRateSummaryByDateRespVO {
  time: string // æ—¶é—´
  businessCount: number // å•†æœºæ•°é‡
  businessWinCount: number // èµ¢å•商机数
}
// å®¢æˆ·åˆ†æž API
export const StatisticFunnelApi = {
  // 1. èŽ·å–é”€å”®æ¼æ–—ç»Ÿè®¡æ•°æ®
  getFunnelSummary: (params: any) => {
    return request.get({
      url: '/crm/statistics-funnel/get-funnel-summary',
      params
    })
  },
  // 2. èŽ·å–å•†æœºç»“æŸçŠ¶æ€ç»Ÿè®¡
  getBusinessSummaryByEndStatus: (params: any) => {
    return request.get({
      url: '/crm/statistics-funnel/get-business-summary-by-end-status',
      params
    })
  },
  // 3. èŽ·å–æ–°å¢žå•†æœºåˆ†æž(按日期)
  getBusinessSummaryByDate: (params: any) => {
    return request.get({
      url: '/crm/statistics-funnel/get-business-summary-by-date',
      params
    })
  },
  // 4. èŽ·å–å•†æœºè½¬åŒ–çŽ‡åˆ†æž(按日期)
  getBusinessInversionRateSummaryByDate: (params: any) => {
    return request.get({
      url: '/crm/statistics-funnel/get-business-inversion-rate-summary-by-date',
      params
    })
  },
  // 5. èŽ·å–å•†æœºåˆ—è¡¨(按日期)
  getBusinessPageByDate: (params: any) => {
    return request.get({
      url: '/crm/statistics-funnel/get-business-page-by-date',
      params
    })
  }
}
src/api/crm/statistics/performance.ts
New file
@@ -0,0 +1,33 @@
import request from '@/config/axios'
export interface StatisticsPerformanceRespVO {
  time: string
  currentMonthCount: number
  lastMonthCount: number
  lastYearCount: number
}
// æŽ’行 API
export const StatisticsPerformanceApi = {
  // å‘˜å·¥èŽ·å¾—åˆåŒé‡‘é¢ç»Ÿè®¡
  getContractPricePerformance: (params: any) => {
    return request.get({
      url: '/crm/statistics-performance/get-contract-price-performance',
      params
    })
  },
  // å‘˜å·¥èŽ·å¾—å›žæ¬¾ç»Ÿè®¡
  getReceivablePricePerformance: (params: any) => {
    return request.get({
      url: '/crm/statistics-performance/get-receivable-price-performance',
      params
    })
  },
  //员工获得签约合同数量统计
  getContractCountPerformance: (params: any) => {
    return request.get({
      url: '/crm/statistics-performance/get-contract-count-performance',
      params
    })
  }
}
src/api/crm/statistics/portrait.ts
New file
@@ -0,0 +1,60 @@
import request from '@/config/axios'
export interface CrmStatisticCustomerBaseRespVO {
  customerCount: number
  dealCount: number
  dealPortion: string | number
}
export interface CrmStatisticCustomerIndustryRespVO extends CrmStatisticCustomerBaseRespVO {
  industryId: number
  industryPortion: string | number
}
export interface CrmStatisticCustomerSourceRespVO extends CrmStatisticCustomerBaseRespVO {
  source: number
  sourcePortion: string | number
}
export interface CrmStatisticCustomerLevelRespVO extends CrmStatisticCustomerBaseRespVO {
  level: number
  levelPortion: string | number
}
export interface CrmStatisticCustomerAreaRespVO extends CrmStatisticCustomerBaseRespVO {
  areaId: number
  areaName: string
  areaPortion: string | number
}
// å®¢æˆ·åˆ†æž API
export const StatisticsPortraitApi = {
  // 1. èŽ·å–å®¢æˆ·è¡Œä¸šç»Ÿè®¡æ•°æ®
  getCustomerIndustry: (params: any) => {
    return request.get({
      url: '/crm/statistics-portrait/get-customer-industry-summary',
      params
    })
  },
  // 2. èŽ·å–å®¢æˆ·æ¥æºç»Ÿè®¡æ•°æ®
  getCustomerSource: (params: any) => {
    return request.get({
      url: '/crm/statistics-portrait/get-customer-source-summary',
      params
    })
  },
  // 3. èŽ·å–å®¢æˆ·çº§åˆ«ç»Ÿè®¡æ•°æ®
  getCustomerLevel: (params: any) => {
    return request.get({
      url: '/crm/statistics-portrait/get-customer-level-summary',
      params
    })
  },
  // 4. èŽ·å–å®¢æˆ·åœ°åŒºç»Ÿè®¡æ•°æ®
  getCustomerArea: (params: any) => {
    return request.get({
      url: '/crm/statistics-portrait/get-customer-area-summary',
      params
    })
  }
}
src/api/crm/statistics/rank.ts
New file
@@ -0,0 +1,67 @@
import request from '@/config/axios'
export interface StatisticsRankRespVO {
  count: number
  nickname: string
  deptName: string
}
// æŽ’行 API
export const StatisticsRankApi = {
  // èŽ·å¾—åˆåŒæŽ’è¡Œæ¦œ
  getContractPriceRank: (params: any) => {
    return request.get({
      url: '/crm/statistics-rank/get-contract-price-rank',
      params
    })
  },
  // èŽ·å¾—å›žæ¬¾æŽ’è¡Œæ¦œ
  getReceivablePriceRank: (params: any) => {
    return request.get({
      url: '/crm/statistics-rank/get-receivable-price-rank',
      params
    })
  },
  // ç­¾çº¦åˆåŒæŽ’行
  getContractCountRank: (params: any) => {
    return request.get({
      url: '/crm/statistics-rank/get-contract-count-rank',
      params
    })
  },
  // äº§å“é”€é‡æŽ’行
  getProductSalesRank: (params: any) => {
    return request.get({
      url: '/crm/statistics-rank/get-product-sales-rank',
      params
    })
  },
  // æ–°å¢žå®¢æˆ·æ•°æŽ’行
  getCustomerCountRank: (params: any) => {
    return request.get({
      url: '/crm/statistics-rank/get-customer-count-rank',
      params
    })
  },
  // æ–°å¢žè”系人数排行
  getContactsCountRank: (params: any) => {
    return request.get({
      url: '/crm/statistics-rank/get-contacts-count-rank',
      params
    })
  },
  // è·Ÿè¿›æ¬¡æ•°æŽ’行
  getFollowCountRank: (params: any) => {
    return request.get({
      url: '/crm/statistics-rank/get-follow-count-rank',
      params
    })
  },
  // è·Ÿè¿›å®¢æˆ·æ•°æŽ’行
  getFollowCustomerCountRank: (params: any) => {
    return request.get({
      url: '/crm/statistics-rank/get-follow-customer-count-rank',
      params
    })
  }
}
src/api/erp/finance/account/index.ts
New file
@@ -0,0 +1,61 @@
import request from '@/config/axios'
// ERP ç»“算账户 VO
export interface AccountVO {
  id: number // ç»“算账户编号
  no: string // è´¦æˆ·ç¼–码
  remark: string // å¤‡æ³¨
  status: number // å¼€å¯çŠ¶æ€
  sort: number // æŽ’序
  defaultStatus: boolean // æ˜¯å¦é»˜è®¤
  name: string // è´¦æˆ·åç§°
}
// ERP ç»“算账户 API
export const AccountApi = {
  // æŸ¥è¯¢ç»“算账户分页
  getAccountPage: async (params: any) => {
    return await request.get({ url: `/erp/account/page`, params })
  },
  // æŸ¥è¯¢ç»“算账户精简列表
  getAccountSimpleList: async () => {
    return await request.get({ url: `/erp/account/simple-list` })
  },
  // æŸ¥è¯¢ç»“算账户详情
  getAccount: async (id: number) => {
    return await request.get({ url: `/erp/account/get?id=` + id })
  },
  // æ–°å¢žç»“算账户
  createAccount: async (data: AccountVO) => {
    return await request.post({ url: `/erp/account/create`, data })
  },
  // ä¿®æ”¹ç»“算账户
  updateAccount: async (data: AccountVO) => {
    return await request.put({ url: `/erp/account/update`, data })
  },
  // ä¿®æ”¹ç»“算账户默认状态
  updateAccountDefaultStatus: async (id: number, defaultStatus: boolean) => {
    return await request.put({
      url: `/erp/account/update-default-status`,
      params: {
        id,
        defaultStatus
      }
    })
  },
  // åˆ é™¤ç»“算账户
  deleteAccount: async (id: number) => {
    return await request.delete({ url: `/erp/account/delete?id=` + id })
  },
  // å¯¼å‡ºç»“算账户 Excel
  exportAccount: async (params: any) => {
    return await request.download({ url: `/erp/account/export-excel`, params })
  }
}
src/api/erp/finance/payment/index.ts
New file
@@ -0,0 +1,61 @@
import request from '@/config/axios'
// ERP ä»˜æ¬¾å• VO
export interface FinancePaymentVO {
  id: number // ä»˜æ¬¾å•编号
  no: string // ä»˜æ¬¾å•号
  supplierId: number // ä¾›åº”商编号
  paymentTime: Date // ä»˜æ¬¾æ—¶é—´
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
}
// ERP ä»˜æ¬¾å• API
export const FinancePaymentApi = {
  // æŸ¥è¯¢ä»˜æ¬¾å•分页
  getFinancePaymentPage: async (params: any) => {
    return await request.get({ url: `/erp/finance-payment/page`, params })
  },
  // æŸ¥è¯¢ä»˜æ¬¾å•详情
  getFinancePayment: async (id: number) => {
    return await request.get({ url: `/erp/finance-payment/get?id=` + id })
  },
  // æ–°å¢žä»˜æ¬¾å•
  createFinancePayment: async (data: FinancePaymentVO) => {
    return await request.post({ url: `/erp/finance-payment/create`, data })
  },
  // ä¿®æ”¹ä»˜æ¬¾å•
  updateFinancePayment: async (data: FinancePaymentVO) => {
    return await request.put({ url: `/erp/finance-payment/update`, data })
  },
  // æ›´æ–°ä»˜æ¬¾å•的状态
  updateFinancePaymentStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/finance-payment/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤ä»˜æ¬¾å•
  deleteFinancePayment: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/finance-payment/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºä»˜æ¬¾å• Excel
  exportFinancePayment: async (params: any) => {
    return await request.download({ url: `/erp/finance-payment/export-excel`, params })
  }
}
src/api/erp/finance/receipt/index.ts
New file
@@ -0,0 +1,61 @@
import request from '@/config/axios'
// ERP æ”¶æ¬¾å• VO
export interface FinanceReceiptVO {
  id: number // æ”¶æ¬¾å•编号
  no: string // æ”¶æ¬¾å•号
  customerId: number // å®¢æˆ·ç¼–号
  receiptTime: Date // æ”¶æ¬¾æ—¶é—´
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
}
// ERP æ”¶æ¬¾å• API
export const FinanceReceiptApi = {
  // æŸ¥è¯¢æ”¶æ¬¾å•分页
  getFinanceReceiptPage: async (params: any) => {
    return await request.get({ url: `/erp/finance-receipt/page`, params })
  },
  // æŸ¥è¯¢æ”¶æ¬¾å•详情
  getFinanceReceipt: async (id: number) => {
    return await request.get({ url: `/erp/finance-receipt/get?id=` + id })
  },
  // æ–°å¢žæ”¶æ¬¾å•
  createFinanceReceipt: async (data: FinanceReceiptVO) => {
    return await request.post({ url: `/erp/finance-receipt/create`, data })
  },
  // ä¿®æ”¹æ”¶æ¬¾å•
  updateFinanceReceipt: async (data: FinanceReceiptVO) => {
    return await request.put({ url: `/erp/finance-receipt/update`, data })
  },
  // æ›´æ–°æ”¶æ¬¾å•的状态
  updateFinanceReceiptStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/finance-receipt/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤æ”¶æ¬¾å•
  deleteFinanceReceipt: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/finance-receipt/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºæ”¶æ¬¾å• Excel
  exportFinanceReceipt: async (params: any) => {
    return await request.download({ url: `/erp/finance-receipt/export-excel`, params })
  }
}
src/api/erp/product/category/index.ts
New file
@@ -0,0 +1,49 @@
import request from '@/config/axios'
// ERP äº§å“åˆ†ç±» VO
export interface ProductCategoryVO {
  id: number // åˆ†ç±»ç¼–号
  parentId: number // çˆ¶åˆ†ç±»ç¼–号
  name: string // åˆ†ç±»åç§°
  code: string // åˆ†ç±»ç¼–码
  sort: number // åˆ†ç±»æŽ’序
  status: number // å¼€å¯çŠ¶æ€
}
// ERP äº§å“åˆ†ç±» API
export const ProductCategoryApi = {
  // æŸ¥è¯¢äº§å“åˆ†ç±»åˆ—表
  getProductCategoryList: async () => {
    return await request.get({ url: `/erp/product-category/list` })
  },
  // æŸ¥è¯¢äº§å“åˆ†ç±»ç²¾ç®€åˆ—表
  getProductCategorySimpleList: async () => {
    return await request.get({ url: `/erp/product-category/simple-list` })
  },
  // æŸ¥è¯¢äº§å“åˆ†ç±»è¯¦æƒ…
  getProductCategory: async (id: number) => {
    return await request.get({ url: `/erp/product-category/get?id=` + id })
  },
  // æ–°å¢žäº§å“åˆ†ç±»
  createProductCategory: async (data: ProductCategoryVO) => {
    return await request.post({ url: `/erp/product-category/create`, data })
  },
  // ä¿®æ”¹äº§å“åˆ†ç±»
  updateProductCategory: async (data: ProductCategoryVO) => {
    return await request.put({ url: `/erp/product-category/update`, data })
  },
  // åˆ é™¤äº§å“åˆ†ç±»
  deleteProductCategory: async (id: number) => {
    return await request.delete({ url: `/erp/product-category/delete?id=` + id })
  },
  // å¯¼å‡ºäº§å“åˆ†ç±» Excel
  exportProductCategory: async (params) => {
    return await request.download({ url: `/erp/product-category/export-excel`, params })
  }
}
src/api/erp/product/product/index.ts
New file
@@ -0,0 +1,57 @@
import request from '@/config/axios'
// ERP äº§å“ VO
export interface ProductVO {
  id: number // äº§å“ç¼–号
  name: string // äº§å“åç§°
  barCode: string // äº§å“æ¡ç 
  categoryId: number // äº§å“ç±»åž‹ç¼–号
  unitId: number // å•位编号
  unitName?: string // å•位名字
  status: number // äº§å“çŠ¶æ€
  standard: string // äº§å“è§„æ ¼
  remark: string // äº§å“å¤‡æ³¨
  expiryDay: number // ä¿è´¨æœŸå¤©æ•°
  weight: number // é‡é‡ï¼ˆkg)
  purchasePrice: number // é‡‡è´­ä»·æ ¼ï¼Œå•位:元
  salePrice: number // é”€å”®ä»·æ ¼ï¼Œå•位:元
  minPrice: number // æœ€ä½Žä»·æ ¼ï¼Œå•位:元
}
// ERP äº§å“ API
export const ProductApi = {
  // æŸ¥è¯¢äº§å“åˆ†é¡µ
  getProductPage: async (params: any) => {
    return await request.get({ url: `/erp/product/page`, params })
  },
  // æŸ¥è¯¢äº§å“ç²¾ç®€åˆ—表
  getProductSimpleList: async () => {
    return await request.get({ url: `/erp/product/simple-list` })
  },
  // æŸ¥è¯¢äº§å“è¯¦æƒ…
  getProduct: async (id: number) => {
    return await request.get({ url: `/erp/product/get?id=` + id })
  },
  // æ–°å¢žäº§å“
  createProduct: async (data: ProductVO) => {
    return await request.post({ url: `/erp/product/create`, data })
  },
  // ä¿®æ”¹äº§å“
  updateProduct: async (data: ProductVO) => {
    return await request.put({ url: `/erp/product/update`, data })
  },
  // åˆ é™¤äº§å“
  deleteProduct: async (id: number) => {
    return await request.delete({ url: `/erp/product/delete?id=` + id })
  },
  // å¯¼å‡ºäº§å“ Excel
  exportProduct: async (params) => {
    return await request.download({ url: `/erp/product/export-excel`, params })
  }
}
src/api/erp/product/unit/index.ts
New file
@@ -0,0 +1,46 @@
import request from '@/config/axios'
// ERP äº§å“å•位 VO
export interface ProductUnitVO {
  id: number // å•位编号
  name: string // å•位名字
  status: number // å•位状态
}
// ERP äº§å“å•位 API
export const ProductUnitApi = {
  // æŸ¥è¯¢äº§å“å•位分页
  getProductUnitPage: async (params: any) => {
    return await request.get({ url: `/erp/product-unit/page`, params })
  },
  // æŸ¥è¯¢äº§å“å•位精简列表
  getProductUnitSimpleList: async () => {
    return await request.get({ url: `/erp/product-unit/simple-list` })
  },
  // æŸ¥è¯¢äº§å“å•位详情
  getProductUnit: async (id: number) => {
    return await request.get({ url: `/erp/product-unit/get?id=` + id })
  },
  // æ–°å¢žäº§å“å•位
  createProductUnit: async (data: ProductUnitVO) => {
    return await request.post({ url: `/erp/product-unit/create`, data })
  },
  // ä¿®æ”¹äº§å“å•位
  updateProductUnit: async (data: ProductUnitVO) => {
    return await request.put({ url: `/erp/product-unit/update`, data })
  },
  // åˆ é™¤äº§å“å•位
  deleteProductUnit: async (id: number) => {
    return await request.delete({ url: `/erp/product-unit/delete?id=` + id })
  },
  // å¯¼å‡ºäº§å“å•位 Excel
  exportProductUnit: async (params) => {
    return await request.download({ url: `/erp/product-unit/export-excel`, params })
  }
}
src/api/erp/purchase/in/index.ts
New file
@@ -0,0 +1,64 @@
import request from '@/config/axios'
// ERP é‡‡è´­å…¥åº“ VO
export interface PurchaseInVO {
  id: number // å…¥åº“工单编号
  no: string // é‡‡è´­å…¥åº“号
  customerId: number // å®¢æˆ·ç¼–号
  inTime: Date // å…¥åº“æ—¶é—´
  totalCount: number // åˆè®¡æ•°é‡
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
  outCount: number // é‡‡è´­å‡ºåº“数量
  returnCount: number // é‡‡è´­é€€è´§æ•°é‡
}
// ERP é‡‡è´­å…¥åº“ API
export const PurchaseInApi = {
  // æŸ¥è¯¢é‡‡è´­å…¥åº“分页
  getPurchaseInPage: async (params: any) => {
    return await request.get({ url: `/erp/purchase-in/page`, params })
  },
  // æŸ¥è¯¢é‡‡è´­å…¥åº“详情
  getPurchaseIn: async (id: number) => {
    return await request.get({ url: `/erp/purchase-in/get?id=` + id })
  },
  // æ–°å¢žé‡‡è´­å…¥åº“
  createPurchaseIn: async (data: PurchaseInVO) => {
    return await request.post({ url: `/erp/purchase-in/create`, data })
  },
  // ä¿®æ”¹é‡‡è´­å…¥åº“
  updatePurchaseIn: async (data: PurchaseInVO) => {
    return await request.put({ url: `/erp/purchase-in/update`, data })
  },
  // æ›´æ–°é‡‡è´­å…¥åº“的状态
  updatePurchaseInStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/purchase-in/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤é‡‡è´­å…¥åº“
  deletePurchaseIn: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/purchase-in/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºé‡‡è´­å…¥åº“ Excel
  exportPurchaseIn: async (params: any) => {
    return await request.download({ url: `/erp/purchase-in/export-excel`, params })
  }
}
src/api/erp/purchase/order/index.ts
New file
@@ -0,0 +1,64 @@
import request from '@/config/axios'
// ERP é‡‡è´­è®¢å• VO
export interface PurchaseOrderVO {
  id: number // è®¢å•工单编号
  no: string // é‡‡è´­è®¢å•号
  customerId: number // å®¢æˆ·ç¼–号
  orderTime: Date // è®¢å•æ—¶é—´
  totalCount: number // åˆè®¡æ•°é‡
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
  outCount: number // é‡‡è´­å‡ºåº“数量
  returnCount: number // é‡‡è´­é€€è´§æ•°é‡
}
// ERP é‡‡è´­è®¢å• API
export const PurchaseOrderApi = {
  // æŸ¥è¯¢é‡‡è´­è®¢å•分页
  getPurchaseOrderPage: async (params: any) => {
    return await request.get({ url: `/erp/purchase-order/page`, params })
  },
  // æŸ¥è¯¢é‡‡è´­è®¢å•详情
  getPurchaseOrder: async (id: number) => {
    return await request.get({ url: `/erp/purchase-order/get?id=` + id })
  },
  // æ–°å¢žé‡‡è´­è®¢å•
  createPurchaseOrder: async (data: PurchaseOrderVO) => {
    return await request.post({ url: `/erp/purchase-order/create`, data })
  },
  // ä¿®æ”¹é‡‡è´­è®¢å•
  updatePurchaseOrder: async (data: PurchaseOrderVO) => {
    return await request.put({ url: `/erp/purchase-order/update`, data })
  },
  // æ›´æ–°é‡‡è´­è®¢å•的状态
  updatePurchaseOrderStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/purchase-order/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤é‡‡è´­è®¢å•
  deletePurchaseOrder: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/purchase-order/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºé‡‡è´­è®¢å• Excel
  exportPurchaseOrder: async (params: any) => {
    return await request.download({ url: `/erp/purchase-order/export-excel`, params })
  }
}
src/api/erp/purchase/return/index.ts
New file
@@ -0,0 +1,62 @@
import request from '@/config/axios'
// ERP é‡‡è´­é€€è´§ VO
export interface PurchaseReturnVO {
  id: number // é‡‡è´­é€€è´§ç¼–号
  no: string // é‡‡è´­é€€è´§å·
  customerId: number // å®¢æˆ·ç¼–号
  returnTime: Date // é€€è´§æ—¶é—´
  totalCount: number // åˆè®¡æ•°é‡
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
}
// ERP é‡‡è´­é€€è´§ API
export const PurchaseReturnApi = {
  // æŸ¥è¯¢é‡‡è´­é€€è´§åˆ†é¡µ
  getPurchaseReturnPage: async (params: any) => {
    return await request.get({ url: `/erp/purchase-return/page`, params })
  },
  // æŸ¥è¯¢é‡‡è´­é€€è´§è¯¦æƒ…
  getPurchaseReturn: async (id: number) => {
    return await request.get({ url: `/erp/purchase-return/get?id=` + id })
  },
  // æ–°å¢žé‡‡è´­é€€è´§
  createPurchaseReturn: async (data: PurchaseReturnVO) => {
    return await request.post({ url: `/erp/purchase-return/create`, data })
  },
  // ä¿®æ”¹é‡‡è´­é€€è´§
  updatePurchaseReturn: async (data: PurchaseReturnVO) => {
    return await request.put({ url: `/erp/purchase-return/update`, data })
  },
  // æ›´æ–°é‡‡è´­é€€è´§çš„状态
  updatePurchaseReturnStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/purchase-return/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤é‡‡è´­é€€è´§
  deletePurchaseReturn: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/purchase-return/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºé‡‡è´­é€€è´§ Excel
  exportPurchaseReturn: async (params: any) => {
    return await request.download({ url: `/erp/purchase-return/export-excel`, params })
  }
}
src/api/erp/purchase/supplier/index.ts
New file
@@ -0,0 +1,58 @@
import request from '@/config/axios'
// ERP ä¾›åº”商 VO
export interface SupplierVO {
  id: number // ä¾›åº”商编号
  name: string // ä¾›åº”商名称
  contact: string // è”系人
  mobile: string // æ‰‹æœºå·ç 
  telephone: string // è”系电话
  email: string // ç”µå­é‚®ç®±
  fax: string // ä¼ çœŸ
  remark: string // å¤‡æ³¨
  status: number // å¼€å¯çŠ¶æ€
  sort: number // æŽ’序
  taxNo: string // çº³ç¨Žäººè¯†åˆ«å·
  taxPercent: number // ç¨Žçއ
  bankName: string // å¼€æˆ·è¡Œ
  bankAccount: string // å¼€æˆ·è´¦å·
  bankAddress: string // å¼€æˆ·åœ°å€
}
// ERP ä¾›åº”商 API
export const SupplierApi = {
  // æŸ¥è¯¢ä¾›åº”商分页
  getSupplierPage: async (params: any) => {
    return await request.get({ url: `/erp/supplier/page`, params })
  },
  // èŽ·å¾—ä¾›åº”å•†ç²¾ç®€åˆ—è¡¨
  getSupplierSimpleList: async () => {
    return await request.get({ url: `/erp/supplier/simple-list` })
  },
  // æŸ¥è¯¢ä¾›åº”商详情
  getSupplier: async (id: number) => {
    return await request.get({ url: `/erp/supplier/get?id=` + id })
  },
  // æ–°å¢žä¾›åº”商
  createSupplier: async (data: SupplierVO) => {
    return await request.post({ url: `/erp/supplier/create`, data })
  },
  // ä¿®æ”¹ä¾›åº”商
  updateSupplier: async (data: SupplierVO) => {
    return await request.put({ url: `/erp/supplier/update`, data })
  },
  // åˆ é™¤ä¾›åº”商
  deleteSupplier: async (id: number) => {
    return await request.delete({ url: `/erp/supplier/delete?id=` + id })
  },
  // å¯¼å‡ºä¾›åº”商 Excel
  exportSupplier: async (params) => {
    return await request.download({ url: `/erp/supplier/export-excel`, params })
  }
}
src/api/erp/sale/customer/index.ts
New file
@@ -0,0 +1,58 @@
import request from '@/config/axios'
// ERP å®¢æˆ· VO
export interface CustomerVO {
  id: number // å®¢æˆ·ç¼–号
  name: string // å®¢æˆ·åç§°
  contact: string // è”系人
  mobile: string // æ‰‹æœºå·ç 
  telephone: string // è”系电话
  email: string // ç”µå­é‚®ç®±
  fax: string // ä¼ çœŸ
  remark: string // å¤‡æ³¨
  status: number // å¼€å¯çŠ¶æ€
  sort: number // æŽ’序
  taxNo: string // çº³ç¨Žäººè¯†åˆ«å·
  taxPercent: number // ç¨Žçއ
  bankName: string // å¼€æˆ·è¡Œ
  bankAccount: string // å¼€æˆ·è´¦å·
  bankAddress: string // å¼€æˆ·åœ°å€
}
// ERP å®¢æˆ· API
export const CustomerApi = {
  // æŸ¥è¯¢å®¢æˆ·åˆ†é¡µ
  getCustomerPage: async (params: any) => {
    return await request.get({ url: `/erp/customer/page`, params })
  },
  // æŸ¥è¯¢å®¢æˆ·ç²¾ç®€åˆ—表
  getCustomerSimpleList: async () => {
    return await request.get({ url: `/erp/customer/simple-list` })
  },
  // æŸ¥è¯¢å®¢æˆ·è¯¦æƒ…
  getCustomer: async (id: number) => {
    return await request.get({ url: `/erp/customer/get?id=` + id })
  },
  // æ–°å¢žå®¢æˆ·
  createCustomer: async (data: CustomerVO) => {
    return await request.post({ url: `/erp/customer/create`, data })
  },
  // ä¿®æ”¹å®¢æˆ·
  updateCustomer: async (data: CustomerVO) => {
    return await request.put({ url: `/erp/customer/update`, data })
  },
  // åˆ é™¤å®¢æˆ·
  deleteCustomer: async (id: number) => {
    return await request.delete({ url: `/erp/customer/delete?id=` + id })
  },
  // å¯¼å‡ºå®¢æˆ· Excel
  exportCustomer: async (params) => {
    return await request.download({ url: `/erp/customer/export-excel`, params })
  }
}
src/api/erp/sale/order/index.ts
New file
@@ -0,0 +1,64 @@
import request from '@/config/axios'
// ERP é”€å”®è®¢å• VO
export interface SaleOrderVO {
  id: number // è®¢å•工单编号
  no: string // é”€å”®è®¢å•号
  customerId: number // å®¢æˆ·ç¼–号
  orderTime: Date // è®¢å•æ—¶é—´
  totalCount: number // åˆè®¡æ•°é‡
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
  outCount: number // é”€å”®å‡ºåº“数量
  returnCount: number // é”€å”®é€€è´§æ•°é‡
}
// ERP é”€å”®è®¢å• API
export const SaleOrderApi = {
  // æŸ¥è¯¢é”€å”®è®¢å•分页
  getSaleOrderPage: async (params: any) => {
    return await request.get({ url: `/erp/sale-order/page`, params })
  },
  // æŸ¥è¯¢é”€å”®è®¢å•详情
  getSaleOrder: async (id: number) => {
    return await request.get({ url: `/erp/sale-order/get?id=` + id })
  },
  // æ–°å¢žé”€å”®è®¢å•
  createSaleOrder: async (data: SaleOrderVO) => {
    return await request.post({ url: `/erp/sale-order/create`, data })
  },
  // ä¿®æ”¹é”€å”®è®¢å•
  updateSaleOrder: async (data: SaleOrderVO) => {
    return await request.put({ url: `/erp/sale-order/update`, data })
  },
  // æ›´æ–°é”€å”®è®¢å•的状态
  updateSaleOrderStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/sale-order/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤é”€å”®è®¢å•
  deleteSaleOrder: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/sale-order/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºé”€å”®è®¢å• Excel
  exportSaleOrder: async (params: any) => {
    return await request.download({ url: `/erp/sale-order/export-excel`, params })
  }
}
src/api/erp/sale/out/index.ts
New file
@@ -0,0 +1,62 @@
import request from '@/config/axios'
// ERP é”€å”®å‡ºåº“ VO
export interface SaleOutVO {
  id: number // é”€å”®å‡ºåº“编号
  no: string // é”€å”®å‡ºåº“号
  customerId: number // å®¢æˆ·ç¼–号
  outTime: Date // å‡ºåº“æ—¶é—´
  totalCount: number // åˆè®¡æ•°é‡
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
}
// ERP é”€å”®å‡ºåº“ API
export const SaleOutApi = {
  // æŸ¥è¯¢é”€å”®å‡ºåº“分页
  getSaleOutPage: async (params: any) => {
    return await request.get({ url: `/erp/sale-out/page`, params })
  },
  // æŸ¥è¯¢é”€å”®å‡ºåº“详情
  getSaleOut: async (id: number) => {
    return await request.get({ url: `/erp/sale-out/get?id=` + id })
  },
  // æ–°å¢žé”€å”®å‡ºåº“
  createSaleOut: async (data: SaleOutVO) => {
    return await request.post({ url: `/erp/sale-out/create`, data })
  },
  // ä¿®æ”¹é”€å”®å‡ºåº“
  updateSaleOut: async (data: SaleOutVO) => {
    return await request.put({ url: `/erp/sale-out/update`, data })
  },
  // æ›´æ–°é”€å”®å‡ºåº“的状态
  updateSaleOutStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/sale-out/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤é”€å”®å‡ºåº“
  deleteSaleOut: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/sale-out/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºé”€å”®å‡ºåº“ Excel
  exportSaleOut: async (params: any) => {
    return await request.download({ url: `/erp/sale-out/export-excel`, params })
  }
}
src/api/erp/sale/return/index.ts
New file
@@ -0,0 +1,62 @@
import request from '@/config/axios'
// ERP é”€å”®é€€è´§ VO
export interface SaleReturnVO {
  id: number // é”€å”®é€€è´§ç¼–号
  no: string // é”€å”®é€€è´§å·
  customerId: number // å®¢æˆ·ç¼–号
  returnTime: Date // é€€è´§æ—¶é—´
  totalCount: number // åˆè®¡æ•°é‡
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
}
// ERP é”€å”®é€€è´§ API
export const SaleReturnApi = {
  // æŸ¥è¯¢é”€å”®é€€è´§åˆ†é¡µ
  getSaleReturnPage: async (params: any) => {
    return await request.get({ url: `/erp/sale-return/page`, params })
  },
  // æŸ¥è¯¢é”€å”®é€€è´§è¯¦æƒ…
  getSaleReturn: async (id: number) => {
    return await request.get({ url: `/erp/sale-return/get?id=` + id })
  },
  // æ–°å¢žé”€å”®é€€è´§
  createSaleReturn: async (data: SaleReturnVO) => {
    return await request.post({ url: `/erp/sale-return/create`, data })
  },
  // ä¿®æ”¹é”€å”®é€€è´§
  updateSaleReturn: async (data: SaleReturnVO) => {
    return await request.put({ url: `/erp/sale-return/update`, data })
  },
  // æ›´æ–°é”€å”®é€€è´§çš„状态
  updateSaleReturnStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/sale-return/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤é”€å”®é€€è´§
  deleteSaleReturn: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/sale-return/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºé”€å”®é€€è´§ Excel
  exportSaleReturn: async (params: any) => {
    return await request.download({ url: `/erp/sale-return/export-excel`, params })
  }
}
src/api/erp/statistics/purchase/index.ts
New file
@@ -0,0 +1,28 @@
import request from '@/config/axios'
// ERP é‡‡è´­å…¨å±€ç»Ÿè®¡ VO
export interface ErpPurchaseSummaryRespVO {
  todayPrice: number // ä»Šæ—¥é‡‡è´­é‡‘额
  yesterdayPrice: number // æ˜¨æ—¥é‡‡è´­é‡‘额
  monthPrice: number // æœ¬æœˆé‡‡è´­é‡‘额
  yearPrice: number // ä»Šå¹´é‡‡è´­é‡‘额
}
// ERP é‡‡è´­æ—¶é—´æ®µç»Ÿè®¡ VO
export interface ErpPurchaseTimeSummaryRespVO {
  time: string // æ—¶é—´
  price: number // é‡‡è´­é‡‘额
}
// ERP é‡‡è´­ç»Ÿè®¡ API
export const PurchaseStatisticsApi = {
  // èŽ·å¾—é‡‡è´­ç»Ÿè®¡
  getPurchaseSummary: async (): Promise<ErpPurchaseSummaryRespVO> => {
    return await request.get({ url: `/erp/purchase-statistics/summary` })
  },
  // èŽ·å¾—é‡‡è´­æ—¶é—´æ®µç»Ÿè®¡
  getPurchaseTimeSummary: async (): Promise<ErpPurchaseTimeSummaryRespVO[]> => {
    return await request.get({ url: `/erp/purchase-statistics/time-summary` })
  }
}
src/api/erp/statistics/sale/index.ts
New file
@@ -0,0 +1,28 @@
import request from '@/config/axios'
// ERP é”€å”®å…¨å±€ç»Ÿè®¡ VO
export interface ErpSaleSummaryRespVO {
  todayPrice: number // ä»Šæ—¥é”€å”®é‡‘额
  yesterdayPrice: number // æ˜¨æ—¥é”€å”®é‡‘额
  monthPrice: number // æœ¬æœˆé”€å”®é‡‘额
  yearPrice: number // ä»Šå¹´é”€å”®é‡‘额
}
// ERP é”€å”®æ—¶é—´æ®µç»Ÿè®¡ VO
export interface ErpSaleTimeSummaryRespVO {
  time: string // æ—¶é—´
  price: number // é”€å”®é‡‘额
}
// ERP é”€å”®ç»Ÿè®¡ API
export const SaleStatisticsApi = {
  // èŽ·å¾—é”€å”®ç»Ÿè®¡
  getSaleSummary: async (): Promise<ErpSaleSummaryRespVO> => {
    return await request.get({ url: `/erp/sale-statistics/summary` })
  },
  // èŽ·å¾—é”€å”®æ—¶é—´æ®µç»Ÿè®¡
  getSaleTimeSummary: async (): Promise<ErpSaleTimeSummaryRespVO[]> => {
    return await request.get({ url: `/erp/sale-statistics/time-summary` })
  }
}
src/api/erp/stock/check/index.ts
New file
@@ -0,0 +1,61 @@
import request from '@/config/axios'
// ERP åº“存盘点单 VO
export interface StockCheckVO {
  id: number // å‡ºåº“编号
  no: string // å‡ºåº“单号
  outTime: Date // å‡ºåº“æ—¶é—´
  totalCount: number // åˆè®¡æ•°é‡
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
}
// ERP åº“存盘点单 API
export const StockCheckApi = {
  // æŸ¥è¯¢åº“存盘点单分页
  getStockCheckPage: async (params: any) => {
    return await request.get({ url: `/erp/stock-check/page`, params })
  },
  // æŸ¥è¯¢åº“存盘点单详情
  getStockCheck: async (id: number) => {
    return await request.get({ url: `/erp/stock-check/get?id=` + id })
  },
  // æ–°å¢žåº“存盘点单
  createStockCheck: async (data: StockCheckVO) => {
    return await request.post({ url: `/erp/stock-check/create`, data })
  },
  // ä¿®æ”¹åº“存盘点单
  updateStockCheck: async (data: StockCheckVO) => {
    return await request.put({ url: `/erp/stock-check/update`, data })
  },
  // æ›´æ–°åº“存盘点单的状态
  updateStockCheckStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/stock-check/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤åº“存盘点单
  deleteStockCheck: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/stock-check/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºåº“存盘点单 Excel
  exportStockCheck: async (params) => {
    return await request.download({ url: `/erp/stock-check/export-excel`, params })
  }
}
src/api/erp/stock/in/index.ts
New file
@@ -0,0 +1,62 @@
import request from '@/config/axios'
// ERP å…¶å®ƒå…¥åº“单 VO
export interface StockInVO {
  id: number // å…¥åº“编号
  no: string // å…¥åº“单号
  supplierId: number // ä¾›åº”商编号
  inTime: Date // å…¥åº“æ—¶é—´
  totalCount: number // åˆè®¡æ•°é‡
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
}
// ERP å…¶å®ƒå…¥åº“单 API
export const StockInApi = {
  // æŸ¥è¯¢å…¶å®ƒå…¥åº“单分页
  getStockInPage: async (params: any) => {
    return await request.get({ url: `/erp/stock-in/page`, params })
  },
  // æŸ¥è¯¢å…¶å®ƒå…¥åº“单详情
  getStockIn: async (id: number) => {
    return await request.get({ url: `/erp/stock-in/get?id=` + id })
  },
  // æ–°å¢žå…¶å®ƒå…¥åº“单
  createStockIn: async (data: StockInVO) => {
    return await request.post({ url: `/erp/stock-in/create`, data })
  },
  // ä¿®æ”¹å…¶å®ƒå…¥åº“单
  updateStockIn: async (data: StockInVO) => {
    return await request.put({ url: `/erp/stock-in/update`, data })
  },
  // æ›´æ–°å…¶å®ƒå…¥åº“单的状态
  updateStockInStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/stock-in/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤å…¶å®ƒå…¥åº“单
  deleteStockIn: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/stock-in/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºå…¶å®ƒå…¥åº“单 Excel
  exportStockIn: async (params) => {
    return await request.download({ url: `/erp/stock-in/export-excel`, params })
  }
}
src/api/erp/stock/move/index.ts
New file
@@ -0,0 +1,61 @@
import request from '@/config/axios'
// ERP åº“存调度单 VO
export interface StockMoveVO {
  id: number // å‡ºåº“编号
  no: string // å‡ºåº“单号
  outTime: Date // å‡ºåº“æ—¶é—´
  totalCount: number // åˆè®¡æ•°é‡
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
}
// ERP åº“存调度单 API
export const StockMoveApi = {
  // æŸ¥è¯¢åº“存调度单分页
  getStockMovePage: async (params: any) => {
    return await request.get({ url: `/erp/stock-move/page`, params })
  },
  // æŸ¥è¯¢åº“存调度单详情
  getStockMove: async (id: number) => {
    return await request.get({ url: `/erp/stock-move/get?id=` + id })
  },
  // æ–°å¢žåº“存调度单
  createStockMove: async (data: StockMoveVO) => {
    return await request.post({ url: `/erp/stock-move/create`, data })
  },
  // ä¿®æ”¹åº“存调度单
  updateStockMove: async (data: StockMoveVO) => {
    return await request.put({ url: `/erp/stock-move/update`, data })
  },
  // æ›´æ–°åº“存调度单的状态
  updateStockMoveStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/stock-move/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤åº“存调度单
  deleteStockMove: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/stock-move/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºåº“存调度单 Excel
  exportStockMove: async (params) => {
    return await request.download({ url: `/erp/stock-move/export-excel`, params })
  }
}
src/api/erp/stock/out/index.ts
New file
@@ -0,0 +1,62 @@
import request from '@/config/axios'
// ERP å…¶å®ƒå‡ºåº“单 VO
export interface StockOutVO {
  id: number // å‡ºåº“编号
  no: string // å‡ºåº“单号
  customerId: number // å®¢æˆ·ç¼–号
  outTime: Date // å‡ºåº“æ—¶é—´
  totalCount: number // åˆè®¡æ•°é‡
  totalPrice: number // åˆè®¡é‡‘额,单位:元
  status: number // çŠ¶æ€
  remark: string // å¤‡æ³¨
}
// ERP å…¶å®ƒå‡ºåº“单 API
export const StockOutApi = {
  // æŸ¥è¯¢å…¶å®ƒå‡ºåº“单分页
  getStockOutPage: async (params: any) => {
    return await request.get({ url: `/erp/stock-out/page`, params })
  },
  // æŸ¥è¯¢å…¶å®ƒå‡ºåº“单详情
  getStockOut: async (id: number) => {
    return await request.get({ url: `/erp/stock-out/get?id=` + id })
  },
  // æ–°å¢žå…¶å®ƒå‡ºåº“单
  createStockOut: async (data: StockOutVO) => {
    return await request.post({ url: `/erp/stock-out/create`, data })
  },
  // ä¿®æ”¹å…¶å®ƒå‡ºåº“单
  updateStockOut: async (data: StockOutVO) => {
    return await request.put({ url: `/erp/stock-out/update`, data })
  },
  // æ›´æ–°å…¶å®ƒå‡ºåº“单的状态
  updateStockOutStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/erp/stock-out/update-status`,
      params: {
        id,
        status
      }
    })
  },
  // åˆ é™¤å…¶å®ƒå‡ºåº“单
  deleteStockOut: async (ids: number[]) => {
    return await request.delete({
      url: `/erp/stock-out/delete`,
      params: {
        ids: ids.join(',')
      }
    })
  },
  // å¯¼å‡ºå…¶å®ƒå‡ºåº“单 Excel
  exportStockOut: async (params) => {
    return await request.download({ url: `/erp/stock-out/export-excel`, params })
  }
}
src/api/erp/stock/record/index.ts
New file
@@ -0,0 +1,32 @@
import request from '@/config/axios'
// ERP äº§å“åº“存明细 VO
export interface StockRecordVO {
  id: number // ç¼–号
  productId: number // äº§å“ç¼–号
  warehouseId: number // ä»“库编号
  count: number // å‡ºå…¥åº“数量
  totalCount: number // æ€»åº“存量
  bizType: number // ä¸šåŠ¡ç±»åž‹
  bizId: number // ä¸šåŠ¡ç¼–å·
  bizItemId: number // ä¸šåŠ¡é¡¹ç¼–å·
  bizNo: string // ä¸šåŠ¡å•å·
}
// ERP äº§å“åº“存明细 API
export const StockRecordApi = {
  // æŸ¥è¯¢äº§å“åº“存明细分页
  getStockRecordPage: async (params: any) => {
    return await request.get({ url: `/erp/stock-record/page`, params })
  },
  // æŸ¥è¯¢äº§å“åº“存明细详情
  getStockRecord: async (id: number) => {
    return await request.get({ url: `/erp/stock-record/get?id=` + id })
  },
  // å¯¼å‡ºäº§å“åº“存明细 Excel
  exportStockRecord: async (params) => {
    return await request.download({ url: `/erp/stock-record/export-excel`, params })
  }
}
src/api/erp/stock/stock/index.ts
New file
@@ -0,0 +1,41 @@
import request from '@/config/axios'
// ERP äº§å“åº“å­˜ VO
export interface StockVO {
  // ç¼–号
  id: number
  // äº§å“ç¼–号
  productId: number
  // ä»“库编号
  warehouseId: number
  // åº“存数量
  count: number
}
// ERP äº§å“åº“å­˜ API
export const StockApi = {
  // æŸ¥è¯¢äº§å“åº“存分页
  getStockPage: async (params: any) => {
    return await request.get({ url: `/erp/stock/page`, params })
  },
  // æŸ¥è¯¢äº§å“åº“存详情
  getStock: async (id: number) => {
    return await request.get({ url: `/erp/stock/get?id=` + id })
  },
  // æŸ¥è¯¢äº§å“åº“存详情
  getStock2: async (productId: number, warehouseId: number) => {
    return await request.get({ url: `/erp/stock/get`, params: { productId, warehouseId } })
  },
  // èŽ·å¾—äº§å“åº“å­˜æ•°é‡
  getStockCount: async (productId: number) => {
    return await request.get({ url: `/erp/stock/get-count`, params: { productId } })
  },
  // å¯¼å‡ºäº§å“åº“å­˜ Excel
  exportStock: async (params) => {
    return await request.download({ url: `/erp/stock/export-excel`, params })
  }
}
src/api/erp/stock/warehouse/index.ts
New file
@@ -0,0 +1,64 @@
import request from '@/config/axios'
// ERP ä»“库 VO
export interface WarehouseVO {
  id: number // ä»“库编号
  name: string // ä»“库名称
  address: string // ä»“库地址
  sort: number // æŽ’序
  remark: string // å¤‡æ³¨
  principal: string // è´Ÿè´£äºº
  warehousePrice: number // ä»“储费,单位:元
  truckagePrice: number // æ¬è¿è´¹ï¼Œå•位:元
  status: number // å¼€å¯çŠ¶æ€
  defaultStatus: boolean // æ˜¯å¦é»˜è®¤
}
// ERP ä»“库 API
export const WarehouseApi = {
  // æŸ¥è¯¢ä»“库分页
  getWarehousePage: async (params: any) => {
    return await request.get({ url: `/erp/warehouse/page`, params })
  },
  // æŸ¥è¯¢ä»“库精简列表
  getWarehouseSimpleList: async () => {
    return await request.get({ url: `/erp/warehouse/simple-list` })
  },
  // æŸ¥è¯¢ä»“库详情
  getWarehouse: async (id: number) => {
    return await request.get({ url: `/erp/warehouse/get?id=` + id })
  },
  // æ–°å¢žä»“库
  createWarehouse: async (data: WarehouseVO) => {
    return await request.post({ url: `/erp/warehouse/create`, data })
  },
  // ä¿®æ”¹ä»“库
  updateWarehouse: async (data: WarehouseVO) => {
    return await request.put({ url: `/erp/warehouse/update`, data })
  },
  // ä¿®æ”¹ä»“库默认状态
  updateWarehouseDefaultStatus: async (id: number, defaultStatus: boolean) => {
    return await request.put({
      url: `/erp/warehouse/update-default-status`,
      params: {
        id,
        defaultStatus
      }
    })
  },
  // åˆ é™¤ä»“库
  deleteWarehouse: async (id: number) => {
    return await request.delete({ url: `/erp/warehouse/delete?id=` + id })
  },
  // å¯¼å‡ºä»“库 Excel
  exportWarehouse: async (params) => {
    return await request.download({ url: `/erp/warehouse/export-excel`, params })
  }
}
src/api/infra/apiAccessLog/index.ts
New file
@@ -0,0 +1,34 @@
import request from '@/config/axios'
export interface ApiAccessLogVO {
  id: number
  traceId: string
  userId: number
  userType: number
  applicationName: string
  requestMethod: string
  requestParams: string
  responseBody: string
  requestUrl: string
  userIp: string
  userAgent: string
  operateModule: string
  operateName: string
  operateType: number
  beginTime: Date
  endTime: Date
  duration: number
  resultCode: number
  resultMsg: string
  createTime: Date
}
// æŸ¥è¯¢åˆ—表API è®¿é—®æ—¥å¿—
export const getApiAccessLogPage = (params: PageParam) => {
  return request.get({ url: '/infra/api-access-log/page', params })
}
// å¯¼å‡ºAPI è®¿é—®æ—¥å¿—
export const exportApiAccessLog = (params) => {
  return request.download({ url: '/infra/api-access-log/export-excel', params })
}
src/api/infra/apiErrorLog/index.ts
New file
@@ -0,0 +1,48 @@
import request from '@/config/axios'
export interface ApiErrorLogVO {
  id: number
  traceId: string
  userId: number
  userType: number
  applicationName: string
  requestMethod: string
  requestParams: string
  requestUrl: string
  userIp: string
  userAgent: string
  exceptionTime: Date
  exceptionName: string
  exceptionMessage: string
  exceptionRootCauseMessage: string
  exceptionStackTrace: string
  exceptionClassName: string
  exceptionFileName: string
  exceptionMethodName: string
  exceptionLineNumber: number
  processUserId: number
  processStatus: number
  processTime: Date
  resultCode: number
  createTime: Date
}
// æŸ¥è¯¢åˆ—表API è®¿é—®æ—¥å¿—
export const getApiErrorLogPage = (params: PageParam) => {
  return request.get({ url: '/infra/api-error-log/page', params })
}
// æ›´æ–° API é”™è¯¯æ—¥å¿—的处理状态
export const updateApiErrorLogPage = (id: number, processStatus: number) => {
  return request.put({
    url: '/infra/api-error-log/update-status?id=' + id + '&processStatus=' + processStatus
  })
}
// å¯¼å‡ºAPI è®¿é—®æ—¥å¿—
export const exportApiErrorLog = (params) => {
  return request.download({
    url: '/infra/api-error-log/export-excel',
    params
  })
}
src/api/infra/codegen/index.ts
New file
@@ -0,0 +1,112 @@
import request from '@/config/axios'
export type CodegenTableVO = {
  id: number
  tableId: number
  isParentMenuIdValid: boolean
  dataSourceConfigId: number
  scene: number
  tableName: string
  tableComment: string
  remark: string
  moduleName: string
  businessName: string
  className: string
  classComment: string
  author: string
  createTime: Date
  updateTime: Date
  templateType: number
  parentMenuId: number
}
export type CodegenColumnVO = {
  id: number
  tableId: number
  columnName: string
  dataType: string
  columnComment: string
  nullable: number
  primaryKey: number
  ordinalPosition: number
  javaType: string
  javaField: string
  dictType: string
  example: string
  createOperation: number
  updateOperation: number
  listOperation: number
  listOperationCondition: string
  listOperationResult: number
  htmlType: string
}
export type DatabaseTableVO = {
  name: string
  comment: string
}
export type CodegenPreviewVO = {
  filePath: string
  code: string
}
export type CodegenUpdateReqVO = {
  table: CodegenTableVO | any
  columns: CodegenColumnVO[]
}
// æŸ¥è¯¢åˆ—表代码生成表定义
export const getCodegenTableList = (dataSourceConfigId: number) => {
  return request.get({ url: '/infra/codegen/table/list?dataSourceConfigId=' + dataSourceConfigId })
}
// æŸ¥è¯¢åˆ—表代码生成表定义
export const getCodegenTablePage = (params: PageParam) => {
  return request.get({ url: '/infra/codegen/table/page', params })
}
// æŸ¥è¯¢è¯¦æƒ…代码生成表定义
export const getCodegenTable = (id: number) => {
  return request.get({ url: '/infra/codegen/detail?tableId=' + id })
}
// ä¿®æ”¹ä»£ç ç”Ÿæˆè¡¨å®šä¹‰
export const updateCodegenTable = (data: CodegenUpdateReqVO) => {
  return request.put({ url: '/infra/codegen/update', data })
}
// åŸºäºŽæ•°æ®åº“的表结构,同步数据库的表和字段定义
export const syncCodegenFromDB = (id: number) => {
  return request.put({ url: '/infra/codegen/sync-from-db?tableId=' + id })
}
// é¢„览生成代码
export const previewCodegen = (id: number) => {
  return request.get({ url: '/infra/codegen/preview?tableId=' + id })
}
// ä¸‹è½½ç”Ÿæˆä»£ç 
export const downloadCodegen = (id: number) => {
  return request.download({ url: '/infra/codegen/download?tableId=' + id })
}
// èŽ·å¾—è¡¨å®šä¹‰
export const getSchemaTableList = (params) => {
  return request.get({ url: '/infra/codegen/db/table/list', params })
}
// åŸºäºŽæ•°æ®åº“的表结构,创建代码生成器的表定义
export const createCodegenList = (data) => {
  return request.post({ url: '/infra/codegen/create-list', data })
}
// åˆ é™¤ä»£ç ç”Ÿæˆè¡¨å®šä¹‰
export const deleteCodegenTable = (id: number) => {
  return request.delete({ url: '/infra/codegen/delete?tableId=' + id })
}
// æ‰¹é‡åˆ é™¤ä»£ç ç”Ÿæˆè¡¨å®šä¹‰
export const deleteCodegenTableList = (ids: number[]) => {
  return request.delete({ url: '/infra/codegen/delete-list', params: { tableIds: ids.join(',') } })
}
src/api/infra/config/index.ts
New file
@@ -0,0 +1,53 @@
import request from '@/config/axios'
export interface ConfigVO {
  id: number | undefined
  category: string
  name: string
  key: string
  value: string
  type: number
  visible: boolean
  remark: string
  createTime: Date
}
// æŸ¥è¯¢å‚数列表
export const getConfigPage = (params: PageParam) => {
  return request.get({ url: '/infra/config/page', params })
}
// æŸ¥è¯¢å‚数详情
export const getConfig = (id: number) => {
  return request.get({ url: '/infra/config/get?id=' + id })
}
// æ ¹æ®å‚数键名查询参数值
export const getConfigKey = (configKey: string) => {
  return request.get({ url: '/infra/config/get-value-by-key?key=' + configKey })
}
// æ–°å¢žå‚æ•°
export const createConfig = (data: ConfigVO) => {
  return request.post({ url: '/infra/config/create', data })
}
// ä¿®æ”¹å‚æ•°
export const updateConfig = (data: ConfigVO) => {
  return request.put({ url: '/infra/config/update', data })
}
// åˆ é™¤å‚æ•°
export const deleteConfig = (id: number) => {
  return request.delete({ url: '/infra/config/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤å‚æ•°
export const deleteConfigList = (ids: number[]) => {
  return request.delete({ url: '/infra/config/delete-list', params: { ids: ids.join(',') } })
}
// å¯¼å‡ºå‚æ•°
export const exportConfig = (params) => {
  return request.download({ url: '/infra/config/export-excel', params })
}
src/api/infra/dataSourceConfig/index.ts
New file
@@ -0,0 +1,40 @@
import request from '@/config/axios'
export interface DataSourceConfigVO {
  id: number | undefined
  name: string
  url: string
  username: string
  password: string
  createTime?: Date
}
// æ–°å¢žæ•°æ®æºé…ç½®
export const createDataSourceConfig = (data: DataSourceConfigVO) => {
  return request.post({ url: '/infra/data-source-config/create', data })
}
// ä¿®æ”¹æ•°æ®æºé…ç½®
export const updateDataSourceConfig = (data: DataSourceConfigVO) => {
  return request.put({ url: '/infra/data-source-config/update', data })
}
// åˆ é™¤æ•°æ®æºé…ç½®
export const deleteDataSourceConfig = (id: number) => {
  return request.delete({ url: '/infra/data-source-config/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤æ•°æ®æºé…ç½®
export const deleteDataSourceConfigList = (ids: number[]) => {
  return request.delete({ url: '/infra/data-source-config/delete-list', params: { ids: ids.join(',') } })
}
// æŸ¥è¯¢æ•°æ®æºé…ç½®è¯¦æƒ…
export const getDataSourceConfig = (id: number) => {
  return request.get({ url: '/infra/data-source-config/get?id=' + id })
}
// æŸ¥è¯¢æ•°æ®æºé…ç½®åˆ—表
export const getDataSourceConfigList = () => {
  return request.get({ url: '/infra/data-source-config/list' })
}
src/api/infra/demo/demo01/index.ts
New file
@@ -0,0 +1,50 @@
import request from '@/config/axios'
import type { Dayjs } from 'dayjs'
/** ç¤ºä¾‹è”系人信息 */
export interface Demo01Contact {
  id: number // ç¼–号
  name?: string // åå­—
  sex?: number // æ€§åˆ«
  birthday?: string | Dayjs // å‡ºç”Ÿå¹´
  description?: string // ç®€ä»‹
  avatar: string // å¤´åƒ
}
// ç¤ºä¾‹è”系人 API
export const Demo01ContactApi = {
  // æŸ¥è¯¢ç¤ºä¾‹è”系人分页
  getDemo01ContactPage: async (params: any) => {
    return await request.get({ url: `/infra/demo01-contact/page`, params })
  },
  // æŸ¥è¯¢ç¤ºä¾‹è”系人详情
  getDemo01Contact: async (id: number) => {
    return await request.get({ url: `/infra/demo01-contact/get?id=` + id })
  },
  // æ–°å¢žç¤ºä¾‹è”系人
  createDemo01Contact: async (data: Demo01Contact) => {
    return await request.post({ url: `/infra/demo01-contact/create`, data })
  },
  // ä¿®æ”¹ç¤ºä¾‹è”系人
  updateDemo01Contact: async (data: Demo01Contact) => {
    return await request.put({ url: `/infra/demo01-contact/update`, data })
  },
  // åˆ é™¤ç¤ºä¾‹è”系人
  deleteDemo01Contact: async (id: number) => {
    return await request.delete({ url: `/infra/demo01-contact/delete?id=` + id })
  },
  /** æ‰¹é‡åˆ é™¤ç¤ºä¾‹è”系人 */
  deleteDemo01ContactList: async (ids: number[]) => {
    return await request.delete({ url: `/infra/demo01-contact/delete-list?ids=${ids.join(',')}` })
  },
  // å¯¼å‡ºç¤ºä¾‹è”系人 Excel
  exportDemo01Contact: async (params) => {
    return await request.download({ url: `/infra/demo01-contact/export-excel`, params })
  }
}
src/api/infra/demo/demo02/index.ts
New file
@@ -0,0 +1,37 @@
import request from '@/config/axios'
export interface Demo02CategoryVO {
  id: number
  name: string
  parentId: number
}
// æŸ¥è¯¢ç¤ºä¾‹åˆ†ç±»åˆ—表
export const getDemo02CategoryList = async () => {
  return await request.get({ url: `/infra/demo02-category/list` })
}
// æŸ¥è¯¢ç¤ºä¾‹åˆ†ç±»è¯¦æƒ…
export const getDemo02Category = async (id: number) => {
  return await request.get({ url: `/infra/demo02-category/get?id=` + id })
}
// æ–°å¢žç¤ºä¾‹åˆ†ç±»
export const createDemo02Category = async (data: Demo02CategoryVO) => {
  return await request.post({ url: `/infra/demo02-category/create`, data })
}
// ä¿®æ”¹ç¤ºä¾‹åˆ†ç±»
export const updateDemo02Category = async (data: Demo02CategoryVO) => {
  return await request.put({ url: `/infra/demo02-category/update`, data })
}
// åˆ é™¤ç¤ºä¾‹åˆ†ç±»
export const deleteDemo02Category = async (id: number) => {
  return await request.delete({ url: `/infra/demo02-category/delete?id=` + id })
}
// å¯¼å‡ºç¤ºä¾‹åˆ†ç±» Excel
export const exportDemo02Category = async (params) => {
  return await request.download({ url: `/infra/demo02-category/export-excel`, params })
}
src/api/infra/demo/demo03/erp/index.ts
New file
@@ -0,0 +1,127 @@
import request from '@/config/axios'
import type { Dayjs } from 'dayjs';
/** å­¦ç”Ÿè¯¾ç¨‹ä¿¡æ¯ */
export interface Demo03Course {
  id: number; // ç¼–号
  studentId?: number; // å­¦ç”Ÿç¼–号
  name?: string; // åå­—
  score?: number; // åˆ†æ•°
}
/** å­¦ç”Ÿç­çº§ä¿¡æ¯ */
export interface Demo03Grade {
  id: number; // ç¼–号
  studentId?: number; // å­¦ç”Ÿç¼–号
  name?: string; // åå­—
  teacher?: string; // ç­ä¸»ä»»
}
/** å­¦ç”Ÿä¿¡æ¯ */
export interface Demo03Student {
  id: number; // ç¼–号
  name?: string; // åå­—
  sex?: number; // æ€§åˆ«
  birthday?: string | Dayjs; // å‡ºç”Ÿæ—¥æœŸ
  description?: string; // ç®€ä»‹
}
// å­¦ç”Ÿ API
export const Demo03StudentApi = {
  // æŸ¥è¯¢å­¦ç”Ÿåˆ†é¡µ
  getDemo03StudentPage: async (params: any) => {
    return await request.get({ url: `/infra/demo03-student-erp/page`, params })
  },
  // æŸ¥è¯¢å­¦ç”Ÿè¯¦æƒ…
  getDemo03Student: async (id: number) => {
    return await request.get({ url: `/infra/demo03-student-erp/get?id=` + id })
  },
  // æ–°å¢žå­¦ç”Ÿ
  createDemo03Student: async (data: Demo03Student) => {
    return await request.post({ url: `/infra/demo03-student-erp/create`, data })
  },
  // ä¿®æ”¹å­¦ç”Ÿ
  updateDemo03Student: async (data: Demo03Student) => {
    return await request.put({ url: `/infra/demo03-student-erp/update`, data })
  },
  // åˆ é™¤å­¦ç”Ÿ
  deleteDemo03Student: async (id: number) => {
    return await request.delete({ url: `/infra/demo03-student-erp/delete?id=` + id })
  },
  /** æ‰¹é‡åˆ é™¤å­¦ç”Ÿ */
  deleteDemo03StudentList: async (ids: number[]) => {
    return await request.delete({ url: `/infra/demo03-student-erp/delete-list?ids=${ids.join(',')}` })
  },
  // å¯¼å‡ºå­¦ç”Ÿ Excel
  exportDemo03Student: async (params) => {
    return await request.download({ url: `/infra/demo03-student-erp/export-excel`, params })
  },
// ==================== å­è¡¨ï¼ˆå­¦ç”Ÿè¯¾ç¨‹ï¼‰ ====================
  // èŽ·å¾—å­¦ç”Ÿè¯¾ç¨‹åˆ†é¡µ
  getDemo03CoursePage: async (params) => {
    return await request.get({ url: `/infra/demo03-student-erp/demo03-course/page`, params })
  },
  // æ–°å¢žå­¦ç”Ÿè¯¾ç¨‹
  createDemo03Course: async (data: Demo03Course) => {
    return await request.post({ url: `/infra/demo03-student-erp/demo03-course/create`, data })
  },
  // ä¿®æ”¹å­¦ç”Ÿè¯¾ç¨‹
  updateDemo03Course: async (data: Demo03Course) => {
    return await request.put({ url: `/infra/demo03-student-erp/demo03-course/update`, data })
  },
  // åˆ é™¤å­¦ç”Ÿè¯¾ç¨‹
  deleteDemo03Course: async (id: number) => {
    return await request.delete({ url: `/infra/demo03-student-erp/demo03-course/delete?id=` + id })
  },
  /** æ‰¹é‡åˆ é™¤å­¦ç”Ÿè¯¾ç¨‹ */
  deleteDemo03CourseList: async (ids: number[]) => {
    return await request.delete({ url: `/infra/demo03-student-erp/demo03-course/delete-list?ids=${ids.join(',')}` })
  },
  // èŽ·å¾—å­¦ç”Ÿè¯¾ç¨‹
  getDemo03Course: async (id: number) => {
    return await request.get({ url: `/infra/demo03-student-erp/demo03-course/get?id=` + id })
  },
// ==================== å­è¡¨ï¼ˆå­¦ç”Ÿç­çº§ï¼‰ ====================
  // èŽ·å¾—å­¦ç”Ÿç­çº§åˆ†é¡µ
  getDemo03GradePage: async (params) => {
    return await request.get({ url: `/infra/demo03-student-erp/demo03-grade/page`, params })
  },
  // æ–°å¢žå­¦ç”Ÿç­çº§
  createDemo03Grade: async (data: Demo03Grade) => {
    return await request.post({ url: `/infra/demo03-student-erp/demo03-grade/create`, data })
  },
  // ä¿®æ”¹å­¦ç”Ÿç­çº§
  updateDemo03Grade: async (data: Demo03Grade) => {
    return await request.put({ url: `/infra/demo03-student-erp/demo03-grade/update`, data })
  },
  // åˆ é™¤å­¦ç”Ÿç­çº§
  deleteDemo03Grade: async (id: number) => {
    return await request.delete({ url: `/infra/demo03-student-erp/demo03-grade/delete?id=` + id })
  },
  /** æ‰¹é‡åˆ é™¤å­¦ç”Ÿç­çº§ */
  deleteDemo03GradeList: async (ids: number[]) => {
    return await request.delete({ url: `/infra/demo03-student-erp/demo03-grade/delete-list?ids=${ids.join(',')}` })
  },
  // èŽ·å¾—å­¦ç”Ÿç­çº§
  getDemo03Grade: async (id: number) => {
    return await request.get({ url: `/infra/demo03-student-erp/demo03-grade/get?id=` + id })
  },
}
src/api/infra/demo/demo03/inner/index.ts
New file
@@ -0,0 +1,81 @@
import request from '@/config/axios'
import type { Dayjs } from 'dayjs';
/** å­¦ç”Ÿè¯¾ç¨‹ä¿¡æ¯ */
export interface Demo03Course {
  id: number; // ç¼–号
  studentId?: number; // å­¦ç”Ÿç¼–号
  name?: string; // åå­—
  score?: number; // åˆ†æ•°
}
/** å­¦ç”Ÿç­çº§ä¿¡æ¯ */
export interface Demo03Grade {
  id: number; // ç¼–号
  studentId?: number; // å­¦ç”Ÿç¼–号
  name?: string; // åå­—
  teacher?: string; // ç­ä¸»ä»»
}
/** å­¦ç”Ÿä¿¡æ¯ */
export interface Demo03Student {
  id: number; // ç¼–号
  name?: string; // åå­—
  sex?: number; // æ€§åˆ«
  birthday?: string | Dayjs; // å‡ºç”Ÿæ—¥æœŸ
  description?: string; // ç®€ä»‹
  demo03courses?: Demo03Course[]
  demo03grade?: Demo03Grade
}
// å­¦ç”Ÿ API
export const Demo03StudentApi = {
  // æŸ¥è¯¢å­¦ç”Ÿåˆ†é¡µ
  getDemo03StudentPage: async (params: any) => {
    return await request.get({ url: `/infra/demo03-student-inner/page`, params })
  },
  // æŸ¥è¯¢å­¦ç”Ÿè¯¦æƒ…
  getDemo03Student: async (id: number) => {
    return await request.get({ url: `/infra/demo03-student-inner/get?id=` + id })
  },
  // æ–°å¢žå­¦ç”Ÿ
  createDemo03Student: async (data: Demo03Student) => {
    return await request.post({ url: `/infra/demo03-student-inner/create`, data })
  },
  // ä¿®æ”¹å­¦ç”Ÿ
  updateDemo03Student: async (data: Demo03Student) => {
    return await request.put({ url: `/infra/demo03-student-inner/update`, data })
  },
  // åˆ é™¤å­¦ç”Ÿ
  deleteDemo03Student: async (id: number) => {
    return await request.delete({ url: `/infra/demo03-student-inner/delete?id=` + id })
  },
  /** æ‰¹é‡åˆ é™¤å­¦ç”Ÿ */
  deleteDemo03StudentList: async (ids: number[]) => {
    return await request.delete({ url: `/infra/demo03-student-inner/delete-list?ids=${ids.join(',')}` })
  },
  // å¯¼å‡ºå­¦ç”Ÿ Excel
  exportDemo03Student: async (params) => {
    return await request.download({ url: `/infra/demo03-student-inner/export-excel`, params })
  },
// ==================== å­è¡¨ï¼ˆå­¦ç”Ÿè¯¾ç¨‹ï¼‰ ====================
  // èŽ·å¾—å­¦ç”Ÿè¯¾ç¨‹åˆ—è¡¨
  getDemo03CourseListByStudentId: async (studentId) => {
    return await request.get({ url: `/infra/demo03-student-inner/demo03-course/list-by-student-id?studentId=` + studentId })
  },
// ==================== å­è¡¨ï¼ˆå­¦ç”Ÿç­çº§ï¼‰ ====================
  // èŽ·å¾—å­¦ç”Ÿç­çº§
  getDemo03GradeByStudentId: async (studentId) => {
    return await request.get({ url: `/infra/demo03-student-inner/demo03-grade/get-by-student-id?studentId=` + studentId })
  },
}
src/api/infra/demo/demo03/normal/index.ts
New file
@@ -0,0 +1,81 @@
import request from '@/config/axios'
import type { Dayjs } from 'dayjs';
/** å­¦ç”Ÿè¯¾ç¨‹ä¿¡æ¯ */
export interface Demo03Course {
  id: number; // ç¼–号
  studentId?: number; // å­¦ç”Ÿç¼–号
  name?: string; // åå­—
  score?: number; // åˆ†æ•°
}
/** å­¦ç”Ÿç­çº§ä¿¡æ¯ */
export interface Demo03Grade {
  id: number; // ç¼–号
  studentId?: number; // å­¦ç”Ÿç¼–号
  name?: string; // åå­—
  teacher?: string; // ç­ä¸»ä»»
}
/** å­¦ç”Ÿä¿¡æ¯ */
export interface Demo03Student {
  id: number; // ç¼–号
  name?: string; // åå­—
  sex?: number; // æ€§åˆ«
  birthday?: string | Dayjs; // å‡ºç”Ÿæ—¥æœŸ
  description?: string; // ç®€ä»‹
  demo03courses?: Demo03Course[]
  demo03grade?: Demo03Grade
}
// å­¦ç”Ÿ API
export const Demo03StudentApi = {
  // æŸ¥è¯¢å­¦ç”Ÿåˆ†é¡µ
  getDemo03StudentPage: async (params: any) => {
    return await request.get({ url: `/infra/demo03-student-normal/page`, params })
  },
  // æŸ¥è¯¢å­¦ç”Ÿè¯¦æƒ…
  getDemo03Student: async (id: number) => {
    return await request.get({ url: `/infra/demo03-student-normal/get?id=` + id })
  },
  // æ–°å¢žå­¦ç”Ÿ
  createDemo03Student: async (data: Demo03Student) => {
    return await request.post({ url: `/infra/demo03-student-normal/create`, data })
  },
  // ä¿®æ”¹å­¦ç”Ÿ
  updateDemo03Student: async (data: Demo03Student) => {
    return await request.put({ url: `/infra/demo03-student-normal/update`, data })
  },
  // åˆ é™¤å­¦ç”Ÿ
  deleteDemo03Student: async (id: number) => {
    return await request.delete({ url: `/infra/demo03-student-normal/delete?id=` + id })
  },
  /** æ‰¹é‡åˆ é™¤å­¦ç”Ÿ */
  deleteDemo03StudentList: async (ids: number[]) => {
    return await request.delete({ url: `/infra/demo03-student-normal/delete-list?ids=${ids.join(',')}` })
  },
  // å¯¼å‡ºå­¦ç”Ÿ Excel
  exportDemo03Student: async (params) => {
    return await request.download({ url: `/infra/demo03-student-normal/export-excel`, params })
  },
// ==================== å­è¡¨ï¼ˆå­¦ç”Ÿè¯¾ç¨‹ï¼‰ ====================
  // èŽ·å¾—å­¦ç”Ÿè¯¾ç¨‹åˆ—è¡¨
  getDemo03CourseListByStudentId: async (studentId) => {
    return await request.get({ url: `/infra/demo03-student-normal/demo03-course/list-by-student-id?studentId=` + studentId })
  },
// ==================== å­è¡¨ï¼ˆå­¦ç”Ÿç­çº§ï¼‰ ====================
  // èŽ·å¾—å­¦ç”Ÿç­çº§
  getDemo03GradeByStudentId: async (studentId) => {
    return await request.get({ url: `/infra/demo03-student-normal/demo03-grade/get-by-student-id?studentId=` + studentId })
  },
}
src/api/infra/file/index.ts
New file
@@ -0,0 +1,46 @@
import request from '@/config/axios'
// æ–‡ä»¶é¢„签名地址 Response VO
export interface FilePresignedUrlRespVO {
  // æ–‡ä»¶é…ç½®ç¼–号
  configId: number
  // æ–‡ä»¶ä¸Šä¼  URL
  uploadUrl: string
  // æ–‡ä»¶ URL
  url: string
  // æ–‡ä»¶è·¯å¾„
  path: string
}
// æŸ¥è¯¢æ–‡ä»¶åˆ—表
export const getFilePage = (params: PageParam) => {
  return request.get({ url: '/infra/file/page', params })
}
// åˆ é™¤æ–‡ä»¶
export const deleteFile = (id: number) => {
  return request.delete({ url: '/infra/file/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤æ–‡ä»¶
export const deleteFileList = (ids: number[]) => {
  return request.delete({ url: '/infra/file/delete-list', params: { ids: ids.join(',') } })
}
// èŽ·å–æ–‡ä»¶é¢„ç­¾ååœ°å€
export const getFilePresignedUrl = (name: string, directory?: string) => {
  return request.get<FilePresignedUrlRespVO>({
    url: '/infra/file/presigned-url',
    params: { name, directory }
  })
}
// åˆ›å»ºæ–‡ä»¶
export const createFile = (data: any) => {
  return request.post({ url: '/infra/file/create', data })
}
// ä¸Šä¼ æ–‡ä»¶
export const updateFile = (data: any, onUploadProgress?: Function) => {
  return request.upload({ url: '/infra/file/upload', data, onUploadProgress })
}
src/api/infra/fileConfig/index.ts
New file
@@ -0,0 +1,69 @@
import request from '@/config/axios'
export interface FileClientConfig {
  basePath: string
  host?: string
  port?: number
  username?: string
  password?: string
  mode?: string
  endpoint?: string
  bucket?: string
  accessKey?: string
  accessSecret?: string
  enablePathStyleAccess?: boolean
  enablePublicAccess?: boolean
  region?: string
  domain: string
}
export interface FileConfigVO {
  id: number
  name: string
  storage?: number
  master: boolean
  visible: boolean
  config: FileClientConfig
  remark: string
  createTime: Date
}
// æŸ¥è¯¢æ–‡ä»¶é…ç½®åˆ—表
export const getFileConfigPage = (params: PageParam) => {
  return request.get({ url: '/infra/file-config/page', params })
}
// æŸ¥è¯¢æ–‡ä»¶é…ç½®è¯¦æƒ…
export const getFileConfig = (id: number) => {
  return request.get({ url: '/infra/file-config/get?id=' + id })
}
// æ›´æ–°æ–‡ä»¶é…ç½®ä¸ºä¸»é…ç½®
export const updateFileConfigMaster = (id: number) => {
  return request.put({ url: '/infra/file-config/update-master?id=' + id })
}
// æ–°å¢žæ–‡ä»¶é…ç½®
export const createFileConfig = (data: FileConfigVO) => {
  return request.post({ url: '/infra/file-config/create', data })
}
// ä¿®æ”¹æ–‡ä»¶é…ç½®
export const updateFileConfig = (data: FileConfigVO) => {
  return request.put({ url: '/infra/file-config/update', data })
}
// åˆ é™¤æ–‡ä»¶é…ç½®
export const deleteFileConfig = (id: number) => {
  return request.delete({ url: '/infra/file-config/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤æ–‡ä»¶é…ç½®
export const deleteFileConfigList = (ids: number[]) => {
  return request.delete({ url: '/infra/file-config/delete-list', params: { ids: ids.join(',') } })
}
// æµ‹è¯•文件配置
export const testFileConfig = (id: number) => {
  return request.get({ url: '/infra/file-config/test?id=' + id })
}
src/api/infra/job/index.ts
New file
@@ -0,0 +1,68 @@
import request from '@/config/axios'
export interface JobVO {
  id: number
  name: string
  status: number
  handlerName: string
  handlerParam: string
  cronExpression: string
  retryCount: number
  retryInterval: number
  monitorTimeout: number
  createTime: Date
}
// ä»»åŠ¡åˆ—è¡¨
export const getJobPage = (params: PageParam) => {
  return request.get({ url: '/infra/job/page', params })
}
// ä»»åŠ¡è¯¦æƒ…
export const getJob = (id: number) => {
  return request.get({ url: '/infra/job/get?id=' + id })
}
// æ–°å¢žä»»åŠ¡
export const createJob = (data: JobVO) => {
  return request.post({ url: '/infra/job/create', data })
}
// ä¿®æ”¹å®šæ—¶ä»»åŠ¡è°ƒåº¦
export const updateJob = (data: JobVO) => {
  return request.put({ url: '/infra/job/update', data })
}
// åˆ é™¤å®šæ—¶ä»»åŠ¡è°ƒåº¦
export const deleteJob = (id: number) => {
  return request.delete({ url: '/infra/job/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤å®šæ—¶ä»»åŠ¡è°ƒåº¦
export const deleteJobList = (ids: number[]) => {
  return request.delete({ url: '/infra/job/delete-list', params: { ids: ids.join(',') } })
}
// å¯¼å‡ºå®šæ—¶ä»»åŠ¡è°ƒåº¦
export const exportJob = (params) => {
  return request.download({ url: '/infra/job/export-excel', params })
}
// ä»»åŠ¡çŠ¶æ€ä¿®æ”¹
export const updateJobStatus = (id: number, status: number) => {
  const params = {
    id,
    status
  }
  return request.put({ url: '/infra/job/update-status', params })
}
// å®šæ—¶ä»»åŠ¡ç«‹å³æ‰§è¡Œä¸€æ¬¡
export const runJob = (id: number) => {
  return request.put({ url: '/infra/job/trigger?id=' + id })
}
// èŽ·å¾—å®šæ—¶ä»»åŠ¡çš„ä¸‹ n æ¬¡æ‰§è¡Œæ—¶é—´
export const getJobNextTimes = (id: number) => {
  return request.get({ url: '/infra/job/get_next_times?id=' + id })
}
src/api/infra/jobLog/index.ts
New file
@@ -0,0 +1,34 @@
import request from '@/config/axios'
export interface JobLogVO {
  id: number
  jobId: number
  handlerName: string
  handlerParam: string
  cronExpression: string
  executeIndex: string
  beginTime: Date
  endTime: Date
  duration: string
  status: number
  createTime: string
  result: string
}
// ä»»åŠ¡æ—¥å¿—åˆ—è¡¨
export const getJobLogPage = (params: PageParam) => {
  return request.get({ url: '/infra/job-log/page', params })
}
// ä»»åŠ¡æ—¥å¿—è¯¦æƒ…
export const getJobLog = (id: number) => {
  return request.get({ url: '/infra/job-log/get?id=' + id })
}
// å¯¼å‡ºå®šæ—¶ä»»åŠ¡æ—¥å¿—
export const exportJobLog = (params) => {
  return request.download({
    url: '/infra/job-log/export-excel',
    params
  })
}
src/api/infra/redis/index.ts
New file
@@ -0,0 +1,8 @@
import request from '@/config/axios'
/**
 * èŽ·å–redis ç›‘控信息
 */
export const getCache = () => {
  return request.get({ url: '/infra/redis/get-monitor-info' })
}
src/api/infra/redis/types.ts
New file
@@ -0,0 +1,176 @@
export interface RedisMonitorInfoVO {
  info: RedisInfoVO
  dbSize: number
  commandStats: RedisCommandStatsVO[]
}
export interface RedisInfoVO {
  io_threaded_reads_processed: string
  tracking_clients: string
  uptime_in_seconds: string
  cluster_connections: string
  current_cow_size: string
  maxmemory_human: string
  aof_last_cow_size: string
  master_replid2: string
  mem_replication_backlog: string
  aof_rewrite_scheduled: string
  total_net_input_bytes: string
  rss_overhead_ratio: string
  hz: string
  current_cow_size_age: string
  redis_build_id: string
  errorstat_BUSYGROUP: string
  aof_last_bgrewrite_status: string
  multiplexing_api: string
  client_recent_max_output_buffer: string
  allocator_resident: string
  mem_fragmentation_bytes: string
  aof_current_size: string
  repl_backlog_first_byte_offset: string
  tracking_total_prefixes: string
  redis_mode: string
  redis_git_dirty: string
  aof_delayed_fsync: string
  allocator_rss_bytes: string
  repl_backlog_histlen: string
  io_threads_active: string
  rss_overhead_bytes: string
  total_system_memory: string
  loading: string
  evicted_keys: string
  maxclients: string
  cluster_enabled: string
  redis_version: string
  repl_backlog_active: string
  mem_aof_buffer: string
  allocator_frag_bytes: string
  io_threaded_writes_processed: string
  instantaneous_ops_per_sec: string
  used_memory_human: string
  total_error_replies: string
  role: string
  maxmemory: string
  used_memory_lua: string
  rdb_current_bgsave_time_sec: string
  used_memory_startup: string
  used_cpu_sys_main_thread: string
  lazyfree_pending_objects: string
  aof_pending_bio_fsync: string
  used_memory_dataset_perc: string
  allocator_frag_ratio: string
  arch_bits: string
  used_cpu_user_main_thread: string
  mem_clients_normal: string
  expired_time_cap_reached_count: string
  unexpected_error_replies: string
  mem_fragmentation_ratio: string
  aof_last_rewrite_time_sec: string
  master_replid: string
  aof_rewrite_in_progress: string
  lru_clock: string
  maxmemory_policy: string
  run_id: string
  latest_fork_usec: string
  tracking_total_items: string
  total_commands_processed: string
  expired_keys: string
  errorstat_ERR: string
  used_memory: string
  module_fork_in_progress: string
  errorstat_WRONGPASS: string
  aof_buffer_length: string
  dump_payload_sanitizations: string
  mem_clients_slaves: string
  keyspace_misses: string
  server_time_usec: string
  executable: string
  lazyfreed_objects: string
  db0: string
  used_memory_peak_human: string
  keyspace_hits: string
  rdb_last_cow_size: string
  aof_pending_rewrite: string
  used_memory_overhead: string
  active_defrag_hits: string
  tcp_port: string
  uptime_in_days: string
  used_memory_peak_perc: string
  current_save_keys_processed: string
  blocked_clients: string
  total_reads_processed: string
  expire_cycle_cpu_milliseconds: string
  sync_partial_err: string
  used_memory_scripts_human: string
  aof_current_rewrite_time_sec: string
  aof_enabled: string
  process_supervised: string
  master_repl_offset: string
  used_memory_dataset: string
  used_cpu_user: string
  rdb_last_bgsave_status: string
  tracking_total_keys: string
  atomicvar_api: string
  allocator_rss_ratio: string
  client_recent_max_input_buffer: string
  clients_in_timeout_table: string
  aof_last_write_status: string
  mem_allocator: string
  used_memory_scripts: string
  used_memory_peak: string
  process_id: string
  master_failover_state: string
  errorstat_NOAUTH: string
  used_cpu_sys: string
  repl_backlog_size: string
  connected_slaves: string
  current_save_keys_total: string
  gcc_version: string
  total_system_memory_human: string
  sync_full: string
  connected_clients: string
  module_fork_last_cow_size: string
  total_writes_processed: string
  allocator_active: string
  total_net_output_bytes: string
  pubsub_channels: string
  current_fork_perc: string
  active_defrag_key_hits: string
  rdb_changes_since_last_save: string
  instantaneous_input_kbps: string
  used_memory_rss_human: string
  configured_hz: string
  expired_stale_perc: string
  active_defrag_misses: string
  used_cpu_sys_children: string
  number_of_cached_scripts: string
  sync_partial_ok: string
  used_memory_lua_human: string
  rdb_last_save_time: string
  pubsub_patterns: string
  slave_expires_tracked_keys: string
  redis_git_sha1: string
  used_memory_rss: string
  rdb_last_bgsave_time_sec: string
  os: string
  mem_not_counted_for_evict: string
  active_defrag_running: string
  rejected_connections: string
  aof_rewrite_buffer_length: string
  total_forks: string
  active_defrag_key_misses: string
  allocator_allocated: string
  aof_base_size: string
  instantaneous_output_kbps: string
  second_repl_offset: string
  rdb_bgsave_in_progress: string
  used_cpu_user_children: string
  total_connections_received: string
  migrate_cached_sockets: string
}
export interface RedisCommandStatsVO {
  command: string
  calls: number
  usec: number
}
src/api/iot/alert/config/index.ts
New file
@@ -0,0 +1,46 @@
import request from '@/config/axios'
/** IoT å‘Šè­¦é…ç½®ä¿¡æ¯ */
export interface AlertConfig {
  id: number // é…ç½®ç¼–号
  name?: string // é…ç½®åç§°
  description: string // é…ç½®æè¿°
  level?: number // å‘Šè­¦çº§åˆ«
  status?: number // é…ç½®çŠ¶æ€
  sceneRuleIds: string // å…³è”的场景联动规则编号数组
  receiveUserIds: string // æŽ¥æ”¶çš„用户编号数组
  receiveTypes: string // æŽ¥æ”¶çš„类型数组
}
// IoT å‘Šè­¦é…ç½® API
export const AlertConfigApi = {
  // æŸ¥è¯¢å‘Šè­¦é…ç½®åˆ†é¡µ
  getAlertConfigPage: async (params: any) => {
    return await request.get({ url: `/iot/alert-config/page`, params })
  },
  // æŸ¥è¯¢å‘Šè­¦é…ç½®è¯¦æƒ…
  getAlertConfig: async (id: number) => {
    return await request.get({ url: `/iot/alert-config/get?id=` + id })
  },
  // æ–°å¢žå‘Šè­¦é…ç½®
  createAlertConfig: async (data: AlertConfig) => {
    return await request.post({ url: `/iot/alert-config/create`, data })
  },
  // ä¿®æ”¹å‘Šè­¦é…ç½®
  updateAlertConfig: async (data: AlertConfig) => {
    return await request.put({ url: `/iot/alert-config/update`, data })
  },
  // åˆ é™¤å‘Šè­¦é…ç½®
  deleteAlertConfig: async (id: number) => {
    return await request.delete({ url: `/iot/alert-config/delete?id=` + id })
  },
  // èŽ·å–å‘Šè­¦é…ç½®ç®€å•åˆ—è¡¨
  getSimpleAlertConfigList: async () => {
    return await request.get({ url: `/iot/alert-config/simple-list` })
  }
}
src/api/iot/alert/record/index.ts
New file
@@ -0,0 +1,35 @@
import request from '@/config/axios'
/** IoT å‘Šè­¦è®°å½•信息 */
export interface AlertRecord {
  id: number // è®°å½•编号
  configId: number // å‘Šè­¦é…ç½®ç¼–号
  configName: string // å‘Šè­¦åç§°
  configLevel: number // å‘Šè­¦çº§åˆ«
  productId: number // äº§å“ç¼–号
  deviceId: number // è®¾å¤‡ç¼–号
  deviceMessage: any // è§¦å‘的设备消息
  processStatus?: boolean // æ˜¯å¦å¤„理
  processRemark: string // å¤„理结果(备注)
}
// IoT å‘Šè­¦è®°å½• API
export const AlertRecordApi = {
  // æŸ¥è¯¢å‘Šè­¦è®°å½•分页
  getAlertRecordPage: async (params: any) => {
    return await request.get({ url: `/iot/alert-record/page`, params })
  },
  // æŸ¥è¯¢å‘Šè­¦è®°å½•详情
  getAlertRecord: async (id: number) => {
    return await request.get({ url: `/iot/alert-record/get?id=` + id })
  },
  // å¤„理告警记录
  processAlertRecord: async (id: number, processRemark: string) => {
    return await request.put({
      url: `/iot/alert-record/process`,
      data: { id, processRemark }
    })
  }
}
src/api/iot/device/device/index.ts
New file
@@ -0,0 +1,165 @@
import request from '@/config/axios'
// IoT è®¾å¤‡ VO
export interface DeviceVO {
  id: number // è®¾å¤‡ ID,主键,自增
  deviceName: string // è®¾å¤‡åç§°
  productId: number // äº§å“ç¼–号
  productKey: string // äº§å“æ ‡è¯†
  deviceType: number // è®¾å¤‡ç±»åž‹
  nickname: string // è®¾å¤‡å¤‡æ³¨åç§°
  gatewayId: number // ç½‘关设备 ID
  state: number // è®¾å¤‡çŠ¶æ€
  onlineTime: Date // æœ€åŽä¸Šçº¿æ—¶é—´
  offlineTime: Date // æœ€åŽç¦»çº¿æ—¶é—´
  activeTime: Date // è®¾å¤‡æ¿€æ´»æ—¶é—´
  createTime: Date // åˆ›å»ºæ—¶é—´
  ip: string // è®¾å¤‡çš„ IP åœ°å€
  firmwareVersion: string // è®¾å¤‡çš„固件版本
  deviceSecret: string // è®¾å¤‡å¯†é’¥ï¼Œç”¨äºŽè®¾å¤‡è®¤è¯ï¼Œéœ€å®‰å…¨å­˜å‚¨
  mqttClientId: string // MQTT å®¢æˆ·ç«¯ ID
  mqttUsername: string // MQTT ç”¨æˆ·å
  mqttPassword: string // MQTT å¯†ç 
  authType: string // è®¤è¯ç±»åž‹
  locationType: number // å®šä½ç±»åž‹
  latitude?: number // è®¾å¤‡ä½ç½®çš„纬度
  longitude?: number // è®¾å¤‡ä½ç½®çš„经度
  areaId: number // åœ°åŒºç¼–码
  address: string // è®¾å¤‡è¯¦ç»†åœ°å€
  serialNumber: string // è®¾å¤‡åºåˆ—号
  config: string // è®¾å¤‡é…ç½®
  groupIds?: number[] // æ·»åŠ åˆ†ç»„ ID
}
// IoT è®¾å¤‡å±žæ€§è¯¦ç»† VO
export interface IotDevicePropertyDetailRespVO {
  identifier: string // å±žæ€§æ ‡è¯†ç¬¦
  value: string // æœ€æ–°å€¼
  updateTime: Date // æ›´æ–°æ—¶é—´
  name: string // å±žæ€§åç§°
  dataType: string // æ•°æ®ç±»åž‹
  dataSpecs: any // æ•°æ®å®šä¹‰
  dataSpecsList: any[] // æ•°æ®å®šä¹‰åˆ—表
}
// IoT è®¾å¤‡å±žæ€§ VO
export interface IotDevicePropertyRespVO {
  identifier: string // å±žæ€§æ ‡è¯†ç¬¦
  value: string // æœ€æ–°å€¼
  updateTime: Date // æ›´æ–°æ—¶é—´
}
// TODO @芋艿:调整到 constants
// IoT è®¾å¤‡çŠ¶æ€æžšä¸¾
export enum DeviceStateEnum {
  INACTIVE = 0, // æœªæ¿€æ´»
  ONLINE = 1, // åœ¨çº¿
  OFFLINE = 2 // ç¦»çº¿
}
// è®¾å¤‡è®¤è¯å‚æ•° VO
export interface IotDeviceAuthInfoVO {
  clientId: string // å®¢æˆ·ç«¯ ID
  username: string // ç”¨æˆ·å
  password: string // å¯†ç 
}
// IoT è®¾å¤‡å‘送消息 Request VO
export interface IotDeviceMessageSendReqVO {
  deviceId: number // è®¾å¤‡ç¼–号
  method: string // è¯·æ±‚方法
  params?: any // è¯·æ±‚参数
}
// è®¾å¤‡ API
export const DeviceApi = {
  // æŸ¥è¯¢è®¾å¤‡åˆ†é¡µ
  getDevicePage: async (params: any) => {
    return await request.get({ url: `/iot/device/page`, params })
  },
  // æŸ¥è¯¢è®¾å¤‡è¯¦æƒ…
  getDevice: async (id: number) => {
    return await request.get({ url: `/iot/device/get?id=` + id })
  },
  // æ–°å¢žè®¾å¤‡
  createDevice: async (data: DeviceVO) => {
    return await request.post({ url: `/iot/device/create`, data })
  },
  // ä¿®æ”¹è®¾å¤‡
  updateDevice: async (data: DeviceVO) => {
    return await request.put({ url: `/iot/device/update`, data })
  },
  // ä¿®æ”¹è®¾å¤‡åˆ†ç»„
  updateDeviceGroup: async (data: { ids: number[]; groupIds: number[] }) => {
    return await request.put({ url: `/iot/device/update-group`, data })
  },
  // åˆ é™¤å•个设备
  deleteDevice: async (id: number) => {
    return await request.delete({ url: `/iot/device/delete?id=` + id })
  },
  // åˆ é™¤å¤šä¸ªè®¾å¤‡
  deleteDeviceList: async (ids: number[]) => {
    return await request.delete({ url: `/iot/device/delete-list`, params: { ids: ids.join(',') } })
  },
  // å¯¼å‡ºè®¾å¤‡
  exportDeviceExcel: async (params: any) => {
    return await request.download({ url: `/iot/device/export-excel`, params })
  },
  // èŽ·å–è®¾å¤‡æ•°é‡
  getDeviceCount: async (productId: number) => {
    return await request.get({ url: `/iot/device/count?productId=` + productId })
  },
  // èŽ·å–è®¾å¤‡çš„ç²¾ç®€ä¿¡æ¯åˆ—è¡¨
  getSimpleDeviceList: async (deviceType?: number, productId?: number) => {
    return await request.get({ url: `/iot/device/simple-list?`, params: { deviceType, productId } })
  },
  // æ ¹æ®äº§å“ç¼–号,获取设备的精简信息列表
  getDeviceListByProductId: async (productId: number) => {
    return await request.get({ url: `/iot/device/simple-list?`, params: { productId } })
  },
  // èŽ·å–å¯¼å…¥æ¨¡æ¿
  importDeviceTemplate: async () => {
    return await request.download({ url: `/iot/device/get-import-template` })
  },
  // èŽ·å–è®¾å¤‡å±žæ€§æœ€æ–°æ•°æ®
  getLatestDeviceProperties: async (params: any) => {
    return await request.get({ url: `/iot/device/property/get-latest`, params })
  },
  // èŽ·å–è®¾å¤‡å±žæ€§åŽ†å²æ•°æ®
  getHistoryDevicePropertyList: async (params: any) => {
    return await request.get({ url: `/iot/device/property/history-list`, params })
  },
  // èŽ·å–è®¾å¤‡è®¤è¯ä¿¡æ¯
  getDeviceAuthInfo: async (id: number) => {
    return await request.get({ url: `/iot/device/get-auth-info`, params: { id } })
  },
  // æŸ¥è¯¢è®¾å¤‡æ¶ˆæ¯åˆ†é¡µ
  getDeviceMessagePage: async (params: any) => {
    return await request.get({ url: `/iot/device/message/page`, params })
  },
  // æŸ¥è¯¢è®¾å¤‡æ¶ˆæ¯é…å¯¹åˆ†é¡µ
  getDeviceMessagePairPage: async (params: any) => {
    return await request.get({ url: `/iot/device/message/pair-page`, params })
  },
  // å‘送设备消息
  sendDeviceMessage: async (params: IotDeviceMessageSendReqVO) => {
    return await request.post({ url: `/iot/device/message/send`, data: params })
  }
}
src/api/iot/device/group/index.ts
New file
@@ -0,0 +1,43 @@
import request from '@/config/axios'
// IoT è®¾å¤‡åˆ†ç»„ VO
export interface DeviceGroupVO {
  id: number // åˆ†ç»„ ID
  name: string // åˆ†ç»„名字
  status: number // åˆ†ç»„状态
  description: string // åˆ†ç»„描述
  deviceCount?: number // è®¾å¤‡æ•°é‡
}
// IoT è®¾å¤‡åˆ†ç»„ API
export const DeviceGroupApi = {
  // æŸ¥è¯¢è®¾å¤‡åˆ†ç»„分页
  getDeviceGroupPage: async (params: any) => {
    return await request.get({ url: `/iot/device-group/page`, params })
  },
  // æŸ¥è¯¢è®¾å¤‡åˆ†ç»„详情
  getDeviceGroup: async (id: number) => {
    return await request.get({ url: `/iot/device-group/get?id=` + id })
  },
  // æ–°å¢žè®¾å¤‡åˆ†ç»„
  createDeviceGroup: async (data: DeviceGroupVO) => {
    return await request.post({ url: `/iot/device-group/create`, data })
  },
  // ä¿®æ”¹è®¾å¤‡åˆ†ç»„
  updateDeviceGroup: async (data: DeviceGroupVO) => {
    return await request.put({ url: `/iot/device-group/update`, data })
  },
  // åˆ é™¤è®¾å¤‡åˆ†ç»„
  deleteDeviceGroup: async (id: number) => {
    return await request.delete({ url: `/iot/device-group/delete?id=` + id })
  },
  // èŽ·å–è®¾å¤‡åˆ†ç»„çš„ç²¾ç®€ä¿¡æ¯åˆ—è¡¨
  getSimpleDeviceGroupList: async () => {
    return await request.get({ url: `/iot/device-group/simple-list` })
  }
}
src/api/iot/ota/firmware/index.ts
New file
@@ -0,0 +1,44 @@
import request from '@/config/axios'
/** IoT OTA å›ºä»¶ä¿¡æ¯ */
export interface IoTOtaFirmware {
  id?: number // å›ºä»¶ç¼–号
  name?: string // å›ºä»¶åç§°
  description?: string // å›ºä»¶æè¿°
  version?: string // ç‰ˆæœ¬å·
  productId?: number // äº§å“ç¼–号
  productName?: string // äº§å“åç§°
  fileUrl?: string // å›ºä»¶æ–‡ä»¶ URL
  fileSize?: number // å›ºä»¶æ–‡ä»¶å¤§å°
  fileDigestAlgorithm?: string // å›ºä»¶æ–‡ä»¶ç­¾åç®—法
  fileDigestValue?: string // å›ºä»¶æ–‡ä»¶ç­¾åç»“æžœ
  createTime?: Date // åˆ›å»ºæ—¶é—´
}
// IoT OTA å›ºä»¶ API
export const IoTOtaFirmwareApi = {
  // æŸ¥è¯¢ OTA å›ºä»¶åˆ†é¡µ
  getOtaFirmwarePage: async (params: any) => {
    return await request.get({ url: `/iot/ota/firmware/page`, params })
  },
  // æŸ¥è¯¢ OTA å›ºä»¶è¯¦æƒ…
  getOtaFirmware: async (id: number) => {
    return await request.get({ url: `/iot/ota/firmware/get?id=` + id })
  },
  // æ–°å¢ž OTA å›ºä»¶
  createOtaFirmware: async (data: IoTOtaFirmware) => {
    return await request.post({ url: `/iot/ota/firmware/create`, data })
  },
  // ä¿®æ”¹ OTA å›ºä»¶
  updateOtaFirmware: async (data: IoTOtaFirmware) => {
    return await request.put({ url: `/iot/ota/firmware/update`, data })
  },
  // åˆ é™¤ OTA å›ºä»¶
  deleteOtaFirmware: async (id: number) => {
    return await request.delete({ url: `/iot/ota/firmware/delete?id=` + id })
  }
}
src/api/iot/ota/task/index.ts
New file
@@ -0,0 +1,38 @@
import request from '@/config/axios'
/** IoT OTA ä»»åŠ¡ä¿¡æ¯ */
export interface OtaTask {
  id?: number // ä»»åŠ¡ç¼–å·
  name: string // ä»»åŠ¡åç§°
  description?: string // ä»»åŠ¡æè¿°
  firmwareId?: number // å›ºä»¶ç¼–号
  status: number // ä»»åŠ¡çŠ¶æ€
  deviceScope?: number // å‡çº§èŒƒå›´
  deviceIds?: number[] // æŒ‡å®šè®¾å¤‡ID列表(当升级范围为指定设备时使用)
  deviceTotalCount?: number // è®¾å¤‡æ€»å…±æ•°é‡
  deviceSuccessCount?: number // è®¾å¤‡æˆåŠŸæ•°é‡
  createTime?: Date // åˆ›å»ºæ—¶é—´
}
// IoT OTA ä»»åŠ¡ API
export const IoTOtaTaskApi = {
  // æŸ¥è¯¢ OTA å‡çº§ä»»åŠ¡åˆ†é¡µ
  getOtaTaskPage: async (params: any) => {
    return await request.get({ url: `/iot/ota/task/page`, params })
  },
  // æŸ¥è¯¢ OTA å‡çº§ä»»åŠ¡è¯¦æƒ…
  getOtaTask: async (id: number) => {
    return await request.get({ url: `/iot/ota/task/get?id=` + id })
  },
  // åˆ›å»º OTA å‡çº§ä»»åŠ¡
  createOtaTask: async (data: OtaTask) => {
    return await request.post({ url: `/iot/ota/task/create`, data })
  },
  // å–消 OTA å‡çº§ä»»åŠ¡
  cancelOtaTask: async (id: number) => {
    return await request.post({ url: `/iot/ota/task/cancel?id=` + id })
  }
}
src/api/iot/ota/task/record/index.ts
New file
@@ -0,0 +1,38 @@
import request from '@/config/axios'
/** IoT OTA ä»»åŠ¡è®°å½•ä¿¡æ¯ */
export interface OtaTaskRecord {
  id?: number // å‡çº§è®°å½•编号
  firmwareId?: number // å›ºä»¶ç¼–号
  firmwareVersion?: string // å›ºä»¶ç‰ˆæœ¬
  taskId?: number // ä»»åŠ¡ç¼–å·
  deviceId?: string // è®¾å¤‡ç¼–号
  deviceName?: string // è®¾å¤‡åç§°
  currentVersion?: string // å½“前版本
  fromFirmwareId?: number // æ¥æºçš„固件编号
  fromFirmwareVersion?: string // æ¥æºçš„固件版本
  status?: number // å‡çº§çŠ¶æ€
  progress?: number // å‡çº§è¿›åº¦ï¼Œç™¾åˆ†æ¯”
  description?: string // å‡çº§è¿›åº¦æè¿°
  updateTime?: Date // æ›´æ–°æ—¶é—´
}
// IoT OTA ä»»åŠ¡è®°å½• API
export const IoTOtaTaskRecordApi = {
  getOtaTaskRecordStatusStatistics: async (firmwareId?: number, taskId?: number) => {
    const params: any = {}
    if (firmwareId) params.firmwareId = firmwareId
    if (taskId) params.taskId = taskId
    return await request.get({ url: `/iot/ota/task/record/get-status-statistics`, params })
  },
  // æŸ¥è¯¢ OTA ä»»åŠ¡è®°å½•åˆ†é¡µ
  getOtaTaskRecordPage: async (params: any) => {
    return await request.get({ url: `/iot/ota/task/record/page`, params })
  },
  // å–消 OTA ä»»åŠ¡è®°å½•
  cancelOtaTaskRecord: async (id: number) => {
    return await request.put({ url: `/iot/ota/task/record/cancel?id=` + id })
  }
}
src/api/iot/product/category/index.ts
New file
@@ -0,0 +1,43 @@
import request from '@/config/axios'
// IoT äº§å“åˆ†ç±» VO
export interface ProductCategoryVO {
  id: number // åˆ†ç±» ID
  name: string // åˆ†ç±»åå­—
  sort: number // åˆ†ç±»æŽ’序
  status: number // åˆ†ç±»çŠ¶æ€
  description: string // åˆ†ç±»æè¿°
}
// IoT äº§å“åˆ†ç±» API
export const ProductCategoryApi = {
  // æŸ¥è¯¢äº§å“åˆ†ç±»åˆ†é¡µ
  getProductCategoryPage: async (params: any) => {
    return await request.get({ url: `/iot/product-category/page`, params })
  },
  // æŸ¥è¯¢äº§å“åˆ†ç±»è¯¦æƒ…
  getProductCategory: async (id: number) => {
    return await request.get({ url: `/iot/product-category/get?id=` + id })
  },
  // æ–°å¢žäº§å“åˆ†ç±»
  createProductCategory: async (data: ProductCategoryVO) => {
    return await request.post({ url: `/iot/product-category/create`, data })
  },
  // ä¿®æ”¹äº§å“åˆ†ç±»
  updateProductCategory: async (data: ProductCategoryVO) => {
    return await request.put({ url: `/iot/product-category/update`, data })
  },
  // åˆ é™¤äº§å“åˆ†ç±»
  deleteProductCategory: async (id: number) => {
    return await request.delete({ url: `/iot/product-category/delete?id=` + id })
  },
  /** èŽ·å–äº§å“åˆ†ç±»ç²¾ç®€åˆ—è¡¨ */
  getSimpleProductCategoryList: () => {
    return request.get({ url: '/iot/product-category/simple-list' })
  }
}
src/api/iot/product/product/index.ts
New file
@@ -0,0 +1,86 @@
import request from '@/config/axios'
// IoT äº§å“ VO
export interface ProductVO {
  id: number // äº§å“ç¼–号
  name: string // äº§å“åç§°
  productKey: string // äº§å“æ ‡è¯†
  protocolId: number // åè®®ç¼–号
  categoryId: number // äº§å“æ‰€å±žå“ç±»æ ‡è¯†ç¬¦
  categoryName?: string // äº§å“æ‰€å±žå“ç±»åç§°
  icon: string // äº§å“å›¾æ ‡
  picUrl: string // äº§å“å›¾ç‰‡
  description: string // äº§å“æè¿°
  status: number // äº§å“çŠ¶æ€
  deviceType: number // è®¾å¤‡ç±»åž‹
  locationType: number // è®¾å¤‡ç±»åž‹
  netType: number // è”网方式
  codecType: string // æ•°æ®æ ¼å¼ï¼ˆç¼–解码器类型)
  deviceCount: number // è®¾å¤‡æ•°é‡
  createTime: Date // åˆ›å»ºæ—¶é—´
}
// IOT äº§å“è®¾å¤‡ç±»åž‹æžšä¸¾ç±» 0: ç›´è¿žè®¾å¤‡, 1: ç½‘关子设备, 2: ç½‘关设备
export enum DeviceTypeEnum {
  DEVICE = 0, // ç›´è¿žè®¾å¤‡
  GATEWAY_SUB = 1, // ç½‘关子设备
  GATEWAY = 2 // ç½‘关设备
}
// IOT äº§å“å®šä½ç±»åž‹æžšä¸¾ç±» 0: æ‰‹åŠ¨å®šä½, 1: IP å®šä½, 2: å®šä½æ¨¡å—定位
export enum LocationTypeEnum {
  IP = 1, // IP å®šä½
  MODULE = 2, // è®¾å¤‡å®šä½
  MANUAL = 3 // æ‰‹åŠ¨å®šä½
}
// IOT æ•°æ®æ ¼å¼ï¼ˆç¼–解码器类型)枚举类
export enum CodecTypeEnum {
  ALINK = 'Alink' // é˜¿é‡Œäº‘ Alink åè®®
}
// IoT äº§å“ API
export const ProductApi = {
  // æŸ¥è¯¢äº§å“åˆ†é¡µ
  getProductPage: async (params: any) => {
    return await request.get({ url: `/iot/product/page`, params })
  },
  // æŸ¥è¯¢äº§å“è¯¦æƒ…
  getProduct: async (id: number) => {
    return await request.get({ url: `/iot/product/get?id=` + id })
  },
  // æ–°å¢žäº§å“
  createProduct: async (data: ProductVO) => {
    return await request.post({ url: `/iot/product/create`, data })
  },
  // ä¿®æ”¹äº§å“
  updateProduct: async (data: ProductVO) => {
    return await request.put({ url: `/iot/product/update`, data })
  },
  // åˆ é™¤äº§å“
  deleteProduct: async (id: number) => {
    return await request.delete({ url: `/iot/product/delete?id=` + id })
  },
  // å¯¼å‡ºäº§å“ Excel
  exportProduct: async (params) => {
    return await request.download({ url: `/iot/product/export-excel`, params })
  },
  // æ›´æ–°äº§å“çŠ¶æ€
  updateProductStatus: async (id: number, status: number) => {
    return await request.put({ url: `/iot/product/update-status?id=` + id + `&status=` + status })
  },
  // æŸ¥è¯¢äº§å“ï¼ˆç²¾ç®€ï¼‰åˆ—表
  getSimpleProductList() {
    return request.get({ url: '/iot/product/simple-list' })
  },
  // æ ¹æ® ProductKey èŽ·å–äº§å“ä¿¡æ¯
  getProductByKey: async (productKey: string) => {
    return await request.get({ url: `/iot/product/get-by-key`, params: { productKey } })
  }
}
src/api/iot/rule/data/rule/index.ts
New file
@@ -0,0 +1,39 @@
import request from '@/config/axios'
/** IoT æ•°æ®æµè½¬è§„则信息 */
export interface DataRule {
  id: number // åœºæ™¯ç¼–号
  name?: string // åœºæ™¯åç§°
  description: string // åœºæ™¯æè¿°
  status?: number // åœºæ™¯çŠ¶æ€
  sourceConfigs?: any[] // æ•°æ®æºé…ç½®æ•°ç»„
  sinkIds?: number[] // æ•°æ®ç›®çš„编号数组
}
// IoT æ•°æ®æµè½¬è§„则 API
export const DataRuleApi = {
  // æŸ¥è¯¢æ•°æ®æµè½¬è§„则分页
  getDataRulePage: async (params: any) => {
    return await request.get({ url: `/iot/data-rule/page`, params })
  },
  // æŸ¥è¯¢æ•°æ®æµè½¬è§„则详情
  getDataRule: async (id: number) => {
    return await request.get({ url: `/iot/data-rule/get?id=` + id })
  },
  // æ–°å¢žæ•°æ®æµè½¬è§„则
  createDataRule: async (data: DataRule) => {
    return await request.post({ url: `/iot/data-rule/create`, data })
  },
  // ä¿®æ”¹æ•°æ®æµè½¬è§„则
  updateDataRule: async (data: DataRule) => {
    return await request.put({ url: `/iot/data-rule/update`, data })
  },
  // åˆ é™¤æ•°æ®æµè½¬è§„则
  deleteDataRule: async (id: number) => {
    return await request.delete({ url: `/iot/data-rule/delete?id=` + id })
  }
}
src/api/iot/rule/data/sink/index.ts
New file
@@ -0,0 +1,126 @@
import request from '@/config/axios'
// IoT æ•°æ®æµè½¬ç›®çš„ VO
export interface DataSinkVO {
  id?: number // æ¡¥æ¢ç¼–号
  name?: string // æ¡¥æ¢åç§°
  description?: string // æ¡¥æ¢æè¿°
  status?: number // æ¡¥æ¢çŠ¶æ€
  direction?: number // æ¡¥æ¢æ–¹å‘
  type?: number // æ¡¥æ¢ç±»åž‹
  config?:
    | HttpConfig
    | MqttConfig
    | RocketMQConfig
    | KafkaMQConfig
    | RabbitMQConfig
    | RedisStreamMQConfig // æ¡¥æ¢é…ç½®
}
interface Config {
  type: string
}
/** HTTP é…ç½® */
export interface HttpConfig extends Config {
  url: string
  method: string
  headers: Record<string, string>
  query: Record<string, string>
  body: string
}
/** MQTT é…ç½® */
export interface MqttConfig extends Config {
  url: string
  username: string
  password: string
  clientId: string
  topic: string
}
/** RocketMQ é…ç½® */
export interface RocketMQConfig extends Config {
  nameServer: string
  accessKey: string
  secretKey: string
  group: string
  topic: string
  tags: string
}
/** Kafka é…ç½® */
export interface KafkaMQConfig extends Config {
  bootstrapServers: string
  username: string
  password: string
  ssl: boolean
  topic: string
}
/** RabbitMQ é…ç½® */
export interface RabbitMQConfig extends Config {
  host: string
  port: number
  virtualHost: string
  username: string
  password: string
  exchange: string
  routingKey: string
  queue: string
}
/** Redis Stream MQ é…ç½® */
export interface RedisStreamMQConfig extends Config {
  host: string
  port: number
  password: string
  database: number
  topic: string
}
/** æ•°æ®æµè½¬ç›®çš„类型 */
export const IotDataSinkTypeEnum = {
  HTTP: 1,
  TCP: 2,
  WEBSOCKET: 3,
  MQTT: 10,
  DATABASE: 20,
  REDIS_STREAM: 21,
  ROCKETMQ: 30,
  RABBITMQ: 31,
  KAFKA: 32
} as const
// æ•°æ®æµè½¬ç›®çš„ API
export const DataSinkApi = {
  // æŸ¥è¯¢æ•°æ®æµè½¬ç›®çš„分页
  getDataSinkPage: async (params: any) => {
    return await request.get({ url: `/iot/data-sink/page`, params })
  },
  // æŸ¥è¯¢æ•°æ®æµè½¬ç›®çš„详情
  getDataSink: async (id: number) => {
    return await request.get({ url: `/iot/data-sink/get?id=` + id })
  },
  // æ–°å¢žæ•°æ®æµè½¬ç›®çš„
  createDataSink: async (data: DataSinkVO) => {
    return await request.post({ url: `/iot/data-sink/create`, data })
  },
  // ä¿®æ”¹æ•°æ®æµè½¬ç›®çš„
  updateDataSink: async (data: DataSinkVO) => {
    return await request.put({ url: `/iot/data-sink/update`, data })
  },
  // åˆ é™¤æ•°æ®æµè½¬ç›®çš„
  deleteDataSink: async (id: number) => {
    return await request.delete({ url: `/iot/data-sink/delete?id=` + id })
  },
  // æŸ¥è¯¢æ•°æ®æµè½¬ç›®çš„(精简)列表
  getDataSinkSimpleList() {
    return request.get({ url: '/iot/data-sink/simple-list' })
  }
}
src/api/iot/rule/scene/index.ts
New file
@@ -0,0 +1,87 @@
import request from '@/config/axios'
// åœºæ™¯è”动
export interface IotSceneRule {
  id?: number // åœºæ™¯ç¼–号
  name: string // åœºæ™¯åç§°
  description?: string // åœºæ™¯æè¿°
  status: number // åœºæ™¯çŠ¶æ€ï¼š0-开启,1-关闭
  triggers: Trigger[] // è§¦å‘器数组
  actions: Action[] // æ‰§è¡Œå™¨æ•°ç»„
}
// è§¦å‘器结构
export interface Trigger {
  type: number // è§¦å‘类型
  productId?: number // äº§å“ç¼–号
  deviceId?: number // è®¾å¤‡ç¼–号
  identifier?: string // ç‰©æ¨¡åž‹æ ‡è¯†ç¬¦
  operator?: string // æ“ä½œç¬¦
  value?: string // å‚数值
  cronExpression?: string // CRON è¡¨è¾¾å¼
  conditionGroups?: TriggerCondition[][] // æ¡ä»¶ç»„(二维数组)
}
// è§¦å‘条件结构
export interface TriggerCondition {
  type: number // æ¡ä»¶ç±»åž‹ï¼š1-设备状态,2-设备属性,3-当前时间
  productId?: number // äº§å“ç¼–号
  deviceId?: number // è®¾å¤‡ç¼–号
  identifier?: string // æ ‡è¯†ç¬¦
  operator: string // æ“ä½œç¬¦
  param: string // å‚æ•°
}
// æ‰§è¡Œå™¨ç»“æž„
export interface Action {
  type: number // æ‰§è¡Œç±»åž‹
  productId?: number // äº§å“ç¼–号
  deviceId?: number // è®¾å¤‡ç¼–号
  identifier?: string // ç‰©æ¨¡åž‹æ ‡è¯†ç¬¦ï¼ˆæœåŠ¡è°ƒç”¨æ—¶ä½¿ç”¨ï¼‰
  params?: string // è¯·æ±‚参数
  alertConfigId?: number // å‘Šè­¦é…ç½®ç¼–号
}
// IoT åœºæ™¯è”动 API
export const RuleSceneApi = {
  // æŸ¥è¯¢åœºæ™¯è”动分页
  getRuleScenePage: async (params: any) => {
    return await request.get({ url: `/iot/scene-rule/page`, params })
  },
  // æŸ¥è¯¢åœºæ™¯è”动详情
  getRuleScene: async (id: number) => {
    return await request.get({ url: `/iot/scene-rule/get?id=` + id })
  },
  // æ–°å¢žåœºæ™¯è”动
  createRuleScene: async (data: IotSceneRule) => {
    return await request.post({ url: `/iot/scene-rule/create`, data })
  },
  // ä¿®æ”¹åœºæ™¯è”动
  updateRuleScene: async (data: IotSceneRule) => {
    return await request.put({ url: `/iot/scene-rule/update`, data })
  },
  // ä¿®æ”¹åœºæ™¯è”动
  updateRuleSceneStatus: async (id: number, status: number) => {
    return await request.put({
      url: `/iot/scene-rule/update-status`,
      data: {
        id,
        status
      }
    })
  },
  // åˆ é™¤åœºæ™¯è”动
  deleteRuleScene: async (id: number) => {
    return await request.delete({ url: `/iot/scene-rule/delete?id=` + id })
  },
  // èŽ·å–åœºæ™¯è”åŠ¨ç®€å•åˆ—è¡¨
  getSimpleRuleSceneList: async () => {
    return await request.get({ url: `/iot/scene-rule/simple-list` })
  }
}
src/api/iot/statistics/index.ts
New file
@@ -0,0 +1,60 @@
import request from '@/config/axios'
/** IoT ç»Ÿè®¡æ•°æ®ç±»åž‹ */
export interface IotStatisticsSummaryRespVO {
  productCategoryCount: number
  productCount: number
  deviceCount: number
  deviceMessageCount: number
  productCategoryTodayCount: number
  productTodayCount: number
  deviceTodayCount: number
  deviceMessageTodayCount: number
  deviceOnlineCount: number
  deviceOfflineCount: number
  deviceInactiveCount: number
  productCategoryDeviceCounts: Record<string, number>
}
/** æ—¶é—´æˆ³-数值的键值对类型 */
interface TimeValueItem {
  [key: string]: number
}
/** IoT æ¶ˆæ¯ç»Ÿè®¡æ•°æ®ç±»åž‹ */
export interface IotStatisticsDeviceMessageSummaryRespVO {
  statType: number
  upstreamCounts: TimeValueItem[]
  downstreamCounts: TimeValueItem[]
}
/** æ–°çš„æ¶ˆæ¯ç»Ÿè®¡æ•°æ®é¡¹ */
export interface IotStatisticsDeviceMessageSummaryByDateRespVO {
  time: string
  upstreamCount: number
  downstreamCount: number
}
/** æ–°çš„æ¶ˆæ¯ç»Ÿè®¡æŽ¥å£å‚æ•° */
export interface IotStatisticsDeviceMessageReqVO {
  interval: number
  times?: string[]
}
// IoT æ•°æ®ç»Ÿè®¡ API
export const StatisticsApi = {
  // æŸ¥è¯¢å…¨å±€çš„æ•°æ®ç»Ÿè®¡
  getStatisticsSummary: async () => {
    return await request.get<IotStatisticsSummaryRespVO>({
      url: `/iot/statistics/get-summary`
    })
  },
  // èŽ·å–è®¾å¤‡æ¶ˆæ¯çš„æ•°æ®ç»Ÿè®¡
  getDeviceMessageSummaryByDate: async (params: IotStatisticsDeviceMessageReqVO) => {
    return await request.get<IotStatisticsDeviceMessageSummaryByDateRespVO[]>({
      url: `/iot/statistics/get-device-message-summary-by-date`,
      params
    })
  }
}
src/api/iot/thingmodel/index.ts
New file
@@ -0,0 +1,301 @@
import request from '@/config/axios'
import { isEmpty } from '@/utils/is'
/**
 * IoT äº§å“ç‰©æ¨¡åž‹
 */
export interface ThingModelData {
  id?: number // ç‰©æ¨¡åž‹åŠŸèƒ½ç¼–å·
  identifier?: string // åŠŸèƒ½æ ‡è¯†
  name?: string // åŠŸèƒ½åç§°
  description?: string // åŠŸèƒ½æè¿°
  productId?: number // äº§å“ç¼–号
  productKey?: string // äº§å“æ ‡è¯†
  dataType: string // æ•°æ®ç±»åž‹ï¼Œä¸Ž dataSpecs çš„ dataType ä¿æŒä¸€è‡´
  type: number // åŠŸèƒ½ç±»åž‹
  property: ThingModelProperty // å±žæ€§
  event?: ThingModelEvent // äº‹ä»¶
  service?: ThingModelService // æœåŠ¡
}
/**
 * ThingModelProperty ç±»åž‹
 */
export interface ThingModelProperty {
  [key: string]: any
}
/**
 * ThingModelEvent ç±»åž‹
 */
export interface ThingModelEvent {
  [key: string]: any
}
/**
 * ThingModelService ç±»åž‹
 */
export interface ThingModelService {
  [key: string]: any
}
/** dataSpecs æ•°å€¼åž‹æ•°æ®ç»“æž„ */
export interface DataSpecsNumberData {
  dataType: 'int' | 'float' | 'double' // æ•°æ®ç±»åž‹ï¼Œå–值为 INT、FLOAT æˆ– DOUBLE
  max: string // æœ€å¤§å€¼ï¼Œå¿…须与 dataType è®¾ç½®ä¸€è‡´ï¼Œä¸”为 STRING ç±»åž‹
  min: string // æœ€å°å€¼ï¼Œå¿…须与 dataType è®¾ç½®ä¸€è‡´ï¼Œä¸”为 STRING ç±»åž‹
  step: string // æ­¥é•¿ï¼Œå¿…须与 dataType è®¾ç½®ä¸€è‡´ï¼Œä¸”为 STRING ç±»åž‹
  precise?: string // ç²¾åº¦ï¼Œå½“ dataType ä¸º FLOAT æˆ– DOUBLE æ—¶å¯é€‰
  defaultValue?: string // é»˜è®¤å€¼ï¼Œå¯é€‰
  unit: string // å•位的符号
  unitName: string // å•位的名称
}
/** dataSpecs æžšä¸¾åž‹æ•°æ®ç»“æž„ */
export interface DataSpecsEnumOrBoolData {
  dataType: 'enum' | 'bool'
  defaultValue?: string // é»˜è®¤å€¼ï¼Œå¯é€‰
  name: string // æžšä¸¾é¡¹çš„名称
  value: number | undefined // æžšä¸¾å€¼
}
/** ç‰©æ¨¡åž‹TSL响应数据结构 */
export interface IotThingModelTSLResp {
  productId: number
  productKey: string
  properties: ThingModelProperty[]
  events: ThingModelEvent[]
  services: ThingModelService[]
}
/** ç‰©æ¨¡åž‹å±žæ€§ */
export interface ThingModelProperty {
  identifier: string
  name: string
  accessMode: string
  required?: boolean
  dataType: string
  description?: string
  dataSpecs?: ThingModelProperty
  dataSpecsList?: ThingModelProperty[]
}
/** ç‰©æ¨¡åž‹äº‹ä»¶ */
export interface ThingModelEvent {
  identifier: string
  name: string
  required?: boolean
  type: string
  description?: string
  outputParams?: ThingModelParam[]
  method?: string
}
/** ç‰©æ¨¡åž‹æœåŠ¡ */
export interface ThingModelService {
  identifier: string
  name: string
  required?: boolean
  callType: string
  description?: string
  inputParams?: ThingModelParam[]
  outputParams?: ThingModelParam[]
  method?: string
}
/** ç‰©æ¨¡åž‹å‚æ•° */
export interface ThingModelParam {
  identifier: string
  name: string
  direction: string
  paraOrder?: number
  dataType: string
  dataSpecs?: ThingModelProperty
  dataSpecsList?: ThingModelProperty[]
}
/** æ•°å€¼åž‹æ•°æ®è§„范 */
export interface ThingModelNumericDataSpec {
  dataType: 'int' | 'float' | 'double'
  max: string
  min: string
  step: string
  precise?: string
  defaultValue?: string
  unit?: string
  unitName?: string
}
/** å¸ƒå°”/枚举型数据规范 */
export interface ThingModelBoolOrEnumDataSpecs {
  dataType: 'bool' | 'enum'
  name: string
  value: number
}
/** æ–‡æœ¬/时间型数据规范 */
export interface ThingModelDateOrTextDataSpecs {
  dataType: 'text' | 'date'
  length?: number
  defaultValue?: string
}
/** æ•°ç»„型数据规范 */
export interface ThingModelArrayDataSpecs {
  dataType: 'array'
  size: number
  childDataType: string
  dataSpecsList?: ThingModelProperty[]
}
/** ç»“构体型数据规范 */
export interface ThingModelStructDataSpecs {
  dataType: 'struct'
  identifier: string
  name: string
  accessMode: string
  required?: boolean
  childDataType: string
  dataSpecs?: ThingModelProperty
  dataSpecsList?: ThingModelProperty[]
}
// IoT äº§å“ç‰©æ¨¡åž‹ API
export const ThingModelApi = {
  // æŸ¥è¯¢äº§å“ç‰©æ¨¡åž‹åˆ†é¡µ
  getThingModelPage: async (params: any) => {
    return await request.get({ url: `/iot/thing-model/page`, params })
  },
  // èŽ·å¾—äº§å“ç‰©æ¨¡åž‹åˆ—è¡¨
  getThingModelList: async (params: any) => {
    return await request.get({ url: `/iot/thing-model/list`, params })
  },
  // èŽ·å¾—äº§å“ç‰©æ¨¡åž‹ TSL
  getThingModelTSLByProductId: async (productId: number) => {
    return await request.get({
      url: `/iot/thing-model/get-tsl?productId=${productId}`
    })
  },
  // æŸ¥è¯¢äº§å“ç‰©æ¨¡åž‹è¯¦æƒ…
  getThingModel: async (id: number) => {
    return await request.get({ url: `/iot/thing-model/get?id=` + id })
  },
  // æ–°å¢žäº§å“ç‰©æ¨¡åž‹
  createThingModel: async (data: ThingModelData) => {
    return await request.post({ url: `/iot/thing-model/create`, data })
  },
  // ä¿®æ”¹äº§å“ç‰©æ¨¡åž‹
  updateThingModel: async (data: ThingModelData) => {
    return await request.put({ url: `/iot/thing-model/update`, data })
  },
  // åˆ é™¤äº§å“ç‰©æ¨¡åž‹
  deleteThingModel: async (id: number) => {
    return await request.delete({ url: `/iot/thing-model/delete?id=` + id })
  }
}
/** å…¬å…±æ ¡éªŒè§„则 */
export const ThingModelFormRules = {
  name: [
    { required: true, message: '功能名称不能为空', trigger: 'blur' },
    {
      pattern: /^[\u4e00-\u9fa5a-zA-Z0-9][\u4e00-\u9fa5a-zA-Z0-9\-_/\.]{0,29}$/,
      message:
        '支持中文、大小写字母、日文、数字、短划线、下划线、斜杠和小数点,必须以中文、英文或数字开头,不超过 30 ä¸ªå­—符',
      trigger: 'blur'
    }
  ],
  type: [{ required: true, message: '功能类型不能为空', trigger: 'blur' }],
  identifier: [
    { required: true, message: '标识符不能为空', trigger: 'blur' },
    {
      pattern: /^[a-zA-Z0-9_]{1,50}$/,
      message: '支持大小写字母、数字和下划线,不超过 50 ä¸ªå­—符',
      trigger: 'blur'
    },
    {
      validator: (_: any, value: string, callback: any) => {
        const reservedKeywords = ['set', 'get', 'post', 'property', 'event', 'time', 'value']
        if (reservedKeywords.includes(value)) {
          callback(
            new Error(
              'set, get, post, property, event, time, value æ˜¯ç³»ç»Ÿä¿ç•™å­—段,不能用于标识符定义'
            )
          )
        } else if (/^\d+$/.test(value)) {
          callback(new Error('标识符不能是纯数字'))
        } else {
          callback()
        }
      },
      trigger: 'blur'
    }
  ],
  'property.dataSpecs.childDataType': [{ required: true, message: '元素类型不能为空' }],
  'property.dataSpecs.size': [
    { required: true, message: '元素个数不能为空' },
    {
      validator: (_: any, value: any, callback: any) => {
        if (isEmpty(value)) {
          callback(new Error('元素个数不能为空'))
          return
        }
        if (isNaN(Number(value))) {
          callback(new Error('元素个数必须是数字'))
          return
        }
        callback()
      },
      trigger: 'blur'
    }
  ],
  'property.dataSpecs.length': [
    { required: true, message: '请输入文本字节长度', trigger: 'blur' },
    {
      validator: (_: any, value: any, callback: any) => {
        if (isEmpty(value)) {
          callback(new Error('文本长度不能为空'))
          return
        }
        if (isNaN(Number(value))) {
          callback(new Error('文本长度必须是数字'))
          return
        }
        callback()
      },
      trigger: 'blur'
    }
  ],
  'property.accessMode': [{ required: true, message: '请选择读写类型', trigger: 'change' }]
}
/** æ ¡éªŒå¸ƒå°”值名称 */
export const validateBoolName = (_: any, value: string, callback: any) => {
  if (isEmpty(value)) {
    callback(new Error('布尔值名称不能为空'))
    return
  }
  // æ£€æŸ¥å¼€å¤´å­—符
  if (!/^[\u4e00-\u9fa5a-zA-Z0-9]/.test(value)) {
    callback(new Error('布尔值名称必须以中文、英文字母或数字开头'))
    return
  }
  // æ£€æŸ¥æ•´ä½“格式
  if (!/^[\u4e00-\u9fa5a-zA-Z0-9][a-zA-Z0-9\u4e00-\u9fa5_-]*$/.test(value)) {
    callback(new Error('布尔值名称只能包含中文、英文字母、数字、下划线和短划线'))
    return
  }
  // æ£€æŸ¥é•¿åº¦ï¼ˆä¸€ä¸ªä¸­æ–‡ç®—一个字符)
  if (value.length > 20) {
    callback(new Error('布尔值名称长度不能超过 20 ä¸ªå­—符'))
    return
  }
  callback()
}
src/api/login/index.ts
New file
@@ -0,0 +1,91 @@
import request from '@/config/axios'
import type { RegisterVO, UserLoginVO } from './types'
export interface SmsCodeVO {
  mobile: string
  scene: number
}
export interface SmsLoginVO {
  mobile: string
  code: string
}
// ç™»å½•
export const login = (data: UserLoginVO) => {
  return request.post({
    url: '/system/auth/login',
    data,
    headers: {
      isEncrypt: false
    }
  })
}
// æ³¨å†Œ
export const register = (data: RegisterVO) => {
  return request.post({ url: '/system/auth/register', data })
}
// ä½¿ç”¨ç§Ÿæˆ·åï¼ŒèŽ·å¾—ç§Ÿæˆ·ç¼–å·
export const getTenantIdByName = (name: string) => {
  return request.get({ url: '/system/tenant/get-id-by-name?name=' + name })
}
// ä½¿ç”¨ç§Ÿæˆ·åŸŸåï¼ŒèŽ·å¾—ç§Ÿæˆ·ä¿¡æ¯
export const getTenantByWebsite = (website: string) => {
  return request.get({ url: '/system/tenant/get-by-website?website=' + website })
}
// ç™»å‡º
export const loginOut = () => {
  return request.post({ url: '/system/auth/logout' })
}
// èŽ·å–ç”¨æˆ·æƒé™ä¿¡æ¯
export const getInfo = () => {
  return request.get({ url: '/system/auth/get-permission-info' })
}
//获取登录验证码
export const sendSmsCode = (data: SmsCodeVO) => {
  return request.post({ url: '/system/auth/send-sms-code', data })
}
// çŸ­ä¿¡éªŒè¯ç ç™»å½•
export const smsLogin = (data: SmsLoginVO) => {
  return request.post({ url: '/system/auth/sms-login', data })
}
// ç¤¾äº¤å¿«æ·ç™»å½•,使用 code æŽˆæƒç 
export function socialLogin(type: string, code: string, state: string) {
  return request.post({
    url: '/system/auth/social-login',
    data: {
      type,
      code,
      state
    }
  })
}
// ç¤¾äº¤æŽˆæƒçš„跳转
export const socialAuthRedirect = (type: number, redirectUri: string) => {
  return request.get({
    url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri
  })
}
// èŽ·å–éªŒè¯å›¾ç‰‡ä»¥åŠ token
export const getCode = (data: any) => {
  return request.postOriginal({ url: 'system/captcha/get', data })
}
// æ»‘动或者点选验证
export const reqCheck = (data: any) => {
  return request.postOriginal({ url: 'system/captcha/check', data })
}
// é€šè¿‡çŸ­ä¿¡é‡ç½®å¯†ç 
export const smsResetPassword = (data: any) => {
  return request.post({ url: '/system/auth/reset-password', data })
}
src/api/login/oauth2/index.ts
New file
@@ -0,0 +1,41 @@
import request from '@/config/axios'
// èŽ·å¾—æŽˆæƒä¿¡æ¯
export const getAuthorize = (clientId: string) => {
  return request.get({ url: '/system/oauth2/authorize?clientId=' + clientId })
}
// å‘起授权
export const authorize = (
  responseType: string,
  clientId: string,
  redirectUri: string,
  state: string,
  autoApprove: boolean,
  checkedScopes: string[],
  uncheckedScopes: string[]
) => {
  // æž„建 scopes
  const scopes = {}
  for (const scope of checkedScopes) {
    scopes[scope] = true
  }
  for (const scope of uncheckedScopes) {
    scopes[scope] = false
  }
  // å‘起请求
  return request.post({
    url: '/system/oauth2/authorize',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    params: {
      response_type: responseType,
      client_id: clientId,
      redirect_uri: redirectUri,
      state: state,
      auto_approve: autoApprove,
      scope: JSON.stringify(scopes)
    }
  })
}
src/api/login/types.ts
New file
@@ -0,0 +1,38 @@
export type UserLoginVO = {
  username: string
  password: string
  captchaVerification: string
  socialType?: string
  socialCode?: string
  socialState?: string
}
export type TokenType = {
  id: number // ç¼–号
  accessToken: string // è®¿é—®ä»¤ç‰Œ
  refreshToken: string // åˆ·æ–°ä»¤ç‰Œ
  userId: number // ç”¨æˆ·ç¼–号
  userType: number //用户类型
  clientId: string //客户端编号
  expiresTime: number //过期时间
}
export type UserVO = {
  id: number
  username: string
  nickname: string
  deptId: number
  email: string
  mobile: string
  sex: number
  avatar: string
  loginIp: string
  loginDate: string
}
export type RegisterVO = {
  tenantName: string
  username: string
  password: string
  captchaVerification: string
}
src/api/mall/market/banner/index.ts
New file
@@ -0,0 +1,37 @@
import request from '@/config/axios'
export interface BannerVO {
  id: number
  title: string
  picUrl: string
  status: number
  url: string
  position: number
  sort: number
  memo: string
}
// æŸ¥è¯¢Banner管理列表
export const getBannerPage = async (params) => {
  return await request.get({ url: `/promotion/banner/page`, params })
}
// æŸ¥è¯¢Banner管理详情
export const getBanner = async (id: number) => {
  return await request.get({ url: `/promotion/banner/get?id=` + id })
}
// æ–°å¢žBanner管理
export const createBanner = async (data: BannerVO) => {
  return await request.post({ url: `/promotion/banner/create`, data })
}
// ä¿®æ”¹Banner管理
export const updateBanner = async (data: BannerVO) => {
  return await request.put({ url: `/promotion/banner/update`, data })
}
// åˆ é™¤Banner管理
export const deleteBanner = async (id: number) => {
  return await request.delete({ url: `/promotion/banner/delete?id=` + id })
}
src/api/mall/product/brand.ts
New file
@@ -0,0 +1,61 @@
import request from '@/config/axios'
/**
 * å•†å“å“ç‰Œ
 */
export interface BrandVO {
  /**
   * å“ç‰Œç¼–号
   */
  id?: number
  /**
   * å“ç‰Œåç§°
   */
  name: string
  /**
   * å“ç‰Œå›¾ç‰‡
   */
  picUrl: string
  /**
   * å“ç‰ŒæŽ’序
   */
  sort?: number
  /**
   * å“ç‰Œæè¿°
   */
  description?: string
  /**
   * å¼€å¯çŠ¶æ€
   */
  status: number
}
// åˆ›å»ºå•†å“å“ç‰Œ
export const createBrand = (data: BrandVO) => {
  return request.post({ url: '/product/brand/create', data })
}
// æ›´æ–°å•†å“å“ç‰Œ
export const updateBrand = (data: BrandVO) => {
  return request.put({ url: '/product/brand/update', data })
}
// åˆ é™¤å•†å“å“ç‰Œ
export const deleteBrand = (id: number) => {
  return request.delete({ url: `/product/brand/delete?id=${id}` })
}
// èŽ·å¾—å•†å“å“ç‰Œ
export const getBrand = (id: number) => {
  return request.get({ url: `/product/brand/get?id=${id}` })
}
// èŽ·å¾—å•†å“å“ç‰Œåˆ—è¡¨
export const getBrandParam = (params: PageParam) => {
  return request.get({ url: '/product/brand/page', params })
}
// èŽ·å¾—å•†å“å“ç‰Œç²¾ç®€ä¿¡æ¯åˆ—è¡¨
export const getSimpleBrandList = () => {
  return request.get({ url: '/product/brand/list-all-simple' })
}
src/api/mall/product/category.ts
New file
@@ -0,0 +1,56 @@
import request from '@/config/axios'
/**
 * äº§å“åˆ†ç±»
 */
export interface CategoryVO {
  /**
   * åˆ†ç±»ç¼–号
   */
  id?: number
  /**
   * çˆ¶åˆ†ç±»ç¼–号
   */
  parentId?: number
  /**
   * åˆ†ç±»åç§°
   */
  name: string
  /**
   * ç§»åŠ¨ç«¯åˆ†ç±»å›¾
   */
  picUrl: string
  /**
   * åˆ†ç±»æŽ’序
   */
  sort: number
  /**
   * å¼€å¯çŠ¶æ€
   */
  status: number
}
// åˆ›å»ºå•†å“åˆ†ç±»
export const createCategory = (data: CategoryVO) => {
  return request.post({ url: '/product/category/create', data })
}
// æ›´æ–°å•†å“åˆ†ç±»
export const updateCategory = (data: CategoryVO) => {
  return request.put({ url: '/product/category/update', data })
}
// åˆ é™¤å•†å“åˆ†ç±»
export const deleteCategory = (id: number) => {
  return request.delete({ url: `/product/category/delete?id=${id}` })
}
// èŽ·å¾—å•†å“åˆ†ç±»
export const getCategory = (id: number) => {
  return request.get({ url: `/product/category/get?id=${id}` })
}
// èŽ·å¾—å•†å“åˆ†ç±»åˆ—è¡¨
export const getCategoryList = (params: any) => {
  return request.get({ url: '/product/category/list', params })
}
src/api/mall/product/comment.ts
New file
@@ -0,0 +1,49 @@
import request from '@/config/axios'
export interface CommentVO {
  id: number
  userId: number
  userNickname: string
  userAvatar: string
  anonymous: boolean
  orderId: number
  orderItemId: number
  spuId: number
  spuName: string
  skuId: number
  visible: boolean
  scores: number
  descriptionScores: number
  benefitScores: number
  content: string
  picUrls: string
  replyStatus: boolean
  replyUserId: number
  replyContent: string
  replyTime: Date
}
// æŸ¥è¯¢å•†å“è¯„论列表
export const getCommentPage = async (params) => {
  return await request.get({ url: `/product/comment/page`, params })
}
// æŸ¥è¯¢å•†å“è¯„论详情
export const getComment = async (id: number) => {
  return await request.get({ url: `/product/comment/get?id=` + id })
}
// æ·»åŠ è‡ªè¯„
export const createComment = async (data: CommentVO) => {
  return await request.post({ url: `/product/comment/create`, data })
}
// æ˜¾ç¤º / éšè—è¯„论
export const updateCommentVisible = async (data: any) => {
  return await request.put({ url: `/product/comment/update-visible`, data })
}
// å•†å®¶å›žå¤
export const replyComment = async (data: any) => {
  return await request.put({ url: `/product/comment/reply`, data })
}
src/api/mall/product/favorite.ts
New file
@@ -0,0 +1,12 @@
import request from '@/config/axios'
export interface Favorite {
  id?: number
  userId?: string // ç”¨æˆ·ç¼–号
  spuId?: number | null // å•†å“ SPU ç¼–号
}
// èŽ·å¾— ProductFavorite åˆ—表
export const getFavoritePage = (params: PageParam) => {
  return request.get({ url: '/product/favorite/page', params })
}
src/api/mall/product/history.ts
New file
@@ -0,0 +1,10 @@
import request from '@/config/axios'
/**
 * èŽ·å¾—å•†å“æµè§ˆè®°å½•åˆ†é¡µ
 *
 * @param params è¯·æ±‚参数
 */
export const getBrowseHistoryPage = (params: any) => {
  return request.get({ url: '/product/browse-history/page', params })
}
src/api/mall/product/property.ts
New file
@@ -0,0 +1,89 @@
import request from '@/config/axios'
/**
 * å•†å“å±žæ€§
 */
export interface PropertyVO {
  id?: number
  /** åç§° */
  name: string
  /** å¤‡æ³¨ */
  remark?: string
}
/**
 * å±žæ€§å€¼
 */
export interface PropertyValueVO {
  id?: number
  /** å±žæ€§é¡¹çš„编号 */
  propertyId?: number
  /** åç§° */
  name: string
  /** å¤‡æ³¨ */
  remark?: string
}
// ------------------------ å±žæ€§é¡¹ -------------------
// åˆ›å»ºå±žæ€§é¡¹
export const createProperty = (data: PropertyVO) => {
  return request.post({ url: '/product/property/create', data })
}
// æ›´æ–°å±žæ€§é¡¹
export const updateProperty = (data: PropertyVO) => {
  return request.put({ url: '/product/property/update', data })
}
// åˆ é™¤å±žæ€§é¡¹
export const deleteProperty = (id: number) => {
  return request.delete({ url: `/product/property/delete?id=${id}` })
}
// èŽ·å¾—å±žæ€§é¡¹
export const getProperty = (id: number): Promise<PropertyVO> => {
  return request.get({ url: `/product/property/get?id=${id}` })
}
// èŽ·å¾—å±žæ€§é¡¹åˆ†é¡µ
export const getPropertyPage = (params: PageParam) => {
  return request.get({ url: '/product/property/page', params })
}
// èŽ·å¾—å±žæ€§é¡¹ç²¾ç®€åˆ—è¡¨
export const getPropertySimpleList = (): Promise<PropertyVO[]> => {
  return request.get({ url: '/product/property/simple-list' })
}
// ------------------------ å±žæ€§å€¼ -------------------
// èŽ·å¾—å±žæ€§å€¼åˆ†é¡µ
export const getPropertyValuePage = (params: PageParam & any) => {
  return request.get({ url: '/product/property/value/page', params })
}
// èŽ·å¾—å±žæ€§å€¼
export const getPropertyValue = (id: number): Promise<PropertyValueVO> => {
  return request.get({ url: `/product/property/value/get?id=${id}` })
}
// åˆ›å»ºå±žæ€§å€¼
export const createPropertyValue = (data: PropertyValueVO) => {
  return request.post({ url: '/product/property/value/create', data })
}
// æ›´æ–°å±žæ€§å€¼
export const updatePropertyValue = (data: PropertyValueVO) => {
  return request.put({ url: '/product/property/value/update', data })
}
// åˆ é™¤å±žæ€§å€¼
export const deletePropertyValue = (id: number) => {
  return request.delete({ url: `/product/property/value/delete?id=${id}` })
}
// èŽ·å¾—å±žæ€§å€¼ç²¾ç®€åˆ—è¡¨
export const getPropertyValueSimpleList = (propertyId: number): Promise<PropertyValueVO[]> => {
  return request.get({ url: '/product/property/value/simple-list', params: { propertyId } })
}
src/api/mall/product/spu.ts
New file
@@ -0,0 +1,111 @@
import request from '@/config/axios'
export interface Property {
  propertyId?: number // å±žæ€§ç¼–号
  propertyName?: string // å±žæ€§åç§°
  valueId?: number // å±žæ€§å€¼ç¼–号
  valueName?: string // å±žæ€§å€¼åç§°
}
export interface Sku {
  id?: number // å•†å“ SKU ç¼–号
  name?: string // å•†å“ SKU åç§°
  spuId?: number // SPU ç¼–号
  properties?: Property[] // å±žæ€§æ•°ç»„
  price?: number | string // å•†å“ä»·æ ¼
  marketPrice?: number | string // å¸‚场价
  costPrice?: number | string // æˆæœ¬ä»·
  barCode?: string // å•†å“æ¡ç 
  picUrl?: string // å›¾ç‰‡åœ°å€
  stock?: number // åº“å­˜
  weight?: number // å•†å“é‡é‡ï¼Œå•位:kg åƒå…‹
  volume?: number // å•†å“ä½“积,单位:m^3 å¹³ç±³
  firstBrokeragePrice?: number | string // ä¸€çº§åˆ†é”€çš„佣金
  secondBrokeragePrice?: number | string // äºŒçº§åˆ†é”€çš„佣金
  salesCount?: number // å•†å“é”€é‡
}
export interface GiveCouponTemplate {
  id?: number
  name?: string // ä¼˜æƒ åˆ¸åç§°
}
export interface Spu {
  id?: number
  name?: string // å•†å“åç§°
  categoryId?: number // å•†å“åˆ†ç±»
  keyword?: string // å…³é”®å­—
  unit?: number | undefined // å•位
  picUrl?: string // å•†å“å°é¢å›¾
  sliderPicUrls?: string[] // å•†å“è½®æ’­å›¾
  introduction?: string // å•†å“ç®€ä»‹
  deliveryTypes?: number[] // é…é€æ–¹å¼
  deliveryTemplateId?: number | undefined // è¿è´¹æ¨¡ç‰ˆ
  brandId?: number // å•†å“å“ç‰Œç¼–号
  specType?: boolean // å•†å“è§„æ ¼
  subCommissionType?: boolean // åˆ†é”€ç±»åž‹
  skus?: Sku[] // sku数组
  description?: string // å•†å“è¯¦æƒ…
  sort?: number // å•†å“æŽ’序
  giveIntegral?: number // èµ é€ç§¯åˆ†
  virtualSalesCount?: number // è™šæ‹Ÿé”€é‡
  price?: number // å•†å“ä»·æ ¼
  combinationPrice?: number // å•†å“æ‹¼å›¢ä»·æ ¼
  seckillPrice?: number // å•†å“ç§’杀价格
  salesCount?: number // å•†å“é”€é‡
  marketPrice?: number // å¸‚场价
  costPrice?: number // æˆæœ¬ä»·
  stock?: number // å•†å“åº“å­˜
  createTime?: Date // å•†å“åˆ›å»ºæ—¶é—´
  status?: number // å•†å“çŠ¶æ€
}
// èŽ·å¾— Spu åˆ—表
export const getSpuPage = (params: PageParam) => {
  return request.get({ url: '/product/spu/page', params })
}
// èŽ·å¾— Spu åˆ—表 tabsCount
export const getTabsCount = () => {
  return request.get({ url: '/product/spu/get-count' })
}
// åˆ›å»ºå•†å“ Spu
export const createSpu = (data: Spu) => {
  return request.post({ url: '/product/spu/create', data })
}
// æ›´æ–°å•†å“ Spu
export const updateSpu = (data: Spu) => {
  return request.put({ url: '/product/spu/update', data })
}
// æ›´æ–°å•†å“ Spu status
export const updateStatus = (data: { id: number; status: number }) => {
  return request.put({ url: '/product/spu/update-status', data })
}
// è޷得商品 Spu
export const getSpu = (id: number) => {
  return request.get({ url: `/product/spu/get-detail?id=${id}` })
}
// è޷得商品 Spu è¯¦æƒ…列表
export const getSpuDetailList = (ids: number[]) => {
  return request.get({ url: `/product/spu/list?spuIds=${ids}` })
}
// åˆ é™¤å•†å“ Spu
export const deleteSpu = (id: number) => {
  return request.delete({ url: `/product/spu/delete?id=${id}` })
}
// å¯¼å‡ºå•†å“ Spu Excel
export const exportSpu = async (params: any) => {
  return await request.download({ url: '/product/spu/export-excel', params })
}
// è޷得商品 SPU ç²¾ç®€åˆ—表
export const getSpuSimpleList = async () => {
  return request.get({ url: '/product/spu/list-all-simple' })
}
src/api/mall/promotion/article/index.ts
New file
@@ -0,0 +1,42 @@
import request from '@/config/axios'
export interface ArticleVO {
  id: number
  categoryId: number
  title: string
  author: string
  picUrl: string
  introduction: string
  browseCount: string
  sort: number
  status: number
  spuId: number
  recommendHot: boolean
  recommendBanner: boolean
  content: string
}
// æŸ¥è¯¢æ–‡ç« ç®¡ç†åˆ—表
export const getArticlePage = async (params: any) => {
  return await request.get({ url: `/promotion/article/page`, params })
}
// æŸ¥è¯¢æ–‡ç« ç®¡ç†è¯¦æƒ…
export const getArticle = async (id: number) => {
  return await request.get({ url: `/promotion/article/get?id=` + id })
}
// æ–°å¢žæ–‡ç« ç®¡ç†
export const createArticle = async (data: ArticleVO) => {
  return await request.post({ url: `/promotion/article/create`, data })
}
// ä¿®æ”¹æ–‡ç« ç®¡ç†
export const updateArticle = async (data: ArticleVO) => {
  return await request.put({ url: `/promotion/article/update`, data })
}
// åˆ é™¤æ–‡ç« ç®¡ç†
export const deleteArticle = async (id: number) => {
  return await request.delete({ url: `/promotion/article/delete?id=` + id })
}
src/api/mall/promotion/articleCategory/index.ts
New file
@@ -0,0 +1,39 @@
import request from '@/config/axios'
export interface ArticleCategoryVO {
  id: number
  name: string
  picUrl: string
  status: number
  sort: number
}
// æŸ¥è¯¢æ–‡ç« åˆ†ç±»åˆ—表
export const getArticleCategoryPage = async (params) => {
  return await request.get({ url: `/promotion/article-category/page`, params })
}
// æŸ¥è¯¢æ–‡ç« åˆ†ç±»ç²¾ç®€ä¿¡æ¯åˆ—表
export const getSimpleArticleCategoryList = async () => {
  return await request.get({ url: `/promotion/article-category/list-all-simple` })
}
// æŸ¥è¯¢æ–‡ç« åˆ†ç±»è¯¦æƒ…
export const getArticleCategory = async (id: number) => {
  return await request.get({ url: `/promotion/article-category/get?id=` + id })
}
// æ–°å¢žæ–‡ç« åˆ†ç±»
export const createArticleCategory = async (data: ArticleCategoryVO) => {
  return await request.post({ url: `/promotion/article-category/create`, data })
}
// ä¿®æ”¹æ–‡ç« åˆ†ç±»
export const updateArticleCategory = async (data: ArticleCategoryVO) => {
  return await request.put({ url: `/promotion/article-category/update`, data })
}
// åˆ é™¤æ–‡ç« åˆ†ç±»
export const deleteArticleCategory = async (id: number) => {
  return await request.delete({ url: `/promotion/article-category/delete?id=` + id })
}
src/api/mall/promotion/bargain/bargainActivity.ts
New file
@@ -0,0 +1,68 @@
import request from '@/config/axios'
import { Sku, Spu } from '@/api/mall/product/spu'
export interface BargainActivityVO {
  id?: number
  name?: string
  startTime?: Date
  endTime?: Date
  status?: number
  helpMaxCount?: number // è¾¾åˆ°è¯¥äººæ•°ï¼Œæ‰èƒ½ç åˆ°ä½Žä»·
  bargainCount?: number // æœ€å¤§å¸®ç æ¬¡æ•°
  totalLimitCount?: number // æœ€å¤§è´­ä¹°æ¬¡æ•°
  spuId: number
  skuId: number
  bargainFirstPrice: number // ç ä»·èµ·å§‹ä»·æ ¼ï¼Œå•位分
  bargainMinPrice: number // ç ä»·åº•ä»·
  stock: number // æ´»åŠ¨åº“å­˜
  randomMinPrice?: number // ç”¨æˆ·æ¯æ¬¡ç ä»·çš„æœ€å°é‡‘额,单位:分
  randomMaxPrice?: number // ç”¨æˆ·æ¯æ¬¡ç ä»·çš„æœ€å¤§é‡‘额,单位:分
}
// ç ä»·æ´»åŠ¨æ‰€éœ€å±žæ€§ã€‚é€‰æ‹©çš„å•†å“å’Œå±žæ€§çš„æ—¶å€™ä½¿ç”¨æ–¹ä¾¿ä½¿ç”¨æ´»åŠ¨çš„é€šç”¨å°è£…
export interface BargainProductVO {
  spuId: number
  skuId: number
  bargainFirstPrice: number // ç ä»·èµ·å§‹ä»·æ ¼ï¼Œå•位分
  bargainMinPrice: number // ç ä»·åº•ä»·
  stock: number // æ´»åŠ¨åº“å­˜
}
// æ‰©å±• Sku é…ç½®
export type SkuExtension = Sku & {
  productConfig: BargainProductVO
}
export interface SpuExtension extends Spu {
  skus: SkuExtension[] // é‡å†™ç±»åž‹
}
// æŸ¥è¯¢ç ä»·æ´»åŠ¨åˆ—è¡¨
export const getBargainActivityPage = async (params: any) => {
  return await request.get({ url: '/promotion/bargain-activity/page', params })
}
// æŸ¥è¯¢ç ä»·æ´»åŠ¨è¯¦æƒ…
export const getBargainActivity = async (id: number) => {
  return await request.get({ url: '/promotion/bargain-activity/get?id=' + id })
}
// æ–°å¢žç ä»·æ´»åЍ
export const createBargainActivity = async (data: BargainActivityVO) => {
  return await request.post({ url: '/promotion/bargain-activity/create', data })
}
// ä¿®æ”¹ç ä»·æ´»åЍ
export const updateBargainActivity = async (data: BargainActivityVO) => {
  return await request.put({ url: '/promotion/bargain-activity/update', data })
}
// å…³é—­ç ä»·æ´»åЍ
export const closeBargainActivity = async (id: number) => {
  return await request.put({ url: '/promotion/bargain-activity/close?id=' + id })
}
// åˆ é™¤ç ä»·æ´»åЍ
export const deleteBargainActivity = async (id: number) => {
  return await request.delete({ url: '/promotion/bargain-activity/delete?id=' + id })
}
src/api/mall/promotion/bargain/bargainHelp.ts
New file
@@ -0,0 +1,14 @@
import request from '@/config/axios'
export interface BargainHelpVO {
  id: number
  record: number
  userId: number
  reducePrice: number
  endTime: Date
}
// æŸ¥è¯¢ç ä»·è®°å½•列表
export const getBargainHelpPage = async (params) => {
  return await request.get({ url: `/promotion/bargain-help/page`, params })
}
src/api/mall/promotion/bargain/bargainRecord.ts
New file
@@ -0,0 +1,19 @@
import request from '@/config/axios'
export interface BargainRecordVO {
  id: number
  activityId: number
  userId: number
  spuId: number
  skuId: number
  bargainFirstPrice: number
  bargainPrice: number
  status: number
  orderId: number
  endTime: Date
}
// æŸ¥è¯¢ç ä»·è®°å½•列表
export const getBargainRecordPage = async (params) => {
  return await request.get({ url: `/promotion/bargain-record/page`, params })
}
src/api/mall/promotion/combination/combinationActivity.ts
New file
@@ -0,0 +1,72 @@
import request from '@/config/axios'
import { Sku, Spu } from '@/api/mall/product/spu'
export interface CombinationActivityVO {
  id?: number
  name?: string
  spuId?: number
  totalLimitCount?: number
  singleLimitCount?: number
  startTime?: Date
  endTime?: Date
  userSize?: number
  totalCount?: number
  successCount?: number
  orderUserCount?: number
  virtualGroup?: number
  status?: number
  limitDuration?: number
  combinationPrice?: number
  products: CombinationProductVO[]
}
// æ‹¼å›¢æ´»åŠ¨æ‰€éœ€å±žæ€§
export interface CombinationProductVO {
  spuId: number
  skuId: number
  combinationPrice: number // æ‹¼å›¢ä»·æ ¼
}
// æ‰©å±• Sku é…ç½®
export type SkuExtension = Sku & {
  productConfig: CombinationProductVO
}
export interface SpuExtension extends Spu {
  skus: SkuExtension[] // é‡å†™ç±»åž‹
}
// æŸ¥è¯¢æ‹¼å›¢æ´»åŠ¨åˆ—è¡¨
export const getCombinationActivityPage = async (params: any) => {
  return await request.get({ url: '/promotion/combination-activity/page', params })
}
// æŸ¥è¯¢æ‹¼å›¢æ´»åŠ¨è¯¦æƒ…
export const getCombinationActivity = async (id: number) => {
  return await request.get({ url: '/promotion/combination-activity/get?id=' + id })
}
// èŽ·å¾—æ‹¼å›¢æ´»åŠ¨åˆ—è¡¨ï¼ŒåŸºäºŽæ´»åŠ¨ç¼–å·æ•°ç»„
export const getCombinationActivityListByIds = (ids: number[]) => {
  return request.get({ url: `/promotion/combination-activity/list-by-ids?ids=${ids}` })
}
// æ–°å¢žæ‹¼å›¢æ´»åЍ
export const createCombinationActivity = async (data: CombinationActivityVO) => {
  return await request.post({ url: '/promotion/combination-activity/create', data })
}
// ä¿®æ”¹æ‹¼å›¢æ´»åЍ
export const updateCombinationActivity = async (data: CombinationActivityVO) => {
  return await request.put({ url: '/promotion/combination-activity/update', data })
}
// å…³é—­æ‹¼å›¢æ´»åЍ
export const closeCombinationActivity = async (id: number) => {
  return await request.put({ url: '/promotion/combination-activity/close?id=' + id })
}
// åˆ é™¤æ‹¼å›¢æ´»åЍ
export const deleteCombinationActivity = async (id: number) => {
  return await request.delete({ url: '/promotion/combination-activity/delete?id=' + id })
}
src/api/mall/promotion/combination/combinationRecord.ts
New file
@@ -0,0 +1,28 @@
import request from '@/config/axios'
export interface CombinationRecordVO {
  id: number // æ‹¼å›¢è®°å½•编号
  activityId: number // æ‹¼å›¢æ´»åŠ¨ç¼–å·
  nickname: string // ç”¨æˆ·æ˜µç§°
  avatar: string // ç”¨æˆ·å¤´åƒ
  headId: number // å›¢é•¿ç¼–号
  expireTime: string // è¿‡æœŸæ—¶é—´
  userSize: number // å¯å‚团人数
  userCount: number // å·²å‚团人数
  status: number // æ‹¼å›¢çŠ¶æ€
  spuName: string // å•†å“åå­—
  picUrl: string // å•†å“å›¾ç‰‡
  virtualGroup: boolean // æ˜¯å¦è™šæ‹Ÿæˆå›¢
  startTime: string // å¼€å§‹æ—¶é—´ (订单付款后开始的时间)
  endTime: string // ç»“束时间(成团时间/失败时间)
}
// æŸ¥è¯¢æ‹¼å›¢è®°å½•列表
export const getCombinationRecordPage = async (params: any) => {
  return await request.get({ url: '/promotion/combination-record/page', params })
}
// èŽ·å¾—æ‹¼å›¢è®°å½•çš„æ¦‚è¦ä¿¡æ¯
export const getCombinationRecordSummary = async () => {
  return await request.get({ url: '/promotion/combination-record/get-summary' })
}
src/api/mall/promotion/coupon/coupon.ts
New file
@@ -0,0 +1,26 @@
import request from '@/config/axios'
// TODO @dhb52:vo ç¼ºå°‘
// åˆ é™¤ä¼˜æƒ åе
export const deleteCoupon = async (id: number) => {
  return request.delete({
    url: `/promotion/coupon/delete?id=${id}`
  })
}
// èŽ·å¾—ä¼˜æƒ åŠµåˆ†é¡µ
export const getCouponPage = async (params: PageParam) => {
  return request.get({
    url: '/promotion/coupon/page',
    params: params
  })
}
// å‘送优惠券
export const sendCoupon = async (data: any) => {
  return request.post({
    url: '/promotion/coupon/send',
    data: data
  })
}
src/api/mall/promotion/coupon/couponTemplate.ts
New file
@@ -0,0 +1,90 @@
import request from '@/config/axios'
export interface CouponTemplateVO {
  id: number
  name: string
  status: number
  totalCount: number
  takeLimitCount: number
  takeType: number
  usePrice: number
  productScope: number
  productScopeValues: number[]
  validityType: number
  validStartTime: Date
  validEndTime: Date
  fixedStartTerm: number
  fixedEndTerm: number
  discountType: number
  discountPercent: number
  discountPrice: number
  discountLimitPrice: number
  takeCount: number
  useCount: number
}
// åˆ›å»ºä¼˜æƒ åŠµæ¨¡æ¿
export function createCouponTemplate(data: CouponTemplateVO) {
  return request.post({
    url: '/promotion/coupon-template/create',
    data: data
  })
}
// æ›´æ–°ä¼˜æƒ åŠµæ¨¡æ¿
export function updateCouponTemplate(data: CouponTemplateVO) {
  return request.put({
    url: '/promotion/coupon-template/update',
    data: data
  })
}
// æ›´æ–°ä¼˜æƒ åŠµæ¨¡æ¿çš„çŠ¶æ€
export function updateCouponTemplateStatus(id: number, status: [0, 1]) {
  const data = {
    id,
    status
  }
  return request.put({
    url: '/promotion/coupon-template/update-status',
    data: data
  })
}
// åˆ é™¤ä¼˜æƒ åŠµæ¨¡æ¿
export function deleteCouponTemplate(id: number) {
  return request.delete({
    url: '/promotion/coupon-template/delete?id=' + id
  })
}
// èŽ·å¾—ä¼˜æƒ åŠµæ¨¡æ¿
export function getCouponTemplate(id: number) {
  return request.get({
    url: '/promotion/coupon-template/get?id=' + id
  })
}
// èŽ·å¾—ä¼˜æƒ åŠµæ¨¡æ¿åˆ†é¡µ
export function getCouponTemplatePage(params: PageParam) {
  return request.get({
    url: '/promotion/coupon-template/page',
    params: params
  })
}
// èŽ·å¾—ä¼˜æƒ åŠµæ¨¡æ¿åˆ†é¡µ
export function getCouponTemplateList(ids: number[]): Promise<CouponTemplateVO[]> {
  return request.get({
    url: `/promotion/coupon-template/list?ids=${ids}`
  })
}
// å¯¼å‡ºä¼˜æƒ åŠµæ¨¡æ¿ Excel
export function exportCouponTemplateExcel(params: PageParam) {
  return request.get({
    url: '/promotion/coupon-template/export-excel',
    params: params,
    responseType: 'blob'
  })
}
src/api/mall/promotion/discount/discountActivity.ts
New file
@@ -0,0 +1,60 @@
import request from '@/config/axios'
import { Sku, Spu } from '@/api/mall/product/spu'
export interface DiscountActivityVO {
  id?: number
  spuId?: number
  name?: string
  status?: number
  remark?: string
  startTime?: Date
  endTime?: Date
  products?: DiscountProductVO[]
}
// é™æ—¶æŠ˜æ‰£ç›¸å…³ å±žæ€§
export interface DiscountProductVO {
  spuId: number
  skuId: number
  discountType: number
  discountPercent: number
  discountPrice: number
}
// æ‰©å±• Sku é…ç½®
export type SkuExtension = Sku & {
  productConfig: DiscountProductVO
}
export interface SpuExtension extends Spu {
  skus: SkuExtension[] // é‡å†™ç±»åž‹
}
// æŸ¥è¯¢é™æ—¶æŠ˜æ‰£æ´»åŠ¨åˆ—è¡¨
export const getDiscountActivityPage = async (params) => {
  return await request.get({ url: '/promotion/discount-activity/page', params })
}
// æŸ¥è¯¢é™æ—¶æŠ˜æ‰£æ´»åŠ¨è¯¦æƒ…
export const getDiscountActivity = async (id: number) => {
  return await request.get({ url: '/promotion/discount-activity/get?id=' + id })
}
// æ–°å¢žé™æ—¶æŠ˜æ‰£æ´»åЍ
export const createDiscountActivity = async (data: DiscountActivityVO) => {
  return await request.post({ url: '/promotion/discount-activity/create', data })
}
// ä¿®æ”¹é™æ—¶æŠ˜æ‰£æ´»åЍ
export const updateDiscountActivity = async (data: DiscountActivityVO) => {
  return await request.put({ url: '/promotion/discount-activity/update', data })
}
// å…³é—­é™æ—¶æŠ˜æ‰£æ´»åЍ
export const closeDiscountActivity = async (id: number) => {
  return await request.put({ url: '/promotion/discount-activity/close?id=' + id })
}
// åˆ é™¤é™æ—¶æŠ˜æ‰£æ´»åЍ
export const deleteDiscountActivity = async (id: number) => {
  return await request.delete({ url: '/promotion/discount-activity/delete?id=' + id })
}
src/api/mall/promotion/diy/page.ts
New file
@@ -0,0 +1,45 @@
import request from '@/config/axios'
export interface DiyPageVO {
  id?: number
  templateId?: number
  name: string
  remark: string
  previewPicUrls: string[]
  property: string
}
// æŸ¥è¯¢è£…修页面列表
export const getDiyPagePage = async (params: any) => {
  return await request.get({ url: `/promotion/diy-page/page`, params })
}
// æŸ¥è¯¢è£…修页面详情
export const getDiyPage = async (id: number) => {
  return await request.get({ url: `/promotion/diy-page/get?id=` + id })
}
// æ–°å¢žè£…修页面
export const createDiyPage = async (data: DiyPageVO) => {
  return await request.post({ url: `/promotion/diy-page/create`, data })
}
// ä¿®æ”¹è£…修页面
export const updateDiyPage = async (data: DiyPageVO) => {
  return await request.put({ url: `/promotion/diy-page/update`, data })
}
// åˆ é™¤è£…修页面
export const deleteDiyPage = async (id: number) => {
  return await request.delete({ url: `/promotion/diy-page/delete?id=` + id })
}
// èŽ·å¾—è£…ä¿®é¡µé¢å±žæ€§
export const getDiyPageProperty = async (id: number) => {
  return await request.get({ url: `/promotion/diy-page/get-property?id=` + id })
}
// æ›´æ–°è£…修页面属性
export const updateDiyPageProperty = async (data: DiyPageVO) => {
  return await request.put({ url: `/promotion/diy-page/update-property`, data })
}
src/api/mall/promotion/diy/template.ts
New file
@@ -0,0 +1,58 @@
import request from '@/config/axios'
import { DiyPageVO } from '@/api/mall/promotion/diy/page'
export interface DiyTemplateVO {
  id?: number
  name: string
  used: boolean
  usedTime?: Date
  remark: string
  previewPicUrls: string[]
  property: string
}
export interface DiyTemplatePropertyVO extends DiyTemplateVO {
  pages: DiyPageVO[]
}
// æŸ¥è¯¢è£…修模板列表
export const getDiyTemplatePage = async (params: any) => {
  return await request.get({ url: `/promotion/diy-template/page`, params })
}
// æŸ¥è¯¢è£…修模板详情
export const getDiyTemplate = async (id: number) => {
  return await request.get({ url: `/promotion/diy-template/get?id=` + id })
}
// æ–°å¢žè£…修模板
export const createDiyTemplate = async (data: DiyTemplateVO) => {
  return await request.post({ url: `/promotion/diy-template/create`, data })
}
// ä¿®æ”¹è£…修模板
export const updateDiyTemplate = async (data: DiyTemplateVO) => {
  return await request.put({ url: `/promotion/diy-template/update`, data })
}
// åˆ é™¤è£…修模板
export const deleteDiyTemplate = async (id: number) => {
  return await request.delete({ url: `/promotion/diy-template/delete?id=` + id })
}
// ä½¿ç”¨è£…修模板
export const useDiyTemplate = async (id: number) => {
  return await request.put({ url: `/promotion/diy-template/use?id=` + id })
}
// èŽ·å¾—è£…ä¿®æ¨¡æ¿å±žæ€§
export const getDiyTemplateProperty = async (id: number) => {
  return await request.get<DiyTemplatePropertyVO>({
    url: `/promotion/diy-template/get-property?id=` + id
  })
}
// æ›´æ–°è£…修模板属性
export const updateDiyTemplateProperty = async (data: DiyTemplateVO) => {
  return await request.put({ url: `/promotion/diy-template/update-property`, data })
}
src/api/mall/promotion/kefu/conversation/index.ts
New file
@@ -0,0 +1,39 @@
import request from '@/config/axios'
export interface KeFuConversationRespVO {
  id: number // ç¼–号
  userId: number // ä¼šè¯æ‰€å±žç”¨æˆ·
  userAvatar: string // ä¼šè¯æ‰€å±žç”¨æˆ·å¤´åƒ
  userNickname: string // ä¼šè¯æ‰€å±žç”¨æˆ·æ˜µç§°
  lastMessageTime: Date // æœ€åŽèŠå¤©æ—¶é—´
  lastMessageContent: string // æœ€åŽèŠå¤©å†…容
  lastMessageContentType: number // æœ€åŽå‘送的消息类型
  adminPinned: boolean // ç®¡ç†ç«¯ç½®é¡¶
  userDeleted: boolean // ç”¨æˆ·æ˜¯å¦å¯è§
  adminDeleted: boolean // ç®¡ç†å‘˜æ˜¯å¦å¯è§
  adminUnreadMessageCount: number // ç®¡ç†å‘˜æœªè¯»æ¶ˆæ¯æ•°
  createTime?: string // åˆ›å»ºæ—¶é—´
}
// å®¢æœä¼šè¯ API
export const KeFuConversationApi = {
  // èŽ·å¾—å®¢æœä¼šè¯åˆ—è¡¨
  getConversationList: async () => {
    return await request.get({ url: '/promotion/kefu-conversation/list' })
  },
  // èŽ·å¾—å®¢æœä¼šè¯
  getConversation: async (id: number) => {
    return await request.get({ url: `/promotion/kefu-conversation/get?id=` + id })
  },
  // å®¢æœä¼šè¯ç½®é¡¶
  updateConversationPinned: async (data: any) => {
    return await request.put({
      url: '/promotion/kefu-conversation/update-conversation-pinned',
      data
    })
  },
  // åˆ é™¤å®¢æœä¼šè¯
  deleteConversation: async (id: number) => {
    return await request.delete({ url: `/promotion/kefu-conversation/delete?id=${id}` })
  }
}
src/api/mall/promotion/kefu/message/index.ts
New file
@@ -0,0 +1,36 @@
import request from '@/config/axios'
export interface KeFuMessageRespVO {
  id: number // ç¼–号
  conversationId: number // ä¼šè¯ç¼–号
  senderId: number // å‘送人编号
  senderAvatar: string // å‘送人头像
  senderType: number // å‘送人类型
  receiverId: number // æŽ¥æ”¶äººç¼–号
  receiverType: number // æŽ¥æ”¶äººç±»åž‹
  contentType: number // æ¶ˆæ¯ç±»åž‹
  content: string // æ¶ˆæ¯
  readStatus: boolean // æ˜¯å¦å·²è¯»
  createTime: Date // åˆ›å»ºæ—¶é—´
}
// å®¢æœä¼šè¯ API
export const KeFuMessageApi = {
  // å‘送客服消息
  sendKeFuMessage: async (data: any) => {
    return await request.post({
      url: '/promotion/kefu-message/send',
      data
    })
  },
  // æ›´æ–°å®¢æœæ¶ˆæ¯å·²è¯»çŠ¶æ€
  updateKeFuMessageReadStatus: async (conversationId: number) => {
    return await request.put({
      url: '/promotion/kefu-message/update-read-status?conversationId=' + conversationId
    })
  },
  // èŽ·å¾—æ¶ˆæ¯åˆ—è¡¨ï¼ˆæµå¼åŠ è½½ï¼‰
  getKeFuMessageList: async (params: any) => {
    return await request.get({ url: '/promotion/kefu-message/list', params })
  }
}
src/api/mall/promotion/point/index.ts
New file
@@ -0,0 +1,91 @@
import request from '@/config/axios'
import { Sku, Spu } from '@/api/mall/product/spu' // ç§¯åˆ†å•†åŸŽæ´»åЍ VO
// ç§¯åˆ†å•†åŸŽæ´»åЍ VO
export interface PointActivityVO {
  id: number // ç§¯åˆ†å•†åŸŽæ´»åŠ¨ç¼–å·
  spuId: number // ç§¯åˆ†å•†åŸŽæ´»åЍ商品
  status: number // æ´»åŠ¨çŠ¶æ€
  stock: number // ç§¯åˆ†å•†åŸŽæ´»åŠ¨åº“å­˜
  totalStock: number // ç§¯åˆ†å•†åŸŽæ´»åŠ¨æ€»åº“å­˜
  remark?: string // å¤‡æ³¨
  sort: number // æŽ’序
  createTime: string // åˆ›å»ºæ—¶é—´
  products: PointProductVO[] // ç§¯åˆ†å•†åŸŽå•†å“
  // ========== å•†å“å­—段 ==========
  spuName: string // å•†å“åç§°
  picUrl: string // å•†å“ä¸»å›¾
  marketPrice: number // å•†å“å¸‚场价,单位:分
  //======================= æ˜¾ç¤ºæ‰€éœ€å…‘换积分最少的 sku ä¿¡æ¯ =======================
  point: number // å…‘换积分
  price: number // å…‘换金额,单位:分
}
// ç§’杀活动所需属性
export interface PointProductVO {
  id?: number // ç§¯åˆ†å•†åŸŽå•†å“ç¼–号
  activityId?: number // ç§¯åˆ†å•†åŸŽæ´»åЍ id
  spuId?: number // å•†å“ SPU ç¼–号
  skuId: number // å•†å“ SKU ç¼–号
  count: number // å¯å…‘换数量
  point: number // å…‘换积分
  price: number // å…‘换金额,单位:分
  stock: number // ç§¯åˆ†å•†åŸŽå•†å“åº“å­˜
  activityStatus?: number // ç§¯åˆ†å•†åŸŽå•†å“çŠ¶æ€
}
// æ‰©å±• Sku é…ç½®
export type SkuExtension = Sku & {
  productConfig: PointProductVO
}
export interface SpuExtension extends Spu {
  skus: SkuExtension[] // é‡å†™ç±»åž‹
}
export interface SpuExtension0 extends Spu {
  pointStock: number // ç§¯åˆ†å•†åŸŽæ´»åŠ¨åº“å­˜
  pointTotalStock: number // ç§¯åˆ†å•†åŸŽæ´»åŠ¨æ€»åº“å­˜
  point: number // å…‘换积分
  pointPrice: number // å…‘换金额,单位:分
}
// ç§¯åˆ†å•†åŸŽæ´»åЍ API
export const PointActivityApi = {
  // æŸ¥è¯¢ç§¯åˆ†å•†åŸŽæ´»åŠ¨åˆ†é¡µ
  getPointActivityPage: async (params: any) => {
    return await request.get({ url: `/promotion/point-activity/page`, params })
  },
  // æŸ¥è¯¢ç§¯åˆ†å•†åŸŽæ´»åŠ¨è¯¦æƒ…
  getPointActivity: async (id: number) => {
    return await request.get({ url: `/promotion/point-activity/get?id=` + id })
  },
  // æŸ¥è¯¢ç§¯åˆ†å•†åŸŽæ´»åŠ¨åˆ—è¡¨ï¼ŒåŸºäºŽæ´»åŠ¨ç¼–å·æ•°ç»„
  getPointActivityListByIds: async (ids: number[]) => {
    return request.get({ url: `/promotion/point-activity/list-by-ids?ids=${ids}` })
  },
  // æ–°å¢žç§¯åˆ†å•†åŸŽæ´»åЍ
  createPointActivity: async (data: PointActivityVO) => {
    return await request.post({ url: `/promotion/point-activity/create`, data })
  },
  // ä¿®æ”¹ç§¯åˆ†å•†åŸŽæ´»åЍ
  updatePointActivity: async (data: PointActivityVO) => {
    return await request.put({ url: `/promotion/point-activity/update`, data })
  },
  // åˆ é™¤ç§¯åˆ†å•†åŸŽæ´»åЍ
  deletePointActivity: async (id: number) => {
    return await request.delete({ url: `/promotion/point-activity/delete?id=` + id })
  },
  // å…³é—­ç§’杀活动
  closePointActivity: async (id: number) => {
    return await request.put({ url: '/promotion/point-activity/close?id=' + id })
  }
}
src/api/mall/promotion/reward/rewardActivity.ts
New file
@@ -0,0 +1,58 @@
import request from '@/config/axios'
export interface RewardActivityVO {
  id?: number
  name?: string
  startTime?: Date
  endTime?: Date
  startAndEndTime?: Date[] // åªå‰ç«¯ä½¿ç”¨
  remark?: string
  conditionType?: number
  productScope?: number
  rules: RewardRule[]
  // å¦‚下仅用于表单,不提交
  productScopeValues?: number[] // å•†å“èŒƒå›´ï¼šå€¼ä¸ºå“ç±»ç¼–号列表、商品编号列表
  productCategoryIds?: number[]
  productSpuIds?: number[]
}
// ä¼˜æƒ è§„则
export interface RewardRule {
  limit?: number
  discountPrice?: number
  freeDelivery?: boolean
  point: number
  giveCouponTemplateCounts?: {
    [key: number]: number
  }
}
// æ–°å¢žæ»¡å‡é€æ´»åЍ
export const createRewardActivity = async (data: RewardActivityVO) => {
  return await request.post({ url: '/promotion/reward-activity/create', data })
}
// æ›´æ–°æ»¡å‡é€æ´»åЍ
export const updateRewardActivity = async (data: RewardActivityVO) => {
  return await request.put({ url: '/promotion/reward-activity/update', data })
}
// æŸ¥è¯¢æ»¡å‡é€æ´»åŠ¨åˆ—è¡¨
export const getRewardActivityPage = async (params) => {
  return await request.get({ url: '/promotion/reward-activity/page', params })
}
// æŸ¥è¯¢æ»¡å‡é€æ´»åŠ¨è¯¦æƒ…
export const getReward = async (id: number) => {
  return await request.get({ url: '/promotion/reward-activity/get?id=' + id })
}
// åˆ é™¤æ»¡å‡é€æ´»åЍ
export const deleteRewardActivity = async (id: number) => {
  return await request.delete({ url: '/promotion/reward-activity/delete?id=' + id })
}
// å…³é—­æ»¡å‡é€æ´»åЍ
export const closeRewardActivity = async (id: number) => {
  return await request.put({ url: '/promotion/reward-activity/close?id=' + id })
}
src/api/mall/promotion/seckill/seckillActivity.ts
New file
@@ -0,0 +1,75 @@
import request from '@/config/axios'
import { Sku, Spu } from '@/api/mall/product/spu'
export interface SeckillActivityVO {
  id?: number
  spuId?: number
  name?: string
  status?: number
  remark?: string
  startTime?: Date
  endTime?: Date
  sort?: number
  configIds?: string
  orderCount?: number
  userCount?: number
  totalPrice?: number
  totalLimitCount?: number
  singleLimitCount?: number
  stock?: number
  totalStock?: number
  seckillPrice?: number
  products?: SeckillProductVO[]
}
// ç§’杀活动所需属性
export interface SeckillProductVO {
  skuId: number
  spuId: number
  seckillPrice: number
  stock: number
}
// æ‰©å±• Sku é…ç½®
export type SkuExtension = Sku & {
  productConfig: SeckillProductVO
}
export interface SpuExtension extends Spu {
  skus: SkuExtension[] // é‡å†™ç±»åž‹
}
// æŸ¥è¯¢ç§’杀活动列表
export const getSeckillActivityPage = async (params) => {
  return await request.get({ url: '/promotion/seckill-activity/page', params })
}
// æŸ¥è¯¢ç§’杀活动列表,基于活动编号数组
export const getSeckillActivityListByIds = (ids: number[]) => {
  return request.get({ url: `/promotion/seckill-activity/list-by-ids?ids=${ids}` })
}
// æŸ¥è¯¢ç§’杀活动详情
export const getSeckillActivity = async (id: number) => {
  return await request.get({ url: '/promotion/seckill-activity/get?id=' + id })
}
// æ–°å¢žç§’杀活动
export const createSeckillActivity = async (data: SeckillActivityVO) => {
  return await request.post({ url: '/promotion/seckill-activity/create', data })
}
// ä¿®æ”¹ç§’杀活动
export const updateSeckillActivity = async (data: SeckillActivityVO) => {
  return await request.put({ url: '/promotion/seckill-activity/update', data })
}
// å…³é—­ç§’杀活动
export const closeSeckillActivity = async (id: number) => {
  return await request.put({ url: '/promotion/seckill-activity/close?id=' + id })
}
// åˆ é™¤ç§’杀活动
export const deleteSeckillActivity = async (id: number) => {
  return await request.delete({ url: '/promotion/seckill-activity/delete?id=' + id })
}
src/api/mall/promotion/seckill/seckillConfig.ts
New file
@@ -0,0 +1,53 @@
import request from '@/config/axios'
// ç§’杀时段 VO
export interface SeckillConfigVO {
  id: number // ç¼–号
  name: string // ç§’杀时段名称
  startTime: string // å¼€å§‹æ—¶é—´ç‚¹
  endTime: string // ç»“束时间点
  sliderPicUrls: string[] // ç§’杀轮播图
  status: number // æ´»åŠ¨çŠ¶æ€
}
// ç§’杀时段 API
export const SeckillConfigApi = {
  // æŸ¥è¯¢ç§’杀时段分页
  getSeckillConfigPage: async (params: any) => {
    return await request.get({ url: `/promotion/seckill-config/page`, params })
  },
  // æŸ¥è¯¢ç§’杀时段列表
  getSimpleSeckillConfigList: async () => {
    return await request.get({ url: `/promotion/seckill-config/list` })
  },
  // æŸ¥è¯¢ç§’杀时段详情
  getSeckillConfig: async (id: number) => {
    return await request.get({ url: `/promotion/seckill-config/get?id=` + id })
  },
  // æ–°å¢žç§’杀时段
  createSeckillConfig: async (data: SeckillConfigVO) => {
    return await request.post({ url: `/promotion/seckill-config/create`, data })
  },
  // ä¿®æ”¹ç§’杀时段
  updateSeckillConfig: async (data: SeckillConfigVO) => {
    return await request.put({ url: `/promotion/seckill-config/update`, data })
  },
  // åˆ é™¤ç§’杀时段
  deleteSeckillConfig: async (id: number) => {
    return await request.delete({ url: `/promotion/seckill-config/delete?id=` + id })
  },
  // ä¿®æ”¹æ—¶æ®µé…ç½®çŠ¶æ€
  updateSeckillConfigStatus: async (id: number, status: number) => {
    const data = {
      id,
      status
    }
    return request.put({ url: '/promotion/seckill-config/update-status', data: data })
  }
}
src/api/mall/statistics/common.ts
New file
@@ -0,0 +1,5 @@
/** æ•°æ®å¯¹ç…§ Response VO */
export interface DataComparisonRespVO<T> {
  value: T
  reference: T
}
src/api/mall/statistics/member.ts
New file
@@ -0,0 +1,123 @@
import request from '@/config/axios'
import dayjs from 'dayjs'
import { DataComparisonRespVO } from '@/api/mall/statistics/common'
import { formatDate } from '@/utils/formatTime'
/** ä¼šå‘˜åˆ†æž Request VO */
export interface MemberAnalyseReqVO {
  times: dayjs.ConfigType[]
}
/** ä¼šå‘˜åˆ†æž Response VO */
export interface MemberAnalyseRespVO {
  visitUserCount: number
  orderUserCount: number
  payUserCount: number
  atv: number
  comparison: DataComparisonRespVO<MemberAnalyseComparisonRespVO>
}
/** ä¼šå‘˜åˆ†æžå¯¹ç…§æ•°æ® Response VO */
export interface MemberAnalyseComparisonRespVO {
  registerUserCount: number
  visitUserCount: number
  rechargeUserCount: number
}
/** ä¼šå‘˜åœ°åŒºç»Ÿè®¡ Response VO */
export interface MemberAreaStatisticsRespVO {
  areaId: number
  areaName: string
  userCount: number
  orderCreateUserCount: number
  orderPayUserCount: number
  orderPayPrice: number
}
/** ä¼šå‘˜æ€§åˆ«ç»Ÿè®¡ Response VO */
export interface MemberSexStatisticsRespVO {
  sex: number
  userCount: number
}
/** ä¼šå‘˜ç»Ÿè®¡ Response VO */
export interface MemberSummaryRespVO {
  userCount: number
  rechargeUserCount: number
  rechargePrice: number
  expensePrice: number
}
/** ä¼šå‘˜ç»ˆç«¯ç»Ÿè®¡ Response VO */
export interface MemberTerminalStatisticsRespVO {
  terminal: number
  userCount: number
}
/** ä¼šå‘˜æ•°é‡ç»Ÿè®¡ Response VO */
export interface MemberCountRespVO {
  /** ç”¨æˆ·è®¿é—®é‡ */
  visitUserCount: string
  /** æ³¨å†Œç”¨æˆ·æ•°é‡ */
  registerUserCount: number
}
/** ä¼šå‘˜æ³¨å†Œæ•°é‡ Response VO */
export interface MemberRegisterCountRespVO {
  date: string
  count: number
}
// æŸ¥è¯¢ä¼šå‘˜ç»Ÿè®¡
export const getMemberSummary = () => {
  return request.get<MemberSummaryRespVO>({
    url: '/statistics/member/summary'
  })
}
// æŸ¥è¯¢ä¼šå‘˜åˆ†æžæ•°æ®
export const getMemberAnalyse = (params: MemberAnalyseReqVO) => {
  return request.get<MemberAnalyseRespVO>({
    url: '/statistics/member/analyse',
    params: { times: [formatDate(params.times[0]), formatDate(params.times[1])] }
  })
}
// æŒ‰ç…§çœä»½ï¼ŒæŸ¥è¯¢ä¼šå‘˜ç»Ÿè®¡åˆ—表
export const getMemberAreaStatisticsList = () => {
  return request.get<MemberAreaStatisticsRespVO[]>({
    url: '/statistics/member/area-statistics-list'
  })
}
// æŒ‰ç…§æ€§åˆ«ï¼ŒæŸ¥è¯¢ä¼šå‘˜ç»Ÿè®¡åˆ—表
export const getMemberSexStatisticsList = () => {
  return request.get<MemberSexStatisticsRespVO[]>({
    url: '/statistics/member/sex-statistics-list'
  })
}
// æŒ‰ç…§ç»ˆç«¯ï¼ŒæŸ¥è¯¢ä¼šå‘˜ç»Ÿè®¡åˆ—表
export const getMemberTerminalStatisticsList = () => {
  return request.get<MemberTerminalStatisticsRespVO[]>({
    url: '/statistics/member/terminal-statistics-list'
  })
}
// èŽ·å¾—ç”¨æˆ·æ•°é‡é‡å¯¹ç…§
export const getUserCountComparison = () => {
  return request.get<DataComparisonRespVO<MemberCountRespVO>>({
    url: '/statistics/member/user-count-comparison'
  })
}
// èŽ·å¾—ä¼šå‘˜æ³¨å†Œæ•°é‡åˆ—è¡¨
export const getMemberRegisterCountList = (
  beginTime: dayjs.ConfigType,
  endTime: dayjs.ConfigType
) => {
  return request.get<MemberRegisterCountRespVO[]>({
    url: '/statistics/member/register-count-list',
    params: { times: [formatDate(beginTime), formatDate(endTime)] }
  })
}
src/api/mall/statistics/pay.ts
New file
@@ -0,0 +1,12 @@
import request from '@/config/axios'
/** æ”¯ä»˜ç»Ÿè®¡ */
export interface PaySummaryRespVO {
  /** å……值金额,单位分 */
  rechargePrice: number
}
/** èŽ·å–é’±åŒ…å……å€¼é‡‘é¢ */
export const getWalletRechargePrice = async () => {
  return await request.get<PaySummaryRespVO>({ url: `/statistics/pay/summary` })
}
src/api/mall/statistics/product.ts
New file
@@ -0,0 +1,52 @@
import request from '@/config/axios'
import { DataComparisonRespVO } from '@/api/mall/statistics/common'
export interface ProductStatisticsVO {
  id: number
  day: string
  spuId: number
  spuName: string
  spuPicUrl: string
  browseCount: number
  browseUserCount: number
  favoriteCount: number
  cartCount: number
  orderCount: number
  orderPayCount: number
  orderPayPrice: number
  afterSaleCount: number
  afterSaleRefundPrice: number
  browseConvertPercent: number
}
// å•†å“ç»Ÿè®¡ API
export const ProductStatisticsApi = {
  // èŽ·å¾—å•†å“ç»Ÿè®¡åˆ†æž
  getProductStatisticsAnalyse: (params: any) => {
    return request.get<DataComparisonRespVO<ProductStatisticsVO>>({
      url: '/statistics/product/analyse',
      params
    })
  },
  // èŽ·å¾—å•†å“çŠ¶å†µæ˜Žç»†
  getProductStatisticsList: (params: any) => {
    return request.get<ProductStatisticsVO[]>({
      url: '/statistics/product/list',
      params
    })
  },
  // å¯¼å‡ºèŽ·å¾—å•†å“çŠ¶å†µæ˜Žç»† Excel
  exportProductStatisticsExcel: (params: any) => {
    return request.download({
      url: '/statistics/product/export-excel',
      params
    })
  },
  // èŽ·å¾—å•†å“æŽ’è¡Œæ¦œåˆ†é¡µ
  getProductStatisticsRankPage: async (params: any) => {
    return await request.get({
      url: `/statistics/product/rank-page`,
      params
    })
  }
}
src/api/mall/statistics/trade.ts
New file
@@ -0,0 +1,119 @@
import request from '@/config/axios'
import dayjs from 'dayjs'
import { formatDate } from '@/utils/formatTime'
import { DataComparisonRespVO } from '@/api/mall/statistics/common'
/** äº¤æ˜“统计 Response VO */
export interface TradeSummaryRespVO {
  yesterdayOrderCount: number
  monthOrderCount: number
  yesterdayPayPrice: number
  monthPayPrice: number
}
/** äº¤æ˜“状况 Request VO */
export interface TradeTrendReqVO {
  times: [dayjs.ConfigType, dayjs.ConfigType]
}
/** äº¤æ˜“状况统计 Response VO */
export interface TradeTrendSummaryRespVO {
  time: string
  turnoverPrice: number
  orderPayPrice: number
  rechargePrice: number
  expensePrice: number
  walletPayPrice: number
  brokerageSettlementPrice: number
  afterSaleRefundPrice: number
}
/** äº¤æ˜“订单数量 Response VO */
export interface TradeOrderCountRespVO {
  /** å¾…发货 */
  undelivered?: number
  /** å¾…核销 */
  pickUp?: number
  /** é€€æ¬¾ä¸­ */
  afterSaleApply?: number
  /** æçŽ°å¾…å®¡æ ¸ */
  auditingWithdraw?: number
}
/** äº¤æ˜“订单统计 Response VO */
export interface TradeOrderSummaryRespVO {
  /** æ”¯ä»˜è®¢å•商品数 */
  orderPayCount?: number
  /** æ€»æ”¯ä»˜é‡‘额,单位:分 */
  orderPayPrice?: number
}
/** è®¢å•量趋势统计 Response VO */
export interface TradeOrderTrendRespVO {
  /** æ—¥æœŸ */
  date: string
  /** è®¢å•数量 */
  orderPayCount: number
  /** è®¢å•支付金额 */
  orderPayPrice: number
}
// æŸ¥è¯¢äº¤æ˜“统计
export const getTradeStatisticsSummary = () => {
  return request.get<DataComparisonRespVO<TradeSummaryRespVO>>({
    url: '/statistics/trade/summary'
  })
}
// èŽ·å¾—äº¤æ˜“çŠ¶å†µç»Ÿè®¡
export const getTradeStatisticsAnalyse = (params: TradeTrendReqVO) => {
  return request.get<DataComparisonRespVO<TradeTrendSummaryRespVO>>({
    url: '/statistics/trade/analyse',
    params: formatDateParam(params)
  })
}
// èŽ·å¾—äº¤æ˜“çŠ¶å†µæ˜Žç»†
export const getTradeStatisticsList = (params: TradeTrendReqVO) => {
  return request.get<TradeTrendSummaryRespVO[]>({
    url: '/statistics/trade/list',
    params: formatDateParam(params)
  })
}
// å¯¼å‡ºäº¤æ˜“状况明细
export const exportTradeStatisticsExcel = (params: TradeTrendReqVO) => {
  return request.download({
    url: '/statistics/trade/export-excel',
    params: formatDateParam(params)
  })
}
// èŽ·å¾—äº¤æ˜“è®¢å•æ•°é‡
export const getOrderCount = async () => {
  return await request.get<TradeOrderCountRespVO>({ url: `/statistics/trade/order-count` })
}
// èŽ·å¾—äº¤æ˜“è®¢å•æ•°é‡å¯¹ç…§
export const getOrderComparison = async () => {
  return await request.get<DataComparisonRespVO<TradeOrderSummaryRespVO>>({
    url: `/statistics/trade/order-comparison`
  })
}
// èŽ·å¾—è®¢å•é‡è¶‹åŠ¿ç»Ÿè®¡
export const getOrderCountTrendComparison = (
  type: number,
  beginTime: dayjs.ConfigType,
  endTime: dayjs.ConfigType
) => {
  return request.get<DataComparisonRespVO<TradeOrderTrendRespVO>[]>({
    url: '/statistics/trade/order-count-trend',
    params: { type, beginTime: formatDate(beginTime), endTime: formatDate(endTime) }
  })
}
/** æ—¶é—´å‚数需要格式化, ç¡®ä¿æŽ¥å£èƒ½è¯†åˆ« */
const formatDateParam = (params: TradeTrendReqVO) => {
  return { times: [formatDate(params.times[0]), formatDate(params.times[1])] } as TradeTrendReqVO
}
src/api/mall/trade/afterSale/index.ts
New file
@@ -0,0 +1,75 @@
import request from '@/config/axios'
export interface TradeAfterSaleVO {
  id?: number | null // å”®åŽç¼–号,主键自增
  no?: string // å”®åŽå•号
  status?: number | null // é€€æ¬¾çŠ¶æ€
  way?: number | null // å”®åŽæ–¹å¼
  type?: number | null // å”®åŽç±»åž‹
  userId?: number | null // ç”¨æˆ·ç¼–号
  applyReason?: string // ç”³è¯·åŽŸå› 
  applyDescription?: string // è¡¥å……描述
  applyPicUrls?: string[] // è¡¥å……凭证图片
  orderId?: number | null // äº¤æ˜“订单编号
  orderNo?: string // è®¢å•流水号
  orderItemId?: number | null // äº¤æ˜“订单项编号
  spuId?: number | null // å•†å“ SPU ç¼–号
  spuName?: string // å•†å“ SPU åç§°
  skuId?: number | null // å•†å“ SKU ç¼–号
  properties?: ProductPropertiesVO[] // å±žæ€§æ•°ç»„
  picUrl?: string // å•†å“å›¾ç‰‡
  count?: number | null // é€€è´§å•†å“æ•°é‡
  auditTime?: Date // å®¡æ‰¹æ—¶é—´
  auditUserId?: number | null // å®¡æ‰¹äºº
  auditReason?: string // å®¡æ‰¹å¤‡æ³¨
  refundPrice?: number | null // é€€æ¬¾é‡‘额,单位:分。
  payRefundId?: number | null // æ”¯ä»˜é€€æ¬¾ç¼–号
  refundTime?: Date // é€€æ¬¾æ—¶é—´
  logisticsId?: number | null // é€€è´§ç‰©æµå…¬å¸ç¼–号
  logisticsNo?: string // é€€è´§ç‰©æµå•号
  deliveryTime?: Date // é€€è´§æ—¶é—´
  receiveTime?: Date // æ”¶è´§æ—¶é—´
  receiveReason?: string // æ”¶è´§å¤‡æ³¨
}
export interface ProductPropertiesVO {
  propertyId?: number | null // å±žæ€§çš„编号
  propertyName?: string // å±žæ€§çš„名称
  valueId?: number | null //属性值的编号
  valueName?: string // å±žæ€§å€¼çš„名称
}
// èŽ·å¾—äº¤æ˜“å”®åŽåˆ†é¡µ
export const getAfterSalePage = async (params) => {
  return await request.get({ url: `/trade/after-sale/page`, params })
}
// èŽ·å¾—äº¤æ˜“å”®åŽè¯¦æƒ…
export const getAfterSale = async (id: any) => {
  return await request.get({ url: `/trade/after-sale/get-detail?id=${id}` })
}
// åŒæ„å”®åŽ
export const agree = async (id: any) => {
  return await request.put({ url: `/trade/after-sale/agree?id=${id}` })
}
// æ‹’绝售后
export const disagree = async (data: any) => {
  return await request.put({ url: `/trade/after-sale/disagree`, data })
}
// ç¡®è®¤æ”¶è´§
export const receive = async (id: any) => {
  return await request.put({ url: `/trade/after-sale/receive?id=${id}` })
}
// æ‹’绝收货
export const refuse = async (id: any) => {
  return await request.put({ url: `/trade/after-sale/refuse?id=${id}` })
}
// ç¡®è®¤é€€æ¬¾
export const refund = async (id: any) => {
  return await request.put({ url: `/trade/after-sale/refund?id=${id}` })
}
src/api/mall/trade/brokerage/record/index.ts
New file
@@ -0,0 +1,11 @@
import request from '@/config/axios'
// æŸ¥è¯¢ä½£é‡‘记录列表
export const getBrokerageRecordPage = async (params: any) => {
  return await request.get({ url: `/trade/brokerage-record/page`, params })
}
// æŸ¥è¯¢ä½£é‡‘记录详情
export const getBrokerageRecord = async (id: number) => {
  return await request.get({ url: `/trade/brokerage-record/get?id=` + id })
}
src/api/mall/trade/brokerage/user/index.ts
New file
@@ -0,0 +1,44 @@
import request from '@/config/axios'
export interface BrokerageUserVO {
  id: number
  bindUserId: number
  bindUserTime: Date
  brokerageEnabled: boolean
  brokerageTime: Date
  price: number
  frozenPrice: number
  nickname: string
  avatar: string
}
// åˆ›å»ºåˆ†é”€ç”¨æˆ·
export const createBrokerageUser = (data: any) => {
  return request.post({ url: '/trade/brokerage-user/create', data })
}
// æŸ¥è¯¢åˆ†é”€ç”¨æˆ·åˆ—表
export const getBrokerageUserPage = async (params: any) => {
  return await request.get({ url: `/trade/brokerage-user/page`, params })
}
// æŸ¥è¯¢åˆ†é”€ç”¨æˆ·è¯¦æƒ…
export const getBrokerageUser = async (id: number) => {
  return await request.get({ url: `/trade/brokerage-user/get?id=` + id })
}
// ä¿®æ”¹æŽ¨å¹¿å‘˜
export const updateBindUser = async (data: any) => {
  return await request.put({ url: `/trade/brokerage-user/update-bind-user`, data })
}
// æ¸…除推广员
export const clearBindUser = async (data: any) => {
  return await request.put({ url: `/trade/brokerage-user/clear-bind-user`, data })
}
// ä¿®æ”¹æŽ¨å¹¿èµ„æ ¼
export const updateBrokerageEnabled = async (data: any) => {
  return await request.put({ url: `/trade/brokerage-user/update-brokerage-enable`, data })
}
src/api/mall/trade/brokerage/withdraw/index.ts
New file
@@ -0,0 +1,43 @@
import request from '@/config/axios'
export interface BrokerageWithdrawVO {
  id: number
  userId: number
  price: number
  feePrice: number
  totalPrice: number
  type: number
  userName: string
  userAccount: string
  bankName: string
  bankAddress: string
  qrCodeUrl: string
  status: number
  auditReason: string
  auditTime: Date
  remark: string
  payTransferId?: number
  transferChannelCode?: string
  transferTime?: Date
  transferErrorMsg?: string
}
// æŸ¥è¯¢ä½£é‡‘提现列表
export const getBrokerageWithdrawPage = async (params: any) => {
  return await request.get({ url: `/trade/brokerage-withdraw/page`, params })
}
// æŸ¥è¯¢ä½£é‡‘提现详情
export const getBrokerageWithdraw = async (id: number) => {
  return await request.get({ url: `/trade/brokerage-withdraw/get?id=` + id })
}
// ä½£é‡‘提现 - é€šè¿‡ç”³è¯·
export const approveBrokerageWithdraw = async (id: number) => {
  return await request.put({ url: `/trade/brokerage-withdraw/approve?id=` + id })
}
// å®¡æ ¸ä½£é‡‘提现 - é©³å›žç”³è¯·
export const rejectBrokerageWithdraw = async (data: BrokerageWithdrawVO) => {
  return await request.put({ url: `/trade/brokerage-withdraw/reject`, data })
}
src/api/mall/trade/config/index.ts
New file
@@ -0,0 +1,23 @@
import request from '@/config/axios'
export interface ConfigVO {
  brokerageEnabled: boolean
  brokerageEnabledCondition: number
  brokerageBindMode: number
  brokeragePosterUrls: string
  brokerageFirstPercent: number
  brokerageSecondPercent: number
  brokerageWithdrawMinPrice: number
  brokerageFrozenDays: number
  brokerageWithdrawTypes: string
}
// æŸ¥è¯¢äº¤æ˜“中心配置详情
export const getTradeConfig = async () => {
  return await request.get({ url: `/trade/config/get` })
}
// ä¿å­˜äº¤æ˜“中心配置
export const saveTradeConfig = async (data: ConfigVO) => {
  return await request.put({ url: `/trade/config/save`, data })
}
src/api/mall/trade/delivery/express/index.ts
New file
@@ -0,0 +1,45 @@
import request from '@/config/axios'
export interface DeliveryExpressVO {
  id: number
  code: string
  name: string
  logo: string
  sort: number
  status: number
}
// æŸ¥è¯¢å¿«é€’公司列表
export const getDeliveryExpressPage = async (params: PageParam) => {
  return await request.get({ url: '/trade/delivery/express/page', params })
}
// æŸ¥è¯¢å¿«é€’公司详情
export const getDeliveryExpress = async (id: number) => {
  return await request.get({ url: '/trade/delivery/express/get?id=' + id })
}
// èŽ·å¾—å¿«é€’å…¬å¸ç²¾ç®€ä¿¡æ¯åˆ—è¡¨
export const getSimpleDeliveryExpressList = () => {
  return request.get({ url: '/trade/delivery/express/list-all-simple' })
}
// æ–°å¢žå¿«é€’公司
export const createDeliveryExpress = async (data: DeliveryExpressVO) => {
  return await request.post({ url: '/trade/delivery/express/create', data })
}
// ä¿®æ”¹å¿«é€’公司
export const updateDeliveryExpress = async (data: DeliveryExpressVO) => {
  return await request.put({ url: '/trade/delivery/express/update', data })
}
// åˆ é™¤å¿«é€’公司
export const deleteDeliveryExpress = async (id: number) => {
  return await request.delete({ url: '/trade/delivery/express/delete?id=' + id })
}
// å¯¼å‡ºå¿«é€’公司 Excel
export const exportDeliveryExpressApi = async (params) => {
  return await request.download({ url: '/trade/delivery/express/export-excel', params })
}
src/api/mall/trade/delivery/expressTemplate/index.ts
New file
@@ -0,0 +1,54 @@
import request from '@/config/axios'
export interface DeliveryExpressTemplateVO {
  id: number
  name: string
  chargeMode: number
  sort: number
  templateCharge: ExpressTemplateChargeVO[]
  templateFree: ExpressTemplateFreeVO[]
}
export declare type ExpressTemplateChargeVO = {
  areaIds: number[]
  startCount: number
  startPrice: number
  extraCount: number
  extraPrice: number
}
export declare type ExpressTemplateFreeVO = {
  areaIds: number[]
  freeCount: number
  freePrice: number
}
// æŸ¥è¯¢å¿«é€’运费模板列表
export const getDeliveryExpressTemplatePage = async (params: PageParam) => {
  return await request.get({ url: '/trade/delivery/express-template/page', params })
}
// æŸ¥è¯¢å¿«é€’运费模板详情
export const getDeliveryExpressTemplate = async (id: number) => {
  return await request.get({ url: '/trade/delivery/express-template/get?id=' + id })
}
// æŸ¥è¯¢å¿«é€’运费模板详情
export const getSimpleTemplateList = async () => {
  return await request.get({ url: '/trade/delivery/express-template/list-all-simple' })
}
// æ–°å¢žå¿«é€’运费模板
export const createDeliveryExpressTemplate = async (data: DeliveryExpressTemplateVO) => {
  return await request.post({ url: '/trade/delivery/express-template/create', data })
}
// ä¿®æ”¹å¿«é€’运费模板
export const updateDeliveryExpressTemplate = async (data: DeliveryExpressTemplateVO) => {
  return await request.put({ url: '/trade/delivery/express-template/update', data })
}
// åˆ é™¤å¿«é€’运费模板
export const deleteDeliveryExpressTemplate = async (id: number) => {
  return await request.delete({ url: '/trade/delivery/express-template/delete?id=' + id })
}
src/api/mall/trade/delivery/pickUpStore/index.ts
New file
@@ -0,0 +1,52 @@
import request from '@/config/axios'
export interface DeliveryPickUpStoreVO {
  id: number
  name: string
  introduction: string
  phone: string
  areaId: number
  detailAddress: string
  logo: string
  openingTime: string
  closingTime: string
  latitude: number
  longitude: number
  status: number
  verifyUserIds: number[] // ç»‘定用户编号组数
}
// æŸ¥è¯¢è‡ªæé—¨åº—列表
export const getDeliveryPickUpStorePage = async (params: any) => {
  return await request.get({ url: '/trade/delivery/pick-up-store/page', params })
}
// æŸ¥è¯¢è‡ªæé—¨åº—详情
export const getDeliveryPickUpStore = async (id: number) => {
  return await request.get({ url: '/trade/delivery/pick-up-store/get?id=' + id })
}
// æŸ¥è¯¢è‡ªæé—¨åº—精简列表
export const getSimpleDeliveryPickUpStoreList = async (): Promise<DeliveryPickUpStoreVO[]> => {
  return await request.get({ url: '/trade/delivery/pick-up-store/simple-list' })
}
// æ–°å¢žè‡ªæé—¨åº—
export const createDeliveryPickUpStore = async (data: DeliveryPickUpStoreVO) => {
  return await request.post({ url: '/trade/delivery/pick-up-store/create', data })
}
// ä¿®æ”¹è‡ªæé—¨åº—
export const updateDeliveryPickUpStore = async (data: DeliveryPickUpStoreVO) => {
  return await request.put({ url: '/trade/delivery/pick-up-store/update', data })
}
// åˆ é™¤è‡ªæé—¨åº—
export const deleteDeliveryPickUpStore = async (id: number) => {
  return await request.delete({ url: '/trade/delivery/pick-up-store/delete?id=' + id })
}
// ç»‘定自提店员
export const bindStoreStaffId = async (data: any) => {
  return await request.post({ url: '/trade/delivery/pick-up-store/bind', data })
}
src/api/mall/trade/order/index.ts
New file
@@ -0,0 +1,188 @@
import request from '@/config/axios'
export interface OrderVO {
  // ========== è®¢å•基本信息 ==========
  id?: number | null // è®¢å•编号
  no?: string // è®¢å•流水号
  createTime?: Date | null // ä¸‹å•æ—¶é—´
  type?: number | null // è®¢å•类型
  terminal?: number | null // è®¢å•来源
  userId?: number | null // ç”¨æˆ·ç¼–号
  userIp?: string // ç”¨æˆ· IP
  userRemark?: string // ç”¨æˆ·å¤‡æ³¨
  status?: number | null // è®¢å•状态
  productCount?: number | null // è´­ä¹°çš„商品数量
  finishTime?: Date | null // è®¢å•完成时间
  cancelTime?: Date | null // è®¢å•取消时间
  cancelType?: number | null // å–消类型
  remark?: string // å•†å®¶å¤‡æ³¨
  // ========== ä»·æ ¼ + æ”¯ä»˜åŸºæœ¬ä¿¡æ¯ ==========
  payOrderId?: number | null // æ”¯ä»˜è®¢å•编号
  payStatus?: boolean // æ˜¯å¦å·²æ”¯ä»˜
  payTime?: Date | null // ä»˜æ¬¾æ—¶é—´
  payChannelCode?: string // æ”¯ä»˜æ¸ é“
  totalPrice?: number | null // å•†å“åŽŸä»·ï¼ˆæ€»ï¼‰
  discountPrice?: number | null // è®¢å•优惠(总)
  deliveryPrice?: number | null // è¿è´¹é‡‘额
  adjustPrice?: number | null // è®¢å•调价(总)
  payPrice?: number | null // åº”付金额(总)
  // ========== æ”¶ä»¶ + ç‰©æµåŸºæœ¬ä¿¡æ¯ ==========
  deliveryType?: number | null // å‘货方式
  pickUpStoreId?: number // è‡ªæé—¨åº—编号
  pickUpVerifyCode?: string // è‡ªææ ¸é”€ç 
  deliveryTemplateId?: number | null // é…é€æ¨¡æ¿ç¼–号
  logisticsId?: number | null // å‘货物流公司编号
  logisticsNo?: string // å‘货物流单号
  deliveryTime?: Date | null // å‘è´§æ—¶é—´
  receiveTime?: Date | null // æ”¶è´§æ—¶é—´
  receiverName?: string // æ”¶ä»¶äººåç§°
  receiverMobile?: string // æ”¶ä»¶äººæ‰‹æœº
  receiverPostCode?: number | null // æ”¶ä»¶äººé‚®ç¼–
  receiverAreaId?: number | null // æ”¶ä»¶äººåœ°åŒºç¼–号
  receiverAreaName?: string //收件人地区名字
  receiverDetailAddress?: string // æ”¶ä»¶äººè¯¦ç»†åœ°å€
  // ========== å”®åŽåŸºæœ¬ä¿¡æ¯ ==========
  afterSaleStatus?: number | null // å”®åŽçŠ¶æ€
  refundPrice?: number | null // é€€æ¬¾é‡‘额
  // ========== è¥é”€åŸºæœ¬ä¿¡æ¯ ==========
  couponId?: number | null // ä¼˜æƒ åŠµç¼–å·
  couponPrice?: number | null // ä¼˜æƒ åŠµå‡å…é‡‘é¢
  pointPrice?: number | null // ç§¯åˆ†æŠµæ‰£çš„金额
  vipPrice?: number | null // VIP å‡å…é‡‘额
  items?: OrderItemRespVO[] // è®¢å•项列表
  // ä¸‹å•用户信息
  user?: {
    id?: number | null
    nickname?: string
    avatar?: string
  }
  // æŽ¨å¹¿ç”¨æˆ·ä¿¡æ¯
  brokerageUser?: {
    id?: number | null
    nickname?: string
    avatar?: string
  }
  // è®¢å•操作日志
  logs?: OrderLogRespVO[]
}
export interface OrderLogRespVO {
  content?: string
  createTime?: Date
  userType?: number
}
export interface OrderItemRespVO {
  // ========== è®¢å•项基本信息 ==========
  id?: number | null // ç¼–号
  userId?: number | null // ç”¨æˆ·ç¼–号
  orderId?: number | null // è®¢å•编号
  // ========== å•†å“åŸºæœ¬ä¿¡æ¯ ==========
  spuId?: number | null // å•†å“ SPU ç¼–号
  spuName?: string //商品 SPU åç§°
  skuId?: number | null // å•†å“ SKU ç¼–号
  picUrl?: string //商品图片
  count?: number | null //购买数量
  // ========== ä»·æ ¼ + æ”¯ä»˜åŸºæœ¬ä¿¡æ¯ ==========
  originalPrice?: number | null //商品原价(总)
  originalUnitPrice?: number | null //商品原价(单)
  discountPrice?: number | null //商品优惠(总)
  payPrice?: number | null //商品实付金额(总)
  orderPartPrice?: number | null //子订单分摊金额(总)
  orderDividePrice?: number | null //分摊后子订单实付金额(总)
  // ========== è¥é”€åŸºæœ¬ä¿¡æ¯ ==========
  // TODO èŠ‹è‰¿ï¼šåœ¨æ‰æ‘¸ä¸€ä¸‹
  // ========== å”®åŽåŸºæœ¬ä¿¡æ¯ ==========
  afterSaleStatus?: number | null // å”®åŽçŠ¶æ€
  properties?: ProductPropertiesVO[] //属性数组
}
export interface ProductPropertiesVO {
  propertyId?: number | null // å±žæ€§çš„编号
  propertyName?: string // å±žæ€§çš„名称
  valueId?: number | null //属性值的编号
  valueName?: string // å±žæ€§å€¼çš„名称
}
/** äº¤æ˜“订单统计 */
export interface TradeOrderSummaryRespVO {
  /** è®¢å•数量 */
  orderCount?: number
  /** è®¢å•金额 */
  orderPayPrice?: string
  /** é€€æ¬¾å•æ•° */
  afterSaleCount?: number
  /** é€€æ¬¾é‡‘额 */
  afterSalePrice?: string
}
// æŸ¥è¯¢äº¤æ˜“订单列表
export const getOrderPage = async (params: any) => {
  return await request.get({ url: `/trade/order/page`, params })
}
// æŸ¥è¯¢äº¤æ˜“订单统计
export const getOrderSummary = async (params: any) => {
  return await request.get<TradeOrderSummaryRespVO>({ url: `/trade/order/summary`, params })
}
// æŸ¥è¯¢äº¤æ˜“订单详情
export const getOrder = async (id: number | null) => {
  return await request.get({ url: `/trade/order/get-detail?id=` + id })
}
// æŸ¥è¯¢äº¤æ˜“订单物流详情
export const getExpressTrackList = async (id: number | null) => {
  return await request.get({ url: `/trade/order/get-express-track-list?id=` + id })
}
export interface DeliveryVO {
  id?: number // è®¢å•编号
  logisticsId: number | null // ç‰©æµå…¬å¸ç¼–号
  logisticsNo: string // ç‰©æµç¼–号
}
// è®¢å•发货
export const deliveryOrder = async (data: DeliveryVO) => {
  return await request.put({ url: `/trade/order/delivery`, data })
}
// è®¢å•备注
export const updateOrderRemark = async (data: any) => {
  return await request.put({ url: `/trade/order/update-remark`, data })
}
// è®¢å•调价
export const updateOrderPrice = async (data: any) => {
  return await request.put({ url: `/trade/order/update-price`, data })
}
// ä¿®æ”¹è®¢å•地址
export const updateOrderAddress = async (data: any) => {
  return await request.put({ url: `/trade/order/update-address`, data })
}
// è®¢å•核销
export const pickUpOrder = async (id: number) => {
  return await request.put({ url: `/trade/order/pick-up-by-id?id=${id}` })
}
// è®¢å•核销
export const pickUpOrderByVerifyCode = async (pickUpVerifyCode: string) => {
  return await request.put({
    url: `/trade/order/pick-up-by-verify-code`,
    params: { pickUpVerifyCode }
  })
}
// æŸ¥è¯¢æ ¸é”€ç å¯¹åº”的订单
export const getOrderByPickUpVerifyCode = async (pickUpVerifyCode: string) => {
  return await request.get<OrderVO>({
    url: `/trade/order/get-by-pick-up-verify-code`,
    params: { pickUpVerifyCode }
  })
}
src/api/member/address/index.ts
New file
@@ -0,0 +1,15 @@
import request from '@/config/axios'
export interface AddressVO {
  id: number
  name: string
  mobile: string
  areaId: number
  detailAddress: string
  defaultStatus: boolean
}
// æŸ¥è¯¢ç”¨æˆ·æ”¶ä»¶åœ°å€åˆ—表
export const getAddressList = async (params) => {
  return await request.get({ url: `/member/address/list`, params })
}
src/api/member/config/index.ts
New file
@@ -0,0 +1,19 @@
import request from '@/config/axios'
export interface ConfigVO {
  id: number
  pointTradeDeductEnable: number
  pointTradeDeductUnitPrice: number
  pointTradeDeductMaxPrice: number
  pointTradeGivePoint: number
}
// æŸ¥è¯¢ç§¯åˆ†è®¾ç½®è¯¦æƒ…
export const getConfig = async () => {
  return await request.get({ url: `/member/config/get` })
}
// æ–°å¢žä¿®æ”¹ç§¯åˆ†è®¾ç½®
export const saveConfig = async (data: ConfigVO) => {
  return await request.put({ url: `/member/config/save`, data })
}
src/api/member/experience-record/index.ts
New file
@@ -0,0 +1,22 @@
import request from '@/config/axios'
export interface ExperienceRecordVO {
  id: number
  userId: number
  bizId: string
  bizType: number
  title: string
  description: string
  experience: number
  totalExperience: number
}
// æŸ¥è¯¢ä¼šå‘˜ç»éªŒè®°å½•列表
export const getExperienceRecordPage = async (params) => {
  return await request.get({ url: `/member/experience-record/page`, params })
}
// æŸ¥è¯¢ä¼šå‘˜ç»éªŒè®°å½•详情
export const getExperienceRecord = async (id: number) => {
  return await request.get({ url: `/member/experience-record/get?id=` + id })
}
src/api/member/group/index.ts
New file
@@ -0,0 +1,38 @@
import request from '@/config/axios'
export interface GroupVO {
  id: number
  name: string
  remark: string
  status: number
}
// æŸ¥è¯¢ç”¨æˆ·åˆ†ç»„列表
export const getGroupPage = async (params: any) => {
  return await request.get({ url: `/member/group/page`, params })
}
// æŸ¥è¯¢ç”¨æˆ·åˆ†ç»„详情
export const getGroup = async (id: number) => {
  return await request.get({ url: `/member/group/get?id=` + id })
}
// æ–°å¢žç”¨æˆ·åˆ†ç»„
export const createGroup = async (data: GroupVO) => {
  return await request.post({ url: `/member/group/create`, data })
}
// æŸ¥è¯¢ç”¨æˆ·åˆ†ç»„ - ç²¾ç®€ä¿¡æ¯åˆ—表
export const getSimpleGroupList = async () => {
  return await request.get({ url: `/member/group/list-all-simple` })
}
// ä¿®æ”¹ç”¨æˆ·åˆ†ç»„
export const updateGroup = async (data: GroupVO) => {
  return await request.put({ url: `/member/group/update`, data })
}
// åˆ é™¤ç”¨æˆ·åˆ†ç»„
export const deleteGroup = async (id: number) => {
  return await request.delete({ url: `/member/group/delete?id=` + id })
}
src/api/member/level/index.ts
New file
@@ -0,0 +1,42 @@
import request from '@/config/axios'
export interface LevelVO {
  id: number
  name: string
  experience: number
  value: number
  discountPercent: number
  icon: string
  bgUrl: string
  status: number
}
// æŸ¥è¯¢ä¼šå‘˜ç­‰çº§åˆ—表
export const getLevelList = async (params) => {
  return await request.get({ url: `/member/level/list`, params })
}
// æŸ¥è¯¢ä¼šå‘˜ç­‰çº§è¯¦æƒ…
export const getLevel = async (id: number) => {
  return await request.get({ url: `/member/level/get?id=` + id })
}
// æŸ¥è¯¢ä¼šå‘˜ç­‰çº§ - ç²¾ç®€ä¿¡æ¯åˆ—表
export const getSimpleLevelList = async () => {
  return await request.get({ url: `/member/level/list-all-simple` })
}
// æ–°å¢žä¼šå‘˜ç­‰çº§
export const createLevel = async (data: LevelVO) => {
  return await request.post({ url: `/member/level/create`, data })
}
// ä¿®æ”¹ä¼šå‘˜ç­‰çº§
export const updateLevel = async (data: LevelVO) => {
  return await request.put({ url: `/member/level/update`, data })
}
// åˆ é™¤ä¼šå‘˜ç­‰çº§
export const deleteLevel = async (id: number) => {
  return await request.delete({ url: `/member/level/delete?id=` + id })
}
src/api/member/point/record/index.ts
New file
@@ -0,0 +1,18 @@
import request from '@/config/axios'
export interface RecordVO {
  id: number
  bizId: string
  bizType: string
  title: string
  description: string
  point: number
  totalPoint: number
  userId: number
  createDate: Date
}
// æŸ¥è¯¢ç”¨æˆ·ç§¯åˆ†è®°å½•列表
export const getRecordPage = async (params) => {
  return await request.get({ url: `/member/point/record/page`, params })
}
src/api/member/signin/config/index.ts
New file
@@ -0,0 +1,34 @@
import request from '@/config/axios'
export interface SignInConfigVO {
  id?: number
  day?: number
  point?: number
  experience?: number
  status?: number
}
// æŸ¥è¯¢ç§¯åˆ†ç­¾åˆ°è§„则列表
export const getSignInConfigList = async () => {
  return await request.get({ url: `/member/sign-in/config/list` })
}
// æŸ¥è¯¢ç§¯åˆ†ç­¾åˆ°è§„则详情
export const getSignInConfig = async (id: number) => {
  return await request.get({ url: `/member/sign-in/config/get?id=` + id })
}
// æ–°å¢žç§¯åˆ†ç­¾åˆ°è§„则
export const createSignInConfig = async (data: SignInConfigVO) => {
  return await request.post({ url: `/member/sign-in/config/create`, data })
}
// ä¿®æ”¹ç§¯åˆ†ç­¾åˆ°è§„则
export const updateSignInConfig = async (data: SignInConfigVO) => {
  return await request.put({ url: `/member/sign-in/config/update`, data })
}
// åˆ é™¤ç§¯åˆ†ç­¾åˆ°è§„则
export const deleteSignInConfig = async (id: number) => {
  return await request.delete({ url: `/member/sign-in/config/delete?id=` + id })
}
src/api/member/signin/record/index.ts
New file
@@ -0,0 +1,13 @@
import request from '@/config/axios'
export interface SignInRecordVO {
  id: number
  userId: number
  day: number
  point: number
}
// æŸ¥è¯¢ç”¨æˆ·ç­¾åˆ°ç§¯åˆ†åˆ—表
export const getSignInRecordPage = async (params) => {
  return await request.get({ url: `/member/sign-in/record/page`, params })
}
src/api/member/tag/index.ts
New file
@@ -0,0 +1,36 @@
import request from '@/config/axios'
export interface TagVO {
  id: number
  name: string
}
// æŸ¥è¯¢ä¼šå‘˜æ ‡ç­¾åˆ—表
export const getMemberTagPage = async (params: any) => {
  return await request.get({ url: `/member/tag/page`, params })
}
// æŸ¥è¯¢ä¼šå‘˜æ ‡ç­¾è¯¦æƒ…
export const getMemberTag = async (id: number) => {
  return await request.get({ url: `/member/tag/get?id=` + id })
}
// æŸ¥è¯¢ä¼šå‘˜æ ‡ç­¾ - ç²¾ç®€ä¿¡æ¯åˆ—表
export const getSimpleTagList = async () => {
  return await request.get({ url: `/member/tag/list-all-simple` })
}
// æ–°å¢žä¼šå‘˜æ ‡ç­¾
export const createMemberTag = async (data: TagVO) => {
  return await request.post({ url: `/member/tag/create`, data })
}
// ä¿®æ”¹ä¼šå‘˜æ ‡ç­¾
export const updateMemberTag = async (data: TagVO) => {
  return await request.put({ url: `/member/tag/update`, data })
}
// åˆ é™¤ä¼šå‘˜æ ‡ç­¾
export const deleteMemberTag = async (id: number) => {
  return await request.delete({ url: `/member/tag/delete?id=` + id })
}
src/api/member/user/index.ts
New file
@@ -0,0 +1,48 @@
import request from '@/config/axios'
export interface UserVO {
  id: number
  avatar: string | undefined
  birthday: number | undefined
  createTime: number | undefined
  loginDate: number | undefined
  loginIp: string
  mark: string
  mobile: string
  name: string | undefined
  nickname: string | undefined
  registerIp: string
  sex: number
  status: number
  areaId: number | undefined
  areaName: string | undefined
  levelName: string | null
  point: number | undefined | null
  totalPoint: number | undefined | null
  experience: number | null | undefined
}
// æŸ¥è¯¢ä¼šå‘˜ç”¨æˆ·åˆ—表
export const getUserPage = async (params) => {
  return await request.get({ url: `/member/user/page`, params })
}
// æŸ¥è¯¢ä¼šå‘˜ç”¨æˆ·è¯¦æƒ…
export const getUser = async (id: number) => {
  return await request.get({ url: `/member/user/get?id=` + id })
}
// ä¿®æ”¹ä¼šå‘˜ç”¨æˆ·
export const updateUser = async (data: UserVO) => {
  return await request.put({ url: `/member/user/update`, data })
}
// ä¿®æ”¹ä¼šå‘˜ç”¨æˆ·ç­‰çº§
export const updateUserLevel = async (data: any) => {
  return await request.put({ url: `/member/user/update-level`, data })
}
// ä¿®æ”¹ä¼šå‘˜ç”¨æˆ·ç§¯åˆ†
export const updateUserPoint = async (data: any) => {
  return await request.put({ url: `/member/user/update-point`, data })
}
src/api/mp/account/index.ts
New file
@@ -0,0 +1,46 @@
import request from '@/config/axios'
export interface AccountVO {
  id: number
  name: string
}
// åˆ›å»ºå…¬ä¼—号账号
export const createAccount = async (data) => {
  return await request.post({ url: '/mp/account/create', data })
}
// æ›´æ–°å…¬ä¼—号账号
export const updateAccount = async (data) => {
  return request.put({ url: '/mp/account/update', data: data })
}
// åˆ é™¤å…¬ä¼—号账号
export const deleteAccount = async (id) => {
  return request.delete({ url: '/mp/account/delete?id=' + id, method: 'delete' })
}
// èŽ·å¾—å…¬ä¼—å·è´¦å·
export const getAccount = async (id) => {
  return request.get({ url: '/mp/account/get?id=' + id })
}
// èŽ·å¾—å…¬ä¼—å·è´¦å·åˆ†é¡µ
export const getAccountPage = async (query) => {
  return request.get({ url: '/mp/account/page', params: query })
}
// èŽ·å–å…¬ä¼—å·è´¦å·ç²¾ç®€ä¿¡æ¯åˆ—è¡¨
export const getSimpleAccountList = async () => {
  return request.get({ url: '/mp/account/list-all-simple' })
}
// ç”Ÿæˆå…¬ä¼—号二维码
export const generateAccountQrCode = async (id) => {
  return request.put({ url: '/mp/account/generate-qr-code?id=' + id })
}
// æ¸…空公众号 API é…é¢
export const clearAccountQuota = async (id) => {
  return request.put({ url: '/mp/account/clear-quota?id=' + id })
}
src/api/mp/autoReply/index.ts
New file
@@ -0,0 +1,39 @@
import request from '@/config/axios'
// åˆ›å»ºå…¬ä¼—号的自动回复
export const createAutoReply = (data) => {
  return request.post({
    url: '/mp/auto-reply/create',
    data: data
  })
}
// æ›´æ–°å…¬ä¼—号的自动回复
export const updateAutoReply = (data) => {
  return request.put({
    url: '/mp/auto-reply/update',
    data: data
  })
}
// åˆ é™¤å…¬ä¼—号的自动回复
export const deleteAutoReply = (id) => {
  return request.delete({
    url: '/mp/auto-reply/delete?id=' + id
  })
}
// èŽ·å¾—å…¬ä¼—å·çš„è‡ªåŠ¨å›žå¤
export const getAutoReply = (id) => {
  return request.get({
    url: '/mp/auto-reply/get?id=' + id
  })
}
// èŽ·å¾—å…¬ä¼—å·çš„è‡ªåŠ¨å›žå¤åˆ†é¡µ
export const getAutoReplyPage = (query) => {
  return request.get({
    url: '/mp/auto-reply/page',
    params: query
  })
}
src/api/mp/draft/index.ts
New file
@@ -0,0 +1,35 @@
import request from '@/config/axios'
// èŽ·å¾—å…¬ä¼—å·è‰ç¨¿åˆ†é¡µ
export const getDraftPage = (query) => {
  return request.get({
    url: '/mp/draft/page',
    params: query
  })
}
// åˆ›å»ºå…¬ä¼—号草稿
export const createDraft = (accountId, articles) => {
  return request.post({
    url: '/mp/draft/create?accountId=' + accountId,
    data: {
      articles
    }
  })
}
// æ›´æ–°å…¬ä¼—号草稿
export const updateDraft = (accountId, mediaId, articles) => {
  return request.put({
    url: '/mp/draft/update?accountId=' + accountId + '&mediaId=' + mediaId,
    method: 'put',
    data: articles
  })
}
// åˆ é™¤å…¬ä¼—号草稿
export const deleteDraft = (accountId, mediaId) => {
  return request.delete({
    url: '/mp/draft/delete?accountId=' + accountId + '&mediaId=' + mediaId
  })
}
src/api/mp/freePublish/index.ts
New file
@@ -0,0 +1,23 @@
import request from '@/config/axios'
// èŽ·å¾—å…¬ä¼—å·ç´ æåˆ†é¡µ
export const getFreePublishPage = (query) => {
  return request.get({
    url: '/mp/free-publish/page',
    params: query
  })
}
// åˆ é™¤å…¬ä¼—号素材
export const deleteFreePublish = (accountId, articleId) => {
  return request.delete({
    url: '/mp/free-publish/delete?accountId=' + accountId + '&articleId=' + articleId
  })
}
// å‘布公众号素材
export const submitFreePublish = (accountId, mediaId) => {
  return request.post({
    url: '/mp/free-publish/submit?accountId=' + accountId + '&mediaId=' + mediaId
  })
}
src/api/mp/material/index.ts
New file
@@ -0,0 +1,16 @@
import request from '@/config/axios'
// èŽ·å¾—å…¬ä¼—å·ç´ æåˆ†é¡µ
export const getMaterialPage = (query) => {
  return request.get({
    url: '/mp/material/page',
    params: query
  })
}
// åˆ é™¤å…¬ä¼—号永久素材
export const deletePermanentMaterial = (id) => {
  return request.delete({
    url: '/mp/material/delete-permanent?id=' + id
  })
}
src/api/mp/menu/index.ts
New file
@@ -0,0 +1,26 @@
import request from '@/config/axios'
// èŽ·å¾—å…¬ä¼—å·èœå•åˆ—è¡¨
export const getMenuList = (accountId) => {
  return request.get({
    url: '/mp/menu/list?accountId=' + accountId
  })
}
// ä¿å­˜å…¬ä¼—号菜单
export const saveMenu = (accountId, menus) => {
  return request.post({
    url: '/mp/menu/save',
    data: {
      accountId,
      menus
    }
  })
}
// åˆ é™¤å…¬ä¼—号菜单
export const deleteMenu = (accountId) => {
  return request.delete({
    url: '/mp/menu/delete?accountId=' + accountId
  })
}
src/api/mp/message/index.ts
New file
@@ -0,0 +1,17 @@
import request from '@/config/axios'
// èŽ·å¾—å…¬ä¼—å·æ¶ˆæ¯åˆ†é¡µ
export const getMessagePage = (query: PageParam) => {
  return request.get({
    url: '/mp/message/page',
    params: query
  })
}
// ç»™ç²‰ä¸å‘送消息
export const sendMessage = (data) => {
  return request.post({
    url: '/mp/message/send',
    data: data
  })
}
src/api/mp/messageTemplate/index.ts
New file
@@ -0,0 +1,49 @@
import request from '@/config/axios'
// æ¶ˆæ¯æ¨¡æ¿ VO
export interface MsgTemplateVO {
  id: number // æ¨¡ç‰ˆä¸»é”®
  accountId: number // å…¬ä¼—号账号的编号
  appId: string // appId
  templateId: string // å…¬ä¼—号模板 ID
  title: string // æ ‡é¢˜
  content: string // æ¨¡æ¿å†…容
  example: string // æ¨¡æ¿ç¤ºä¾‹
  primaryIndustry: string // æ¨¡æ¿æ‰€å±žè¡Œä¸šçš„一级行业
  deputyIndustry: string // æ¨¡æ¿æ‰€å±žè¡Œä¸šçš„二级行业
  createTime: Date // åˆ›å»ºæ—¶é—´
}
// å‘送消息模板请求 VO
export interface MsgTemplateSendVO {
  id: number // æ¨¡æ¿ç¼–号
  userId: number // ç”¨æˆ·ç¼–号
  data?: string // æ¨¡æ¿æ•°æ®ï¼ˆJSON æ ¼å¼å­—符串)
  url?: string // è·³è½¬é“¾æŽ¥
  miniProgramAppId?: string // å°ç¨‹åº appId
  miniProgramPagePath?: string // å°ç¨‹åºé¡µé¢è·¯å¾„
  miniprogram?: string // å°ç¨‹åºä¿¡æ¯ï¼ˆJSON æ ¼å¼å­—符串)
}
// å…¬ä¼—号消息模板 API
export const MessageTemplateApi = {
  // æŸ¥è¯¢æ¶ˆæ¯æ¨¡æ¿åˆ†é¡µ
  getMessageTemplateList: async (params: any) => {
    return await request.get({ url: `/mp/message-template/list`, params })
  },
  // åˆ é™¤æ¶ˆæ¯æ¨¡æ¿
  deleteMessageTemplate: async (id: number) => {
    return await request.delete({ url: `/mp/message-template/delete?id=` + id })
  },
  // åŒæ­¥å…¬ä¼—号模板
  syncMessageTemplate: async (accountId: number) => {
    return await request.post({ url: `/mp/message-template/sync?accountId=` + accountId })
  },
  // å‘送消息模板
  sendMessageTemplate: async (data: MsgTemplateSendVO) => {
    return await request.post({ url: `/mp/message-template/send`, data })
  }
}
src/api/mp/statistics/index.ts
New file
@@ -0,0 +1,33 @@
import request from '@/config/axios'
// èŽ·å–æ¶ˆæ¯å‘é€æ¦‚å†µæ•°æ®
export const getUpstreamMessage = (query) => {
  return request.get({
    url: '/mp/statistics/upstream-message',
    params: query
  })
}
// ç”¨æˆ·å¢žå‡æ•°æ®
export const getUserSummary = (query) => {
  return request.get({
    url: '/mp/statistics/user-summary',
    params: query
  })
}
// èŽ·å¾—ç”¨æˆ·ç´¯è®¡æ•°æ®
export const getUserCumulate = (query) => {
  return request.get({
    url: '/mp/statistics/user-cumulate',
    params: query
  })
}
// èŽ·å¾—æŽ¥å£åˆ†æžæ•°æ®
export const getInterfaceSummary = (query) => {
  return request.get({
    url: '/mp/statistics/interface-summary',
    params: query
  })
}
src/api/mp/tag/index.ts
New file
@@ -0,0 +1,60 @@
import request from '@/config/axios'
export interface TagVO {
  id?: number
  name: string
  accountId: number
  createTime: Date
}
// åˆ›å»ºå…¬ä¼—号标签
export const createTag = (data: TagVO) => {
  return request.post({
    url: '/mp/tag/create',
    data: data
  })
}
// æ›´æ–°å…¬ä¼—号标签
export const updateTag = (data: TagVO) => {
  return request.put({
    url: '/mp/tag/update',
    data: data
  })
}
// åˆ é™¤å…¬ä¼—号标签
export const deleteTag = (id: number) => {
  return request.delete({
    url: '/mp/tag/delete?id=' + id
  })
}
// èŽ·å¾—å…¬ä¼—å·æ ‡ç­¾
export const getTag = (id: number) => {
  return request.get({
    url: '/mp/tag/get?id=' + id
  })
}
// èŽ·å¾—å…¬ä¼—å·æ ‡ç­¾åˆ†é¡µ
export const getTagPage = (query: PageParam) => {
  return request.get({
    url: '/mp/tag/page',
    params: query
  })
}
// èŽ·å–å…¬ä¼—å·æ ‡ç­¾ç²¾ç®€ä¿¡æ¯åˆ—è¡¨
export const getSimpleTagList = () => {
  return request.get({
    url: '/mp/tag/list-all-simple'
  })
}
// åŒæ­¥å…¬ä¼—号标签
export const syncTag = (accountId: number) => {
  return request.post({
    url: '/mp/tag/sync?accountId=' + accountId
  })
}
src/api/mp/user/index.ts
New file
@@ -0,0 +1,31 @@
import request from '@/config/axios'
// æ›´æ–°å…¬ä¼—号粉丝
export const updateUser = (data) => {
  return request.put({
    url: '/mp/user/update',
    data: data
  })
}
// èŽ·å¾—å…¬ä¼—å·ç²‰ä¸
export const getUser = (id) => {
  return request.get({
    url: '/mp/user/get?id=' + id
  })
}
// èŽ·å¾—å…¬ä¼—å·ç²‰ä¸åˆ†é¡µ
export const getUserPage = (query) => {
  return request.get({
    url: '/mp/user/page',
    params: query
  })
}
// åŒæ­¥å…¬ä¼—号粉丝
export const syncUser = (accountId) => {
  return request.post({
    url: '/mp/user/sync?accountId=' + accountId
  })
}
src/api/pay/app/index.ts
New file
@@ -0,0 +1,68 @@
import request from '@/config/axios'
export interface AppVO {
  id: number
  appKey: string
  name: string
  status: number
  remark: string
  payNotifyUrl: string
  refundNotifyUrl: string
  transferNotifyUrl: string
  merchantId: number
  merchantName: string
  createTime: Date
}
export interface AppPageReqVO extends PageParam {
  name?: string
  status?: number
  remark?: string
  payNotifyUrl?: string
  refundNotifyUrl?: string
  transferNotifyUrl?: string
  merchantName?: string
  createTime?: Date[]
}
export interface AppUpdateStatusReqVO {
  id: number
  status: number
}
// æŸ¥è¯¢åˆ—表支付应用
export const getAppPage = (params: AppPageReqVO) => {
  return request.get({ url: '/pay/app/page', params })
}
// æŸ¥è¯¢è¯¦æƒ…支付应用
export const getApp = (id: number) => {
  return request.get({ url: '/pay/app/get?id=' + id })
}
// æ–°å¢žæ”¯ä»˜åº”用
export const createApp = (data: AppVO) => {
  return request.post({ url: '/pay/app/create', data })
}
// ä¿®æ”¹æ”¯ä»˜åº”用
export const updateApp = (data: AppVO) => {
  return request.put({ url: '/pay/app/update', data })
}
// æ”¯ä»˜åº”用信息状态修改
export const changeAppStatus = (data: AppUpdateStatusReqVO) => {
  return request.put({ url: '/pay/app/update-status', data: data })
}
// åˆ é™¤æ”¯ä»˜åº”用
export const deleteApp = (id: number) => {
  return request.delete({ url: '/pay/app/delete?id=' + id })
}
// èŽ·å¾—æ”¯ä»˜åº”ç”¨åˆ—è¡¨
export const getAppList = () => {
  return request.get({
    url: '/pay/app/list'
  })
}
src/api/pay/channel/index.ts
New file
@@ -0,0 +1,46 @@
import request from '@/config/axios'
export interface ChannelVO {
  id: number
  code: string
  config: string
  status: number
  remark: string
  feeRate: number
  appId: number
  createTime: Date
}
// æŸ¥è¯¢åˆ—表支付渠道
export const getChannelPage = (params: PageParam) => {
  return request.get({ url: '/pay/channel/page', params })
}
// æŸ¥è¯¢è¯¦æƒ…支付渠道
export const getChannel = (appId: string, code: string) => {
  const params = {
    appId: appId,
    code: code
  }
  return request.get({ url: '/pay/channel/get', params: params })
}
// æ–°å¢žæ”¯ä»˜æ¸ é“
export const createChannel = (data: ChannelVO) => {
  return request.post({ url: '/pay/channel/create', data })
}
// ä¿®æ”¹æ”¯ä»˜æ¸ é“
export const updateChannel = (data: ChannelVO) => {
  return request.put({ url: '/pay/channel/update', data })
}
// åˆ é™¤æ”¯ä»˜æ¸ é“
export const deleteChannel = (id: number) => {
  return request.delete({ url: '/pay/channel/delete?id=' + id })
}
// å¯¼å‡ºæ”¯ä»˜æ¸ é“
export const exportChannel = (params) => {
  return request.download({ url: '/pay/channel/export-excel', params })
}
src/api/pay/demo/order/index.ts
New file
@@ -0,0 +1,29 @@
import request from '@/config/axios'
export interface DemoOrderVO {
  spuId: number
  createTime: Date
}
// åˆ›å»ºç¤ºä¾‹è®¢å•
export function createDemoOrder(data: DemoOrderVO) {
  return request.post({
    url: '/pay/demo-order/create',
    data: data
  })
}
// èŽ·å¾—ç¤ºä¾‹è®¢å•åˆ†é¡µ
export function getDemoOrderPage(query: PageParam) {
  return request.get({
    url: '/pay/demo-order/page',
    params: query
  })
}
// é€€æ¬¾ç¤ºä¾‹è®¢å•
export function refundDemoOrder(id: number) {
  return request.put({
    url: '/pay/demo-order/refund?id=' + id
  })
}
src/api/pay/demo/withdraw/index.ts
New file
@@ -0,0 +1,30 @@
import request from '@/config/axios'
export interface PayDemoWithdrawVO {
  id?: number
  subject: string
  price: number
  userName: string
  userAccount: string
  type: number
  status?: number
  payTransferId?: number
  transferChannelCode?: string
  transferTime?: Date
  transferErrorMsg?: string
}
// æŸ¥è¯¢ç¤ºä¾‹æçŽ°å•åˆ—è¡¨
export const getDemoWithdrawPage = (params: PageParam) => {
  return request.get({ url: '/pay/demo-withdraw/page', params })
}
// åˆ›å»ºç¤ºä¾‹æçŽ°å•
export const createDemoWithdraw = (data: PayDemoWithdrawVO) => {
  return request.post({ url: '/pay/demo-withdraw/create', data })
}
// å‘起提现单转账
export const transferDemoWithdraw = (id: number) => {
  return request.post({ url: '/pay/demo-withdraw/transfer', params: { id } })
}
src/api/pay/notify/index.ts
New file
@@ -0,0 +1,16 @@
import request from '@/config/axios'
// èŽ·å¾—æ”¯ä»˜é€šçŸ¥æ˜Žç»†
export const getNotifyTaskDetail = (id) => {
  return request.get({
    url: '/pay/notify/get-detail?id=' + id
  })
}
// èŽ·å¾—æ”¯ä»˜é€šçŸ¥åˆ†é¡µ
export const getNotifyTaskPage = (query) => {
  return request.get({
    url: '/pay/notify/page',
    params: query
  })
}
src/api/pay/order/index.ts
New file
@@ -0,0 +1,110 @@
import request from '@/config/axios'
export interface OrderVO {
  id: number
  merchantId: number
  appId: number
  channelId: number
  channelCode: string
  merchantOrderId: string
  subject: string
  body: string
  notifyUrl: string
  notifyStatus: number
  amount: number
  channelFeeRate: number
  channelFeeAmount: number
  status: number
  userIp: string
  expireTime: Date
  successTime: Date
  notifyTime: Date
  successExtensionId: number
  refundStatus: number
  refundTimes: number
  refundAmount: number
  channelUserId: string
  channelOrderNo: string
  createTime: Date
}
export interface OrderPageReqVO extends PageParam {
  merchantId?: number
  appId?: number
  channelId?: number
  channelCode?: string
  merchantOrderId?: string
  subject?: string
  body?: string
  notifyUrl?: string
  notifyStatus?: number
  amount?: number
  channelFeeRate?: number
  channelFeeAmount?: number
  status?: number
  expireTime?: Date[]
  successTime?: Date[]
  notifyTime?: Date[]
  successExtensionId?: number
  refundStatus?: number
  refundTimes?: number
  channelUserId?: string
  channelOrderNo?: string
  createTime?: Date[]
}
export interface OrderExportReqVO {
  merchantId?: number
  appId?: number
  channelId?: number
  channelCode?: string
  merchantOrderId?: string
  subject?: string
  body?: string
  notifyUrl?: string
  notifyStatus?: number
  amount?: number
  channelFeeRate?: number
  channelFeeAmount?: number
  status?: number
  expireTime?: Date[]
  successTime?: Date[]
  notifyTime?: Date[]
  successExtensionId?: number
  refundStatus?: number
  refundTimes?: number
  channelUserId?: string
  channelOrderNo?: string
  createTime?: Date[]
}
// æŸ¥è¯¢åˆ—表支付订单
export const getOrderPage = async (params: OrderPageReqVO) => {
  return await request.get({ url: '/pay/order/page', params })
}
// æŸ¥è¯¢è¯¦æƒ…支付订单
export const getOrder = async (id: number, sync?: boolean) => {
  return await request.get({
    url: '/pay/order/get',
    params: {
      id,
      sync
    }
  })
}
// èŽ·å¾—æ”¯ä»˜è®¢å•çš„æ˜Žç»†
export const getOrderDetail = async (id: number) => {
  return await request.get({ url: '/pay/order/get-detail?id=' + id })
}
// æäº¤æ”¯ä»˜è®¢å•
export const submitOrder = async (data: any) => {
  return await request.post({ url: '/pay/order/submit', data })
}
// å¯¼å‡ºæ”¯ä»˜è®¢å•
export const exportOrder = async (params: OrderExportReqVO) => {
  return await request.download({ url: '/pay/order/export-excel', params })
}
src/api/pay/refund/index.ts
New file
@@ -0,0 +1,116 @@
import request from '@/config/axios'
export interface RefundVO {
  id: number
  merchantId: number
  appId: number
  channelId: number
  channelCode: string
  orderId: string
  tradeNo: string
  merchantOrderId: string
  merchantRefundNo: string
  notifyUrl: string
  notifyStatus: number
  status: number
  type: number
  payAmount: number
  refundAmount: number
  reason: string
  userIp: string
  channelOrderNo: string
  channelRefundNo: string
  channelErrorCode: string
  channelErrorMsg: string
  channelExtras: string
  expireTime: Date
  successTime: Date
  notifyTime: Date
  createTime: Date
}
export interface RefundPageReqVO extends PageParam {
  merchantId?: number
  appId?: number
  channelId?: number
  channelCode?: string
  orderId?: string
  tradeNo?: string
  merchantOrderId?: string
  merchantRefundNo?: string
  notifyUrl?: string
  notifyStatus?: number
  status?: number
  type?: number
  payAmount?: number
  refundAmount?: number
  reason?: string
  userIp?: string
  channelOrderNo?: string
  channelRefundNo?: string
  channelErrorCode?: string
  channelErrorMsg?: string
  channelExtras?: string
  expireTime?: Date[]
  successTime?: Date[]
  notifyTime?: Date[]
  createTime?: Date[]
}
export interface PayRefundExportReqVO {
  merchantId?: number
  appId?: number
  channelId?: number
  channelCode?: string
  orderId?: string
  tradeNo?: string
  merchantOrderId?: string
  merchantRefundNo?: string
  notifyUrl?: string
  notifyStatus?: number
  status?: number
  type?: number
  payAmount?: number
  refundAmount?: number
  reason?: string
  userIp?: string
  channelOrderNo?: string
  channelRefundNo?: string
  channelErrorCode?: string
  channelErrorMsg?: string
  channelExtras?: string
  expireTime?: Date[]
  successTime?: Date[]
  notifyTime?: Date[]
  createTime?: Date[]
}
// æŸ¥è¯¢åˆ—表退款订单
export const getRefundPage = (params: RefundPageReqVO) => {
  return request.get({ url: '/pay/refund/page', params })
}
// æŸ¥è¯¢è¯¦æƒ…退款订单
export const getRefund = (id: number) => {
  return request.get({ url: '/pay/refund/get?id=' + id })
}
// æ–°å¢žé€€æ¬¾è®¢å•
export const createRefund = (data: RefundVO) => {
  return request.post({ url: '/pay/refund/create', data })
}
// ä¿®æ”¹é€€æ¬¾è®¢å•
export const updateRefund = (data: RefundVO) => {
  return request.put({ url: '/pay/refund/update', data })
}
// åˆ é™¤é€€æ¬¾è®¢å•
export const deleteRefund = (id: number) => {
  return request.delete({ url: '/pay/refund/delete?id=' + id })
}
// å¯¼å‡ºé€€æ¬¾è®¢å•
export const exportRefund = (params: PayRefundExportReqVO) => {
  return request.download({ url: '/pay/refund/export-excel', params })
}
src/api/pay/transfer/index.ts
New file
@@ -0,0 +1,16 @@
import request from '@/config/axios'
// æŸ¥è¯¢è½¬è´¦å•列表
export const getTransferPage = async (params: PageParam) => {
  return await request.get({ url: `/pay/transfer/page`, params })
}
// æŸ¥è¯¢è½¬è´¦å•详情
export const getTransfer = async (id: number) => {
  return await request.get({ url: '/pay/transfer/get?id=' + id })
}
// å¯¼å‡ºè½¬è´¦å•
export const exportTransfer = async (params: PageParam) => {
  return await request.download({ url: '/pay/transfer/export-excel', params })
}
src/api/pay/wallet/balance/index.ts
New file
@@ -0,0 +1,32 @@
import request from '@/config/axios'
/** ç”¨æˆ·é’±åŒ…查询参数 */
export interface PayWalletUserReqVO {
  userId: number
}
/** é’±åŒ… VO */
export interface WalletVO {
  id: number
  userId: number
  userType: number
  balance: number
  totalExpense: number
  totalRecharge: number
  freezePrice: number
}
/** æŸ¥è¯¢ç”¨æˆ·é’±åŒ…详情 */
export const getWallet = async (params: PayWalletUserReqVO) => {
  return await request.get<WalletVO>({ url: `/pay/wallet/get`, params })
}
/** æŸ¥è¯¢ä¼šå‘˜é’±åŒ…列表 */
export const getWalletPage = async (params: any) => {
  return await request.get({ url: `/pay/wallet/page`, params })
}
/** ä¿®æ”¹ä¼šå‘˜é’±åŒ…余额 */
export const updateWalletBalance = async (data: any) => {
  return await request.put({ url: `/pay/wallet/update-balance`, data })
}
src/api/pay/wallet/rechargePackage/index.ts
New file
@@ -0,0 +1,34 @@
import request from '@/config/axios'
export interface WalletRechargePackageVO {
  id: number
  name: string
  payPrice: number
  bonusPrice: number
  status: number
}
// æŸ¥è¯¢å¥—餐充值列表
export const getWalletRechargePackagePage = async (params) => {
  return await request.get({ url: '/pay/wallet-recharge-package/page', params })
}
// æŸ¥è¯¢å¥—餐充值详情
export const getWalletRechargePackage = async (id: number) => {
  return await request.get({ url: '/pay/wallet-recharge-package/get?id=' + id })
}
// æ–°å¢žå¥—餐充值
export const createWalletRechargePackage = async (data: WalletRechargePackageVO) => {
  return await request.post({ url: '/pay/wallet-recharge-package/create', data })
}
// ä¿®æ”¹å¥—餐充值
export const updateWalletRechargePackage = async (data: WalletRechargePackageVO) => {
  return await request.put({ url: '/pay/wallet-recharge-package/update', data })
}
// åˆ é™¤å¥—餐充值
export const deleteWalletRechargePackage = async (id: number) => {
  return await request.delete({ url: '/pay/wallet-recharge-package/delete?id=' + id })
}
src/api/pay/wallet/transaction/index.ts
New file
@@ -0,0 +1,14 @@
import request from '@/config/axios'
export interface WalletTransactionVO {
  id: number
  walletId: number
  title: string
  price: number
  balance: number
}
// æŸ¥è¯¢ä¼šå‘˜é’±åŒ…流水列表
export const getWalletTransactionPage = async (params) => {
  return await request.get({ url: `/pay/wallet-transaction/page`, params })
}
src/api/system/area/index.ts
New file
@@ -0,0 +1,11 @@
import request from '@/config/axios'
// èŽ·å¾—åœ°åŒºæ ‘
export const getAreaTree = async () => {
  return await request.get({ url: '/system/area/tree' })
}
// èŽ·å¾— IP å¯¹åº”的地区名
export const getAreaByIp = async (ip: string) => {
  return await request.get({ url: '/system/area/get-by-ip?ip=' + ip })
}
src/api/system/dept/index.ts
New file
@@ -0,0 +1,53 @@
import request from '@/config/axios'
export interface DeptVO {
  id: number
  name: string
  parentId: number
  status: number
  sort: number
  leaderUserId: number
  phone: string
  email: string
  createTime: Date
}
// æŸ¥è¯¢éƒ¨é—¨ï¼ˆç²¾ç®€)列表
export const getSimpleDeptList = (): Promise<DeptVO[]> => {
  return request.get({ url: '/system/dept/simple-list' })
}
// æŸ¥è¯¢éƒ¨é—¨åˆ—表
export const getDeptList = (params: any) => {
  return request.get({ url: '/system/dept/list', params })
}
// æŸ¥è¯¢éƒ¨é—¨åˆ†é¡µ
export const getDeptPage = async (params: PageParam) => {
  return await request.get({ url: '/system/dept/list', params })
}
// æŸ¥è¯¢éƒ¨é—¨è¯¦æƒ…
export const getDept = (id: number) => {
  return request.get({ url: '/system/dept/get?id=' + id })
}
// æ–°å¢žéƒ¨é—¨
export const createDept = (data: DeptVO) => {
  return request.post({ url: '/system/dept/create', data })
}
// ä¿®æ”¹éƒ¨é—¨
export const updateDept = (data: DeptVO) => {
  return request.put({ url: '/system/dept/update', data })
}
// åˆ é™¤éƒ¨é—¨
export const deleteDept = async (id: number) => {
  return await request.delete({ url: '/system/dept/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤éƒ¨é—¨
export const deleteDeptList = async (ids: number[]) => {
  return await request.delete({ url: '/system/dept/delete-list', params: { ids: ids.join(',') } })
}
src/api/system/dict/dict.data.ts
New file
@@ -0,0 +1,59 @@
import request from '@/config/axios'
export interface DictDataVO {
  id: number
  sort: number
  label: string
  value: string
  dictType: string
  status: number
  colorType: string
  cssClass: string
  remark: string
  createTime: Date
}
// æŸ¥è¯¢å­—典数据(精简)列表
export const getSimpleDictDataList = () => {
  return request.get({ url: '/system/dict-data/simple-list' })
}
// æŸ¥è¯¢å­—典数据列表
export const getDictDataPage = (params: PageParam) => {
  return request.get({ url: '/system/dict-data/page', params })
}
// æŸ¥è¯¢å­—典数据详情
export const getDictData = (id: number) => {
  return request.get({ url: '/system/dict-data/get?id=' + id })
}
// æ ¹æ®å­—典类型查询字典数据
export const getDictDataByType = (dictType: string) => {
  return request.get({ url: '/system/dict-data/type?type=' + dictType })
}
// æ–°å¢žå­—典数据
export const createDictData = (data: DictDataVO) => {
  return request.post({ url: '/system/dict-data/create', data })
}
// ä¿®æ”¹å­—典数据
export const updateDictData = (data: DictDataVO) => {
  return request.put({ url: '/system/dict-data/update', data })
}
// åˆ é™¤å­—典数据
export const deleteDictData = (id: number) => {
  return request.delete({ url: '/system/dict-data/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤å­—典数据
export const deleteDictDataList = (ids: number[]) => {
  return request.delete({ url: '/system/dict-data/delete-list', params: { ids: ids.join(',') } })
}
// å¯¼å‡ºå­—典数据
export const exportDictData = (params: any) => {
  return request.download({ url: '/system/dict-data/export-excel', params })
}
src/api/system/dict/dict.type.ts
New file
@@ -0,0 +1,53 @@
import request from '@/config/axios'
export interface DictTypeVO {
  id: number
  name: string
  type: string
  status: number
  remark: string
  createTime: Date
}
// æŸ¥è¯¢å­—典(精简)列表
export const getSimpleDictTypeList = (): Promise<DictTypeVO[]> => {
  return request.get({ url: '/system/dict-type/simple-list' })
}
// æŸ¥è¯¢å­—典列表
export const getDictTypePage = (params: PageParam) => {
  return request.get({ url: '/system/dict-type/page', params })
}
// æŸ¥è¯¢å­—典详情
export const getDictType = (id: number) => {
  return request.get({ url: '/system/dict-type/get?id=' + id })
}
// æ–°å¢žå­—å…¸
export const createDictType = (data: DictTypeVO) => {
  return request.post({ url: '/system/dict-type/create', data })
}
// ä¿®æ”¹å­—å…¸
export const updateDictType = (data: DictTypeVO) => {
  return request.put({ url: '/system/dict-type/update', data })
}
// åˆ é™¤å­—å…¸
export const deleteDictType = (id: number) => {
  return request.delete({ url: '/system/dict-type/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤å­—典类型
export const deleteDictTypeList = (ids: number[]) => {
  return request.delete({ url: '/system/dict-type/delete-list', params: { ids: ids.join(',') } })
}
// å¯¼å‡ºå­—å…¸
export const exportDictType = (params) => {
  return request.download({
    url: '/system/dict-type/export-excel',
    params
  })
}
src/api/system/loginLog/index.ts
New file
@@ -0,0 +1,25 @@
import request from '@/config/axios'
export interface LoginLogVO {
  id: number
  logType: number
  traceId: number
  userId: number
  userType: number
  username: string
  result: number
  status: number
  userIp: string
  userAgent: string
  createTime: Date
}
// æŸ¥è¯¢ç™»å½•日志列表
export const getLoginLogPage = (params: PageParam) => {
  return request.get({ url: '/system/login-log/page', params })
}
// å¯¼å‡ºç™»å½•日志
export const exportLoginLog = (params) => {
  return request.download({ url: '/system/login-log/export-excel', params })
}
src/api/system/mail/account/index.ts
New file
@@ -0,0 +1,47 @@
import request from '@/config/axios'
export interface MailAccountVO {
  id: number
  mail: string
  username: string
  password: string
  host: string
  port: number
  sslEnable: boolean
  starttlsEnable: boolean
}
// æŸ¥è¯¢é‚®ç®±è´¦å·åˆ—表
export const getMailAccountPage = async (params: PageParam) => {
  return await request.get({ url: '/system/mail-account/page', params })
}
// æŸ¥è¯¢é‚®ç®±è´¦å·è¯¦æƒ…
export const getMailAccount = async (id: number) => {
  return await request.get({ url: '/system/mail-account/get?id=' + id })
}
// æ–°å¢žé‚®ç®±è´¦å·
export const createMailAccount = async (data: MailAccountVO) => {
  return await request.post({ url: '/system/mail-account/create', data })
}
// ä¿®æ”¹é‚®ç®±è´¦å·
export const updateMailAccount = async (data: MailAccountVO) => {
  return await request.put({ url: '/system/mail-account/update', data })
}
// åˆ é™¤é‚®ç®±è´¦å·
export const deleteMailAccount = async (id: number) => {
  return await request.delete({ url: '/system/mail-account/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤é‚®ç®±è´¦å·
export const deleteMailAccountList = async (ids: number[]) => {
  return await request.delete({ url: '/system/mail-account/delete-list', params: { ids: ids.join(',') } })
}
// èŽ·å¾—é‚®ç®±è´¦å·ç²¾ç®€åˆ—è¡¨
export const getSimpleMailAccountList = async () => {
  return request.get({ url: '/system/mail-account/simple-list' })
}
src/api/system/mail/log/index.ts
New file
@@ -0,0 +1,37 @@
import request from '@/config/axios'
export interface MailLogVO {
  id: number
  userId: number
  userType: number
  toMails: string[]
  ccMails?: string[]
  bccMails?: string[]
  accountId: number
  fromMail: string
  templateId: number
  templateCode: string
  templateNickname: string
  templateTitle: string
  templateContent: string
  templateParams: string
  sendStatus: number
  sendTime: Date
  sendMessageId: string
  sendException: string
}
// æŸ¥è¯¢é‚®ä»¶æ—¥å¿—列表
export const getMailLogPage = async (params: PageParam) => {
  return await request.get({ url: '/system/mail-log/page', params })
}
// æŸ¥è¯¢é‚®ä»¶æ—¥å¿—详情
export const getMailLog = async (id: number) => {
  return await request.get({ url: '/system/mail-log/get?id=' + id })
}
// å¯¼å‡ºé‚®ä»¶æ—¥å¿—
export const exportMailLog = (params) => {
  return request.download({ url: '/system/mail-log/export-excel', params })
}
src/api/system/mail/template/index.ts
New file
@@ -0,0 +1,58 @@
import request from '@/config/axios'
export interface MailTemplateVO {
  id?: number
  name: string
  code: string
  accountId: number
  nickname: string
  title: string
  content: string
  status: number
}
export interface MailSendReqVO {
  toMails: string[]
  ccMails?: string[]
  bccMails?: string[]
  templateCode: string
  templateParams: Map<String, Object>
}
// æŸ¥è¯¢é‚®ä»¶æ¨¡ç‰ˆåˆ—表
export const getMailTemplatePage = async (params: PageParam) => {
  return await request.get({ url: '/system/mail-template/page', params })
}
// æŸ¥è¯¢é‚®ä»¶æ¨¡ç‰ˆè¯¦æƒ…
export const getMailTemplate = async (id: number) => {
  return await request.get({ url: '/system/mail-template/get?id=' + id })
}
// æ–°å¢žé‚®ä»¶æ¨¡ç‰ˆ
export const createMailTemplate = async (data: MailTemplateVO) => {
  return await request.post({ url: '/system/mail-template/create', data })
}
// ä¿®æ”¹é‚®ä»¶æ¨¡ç‰ˆ
export const updateMailTemplate = async (data: MailTemplateVO) => {
  return await request.put({ url: '/system/mail-template/update', data })
}
// åˆ é™¤é‚®ä»¶æ¨¡ç‰ˆ
export const deleteMailTemplate = async (id: number) => {
  return await request.delete({ url: '/system/mail-template/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤é‚®ä»¶æ¨¡ç‰ˆ
export const deleteMailTemplateList = async (ids: number[]) => {
  return await request.delete({
    url: '/system/mail-template/delete-list',
    params: { ids: ids.join(',') }
  })
}
// å‘送邮件
export const sendMail = (data: MailSendReqVO) => {
  return request.post({ url: '/system/mail-template/send-mail', data })
}
src/api/system/menu/index.ts
New file
@@ -0,0 +1,49 @@
import request from '@/config/axios'
export interface MenuVO {
  id: number
  name: string
  permission: string
  type: number
  sort: number
  parentId: number
  path: string
  icon: string
  component: string
  componentName?: string
  status: number
  visible: boolean
  keepAlive: boolean
  alwaysShow?: boolean
  createTime: Date
}
// æŸ¥è¯¢èœå•(精简)列表
export const getSimpleMenusList = () => {
  return request.get({ url: '/system/menu/simple-list' })
}
// æŸ¥è¯¢èœå•列表
export const getMenuList = (params) => {
  return request.get({ url: '/system/menu/list', params })
}
// èŽ·å–èœå•è¯¦æƒ…
export const getMenu = (id: number) => {
  return request.get({ url: '/system/menu/get?id=' + id })
}
// æ–°å¢žèœå•
export const createMenu = (data: MenuVO) => {
  return request.post({ url: '/system/menu/create', data })
}
// ä¿®æ”¹èœå•
export const updateMenu = (data: MenuVO) => {
  return request.put({ url: '/system/menu/update', data })
}
// åˆ é™¤èœå•
export const deleteMenu = (id: number) => {
  return request.delete({ url: '/system/menu/delete?id=' + id })
}
src/api/system/notice/index.ts
New file
@@ -0,0 +1,47 @@
import request from '@/config/axios'
export interface NoticeVO {
  id: number | undefined
  title: string
  type: number
  content: string
  status: number
  remark: string
  creator: string
  createTime: Date
}
// æŸ¥è¯¢å…¬å‘Šåˆ—表
export const getNoticePage = (params: PageParam) => {
  return request.get({ url: '/system/notice/page', params })
}
// æŸ¥è¯¢å…¬å‘Šè¯¦æƒ…
export const getNotice = (id: number) => {
  return request.get({ url: '/system/notice/get?id=' + id })
}
// æ–°å¢žå…¬å‘Š
export const createNotice = (data: NoticeVO) => {
  return request.post({ url: '/system/notice/create', data })
}
// ä¿®æ”¹å…¬å‘Š
export const updateNotice = (data: NoticeVO) => {
  return request.put({ url: '/system/notice/update', data })
}
// åˆ é™¤å…¬å‘Š
export const deleteNotice = (id: number) => {
  return request.delete({ url: '/system/notice/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤å…¬å‘Š
export const deleteNoticeList = (ids: number[]) => {
  return request.delete({ url: '/system/notice/delete-list', params: { ids: ids.join(',') } })
}
// æŽ¨é€å…¬å‘Š
export const pushNotice = (id: number) => {
  return request.post({ url: '/system/notice/push?id=' + id })
}
src/api/system/notify/message/index.ts
New file
@@ -0,0 +1,49 @@
import request from '@/config/axios'
import qs from 'qs'
export interface NotifyMessageVO {
  id: number
  userId: number
  userType: number
  templateId: number
  templateCode: string
  templateNickname: string
  templateContent: string
  templateType: number
  templateParams: string
  readStatus: boolean
  readTime: Date
  createTime: Date
}
// æŸ¥è¯¢ç«™å†…信消息列表
export const getNotifyMessagePage = async (params: PageParam) => {
  return await request.get({ url: '/system/notify-message/page', params })
}
// èŽ·å¾—æˆ‘çš„ç«™å†…ä¿¡åˆ†é¡µ
export const getMyNotifyMessagePage = async (params: PageParam) => {
  return await request.get({ url: '/system/notify-message/my-page', params })
}
// æ‰¹é‡æ ‡è®°å·²è¯»
export const updateNotifyMessageRead = async (ids) => {
  return await request.put({
    url: '/system/notify-message/update-read?' + qs.stringify({ ids: ids }, { indices: false })
  })
}
// æ ‡è®°æ‰€æœ‰ç«™å†…信为已读
export const updateAllNotifyMessageRead = async () => {
  return await request.put({ url: '/system/notify-message/update-all-read' })
}
// èŽ·å–å½“å‰ç”¨æˆ·çš„æœ€æ–°ç«™å†…ä¿¡åˆ—è¡¨
export const getUnreadNotifyMessageList = async () => {
  return await request.get({ url: '/system/notify-message/get-unread-list' })
}
// èŽ·å¾—å½“å‰ç”¨æˆ·çš„æœªè¯»ç«™å†…ä¿¡æ•°é‡
export const getUnreadNotifyMessageCount = async () => {
  return await request.get({ url: '/system/notify-message/get-unread-count' })
}
src/api/system/notify/template/index.ts
New file
@@ -0,0 +1,54 @@
import request from '@/config/axios'
export interface NotifyTemplateVO {
  id?: number
  name: string
  nickname: string
  code: string
  content: string
  type?: number
  params: string
  status: number
  remark: string
}
export interface NotifySendReqVO {
  userId: number | null
  templateCode: string
  templateParams: Map<String, Object>
}
// æŸ¥è¯¢ç«™å†…信模板列表
export const getNotifyTemplatePage = async (params: PageParam) => {
  return await request.get({ url: '/system/notify-template/page', params })
}
// æŸ¥è¯¢ç«™å†…信模板详情
export const getNotifyTemplate = async (id: number) => {
  return await request.get({ url: '/system/notify-template/get?id=' + id })
}
// æ–°å¢žç«™å†…信模板
export const createNotifyTemplate = async (data: NotifyTemplateVO) => {
  return await request.post({ url: '/system/notify-template/create', data })
}
// ä¿®æ”¹ç«™å†…信模板
export const updateNotifyTemplate = async (data: NotifyTemplateVO) => {
  return await request.put({ url: '/system/notify-template/update', data })
}
// åˆ é™¤ç«™å†…信模板
export const deleteNotifyTemplate = async (id: number) => {
  return await request.delete({ url: '/system/notify-template/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤ç«™å†…信模板
export const deleteNotifyTemplateList = async (ids: number[]) => {
  return await request.delete({ url: '/system/notify-template/delete-list', params: { ids: ids.join(',') } })
}
// å‘送站内信
export const sendNotify = (data: NotifySendReqVO) => {
  return request.post({ url: '/system/notify-template/send-notify', data })
}
src/api/system/oauth2/client.ts
New file
@@ -0,0 +1,52 @@
import request from '@/config/axios'
export interface OAuth2ClientVO {
  id: number
  clientId: string
  secret: string
  name: string
  logo: string
  description: string
  status: number
  accessTokenValiditySeconds: number
  refreshTokenValiditySeconds: number
  redirectUris: string[]
  autoApprove: boolean
  authorizedGrantTypes: string[]
  scopes: string[]
  authorities: string[]
  resourceIds: string[]
  additionalInformation: string
  isAdditionalInformationJson: boolean
  createTime: Date
}
// æŸ¥è¯¢ OAuth2 å®¢æˆ·ç«¯çš„列表
export const getOAuth2ClientPage = (params: PageParam) => {
  return request.get({ url: '/system/oauth2-client/page', params })
}
// æŸ¥è¯¢ OAuth2 å®¢æˆ·ç«¯çš„详情
export const getOAuth2Client = (id: number) => {
  return request.get({ url: '/system/oauth2-client/get?id=' + id })
}
// æ–°å¢ž OAuth2 å®¢æˆ·ç«¯
export const createOAuth2Client = (data: OAuth2ClientVO) => {
  return request.post({ url: '/system/oauth2-client/create', data })
}
// ä¿®æ”¹ OAuth2 å®¢æˆ·ç«¯
export const updateOAuth2Client = (data: OAuth2ClientVO) => {
  return request.put({ url: '/system/oauth2-client/update', data })
}
// åˆ é™¤ OAuth2
export const deleteOAuth2Client = (id: number) => {
  return request.delete({ url: '/system/oauth2-client/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤ OAuth2 å®¢æˆ·ç«¯
export const deleteOAuth2ClientList = (ids: number[]) => {
  return request.delete({ url: '/system/oauth2-client/delete-list', params: { ids: ids.join(',') } })
}
src/api/system/oauth2/token.ts
New file
@@ -0,0 +1,22 @@
import request from '@/config/axios'
export interface OAuth2TokenVO {
  id: number
  accessToken: string
  refreshToken: string
  userId: number
  userType: number
  clientId: string
  createTime: Date
  expiresTime: Date
}
// æŸ¥è¯¢ token列表
export const getAccessTokenPage = (params: PageParam) => {
  return request.get({ url: '/system/oauth2-token/page', params })
}
// åˆ é™¤ token
export const deleteAccessToken = (accessToken: string) => {
  return request.delete({ url: '/system/oauth2-token/delete?accessToken=' + accessToken })
}
src/api/system/operatelog/index.ts
New file
@@ -0,0 +1,30 @@
import request from '@/config/axios'
export type OperateLogVO = {
  id: number
  traceId: string
  userType: number
  userId: number
  userName: string
  type: string
  subType: string
  bizId: number
  action: string
  extra: string
  requestMethod: string
  requestUrl: string
  userIp: string
  userAgent: string
  creator: string
  creatorName: string
  createTime: Date
}
// æŸ¥è¯¢æ“ä½œæ—¥å¿—列表
export const getOperateLogPage = (params: PageParam) => {
  return request.get({ url: '/system/operate-log/page', params })
}
// å¯¼å‡ºæ“ä½œæ—¥å¿—
export const exportOperateLog = (params: any) => {
  return request.download({ url: '/system/operate-log/export-excel', params })
}
src/api/system/permission/index.ts
New file
@@ -0,0 +1,42 @@
import request from '@/config/axios'
export interface PermissionAssignUserRoleReqVO {
  userId: number
  roleIds: number[]
}
export interface PermissionAssignRoleMenuReqVO {
  roleId: number
  menuIds: number[]
}
export interface PermissionAssignRoleDataScopeReqVO {
  roleId: number
  dataScope: number
  dataScopeDeptIds: number[]
}
// æŸ¥è¯¢è§’色拥有的菜单权限
export const getRoleMenuList = async (roleId: number) => {
  return await request.get({ url: '/system/permission/list-role-menus?roleId=' + roleId })
}
// èµ‹äºˆè§’色菜单权限
export const assignRoleMenu = async (data: PermissionAssignRoleMenuReqVO) => {
  return await request.post({ url: '/system/permission/assign-role-menu', data })
}
// èµ‹äºˆè§’色数据权限
export const assignRoleDataScope = async (data: PermissionAssignRoleDataScopeReqVO) => {
  return await request.post({ url: '/system/permission/assign-role-data-scope', data })
}
// æŸ¥è¯¢ç”¨æˆ·æ‹¥æœ‰çš„角色数组
export const getUserRoleList = async (userId: number) => {
  return await request.get({ url: '/system/permission/list-user-roles?userId=' + userId })
}
// èµ‹äºˆç”¨æˆ·è§’色
export const assignUserRole = async (data: PermissionAssignUserRoleReqVO) => {
  return await request.post({ url: '/system/permission/assign-user-role', data })
}
src/api/system/post/index.ts
New file
@@ -0,0 +1,51 @@
import request from '@/config/axios'
export interface PostVO {
  id?: number
  name: string
  code: string
  sort: number
  status: number
  remark: string
  createTime?: Date
}
// æŸ¥è¯¢å²—位列表
export const getPostPage = async (params: PageParam) => {
  return await request.get({ url: '/system/post/page', params })
}
// èŽ·å–å²—ä½ç²¾ç®€ä¿¡æ¯åˆ—è¡¨
export const getSimplePostList = async (): Promise<PostVO[]> => {
  return await request.get({ url: '/system/post/simple-list' })
}
// æŸ¥è¯¢å²—位详情
export const getPost = async (id: number) => {
  return await request.get({ url: '/system/post/get?id=' + id })
}
// æ–°å¢žå²—位
export const createPost = async (data: PostVO) => {
  return await request.post({ url: '/system/post/create', data })
}
// ä¿®æ”¹å²—位
export const updatePost = async (data: PostVO) => {
  return await request.put({ url: '/system/post/update', data })
}
// åˆ é™¤å²—位
export const deletePost = async (id: number) => {
  return await request.delete({ url: '/system/post/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤å²—位
export const deletePostList = async (ids: number[]) => {
  return await request.delete({ url: '/system/post/delete-list', params: { ids: ids.join(',') } })
}
// å¯¼å‡ºå²—位
export const exportPost = async (params) => {
  return await request.download({ url: '/system/post/export-excel', params })
}
src/api/system/role/index.ts
New file
@@ -0,0 +1,56 @@
import request from '@/config/axios'
export interface RoleVO {
  id: number
  name: string
  code: string
  sort: number
  status: number
  type: number
  dataScope: number
  dataScopeDeptIds: number[]
  createTime: Date
}
// æŸ¥è¯¢è§’色列表
export const getRolePage = async (params: PageParam) => {
  return await request.get({ url: '/system/role/page', params })
}
// æŸ¥è¯¢è§’色(精简)列表
export const getSimpleRoleList = async (): Promise<RoleVO[]> => {
  return await request.get({ url: '/system/role/simple-list' })
}
// æŸ¥è¯¢è§’色详情
export const getRole = async (id: number) => {
  return await request.get({ url: '/system/role/get?id=' + id })
}
// æ–°å¢žè§’色
export const createRole = async (data: RoleVO) => {
  return await request.post({ url: '/system/role/create', data })
}
// ä¿®æ”¹è§’色
export const updateRole = async (data: RoleVO) => {
  return await request.put({ url: '/system/role/update', data })
}
// åˆ é™¤è§’色
export const deleteRole = async (id: number) => {
  return await request.delete({ url: '/system/role/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤è§’色
export const deleteRoleList = async (ids: number[]) => {
  return await request.delete({ url: '/system/role/delete-list', params: { ids: ids.join(',') } })
}
// å¯¼å‡ºè§’色
export const exportRole = (params: any) => {
  return request.download({
    url: '/system/role/export-excel',
    params
  })
}
src/api/system/sms/smsChannel/index.ts
New file
@@ -0,0 +1,48 @@
import request from '@/config/axios'
export interface SmsChannelVO {
  id: number
  code: string
  status: number
  signature: string
  remark: string
  apiKey: string
  apiSecret: string
  callbackUrl: string
  createTime: Date
}
// æŸ¥è¯¢çŸ­ä¿¡æ¸ é“列表
export const getSmsChannelPage = (params: PageParam) => {
  return request.get({ url: '/system/sms-channel/page', params })
}
// èŽ·å¾—çŸ­ä¿¡æ¸ é“ç²¾ç®€åˆ—è¡¨
export function getSimpleSmsChannelList() {
  return request.get({ url: '/system/sms-channel/simple-list' })
}
// æŸ¥è¯¢çŸ­ä¿¡æ¸ é“详情
export const getSmsChannel = (id: number) => {
  return request.get({ url: '/system/sms-channel/get?id=' + id })
}
// æ–°å¢žçŸ­ä¿¡æ¸ é“
export const createSmsChannel = (data: SmsChannelVO) => {
  return request.post({ url: '/system/sms-channel/create', data })
}
// ä¿®æ”¹çŸ­ä¿¡æ¸ é“
export const updateSmsChannel = (data: SmsChannelVO) => {
  return request.put({ url: '/system/sms-channel/update', data })
}
// åˆ é™¤çŸ­ä¿¡æ¸ é“
export const deleteSmsChannel = (id: number) => {
  return request.delete({ url: '/system/sms-channel/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤çŸ­ä¿¡æ¸ é“
export const deleteSmsChannelList = (ids: number[]) => {
  return request.delete({ url: '/system/sms-channel/delete-list', params: { ids: ids.join(',') } })
}
src/api/system/sms/smsLog/index.ts
New file
@@ -0,0 +1,37 @@
import request from '@/config/axios'
export interface SmsLogVO {
  id: number | null
  channelId: number | null
  channelCode: string
  templateId: number | null
  templateCode: string
  templateType: number | null
  templateContent: string
  templateParams: Map<string, object> | null
  apiTemplateId: string
  mobile: string
  userId: number | null
  userType: number | null
  sendStatus: number | null
  sendTime: Date | null
  apiSendCode: string
  apiSendMsg: string
  apiRequestId: string
  apiSerialNo: string
  receiveStatus: number | null
  receiveTime: Date | null
  apiReceiveCode: string
  apiReceiveMsg: string
  createTime: Date | null
}
// æŸ¥è¯¢çŸ­ä¿¡æ—¥å¿—列表
export const getSmsLogPage = (params: PageParam) => {
  return request.get({ url: '/system/sms-log/page', params })
}
// å¯¼å‡ºçŸ­ä¿¡æ—¥å¿—
export const exportSmsLog = (params) => {
  return request.download({ url: '/system/sms-log/export-excel', params })
}
src/api/system/sms/smsTemplate/index.ts
New file
@@ -0,0 +1,65 @@
import request from '@/config/axios'
export interface SmsTemplateVO {
  id?: number
  type?: number
  status: number
  code: string
  name: string
  content: string
  remark: string
  apiTemplateId: string
  channelId?: number
  channelCode?: string
  params?: string[]
  createTime?: Date
}
export interface SendSmsReqVO {
  mobile: string
  templateCode: string
  templateParams: Map<String, Object>
}
// æŸ¥è¯¢çŸ­ä¿¡æ¨¡æ¿åˆ—表
export const getSmsTemplatePage = (params: PageParam) => {
  return request.get({ url: '/system/sms-template/page', params })
}
// æŸ¥è¯¢çŸ­ä¿¡æ¨¡æ¿è¯¦æƒ…
export const getSmsTemplate = (id: number) => {
  return request.get({ url: '/system/sms-template/get?id=' + id })
}
// æ–°å¢žçŸ­ä¿¡æ¨¡æ¿
export const createSmsTemplate = (data: SmsTemplateVO) => {
  return request.post({ url: '/system/sms-template/create', data })
}
// ä¿®æ”¹çŸ­ä¿¡æ¨¡æ¿
export const updateSmsTemplate = (data: SmsTemplateVO) => {
  return request.put({ url: '/system/sms-template/update', data })
}
// åˆ é™¤çŸ­ä¿¡æ¨¡æ¿
export const deleteSmsTemplate = (id: number) => {
  return request.delete({ url: '/system/sms-template/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤çŸ­ä¿¡æ¨¡æ¿
export const deleteSmsTemplateList = (ids: number[]) => {
  return request.delete({ url: '/system/sms-template/delete-list', params: { ids: ids.join(',') } })
}
// å¯¼å‡ºçŸ­ä¿¡æ¨¡æ¿
export const exportSmsTemplate = (params) => {
  return request.download({
    url: '/system/sms-template/export-excel',
    params
  })
}
// å‘送短信
export const sendSms = (data: SendSmsReqVO) => {
  return request.post({ url: '/system/sms-template/send-sms', data })
}
src/api/system/social/client/index.ts
New file
@@ -0,0 +1,38 @@
import request from '@/config/axios'
export interface SocialClientVO {
  id: number
  name: string
  socialType: number
  userType: number
  clientId: string
  clientSecret: string
  agentId: string
  publicKey: string
  status: number
}
// æŸ¥è¯¢ç¤¾äº¤å®¢æˆ·ç«¯åˆ—表
export const getSocialClientPage = async (params) => {
  return await request.get({ url: `/system/social-client/page`, params })
}
// æŸ¥è¯¢ç¤¾äº¤å®¢æˆ·ç«¯è¯¦æƒ…
export const getSocialClient = async (id: number) => {
  return await request.get({ url: `/system/social-client/get?id=` + id })
}
// æ–°å¢žç¤¾äº¤å®¢æˆ·ç«¯
export const createSocialClient = async (data: SocialClientVO) => {
  return await request.post({ url: `/system/social-client/create`, data })
}
// ä¿®æ”¹ç¤¾äº¤å®¢æˆ·ç«¯
export const updateSocialClient = async (data: SocialClientVO) => {
  return await request.put({ url: `/system/social-client/update`, data })
}
// åˆ é™¤ç¤¾äº¤å®¢æˆ·ç«¯
export const deleteSocialClient = async (id: number) => {
  return await request.delete({ url: `/system/social-client/delete?id=` + id })
}
src/api/system/social/user/index.ts
New file
@@ -0,0 +1,29 @@
import request from '@/config/axios'
export interface SocialUserVO {
  id: number
  type: number
  openid: string
  token: string
  rawTokenInfo: string
  nickname: string
  avatar: string
  rawUserInfo: string
  code: string
  state: string
}
// æŸ¥è¯¢ç¤¾äº¤ç”¨æˆ·åˆ—表
export const getSocialUserPage = async (params: any) => {
  return await request.get({ url: `/system/social-user/page`, params })
}
// æŸ¥è¯¢ç¤¾äº¤ç”¨æˆ·è¯¦æƒ…
export const getSocialUser = async (id: number) => {
  return await request.get({ url: `/system/social-user/get?id=` + id })
}
// èŽ·å¾—ç»‘å®šç¤¾äº¤ç”¨æˆ·åˆ—è¡¨
export const getBindSocialUserList = async () => {
  return await request.get({ url: '/system/social-user/get-bind-list' })
}
src/api/system/tenant/index.ts
New file
@@ -0,0 +1,73 @@
import request from '@/config/axios'
export interface TenantVO {
  id: number
  name: string
  contactName: string
  contactMobile: string
  status: number
  domain: string
  packageId: number
  username: string
  password: string
  expireTime: Date
  accountCount: number
  websites: string[]
  createTime: Date
}
export interface TenantPageReqVO extends PageParam {
  name?: string
  contactName?: string
  contactMobile?: string
  status?: number
  createTime?: Date[]
}
export interface TenantExportReqVO {
  name?: string
  contactName?: string
  contactMobile?: string
  status?: number
  createTime?: Date[]
}
// æŸ¥è¯¢ç§Ÿæˆ·åˆ—表
export const getTenantPage = (params: TenantPageReqVO) => {
  return request.get({ url: '/system/tenant/page', params })
}
// æŸ¥è¯¢ç§Ÿæˆ·è¯¦æƒ…
export const getTenant = (id: number) => {
  return request.get({ url: '/system/tenant/get?id=' + id })
}
// èŽ·å–ç§Ÿæˆ·ç²¾ç®€ä¿¡æ¯åˆ—è¡¨
export const getTenantList = () => {
  return request.get({ url: '/system/tenant/simple-list' })
}
// æ–°å¢žç§Ÿæˆ·
export const createTenant = (data: TenantVO) => {
  return request.post({ url: '/system/tenant/create', data })
}
// ä¿®æ”¹ç§Ÿæˆ·
export const updateTenant = (data: TenantVO) => {
  return request.put({ url: '/system/tenant/update', data })
}
// åˆ é™¤ç§Ÿæˆ·
export const deleteTenant = (id: number) => {
  return request.delete({ url: '/system/tenant/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤ç§Ÿæˆ·
export const deleteTenantList = (ids: number[]) => {
  return request.delete({ url: '/system/tenant/delete-list', params: { ids: ids.join(',') } })
}
// å¯¼å‡ºç§Ÿæˆ·
export const exportTenant = (params: TenantExportReqVO) => {
  return request.download({ url: '/system/tenant/export-excel', params })
}
src/api/system/tenantPackage/index.ts
New file
@@ -0,0 +1,48 @@
import request from '@/config/axios'
export interface TenantPackageVO {
  id: number
  name: string
  status: number
  remark: string
  creator: string
  updater: string
  updateTime: string
  menuIds: number[]
  createTime: Date
}
// æŸ¥è¯¢ç§Ÿæˆ·å¥—餐列表
export const getTenantPackagePage = (params: PageParam) => {
  return request.get({ url: '/system/tenant-package/page', params })
}
// èŽ·å¾—ç§Ÿæˆ·
export const getTenantPackage = (id: number) => {
  return request.get({ url: '/system/tenant-package/get?id=' + id })
}
// æ–°å¢žç§Ÿæˆ·å¥—餐
export const createTenantPackage = (data: TenantPackageVO) => {
  return request.post({ url: '/system/tenant-package/create', data })
}
// ä¿®æ”¹ç§Ÿæˆ·å¥—餐
export const updateTenantPackage = (data: TenantPackageVO) => {
  return request.put({ url: '/system/tenant-package/update', data })
}
// åˆ é™¤ç§Ÿæˆ·å¥—餐
export const deleteTenantPackage = (id: number) => {
  return request.delete({ url: '/system/tenant-package/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤ç§Ÿæˆ·å¥—餐
export const deleteTenantPackageList = (ids: number[]) => {
  return request.delete({ url: '/system/tenant-package/delete-list', params: { ids: ids.join(',') } })
}
// èŽ·å–ç§Ÿæˆ·å¥—é¤ç²¾ç®€ä¿¡æ¯åˆ—è¡¨
export const getTenantPackageList = () => {
  return request.get({ url: '/system/tenant-package/simple-list' })
}
src/api/system/user/index.ts
New file
@@ -0,0 +1,81 @@
import request from '@/config/axios'
export interface UserVO {
  id: number
  username: string
  nickname: string
  deptId: number
  postIds: string[]
  email: string
  mobile: string
  sex: number
  avatar: string
  loginIp: string
  status: number
  remark: string
  loginDate: Date
  createTime: Date
}
// æŸ¥è¯¢ç”¨æˆ·ç®¡ç†åˆ—表
export const getUserPage = (params: PageParam) => {
  return request.get({ url: '/system/user/page', params })
}
// æŸ¥è¯¢ç”¨æˆ·è¯¦æƒ…
export const getUser = (id: number) => {
  return request.get({ url: '/system/user/get?id=' + id })
}
// æ–°å¢žç”¨æˆ·
export const createUser = (data: UserVO) => {
  return request.post({ url: '/system/user/create', data })
}
// ä¿®æ”¹ç”¨æˆ·
export const updateUser = (data: UserVO) => {
  return request.put({ url: '/system/user/update', data })
}
// åˆ é™¤ç”¨æˆ·
export const deleteUser = (id: number) => {
  return request.delete({ url: '/system/user/delete?id=' + id })
}
// æ‰¹é‡åˆ é™¤ç”¨æˆ·
export const deleteUserList = (ids: number[]) => {
  return request.delete({ url: '/system/user/delete-list', params: { ids: ids.join(',') } })
}
// å¯¼å‡ºç”¨æˆ·
export const exportUser = (params: any) => {
  return request.download({ url: '/system/user/export-excel', params })
}
// ä¸‹è½½ç”¨æˆ·å¯¼å…¥æ¨¡æ¿
export const importUserTemplate = () => {
  return request.download({ url: '/system/user/get-import-template' })
}
// ç”¨æˆ·å¯†ç é‡ç½®
export const resetUserPassword = (id: number, password: string) => {
  const data = {
    id,
    password
  }
  return request.put({ url: '/system/user/update-password', data: data })
}
// ç”¨æˆ·çŠ¶æ€ä¿®æ”¹
export const updateUserStatus = (id: number, status: number) => {
  const data = {
    id,
    status
  }
  return request.put({ url: '/system/user/update-status', data: data })
}
// èŽ·å–ç”¨æˆ·ç²¾ç®€ä¿¡æ¯åˆ—è¡¨
export const getSimpleUserList = (): Promise<UserVO[]> => {
  return request.get({ url: '/system/user/simple-list' })
}
src/api/system/user/profile.ts
New file
@@ -0,0 +1,57 @@
import request from '@/config/axios'
export interface ProfileVO {
  id: number
  username: string
  nickname: string
  dept: {
    id: number
    name: string
  }
  roles: {
    id: number
    name: string
  }[]
  posts: {
    id: number
    name: string
  }[]
  email: string
  mobile: string
  sex: number
  avatar: string
  status: number
  remark: string
  loginIp: string
  loginDate: Date
  createTime: Date
}
export interface UserProfileUpdateReqVO {
  nickname?: string
  email?: string
  mobile?: string
  sex?: number
  avatar?: string
}
// æŸ¥è¯¢ç”¨æˆ·ä¸ªäººä¿¡æ¯
export const getUserProfile = () => {
  return request.get({ url: '/system/user/profile/get' })
}
// ä¿®æ”¹ç”¨æˆ·ä¸ªäººä¿¡æ¯
export const updateUserProfile = (data: UserProfileUpdateReqVO) => {
  return request.put({ url: '/system/user/profile/update', data })
}
// ç”¨æˆ·å¯†ç é‡ç½®
export const updateUserPassword = (oldPassword: string, newPassword: string) => {
  return request.put({
    url: '/system/user/profile/update-password',
    data: {
      oldPassword: oldPassword,
      newPassword: newPassword
    }
  })
}
src/api/system/user/socialUser.ts
New file
@@ -0,0 +1,31 @@
import request from '@/config/axios'
// ç¤¾äº¤ç»‘定,使用 code æŽˆæƒç 
export const socialBind = (type, code, state) => {
  return request.post({
    url: '/system/social-user/bind',
    data: {
      type,
      code,
      state
    }
  })
}
// å–消社交绑定
export const socialUnbind = (type, openid) => {
  return request.delete({
    url: '/system/social-user/unbind',
    data: {
      type,
      openid
    }
  })
}
// ç¤¾äº¤æŽˆæƒçš„跳转
export const socialAuthRedirect = (type, redirectUri) => {
  return request.get({
    url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri
  })
}
src/assets/ai/copy-style2.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1715606039621" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4256" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M878.250667 981.333333H375.338667a104.661333 104.661333 0 0 1-104.661334-104.661333V375.338667a104.661333 104.661333 0 0 1 104.661334-104.661334h502.912a104.661333 104.661333 0 0 1 104.661333 104.661334v502.912C981.333333 934.485333 934.485333 981.333333 878.250667 981.333333zM375.338667 364.373333a10.666667 10.666667 0 0 0-10.922667 10.965334v502.912c0 6.229333 4.693333 10.922667 10.922667 10.922666h502.912a10.666667 10.666667 0 0 0 10.922666-10.922666V375.338667a10.666667 10.666667 0 0 0-10.922666-10.922667H375.338667z" fill="#ffffff" p-id="4257"></path><path d="M192.597333 753.322667H147.328A104.661333 104.661333 0 0 1 42.666667 648.661333V147.328A104.661333 104.661333 0 0 1 147.328 42.666667H650.24a104.661333 104.661333 0 0 1 104.618667 104.661333v49.962667c0 26.538667-20.309333 46.848-46.848 46.848a46.037333 46.037333 0 0 1-46.848-46.848V147.328a10.666667 10.666667 0 0 0-10.922667-10.965333H147.328a10.666667 10.666667 0 0 0-10.965333 10.965333V650.24c0 6.229333 4.693333 10.922667 10.965333 10.922667h45.269333c26.538667 0 46.848 20.309333 46.848 46.848 0 26.538667-21.845333 45.312-46.848 45.312z" fill="#ffffff" p-id="4258"></path></svg>
src/assets/ai/copy.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1715352878351" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1499" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M624.5 786.3c92.9 0 168.2-75.3 168.2-168.2V309c0-92.4-75.3-168.2-168.2-168.2H303.6c-92.4 0-168.2 75.3-168.2 168.2v309.1c0 92.4 75.3 168.2 168.2 168.2h320.9zM178.2 618.1V309c0-69.4 56.1-125.5 125.5-125.5h320.9c69.4 0 125.5 56.1 125.5 125.5v309.1c0 69.4-56.1 125.5-125.5 125.5h-321c-69.4 0-125.4-56.1-125.4-125.5z" p-id="1500" fill="#8a8a8a"></path><path d="M849.8 295.1v361.5c0 102.7-83.6 186.3-186.3 186.3H279.1v42.7h384.4c126.3 0 229.1-102.8 229.1-229.1V295.1h-42.8zM307.9 361.8h312.3c11.8 0 21.4-9.6 21.4-21.4 0-11.8-9.6-21.4-21.4-21.4H307.9c-11.8 0-21.4 9.6-21.4 21.4 0 11.9 9.6 21.4 21.4 21.4zM307.9 484.6h312.3c11.8 0 21.4-9.6 21.4-21.4 0-11.8-9.6-21.4-21.4-21.4H307.9c-11.8 0-21.4 9.6-21.4 21.4 0 11.9 9.6 21.4 21.4 21.4z" p-id="1501" fill="#8a8a8a"></path><path d="M620.2 607.4c11.8 0 21.4-9.6 21.4-21.4 0-11.8-9.6-21.4-21.4-21.4H307.9c-11.8 0-21.4 9.6-21.4 21.4 0 11.8 9.6 21.4 21.4 21.4h312.3z" p-id="1502" fill="#8a8a8a"></path></svg>
src/assets/ai/dall2.jpg
src/assets/ai/dall3.jpg
src/assets/ai/delete.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1715354120346" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3256" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M907.1 263.7H118.9c-9.1 0-16.4-7.3-16.4-16.4s7.3-16.4 16.4-16.4H907c9.1 0 16.4 7.3 16.4 16.4s-7.3 16.4-16.3 16.4z" fill="#8a8a8a" p-id="3257"></path><path d="M772.5 928.3H257.4c-27.7 0-50.2-22.5-50.2-50.2V247.2c0-9.1 7.3-16.4 16.4-16.4H801c12.1 0 21.9 9.8 21.9 21.9v625.2c0 27.8-22.6 50.4-50.4 50.4zM240 263.7v614.4c0 9.6 7.8 17.4 17.4 17.4h515.2c9.7 0 17.5-7.9 17.5-17.5V263.7H240zM657.4 131.1H368.6c-9.1 0-16.4-7.3-16.4-16.4s7.3-16.4 16.4-16.4h288.7c9.1 0 16.4 7.3 16.4 16.4s-7.3 16.4-16.3 16.4z" fill="#8a8a8a" p-id="3258"></path><path d="M416 754.5c-9.1 0-16.4-7.3-16.4-16.4V517.8c0-9.1 7.3-16.4 16.4-16.4s16.4 7.3 16.4 16.4V738c0.1 9.1-7.3 16.5-16.4 16.5z" fill="#8a8a8a" p-id="3259"></path><path d="M416 465.2c-9.1 0-16.4-7.3-16.4-16.4v-59.4c0-9.1 7.3-16.4 16.4-16.4s16.4 7.3 16.4 16.4v59.4c0.1 9.1-7.3 16.4-16.4 16.4zM604.9 754.5c-9.1 0-16.4-7.3-16.4-16.4v-67.2c0-9.1 7.3-16.4 16.4-16.4s16.4 7.3 16.4 16.4V738c0 9.1-7.3 16.5-16.4 16.5z" fill="#8a8a8a" opacity=".4" p-id="3260"></path><path d="M604.9 619.1c-9.1 0-16.4-7.3-16.4-16.4V389.4c0-9.1 7.3-16.4 16.4-16.4s16.4 7.3 16.4 16.4v213.3c0 9.1-7.3 16.4-16.4 16.4z" fill="#8a8a8a" p-id="3261"></path></svg>
src/assets/ai/gpt.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1716345268026" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5622" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M956.408445 419.226665a250.670939 250.670939 0 0 0-22.425219-209.609236A263.163526 263.163526 0 0 0 652.490412 85.715535 259.784384 259.784384 0 0 0 457.728923 0.008192a261.422756 261.422756 0 0 0-249.44216 178.582564 258.453206 258.453206 0 0 0-172.848261 123.901894c-57.03583 96.868753-44.031251 219.132275 32.153053 302.279661a250.670939 250.670939 0 0 0 22.32282 209.609237 263.163526 263.163526 0 0 0 281.595213 123.901893A259.067596 259.067596 0 0 0 566.271077 1023.990784a260.60357 260.60357 0 0 0 249.339762-178.889759 258.453206 258.453206 0 0 0 172.848261-123.901893c57.445423-96.868753 44.13365-218.82508-32.050655-302.074865zM566.578272 957.124721c-45.362429 0-89.496079-15.666934-124.516283-44.543243 1.638372-0.921584 4.198329-2.150363 6.143895-3.481541l206.537289-117.757998a32.35785 32.35785 0 0 0 16.895713-29.081105V474.82892l87.243317 49.97035c1.023983 0.307195 1.638372 1.228779 1.638372 2.252762v238.075953c0 105.8798-86.936122 191.689541-193.942303 191.996736zM148.588578 781.102113a189.846373 189.846373 0 0 1-23.346803-128.612213c1.535974 1.023983 4.09593 2.559956 6.143895 3.48154L337.922959 773.729439c10.444622 6.143896 23.346803 6.143896 34.098621 0l252.30931-143.664758v99.531108c0 1.023983-0.307195 1.945567-1.331177 2.559956l-208.892449 118.986778a196.297463 196.297463 0 0 1-265.518686-70.04041zM94.112704 335.97688c22.630015-39.013737 58.367008-68.81163 101.16948-84.171369V494.591784c0 11.7758 6.45109 22.93721 16.793315 28.978707l252.30931 143.767156L377.141493 716.796006a3.174346 3.174346 0 0 1-2.867152 0.307195l-208.892448-118.986777A190.870355 190.870355 0 0 1 94.215102 335.874482z m717.607001 164.861198L559.410394 357.070922 646.653711 307.20297a3.174346 3.174346 0 0 1 2.969549-0.307195l208.892449 118.986777a190.358364 190.358364 0 0 1 70.961994 262.139544 194.556693 194.556693 0 0 1-101.16948 84.171369V529.407192a31.538664 31.538664 0 0 0-16.588518-28.671513z m87.03852-129.329002c-1.74077-1.023983-4.300727-2.559956-6.246294-3.48154l-206.639687-117.757999a34.09862 34.09862 0 0 0-33.996222 0L399.566711 393.934295v-99.531108c0-1.023983 0.307195-1.945567 1.331178-2.559956l208.892449-119.089176a195.990268 195.990268 0 0 1 265.518686 70.450003c22.732414 38.706542 31.129071 84.171369 23.346803 128.305018zM352.258716 548.862861l-87.243317-49.560757a2.457558 2.457558 0 0 1-1.638372-2.252762V258.870991c0-105.8798 87.243317-191.996736 194.556692-191.689541a194.556693 194.556693 0 0 1 124.209089 44.543243c-1.638372 0.921584-4.198329 2.252762-6.143896 3.48154l-206.639687 117.757999a31.948257 31.948257 0 0 0-16.793315 29.081105l-0.307194 286.715126z m47.307995-100.759887L512 384.001664l112.535687 63.998912v127.997824l-112.228492 63.998912-112.535687-63.998912-0.307195-127.997824z" p-id="5623" fill="#707070"></path></svg>
src/assets/ai/qingxi.jpg
src/assets/ai/ziran.jpg
src/assets/audio/response.mp3
Binary files differ
src/assets/imgs/avatar.gif
src/assets/imgs/avatar.jpg
src/assets/imgs/diy/app-nav-bar-mp.png
src/assets/imgs/diy/statusBar.png
src/assets/imgs/iot/device.png
src/assets/imgs/logo.png
src/assets/imgs/profile.jpg
src/assets/imgs/wechat.png
src/assets/map/json/china.json
New file
@@ -0,0 +1,856 @@
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": "710000",
      "properties": {
        "id": "710000",
        "cp": [121.509062, 24.044332],
        "name": "台湾",
        "childNum": 6
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@°Ü¯Û"],
          [
            "@@ƛĴÕƊÉɼģºðʀ\\ƎsÆNŌÔĚäœnÜƤɊĂǀĆĴžĤNJŨxĚĮǂƺòƌ‚–âÔ®ĮXŦţƸZûЋƕƑGđ¨ĭMó·ęcëƝɉlÝƯֹÅŃ^Ó·śŃNjƏďíåɛGɉ™¿@ăƑŽ¥ĘWǬÏĶŁâ"
          ],
          ["@@\\p|WoYG¿¥I†j@¢"],
          ["@@…¡‰@ˆV^RqˆBbAŒnTXeRz¤Lž«³I"],
          ["@@ÆEE—„kWqë @œ"],
          ["@@fced"],
          ["@@„¯ɜÄèaì¯ØǓIġĽ"],
          ["@@çûĖ롖hòř "]
        ],
        "encodeOffsets": [
          [[122886, 24033]],
          [[123335, 22980]],
          [[122375, 24193]],
          [[122518, 24117]],
          [[124427, 22618]],
          [[124862, 26043]],
          [[126259, 26318]],
          [[127671, 26683]]
        ]
      }
    },
    {
      "type": "Feature",
      "id": "130000",
      "properties": {
        "id": "130000",
        "cp": [114.502461, 38.045474],
        "name": "河北",
        "childNum": 3
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@o~†Z]‚ªr‰ºc_ħ²G¼s`jΟnüsœłNX_“M`ǽÓnUK…Ĝēs¤­©yrý§uģŒc†JŠ›e"],
          ["@@U`Ts¿m‚"],
          [
            "@@oºƋÄd–eVŽDJj£€J|Ådz•Ft~žKŨ¸IÆv|”‡¢r}膎onb˜}`RÎÄn°ÒdÞ²„^®’lnÐèĄlðӜ×]ªÆ}LiĂ±Ö`^°Ç¶p®đDcœŋ`–ZÔ’¶êqvFƚ†N®ĆTH®¦O’¾ŠIbÐã´BĐɢŴÆíȦp–ĐÞXR€·nndOž¤’OÀĈƒ­Qg˜µFo|gȒęSWb©osx|hYh•gŃfmÖĩnº€T̒SpݢdYĤ¶UĈjl’ǐpäìë|³kÛfw²Xjz~ÂqbTŠÑ„ěŨ@|oM‡’zv¢ZrÃVw¬ŧˏfŒ°ÐTۻqŽs{Sž¯r æÝlNd®²Ğ džiGʂJ™¼lr}~K¨ŸƐÌWö€™ÆŠzRš¤lêmĞL΄’@¡|q]SvKۄcwpÏρ†ĿćènĪWlĄkT}ˆJ”¤~ƒÈT„d„™pddʾĬŠ”ŽBVt„EÀ¢ôPĎƗè@~‚k–ü\\rÊĔÖæW_§¼F˜†´©òDòj’ˆYÈrbĞāøŀG{ƀ|¦ðrb|ÀH`pʞkv‚GpuARhÞÆǶgƊTǼƹS£¨¡ù³ŘÍ]¿Ây™ôEP xX¶¹܇O¡“gÚ¡IwÃ鑦ÅB‡Ï|ǰ…N«úmH¯‹âŸDùŽyŜžŲIÄuШDž•¸dɂ‡‚FŸƒ•›Oh‡đ©OŸ›iÃ`ww^ƒÌkŸ‘ÑH«ƇǤŗĺtFu…{Z}Ö@U‡´…ʚLg®¯Oı°ÃwŸ ^˜—€VbÉs‡ˆmA…ê]]w„§›RRl£‡ȭµu¯b{ÍDěïÿȧŽuT£ġƒěŗƃĝ“Q¨fV†Ƌ•ƅn­a@‘³@šď„yýIĹÊKšŭfċŰóŒxV@tˆƯŒJ”]eƒR¾fe|rHA˜|h~Ėƍl§ÏŠlTíb ØoˆÅbbx³^zÃ͚¶Sj®A”yÂhðk`š«P€”ˈµEF†Û¬Y¨Ļrõqi¼‰Wi°§’б´°^[ˆÀ|Ä O@ÆxO\\tŽa\\tĕtû{ġŒȧXýĪÓjùÎRb›š^ΛfK[ݏděYfíÙTyŽuUSyŌŏů@Oi½’éŅ­aVcř§ax¹XŻác‡žWU£ôãºQ¨÷ÑwsÂ¥qEH‰Ù|‰›šYQoŕÇyáĂ£MðoťÊ‰P¡mšWO¡€v†{ôvîēÜISpÌhp¨ ‘j†deŔQÖj˜X³à™Ĉ[n`Yp@Už–cM`’RKhŒEbœ”pŞlNut®Etq‚nsÁŠgA‹iú‹oH‡qCX‡”hfgu“~ϋWP½¢G^}¯ÅīGCŸÑ^ãziMáļMTÃƘrMc|O_ž¯Ŏ´|‡morDkO\\mĆJfl@c̬¢aĦtRıҙ¾ùƀ^juųœK­ƒUFy™—Ɲ…›īÛ÷ąV×qÆ¥V¿aȉd³B›qPBm›aËđŻģm“Å®Vйd^K‡KoŸnYg“¯Xhqa”Ldu¥•ÍpDž¡KąÅƒkĝęěhq‡}HyÓ]¹ǧ£…Í÷¿qáµ§š™g‘¤o^á¾ZE‡¤i`ij{n•ƒOl»ŸWÝĔįhg›F[¿¡—ßkOüš_‰€ū‹i„DZàUtėGylƒ}ŒÓM}€jpEC~¡FtoQi‘šHkk{Ãmï‚"
          ]
        ],
        "encodeOffsets": [[[119712, 40641]], [[121616, 39981]], [[116462, 37237]]]
      }
    },
    {
      "type": "Feature",
      "id": "140000",
      "properties": {
        "id": "140000",
        "cp": [111.849248, 36.857014],
        "name": "山西",
        "childNum": 1
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@Þĩ҃S‰ra}Á€yWix±Üe´lè“ßÓǏok‘ćiµVZģ¡coœ‘TS˹ĪmnÕńe–hZg{gtwªpXaĚThȑp{¶Eh—®RćƑP¿£‘Pmc¸mQÝW•ďȥoÅîɡųAďä³aωJ‘½¥PG­ąSM­™…EÅruµé€‘Yӎ•Ō_d›ĒCo­Èµ]¯_²ÕjāŽK~©ÅØ^ԛkïçămϑk]­±ƒcݯÑÃmQÍ~_a—pm…~ç¡q“ˆu{JÅŧ·Ls}–EyÁÆcI{¤IiCfUc•ƌÃp§]웫vD@¡SÀ‘µM‚ÅwuŽYY‡¡DbÑc¡hƒ×]nkoQdaMç~eD•ÛtT䩱@¥ù@É¡‰ZcW|WqOJmÄ©l«ħşvOÓ«IqăV—¥ŸD[mI~Ó¢cehiÍ]Ɠ~Ä¥qXŠ·eƷœn±“}v•[ěďŽŕ]_‘œ•`‰¹ƒ§ÕōI™o©b­s^}Ét±ū«³p£ÿ·Wµ|¡¥ăFÏs׌¥ŅxŸÊdÒ{ºvĴÎêÌɊ²¶€ü¨|ÞƸµȲ‘LLúÉƎ¤ϊęĔV`„_bª‹S^|ŸdŠzY|dzÂ¥p†ZbÆ£¶ÒK}tĦÔņƠ‚PYzn€ÍvX¶Ěn ĠÔ„zý¦ª˜÷žÑĸَUȌ¸‚dòÜJð´’ìúNM¬ŒXZ´‘¤ŊǸ_tldIš{¦ƀðĠȤ¥NehXnYG‚‡R° ƬDj¬¸|CĞ„Kq‚ºfƐiĺ©ª~ĆOQª ¤@ìǦɌ²æBŒÊ”TœŸ˜ʂōĖ’šĴŞ–ȀœÆÿȄlŤĒö„t”νî¼ĨXhŒ‘˜|ªM¤Ðz"
        ],
        "encodeOffsets": [[116874, 41716]]
      }
    },
    {
      "type": "Feature",
      "id": "150000",
      "properties": {
        "id": "150000",
        "cp": [111.670801, 41.818311],
        "name": "内蒙古",
        "childNum": 2
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            "@@¯PqƒFB…‰|S•³C|kñ•H‹d‘iÄ¥sˆʼnő…PóÑÑE^‘ÅPpy_YtS™hQ·aHwsOnʼnÚs©iqj›‰€USiº]ïWš‰«gW¡A–Rë¥_ŽsgÁnUI«m‰…„‹]j‡vV¼euhwqA„aW˜ƒ_µj…»çjioQR¹ēÃßt@r³[ÛlćË^ÍÉáG“›OUۗOB±•XŸkŇ¹£k|e]ol™ŸkVͼÕqtaÏõjgÁ£§U^Œ”RLˆËnX°Ç’Bz†^~wfvˆypV ¯„ƫĉ˭ȫƗŷɿÿĿƑ˃ĝÿÃǃßËőó©ǐȍŒĖM×ÍEyx‹þp]Évïè‘vƀnÂĴÖ@‚‰†V~Ĉv¦wĖt—ējyÄDXÄxGQuv_›i¦aBçw‘˛wD™©{ŸtāmQ€{EJ§KPśƘƿ¥@‰sCT•É}ɃwˆƇy±ŸgÑ“}T[÷kÐ禫…SÒ¥¸ëBX½‰HáŵÀğtSÝÂa[ƣ°¯¦P]£ġ“–“Òk®G²„èQ°óMq}EŠóƐÇ\\ƒ‡@áügQ͋uÂ¥Fƒ“T՛¿Jû‡]|mvāÎYua^WoÀa·­ząÒot×¶CLƗi¯¤mƎHNJ¤îìɾŊìTdÃ¥wsRÖgĒųúÍġäÕ}Q¶—ˆ¿A•†‹[¡Œ{d×uQAƒ›M•xV‹vMOmăl«ct[wº_šÇʊŽŸjb£ĦS_é“QZ“_lwgOiýe`YYLq§IÁˆdz£ÙË[ÕªuƏ³ÍT—s·bÁĽäė[›b[ˆŗfãcn¥îC¿÷µ[ŏÀQ­ōšĉm¿Á^£mJVm‡—L[{Ï_£›F¥Ö{ŹA}…×Wu©ÅaųijƳhB{·TQqÙIķˑZđ©Yc|M¡…L•eVUóK_QWk’_ĥ‘¿ãZ•»X\\Ä´uUƒè‡lG®ěłTĠğDєOrÍd‚ÆÍz]‹±…ŭ©ŸÅ’]ŒÅÐ}U贩Tċ™ïxgckfWgi\\ÏĒ¥HkµE˜ë{»ÏetcG±ahUiñiWsɁˆ·c–C‚Õk]wȑ|ća}w…VaĚ᠞ŒG°ùnM¬¯†{ÈˆÐÆA’¥ÄêJxÙ¢”hP¢Ûˆº€µwWOŸóFŽšÁz^ÀŗÎú´§¢T¤ǻƺSė‰ǵhÝÅQgvBHouʝl_o¿Ga{ïq{Â¥|ſĿHĂ÷aĝÇq‡Z‘ñiñC³ª—…»E`¨åXēÕqÉû[l•}ç@čƘóO¿¡ƒFUsA‰“ʽīccšocƒ‚ƒÇS}„“£‡IS~ălkÄ©XçmĈ…ŀЂoÐdxÒuL^T{r@¢‘žÍƒĝKén£kQ™‰yšÅõËXŷƏL§~}kqš»IHėDžjĝŸ»ÑÞoŸå°qTt|r©ÏS‹¯·eŨĕx«È[eMˆ¿yuˆ‘pN~¹ÏyN£{©’—g‹ħWí»Í¾s“əšDž_ÃĀɗ±ą™ijĉʍŌŷ—S›É“A‹±åǥɋ@럣R©ąP©}ĹªƏj¹erƒLDĝ·{i«ƫC£µsKCš…GS|úþX”gp›{ÁX¿Ÿć{ƱȏñZáĔyoÁhA™}ŅĆfdʼn„_¹„Y°ėǩÑ¡H¯¶oMQqð¡Ë™|‘Ñ`ƭŁX½·óۓxğįÅcQ‡ˆ“ƒs«tȋDžF“Ÿù^i‘t«Č¯[›hAi©á¥ÇĚ×l|¹y¯YȵƓ‹ñǙµï‚ċ™Ļ|Dœ™üȭ¶¡˜›oŽäÕG\\ďT¿Òõr¯œŸLguÏYęRƩšɷŌO\\İТæ^Ŋ IJȶȆbÜGŽĝ¬¿ĚVĎgª^íu½jÿĕęjık@Ľƒ]ėl¥Ë‡ĭûÁ„ƒėéV©±ćn©­ȇžÍq¯½•YÃÔʼn“ÉNѝÅÝy¹NqáʅDǡËñ­ƁYÅy̱os§ȋµʽǘǏƬɱà‘ưN¢ƔÊuľýľώȪƺɂļžxœZĈ}ÌʼnŪ˜ĺœŽĭFЛĽ̅ȣͽÒŵìƩÇϋÿȮǡŏçƑůĕ~Ǎ›¼ȳÐUf†dIxÿ\\G ˆzâɏÙOº·pqy£†@ŒŠqþ@Ǟ˽IBäƣzsÂZ†ÁàĻdñ°ŕzéØűzșCìDȐĴĺf®ŽÀľưø@ɜÖÞKĊŇƄ§‚͑těï͡VAġÑÑ»d³öǍÝXĉĕÖ{þĉu¸ËʅğU̎éhɹƆ̗̮ȘNJ֥ड़ࡰţાíϲäʮW¬®ҌeרūȠkɬɻ̼ãüfÆ SצɩςåȈHϚÎKdzͲOðÏȆƘ¼CϚǚ࢚˼ФԂ¤ƌžĞ̪Qʤ´¼mÈ JˀŸƲÀɠmǐnǔĎȆÞǠN~€ʢĜ‚¶ƌĆĘźʆȬ˪ĚǏĞGȖƴƀj`ĢçĶāàŃºē̃ĖćšYŒÀŎüôQÐÂŎŞdžŞêƖš˜oˆDĤÕºÑǘÛˤ³̀gńƘĔÀ^žªƂ`ªt¾äƚêĦĀ¼Ð€Ĕǎ¨Ȕ»͠^ˮÊȦƤøxRrŜH¤¸ÂxDĝŒ|ø˂˜ƮÐ¬ɚwɲFjĔ²Äw°dždÀɞ_ĸdîàŎjʜêTĞªŌ‡ŜWÈ|tqÄ¢UB~´°ÎFC•ŽU¼pĀēƄN¦¾O¶ŠłKĊOj“Ě”j´ĜYp˜{¦„ˆSĚÍ\\Tš×ªV–÷Ší¨ÅDK°ßtŇĔKš¨ǵÂcḷ̌ĚǣȄĽF‡lÄ¡UĵœŇ‹ȣFʉɁƒMğįʏƶɷØŭOǽ«ƽū¹Ʊő̝Ȩ§ȞʘĖiɜɶʦ}¨֪ࠜ̀ƇǬ¹ǨE˦ĥªÔêFŽxúQ„Er´W„rh¤Ɛ \\talĈDJ˜Ü|[Pll̚¸ƎGú´Pž¬W¦†^¦–H]prR“n|or¾wLVnÇIujkmon£cX^Bh`Â¥V”„¦U¤¸}€xRj–[^xN[~ªŠxQ„‚[`ªHÆÂExx^wšN¶Ê˜|¨ì†˜€MrœdYp‚oRzNy˜ÀDs~€bcfÌ`L–¾n‹|¾T‚°c¨È¢a‚r¤–`[|òDŞĔöxElÖdH„ÀI`„Ď\\Àì~ƎR¼tf•¦^¢ķ¶e”ÐÚMŒptgj–„ɡČÅyÄ¡Lû™ŇV®ŠÄÈƀ†Ď°P|ªVV†ªj–¬ĚÒêp¬–E|ŬÂc|ÀtƐK fˆ{ĘFǜƌXƲąo½Ę‘\\¥–o}›Ûu£ç­kX‘{uĩ«āíÓUŅßŢq€Ť¥lyň[€oi{¦‹L‡ń‡ðFȪȖ”ĒL„¿Ì‹ˆfΣK£ʺ™oqNŸƒwğc`ue—tOj×°KJ±qƒÆġm‰Ěŗos¬…qehqsuœƒH{¸kH¡Š…ÊRǪÇƌbȆ¢´ä܍¢NìÉʖ¦â©Ġu¦öČ^â£Ăh–šĖMÈÄw‚\\fŦ°W ¢¾luŸD„wŠ\\̀ʉÌÛM…Ā[bӞEn}¶Vc…ê“sƒ"
          ]
        ],
        "encodeOffsets": [[[129102, 52189]]]
      }
    },
    {
      "type": "Feature",
      "id": "210000",
      "properties": {
        "id": "210000",
        "cp": [123.429096, 41.796767],
        "name": "辽宁",
        "childNum": 16
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@L–Ž@@s™a"],
          ["@@MnNm"],
          ["@@d‚c"],
          ["@@eÀ‚C@b‚“‰"],
          ["@@f‡…Xwkbr–Ä`qg"],
          ["@@^jtW‘Q"],
          ["@@~ Y]c"],
          ["@@G`ĔN^_¿Z‚ÃM"],
          ["@@iX¶B‹Y"],
          ["@@„YƒZ"],
          ["@@L_{Epf"],
          ["@@^WqCT\\"],
          ["@@\\[“‹§t|”¤_"],
          ["@@m`n_"],
          ["@@Ïxnj{q_×^Giip"],
          [
            "@@@ώ^B†‡ntˆaÊU—˜Ÿ]x ¯ÄPIJ­°h€ʙK³†VˆÕ@Y~†|EvĹsDŽ¦­L^p²ŸÒG ’Ël]„xxÄ_˜fT¤Ď¤cŽœP„–C¨¸TVjbgH²sdÎdHt`Bˆ—²¬GJję¶[ÐhjeXdlwhšðSȦªVÊπ‹Æ‘Z˜ÆŶ®²†^ŒÎyÅÎcPqń“ĚDMħĜŁH­ˆk„çvV[ij¼W–‚YÀäĦ’‘`XlžR`žôLUVžfK–¢†{NZdĒª’YĸÌÚJRr¸SA|Æ´gŴĴÆbvªØX~†źBŽ|¦ÕœEž¤Ð`\\|Kˆ˜UnnI]¤ÀÂĊnŎ™R®Ő¿¶\\ÀøíDm¦ÎbŨab‰œaĘ\\ľã‚¸a˜tÎSƐ´©v\\ÖÚÌǴ¤Â‡¨JKr€Z_Z€fjþhPkx€`Y”’RIŒjJcVf~sCN¤ ˆE‚œhæm‰–sHy¨SðÑÌ\\\\ŸĐRZk°IS§fqŒßýáЍÙÉÖ[^¯ǤŲ„ê´\\¦¬ĆPM¯£Ÿˆ»uïpùzEx€žanµyoluqe¦W^£ÊL}ñrkqWňûP™‰UP¡ôJŠoo·ŒU}£Œ„[·¨@XŒĸŸ“‹‹DXm­Ûݏº‡›GU‹CÁª½{íĂ^cj‡k“¶Ã[q¤“LÉö³cux«zZfƒ²BWÇ®Yß½ve±ÃC•ý£W{Ú^’q^sÑ·¨‹ÍOt“¹·C¥‡GD›rí@wÕKţ݋˜Ÿ«V·i}xËÍ÷‘i©ĝ‡ɝǡ]ƒˆ{c™±OW‹³Ya±Ÿ‰_穂Hžĕoƫ€Ňqƒr³‰Lys[„ñ³¯OS–ďOMisZ†±ÅFCÂ¥Pq{‚Ã[Pg}\\—¿ghćO…•k^ģÁFıĉĥM­oEqqZûěʼn³F‘¦oĵ—hŸÕP{¯~TÍlª‰N‰ßY“Ð{Ps{ÃVU™™eĎwk±ʼnVÓ½ŽJãÇÇ»Jm°dhcÀff‘dF~ˆ€ĀeĖ€d`sx² šƒ®EżĀdQ‹Âd^~ăÔHˆ¦\\›LKpĄVez¤NP ǹӗR™ÆąJSh­a[¦´Âghwm€BÐ¨źhI|žVVŽ—Ž|p] Â¼èNä¶ÜBÖ¼“L`‚¼bØæŒKV”ŸpoϜNZÞÒKxpw|ÊEMnzEQšŽIZ”ŽZ‡NBˆčÚFÜçmĩ‚WĪñt‘ÞĵÇñZ«uD‚±|Əlij¥ãn·±PmÍa‰–da‡ CL‡Ǒkùó¡³Ï«QaċϑOÃ¥ÕđQȥċƭy‹³ÃA"
          ]
        ],
        "encodeOffsets": [
          [[123686, 41445]],
          [[126019, 40435]],
          [[124393, 40128]],
          [[126117, 39963]],
          [[125322, 40140]],
          [[126686, 40700]],
          [[126041, 40374]],
          [[125584, 40168]],
          [[125453, 40165]],
          [[125362, 40214]],
          [[125280, 40291]],
          [[125774, 39997]],
          [[125976, 40496]],
          [[125822, 39993]],
          [[125509, 40217]],
          [[122731, 40949]]
        ]
      }
    },
    {
      "type": "Feature",
      "id": "220000",
      "properties": { "id": "220000", "cp": [125.3245, 43.886841], "name": "吉林", "childNum": 1 },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@‘p䔳PClƒFbbÍzš€wBG’ĭ€Z„Åi“»ƒlY­ċ²SgŽkÇ£—^S‰“qd¯•‹R…©éŽ£¯S†\\cZ¹iűƏCuƍÓX‡oR}“M^o•£…R}oªU­F…uuXHlEŕ‡€Ï©¤ÛmTŽþ¤D–²ÄufàÀ­XXȱAe„yYw¬dvõ´KÊ£”\\rµÄl”iˆdā]|DÂVŒœH¹ˆÞ®ÜWnŒC”Œķ W‹§@\\¸‹ƒ~¤‹Vp¸‰póIO¢ŠVOšŇürXql~òÉK]¤¥Xrfkvzpm¶bwyFoúvð‡¼¤ N°ąO¥«³[ƒéǡű_°Õ\\ÚÊĝŽþâőàerR¨­JYlďQ[ ÏYëЧTGz•tnŠß¡gFkMŸāGÁ¤ia É‰™È¹`\\xs€¬dĆkNnuNUŠ–užP@‚vRY¾•–\\¢…ŒGªóĄ~RãÖÎĢù‚đŴÕhQŽxtcæëSɽʼníëlj£ƍG£nj°KƘµDsØÑpyƸ®¿bXp‚]vbÍZuĂ{nˆ^IüœÀSք”¦EŒvRÎûh@℈[‚Əȉô~FNr¯ôçR±ƒ­HÑl•’Ģ–^¤¢‚OðŸŒævxsŒ]ÞÁTĠs¶¿âƊGW¾ìA¦·TѬ†è¥€ÏÐJ¨¼ÒÖ¼ƒƦɄxÊ~S–tD@ŠĂ¼Ŵ¡jlºWžvЉˆzƦZЎ²CH— „Axiukd‹ŒGgetqmcžÛ£OzyÂ¥cE}|…¾cZ…k‚‰¿uŐã[oxGikfeäT@…šSUwpiÚFM©’£è^ڟ‚`@v¶eň†f h˜eP¶žt“äOlÔUgƒÞzŸU`lœ}ÔÆUvØ_Ō¬Öi^ĉi§²ÃŠB~¡Ĉ™ÚEgc|DC_Ȧm²rBx¼MÔ¦ŮdĨÃâYx‘ƘDVÇĺĿg¿cwÅ\\¹˜¥YÄ­lœ¤žOv†šLjM_a W`zļMž·\\swqÝSA‡š—q‰Śij¯Š‘°kŠRē°wx^Đkǂғ„œž“œŽ„‹\\]˜nrĂ}²ĊŲÒøãh·M{yMzysěnĒġV·°“G³¼XÀ““™¤¹i´o¤ŃšŸÈ`̃DzÄUĞd\\i֚ŒˆmÈBĤÜɲDEh LG¾ƀľ{WaŒYÍȏĢĘÔRîĐj‹}Ǟ“ccj‡oUb½š{“h§Ǿ{K‹ƖµÎ÷žGĀÖŠåưÎs­l›•yiē«‹`姝HÂ¥Ae^§„GK}iã\\c]v©ģZ“mÃ|“[M}Ä£Tɟĵ‘Â`À–çm‰‘FK¥ÚíÁbXš³ÌQґHof{‰]e€pt·GŋĜYünĎųVY^’˜ydõkÅZW„«WUa~U·Sb•wGçǑ‚“iW^q‹F‚“›uNĝ—·Ew„‹UtW·Ýďæ©PuqEzwAV•—XR‰ãQ`­©GŒM‡ehc›c”ďϝd੄W_ϗYƅŒ»…é\\ƒɹ~ǙG³mØ©BšuT§Ĥ½¢Ã_ý‘L¡‘ýŸqT^rme™\\Pp•ZZbƒyŸ’uybQ—efµ]UhÄ¿DCmûvašÙNSkCwn‰cćfv~…Y‹„ÇG"
        ],
        "encodeOffsets": [[130196, 42528]]
      }
    },
    {
      "type": "Feature",
      "id": "230000",
      "properties": {
        "id": "230000",
        "cp": [128.642464, 46.756967],
        "name": "黑龙江",
        "childNum": 2
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            "@@UĵNÿ¥īè灋•HÍøƕ¶LŒǽ|g¨|”™Ža¾pViˆdd”~ÈiŒíďÓQġėǐZ΋ŽXb½|ſÃH½ŸKFgɱCģÛÇA‡n™‹jÕc[VĝDZÃ˄Ç_™ £ń³pŽj£º”š¿”»WH´¯”U¸đĢmžtĜyzzNN|g¸÷äűѱĉā~mq^—Œ[ƒ”››”ƒǁÑďlw]¯xQĔ‰¯l‰’€°řĴrŠ™˜BˆÞTxr[tޏĻN_yŸX`biN™Ku…Pݣk‚ZĮ—¦[ºxÆÀdhŽĹŀUÈƗCw’áZħÄŭcÓ¥»NAw±qÈ¥nD`{ChdÙFćš}¢‰A±Äj¨]ĊÕjŋ«×`VuÓś~_kÅ·VÝyh„“VkÄãPs”Oµ—fŸge‚Ň…µf@u_Ù ÙcٻNªÙEojVx™T@†ãSefjlwH\\pŏäÀvŠŽlY†½d{†F~¦dyz¤PÜndsrhf‹HcŒvlwjFœ£G˜±DύƥY‡yϊu¹XikĿ¦ÏqƗǀOŜ¨LI|FRĂn sª|Cš˜zxAè¥bœfudTrFWÁ¹Am|˜ĔĕsķÆF‡´Nš‰}ć…UŠÕ@Áijſmužç’uð^ÊýowŒFzØÎĕNőžǏȎôªÌŒDŽàĀÄ˄ĞŀƒʀĀƘŸˮȬƬĊ°ƒUŸzou‡xe]}Ž…AyȑW¯ÌmK‡“Q]‹Īºif¸ÄX|sZt|½ÚUΠlkš^p{f¤lˆºlÆW –€A²˜PVܜPH”Êâ]ÎĈÌÜk´\\@qàsĔÄQºpRij¼èi†`¶—„bXƒrBgxfv»ŽuUiˆŒ^v~”J¬mVp´£Œ´VWrnP½ì¢BX‚¬h™ŠðX¹^TjVœŠriªj™tŊÄm€tPGx¸bgRšŽsT`ZozÆO]’ÒFô҆Oƒ‡ŊŒvŞ”p’cGŒêŠsx´DR–Œ{A†„EOr°Œ•žx|íœbˆ³Wm~DVjºéNN†Ëܲɶ­GƒxÅ·CStŸ}]ûō•SmtuÇÃĕN•™āg»šíT«u}ç½BĵÞʣ¥ëÊ¡Mێ³ãȅ¡ƋaǩÈÉQ‰†G¢·lG|›„tvgrrfǠptęŘnŠÅĢr„I²¯LiØsPf˜_vÄ d„xM prʹšL¤‹¤‡eˌƒÀđK“žïÙVY§]I‡óáĥ]ķ†Kˆ¥Œj|pŇ\\kzţ¦šnņäÔVĂîά|vW’®l¤èØr‚˜•xm¶ă~lÄƯĄ̈́öȄEÔ¤ØQĄ–Ą»ƢjȦOǺ¨ìSŖÆƬy”Qœv`–cwƒZSÌ®ü±DŽ]ŀç¬B¬©ńzƺŷɄeeOĨS’Œfm Ċ‚ƀP̎ēz©Ċ‚ÄÕÊmgŸÇsJ¥ƔˆŊśæ’΁Ñqv¿íUOµª‰ÂnĦÁ_½ä@ê텣P}Ä [@gÄ¡}g“ɊדûÏWXá¢užƻÌsNͽƎÁ§č՛AēeL³àydl›¦ĘVçŁpśdžĽĺſʃQíÜçÛġԏsĕ¬—Ǹ¯YßċġHµ ¡eÃ¥`ļƒrĉŘóƢFì“ĎWøxÊk†”ƈdƬv|–I|·©NqńRŀƒ¤é”eŊœŀ›ˆàŀU²ŕƀB‚Q£Ď}L¹Îk@©ĈuǰųǨ”Ú§ƈnTËÇéƟÊcfčŤ^Xm‡—HĊĕË«W·ċëx³ǔķÐċJā‚wİ_ĸ˜Ȁ^ôWr­°oú¬Ħ…ŨK~”ȰCĐ´Ƕ£’fNÎèâw¢XnÅ®eÂÆĶŽ¾¾xäLĴĘlļO¤ÒĨA¢Êɚ¨®‚ØCÔ ŬGƠ”ƦYĜ‡ĘÜƬDJ—g_ͥœ@čŅĻA“¶¯@wÎqC½Ĉ»NŸăëK™ďÍQ“ÙÆ«[«Ãí•gßÔÇOÝáW‘ñuZ“¯ĥ€Ÿŕā¡ÑķJu¤E Ÿå¯°WKɱ_d_}}vyŸõu¬ï¹ÓU±½@gÏ¿rýD‰†g…Cd‰µ—°MFYxw¿CG£‹Rƛ½Õ{]L§{qqąš¿BÇƻğëšܭNJË|c²}Fµ}›ÙRsÓpg±ŠQNqǫŋRwŕnéÑÉKŸ†«SeYR…ŋ‹@{¤SJ}šD Ûǖ֍Ÿ]gr¡µŷjqWÛham³~S«“„›Þ]"
          ]
        ],
        "encodeOffsets": [[[134456, 44547]]]
      }
    },
    {
      "type": "Feature",
      "id": "320000",
      "properties": {
        "id": "320000",
        "cp": [119.767413, 33.041544],
        "name": "江苏",
        "childNum": 1
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@cþÅPiŠ`ZŸRu¥É\\]~°ŽY`µ†Óƒ^phÁbnÀşúŽòa–ĬºTÖŒb‚˜e¦¦€{¸ZâćNpŒ©žHr|^ˆmjhŠSEb\\afv`sz^lkŽlj‹Ätg‹¤D˜­¾Xš¿À’|ДiZ„ȀåB·î}GL¢õcßjaŸyBFµÏC^ĭ•cÙt¿sğH]j{s©HM¢ƒQnDÀ©DaÜތ·jgàiDbPufjDk`dPOîƒhw¡ĥ‡¥šG˜ŸP²ĐobºrY†„î¶aHŢ´ ]´‚rılw³r_{£DB_ÛdÃ¥uk|ˆŨ¯F Cºyr{XFy™e³Þċ‡¿Â™kÄ­B¿„MvÛpm`rÚã”@ƹhÃ¥gËÖƿxnlč¶Åì½Ot¾dJlŠVJʜǀœŞqvnOŠ^ŸJ”Z‘ż·Q}ê͎ÅmµÒ]Žƍ¦Dq}¬R^èĂ´ŀĻĊIԒtžIJyQŐĠMNtœR®òLh‰›Ěs©»œ}OӌGZz¶A\\jĨFˆäOĤ˜HYš†JvÞHNiÜaϚɖnFQlšNM¤ˆB´ĄNöɂtp–Ŭdf先‹qm¿QûŠùއÚb¤uŃJÅ´u»¹Ą•lȖħŴw̌ŵ²ǹǠ͛hĭłƕrçü±Y™xci‡tğ®jű¢KOķ•Coy`å®VTa­_Ā]ŐÝɞï²ʯÊ^]afYǸÃĆēĪȣJđ͍ôƋĝÄ͎ī‰çÛɈǥ£­ÛmY`ó£Z«§°Ó³QafusNıDž_k}¢m[ÝóDµ—¡RLčiXy‡ÅNïă¡¸iĔϑNÌŕoēdōîåŤûHcs}~Ûwbù¹£¦ÓCt‹OPrƒE^ÒoŠg™ĉIµžÛÅʹK…¤½phMŠü`o怆ŀ"
        ],
        "encodeOffsets": [[121740, 32276]]
      }
    },
    {
      "type": "Feature",
      "id": "330000",
      "properties": {
        "id": "330000",
        "cp": [120.153576, 29.287459],
        "name": "浙江",
        "childNum": 45
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@E^dQ]K"],
          ["@@jX^j‡"],
          ["@@sfŠbU‡"],
          ["@@qP\\xz[ck"],
          ["@@‘Rƒ¢‚FX}°[s_"],
          ["@@Cbœ\\—}"],
          ["@@e|v\\la{u"],
          ["@@v~u}"],
          ["@@QxÂF¯}"],
          ["@@¹nŒvÞs¯o"],
          ["@@rSkUEj"],
          ["@@bi­ZŒP"],
          ["@@p[}INf"],
          ["@@À¿€"],
          ["@@¹dnbŒ…"],
          ["@@rSŸBnR"],
          ["@@g~h}"],
          ["@@FlEk"],
          ["@@OdPc"],
          ["@@v[u\\"],
          ["@@FjâL~wyoo~›sµL–\\"],
          ["@@¬e¹aNˆ"],
          ["@@\\nÔ¡q]L³ë\\ÿ®ŒQ֎"],
          ["@@ÊA­©[¬"],
          ["@@KxŒv­"],
          ["@@@hlIk]"],
          ["@@pW{o||j"],
          ["@@Md|_mC"],
          ["@@¢…X£ÏylD¼XˆtH"],
          ["@@hlÜ[LykAvyfw^Ež›¤"],
          ["@@fp¤Mus“R"],
          ["@@®_ma~•LÁ¬šZ"],
          ["@@iM„xZ"],
          ["@@ZcYd"],
          ["@@Z~dOSo|A¿qZv"],
          ["@@@`”EN¡v"],
          ["@@|–TY{"],
          ["@@@n@m"],
          ["@@XWkCT\\"],
          ["@@ºwšZRkĕWO¢"],
          ["@@™X®±Grƪ\\ÔáXq{‹"],
          ["@@ůTG°ĄLHm°UC‹"],
          [
            "@@¤Ž€aÜx~}dtüGæţŎíĔcŖpMËВj碷ðĄÆMzˆjWKĎ¢Q¶˜À_꒔_Bı€i«pZ€gf€¤Nrq]§ĂN®«H±‡yƳí¾×ŸīàLłčŴǝĂíÀBŖÕªˆŠÁŖHŗʼnåqûõi¨hÜ·ƒñt»¹ýv_[«¸m‰YL¯‰Qª…mĉÅdMˆ•gÇjcº«•ęœ¬­K­´ƒB«Âącoċ\\xKd¡gěŧ«®á’[~ıxu·Å”KsËɏc¢Ù\\ĭƛëbf¹­ģSƒĜkáƉÔ­ĈZB{ŠaM‘µ‰fzʼnfåÂŧįƋǝÊĕġć£g³ne­ą»@­¦S®‚\\ßðCšh™iqªĭiAu‡A­µ”_W¥ƣO\\lċĢttC¨£t`ˆ™PZäuXßBs‡Ļyek€OđġĵHuXBšµ]׌‡­­\\›°®¬F¢¾pµ¼kŘó¬Wät’¸|@ž•L¨¸µr“ºù³Ù~§WI‹ŸZWŽ®’±Ð¨ÒÉx€`‰²pĜ•rOògtÁZ}þÙ]„’¡ŒŸFK‚wsPlU[}¦Rvn`hq¬\\”nQ´ĘRWb”‚_ rtČFI֊kŠŠĦPJ¶ÖÀÖJĈĄTĚòžC ²@Pú…ØzϩPœCÈÚœĒ±„hŖ‡l‰~nm¨f©–iļ«m‡nt–u†ÖZÜÄj“ŠLŽ®E̜Fª²iÊxبžIÈhhst"
          ],
          ["@@o\\V’zRZ}y"],
          ["@@†@°¡mۛGĕ¨§Ianá[ýƤjfæ‡ØL–•äGr™"]
        ],
        "encodeOffsets": [
          [[125592, 31553]],
          [[125785, 31436]],
          [[125729, 31431]],
          [[125513, 31380]],
          [[125223, 30438]],
          [[125115, 30114]],
          [[124815, 29155]],
          [[124419, 28746]],
          [[124095, 28635]],
          [[124005, 28609]],
          [[125000, 30713]],
          [[125111, 30698]],
          [[125078, 30682]],
          [[125150, 30684]],
          [[124014, 28103]],
          [[125008, 31331]],
          [[125411, 31468]],
          [[125329, 31479]],
          [[125626, 30916]],
          [[125417, 30956]],
          [[125254, 30976]],
          [[125199, 30997]],
          [[125095, 31058]],
          [[125083, 30915]],
          [[124885, 31015]],
          [[125218, 30798]],
          [[124867, 30838]],
          [[124755, 30788]],
          [[124802, 30809]],
          [[125267, 30657]],
          [[125218, 30578]],
          [[125200, 30562]],
          [[124968, 30474]],
          [[125167, 30396]],
          [[124955, 29879]],
          [[124714, 29781]],
          [[124762, 29462]],
          [[124325, 28754]],
          [[123990, 28459]],
          [[125366, 31477]],
          [[125115, 30363]],
          [[125369, 31139]],
          [[122495, 31878]],
          [[125329, 30690]],
          [[125192, 30787]]
        ]
      }
    },
    {
      "type": "Feature",
      "id": "340000",
      "properties": { "id": "340000", "cp": [117.283042, 31.26119], "name": "安徽", "childNum": 3 },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@^iuLX^"],
          ["@@‚e©Ehl"],
          [
            "@@°ZÆëϵmkǀwÌÕæhºgBĝâqÙĊz›ÖgņtÀÁÊÆá’hEz|WzqD¹€Ÿ°E‡ŧl{ævÜcA`¤C`|´qžxIJkq^³³ŸGšµbĒZ…¹qpa±ď OH—¦™Ħˆx¢„gPícOl_iCveaOjCh߸i݋bÛªCC¿€m„RV§¢A|t^iÄ GÀtÚs–d]ĮÐDE¶zAb àiödK¡~H¸íæAžǿYƒ“j{ď¿‘™À½W—®£ChŒÃsiŒkkly]_teu[bFa‰Tig‡n{]Gqªo‹ĈMYá|·¥f¥—őaSÕė™NµñĞ«ImŒ_m¿Âa]uĜp …Z_§{CĊg¤°r[_Yj‰ÆOdý“[ŽI[á·¥“Q_n‡ùgL¾mv™ˊBÜÆ¶ĊJhšp“c¹˜O]iÅ ]œ¥ jtsggJǧw×jÉ©±›EFˍ­‰Ki”ÛÃÕYv…s•ˆm¬njĻª•§emná}k«ŕˆƒgđ²Ù›DǤ›í¡ªOy›†×Où±@DŸñSęćăÕIÕ¿IµĥO‰‰jNÕËT¡¿tNæŇàåyÄ·rĕq§ÄĩsWÆßŽF¶žX®¿‰mΪw…RIޓfßoG‘³¾©uyH‘į{Ɓħ¯AFnuP…ÍÔzšŒV—dàôº^Ðæd´€‡oG¤{S‰¬ćxã}›ŧ×Kǥĩ«žÕOEзÖdÖsƘѨ[’Û^Xr¢¼˜§xvěƵ`K”§ tÒ´Cvlo¸fzŨð¾NY´ı~ÉĔē…ßúLÃϖ_ÈÏ|]ÂÏFl”g`bšežž€n¾¢pU‚h~ƴ˶_‚r sĄ~cž”ƈ]|r c~`¼{À{ȒiJjz`îÀT¥Û³…]’u}›f…ïQl{skl“oNdŸjŸäËzDvčoQŠďHI¦rb“tHĔ~BmlRš—V_„ħTLnñH±’DžœL‘¼L˜ªl§Ťa¸ŒĚlK²€\\RòvDcÎJbt[¤€D@®hh~kt°ǾzÖ@¾ªdb„YhüóZ ň¶vHrľ\\ʗJuxAT|dmÀO„‹[ÃԋG·ĚąĐlŪÚpSJ¨ĸˆLvÞcPæķŨŽ®mАˆálŸwKhïgA¢ųƩޖ¤OȜm’°ŒK´"
          ]
        ],
        "encodeOffsets": [[[121722, 32278]], [[119475, 30423]], [[119168, 35472]]]
      }
    },
    {
      "type": "Feature",
      "id": "350000",
      "properties": {
        "id": "350000",
        "cp": [118.306239, 26.075302],
        "name": "福建",
        "childNum": 18
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@“zht´‡]"],
          ["@@aj^~ĆG—©O"],
          ["@@ed¨„C}}i"],
          ["@@@vˆPGsQ"],
          ["@@‰sBz‚ddW]Q"],
          ["@@SލQ“{"],
          ["@@NŽVucW"],
          ["@@qptBAq"],
          ["@@‰’¸[mu"],
          ["@@Q\\pD]_"],
          ["@@jSwUadpF"],
          ["@@eXª~ĥ"],
          ["@@AjvFso"],
          ["@@fT–›_Çí\\Ÿ™—v|ba¦jZÆy€°"],
          ["@@IjJi"],
          ["@@wJI€ˆxš«¼AoNe{M­"],
          ["@@K‰±¡Óˆ”ČäeZ"],
          [
            "@@k¡¹Eh~c®wBk‹UplÀ¡I•~Māe£bN¨gZý¡a±Öcp©PhžI”Ÿ¢Qq…ÇGj‹|Â¥U™ g[Ky¬ŏ–v@OpˆtÉEŸF„\\@ åA¬ˆV{Xģ‰ĐBy…cpě…¼³Ăp·¤ƒ¥o“hqqÚ¡ŅLsƒ^ᗞ§qlŸÀhH¨MCe»åÇGDÂ¥zPO£čÙkJA¼ß–ėu›ĕeûҍiÁŧSW¥˜QŠûŗ½ùěcݧSùĩąSWó«íęACµ›eR—åǃRCÒÇZÍ¢‹ź±^dlsŒtjD¸•‚ZpužÔâÒH¾oLUêÃÔjjēò´ĄW‚ƛ…^Ñ¥‹ĦŸ@Çò–ŠmŒƒOw¡õyJ†yD}¢ďÑÈġfŠZd–a©º²z£šN–ƒjD°Ötj¶¬ZSÎ~¾c°¶Ðm˜x‚O¸¢Pl´žSL|¥žA†ȪĖM’ņIJg®áIJČĒü` ŽQF‡¬h|ÓJ@zµ |ê³È ¸UÖŬŬÀEttĸr‚]€˜ðŽM¤ĶIJHtÏ A’†žĬkvsq‡^aÎbvŒd–™fÊòSD€´Z^’xPsÞrv‹ƞŀ˜jJd×ŘÉ ®A–ΦĤd€xĆqAΠZR”ÀMźŒnĊ»ŒİÐZ— YX–æJŠyĊ²ˆ·¶q§·–K@·{s‘Xãô«lŗ¶»o½E¡­«¢±¨Yˆ®Ø‹¶^A™vWĶGĒĢžPlzfˆļŽtàAvWYãšO_‡¤sD§ssČġ[kƤPX¦Ž`¶“ž®ˆBBvĪjv©šjx[L¥àï[F…¼ÍË»ğV`«•Ip™}ccÅĥZE‹ãoP…´B@ŠD—¸m±“z«Ƴ—¿å³BRضˆœWlâþäą`“]Z£Tc— ĹGµ¶H™m@_©—kŒ‰¾xĨ‡ôȉðX«½đCIbćqK³Á‹Äš¬OAwã»aLʼn‡ËĥW[“ÂGI—ÂNxij¤D¢ŽîĎÎB§°_JœGsĴE@…¤uć…P‘å†cuMuw¢BI¿‡]zG¹guÄ®ck\\_"
          ]
        ],
        "encodeOffsets": [
          [[123250, 27563]],
          [[122541, 27268]],
          [[123020, 27189]],
          [[122916, 27125]],
          [[122887, 26845]],
          [[122808, 26762]],
          [[122568, 25912]],
          [[122778, 26197]],
          [[122515, 26757]],
          [[122816, 26587]],
          [[123388, 27005]],
          [[122450, 26243]],
          [[122578, 25962]],
          [[121255, 25103]],
          [[120987, 24903]],
          [[122339, 25802]],
          [[121042, 25093]],
          [[122439, 26024]]
        ]
      }
    },
    {
      "type": "Feature",
      "id": "360000",
      "properties": {
        "id": "360000",
        "cp": [115.592151, 27.676493],
        "name": "江西",
        "childNum": 1
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@ĢĨƐgÂMD~ņªe^\\^§„ý©j׍cZ†Ø¨zdÒa¶ˆlҍJŒìõ`oz÷@¤u޸´†ôęöY¼‰HČƶajlÞƩ¥éZ[”|h}^U Œ ¥p„ĄžƦO lt¸Æ €Q\\€ŠaÆ|CnÂOjt­ĚĤd’ÈŒF`’¶„@Ð딠¦ōҞ¨Sêv†HĢûXD®…QgėWiØPÞìºr¤dž€NĠ¢l–•ĄtZoœCƞÔºCxrpÄ V®Ê{f_Y`_ƒeq’’®Aot`@o‚DXfkp¨|Šs¬\\D‘ÄSfè©Hn¬…^DhÆyøJh“ØxĢĀLʈ„ƠPżċĄwȠ̦G®ǒĤäTŠÆ~ĦwŠ«|TF¡Šn€c³Ïå¹]ĉđxe{ÎӐ†vOEm°BƂĨİ|G’vz½ª´€H’àp”eJ݆Qšxn‹ÀŠW­žEµàXÅĪt¨ÃĖrÄwÀFÎ|ňÓMå¼ibµ¯»åDT±m[“r«_gŽmQu~Â¥V\\OkxtL E¢‹ƒ‘Ú^~ýê‹Pó–qo슱_Êw§ÑªåƗ⼋mĉŹ‹¿NQ“…YB‹ąrwÄ£cÍ¥B•Ÿ­ŗÊcØiI—žƝĿuŒqtāwO]‘³YCñTeɕš‹caub͈]trlu€ī…B‘ПGsĵıN£ï—^Ä·qss¿FūūV՟·´Ç{éĈý‰ÿ›OEˆR_ŸđûIċâJh­ŅıN‘ȩĕB…¦K{Tk³¡OP·wn—µÏd¯}½TÍ«YiµÕsC¯„iM•¤™­•¦¯P|ÿUHv“heÂ¥oFTu‰õ\\ŽOSs‹MòđƇiaºćXŸĊĵà·çhƃ÷ǜ{‘ígu^›đg’m[×zkKN‘¶Õ»lčÓ{XSƉv©_ÈëJbVk„ĔVÀ¤P¾ºÈMÖxlò~ªÚàGĂ¢B„±’ÌŒK˜y’áV‡¼Ã~­…`g›ŸsÙfI›Ƌlę¹e|–~udjˆuTlXµf`¿JdŠ[\\˜„L‚‘²"
        ],
        "encodeOffsets": [[116689, 26234]]
      }
    },
    {
      "type": "Feature",
      "id": "370000",
      "properties": {
        "id": "370000",
        "cp": [118.000923, 36.275807],
        "name": "山东",
        "childNum": 13
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@Xjd]{K"],
          ["@@itbFHy"],
          ["@@HlGk"],
          ["@@T‚ŒGŸy"],
          ["@@K¬˜•‹U"],
          ["@@WdXc"],
          ["@@PtOs"],
          ["@@•LnXhc"],
          ["@@ppVƒu]Or"],
          ["@@cdzAUa"],
          ["@@udRhnCI‡"],
          ["@@ˆoIƒpR„"],
          [
            "@@Ľč{fzƤî’Kš–ÎMÄ®]†—ZFˆ½Y]â£ph’™š¶¨râøÀ†ÎǨ¤^ºÄ”Gzˆ~grĚĜlĞÆ„LĆdž¢Îo¦–cv“Kb€gr°Wh”mZp ˆL]LºcU‰Æ­n”żĤÌǜbAnrOAœ´žȊcÀbƦUØrĆUÜøœĬƞ†š˜Ez„VL®öØBkŖÝĐ˹ŧ̄±ÀbÎɜnb²ĦhņBĖ›žįĦåXćì@L¯´ywƕCéõė ƿ¸‘lµ¾Z|†ZWyFY٬Mf~C¿`ۈ_RÇzwƌfQnny´INoƬˆèôº|sT„JUš›‚L„îVj„ǎ¾Ē؍‚Dz²XPn±ŴPè¸ŔLƔÜƺ_T‘üÃĤBBċȉöA´fa„˜M¨{«M`‡¶d¡ô‰Ö°šmȰBÔjjΫPM|”c^d¤u•ƒ¤Û´Œä«ƢfPk¶Môlˆ]Lb„}su^ke{lC‘…M•rDŠÇ­]NÑFsmoõľH‰yGă{{çrnÓE‰‹ƕZGª¹Fj¢ïW…uøCǷ돡ąuhÛ¡^Kx•C`C\\bÅxì²ĝÝ¿_N‰īCȽĿåB¥¢·IŖÕy\\‡¹kx‡Ã£Č×GDyÕ¤ÁçFQ¡„KtŵƋ]CgÏAùSed‡cÚź—ŠuYfƒyMmhUWpSyGwMPqŀ—›Á¼zK›¶†G•­Y§Ëƒ@–´śÇµƕBmœ@Io‚g——Z¯u‹TMx}C‘‰VK‚ï{éƵP—™_K«™pÛÙqċtkkù]gŽ‹Tğwo•ɁsMõ³ă‡AN£™MRkmEʕč™ÛbMjÝGu…IZ™—GPģ‡ãħE[iµBEuŸDPԛ~ª¼ętŠœ]ΞG§€¡QMsğNPŏįzs£Ug{đJĿļā³]ç«Qr~Â¥CƎÑ^n¶ÆéÎR~ݏY’I“] P‰umŝrƿ›‰›Iā‹[x‰edz‹L‘¯v¯s¬ÁY…~}…ťuٌg›ƋpÝĄ_ņī¶ÏSR´ÁP~ž¿Cyžċßdwk´Ss•X|t‰`Ä Èð€AªìÎT°¦Dd–€a^lĎDĶÚY°Ž`ĪŴǒˆ”àŠv\\ebŒZH„ŖR¬ŢƱùęO•ÑM­³FۃWp[ƒ"
          ]
        ],
        "encodeOffsets": [
          [[123806, 39303]],
          [[123821, 39266]],
          [[123742, 39256]],
          [[123702, 39203]],
          [[123649, 39066]],
          [[123847, 38933]],
          [[123580, 38839]],
          [[123894, 37288]],
          [[123043, 36624]],
          [[123344, 38676]],
          [[123522, 38857]],
          [[123628, 38858]],
          [[118260, 36742]]
        ]
      }
    },
    {
      "type": "Feature",
      "id": "410000",
      "properties": {
        "id": "410000",
        "cp": [113.665412, 33.757975],
        "name": "河南",
        "childNum": 1
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@•ýL™ùµP³swIÓxcŢĞð†´E®žÚPt†ĴXØx¶˜@«ŕŕQGƒ‹Yfa[şu“ßǩ™đš_X³ijÕčC]kbc•¥CS¯ëÍB©÷‹–³­Siˆ_}m˜YTtž³xlàcȂzÀD}ÂOQ³ÐTĨ¯†ƗòËŖ[hœł‹Ŧv~††}ÂZž«¤lPǕ£ªÝŴÅR§ØnhcŒtâk‡nύ­ľŹUÓÝdKuķ‡I§oTũÙďkęĆH¸ÓŒ\\ăŒ¿PcnS{wBIvɘĽ[GqµuŸŇôYgûƒZcaŽ©@½Õǽys¯}lgg@­C\\£as€IdÍuCQñ[L±ęk·‹ţb¨©kK—’»›KC²‘òGKmĨS`ƒ˜UQ™nk}AGē”sqaJ¥ĐGR‰ĎpCuÌy ã iMc”plk|tRk†ðœev~^‘´†¦ÜŽSí¿_iyjI|ȑ|¿_»d}qŸ^{“Ƈdă}Ÿtqµ`Ƴĕg}V¡om½fa™Ço³TTj¥„tĠ—Ry”K{ùÓjuµ{t}uËR‘iŸvGŠçJFjµŠÍyqΘàQÂFewixGw½YÅ·pµú³XU›½ġy™łå‰kÚwZXˆ·l„¢Á¢K”zO„Λ΀jc¼htoDHr…|­J“½}JZ_¯iPq{tę½ĕ¦Zpĵø«kQ…Ťƒ]MÛfaQpě±ǽ¾]u­Fu‹÷nƒ™čįADp}AjmcEǒaª³o³ÆÍSƇĈÙDIzˑ赟^ˆKLœ—i—Þñ€[œƒaA²zz‰Ì÷Dœ|[šíijgf‚ÕÞd®|`ƒĆ~„oĠƑô³Ŋ‘D×°¯CsŠøÀ«ì‰UMhTº¨¸ǡîS–Ô„DruÂÇZ•ÖEŽ’vPZ„žW”~؋ÐtĄE¢¦Ðy¸bŠô´oŬ¬Ž²Ês~€€]®tªašpŎJ¨Öº„_ŠŔ–`’Ŗ^Ѝ\\Ĝu–”~m²Ƹ›¸fW‰ĦrƔ}Î^gjdfÔ¡J}\\n C˜¦þWxªJRÔŠu¬ĨĨmF†dM{\\d\\ŠYÊ¢ú@@¦ª²SŠÜsC–}fNècbpRmlØ^g„d¢aÒ¢CZˆZxvÆ¶N¿’¢T@€uCœ¬^ĊðÄn|žlGl’™Rjsp¢ED}€Fio~ÔNŽ‹„~zkĘHVsDzßjƒŬŒŠÅ¢`Pûàl¢˜\\ÀœEhŽİgÞē X¼Pk–„|m"
        ],
        "encodeOffsets": [[118256, 37017]]
      }
    },
    {
      "type": "Feature",
      "id": "420000",
      "properties": {
        "id": "420000",
        "cp": [113.298572, 30.684355],
        "name": "湖北",
        "childNum": 3
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@AB‚"],
          ["@@lskt"],
          [
            "@@¾«}{ra®pîÃ\\™›{øCŠËyyB±„b\\›ò˜Ý˜jK›‡L ]ĎĽÌ’JyÚCƈćÎT´Å´pb©È‘dFin~BCo°BĎĚømvΨE^vǾ½Ĝ²Ro‚bÜeNŽ„^ĺ£R†¬lĶ÷YoĖ¥Ě¾|sOr°jY`~I”¾®I†{GqpCgyl{‡£œÍƒÍyPL“¡ƒ¡¸kW‡xYlÙæŠšŁĢzœ¾žV´W¶ùŸo¾ZHxjwfx„GNÁ•³Xéæl¶‰EièIH‰ u’jÌQ~v|sv¶Ôi|ú¢Fh˜Qsğ¦ƒSiÅ Bg™ÐE^ÁÐ{–čnOÂȞUÎóĔ†ÊēIJ}Z³½Mŧïeyp·uk³DsѨŸL“¶_ρuèw»—€¡WqÜ]\\‘Ò§tƗcÕ¸ÕFÏǝĉăxŻČƟO‡ƒKÉġÿ×wg”÷IÅzCg†]mǻGeçÃTC’«[‰t§{loWeC@ps_Bp‘­r‘„f_``Z|ei¡—oċMqow€¹DƝӛDYpûs•–‹Ykıǃ}s¥ç³[§ŸcYЧHK„«Qy‰]¢“wwö€¸ïx¼ņ¾Xv®ÇÀµRĠЋžHMž±cÏd„ƒǍũȅȷ±DSyúĝ£ŤĀàtÖÿï[îb\\}pĭÉI±Ñy…¿³x¯N‰o‰|¹H™ÏÛm‹júË~Tš•u˜ęjCöAwě¬R’đl¯ Ñb­‰ŇT†Ŀ_[Œ‘IčĄʿnM¦ğ\\É[T·™k¹œ©oĕ@A¾w•ya¥Y\\¥Âaz¯ãÁ¡kÂ¥ne£Ûw†E©Êō¶˓uoj_Uƒ¡cF¹­[Wv“P©w—huÕyBF“ƒ`R‹qJUw\\i¡{jŸŸEPïÿ½fć…QÑÀQ{ž‚°‡fLԁ~wXg—ītêݾ–ĺ‘Hdˆ³fJd]‹HJ²…E€ƒoU¥†HhwQsƐ»Xmg±çve›]Dm͂PˆoCc¾‹_h”–høYrŊU¶eD°Č_N~øĹĚ·`z’]Äþp¼…äÌQŒv\\rCŒé¾TnkžŐڀÜa‡“¼ÝƆ̶Ûo…d…ĔňТJq’Pb ¾|JŒ¾fXŠƐîĨ_Z¯À}úƲ‹N_ĒĊ^„‘ĈaŐyp»CÇĕKŠšñL³ŠġMŒ²wrIÒŭxjb[œžn«øœ˜—æˆàƒ ^²­h¯Ú€ŐªÞ¸€Y²ĒVø}Ā^İ™´‚LŠÚm„¥ÀJÞ{JVŒųÞŃx×sxxƈē ģMř–ÚðòIf–Ċ“Œ\\Ʈ±ŒdʧĘD†vČ_Àæ~DŒċ´A®µ†¨ØLV¦êHÒ¤"
          ]
        ],
        "encodeOffsets": [[[113712, 34000]], [[115612, 30507]], [[113649, 34054]]]
      }
    },
    {
      "type": "Feature",
      "id": "430000",
      "properties": { "id": "430000", "cp": [111.782279, 28.09409], "name": "湖南", "childNum": 3 },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@—n„FTs"],
          ["@@ßÅÆá‰½ÔXr—†CO™“…ËR‘ïÿĩ­TooQyšÓ[‹ŅBE¬–ÎÓXa„į§Ã¸G °ITxp‰úxÚij¥Ïš–̾ŠedžÄ©ĸG…œàGh‚€M¤–Â_U}Ċ}¢pczfŠþg¤€”ÇòAV‘‹M"],
          [
            "@@©K—ƒA·³CQ±Á«³BUŠƑ¹AŠtćOw™D]ŒJiØSm¯b£‘ylƒ›X…H脱H•«–‘C^õľA–Å§¤É¥„ïyuǙuA¢^{ÌC´­¦ŷJ£^[†“ª¿‡ĕ~•Ƈ…•N… skóā‡¹¿€ï]ă~÷O§­@—Vm¡‹Qđ¦¢Ĥ{ºjԏŽŒª¥nf´•~ÕoŸž×Ûą‹MąıuZœmZcÒ IJβSÊDŽŶ¨ƚƒ’CÖŎªQؼrŭŽ­«}NÏürʬŒmjr€@ĘrTW ­SsdHzƓ^ÇÂyUi¯DÅYlŹu{hTœ}mĉ–¹¥ě‰Dÿë©ıÓ[Oº£ž“¥ót€ł¹MՄžƪƒ`Pš…Di–ÛUоÅ‌ìˆU’ñB“È£ýhe‰dy¡oċ€`pfmjP~‚kZa…ZsÐd°wj§ƒ@€Ĵ®w~^‚kÀÅKvNmX\\¨a“”сqvíó¿F„¤¡@ũÑVw}S@j}¾«pĂr–ªg àÀ²NJ¶¶Dô…K‚|^ª†Ž°LX¾ŴäPᜣEXd›”^¶›IJÞܓ~‘u¸ǔ˜Ž›MRhsR…e†`ÄofIÔ\\Ø  i”ćymnú¨cj ¢»–GČìƊÿШXeĈ¾Oð Fi ¢|[jVxrIQŒ„_E”zAN¦zLU`œcªx”OTu RLÄ¢dV„i`p˔vŎµªÉžF~ƒØ€d¢ºgİàw¸Áb[¦Zb¦–z½xBĖ@ªpº›šlS¸Ö\\Ĕ[N¥ˀmĎă’J\\‹ŀ`€…ňSڊĖÁĐiO“Ĝ«BxDõĚiv—ž–S™Ì}iùŒžÜnšÐºGŠ{Šp°M´w†ÀÒzJ²ò¨ oTçüöoÛÿñŽőФ‚ùTz²CȆȸǎۃƑÐc°dPÎŸğ˶[Ƚu¯½WM¡­Éž“’B·rížnZŸÒ `‡¨GA¾\\pē˜XhÆRC­üWGÄ¡u…T靧Ŏѝ©ò³I±³}_‘‹EÃħg®ęisÁPDmÅ{‰b[Rşs·€kPŸŽƥƒóRo”O‹ŸVŸ~]{g\\“êYƪ¦kÝbiċƵŠGZ»Ěõ…ó·³vŝž£ø@pyö_‹ëŽIkѵ‡bcѧy…×dY؎ªiþž¨ƒ[]f]Ņ©C}ÁN‡»hĻħƏ’ĩ"
          ]
        ],
        "encodeOffsets": [[[115640, 30489]], [[112543, 27312]], [[116690, 26230]]]
      }
    },
    {
      "type": "Feature",
      "id": "440000",
      "properties": {
        "id": "440000",
        "cp": [113.280637, 23.125178],
        "name": "广东",
        "childNum": 24
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@QdˆAua"],
          ["@@ƒlxDLo"],
          ["@@sbhNLo"],
          ["@@Ă āŸ"],
          ["@@WltO[["],
          ["@@Krœ]S"],
          ["@@e„„I]y"],
          ["@@I|„Mym"],
          ["@@ƒÛ³LSŒž¼Y"],
          ["@@nvºB–ëui©`¾"],
          ["@@zdšÛ›Jw®"],
          ["@@†°…¯"],
          ["@@a yAª¸ËJIx،@€ĀHAmßV¡o•fu•o"],
          ["@@šs‰ŗÃÔėAƁ›ZšÄ ~°ČP‚‹äh"],
          ["@@‹¶Ý’Ì‚vmĞh­ı‡Q"],
          ["@@HœŠdSjĒ¢D}war…“u«ZqadYM"],
          ["@@elŒ\\LqqU"],
          ["@@~rMo\\"],
          ["@@f„^ƒC"],
          ["@@øPªoj÷ÍÝħXČx”°Q¨ıXNv"],
          ["@@gÇƳˆŽˆ”oˆŠˆ[~tly"],
          ["@@E–ÆC¿‘"],
          ["@@OŽP"],
          [
            "@@w‹†đóg‰™ĝ—[³‹¡VÙæÅöM̳¹pÁaËýý©D©Ü“JŹƕģGą¤{Ùū…ǘO²«BƱéA—Ò‰ĥ‡¡«BhlmtÃPµyU¯uc“d·w_bŝcīímGOŽ|KP’ȏ‡ŹãŝIŕŭŕ@Óoo¿ē‹±ß}Ž…ŭ‚ŸIJWÈCőâUâǙI›ğʼn©I›ijEׅÁ”³Aó›wXJþ±ÌŒÜӔĨ£L]ĈÙƺZǾĆĖMĸĤfŒÎĵl•ŨnȈ‘ĐtF”Š–FĤ–‚êk¶œ^k°f¶gŠŽœ}®Fa˜f`vXŲxl˜„¦–ÔÁ²¬ÐŸ¦pqÊ̲ˆi€XŸØRDÎ}†Ä@ZĠ’s„x®AR~®ETtĄZ†–ƈfÅ Å HâÒÐA†µ\\S¸„^wĖkRzŠalŽŜ|E¨ÈNĀňZTŒ’pBh£\\ŒĎƀuXĖtKL–¶G|Ž»ĺEļĞ~ÜĢÛĊrˆO˜Ùîvd]nˆ¬VœÊĜ°R֟pM††–‚ƂªFbwžEÀˆ˜©Œž\\…¤]ŸI®¥D³|ˎ]CöAŤ¦…æ’´¥¸Lv¼€•¢ĽBaô–F~—š®²GÌҐEY„„œzk¤’°ahlV՞I^‹šCxĈPŽsB‰ƒºV‰¸@¾ªR²ĨN]´_eavSi‡vc•}p}Đ¼ƌkJœÚe thϠ_¸ ºx±ò_xN›Ë‹²‘@ƒă¡ßH©Ùñ}wkNÕ¹ÇO½¿£ĕ]ly_WìIžÇª`ŠuTÅxYĒÖ¼k֞’µ‚MžjJÚwn\\h‘œĒv]îh|’È›Ƅøègž¸Ķß ĉĈWb¹ƀdéƌNTtP[ŠöSvrCZžžaGuœbo´ŖÒÇА~¡zCI…özx¢„Pn‹•‰Èñ @ŒĥÒ¦†]ƞŠV}³ăĔñiiÄÓVépKG½Ä‘ÓávYo–C·sit‹iaÀy„ŧΡÈYDÑům}‰ý|m[węõĉZÅxUO}÷N¹³ĉo_qtă“qwµŁYلǝŕ¹tïÛUïmRCº…ˆĭ|µ›ÕÊK™½R‘ē ó]‘–GªęAx–»HO£|ām‡¡diď×YïYWªʼnOeÚtĐ«zđ¹T…ā‡úE™á²\\‹ķÍ}jYàÙÆſ¿Çdğ·ùTßÇţʄ¡XgWÀLJğ·¿ÃˆOj YÇ÷Qě‹i"
          ]
        ],
        "encodeOffsets": [
          [[117381, 22988]],
          [[116552, 22934]],
          [[116790, 22617]],
          [[116973, 22545]],
          [[116444, 22536]],
          [[116931, 22515]],
          [[116496, 22490]],
          [[116453, 22449]],
          [[113301, 21439]],
          [[118726, 21604]],
          [[118709, 21486]],
          [[113210, 20816]],
          [[115482, 22082]],
          [[113171, 21585]],
          [[113199, 21590]],
          [[115232, 22102]],
          [[115739, 22373]],
          [[115134, 22184]],
          [[113056, 21175]],
          [[119573, 21271]],
          [[119957, 24020]],
          [[115859, 22356]],
          [[116561, 22649]],
          [[116285, 22746]]
        ]
      }
    },
    {
      "type": "Feature",
      "id": "450000",
      "properties": { "id": "450000", "cp": [108.320004, 22.82402], "name": "广西", "childNum": 2 },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@H– TQ§•A"],
          [
            "@@ĨʪƒLƒƊDÎĹĐCǦė¸zÚGn£¾›rªŀÜt¬@֛ڈSx~øOŒ˜ŶÐÂæȠ\\„ÈÜObĖw^oބLf¬°bI lTØB̈F£Ć¹gñĤaY“t¿¤VSñœK¸¤nM†¼‚JE±„½¸šŠño‹ÜCƆæĪ^ŠĚQÖ¦^‡ˆˆf´Q†üÜʝz¯šlzUĺš@쇀p¶n]sxtx¶@„~ÒĂJb©gk‚{°‚~c°`ԙ¬rV\\“la¼¤ôá`¯¹LC†ÆbŒxEræO‚v[H­˜„[~|aB£ÖsºdAĐzNÂðsŽÞƔ…Ĥªbƒ–ab`ho¡³F«èVloޤ™ÔRzpp®SŽĪº¨ÖƒºN…ij„d`’a”¦¤F³ºDÎńĀìŠCžĜº¦Ċ•~nS›|gźvZkCÆj°zVÈÁƔ]LÊFZg…čP­kini«‹qǀcz͔Y®¬Ů»qR×ō©DՄ‘§ƙǃŵTÉĩ±ŸıdÑnYY›IJvNĆÌØÜ Öp–}e³¦m‹©iÓ|¹Ÿħņ›|ª¦QF¢Â¬ʖovg¿em‡^ucà÷gՎuŒíÙćĝ}FϼĹ{µHK•sLSđƃr‹č¤[Ag‘oS‹ŇYMÿ§Ç{Fśbky‰lQxĕƒ]T·¶[B…ÑÏGáşşƇe€…•ăYSs­FQ}­Bƒw‘tYğÃ@~…C̀Q ×W‡j˱rÉ¥oÏ ±«ÓÂ¥•ƒ€k—ŽwWűŒmcih³K›~‰µh¯e]lµ›él•E쉕E“ďs‡’mǖŧē`ãògK_ÛsUʝ“ćğ¶hŒöŒO¤Ǜn³Žc‘`¡y‹¦C‘ez€YŠwa™–‘[ďĵűMę§]X˜Î_‚훘Û]é’ÛUćİÕBƣ±…dƒy¹T^džûÅÑŦ·‡PĻþÙ`K€¦˜…¢ÍeœĥR¿Œ³£[~Ίu¼dl‰t‚†W¸oRM¢ď\\zœ}Æzdvň–{ÎXF¶°Â_„ÒÂÏL©Ö•TmuŸ¼ãl‰›īkiqéfA„·Êµ\\őDc¥ÝF“y›Ôć˜c€űH_hL܋êĺШc}rn`½„Ì@¸¶ªVLŒŠhŒ‹\\•Ţĺk~ŽĠið°|gŒtTĭĸ^x‘vK˜VGréAé‘bUu›MJ‰VÃO¡…qĂXËS‰ģãlýàŸ_ju‡YÛÒB†œG^˜é֊¶§ŽƒEGӁzěƒƯ¤Ek‡N[kdÃ¥ucé¬dnYpAyČ{`]þ¯T’bÜÈk‚¡Ġ•vΈh„ÂƄ¢Jî¶²"
          ]
        ],
        "encodeOffsets": [[[111707, 21520]], [[107619, 25527]]]
      }
    },
    {
      "type": "Feature",
      "id": "460000",
      "properties": { "id": "460000", "cp": [109.83119, 19.031971], "name": "海南", "childNum": 1 },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@š¦Ŝil¢”XƦ‘ƞò–ïè§ŞCêɕrŧůÇąĻõ™·ĉ³œ̅kÇm@ċȧƒŧĥ‰Ľʉ­ƅſ“ȓÒ˦ŝE}ºƑ[ÍĜȋ gÎfǐÏĤ¨êƺ\\Ɔ¸ĠĎvʄȀœÐ¾jNðĀÒRŒšZdž™zÐŘΰH¨Ƣb²_Ġ "
        ],
        "encodeOffsets": [[112750, 20508]]
      }
    },
    {
      "type": "Feature",
      "id": "510000",
      "properties": {
        "id": "510000",
        "cp": [104.065735, 30.659462],
        "name": "四川",
        "childNum": 2
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@LqKr"],
          [
            "@@Š[ĻéV£ž_ţġñpG •réÏ·~ąSfy×͂·ºſƽiÍıƣıĻmHH}siaX@iǰÁÃ×t«ƒ­Tƒ¤J–JJŒyJ•ÈŠ`Ohߦ¡uËhIyCjmÿw…ZG……Ti‹SˆsO‰žB²ŸfNmsPaˆ{M{ŠõE‘^Hj}gYpaeuž¯‘oáwHjÁ½M¡pM“–uå‡mni{fk”\\oƒÎqCw†EZ¼K›ĝŠƒAy{m÷L‡wO×SimRI¯rK™õBS«sFe‡]fµ¢óY_ÆPRcue°Cbo׌bd£ŌIHgtrnyPt¦foaXďx›lBowz‹_{ÊéWiêE„GhܸºuFĈIxf®Ž•Y½ĀǙ]¤EyŸF²ċ’w¸¿@g¢§RGv»–áŸW`ÃĵJwi]tÂ¥wO­½a[׈]`Ãi­üL€¦LabbTÀå’c}Íh™Æhˆ‹®BH۔|Ék­¤S†y£„ia©taį·Ɖ`ō¥Uh“O…ƒĝLk}©Fos‰´›Jm„µlŁu—…ø–nÑJWΪ–YÀïAetTžŅ‚ӍG™Ë«bo‰{ıwodƟ½ƒžOġܑµxàNÖ¾P²§HKv¾–]|•B஌oZ`¡Ø`ÀmºĠ~ÌЧnDž¿¤]wğ@sƒ‰rğu‰~‘Io”[é±¹ ¿žſđӉ@q‹gˆ¹zƱřaí°KtǤV»Ã[ĩǭƑ^ÇÓ@ỗs›Zϕ‹œÅĭ€Ƌ•ěpwDóÖሯneQˌq·•GCœýS]xŸ·ý‹q³•O՜Œ¶Qzßti{ř‰áÍÇWŝŭñzÇW‹pç¿JŒ™‚Xœĩè½cŒF–ÂLiVjx}\\N†ŇĖ¥Ge–“JA¼ÄHfÈu~¸Æ«dE³ÉMA|b˜Ò…˜ćhG¬CM‚õŠ„ƤąAvğV€éŀ‰_V̳ĐwQj´·ZeÈÁ¨X´Æ¡Qu·»Ÿ“˜ÕZ³ġqDo‰y`L¬gdp°şŠp¦ėìÅĮZްIä”h‚‘ˆzŠĵœf²å ›ĚрKp‹IN|‹„Ñz]ń……·FU×é»R³™MƒÉ»GM«€ki€™ér™}Ã`¹ăÞmȝnÁîRǀ³ĜoİzŔwǶVÚ£À]ɜ»ĆlƂ²Ġ…þTº·àUȞÏʦ¶†I’«dĽĢdĬ¿–»Ĕ׊h\\c¬†ä²GêëĤł¥ÀǿżÃÆMº}BÕĢyFVvw–ˆxBèĻĒ©Ĉ“tCĢɽŠȣ¦āæ·HĽî“ôNԓ~^¤Ɗœu„œ^s¼{TA¼ø°¢İªDè¾Ň¶ÝJ‘®Z´ğ~Sn|ªWÚ©òzPOȸ‚bð¢|‹øĞŠŒœŒQìÛÐ@Ğ™ǎRS¤Á§d…i“´ezÝúØã]Hq„kIŸþËQǦÃsǤ[E¬ÉŪÍxXƒ·ÖƁİlƞ¹ª¹|XÊwn‘ÆƄmÀêErĒtD®ċæcQƒ”E®³^ĭ¥©l}äQto˜ŖÜqƎkµ–„ªÔĻĴ¡@Ċ°B²Èw^^RsºT£ڿœQP‘JvÄz„^Đ¹Æ¯fLà´GC²‘dt˜­ĀRt¼¤ĦOðğfÔðDŨŁĞƘïžPȆ®âbMüÀXZ ¸£@Ś›»»QÉ­™]d“sÖ×_͖_ÌêŮPrĔĐÕGĂeZÜîĘqBhtO ¤tE[h|Y‹Ô‚ZśÎs´xº±UŒ’ñˆt|O’ĩĠºNbgþŠJy^dÂY Į„]Řz¦gC‚³€R`Šz’¢AjŒ¸CL„¤RÆ»@­Ŏk\\Ç´£YW}z@Z}‰Ã¶“oû¶]´^N‡Ò}èN‚ª–P˜Íy¹`S°´†ATe€VamdUĐwʄvĮÕ\\ƒu‹Æŗ¨Yp¹àZÂm™Wh{á„}WØǍ•Éüw™ga§áCNęÎ[ĀÕĪgÖɪX˜øx¬½Ů¦¦[€—„NΆLۆUÖ´òrÙŠxR^–†J˜k„ijnDX{Uƒ~ET{ļº¦PZc”jF²Ė@Žp˜g€ˆ¨“B{ƒu¨ŦyhoÚD®¯¢˜ WòàFΤ¨GDäz¦kÅ®Pœġq˚¥À]€Ÿ˜eŽâÚ´ªKxī„Pˆ—Ö|æ[xäJÞĥ‚s’NÖ½ž€I†¬nĨY´®Ð—ƐŠ€mD™ŝuäđđEb…e’e_™v¡}ìęNJē}q”É埁T¯µRs¡M@}ůa†a­¯wvƉåZwž\\Z{åû^›"
          ]
        ],
        "encodeOffsets": [[[108815, 30935]], [[110617, 31811]]]
      }
    },
    {
      "type": "Feature",
      "id": "520000",
      "properties": {
        "id": "520000",
        "cp": [106.713478, 26.578343],
        "name": "贵州",
        "childNum": 3
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@†G\\†lY£‘in"],
          ["@@q‚|ˆ‚mc¯tχVSÎ"],
          [
            "@@hÑ£Is‡NgßH†›HªķÃh_¹ƒ¡ĝħń¦uيùŽgS¯JHŸ|sÝÅtÁïyMDč»eÕtA¤{b\\}—ƒG®u\\åPFq‹wÅaD…žK°ºâ_£ùbµ”mÁ‹ÛœĹM[q|hlaªāI}тƒµ@swtwm^oµˆD鼊yV™ky°ÉžûÛR…³‚‡eˆ‡¥]RՋěħ[ƅåÛDpŒ”J„iV™™‰ÂF²I…»mN·£›LbÒYb—WsÀbŽ™pki™TZĄă¶HŒq`……ĥ_JŸ¯ae«ƒKpÝx]aĕÛPƒÇȟ[ÁåŵÏő—÷Pw}‡TœÙ@Õs«ĿÛq©½œm¤ÙH·yǥĘĉBµĨÕnđ]K„©„œá‹ŸG纍§Õßg‡ǗĦTèƤƺ{¶ÉHÎd¾ŚÊ·OÐjXWrãLyzÉAL¾ę¢bĶėy_qMĔąro¼hĊžw¶øV¤w”²Ĉ]ʚKx|`ź¦ÂÈdr„cȁbe¸›`I¼čTF´¼Óýȃr¹ÍJ©k_șl³´_pН`oÒh޶pa‚^ÓĔ}D»^Xyœ`d˜[Kv…JPhèhCrĂĚÂ^Êƌ wˆZL­Ġ£šÁbrzOIl’MM”ĪŐžËr×ÎeŦŽtw|΢mKjSǘňĂStÎŦEtqFT†¾†E쬬ôxÌO¢Ÿ KгŀºäY†„”PVgŎ¦Ŋm޼VZwVlŒ„z¤…ž£Tl®ctĽÚó{G­A‡ŒÇgeš~Αd¿æaSbaÂ¥KKûj®_ć^\\ؾbP®¦x^sxjĶI_Ä X‚⼕Hu¨Qh¡À@Ëô}ޱžGNìĎlT¸ˆ…`V~R°tbÕĊ`¸úÛtπFDu€[ƒMfqGH·¥yA‰ztMFe|R‚_Gk†ChZeÚ°to˜v`x‹b„ŒDnÐ{E}šZ˜è€x—†NEފREn˜[Pv@{~rĆAB§‚EO¿|UZ~ì„Uf¨J²ĂÝÆ€‚sª–B`„s¶œfvö¦ŠÕ~dÔq¨¸º»uù[[§´sb¤¢zþFœ¢Æ…Àhˆ™ÂˆW\\ıŽËI݊o±ĭŠ£þˆÊs}¡R]ŒěƒD‚g´VG¢‚j±®è†ºÃmpU[Á›‘Œëº°r݆bNu¸}Žº¼‡`ni”ºÔXĄ¤¼Ôdaµ€Á_À…†ftQQgœR—‘·Ǔ’v”}Ýלĵ]µœ“Wc¤F²›OĩųãW½¯K‚©…]€{†LóµCIµ±Mß¿hŸ•©āq¬o‚½ž~@i~TUxŪÒ¢@ƒ£ÀEîôruń‚”“‚b[§nWuMÆLl¿]x}ij­€½"
          ]
        ],
        "encodeOffsets": [[[112158, 27383]], [[112105, 27474]], [[112095, 27476]]]
      }
    },
    {
      "type": "Feature",
      "id": "530000",
      "properties": {
        "id": "530000",
        "cp": [101.512251, 24.740609],
        "name": "云南",
        "childNum": 1
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@[„ùx½}ÑRH‘YīĺûsÍn‘iEoã½Ya²ė{c¬ĝg•ĂsA•ØÅwď‚õzFjw}—«Dx¿}UÅ©lŸê™@•HÅ­F䬂oJ´ÓnÅ©uą¡Ã¢pÒŌ“Ø TF²‚xa²ËX€‚cʋlHîAßËŁkŻƑŷÉ©h™W­æßU‡“Ës¡¦}•teèÆ¶StǀÇ}Fd£j‹ĈZĆÆ‹¤T‚č\\Dƒ}O÷š£Uˆ§~ŃG™‚åŃDĝ¸œTsd¶¶Bªš¤u¢ŌĎo~t¾ÍŶÒtD¦Ú„iôö‰€zݯX²ghįh½Û±¯€ÿm·zR¦Ɵ`ªŊÃh¢rOԍ´£Ym¼èêf¯ŪĽn„†cÚbŒw\\zlvWžªâˆ ¦g–mÄ¿Bş£¢ƹřbÄ¥kǫßeeZkÙIKueT»sVesb‘aĕ  ¶®dNœĄÄpªyސ¼—„³BE˜®l‡ŽGœŭCœǶwêżĔÂe„pÍÀQƞpC„–¼ŲÈ­AÎô¶R„ä’Q^Øu¬°š_Èôc´¹ò¨P΢hlϦ´Ħ“Æ´sâDŽŲPnÊD^¯°’Upv†}®BP̪–jǬx–Söwlfòªv€qĸ|`H€­viļ€ndĜ­Ćhň•‚em·FyށqóžSᝑ³X_ĞçêtryvL¤§z„¦c¦¥jnŞk˜ˆlD¤øz½ĜàžĂŧMÅ|áƆàÊcðÂF܎‚áŢ¥\\\\º™İøÒÐJĴ‡„îD¦zK²ǏÎEh~’CD­hMn^ÌöÄ©ČZÀžaü„fÉ­yœpį´ěFűk]Ôě¢qlÅĆÙa¶~Äqššê€ljN¬¼H„ÊšNQ´ê¼VظE††^ŃÒyŒƒM{ŒJLoÒœęæŸe±Ķ›y‰’‡gã“¯JYÆĭĘëo¥Š‰o¯hcK«z_pŠrC´ĢÖY”—¼ v¸¢RŽÅW³Â§fǸYi³xR´ďUˊ`êĿU„û€uĆBƒƣö‰N€DH«Ĉg†——Ñ‚aB{ÊNF´¬c·Åv}eÇÃGB»”If•¦HňĕM…~[iwjUÁKE•Ž‹¾dĪçW›šI‹èÀŒoÈXòyŞŮÈXâÎŚŠj|àsRy‹µÖ›–Pr´þŒ ¸^wþTDŔ–Hr¸‹žRÌmf‡żÕâCôox–ĜƌÆĮŒ›Ð–œY˜tâŦÔ@]ÈǮƒ\\μģUsȯLbîƲŚºyh‡rŒŠ@ĒԝƀŸÀ²º\\êp“’JŠ}Ä vŠqt„Ġ@^xˣ頬mËÏğ}n¹_¿¢×Y_æpˆÅ–A^{½•Lu¨GO±Õ½ßM¶w’ÁĢۂP‚›Ƣ¼pcIJxŠ|ap̬HšÐŒŊSfsðBZ¿©“XÏÒK•k†÷Eû¿‰S…rEFsÕūk”óVǥʼniTL‚¡n{‹uxţÏh™ôŝ¬ğōN“‘NJkyPaq™Âğ¤K®‡YŸxÉƋÁ]āęDqçgOg†ILu—\\_gz—]W¼ž~CÔē]bµogpў_oď`´³Țkl`IªºÎȄqÔþž»E³ĎSJ»œ_f·‚adÇqĂc¥Á_Źw{™L^ɱćx“U£µ÷xgĉp»ĆqNē`rĘzaĵĚ¡K½ÊBzyäKXqiWPÏɸ½řÍcÊG|µƕƣG˛÷Ÿk°_^ý|_zċBZocmø¯hhcæ\\lˆMFlư£Ĝ„ÆyH“„F¨‰µêÕ]—›HA…àӄ^it `þßäkŠĤÎT~Wlÿ¨„ÔPzUC–NVv [jâôDôď[}ž‰z¿–msSh‹¯{jïğl}šĹ[–őŒ‰gK‹©U·µË@¾ƒm_~q¡f¹…ÅË^»‘f³ø}Q•„¡Ö˳gͱ^ǁ…\\ëÃA_—¿bW›Ï[¶ƛ鏝£F{Ä«Zgm@|kHǭƁć¦UĔťƒ×ë}ǝƒeďºȡȘÏíBə£āĘPªij¶“ʼnÿ‡y©n‰ď£G¹¡I›Š±LÉĺÑdĉ܇W¥˜‰}g˜Á†{aqÃ¥aŠıęÏZ—ï`"
        ],
        "encodeOffsets": [[104636, 22969]]
      }
    },
    {
      "type": "Feature",
      "id": "540000",
      "properties": { "id": "540000", "cp": [89.132212, 30.860361], "name": "西藏", "childNum": 1 },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@hžľxŽŖ‰xƒÒVކºÅâAĪÝȆµę¯Ňa±r_w~uSÕň‘qOj]ɄQ…£Z……UDûoY’»©M[‹L¼qãË{V͕çWViŽ]ë©Ä÷àyƛh›ÚU°ŒŒa”d„cQƒ~Mx¥™cc¡ÙaSyF—ցk­ŒuRýq¿Ôµ•QĽ³aG{¿FµëªéĜÿª@¬·–K‰·àariĕĀ«V»Ŷ™Ĵū˜gèLǴŇƶaf‹tΏBŚ£^Šâ†ǐÝ®–šM¦ÁǞÿ¬LhŸŽJ¾óƾƺcxw‹f]Y…´ƒ¦|œQLn°aœdĊ…œ\\¨o’œǀÍŎœ´ĩĀd`tÊQŞŕ|‚¨C^©œĈ¦„¦ÎJĊ{ŽëĎjª²rЉšl`¼Ą[t|¦St辉PΆK¸€d˜Ƅı]s¤—î_v¹ÎVòŦj˜£Əsc—¬_Ğ´|٘¦Avަw`ăaÝaa­¢e¤ı²©ªSªšÈMĄwžÉØŔì@T‘¤—Ę™\\õª@”þo´­xA s”ÂtŎKzó´ÇĊµ¢rž^nĊ­Æ¬×üGž¢‚³ {âĊ]š™G‚~bÀgVjzlhǶf€žOšfdЉªB]pj„•TO–tĊ‚n¤}®¦ƒČ¥d¢¼»ddš”Y¼Žt—¢eȤJ¤}Ǿ¡°§¤AГlc@ĝ”sªćļđAç‡wx•UuzEÖġ~AN¹ÄÅȀݦ¿ģŁéì±H…ãd«g[؉¼ēÀ•cīľġ¬cJ‘µ…ÐʥVȝ¸ßS¹†ý±ğkƁ¼ą^ɛ¤Ûÿ‰b[}¬ōõÃ]ËNm®g@•Bg}ÍF±ǐyL¥íCˆƒIij€Ï÷њį[¹¦[⚍EÛïÁÉdƅß{âNÆāŨߝ¾ě÷yC£‡k­´ÓH@¹†TZ¥¢įƒ·ÌAЧ®—Zc…v½ŸZ­¹|ŕWZqgW“|ieZÅYVӁqdq•bc²R@†c‡¥Rã»Ge†ŸeƃīQ•}J[ғK…¬Ə|o’ėjġĠÑN¡ð¯EBčnwôɍėªƒ²•CλŹġǝʅįĭạ̃ūȹ]ΓͧgÅ¡sgȽóϧµǛ†ęgſ¶ҍć`ĘąŌJޚä¤rÅň¥ÖÁUětęuůÞiĊÄÀ\\Æs¦ÓRb|Â^řÌkÄŷ¶½÷‡f±iMݑ›‰@ĥ°G¬ÃMÂ¥n£Øą‚ğ¯ß”§aëbéüÑOčœk£{\\‘eµª×M‘šÉfm«Ƒ{Å׃Gŏǩãy³©WÑăû‚··‘Q—òı}¯ã‰I•éÕÂZ¨īès¶ZÈsŽæĔTŘvŽgÌsN@îá¾ó@‰˜ÙwU±ÉT廣TđŸWxq¹Zo‘b‹s[׌¯cÄ©v‡Œėŧ³BM|¹k‰ªħ—¥TzNYnݍßpęrñĠĉRS~½ŠěVVе‚õ‡«ŒM££µB•ĉ¥áºae~³AuĐh`Ü³ç@BۘïĿa©|z²Ý¼D”£à貋ŸƒIƒû›I ā€óK¥}rÝ_Á´éMaň¨€~ªSĈ½Ž½KÙóĿeƃÆBŽ·¬ën×W|Uº}LJrƳ˜lε`bÔ`QˆˆÐÓ@s–IŒÍ@ûws¡åQÑßÁ`ŋĴ{Ī“T•ÚÅTSij‚‹Yo|Ç[ǾµMW¢ĭiÕØ¿@˜šMh…pÕ]j†éò¿OƇĆƇp€êĉâlØw–ěsˆǩ‚ĵ¸c…bU¹ř¨WavquSMzeo_^gsÏ·¥Ó@~¯¿RiÄ«B™Š\\”qTGªÇĜçPoŠÿfñòą¦óQīÈáP•œābß{ƒZŗĸIæÅ„hnszÁCËìñšÏ·ąĚÝUm®ó­L·ăU›Èíoù´Êj°ŁŤ_uµ^‘°Œìǖ@tĶĒ¡Æ‡M³Ģ«˜İĨÅ®ğ†RŽāð“ggheÆ¢z‚Ê©Ô\\°ÝĎz~ź¤Pn–MĪÖB£Ÿk™n鄧żćŠ˜ĆK„ǰ¼L¶è‰âz¨u¦¥LDĘz¬ýÎmĘd¾ß”Fz“hg²™Fy¦ĝ¤ċņbΛ@y‚Ąæm°NĮZRÖíŽJ²öLĸÒ¨Y®ƌÐV‰à˜tt_ڀÂyÄ zž]Å¢h€zĎ{†ĢX”ˆc|šÐqŽšfO¢¤ög‚ÌHNŽ„PKŖœŽ˜Uú´xx[xˆvĐCûŠìÖT¬¸^}Ìsòd´_އKgžLĴ…ÀBon|H@–Êx˜—¦BpŰˆŌ¿fµƌA¾zLjRxжF”œkĄźRzŀˆ~¶[”´Hnª–VƞuĒ­È¨ƎcƽÌm¸ÁÈM¦x͊ëÀxdžB’šú^´W†£–d„kɾĬpœw‚˂ØɦļĬIŚœÊ•n›Ŕa¸™~J°î”lɌxĤÊÈðhÌ®‚g˜T´øŽàCˆŽÀ^ªerrƘdž¢İP|Ė ŸWœªĦ^¶´ÂL„aT±üWƜ˜ǀRšŶUńšĖ[QhlLüA†‹Ü\\†qR›Ą©"
        ],
        "encodeOffsets": [[90849, 37210]]
      }
    },
    {
      "type": "Feature",
      "id": "610000",
      "properties": {
        "id": "610000",
        "cp": [108.948024, 34.263161],
        "name": "陕西",
        "childNum": 1
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@˜p¢—ȮµšûG™Ħ}Ħšðǚ¶òƄ€jɂz°{ºØkÈęâ¦jª‚Bg‚\\œċ°s¬Ž’]jžú ‚E”Ȍdž¬s„t‡”RˆÆdĠݎwܔ¸ôW¾ƮłÒ_{’Ìšû¼„jº¹¢GǪÒ¯ĘƒZ`ºŊƒecņąš~BÂgzpâēòYǠȰÌTΨÂWœ|fcŸă§uF—Œ@NŸ¢XLƒŠRMº[ğȣſï|Â¥J™kc`sʼnǷ’Y¹‹W@µ÷K…ãï³ÛIcñ·VȋڍÒķø©—þ¥ƒy‚ÓŸğęmWµÎumZyOŅƟĥÓ~sÑL¤µaŅY¦ocyZ{‰y c]{ŒTa©ƒ`U_Ěē£ωÊƍKù’K¶ȱÝƷ§{û»ÅÁȹÍéuij|¹cÑd‘ŠìUYƒŽO‘uF–ÕÈYvÁCqӃT•Ǣí§·S¹NgŠV¬ë÷Át‡°Dد’C´ʼnƒópÄ£}„ċcE˅FŸŸéGU¥×K…§­¶³B‹Č}C¿åċ`wÄ¡B·¤őcƭ²ő[Å^axwQO…ÿEËߌ•ĤNĔŸwƇˆÄŠńwĪ­Šo[„_KÓª³“ÙnK‰Çƒěœÿ]ď€ă_d©·©Ýŏ°Ù®g]±„Ÿ‡ß˜å›—¬÷m\\›iaǑkěX{¢|ZKlçhLt€Ňîŵ€œè[ۃ@ƉĄEœ‡tƇÏ˜³­ħZ«mJ…›×¾‘MtÝĦ£IwÄå\\Õ{‡˜ƒOwĬ©LÙ³ÙgBƕŀr̛ĢŭOÂ¥lãyC§H꣧EñŸX¡—­°ÙCgpÅ¥z‘ˆb`wI„vA|§”‡—hoĕ@E±“iYdÂ¥OϹS|}F@¾oAO²{tfžÜ—¢Fǂ҈W²°BĤh^Wx{@„¬‚­F¸¡„ķn£P|ŸªĴ@^ĠĈæb–Ôc¶l˜Yi…–^Mi˜cϰÂ[ä€vï¶gv@À“Ĭ·lJ¸sn|¼u~a]’ÆÈtŌºJp’ƒþ£KKf~ЦUbyäIšĺãn‡Ô¿^­žŵMT–hĠܤko¼Ŏìąǜh`[tŒRd²IJ_œXPrɲ‰l‘‚XžiL§àƒ–¹ŽH˜°Ȧqº®QC—bA†„ŌJ¸ĕÚ³ĺ§ `d¨YjžiZvRĺ±öVKkjGȊĐePОZmļKÀ€‚[ŠŽ`ösìh†ïÎoĬdtKÞ{¬èÒÒBŒÔpIJÇĬJŊ¦±J«ˆY§‹@·pH€µàåVKe›pW†ftsAÅqC·¬ko«pHÆuK@oŸHĆۄķhx“e‘n›S³àǍrqƶRbzy€¸ËАl›¼EºpĤ¼Œx¼½~Ğ’”à@†ÚüdK^ˆmÌSj"
        ],
        "encodeOffsets": [[110234, 38774]]
      }
    },
    {
      "type": "Feature",
      "id": "620000",
      "properties": {
        "id": "620000",
        "cp": [103.823557, 36.058039],
        "name": "甘肃",
        "childNum": 2
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@VuUv"],
          [
            "@@ũ‹EĠtt~nkh`Q‰¦ÅÄÜdw˜Ab×ĠąJˆ¤DüègĺqBqœj°lI¡ĨÒ¤úSHbš‡ŠjΑBаaZˆ¢KJŽ’O[|A£žDx}Nì•HUnrk„ kp€¼Y kMJn[aG‚áÚÏ[½rc†}aQxOgsPMnUs‡nc‹Z…ž–sKúvA›t„Þġ’£®ĀYKdnFwš¢JE°”Latf`¼h¬we|€Æ‡šbj}GA€·~WŽ”—`†¢MC¤tL©IJ°qdf”O‚“bÞĬ¹ttu`^ZúE`Œ[@„Æsîz®¡’C„ƳƜG²“R‘¢R’m”fŽwĸg܃‚ą G@pzJM½mŠhVy¸uÈÔO±¨{LfæU¶ßGĂq\\ª¬‡²I‚¥IʼnÈīoı‹ÓÑAçÑ|«LÝcspīðÍg…të_õ‰\\ĉñLYnĝg’ŸRǡÁiHLlõUĹ²uQjYi§Z_c¨Ÿ´ĹĖÙ·ŋI…ƒaBD˜­R¹ȥr—¯G•ºß„K¨jWk’ɱŠOq›Wij\\a­‹Q\\sg_ĆǛōëpȣlğۀgS•ŶN®À]ˆÓäm™ĹãJazÂ¥V}‰Le¤L„ýo‘¹IsŋÅÇ^‘Žbz…³tmEÁ´aйcčecÇN•ĊãÁ\\蝗dNj•]j†—ZµkÓda•ćå]ğij@ ©O{¤ĸm¢ƒE·®ƒ«|@Xwg]A챝‡XǁÑdzªc›wQÚŝñsÕ³ÛV_ýƒ˜¥\\ů¥©¾÷w—Ž©WÕÊĩhÿÖÁRo¸V‰Db¨šhûx–Ê×nj~Zâƒg|šXÁnßYoº§ZÅŘvŒ[„ĭÖʃuďxcVbnUSf…B¯³_Tzº—ΕO©çMÑ~Mˆ³]µ^püµ”ŠÄY~y@X~¤Z³€[Èōl@®Å¼£QKƒ·Di‹¡By‘ÿ‰Q_´D¥hŗyƒ^ŸĭÁZ]cIzý‰ah¹MĪğP‘s{ò‡‹‘²Vw¹t³Ŝˁ[ŽÑ}X\\gsFŸ£sPAgěp×ëfYHāďÖqēŭOÏë“dLü•\\iŒ”t^c®šRʺ¶—¢H°mˆ‘rYŸ£BŸ¹čIoľu¶uI]vÄ£SQ{ƒUŻ”Å}QÂ|̋°ƅ¤ĩŪU ęĄžÌZҞ\\v˜²PĔ»ƢNHƒĂyAmƂwVmž`”]ȏb•”H`‰Ì¢²ILvĜ—H®¤Dlt_„¢JJÄämèÔDëþgºƫ™”aʎÌrêYi~ ÎݤNpÀA¾Ĕ¼b…ð÷’Žˆ‡®‚”üs”zMzÖĖQdȨý†v§Tè|ªH’þa¸|šÐ ƒwKÄ¢x¦ivr^ÿ ¸l öæfƟĴ·PJv}n\\h¹¶v†·À|\\ƁĚN´Ĝ€çèÁz]ġ¤²¨QÒŨTIl‡ªťØ}¼˗ƦvÄùØE‹’«Fï˛Iq”ōŒTvāÜŏ‚íÛߜÛV—j³âwGăÂíNOŠˆŠPìyV³ʼnĖýZso§HіiYw[߆\\X¦¥c]ÔƩÜ·«j‡ÐqvÁ¦m^ċ±R™¦΋ƈťĚgÀ»IïĨʗƮްƝ˜ĻþÍAƉſ±tÍEÕÞāNU͗¡\\ſčåÒʻĘm ƭÌŹöʥ’ëQ¤µ­ÇcƕªoIýˆ‰Iɐ_mkl³ă‰Ɠ¦j—¡Yz•Ňi–}Msßõ–īʋ —}ƒÁVmŸ_[n}eı­Uĥ¼‘ª•I{ΧDӜƻėoj‘qYhĹT©oūĶ£]ďxĩ‹ǑMĝ‰q`B´ƃ˺Ч—ç~™²ņj@Ӵ@đ´ί}Ä¥tPńǾV¬ufӃÉC‹tÓ̻‰…¹£G³€]ƖƾŎĪŪĘ̖¨ʈĢƂlɘ۪üºňUðǜȢƢż̌ȦǼ‚ĤŊɲĖ­Kq´ï¦—ºĒDzņɾªǀÞĈĂD†½ĄĎÌŗĞrôñnŽœN¼â¾ʄľԆ|DŽŽ֦ज़ȗlj̘̭ɺƅêgV̍ʆĠ·ÌĊv|ýĖÕWĊǎÞ´õ¼cÒÒBĢ͢UĜð͒s¨ňƃLĉÕÝ@ɛƯ÷¿Ľ­ĹeȏijëCȚDŲyê×Ŗyò¯ļcÂßY…tÁƤyAã˾J@ǝrý‹‰@¤…rz¸oP¹ɐÚyᐇHŸĀ[Jw…cVeȴϜ»ÈŽĖ}ƒŰŐèȭǢόĀƪÈŶë;Ñ̆ȤМľĮEŔ—ĹŊũ~ËUă{ŸĻƹɁύȩþĽvĽƓÉ@ē„ĽɲßǐƫʾǗĒpäWÐxnsÀ^ƆwW©¦cÅ¡Ji§vúF¶Ž¨c~c¼īŒeXǚ‹\\đ¾JŽwÀďksãA‹fÕ¦L}wa‚o”Z’‹D½†Ml«]eÒÅaɲáo½FõÛ]ĻÒ¡wYR£¢rvÓ®y®LF‹LzĈ„ôe]gx}•|KK}xklL]c¦£fRtív¦†PĤoH{tK"
          ]
        ],
        "encodeOffsets": [[[108619, 36299]], [[108589, 36341]]]
      }
    },
    {
      "type": "Feature",
      "id": "630000",
      "properties": { "id": "630000", "cp": [96.778916, 35.623178], "name": "青海", "childNum": 2 },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@InJm"],
          [
            "@@CƒÆ½OŃĦsΰ~dz¦@@“Ņiš±è}ؘƄ˹A³r_ĞŠǒNΌĐw¤^ŬĵªpĺSZg’rpiƼĘԛ¨C|͖J’©Ħ»®VIJ~f\\m `Un„˜~ʌŸ•ĬàöNt•~ňjy–¢Zi˜Ɣ¥ĄŠk´nl`JʇŠJþ©pdƖ®È£¶ìRʦ‘źõƮËnŸʼėæÑƀĎ[‚˜¢VÎĂMÖÝÎF²sƊƀÎBļýƞ—¯ʘƭðħ¼Jh¿ŦęΌƇš¥²Q]Č¥nuÂÏriˆ¸¬ƪÛ^Ó¦d€¥[Wà…x\\ZŽjҕ¨GtpþYŊĕ´€zUO뇉P‰îMĄÁxH´á˜iÜUà›îÜՁĂÛSuŎ‹r“œJð̬EŒ‘FÁú×uÃÎkr“Ē{V}İ«O_ÌËĬ©ŽÓŧSRѱ§Ģ£^ÂyèçěM³Ƃę{[¸¿u…ºµ[gt£¸OƤĿéYŸõ·kŸq]juwÂ¥Dĩƍ€õÇPéĽG‘ž©ã‡¤G…uȧþRcÕĕNy“yût“ˆ­‡ø‘†ï»a½ē¿BMoᣟÍj}éZËqbʍš“Ƭh¹ìÿÓAçãnIáI`ƒks£CG­ě˜Uy×Cy•…’Ÿ@¶ʡÊBnāzG„ơMē¼±O÷õJËĚăVŸĪũƆ£Œ¯{ËL½Ìzż“„VR|Ä TbuvJvµhĻĖH”Aëáa…­OÇðñęNw‡…œľ·L›mI±íĠĩPÉ×®ÿs—’cB³±JKßĊ«`…ađ»·QAmO’‘Vţéÿ¤¹SQt]]Çx€±¯A@ĉij¢Ó祖•ƒl¶ÅÛr—ŕspãRk~¦ª]Į­´“FR„åd­ČsCqđéFn¿Åƃm’Éx{W©ºƝºįkÕƂƑ¸wWūЩÈFž£\\t鴀RÈýÌJ ƒlGr^×äùyÞ³fj”c†€¨£ÂZ|ǓMĝšÏ@ëÜőR‹›ĝ‰Œ÷¡{aïȷPu°ËXÙ{©TmÄ }Y³’­ÞIňµç½©C¡į÷¯B»|St»›]vƒųƒs»”}MÓ ÿʪƟǭA¡fs˜»PY¼c¡»¦c„ċ­¥£~msĉP•–Siƒ^o©A‰Šec‚™PeǵŽkg‚yUi¿h}aH™šĉ^|ᴟ¡HØûÅ«ĉ®]m€¡qĉ¶³ÈyôōLÁst“BŸ®wn±ă¥HSò뚣˜S’ë@לÊăxÇN©™©T±ª£IJ¡fb®ÞbŽb_Ą¥xu¥B—ž{łĝ³«`d˜Ɛt—¤ťiñžÍUuºí`£˜^tƃIJc—·ÛLO‹½Šsç¥Ts{ă\\_»™kϊ±q©čiìĉ|ÍIƒ¥ć¥›€]ª§D{ŝŖÉR_sÿc³Īō›ƿΑ›§p›[ĉ†›c¯bKm›RÂ¥{³„Z†e^ŽŒwx¹dƽŽôIg §Mĕ ƹĴ¿—ǣÜ̓]‹Ý–]snÃ¥A{‹eŒƭ`ǻŊĿ\\ijŬű”YÂÿ¬jĖqŽßbЏ•L«¸©@ěĀ©ê¶ìÀEH|´bRľž–Ó¶rÀQþ‹vl®Õ‚E˜TzÜdb ˜hw¤{LR„ƒd“c‹b¯‹ÙVgœ‚ƜßzÃô쮍^jUèXΖ|UäÌ»rKŽ\\λN‘¼pZCü†VY††¤ɃRi^rPҒTÖ}|br°qňb̰ªiƶGQ¾²„x¦PœmlŜ‘[Ĥ¡ΞsĦŸÔÏâ\\ªÚŒU\\f…¢N²§x|¤§„xĔsZPòʛ²SÐqF`ª„VƒÞŜĶƨVZŒÌL`ˆ¢dŐIqr\\oäõ–F礻Ŷ×h¹]Clـ\\¦ďÌį¬řtTӺƙgQÇÓHţĒ”´ÃbEÄlbʔC”|CˆŮˆk„Ʈ[ʼ¬ňœ´KŮÈΰÌζƶlð”ļA†TUvdTŠG†º̼ŠÔ€ŒsÊDԄveOg"
          ]
        ],
        "encodeOffsets": [[[105308, 37219]], [[95370, 40081]]]
      }
    },
    {
      "type": "Feature",
      "id": "640000",
      "properties": { "id": "640000", "cp": [106.278179, 37.26637], "name": "宁夏", "childNum": 2 },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            "@@KëÀęĞ«OęȿȕŸı]ʼn¡åįÕÔ«Ǵõƪ™ĚQÐZhv K°›öqÀѐS[ÃÖHƖčË‡nL]ûc…Ùß@‚“ĝ‘¾}w»»‹oÄ£F¹œ»kÌÏ·{zPĤB­¢íyÅt@ƒ@áš]Yv_ssģ¼i߁”ĻL¾ġsKD£¡N_…“˜X¸}B~Haiˆ™Åf{«x»ge_bs“KF¯¡Ix™mELcÿZ¤­Ģ‘ƒÝœsuBLù•t†ŒYdˆmVtNmtOPhRw~bd…¾qÐ\\âÙH\\bImlNZŸ»loƒŸqlVm–Gā§~QCw¤™{A\\‘PKŸNY‡¯bF‡kC¥’sk‹Šs_Ã\\ă«¢ħkJi¯r›rAhĹûç£CU‡ĕĊ_ԗBixÅُĄnªÑaM~ħpOuÂ¥sîeQ¥¤^dkKwlL~{L~–hw^‚ófćƒKyEŒ­K­zuÔ¡qQ¤xZÑ¢^ļöܾEpž±âbÊÑÆ^fk¬…NC¾‘Œ“YpxbK~¥Že֎ŒäBlt¿Đx½I[ĒǙŒWž‹f»Ĭ}d§dµùEuj¨‚IÆ¢¥dXªƅx¿]mtÏwßR͌X¢͎vÆzƂZò®ǢÌʆCrâºMÞzžÆMҔÊÓŊZľ–r°Î®Ȉmª²ĈUªĚøºˆĮ¦ÌĘk„^FłĬhĚiĀ˾iİbjÕ"
          ],
          ["@@mfwěwMrŢªv@G‰"]
        ],
        "encodeOffsets": [[[109366, 40242]], [[108600, 36303]]]
      }
    },
    {
      "type": "Feature",
      "id": "650000",
      "properties": { "id": "650000", "cp": [85.617733, 40.792818], "name": "新疆", "childNum": 1 },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@QØĔ²X¨”~ǘBºjʐߨvK”ƔX¨vĊOžÃƒ·¢i@~c—‡ĝe_«”Eš“}QxgɪëÏÃ@sÅyXoŖ{ô«ŸuX…ê•Îf`œC‚¹ÂÿÐGĮÕĞXŪōŸMźÈƺQèĽôe|¿ƸJR¤ĘEjcUóº¯Ĩ_ŘÁMª÷Ð¥Oéȇ¿ÖğǤǷÂF҇zÉx[]­Ĥĝ‰œ¦EP}ûƥé¿İƷTėƫœŕƅ™ƱB»Đ±’ēO…¦E–•}‘`cȺrĦáŖuҞª«IJ‡πdƺÏØZÆ´wʄ¤ĖGЙǂZ̓èH¶}ÚZצʥĪï|ÇĦMŔ»İĝLj‹ì¥Βœba­¯¥ǕǚkĆŵĦɑĺƯxūД̵nơʃĽá½M»›òmqóŘĝč˾ăC…ćāƿÝɽ©DZŅ¹đ¥˜³ðLrÁ®ɱĕģʼnǻ̋ȥơŻǛȡVï¹Ň۩ûkɗġƁ§ʇė̕ĩũƽō^ƕŠUv£ƁQï“Ƶkŏ½ΉÃŭdzLқʻ«ƭ\\lƒ‡ŭD‡“{ʓDkaFÃÄa“³ŤđÔGRÈƚhSӹŚsİ«ĐË[¥ÚDkº^Øg¼ŵ¸£EÍö•€ůʼnT¡c_‡ËKY‹ƧUśĵ„݃U_©rETÏʜ±OñtYw獃{£¨uM³x½şL©Ùá[ÓÐĥ Νtģ¢\\‚ś’nkO›w¥±ƒT»ƷFɯàĩÞáB¹Æ…ÑUw„੍žĽw[“mG½Èå~‡Æ÷QyŠěCFmÄ­Zī—ŵVÁ™ƿQƛ—ûXS²‰b½KϽĉS›©ŷXĕŸ{ŽĕK·¥Ɨcqq©f¿]‡ßDõU³h—­gËÇïģÉɋw“k¯í}I·šœbmœÉ–ř›īJɥĻˁ×xo›ɹī‡l•c…¤³Xù]‘™DžA¿w͉ì¥wÇN·ÂËnƾƍdǧđ®Ɲv•Um©³G\\“}µĿ‡QyŹl㓛µEw‰LJQ½yƋBe¶ŋÀů‡ož¥A—˜Éw@•{Gpm¿Aij†ŽKLhˆ³`ñcËtW‚±»ÕS‰ëüÿďD‡u\\wwwù³—V›LŕƒOMËGh£õP¡™er™Ïd{“‡ġWÁ…č|yÅ¡g^ğyÁzÙs`—s|ÉåªÇ}m¢Ń¨`x¥’ù^•}ƒÌ¥H«‰Yªƅ”Aйn~Ꝛf¤áÀz„gŠÇDIԝ´AňĀ҄¶ûEYospõD[{ù°]u›Jq•U•|SoċxÅ£[õÔĥkŋÞŭZ輗YËüċrw €ÞkrťË¿XGÉbřaDü·Ē÷Aê[Ää€I®BÕИÞ_¢āĠpŠÛÄȉĖġDKwbm‡ÄNô‡ŠfœƫVÉvi†dz—H‘‹QµâFšù­Âœ³¦{YGžƒd¢ĚÜO „€{Ö¦ÞÍÀPŒ^b–ƾŠlŽ[„vt×ĈÍE˨¡Đ~´î¸ùÎh€uè`¸ŸHÕŔVºwĠââWò‡@{œÙNÝ´ə²ȕn{¿¥{l—÷eé^e’ďˆXj©î\\ªÑò˜Üìc\\üqˆÕ[Č¡xoÂċªbØ­Œø|€¶ȴZdÆÂšońéŒGš\\”¼C°ÌƁn´nxšÊOĨ’ہƴĸ¢¸òTxÊǪMīИÖŲÃɎOvˆʦƢ~FއRěò—¿ġ~åŊœú‰Nšžš¸qŽ’Ę[Ĕ¶ÂćnÒPĒÜvúĀÊbÖ{Äî¸~Ŕünp¤ÂH¾œĄYÒ©ÊfºmԈĘcDoĬMŬ’˜S¤„s²‚”ʘچžȂVŦ –ŽèW°ªB|IJXŔþÈJĦÆæFĚêŠYĂªĂ]øªŖNÞüA€’fɨJ€˜¯ÎrDDšĤ€`€mz\\„§~D¬{vJÂ˜«lµĂb–¤p€ŌŰNĄ¨ĊXW|ų ¿¾ɄĦƐMT”‡òP˜÷fØĶK¢ȝ˔Sô¹òEð­”`Ɩ½ǒÂň×äı–§ĤƝ§C~¡‚hlå‚ǺŦŞkâ’~}ŽFøàIJaĞ‚fƠ¥Ž„Ŕdž˜®U¸ˆźXœv¢aƆúŪtŠųƠjd•ƺŠƺÅìnrh\\ĺ¯äɝĦ]èpĄ¦´LƞĬŠ´ƤǬ˼Ēɸ¤rºǼ²¨zÌPðŀbþ¹ļD¢¹œ\\ĜÑŚŸ¶ZƄ³àjĨoâŠȴLʉȮŒĐ­ĚăŽÀêZǚŐ¤qȂ\\L¢ŌİfÆs|zºeªÙæ§΢{Ā´ƐÚ¬¨Ĵà²łhʺKÞºÖTŠiƢ¾ªì°`öøu®Ê¾ãØ"
        ],
        "encodeOffsets": [[88824, 50096]]
      }
    },
    {
      "type": "Feature",
      "id": "110000",
      "properties": {
        "id": "110000",
        "cp": [116.405285, 39.904989],
        "name": "北京",
        "childNum": 1
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@ĽOÁ›ûtÅ·miÍt_H»Ĩ±d`й­{bw…Yr“³S]§§o¹€qGtm_Sŧ€“oa›‹FLg‘QN_•dV€@Zom_ć\\ߚc±x¯oœRcfe…£’o§ËgToÛJíĔóu…|wP¤™XnO¢ÉˆŦ¯rNÄā¤zâŖÈRpÅ¢ZŠœÚ{GŠrFt¦Òx§ø¹RóäV¤XdˆżâºWbwڍUd®bêņ¾‘jnŎGŃŶŠnzÚSeîĜZczî¾i]͜™QaúÍÔiþĩȨWĢ‹ü|Ėu[qb[swP@ÅğP¿{\\‡¥A¨Ï‘Ѩj¯ŠX\\¯œMK‘pA³[H…īu}}"
        ],
        "encodeOffsets": [[120023, 41045]]
      }
    },
    {
      "type": "Feature",
      "id": "120000",
      "properties": {
        "id": "120000",
        "cp": [117.190182, 39.125596],
        "name": "天津",
        "childNum": 1
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          "@@ŬgX§Ü«E…¶Ḟ“¬O_™ïlÁg“z±AXe™µÄĵ{¶]gitgšIj·›¥îakS€‰¨ÐƎk}ĕ{gB—qGf{¿a†U^fI“ư‹³õ{YƒıëNĿžk©ïËZŏ‘R§òoY×Ógc…ĥs¡bġ«@dekąI[nlPqCnp{ˆō³°`{PNdƗqSÄĻNNâyj]äžÒD ĬH°Æ]~¡HO¾ŒX}ÐxŒgp“gWˆrDGˆŒpù‚Š^L‚ˆrzWxˆZ^¨´T\\|~@I‰zƒ–bĤ‹œjeĊªz£®Ĕvě€L†mV¾Ô_ȔNW~zbĬvG†²ZmDM~”~"
        ],
        "encodeOffsets": [[120237, 41215]]
      }
    },
    {
      "type": "Feature",
      "id": "310000",
      "properties": {
        "id": "310000",
        "cp": [121.472644, 31.231706],
        "name": "上海",
        "childNum": 6
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@ɧư¬EpƸÁxc‡"],
          ["@@©„ªƒ"],
          ["@@”MA‹‘š"],
          ["@@Qp݁E§ÉC¾"],
          ["@@bŝՕÕEȣÚƥêImɇǦèÜĠŒÚžÃƌÃ͎ó"],
          ["@@ǜûȬɋŠŭ™×^‰sYŒɍDŋ‘ŽąñCG²«ªč@h–_p¯A{‡oloY€¬j@IJ`•gQڛhr|ǀ^MIJvtbe´R¯Ô¬¨YŽô¤r]ì†Ƭį"]
        ],
        "encodeOffsets": [
          [[124702, 32062]],
          [[124547, 32200]],
          [[124808, 31991]],
          [[124726, 32110]],
          [[124903, 32376]],
          [[124438, 32149]]
        ]
      }
    },
    {
      "type": "Feature",
      "id": "500000",
      "properties": {
        "id": "500000",
        "cp": [107.304962, 29.533155],
        "name": "重庆",
        "childNum": 2
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            "@@vjG~nGŘŬĶȂƀƾ¹¸ØÎezĆT¸}êЖqHŸðqĖ䒊¥^CƒIj–²p…\\_ æüY|[YxƊæuž°xb®…Űb@~¢NQt°¶‚S栓Ê~rljĔëĚ¢~šuf`‘‚†fa‚ĔJåĊ„nÖ]„jƎćÊ@Š£¾a®£Ű{ŶĕF‹ègLk{Y|¡ĜWƔtƬJÑxq‹±ĢN´‰òK‰™–LÈüD|s`ŋ’ć]ƒÃ‰`đŒMûƱ½~Y°ħ`ƏíW‰½eI‹½{aŸ‘OIrÏ¡ĕŇa†p†µÜƅġ‘œ^ÖÛbÙŽŏml½S‹êqDu[R‹ãË»†ÿw`»y‘¸_ĺę}÷`M¯ċfCVµqʼn÷Z•gg“Œ`d½pDO‡ÎCnœ^uf²ènh¼WtƏxRGg¦…pV„†FI±ŽG^ŒIc´ec‡’G•ĹÞ½sëĬ„h˜xW‚}Kӈe­Xsbk”F¦›L‘ØgTkïƵNï¶}Gy“w\\oñ¡nmĈzjŸ•@™Óc£»Wă¹Ój“_m»ˆ¹·~MvÛaqœ»­‰êœ’\\ÂoVnŽÓØÍ™²«‹bq¿efE „€‹Ĝ^Qž~ Évý‡ş¤²Į‰pEİ}zcĺƒL‹½‡š¿gņ›¡ýE¡ya£³t\\¨\\vú»¼§·Ñr_oÒý¥u‚•_n»_ĥAt©Þűā§IVeëƒY}{VPÀFA¨ąB}q@|Ou—\\Fm‰QF݅Mw˜å}]•€|FmϋCaƒwŒu_p—¯sfÙgY…DHl`{QEfNysBЦzG¸rHe‚„N\\CvEsÐùÜ_·ÖĉsaQ¯€}_U‡†xÃđŠq›NH¬•Äd^ÝŰR¬ã°wećJEž·vÝ·Hgƒ‚éFXjÉê`|yŒpxkAwœWĐpbÂ¥eOsmzwqChóUQlÂ¥F^laf‹anòsr›EvfQdÁUVf—ÎvÜ^efˆtET¬ôA\\ϢsJŽnQTjP؈xøK|nBz‰„œĞ»LY‚…FDxӄvr“[ehľš•vNӢo¾NiÂxGp⬐z›bfZo~hGi’]öF|‰|Nb‡tOMn eA±ŠtPT‡LjpYQ|†SH††YĀxinzDJ€Ìg¢và¥Pg‰_–ÇzII‹€II•„£®S¬„Øs쐣ŒN"
          ],
          ["@@ifjN@s"]
        ],
        "encodeOffsets": [[[109628, 30765]], [[111725, 31320]]]
      }
    },
    {
      "type": "Feature",
      "id": "810000",
      "properties": {
        "id": "810000",
        "cp": [114.173355, 22.320048],
        "name": "香港",
        "childNum": 5
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          ["@@AlBk"],
          ["@@mŽn"],
          ["@@EpFo"],
          ["@@ea¢pl¸Eõ¹‡hj[ƒ]ÔCΖ@lj˜¡uBXŸ…•´‹AI¹…[‹yDUˆ]W`çwZkmc–…M›žpہv›}I‹oJlcaƒfёKްä¬XJmРđhI®æÔtSHn€Eˆ„ÒrÈc"],
          ["@@rMUw‡AS®€e"]
        ],
        "encodeOffsets": [
          [[117111, 23002]],
          [[117072, 22876]],
          [[117045, 22887]],
          [[116975, 23082]],
          [[116882, 22747]]
        ]
      }
    },
    {
      "type": "Feature",
      "id": "820000",
      "properties": { "id": "820000", "cp": [113.54909, 22.198951], "name": "澳门", "childNum": 1 },
      "geometry": {
        "type": "Polygon",
        "coordinates": ["@@kÊd°å§s"],
        "encodeOffsets": [[116279, 22639]]
      }
    }
  ],
  "UTF8Encoding": true
}
src/assets/svgs/403.svg
New file
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" enable-background="new 0 0 800 800"><style>.st26{fill:#fff}</style><g id="图层_11"><linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="401.773" y1="162.104" x2="401.773" y2="717.596"><stop offset="0" stop-color="#F4F2FB"/><stop offset="1" stop-color="#E1EEF5"/></linearGradient><path d="M485.03 203.46c-38.37 30.29-120.74 33.81-181.17-2.22s-172-31.38-202.22 34.87 37.19 131.33 12.78 178.98S8.66 530.13 64.45 611.49s126.6 60.62 169.22 52.45c84.17-16.13 189.79 115.67 308.62 16.13 68.47-57.35 170.44 42.09 210.17-81.36 32.78-101.86-85.67-139.5-49.97-208.03 37.96-72.88 30.67-159.24-10.46-201.06-38.31-38.96-140.75-38.46-207 13.84z" style="fill:url(#SVGID_1_)"/><linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="494.782" y1="599.604" x2="494.782" y2="428.659"><stop offset=".34" stop-color="#B0B9E1"/><stop offset=".866" stop-color="#EAF0F8"/></linearGradient><path d="M406.65 428.66h216.44l-22.53 49.03s59.19 57.87-14.13 121.91c-134.28-44.17-221.74-37.1-219.98-38.87 1.77-1.76 40.2-132.07 40.2-132.07z" style="fill:url(#SVGID_2_)"/><linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="116.855" y1="542.49" x2="116.855" y2="405.316"><stop offset=".227" stop-color="#B7ACE0"/><stop offset=".789" stop-color="#E8E7FA"/></linearGradient><path d="M117.64 405.56s-.22-.57-.52.04c-2.7 5.49-27.15 64.96-29.09 110.86 0 0-4.08 26.37 30.11 26.02 28.54-.29 27.78-24.6 27.68-32.79-.39-33.22-28.18-104.13-28.18-104.13z" style="fill:url(#SVGID_3_)"/><linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="116.857" y1="420.547" x2="116.857" y2="571.681"><stop offset="0" stop-color="#ECF1FB"/><stop offset=".818" stop-color="#AFB0E7"/></linearGradient><path d="M116.86 571.68c-.55 0-1-.45-1-1V421.55c0-.55.45-1 1-1s1 .45 1 1v149.13c0 .55-.45 1-1 1z" style="fill:url(#SVGID_4_)"/><linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="617.984" y1="450.968" x2="617.984" y2="362.644"><stop offset=".227" stop-color="#CCD4F4"/><stop offset=".789" stop-color="#ECF1FB"/></linearGradient><path d="M618.49 362.8s-.14-.37-.33.03c-1.74 3.53-17.48 41.83-18.73 71.38 0 0-2.63 16.98 19.39 16.76 18.38-.18 17.89-15.84 17.82-21.11-.25-21.4-18.15-67.06-18.15-67.06z" style="fill:url(#SVGID_5_)"/><linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="617.985" y1="372.451" x2="617.985" y2="469.764"><stop offset="0" stop-color="#ECF1FB"/><stop offset="1" stop-color="#A6A8E2"/></linearGradient><path d="M617.99 469.76c-.36 0-.64-.29-.64-.64V373.1c0-.36.29-.64.64-.64s.64.29.64.64v96.02c0 .36-.29.64-.64.64z" style="fill:url(#SVGID_6_)"/><linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="463.902" y1="88.362" x2="429.148" y2="148.558"><stop offset="0" stop-color="#FFDB80"/><stop offset="1" stop-color="#FFBB24"/></linearGradient><circle cx="446.52" cy="118.46" r="34.75" style="fill:url(#SVGID_7_)"/><linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="421.565" y1="118.828" x2="421.565" y2="176.282"><stop offset="0" stop-color="#F9FAFE"/><stop offset="1" stop-color="#E5EDF7"/></linearGradient><path d="M466.3 137.41h-34.57c-2.23-10.61-11.65-18.58-22.93-18.58s-20.69 7.97-22.93 18.58h-9.05c-10.73 0-19.44 8.7-19.44 19.44 0 10.73 8.7 19.44 19.44 19.44h89.47c10.73 0 19.44-8.7 19.44-19.44.01-10.74-8.69-19.44-19.43-19.44z" style="fill:url(#SVGID_8_)"/><g><linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="688.586" y1="540.208" x2="688.586" y2="512.38"><stop offset=".227" stop-color="#AFB0E7"/><stop offset="1" stop-color="#ECF1FB"/></linearGradient><circle cx="688.59" cy="526.29" r="13.91" style="fill:url(#SVGID_9_)"/><linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="688.635" y1="515.894" x2="688.635" y2="560.69"><stop offset="0" stop-color="#DDE1F6"/><stop offset=".818" stop-color="#A6A8E2"/></linearGradient><path d="M688.64 560.69c-.24 0-.43-.19-.43-.43v-43.94c0-.24.19-.43.43-.43s.43.19.43.43v43.94a.44.44 0 01-.43.43z" style="fill:url(#SVGID_10_)"/></g><g><linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="2622.045" y1="266.481" x2="2451.058" y2="562.64" gradientTransform="matrix(-1 0 0 1 2941.346 0)"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M248.82 393.99c0-24.52-.03-49.03.01-73.54.02-14.37 4.24-18.36 17.97-20.53 41.87-6.61 82.03-18.72 117.91-42.29 10.38-6.82 18.3-7.59 29.06-.47 34.85 23.06 73.26 37.11 114.55 42.8 13.12 1.81 16.84 5.88 16.85 19.25.04 45.72-.4 91.44.18 137.15.34 26.77-8.17 49.99-24.02 70.73-31.46 41.17-74.88 63.76-122.21 80.03-2.5.86-5.83.67-8.36-.23-38.47-13.74-74.58-31.84-104.15-61.09-22.97-22.73-37.84-49.56-37.79-83.22.03-22.87.01-45.73 0-68.59z" style="fill:url(#SVGID_11_)"/><linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="2625.25" y1="279.944" x2="2462.749" y2="561.403" gradientTransform="matrix(-1 0 0 1 2941.346 0)"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M247.94 401.44c0-23.21-.03-46.42.01-69.63.02-13.61 4.06-17.38 17.23-19.43 40.15-6.26 78.67-17.72 113.07-40.04 9.95-6.46 17.55-7.18 27.86-.44 33.42 21.83 70.25 35.14 109.84 40.52 12.58 1.71 16.14 5.56 16.15 18.22.03 43.28-.38 86.57.18 129.84.33 25.34-7.83 47.33-23.03 66.96-30.17 38.98-71.81 60.36-117.19 75.77-2.4.81-5.59.64-8.01-.22-36.89-13.01-71.52-30.14-99.87-57.84-22.03-21.52-36.28-46.91-36.23-78.78.02-21.65-.01-43.29-.01-64.93z" style="fill:url(#SVGID_12_)"/><linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="361.421" y1="346.477" x2="449.513" y2="499.057"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M411.59 435.75c23.18-5.61 40.41-26.11 40.41-50.49 0-28.68-23.85-52.01-53.17-52.01s-53.17 23.33-53.17 52.01c0 24.38 17.24 44.88 40.41 50.49v85.2h25.52v-36.38h32.67v-24.96h-32.67v-23.86zm-40.41-50.49c0-14.91 12.41-27.05 27.65-27.05s27.65 12.14 27.65 27.05-12.41 27.05-27.65 27.05-27.65-12.14-27.65-27.05z" style="fill:url(#SVGID_13_)"/><path class="st26" d="M407.67 439.03c21.8-5.39 38.01-25.1 38.01-48.54 0-27.58-22.43-50.01-50.01-50.01s-50.01 22.43-50.01 50.01c0 23.44 16.21 43.15 38.01 48.54v81.92h24v-34.98h30.73v-24h-30.73v-22.94zm-38.01-48.55c0-14.34 11.67-26.01 26.01-26.01s26.01 11.67 26.01 26.01-11.67 26.01-26.01 26.01-26.01-11.67-26.01-26.01z"/><linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="484.836" y1="475.674" x2="565.754" y2="615.828"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><circle cx="525.3" cy="545.75" r="80.9" style="fill:url(#SVGID_14_)"/><linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="482.787" y1="483.323" x2="559.605" y2="616.376"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#C6D5F4"/></linearGradient><circle cx="521.2" cy="549.85" r="76.81" style="fill:url(#SVGID_15_)"/><path class="st26" d="M538.5 547.62l23.01-23.01c4.44-4.44 4.44-11.63 0-16.06-4.44-4.44-11.63-4.44-16.06 0l-23.01 23.01-23.01-23.01c-4.44-4.44-11.63-4.44-16.06 0-4.44 4.44-4.44 11.63 0 16.06l23.01 23.01-23.01 23.01c-4.44 4.44-4.44 11.63 0 16.06 2.22 2.22 5.13 3.33 8.03 3.33 2.91 0 5.81-1.11 8.03-3.33l23.01-23.01 23.01 23.01c2.22 2.22 5.13 3.33 8.03 3.33s5.81-1.11 8.03-3.33c4.44-4.44 4.44-11.63 0-16.06l-23.01-23.01z"/></g><g><linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="232.569" y1="558.709" x2="232.569" y2="484.191"><stop offset="0" stop-color="#C3D5FD"/><stop offset="1" stop-color="#1A90FC"/></linearGradient><path d="M224.88 484.54s-18.08-2.5-23.95 5.81-8.02 29.58-8.02 29.58l13.61-.72-1.15 24.78 25.11 14.72 35.77-19.24-5.44-22.45 11.43-2.98s-3.4-32.58-19.31-27.77c-8.17.87-10.74.73-10.74.73s-2.15 6.85-9.53 6.27c-7.38-.59-7.78-8.73-7.78-8.73z" style="fill:url(#SVGID_16_)"/><linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="233.602" y1="471.483" x2="233.602" y2="495.089"><stop offset="0" stop-color="#F4AE98"/><stop offset="1" stop-color="#FAD1BB"/></linearGradient><path d="M226.69 474.3l-3.76 16.76c-.18.79.23 1.59.98 1.89 1.94.79 5.83 2.13 9.82 2.13 4.15 0 8.06-2.27 9.86-3.48.62-.42.88-1.19.64-1.9l-5.75-17.09a1.643 1.643 0 00-1.86-1.1l-8.61 1.53c-.65.11-1.18.61-1.32 1.26z" style="fill:url(#SVGID_17_)"/><linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="-816.068" y1="920.854" x2="-804.529" y2="839.612" gradientTransform="rotate(-8.082 -2795.015 -6505.71)"><stop offset="0" stop-color="#C3D5FD"/><stop offset="1" stop-color="#1A90FC"/></linearGradient><path d="M204.24 487.44c5.26-1.75 12.4-.58 12.69 11.22s-11.28 30.62-7.13 37.16c4.2 6.63 13.17 16.05 18.89 21.41-1.33 6.3-4.91 11.61-4.91 11.61s-21.05-9.71-30.21-19.44c-9.17-9.73-4.54-32.03-.3-47.9 3.19-11.95 10.97-14.06 10.97-14.06z" style="fill:url(#SVGID_18_)"/><linearGradient id="SVGID_19_" gradientUnits="userSpaceOnUse" x1="-6575.898" y1="102.823" x2="-6564.359" y2="21.581" gradientTransform="scale(-1 1) rotate(-8.082 -118.103 -44396.273)"><stop offset="0" stop-color="#C3D5FD"/><stop offset="1" stop-color="#1A90FC"/></linearGradient><path d="M259.39 487.44c-5.26-1.75-12.4-.58-12.69 11.22s11.28 30.62 7.13 37.16c-4.2 6.63-13.17 16.05-18.89 21.41 1.33 6.3 4.91 11.61 4.91 11.61s21.05-9.71 30.21-19.44c9.17-9.73 4.54-32.03.3-47.9-3.19-11.95-10.97-14.06-10.97-14.06z" style="fill:url(#SVGID_19_)"/><linearGradient id="SVGID_20_" gradientUnits="userSpaceOnUse" x1="232.569" y1="531.798" x2="232.569" y2="579.152"><stop offset="0" stop-color="#275C89"/><stop offset="1" stop-color="#013F7C"/></linearGradient><path d="M206.79 579.15h51.1c2.31 0 4.38-1.75 5.19-4.4l10.3-33.89c1.34-4.4-1.33-9.07-5.19-9.07h-71.23c-3.82 0-6.48 4.6-5.21 8.98l9.84 33.89c.77 2.69 2.86 4.49 5.2 4.49z" style="fill:url(#SVGID_20_)"/><path class="st26" d="M204.75 594.74s-.79-1.74-1.4-1.93c-.61-.19-9.35-.54-12.53-1.36-3.19-.83-12.38-2.14-16.32 1.59-3.43 3.25-4.56 10.84.66 15.2 1.96 1.7 3.89 2.2 11.14 1.86 7.26-.34 17.78-.26 20.09-3.63-.07-5.55-1.64-11.73-1.64-11.73z"/><linearGradient id="SVGID_21_" gradientUnits="userSpaceOnUse" x1="-5720.751" y1="599.589" x2="-5703.986" y2="599.589" gradientTransform="matrix(-1 0 0 1 -5504.059 0)"><stop offset="0" stop-color="#F4B9A4"/><stop offset=".652" stop-color="#FAD1BB"/></linearGradient><path d="M212.86 592.81s-8.44 1.9-11.45 1.62-.49 11.87-.49 11.87 8.05.56 15.18-1.51c2.4-9.3-3.24-11.98-3.24-11.98z" style="fill:url(#SVGID_21_)"/><linearGradient id="SVGID_22_" gradientUnits="userSpaceOnUse" x1="209.839" y1="581.112" x2="296.322" y2="581.112"><stop offset="0" stop-color="#18264B"/><stop offset=".652" stop-color="#2D3C65"/></linearGradient><path d="M209.84 592.37l4.39 13.64s94.25-12.41 80.78-43c-11.27-25.57-85.17 29.36-85.17 29.36z" style="fill:url(#SVGID_22_)"/><linearGradient id="SVGID_23_" gradientUnits="userSpaceOnUse" x1="190.339" y1="591.445" x2="190.339" y2="609.24"><stop offset="0" stop-color="#FFDB80"/><stop offset="1" stop-color="#FFBB24"/></linearGradient><path d="M203.66 593.42s3.45 1.35 3.89 6.17c.44 4.82-.99 8.05-8.33 8.94s-9.21.56-13.81.67-11.29.56-12.27-8.2c-.99-8.75 7.96-10.98 17.24-8.75 2.92.56 13.28 1.17 13.28 1.17z" style="fill:url(#SVGID_23_)"/><g><path class="st26" d="M263.56 594.74s.79-1.74 1.4-1.93c.61-.19 9.35-.54 12.53-1.36 3.19-.83 11.75-2.2 16.08 1.49 4.01 3.42 4.27 11-.29 15.18-1.96 1.7-4.02 2.32-11.28 1.98-7.26-.34-17.78-.26-20.09-3.63.09-5.55 1.65-11.73 1.65-11.73z"/><linearGradient id="SVGID_24_" gradientUnits="userSpaceOnUse" x1="251.623" y1="599.589" x2="268.387" y2="599.589"><stop offset="0" stop-color="#F4B9A4"/><stop offset=".652" stop-color="#FAD1BB"/></linearGradient><path d="M255.45 592.81s8.44 1.9 11.45 1.62.49 11.87.49 11.87-8.05.56-15.18-1.51c-2.4-9.3 3.24-11.98 3.24-11.98z" style="fill:url(#SVGID_24_)"/><linearGradient id="SVGID_25_" gradientUnits="userSpaceOnUse" x1="171.993" y1="581.112" x2="258.476" y2="581.112"><stop offset="0" stop-color="#445677"/><stop offset="1" stop-color="#293861"/></linearGradient><path d="M258.48 592.37L254.09 606s-94.25-12.41-80.78-43c11.26-25.56 85.17 29.37 85.17 29.37z" style="fill:url(#SVGID_25_)"/><linearGradient id="SVGID_26_" gradientUnits="userSpaceOnUse" x1="277.976" y1="591.445" x2="277.976" y2="609.24"><stop offset="0" stop-color="#FFDB80"/><stop offset="1" stop-color="#FFBB24"/></linearGradient><path d="M264.66 593.42s-3.45 1.35-3.89 6.17.99 8.05 8.33 8.94c7.34.89 9.21.56 13.81.67s11.29.56 12.27-8.2c.99-8.75-7.96-10.98-17.24-8.75-2.92.56-13.28 1.17-13.28 1.17z" style="fill:url(#SVGID_26_)"/></g><linearGradient id="SVGID_27_" gradientUnits="userSpaceOnUse" x1="249.053" y1="466.067" x2="218.202" y2="466.067"><stop offset="0" stop-color="#F4B9A4"/><stop offset=".652" stop-color="#FAD1BB"/></linearGradient><path d="M248.39 467.6c.56-.8.91-2.84.46-3.44-.83-.67-1.61-.28-2.21.3.14-4.88-.31-8.94-.41-9.97-.3-2.99-3.35-8.48-13.3-8.48-9.95 0-11.88 7.18-11.88 7.18s-.65 5.08-.46 11.24c-.59-.57-1.37-.93-2.18-.27-.46.6-.1 2.64.46 3.44.56.8.91 2.69 1.02 3.74.1.99-.62 3.65 2 3.31 1.56 6.25 7.89 11.47 11.82 11.47 4.3 0 10.01-5.26 11.63-11.48 2.68.37 1.95-2.31 2.04-3.31.09-1.04.45-2.93 1.01-3.73z" style="fill:url(#SVGID_27_)"/><linearGradient id="SVGID_28_" gradientUnits="userSpaceOnUse" x1="213.957" y1="454.142" x2="249.774" y2="454.142"><stop offset="0" stop-color="#4F5C7C"/><stop offset="1" stop-color="#274168"/></linearGradient><path d="M240.1 443.88s-1.94-6.12-9.39-4.65c-7.44 1.46-7.95 4.98-10.87 5.12-4.99.23-8.97 6.45-2.58 13.03 2.85 2.93.44 4.19 1.79 6.78s1.34 5.12 1.34 5.12 2.38-7.6.81-10.84c-.81-1.67 2.77-2.13 7.24-1.73s11.51-1.08 12.06-4.12c1.32 6.23 2.64 6.88 4.31 7.83 1.68.95 1.78 8.48 1.78 8.48s.3-5.53 1.47-6.78c.96-2.04 2.85-10.07.72-12.02s-.32-8.19-8.68-6.22z" style="fill:url(#SVGID_28_)"/></g></g></svg>
src/assets/svgs/404.svg
New file
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" enable-background="new 0 0 800 800"><style>.st49{fill:#d4e4fe}</style><g id="图层_5"><linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="401.193" y1="159.763" x2="401.193" y2="715.254"><stop offset="0" stop-color="#F4F2FB"/><stop offset="1" stop-color="#E1EEF5"/></linearGradient><path d="M484.45 201.12c-38.37 30.29-120.74 33.81-181.17-2.22s-172-31.38-202.22 34.87 37.19 131.33 12.78 178.98S8.08 527.79 63.87 609.15s126.6 60.62 169.22 52.45c84.17-16.13 189.79 115.67 308.62 16.13 68.47-57.35 170.44 42.09 210.17-81.36 32.78-101.86-85.67-139.5-49.97-208.03 37.96-72.88 30.67-159.24-10.46-201.06-38.31-38.96-140.75-38.46-207 13.84z" style="fill:url(#SVGID_1_)"/><linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="484.537" y1="604.68" x2="484.537" y2="493.367"><stop offset=".34" stop-color="#B0B9E1"/><stop offset=".866" stop-color="#EAF0F8"/></linearGradient><path d="M285.1 583.44c1.77-1.63 77.74-90.07 77.74-90.07h321.13l-99.5 111.31-299.37-21.24z" style="fill:url(#SVGID_2_)"/><linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="616.023" y1="627.266" x2="657.332" y2="555.716"><stop offset="0" stop-color="#B0B9E1"/><stop offset=".866" stop-color="#EAF0F8"/></linearGradient><path d="M604.49 620.61L659.43 556.93 633.22 624.12z" style="fill:url(#SVGID_3_)"/><linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="116.275" y1="540.149" x2="116.275" y2="402.974"><stop offset=".003" stop-color="#9A9ADB"/><stop offset=".789" stop-color="#CECDF1"/></linearGradient><path d="M117.06 403.22s-.22-.57-.52.04c-2.7 5.49-27.15 64.96-29.09 110.86 0 0-4.08 26.37 30.11 26.02 28.54-.29 27.78-24.6 27.68-32.79-.39-33.22-28.18-104.13-28.18-104.13z" style="fill:url(#SVGID_4_)"/><linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="116.277" y1="418.206" x2="116.277" y2="569.34"><stop offset="0" stop-color="#ECF1FB"/><stop offset=".818" stop-color="#AFB0E7"/></linearGradient><path d="M116.28 569.34c-.55 0-1-.45-1-1V419.21c0-.55.45-1 1-1s1 .45 1 1v149.13c0 .55-.45 1-1 1z" style="fill:url(#SVGID_5_)"/><linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="617.404" y1="448.627" x2="617.404" y2="360.303"><stop offset=".227" stop-color="#CCD4F4"/><stop offset=".789" stop-color="#ECF1FB"/></linearGradient><path d="M617.91 360.46s-.14-.37-.33.03c-1.74 3.53-17.48 41.83-18.73 71.38 0 0-2.63 16.98 19.39 16.76 18.38-.18 17.89-15.84 17.82-21.11-.25-21.4-18.15-67.06-18.15-67.06z" style="fill:url(#SVGID_6_)"/><linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="617.405" y1="370.11" x2="617.405" y2="467.422"><stop offset="0" stop-color="#ECF1FB"/><stop offset="1" stop-color="#A6A8E2"/></linearGradient><path d="M617.41 467.42c-.36 0-.64-.29-.64-.64v-96.02c0-.36.29-.64.64-.64.36 0 .64.29.64.64v96.02c0 .35-.29.64-.64.64z" style="fill:url(#SVGID_7_)"/><linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="463.322" y1="86.02" x2="428.568" y2="146.217"><stop offset="0" stop-color="#FFDB80"/><stop offset="1" stop-color="#FFBB24"/></linearGradient><circle cx="445.95" cy="116.12" r="34.75" style="fill:url(#SVGID_8_)"/><linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="420.985" y1="116.487" x2="420.985" y2="173.941"><stop offset="0" stop-color="#F9FAFE"/><stop offset="1" stop-color="#E5EDF7"/></linearGradient><path d="M465.72 135.07h-34.57c-2.23-10.61-11.65-18.58-22.93-18.58s-20.69 7.97-22.93 18.58h-9.05c-10.73 0-19.44 8.7-19.44 19.44 0 10.73 8.7 19.44 19.44 19.44h89.47c10.73 0 19.44-8.7 19.44-19.44.01-10.74-8.69-19.44-19.43-19.44z" style="fill:url(#SVGID_9_)"/><g><linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="688.006" y1="537.867" x2="688.006" y2="510.039"><stop offset=".227" stop-color="#AFB0E7"/><stop offset="1" stop-color="#ECF1FB"/></linearGradient><circle cx="688.01" cy="523.95" r="13.91" style="fill:url(#SVGID_10_)"/><linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="688.056" y1="513.553" x2="688.056" y2="558.349"><stop offset="0" stop-color="#DDE1F6"/><stop offset=".818" stop-color="#A6A8E2"/></linearGradient><path d="M688.06 558.35c-.24 0-.43-.19-.43-.43v-43.94c0-.24.19-.43.43-.43s.43.19.43.43v43.94a.44.44 0 01-.43.43z" style="fill:url(#SVGID_11_)"/></g><g><linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="2879.853" y1="308.382" x2="2737.462" y2="450.774" gradientTransform="matrix(-1 0 0 1 3207.18 0)"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M270.73 392.79l91.4-73.3c7.43 11.92 20.65 19.87 35.7 19.87 16.43 0 30.69-9.48 37.6-23.26l92.11 76.85 10.83-12.98-98.5-82.19c0-.16.01-.31.01-.47 0-23.18-18.86-42.04-42.05-42.04-23.18 0-42.04 18.86-42.04 42.04 0 1.8.13 3.58.35 5.32l-95.98 76.97 10.57 13.19zm101.96-95.48c0-13.86 11.28-25.14 25.14-25.14s25.14 11.28 25.14 25.14-11.28 25.14-25.14 25.14-25.14-11.27-25.14-25.14z" style="fill:url(#SVGID_12_)"/><linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="2814.247" y1="259.815" x2="2814.247" y2="392.836" gradientTransform="matrix(-1 0 0 1 3207.18 0)"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#C6D5F4"/></linearGradient><path d="M268.75 392.68l88.31-70.82c7.18 11.51 19.95 19.2 34.49 19.2 15.88 0 29.65-9.16 36.33-22.47l88.99 74.25 10.46-12.54-95.17-79.41c0-.15.01-.3.01-.46 0-22.4-18.22-40.62-40.62-40.62s-40.62 18.22-40.62 40.62c0 1.74.12 3.46.34 5.14l-92.73 74.37 10.21 12.74zm98.51-92.24c0-13.4 10.9-24.29 24.29-24.29 13.4 0 24.29 10.9 24.29 24.29 0 13.4-10.9 24.29-24.29 24.29-13.4 0-24.29-10.9-24.29-24.29z" style="fill:url(#SVGID_13_)"/><linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="2966.463" y1="329.794" x2="2654.707" y2="641.55" gradientTransform="matrix(-1 0 0 1 3203.43 0)"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M230.6 619.91h326.35c17.89 0 32.39-14.5 32.39-32.39V388.31c0-21.39-17.34-38.72-38.72-38.72H230.6c-17.89 0-32.39 14.5-32.39 32.39v205.54c-.01 17.88 14.5 32.39 32.39 32.39z" style="fill:url(#SVGID_14_)"/><linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="2716.773" y1="319.563" x2="2914.293" y2="661.678" gradientTransform="matrix(-1 0 0 1 3203.43 0)"><stop offset="0" stop-color="#EBF2FA"/><stop offset=".525" stop-color="#FDFEFF"/></linearGradient><path d="M223.6 619.91h328.59c14.03 0 25.4-11.37 25.4-25.4V386.73c0-14.03-11.37-25.4-25.4-25.4H223.6c-14.03 0-25.4 11.37-25.4 25.4v207.78c0 14.03 11.38 25.4 25.4 25.4z" style="fill:url(#SVGID_15_)"/><linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="2815.495" y1="361.334" x2="2815.495" y2="425.526" gradientTransform="matrix(-1 0 0 1 3203.43 0)"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M198.24 425.53h379.39v-38.79c0-14.03-11.37-25.4-25.4-25.4H223.64c-14.03 0-25.4 11.37-25.4 25.4v38.79z" style="fill:url(#SVGID_16_)"/><linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="276.445" y1="488.742" x2="350.685" y2="531.604"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M328.82 457.46H307.7c-1.27 0-2.46.59-3.24 1.59L261.91 514c-.56.72-.86 1.6-.86 2.51v23.15c0 2.26 1.83 4.09 4.09 4.09h41.34c2.26 0 4.09 1.83 4.09 4.09v13.46c0 2.26 1.83 4.09 4.09 4.09h14.14c2.26 0 4.09-1.83 4.09-4.09v-13.46c0-2.26 1.83-4.09 4.09-4.09s4.09-1.83 4.09-4.09V525.5c0-2.26-1.83-4.09-4.09-4.09s-4.09-1.83-4.09-4.09v-55.77a4.059 4.059 0 00-4.07-4.09zm-39.3 57.35l13.74-17.74c2.39-3.08 7.33-1.4 7.33 2.51v17.74c0 2.26-1.83 4.09-4.09 4.09h-13.74c-3.41 0-5.33-3.91-3.24-6.6z" style="fill:url(#SVGID_17_)"/><linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="455.095" y1="488.742" x2="529.335" y2="531.604"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M511.56 517.32v-55.77c0-2.26-1.83-4.09-4.09-4.09h-21.12c-1.27 0-2.46.59-3.24 1.59L440.56 514c-.56.72-.86 1.6-.86 2.51v23.15c0 2.26 1.83 4.09 4.09 4.09h41.34c2.26 0 4.09 1.83 4.09 4.09v13.46c0 2.26 1.83 4.09 4.09 4.09h14.14c2.26 0 4.09-1.83 4.09-4.09v-13.46c0-2.26 1.83-4.09 4.09-4.09s4.09-1.83 4.09-4.09V525.5c0-2.26-1.83-4.09-4.09-4.09-2.24 0-4.07-1.83-4.07-4.09zm-43.39-2.51l13.74-17.74c2.39-3.08 7.33-1.4 7.33 2.51v17.74c0 2.26-1.83 4.09-4.09 4.09H471.4c-3.4 0-5.32-3.91-3.23-6.6z" style="fill:url(#SVGID_18_)"/><linearGradient id="SVGID_19_" gradientUnits="userSpaceOnUse" x1="339.488" y1="482.174" x2="441.31" y2="540.961"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M356.4 566.16h68c2.26 0 4.09-1.83 4.09-4.09v-101c0-2.26-1.83-4.09-4.09-4.09h-68c-2.26 0-4.09 1.83-4.09 4.09v101c0 2.26 1.83 4.09 4.09 4.09zm49.76-82.76v56.34c0 2.26-1.83 4.09-4.09 4.09h-23.34c-2.26 0-4.09-1.83-4.09-4.09V483.4c0-2.26 1.83-4.09 4.09-4.09h23.34c2.26 0 4.09 1.83 4.09 4.09z" style="fill:url(#SVGID_19_)"/></g><g><linearGradient id="SVGID_20_" gradientUnits="userSpaceOnUse" x1="871.514" y1="4485.232" x2="872.065" y2="4498.77" gradientTransform="rotate(2.333 95904.663 -3670.234)"><stop offset="0" stop-color="#FFDB80"/><stop offset="1" stop-color="#FFBB24"/></linearGradient><path d="M605.95 610.6s3.25 4.88 10.55 1.06c3.91 2.72 8.92 4.97 12.39 5.88 3.47.91 3.68 5.4 3.12 6.61-4.66-.47-18.14.64-27.3-2.94.72-7.53 1.24-10.61 1.24-10.61z" style="fill:url(#SVGID_20_)"/><path class="st49" d="M604.06 623.84l.43-3.23s10.54 2.63 28.38 1.03c.17 1.66.35 2.48.35 2.48s-13.56 2.02-29.16-.28z"/><linearGradient id="SVGID_21_" gradientUnits="userSpaceOnUse" x1="-1427.263" y1="-235.579" x2="-1409.896" y2="-215.318" gradientTransform="rotate(40.6 -1575.457 2818.52)"><stop offset="0" stop-color="#FFDB80"/><stop offset="1" stop-color="#FFBB24"/></linearGradient><path d="M520.47 596.12s-.05 5.81 7.27 7.94c1.95 5-3.73 11.79 5.37 12.42 3.34.23 1.75 5.12.73 5.63-10.95 4.01-14.63-10.12-19.62-18.98 4.32-5.09 6.25-7.01 6.25-7.01z" style="fill:url(#SVGID_21_)"/><linearGradient id="SVGID_22_" gradientUnits="userSpaceOnUse" x1="-3772.01" y1="604.486" x2="-3772.01" y2="502.198" gradientTransform="matrix(-1 0 0 1 -3222.68 0)"><stop offset="0" stop-color="#445677"/><stop offset="1" stop-color="#293861"/></linearGradient><path d="M569.3 502.2s-14.44-.26-17.67 18.85c-3.23 19.11 1.57 23.66-5.38 37.29-3.62 7.1-27.15 41.12-27.15 41.12l6.83 5.03s37.94-34.72 43.52-48.71 9.83-28.83 10.13-41.46c.28-12.62-10.28-12.12-10.28-12.12z" style="fill:url(#SVGID_22_)"/><linearGradient id="SVGID_23_" gradientUnits="userSpaceOnUse" x1="-3839.642" y1="559.801" x2="-3786.238" y2="559.801" gradientTransform="matrix(-1 0 0 1 -3222.68 0)"><stop offset="0" stop-color="#445677"/><stop offset="1" stop-color="#293861"/></linearGradient><path d="M572.72 506.19s14.87 3.53 15.75 3.98c.44.23 2.89 7.07 5.24 13.95 5.04 6.87 23.02 32.28 23.21 45.51.29 20.13-.96 43.67-.96 43.67l-9.24.11s-3.5-38.9-5.85-42.31c-.42-.61-1.29-1.95-2.42-3.74-5.14-6.22-16.5-16.65-28.16-27.07-16.45-14.66 2.43-34.1 2.43-34.1z" style="fill:url(#SVGID_23_)"/><linearGradient id="SVGID_24_" gradientUnits="userSpaceOnUse" x1="5317.908" y1="132.095" x2="5317.908" y2="56.817" gradientTransform="rotate(26.086 2112.504 -9908.036)"><stop offset="0" stop-color="#C3D5FD"/><stop offset="1" stop-color="#1A90FC"/></linearGradient><path d="M603.14 448.91s-10.69-8.37-16.99-4.36c-6.3 4-14.27 18.91-14.27 18.91l8.85 4.38-23.8 39.67 40.69 21.83 14.6-42.28 11.79.69s7.96-25.24-3.62-27.43c-5.45-2.3-7.04-3.34-7.04-3.34s-3.49 4.27-7.99 1.18-2.22-9.25-2.22-9.25z" style="fill:url(#SVGID_24_)"/><linearGradient id="SVGID_25_" gradientUnits="userSpaceOnUse" x1="5161.945" y1="1134.369" x2="5171.26" y2="1068.78" gradientTransform="rotate(18.006 4848.87 -13687.47)"><stop offset="0" stop-color="#C3D5FD"/><stop offset="1" stop-color="#1A90FC"/></linearGradient><path d="M589.15 443.6c3.88.61 8.04 4.05 4.56 12.85-3.48 8.8-16.66 18.5-16.06 24.82.6 6.4 3.37 16.58 5.33 22.6-2.8 4.17-6.72 6.78-6.72 6.78s-10.33-14.75-13.12-25.23 7.07-25.25 14.69-35.41c5.73-7.67 11.32-6.41 11.32-6.41z" style="fill:url(#SVGID_25_)"/><linearGradient id="SVGID_26_" gradientUnits="userSpaceOnUse" x1="-8924.659" y1="-865.525" x2="-8915.544" y2="-929.706" gradientTransform="scale(-1 1) rotate(-34.172 -2504.53 -13720.806)"><stop offset="0" stop-color="#C3D5FD"/><stop offset="1" stop-color="#1A90FC"/></linearGradient><path d="M624.12 463.5c-2.79-3.19-7.68-4.9-11.53 3.69s-2.35 26.64-7.02 29.97c-4.72 3.37-13.34 7.07-18.62 8.96-1.12 5.12-.49 10.33-.49 10.33s16.36.44 25.19-3.42c8.83-3.86 12.82-21.97 15.06-35.2 1.69-9.97-2.59-14.33-2.59-14.33z" style="fill:url(#SVGID_26_)"/><linearGradient id="SVGID_27_" gradientUnits="userSpaceOnUse" x1="-3813.896" y1="480.898" x2="-3841.811" y2="423.883" gradientTransform="matrix(-1 0 0 1 -3222.68 0)"><stop offset="0" stop-color="#4F5C7C"/><stop offset="1" stop-color="#274168"/></linearGradient><path d="M590.9 439.68c.43-4.69 4.5-7.9 9.3-7.17.4-1.31 4.44-2.98 5.38-4.6 3.5-6.03 9.26-7 14-3.56 9.79 2.79 8.01 12.2 4.75 21.55 2.8 5.61 1.52 12.41-.06 15.18 4.75 5.07 2.09 11.58-1.39 16.52-.4.56-.82 1.06-1.25 1.52-.21 5.85-8.34 7.86-11.32 4.89-3.17-3.16-3.57-4.49-9.32-1.76-5.75 2.73-11.24-1.54-11.3-7.34-.06-5.8-4.28-4.1-6.12-5.63-3.33-2.77-1.15-5.93-1.15-5.93s-4.85-.26-6.01-7.38c-1.33-16.99 11.95-17.08 14.49-16.29z" style="fill:url(#SVGID_27_)"/><path class="st49" d="M515.38 601.24s4.92 12.03 5.91 13.61 5.9 9.27 14.26 5.05c-.04 1.49-.11 2.43-.11 2.43s-9.42 6.26-15.33-4.62c-5.91-10.88-6.75-14.63-6.75-14.63l2.02-1.84z"/></g></g></svg>
src/assets/svgs/500.svg
New file
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" enable-background="new 0 0 800 800"><style>.st26{fill:#fff}</style><g id="图层_16"><linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="402.832" y1="159.843" x2="402.832" y2="715.335"><stop offset="0" stop-color="#F4F2FB"/><stop offset="1" stop-color="#E1EEF5"/></linearGradient><path d="M486.09 201.2c-38.37 30.29-120.74 33.81-181.17-2.22s-172-31.38-202.22 34.87 37.19 131.33 12.78 178.98S9.72 527.87 65.5 609.23s126.6 60.62 169.22 52.45c84.17-16.13 189.79 115.67 308.62 16.13 68.47-57.35 170.44 42.09 210.17-81.36 32.78-101.86-85.67-139.5-49.97-208.03 37.96-72.88 30.67-159.24-10.46-201.06-38.3-38.96-140.75-38.46-206.99 13.84z" style="fill:url(#SVGID_1_)"/><linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="117.913" y1="540.229" x2="117.913" y2="403.055"><stop offset=".227" stop-color="#B7ACE0"/><stop offset=".789" stop-color="#E8E7FA"/></linearGradient><path d="M118.7 403.3s-.22-.57-.52.04c-2.7 5.49-27.15 64.96-29.09 110.86 0 0-4.08 26.37 30.11 26.02 28.54-.29 27.78-24.6 27.68-32.79-.39-33.22-28.18-104.13-28.18-104.13z" style="fill:url(#SVGID_2_)"/><linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="117.915" y1="418.287" x2="117.915" y2="569.42"><stop offset="0" stop-color="#ECF1FB"/><stop offset=".818" stop-color="#AFB0E7"/></linearGradient><path d="M117.92 569.42c-.55 0-1-.45-1-1V419.29c0-.55.45-1 1-1s1 .45 1 1v149.13c0 .55-.45 1-1 1z" style="fill:url(#SVGID_3_)"/><linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="619.042" y1="448.707" x2="619.042" y2="360.383"><stop offset=".227" stop-color="#CCD4F4"/><stop offset=".789" stop-color="#ECF1FB"/></linearGradient><path d="M619.55 360.54s-.14-.37-.33.03c-1.74 3.53-17.48 41.83-18.73 71.38 0 0-2.63 16.98 19.39 16.76 18.38-.18 17.89-15.84 17.82-21.11-.26-21.4-18.15-67.06-18.15-67.06z" style="fill:url(#SVGID_4_)"/><linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="619.043" y1="370.19" x2="619.043" y2="467.503"><stop offset="0" stop-color="#ECF1FB"/><stop offset="1" stop-color="#A6A8E2"/></linearGradient><path d="M619.04 467.5c-.36 0-.64-.29-.64-.64v-96.02c0-.36.29-.64.64-.64s.64.29.64.64v96.02c.01.35-.28.64-.64.64z" style="fill:url(#SVGID_5_)"/><linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="464.96" y1="86.101" x2="430.206" y2="146.297"><stop offset="0" stop-color="#FFDB80"/><stop offset="1" stop-color="#FFBB24"/></linearGradient><circle cx="447.58" cy="116.2" r="34.75" style="fill:url(#SVGID_6_)"/><linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="422.623" y1="116.567" x2="422.623" y2="174.021"><stop offset="0" stop-color="#F9FAFE"/><stop offset="1" stop-color="#E5EDF7"/></linearGradient><path d="M467.36 135.15h-34.57c-2.23-10.61-11.65-18.58-22.93-18.58s-20.69 7.97-22.93 18.58h-9.05c-10.73 0-19.44 8.7-19.44 19.44 0 10.73 8.7 19.44 19.44 19.44h89.47c10.73 0 19.44-8.7 19.44-19.44.01-10.74-8.7-19.44-19.43-19.44z" style="fill:url(#SVGID_7_)"/><linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="689.644" y1="537.948" x2="689.644" y2="510.119"><stop offset=".227" stop-color="#AFB0E7"/><stop offset="1" stop-color="#ECF1FB"/></linearGradient><circle cx="689.64" cy="524.03" r="13.91" style="fill:url(#SVGID_8_)"/><linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="689.694" y1="513.633" x2="689.694" y2="558.429"><stop offset="0" stop-color="#DDE1F6"/><stop offset=".818" stop-color="#A6A8E2"/></linearGradient><path d="M689.69 558.43c-.24 0-.43-.19-.43-.43v-43.94c0-.24.19-.43.43-.43s.43.19.43.43V558c0 .24-.19.43-.43.43z" style="fill:url(#SVGID_9_)"/><linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="289.384" y1="477.19" x2="289.384" y2="411.226"><stop offset="0" stop-color="#B0B9E1"/><stop offset="1" stop-color="#E7EFF7"/></linearGradient><path d="M202.07 451.28L270.1 411.23 376.7 411.23 315.15 477.19 237.41 476.01z" style="fill:url(#SVGID_10_)"/><linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="454.145" y1="502.809" x2="454.145" y2="420.65"><stop offset="0" stop-color="#B0B9E1"/><stop offset="1" stop-color="#E7EFF7"/></linearGradient><path d="M386.71 479.55L431.76 420.65 521.58 420.65 423.81 502.81 394.37 495.15z" style="fill:url(#SVGID_11_)"/><linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="589.016" y1="472.132" x2="589.016" y2="397.68"><stop offset="0" stop-color="#B0B9E1"/><stop offset="1" stop-color="#E7EFF7"/></linearGradient><path d="M501.26 458.64l64.79-60.96h110.72l-48.99 66.61a19.243 19.243 0 01-17.85 7.7l-108.67-13.35z" style="fill:url(#SVGID_12_)"/><linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="314.267" y1="607.349" x2="314.267" y2="497.361"><stop offset="0" stop-color="#B0B9E1"/><stop offset="1" stop-color="#E7EFF7"/></linearGradient><path d="M212.23 592.77L303.67 497.36 416.3 497.36 297.04 607.35 247.57 604.7z" style="fill:url(#SVGID_13_)"/><g><linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="515.604" y1="312.867" x2="613.092" y2="481.721"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M564.35 296.53c-41.79 0-75.67 33.6-75.67 75.05v51.43c0 41.45 33.88 75.05 75.67 75.05s75.67-33.6 75.67-75.05v-51.43c-.01-41.45-33.88-75.05-75.67-75.05zm23.82 137.83c0 13.05-10.67 23.63-23.82 23.63-13.16 0-23.82-10.58-23.82-23.63v-74.13c0-13.05 10.67-23.63 23.82-23.63 13.16 0 23.82 10.58 23.82 23.63v74.13z" style="fill:url(#SVGID_14_)"/><linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="513.839" y1="321.619" x2="606.64" y2="482.355"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M560.24 305.91c-39.52 0-71.56 32.04-71.56 71.56v49.03c0 39.52 32.04 71.56 71.56 71.56s71.56-32.04 71.56-71.56v-49.03c0-39.52-32.04-71.56-71.56-71.56zm22.53 131.41c0 12.44-10.09 22.53-22.53 22.53-12.44 0-22.53-10.09-22.53-22.53v-70.67c0-12.44 10.09-22.53 22.53-22.53 12.44 0 22.53 10.09 22.53 22.53v70.67z" style="fill:url(#SVGID_15_)"/><linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="217.031" y1="307.363" x2="316.583" y2="479.793"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M333.72 412.6c-5.55-58.15-65.99-54.01-90.14-49.98l2.26-15.28 71.49 5.88 8.98-5.88V307.2h-109l-9.09 7.47-14.81 92.41h43.6c22.73-19.99 38.77-11.37 45.38 0 6.34 10.92 7.27 43.26-19.71 43.87-23.34.53-23.13-19.92-23.13-19.92l-41.55.58-8.06 7.52s6.18 59.41 69.73 59.41 77.3-50.09 74.05-85.94z" style="fill:url(#SVGID_16_)"/><linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="212.735" y1="311.982" x2="309.699" y2="479.928"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M324.26 415.94c-5.19-55.89-61.65-51.92-84.21-48.04l2.11-14.69h75.17v-38.58H208.14l-14.95 96h40.73c21.23-19.21 36.22-10.93 42.39 0 5.92 10.49 6.79 46.38-18.41 46.97-21.8.51-24.41-19.14-24.41-19.14l-43.54.66s5.78 59.41 65.14 59.41 72.2-48.14 69.17-82.59z" style="fill:url(#SVGID_17_)"/><linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="368.459" y1="304.731" x2="452.448" y2="450.205"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M387.26 461.26s-54.09-36.72-56.49-83.83c-2.29-45.03 25.47-81.27 76.27-81.27 55.29 0 78.12 47.95 78.12 73.99 0 26.04-10.63 63.25-55.73 93.35-23.53 0-42.17-2.24-42.17-2.24z" style="fill:url(#SVGID_18_)"/><linearGradient id="SVGID_19_" gradientUnits="userSpaceOnUse" x1="366.623" y1="312.428" x2="445.175" y2="448.483"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M384.76 461.29s-51.7-34.94-53.99-79.77c-2.19-42.85 24.35-77.34 72.9-77.34 52.85 0 73.47 45.54 73.47 70.32 0 24.78-12.03 58.72-55.14 87.36-22.49.01-37.24-.57-37.24-.57z" style="fill:url(#SVGID_19_)"/><linearGradient id="SVGID_20_" gradientUnits="userSpaceOnUse" x1="400.418" y1="454.748" x2="417.994" y2="485.191"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M414.59 486.78h-16.64c-.85 0-1.64-.44-2.08-1.17l-11.39-18.8c-.7-1.15-.33-2.64.82-3.34 1.15-.69 2.64-.33 3.34.82l10.68 17.62h13.84l10.6-19.05c.65-1.17 2.13-1.6 3.31-.94 1.17.65 1.6 2.13.94 3.31l-11.29 20.3c-.44.77-1.25 1.25-2.13 1.25z" style="fill:url(#SVGID_20_)"/><linearGradient id="SVGID_21_" gradientUnits="userSpaceOnUse" x1="397.841" y1="454.748" x2="415.417" y2="485.191"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M412.01 486.78h-16.64c-.85 0-1.64-.44-2.08-1.17l-11.39-18.8c-.7-1.15-.33-2.64.82-3.34 1.15-.69 2.64-.33 3.34.82l10.68 17.62h13.84l10.6-19.05c.65-1.17 2.13-1.6 3.31-.94 1.17.65 1.6 2.13.94 3.31l-11.29 20.3c-.43.77-1.25 1.25-2.13 1.25z" style="fill:url(#SVGID_21_)"/><linearGradient id="SVGID_22_" gradientUnits="userSpaceOnUse" x1="395.626" y1="441.888" x2="415.816" y2="476.856"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M429.22 468.35h-47.66c-2.76 0-5-2.24-5-5V452.9h57.65v10.45c0 2.76-2.23 5-4.99 5z" style="fill:url(#SVGID_22_)"/><linearGradient id="SVGID_23_" gradientUnits="userSpaceOnUse" x1="395.022" y1="445.756" x2="412.776" y2="476.507"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M425.57 468.35h-44.01c-2.76 0-5-2.24-5-5v-6.93h54.01v6.93c0 2.76-2.24 5-5 5z" style="fill:url(#SVGID_23_)"/><linearGradient id="SVGID_24_" gradientUnits="userSpaceOnUse" x1="396.171" y1="472.261" x2="416.697" y2="507.813"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M418.79 505.46h-25.7c-4.09 0-7.4-3.31-7.4-7.4v-19.75h40.5v19.75c0 4.09-3.31 7.4-7.4 7.4z" style="fill:url(#SVGID_24_)"/><linearGradient id="SVGID_25_" gradientUnits="userSpaceOnUse" x1="395.099" y1="476.159" x2="413.018" y2="507.195"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><path d="M414.04 505.46h-20.95c-4.09 0-7.4-3.31-7.4-7.4v-16.47h35.75v16.47c0 4.09-3.31 7.4-7.4 7.4z" style="fill:url(#SVGID_25_)"/><linearGradient id="SVGID_26_" gradientUnits="userSpaceOnUse" x1="370.752" y1="345.042" x2="439.366" y2="413.656"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M404.4 311.4s-17.23 79.51 1.33 135.9c47.84-62.43-1.33-135.9-1.33-135.9z" style="fill:url(#SVGID_26_)"/><linearGradient id="SVGID_27_" gradientUnits="userSpaceOnUse" x1="352.936" y1="350.49" x2="415.513" y2="413.067"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M386.43 316.99s-15.24 26.94-16.34 62.72c-.75 24.43 11.93 66.85 11.93 66.85s-20.76-36.07-20.76-70.23 25.17-59.34 25.17-59.34z" style="fill:url(#SVGID_27_)"/><linearGradient id="SVGID_28_" gradientUnits="userSpaceOnUse" x1="389.798" y1="347.846" x2="456.792" y2="414.84"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><path d="M420.65 316.99s34.1 22.12 34.1 60.99-29.68 68.58-29.68 68.58 23.5-42.18 23.5-70.9c0-14.24-13.98-48.76-27.92-58.67z" style="fill:url(#SVGID_28_)"/><path class="st26" d="M386.43 316.99s-62.13 47.12-4.42 129.57c-7.06-15.6-36.21-73.62 4.42-129.57zM420.65 316.99s62.13 47.12 4.42 129.57c7.07-15.6 36.22-73.62-4.42-129.57zM404.4 311.4s-35.48 79.66 1.33 135.9c32.24-57.5-1.33-135.9-1.33-135.9z"/></g><g><linearGradient id="SVGID_29_" gradientUnits="userSpaceOnUse" x1="234.692" y1="561.708" x2="234.692" y2="486.088"><stop offset="0" stop-color="#C3D5FD"/><stop offset="1" stop-color="#1A90FC"/></linearGradient><path d="M226.89 486.45s-18.35-2.54-24.31 5.89c-5.96 8.43-8.14 30.01-8.14 30.01l13.81-.73-1.16 25.14 25.48 14.94 36.3-19.52-5.52-22.78 11.6-3.03s-3.46-33.06-19.59-28.18c-8.29.89-10.9.74-10.9.74s-2.18 6.95-9.67 6.36c-7.49-.58-7.9-8.84-7.9-8.84z" style="fill:url(#SVGID_29_)"/><linearGradient id="SVGID_30_" gradientUnits="userSpaceOnUse" x1="235.741" y1="473.191" x2="235.741" y2="497.147"><stop offset="0" stop-color="#F4AE98"/><stop offset="1" stop-color="#FAD1BB"/></linearGradient><path d="M228.72 476.05l-3.81 17.01c-.18.8.24 1.61 1 1.92 1.97.8 5.91 2.17 9.97 2.17 4.21 0 8.18-2.3 10-3.53.63-.42.89-1.21.65-1.93l-5.83-17.35a1.681 1.681 0 00-1.89-1.12l-8.74 1.55c-.67.11-1.2.62-1.35 1.28z" style="fill:url(#SVGID_30_)"/><linearGradient id="SVGID_31_" gradientUnits="userSpaceOnUse" x1="-1535.437" y1="750.954" x2="-1523.728" y2="668.51" gradientTransform="rotate(-8.082 -1929.216 -11692.611)"><stop offset="0" stop-color="#C3D5FD"/><stop offset="1" stop-color="#1A90FC"/></linearGradient><path d="M205.94 489.39c5.34-1.77 12.58-.59 12.88 11.39.29 11.98-11.45 31.07-7.24 37.71 4.26 6.73 13.37 16.29 19.17 21.73-1.35 6.4-4.99 11.78-4.99 11.78s-21.36-9.86-30.66-19.73c-9.3-9.87-4.61-32.5-.3-48.61 3.24-12.13 11.14-14.27 11.14-14.27z" style="fill:url(#SVGID_31_)"/><linearGradient id="SVGID_32_" gradientUnits="userSpaceOnUse" x1="-5585.118" y1="175.804" x2="-5573.409" y2="93.36" gradientTransform="scale(-1 1) rotate(-8.082 -118.041 -37329.02)"><stop offset="0" stop-color="#C3D5FD"/><stop offset="1" stop-color="#1A90FC"/></linearGradient><path d="M261.91 489.39c-5.34-1.77-12.58-.59-12.88 11.39-.29 11.98 11.45 31.07 7.24 37.71-4.26 6.73-13.37 16.29-19.17 21.73 1.35 6.4 4.99 11.78 4.99 11.78s21.36-9.86 30.66-19.73c9.3-9.87 4.61-32.5.3-48.61-3.24-12.13-11.14-14.27-11.14-14.27z" style="fill:url(#SVGID_32_)"/><linearGradient id="SVGID_33_" gradientUnits="userSpaceOnUse" x1="234.692" y1="534.399" x2="234.692" y2="582.454"><stop offset="0" stop-color="#275C89"/><stop offset="1" stop-color="#013F7C"/></linearGradient><path d="M208.53 582.45h51.85c2.35 0 4.45-1.78 5.26-4.46l10.45-34.39c1.36-4.46-1.35-9.21-5.26-9.21h-72.29c-3.87 0-6.58 4.67-5.29 9.11l9.98 34.39c.8 2.74 2.92 4.56 5.3 4.56z" style="fill:url(#SVGID_33_)"/><path class="st26" d="M206.46 598.27s-.8-1.76-1.42-1.95c-.62-.19-9.49-.54-12.72-1.38s-12.56-2.17-16.56 1.61c-3.48 3.3-4.63 11 .67 15.43 1.99 1.73 3.94 2.23 11.31 1.89s18.04-.27 20.38-3.68c-.07-5.65-1.66-11.92-1.66-11.92z"/><linearGradient id="SVGID_34_" gradientUnits="userSpaceOnUse" x1="-3991.106" y1="603.193" x2="-3974.093" y2="603.193" gradientTransform="matrix(-1 0 0 1 -3772.525 0)"><stop offset="0" stop-color="#F4B9A4"/><stop offset=".652" stop-color="#FAD1BB"/></linearGradient><path d="M214.69 596.31s-8.56 1.92-11.62 1.64c-3.06-.28-.5 12.05-.5 12.05s8.17.57 15.4-1.53c2.45-9.44-3.28-12.16-3.28-12.16z" style="fill:url(#SVGID_34_)"/><linearGradient id="SVGID_35_" gradientUnits="userSpaceOnUse" x1="211.625" y1="584.443" x2="299.388" y2="584.443"><stop offset="0" stop-color="#18264B"/><stop offset=".652" stop-color="#2D3C65"/></linearGradient><path d="M211.63 595.87l4.45 13.84s95.64-12.6 81.97-43.63c-11.43-25.96-86.42 29.79-86.42 29.79z" style="fill:url(#SVGID_35_)"/><linearGradient id="SVGID_36_" gradientUnits="userSpaceOnUse" x1="191.837" y1="594.929" x2="191.837" y2="612.987"><stop offset="0" stop-color="#FFDB80"/><stop offset="1" stop-color="#FFBB24"/></linearGradient><path d="M205.35 596.94s3.5 1.37 3.95 6.26c.44 4.89-1 8.17-8.45 9.07-7.45.91-9.34.57-14.01.68-4.67.11-11.45.57-12.46-8.32-1-8.88 8.08-11.15 17.5-8.88 2.96.56 13.47 1.19 13.47 1.19z" style="fill:url(#SVGID_36_)"/><g><path class="st26" d="M266.14 598.27s.8-1.76 1.42-1.95c.62-.19 9.49-.54 12.72-1.38 3.23-.84 11.93-2.24 16.32 1.51 4.07 3.48 4.34 11.16-.3 15.4-1.99 1.73-4.08 2.35-11.44 2.01s-18.04-.27-20.38-3.68c.08-5.64 1.66-11.91 1.66-11.91z"/><linearGradient id="SVGID_37_" gradientUnits="userSpaceOnUse" x1="254.028" y1="603.193" x2="271.04" y2="603.193"><stop offset="0" stop-color="#F4B9A4"/><stop offset=".652" stop-color="#FAD1BB"/></linearGradient><path d="M257.92 596.31s8.56 1.92 11.62 1.64c3.06-.28.5 12.05.5 12.05s-8.17.57-15.4-1.53c-2.45-9.44 3.28-12.16 3.28-12.16z" style="fill:url(#SVGID_37_)"/><linearGradient id="SVGID_38_" gradientUnits="userSpaceOnUse" x1="173.22" y1="584.443" x2="260.983" y2="584.443"><stop offset="0" stop-color="#445677"/><stop offset="1" stop-color="#293861"/></linearGradient><path d="M260.98 595.87l-4.45 13.84s-95.64-12.6-81.97-43.63c11.43-25.96 86.42 29.79 86.42 29.79z" style="fill:url(#SVGID_38_)"/><linearGradient id="SVGID_39_" gradientUnits="userSpaceOnUse" x1="280.771" y1="594.929" x2="280.771" y2="612.987"><stop offset="0" stop-color="#FFDB80"/><stop offset="1" stop-color="#FFBB24"/></linearGradient><path d="M267.26 596.94s-3.5 1.37-3.95 6.26 1 8.17 8.45 9.07 9.34.57 14.01.68 11.45.57 12.46-8.32c1-8.88-8.08-11.15-17.5-8.88-2.96.56-13.47 1.19-13.47 1.19z" style="fill:url(#SVGID_39_)"/></g><linearGradient id="SVGID_40_" gradientUnits="userSpaceOnUse" x1="251.42" y1="467.696" x2="220.113" y2="467.696"><stop offset="0" stop-color="#F4B9A4"/><stop offset=".652" stop-color="#FAD1BB"/></linearGradient><path d="M250.74 469.25c.57-.81.93-2.88.46-3.49-.84-.68-1.63-.29-2.24.3.14-4.96-.31-9.07-.42-10.12-.31-3.04-3.4-8.6-13.5-8.6s-12.05 7.29-12.05 7.29-.66 5.15-.46 11.41c-.6-.58-1.39-.95-2.22-.28-.46.61-.1 2.68.46 3.49.57.81.93 2.73 1.03 3.79.1 1.01-.63 3.7 2.03 3.36 1.59 6.35 8.01 11.64 11.99 11.64 4.36 0 10.16-5.33 11.8-11.65 2.71.37 1.98-2.34 2.07-3.35.13-1.06.49-2.98 1.05-3.79z" style="fill:url(#SVGID_40_)"/><linearGradient id="SVGID_41_" gradientUnits="userSpaceOnUse" x1="215.804" y1="455.594" x2="252.152" y2="455.594"><stop offset="0" stop-color="#4F5C7C"/><stop offset="1" stop-color="#274168"/></linearGradient><path d="M242.34 445.19s-1.97-6.21-9.53-4.72c-7.55 1.48-8.06 5.06-11.03 5.19-5.06.24-9.11 6.54-2.61 13.22 2.89 2.97.45 4.25 1.82 6.88s1.36 5.19 1.36 5.19 2.41-7.71.82-11c-.82-1.7 2.82-2.16 7.35-1.75s11.68-1.1 12.24-4.18c1.34 6.32 2.68 6.98 4.38 7.94 1.7.96 1.8 8.6 1.8 8.6s.3-5.62 1.49-6.88c.98-2.07 2.89-10.22.73-12.19s-.34-8.31-8.82-6.3z" style="fill:url(#SVGID_41_)"/></g><linearGradient id="SVGID_42_" gradientUnits="userSpaceOnUse" x1="509.948" y1="612.061" x2="509.948" y2="547.57"><stop offset="0" stop-color="#B0B9E1"/><stop offset="1" stop-color="#E7EFF7"/></linearGradient><path d="M452.67 596.16L498.32 547.57 567.22 547.57 506.27 612.06z" style="fill:url(#SVGID_42_)"/><linearGradient id="SVGID_43_" gradientUnits="userSpaceOnUse" x1="461.835" y1="563.724" x2="495.632" y2="622.263"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><circle cx="478.73" cy="592.99" r="33.79" style="fill:url(#SVGID_43_)"/><linearGradient id="SVGID_44_" gradientUnits="userSpaceOnUse" x1="455.798" y1="564.313" x2="489.595" y2="622.851"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><circle cx="472.7" cy="593.58" r="33.79" style="fill:url(#SVGID_44_)"/><linearGradient id="SVGID_45_" gradientUnits="userSpaceOnUse" x1="479.001" y1="231.35" x2="503.267" y2="273.38"><stop offset="0" stop-color="#C8CBF2"/><stop offset="1" stop-color="#AFB0E7"/></linearGradient><circle cx="491.13" cy="252.36" r="24.26" style="fill:url(#SVGID_45_)"/><linearGradient id="SVGID_46_" gradientUnits="userSpaceOnUse" x1="474.666" y1="231.772" x2="498.933" y2="273.803"><stop offset=".116" stop-color="#DEE4FF"/><stop offset=".847" stop-color="#BACBEE"/></linearGradient><circle cx="486.8" cy="252.79" r="24.26" style="fill:url(#SVGID_46_)"/></g></svg>
src/assets/svgs/bpm/add-user.svg
New file
@@ -0,0 +1 @@
<svg t="1731390087280" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4297" width="200" height="200"><path d="M639.9 541.7c76.4-44.2 127.9-126.8 127.9-221.5C767.7 179 653.2 64.5 512 64.5S256.3 179 256.3 320.2c0 89.6 46.1 168.4 115.8 214.1C193.5 593 64.5 761.2 64.5 959.5h63.9c0-211.5 172.1-383.6 383.6-383.6 44.9 0 87.8 8.1 127.9 22.4v-56.6zM320.2 320.2c0-105.8 86-191.8 191.8-191.8s191.8 86 191.8 191.8S617.7 512 512 512s-191.8-86-191.8-191.8zM831.6 767.7V639.9h-63.9v127.8H639.9v63.9h127.8v127.9h63.9V831.6h127.9v-63.9z" fill="#5f6266" p-id="4298"></path></svg>
src/assets/svgs/bpm/approve.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1724316565416" class="icon" viewBox="0 0 1300 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1339" xmlns:xlink="http://www.w3.org/1999/xlink" width="253.90625" height="200"><path d="M784.058182 99.258182l10.938182 18.385454-21.294546-2.56-14.196363 16.058182-4.072728-21.061818-19.781818-8.494545 18.734546-10.472728 2.094545-21.294545 15.709091 14.545454 20.945454-4.654545-9.076363 19.549091zM1067.287273 642.443636l-18.501818 10.821819 2.56-21.294546-16.058182-14.196364 21.061818-4.072727 8.494545-19.665454 10.472728 18.734545 21.294545 1.978182-14.661818 15.709091 4.770909 20.945454-19.432727-8.96z" fill="#13C463" p-id="1340"></path><path d="M1067.287273 642.443636l-18.501818 10.821819 2.56-21.294546-16.058182-14.196364 21.061818-4.072727 8.494545-19.665454 10.472728 18.734545 21.294545 1.978182-14.661818 15.709091 4.770909 20.945454-19.432727-8.96zM571.927273 100.072727l-17.454546-12.567272 20.596364-6.167273 6.516364-20.48 12.218181 17.570909 21.410909-0.116364-12.916363 17.105455 6.749091 20.363636-20.247273-6.981818-17.338182 12.683636 0.465455-21.410909zM991.418182 784.407273l-21.178182 3.490909 10.123636-18.967273-9.774545-18.967273 21.061818 3.723637 15.127273-15.243637 2.909091 21.294546 19.2 9.658182-19.316364 9.309091-3.258182 21.178181-14.894545-15.476363zM427.985455 156.741818L407.272727 151.505455l16.872728-13.265455-1.396364-21.410909 17.803636 11.985454 20.014546-7.912727-5.934546 20.596364 13.730909 16.523636-21.410909 0.814546-11.52 18.152727-7.447272-20.247273zM854.225455 896.465455l-20.712728-5.352728 16.872728-13.265454-1.396364-21.294546 17.803636 11.869091 20.014546-7.912727-5.934546 20.712727 13.730909 16.523637-21.527272 0.814545-11.403637 18.036364-7.447272-20.130909zM562.501818 923.694545l10.821818 18.385455-21.294545-2.56-14.196364 16.058182-4.072727-21.061818-19.665455-8.494546 18.734546-10.356363 1.978182-21.41091 15.709091 14.661819 20.945454-4.770909-8.96 19.54909zM242.734545 420.770909l-18.385454 10.938182 2.56-21.294546-16.058182-14.196363 21.061818-4.189091 8.494546-19.665455 10.356363 18.734546 21.410909 2.094545-14.545454 15.709091 4.654545 20.945455-19.549091-9.076364z" fill="#13C463" p-id="1341"></path><path d="M242.734545 420.770909l-18.385454 10.938182 2.56-21.294546-16.058182-14.196363 21.061818-4.189091 8.494546-19.665455 10.356363 18.734546 21.410909 2.094545-14.545454 15.709091 4.654545 20.945455-19.549091-9.076364zM700.858182 943.941818l-17.454546-12.450909 20.48-6.283636 6.516364-20.48 12.334545 17.687272 21.41091-0.116363-12.916364 17.105454 6.632727 20.363637-20.247273-7.098182-17.221818 12.683636 0.465455-21.410909zM303.592727 278.807273l-21.178182 3.490909 10.123637-18.967273-9.890909-18.967273 21.178182 3.723637 15.010909-15.243637 2.909091 21.294546 19.2 9.541818-19.316364 9.425455-3.258182 21.178181-14.778182-15.476363z" fill="#13C463" p-id="1342"></path><path d="M407.272727 90.647273a486.632727 486.632727 0 0 1 504.552728 11.636363l25.018181-14.429091A512 512 0 0 0 139.636364 546.909091l25.018181-14.429091A486.981818 486.981818 0 0 1 407.272727 90.647273zM893.323636 933.352727a486.749091 486.749091 0 0 1-504.669091-11.636363l-24.901818 14.429091A512 512 0 0 0 1161.192727 477.090909l-24.901818 13.963636a486.981818 486.981818 0 0 1-242.967273 442.298182z" fill="#13C463" p-id="1343"></path><path d="M814.545455 795.927273a327.447273 327.447273 0 0 1-258.21091 29.556363l-29.78909 17.105455A353.163636 353.163636 0 0 0 998.865455 570.181818l-29.789091 17.105455A326.865455 326.865455 0 0 1 814.545455 795.927273zM486.865455 228.072727A327.447273 327.447273 0 0 1 744.727273 198.516364l29.789091-17.105455A353.163636 353.163636 0 0 0 302.545455 453.818182l29.78909-17.105455A326.865455 326.865455 0 0 1 486.865455 228.072727zM1288.378182 374.690909a53.294545 53.294545 0 0 1-14.429091 11.636364L229.469091 989.090909a53.876364 53.876364 0 0 1-73.425455-19.665454L7.214545 710.632727a53.527273 53.527273 0 0 1 19.781819-73.309091L1071.476364 34.909091a53.876364 53.876364 0 0 1 73.425454 19.665454l148.829091 258.327273a53.061818 53.061818 0 0 1 5.352727 40.727273 55.272727 55.272727 0 0 1-10.705454 21.061818zM32.232727 665.716364A28.043636 28.043636 0 0 0 29.323636 698.181818l148.829091 257.978182a28.392727 28.392727 0 0 0 38.516364 10.356364l1044.48-601.949091a28.16 28.16 0 0 0 10.356364-38.516364L1122.676364 67.84a28.276364 28.276364 0 0 0-38.4-10.356364L39.68 659.432727a27.810909 27.810909 0 0 0-7.447273 6.283637z" fill="#13C463" p-id="1344"></path><path d="M356.770909 569.250909l22.341818 38.749091-15.476363 8.727273L349.090909 592.64l-153.483636 88.785455 14.778182 25.483636-15.476364 8.96-23.272727-39.912727L256 627.2c-6.283636-4.887273-11.636364-8.843636-16.174545-11.636364L256 602.647273c3.956364 3.141818 9.774545 8.261818 17.338182 15.127272z m-17.338182 199.447273l-49.221818 28.392727 7.563636 13.149091-15.476363 8.96-62.138182-107.52 64.814545-37.469091-12.8-22.574545 15.941819-9.192728 12.8 22.109091 65.396363-37.701818 61.672728 106.821818-15.476364 8.96-7.214546-12.450909-49.92 28.858182 26.065455 45.032727-16.058182 9.192728z m-46.545454-79.825455L244.363636 717.265455l14.778182 25.6 49.221818-28.509091zM267.636364 756.945455l14.778181 25.6 49.221819-28.509091-14.778182-25.483637z m106.938181-80.523637l-14.778181-25.483636-49.92 28.741818 14.778181 25.483636zM346.996364 744.727273l49.803636-28.741818-14.661818-25.483637-49.92 28.741818zM505.832727 609.978182c-4.654545 6.283636-10.123636 13.265455-16.523636 21.061818l35.84 62.021818a18.967273 18.967273 0 0 1-6.749091 29.672727l-19.316364 11.636364-12.450909-13.847273a170.123636 170.123636 0 0 0 17.803637-8.727272 8.494545 8.494545 0 0 0 2.909091-13.614546L477.090909 645.352727l-9.890909 10.472728-10.007273 10.24-12.683636-13.149091c9.309091-8.261818 17.221818-15.941818 23.272727-23.272728l-31.301818-54.341818-25.018182 14.545455-8.843636-15.36 25.018182-14.429091-23.272728-41.076364 15.476364-8.96 23.272727 41.076364L465.454545 538.763636l8.843637 15.36-22.109091 12.567273 28.509091 49.221818c5.469091-6.516364 10.938182-13.498182 16.407273-21.061818z m9.076364-45.730909L572.043636 663.272727a207.825455 207.825455 0 0 0 23.272728-27.461818l11.636363 13.149091a365.381818 365.381818 0 0 1-41.774545 45.498182l-12.567273-12.567273a11.636364 11.636364 0 0 0 1.745455-13.963636L453.818182 493.963636l15.709091-9.076363 36.887272 63.883636 31.301819-18.152727 8.96 15.592727z m129.745454 83.316363a20.596364 20.596364 0 0 1-31.418181-9.774545l-103.098182-178.618182 15.709091-9.192727 38.632727 67.025454a200.261818 200.261818 0 0 0 28.043636-41.076363l16.872728 7.68a303.243636 303.243636 0 0 1-35.723637 49.338182l53.410909 93.090909a9.192727 9.192727 0 0 0 13.963637 4.072727l10.821818-6.283636a14.312727 14.312727 0 0 0 8.029091-11.636364 103.447273 103.447273 0 0 0-15.243637-39.098182l17.338182-3.84c12.567273 25.134545 18.036364 41.658182 16.290909 49.803636A28.392727 28.392727 0 0 1 663.272727 636.741818zM860.276364 521.774545c-7.563636 4.421818-20.829091 11.636364-39.912728 22.574546a179.432727 179.432727 0 0 1-37.352727 16.174545 58.181818 58.181818 0 0 1-33.047273-1.978181 14.312727 14.312727 0 0 0-11.636363-0.581819c-5.352727 3.025455-8.261818 18.385455-8.727273 45.847273l-18.269091-3.956364c1.047273-25.483636 5.003636-42.821818 11.636364-52.014545l-38.865455-67.374545-31.534545 18.152727-8.378182-14.661818 46.545454-26.647273 47.825455 82.850909a55.505455 55.505455 0 0 1 8.494545 1.861818 59.694545 59.694545 0 0 0 25.367273 4.072727 101.701818 101.701818 0 0 0 33.512727-11.636363L849.454545 508.509091l31.418182-18.734546c11.636364-7.214545 19.898182-12.334545 24.087273-15.127272l5.469091 18.152727zM676.072727 413.207273L671.185455 430.545455a279.272727 279.272727 0 0 0-58.181819-13.265455l4.887273-16.64a307.781818 307.781818 0 0 1 58.181818 12.567273zM754.967273 372.363636a261.818182 261.818182 0 0 0 20.247272-38.516363l-98.443636 56.785454-7.796364-13.498182 119.97091-69.46909 6.632727 11.636363a281.134545 281.134545 0 0 1-25.949091 54.807273l5.236364 0.930909L818.734545 349.090909l57.25091 99.025455a18.385455 18.385455 0 0 1-8.843637 27.927272l-18.385454 10.589091-11.636364-11.636363 17.92-9.425455a7.796364 7.796364 0 0 0 3.607273-11.636364L849.454545 437.410909l-37.236363 21.527273 21.992727 38.050909-14.894545 8.610909-21.992728-38.167273L760.203636 488.727273l22.458182 38.749091-15.127273 8.727272L699.461818 418.909091l55.389091-32a306.269091 306.269091 0 0 0-39.330909-1.047273l4.305455-15.127273c13.265455-0.232727 24.901818 0.465455 35.141818 1.629091z m15.825454 49.454546l-11.636363-20.014546-37.003637 21.410909 11.636364 20.014546z m-29.44 34.909091l11.636364 19.549091 37.003636-21.410909-11.636363-19.549091z m81.454546-64.814546l-11.636364-19.898182-37.236364 21.527273 11.636364 19.898182z m-29.556364 34.909091l11.636364 19.432727 37.236363-21.527272-11.636363-19.432728zM1086.370909 391.214545l-19.898182 11.636364-10.589091 6.167273-10.938181 6.050909a186.181818 186.181818 0 0 1-38.749091 16.989091 60.16 60.16 0 0 1-33.978182-1.978182 14.312727 14.312727 0 0 0-11.636364 0c-5.585455 3.258182-8.610909 18.734545-8.96 46.545455l-18.036363-3.723637c0.814545-26.181818 4.770909-43.752727 11.636363-52.945454l-38.865454-67.141819-31.883637 18.385455-8.727272-15.010909 47.243636-27.345455 47.941818 83.2h4.189091a32.465455 32.465455 0 0 1 4.538182 1.163637 71.68 71.68 0 0 0 26.298182 3.490909 112.872727 112.872727 0 0 0 34.210909-13.265455c16.523636-9.192727 31.767273-17.803636 46.545454-25.949091l14.545455-8.727272 14.196363-8.727273c11.636364-6.865455 18.618182-11.636364 22.574546-14.196364l5.352727 18.385455zM896 286.021818l-4.770909 18.385455a296.378182 296.378182 0 0 0-58.181818-14.661818l4.770909-16.872728a311.156364 311.156364 0 0 1 58.181818 13.149091zM1031.098182 384l-12.334546-13.149091c11.636364-5.934545 21.76-11.636364 30.138182-15.941818a9.658182 9.658182 0 0 0 4.189091-14.661818l-54.341818-94.138182-83.781818 48.290909-9.076364-15.709091 83.781818-48.407273-20.712727-35.84 16.174545-9.425454 20.712728 36.072727 32.814545-18.967273 8.610909 15.243637-32.349091 18.850909 56.552728 97.978182a20.247273 20.247273 0 0 1-8.843637 31.185454z m-23.272727-59.345455L1000.727273 340.48a405.876364 405.876364 0 0 0-58.181818-25.6l7.796363-15.127273a393.890909 393.890909 0 0 1 57.716364 24.436364z" fill="#13C463" p-id="1345"></path></svg>
src/assets/svgs/bpm/auditor.svg
New file
@@ -0,0 +1 @@
<svg t="1729561718271" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8640" width="200" height="200"><path d="M908.5952 920.4224H164.7616a31.0784 31.0784 0 0 1-30.976-30.976c0-17.0496 13.9264-30.976 30.976-30.976h743.8336c17.0496 0 31.0272 13.9264 31.0272 30.976a31.0784 31.0784 0 0 1-31.0272 30.976z m0-123.9552H164.7616a31.0784 31.0784 0 0 1-30.976-30.976v-154.9824c0-51.1488 41.8304-92.9792 92.9792-92.9792h198.3488c-6.1952-37.1712-24.7808-72.8064-51.1488-103.8336a216.576 216.576 0 0 1-54.2208-144.128c0-58.88 23.2448-114.688 66.6112-156.4672C429.7728 71.168 485.5296 51.0976 545.9968 52.6848c111.5648 4.608 206.08 100.6592 207.616 212.2752 1.536 55.808-20.1216 110.0288-57.344 151.8592-26.3168 27.904-41.8304 61.952-48.0256 100.7104h198.3488c51.2 0 93.0304 41.8304 93.0304 92.9792v154.9824a31.0784 31.0784 0 0 1-31.0272 30.976z m-712.8064-61.952H877.568v-124.0064a31.0784 31.0784 0 0 0-31.0272-30.976h-232.448a31.0784 31.0784 0 0 1-30.976-31.0272c0-65.024 23.2448-127.0784 66.6624-173.568 27.8528-29.3888 41.8304-68.1472 41.8304-108.4416-1.536-80.5888-68.1984-148.7872-148.7872-151.8592a150.528 150.528 0 0 0-113.152 43.3664 153.6 153.6 0 0 0-48.0256 111.616c0 37.1712 13.9776 74.3424 38.7584 102.2464 44.9536 51.1488 69.7344 113.152 69.7344 176.64a31.0784 31.0784 0 0 1-30.976 31.0272h-232.448a31.0784 31.0784 0 0 0-30.976 30.976v123.9552z" fill="#fff" p-id="8641"></path></svg>
src/assets/svgs/bpm/cancel.svg
New file
@@ -0,0 +1 @@
<svg t="1729178183592" class="icon" viewBox="0 0 1300 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4332" width="200" height="200"><path d="M784.074702 99.196443l10.927871 18.473304-21.302843-2.56935-14.180213 16.066571-4.130475-21.042655-19.676671-8.521137 18.733492-10.440019 2.016452-21.335366 15.708814 14.603017 20.945085-4.683373-9.041512 19.449008zM1067.22363 642.402668l-18.440781 10.92787 2.56935-21.302842-16.099094-14.180213 21.042655-4.130475 8.521137-19.676671 10.440019 18.733492 21.367889 2.016452-14.603017 15.708814 4.683373 20.945085-19.481531-9.041512z" fill="#8a8a8a" p-id="4333"></path><path d="M1067.22363 642.402668l-18.440781 10.92787 2.56935-21.302842-16.099094-14.180213 21.042655-4.130475 8.521137-19.676671 10.440019 18.733492 21.367889 2.016452-14.603017 15.708814 4.683373 20.945085-19.481531-9.041512zM571.924408 100.009528l-17.400031-12.488994 20.52228-6.211974 6.504685-20.457234 12.261331 17.595172 21.432936-0.09757-12.944323 17.074798 6.732349 20.359663-20.262093-7.02506-17.269938 12.716659 0.422804-21.46546zM991.444053 784.43246l-21.172749 3.480006 10.114785-18.928632-9.822074-19.026203 21.107702 3.772717 15.090868-15.253486 2.927109 21.237796 19.156296 9.626933-19.318914 9.366746-3.219819 21.205273-14.863204-15.48115zM428.008258 156.795426l-20.749945-5.333841 16.879657-13.237034-1.365983-21.400413 17.822836 11.936097 19.936859-7.870669-5.88674 20.619851 13.692361 16.521899-21.432936 0.813086-11.513292 18.083024-7.382817-20.132zM854.260251 896.475655l-20.749945-5.333841 16.879657-13.237034-1.365983-21.400413 17.822836 11.96862 19.936859-7.903192-5.854217 20.619851 13.659838 16.554423-21.432936 0.780562-11.513292 18.115547-7.382817-20.164523zM562.460092 923.665237l10.895347 18.440782-21.302843-2.569351-14.180212 16.099095-4.130475-21.042655-19.676672-8.521137 18.733493-10.440019 2.016452-21.36789 15.708814 14.603018 20.945085-4.683373-9.008989 19.48153zM242.787359 420.788058l-18.473305 10.895347 2.569351-21.302843-16.066572-14.180213 21.042656-4.130474 8.521137-19.676672 10.440019 18.733492 21.335366 2.016453-14.603018 15.708813 4.683374 20.945085-19.449008-9.008988z" fill="#8a8a8a" p-id="4334"></path><path d="M242.787359 420.788058l-18.473305 10.895347 2.569351-21.302843-16.066572-14.180213 21.042656-4.130474 8.521137-19.676672 10.440019 18.733492 21.335366 2.016453-14.603018 15.708813 4.683374 20.945085-19.449008-9.008988zM700.814737 943.959854l-17.400032-12.521518 20.522281-6.211974 6.504685-20.42471 12.26133 17.595172 21.432937-0.130094-12.944323 17.107321 6.732349 20.359663-20.262093-7.025059-17.269938 12.684135 0.422804-21.432936zM303.541115 278.823313l-21.140226 3.480006 10.114785-18.928633-9.854597-19.058726 21.107702 3.772717 15.090868-15.220962 2.927109 21.237796 19.156296 9.626933-19.28639 9.366746-3.252342 21.172749-14.863205-15.448626z" fill="#8a8a8a" p-id="4335"></path><path d="M407.648595 90.642782a486.713038 486.713038 0 0 1 504.568397 11.578339l25.010513-14.407877A512.081309 512.081309 0 0 0 139.850723 547.401747l24.977989-14.407877a486.778085 486.778085 0 0 1 242.819883-442.351088zM893.28836 933.422265a486.810608 486.810608 0 0 1-504.568398-11.610863l-25.010513 14.407877a512.081309 512.081309 0 0 0 797.5394-459.621026l-24.97799 14.505447a486.843132 486.843132 0 0 1-242.982499 442.318565z" fill="#8a8a8a" p-id="4336"></path><path d="M814.061299 795.880705a326.665269 326.665269 0 0 1-258.170939 29.563792l-29.791456 17.172368a353.236906 353.236906 0 0 0 472.793013-272.448721l-29.693886 17.172367a326.762839 326.762839 0 0 1-155.136732 208.540194zM486.875655 228.119295a326.795363 326.795363 0 0 1 258.170939-29.563792l29.791456-17.172368a353.236906 353.236906 0 0 0-472.793013 272.448721l29.82398-17.172367a326.762839 326.762839 0 0 1 155.006638-208.540194zM1288.350389 374.73489a53.923837 53.923837 0 0 1-14.34283 12.001143L229.420232 988.712085A53.793743 53.793743 0 0 1 156.112434 968.937843l-148.924757-258.235985a53.76122 53.76122 0 0 1 19.741718-73.437891L1071.516722 35.352962A53.826266 53.826266 0 0 1 1144.82452 55.062157l148.827187 258.268508a53.793743 53.793743 0 0 1-5.398888 61.404225zM32.19819 665.754486a28.360426 28.360426 0 0 0-5.626553 10.73273 28.067715 28.067715 0 0 0 2.699444 21.432936L178.195839 956.188661a28.165285 28.165285 0 0 0 38.442687 10.342449l1044.587328-601.976052a28.132762 28.132762 0 0 0 10.440019-38.442687l-148.924758-258.268509a28.197808 28.197808 0 0 0-38.442687-10.342449L39.711101 659.444942a28.230332 28.230332 0 0 0-7.512911 6.309544z" fill="#8a8a8a" p-id="4337"></path><path d="M498.941845 597.390249l-138.322121 79.877529 38.637827 66.933207q8.000762 13.854979 21.595554 5.98431l114.254788-65.957504a21.172749 21.172749 0 0 0 9.952167-11.123011q2.634397-9.757027-16.91218-47.321582l18.440781-4.130474q20.489757 43.22363 18.148071 56.167953a36.166047 36.166047 0 0 1-16.261712 19.514054l-123.068636 71.031158q-25.17313 14.603017-40.394092-11.77348L317.103383 639.020232l16.066571-9.269176 18.570875 32.133143 122.027886-70.47826-33.596697-58.249452-150.160648 86.707448-9.041511-15.611243 166.454883-96.106718zM691.903319 563.663459c-3.935334 3.837764-9.757027 9.399269-17.497602 16.619469l23.319295 40.394093-15.611244 9.008988-21.237795-36.816516q-31.027346 27.709957-64.754137 54.314118l-12.814229-13.39965 9.171605-7.382818 9.236653-7.122629-79.714912-138.126982-17.627696 10.179832-8.781324-15.155915L601.683341 414.836271l6.960013 12.06619 86.34969-49.858408 8.488614 14.733111q28.197808 65.82741 30.506972 123.39387a274.660314 274.660314 0 0 0 69.339939 27.612387l-3.642623 18.440781a322.177037 322.177037 0 0 1-65.534699-26.40902 220.899095 220.899095 0 0 1-15.38358 72.819946l-18.14807-6.179451a215.272542 215.272542 0 0 0 15.448626-77.340702 312.940384 312.940384 0 0 1-89.374369-86.739971l-8.748801 5.138701-7.2202-12.488995-17.172368 9.919644 71.876767 124.499667q10.570113-10.017215 17.465079-16.61947z m-134.32174-56.948515l40.166428-23.189202-19.969382-34.702493-40.166429 23.189201z m28.067714 48.785135l40.166429-23.189201-19.514055-33.921931-40.166428 23.189201z m48.557472-8.813847l-40.166428 23.189201 21.888264 37.922312q13.334604-10.92787 35.775766-30.767159z m7.2202-117.832365A289.848753 289.848753 0 0 0 715.515325 503.365031a330.437986 330.437986 0 0 0-26.441544-101.92841zM812.760362 400.460918l-4.813467 17.95293a280.482007 280.482007 0 0 0-56.167953-12.781706l5.073654-17.530125a291.637542 291.637542 0 0 1 55.907766 12.358901z m24.360045 28.78323a925.063745 925.063745 0 0 1 10.017214 101.895887l-18.440781 2.016452a812.792886 812.792886 0 0 0-8.878895-101.375512z m-45.923075-86.25212l-4.813467 18.017977a290.922026 290.922026 0 0 0-58.542163-11.513292l5.073655-17.497602a308.972527 308.972527 0 0 1 58.281975 10.992917z m48.459902-17.562649l-9.334223 13.724885A298.792695 298.792695 0 0 0 783.814515 315.477211l9.757027-14.180212a437.635191 437.635191 0 0 1 46.085692 24.13238zM834.355916 269.944418l16.521899-9.529363 35.157821 60.916373 48.199714-27.840051L1003.282579 413.047483q12.716659 22.115928-8.228426 34.214642l-26.018739 15.058345-13.237034-13.009369 25.238177-13.952549c6.992536-4.065428 8.45609-9.561887 4.423186-16.554423l-12.716659-22.018358-80.527997 46.475973L919.762427 491.1037l-16.066572 9.269176-81.926505-141.899698 47.744387-27.579864z m107.750103 73.763125l-14.830682-25.660981-80.56052 46.508496 14.830681 25.726028z m-72.592282 60.330952l14.700587 25.433317 80.560521-46.508496-14.700587-25.433318z m45.532793-166.064603a222.720407 222.720407 0 0 1-2.406733 56.13543l-16.456853 0.878132a242.722312 242.722312 0 0 0 2.081499-55.647578z" fill="#8a8a8a" p-id="4338"></path></svg>
src/assets/svgs/bpm/child-process.svg
New file
@@ -0,0 +1 @@
<svg t="1740116949537" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1153" width="200" height="200"><path d="M440.32 296.96h283.30496v145.92h66.56V230.4H440.32V17.92H17.92v424.96H440.32V296.96zM373.76 376.32H84.48v-291.84H373.76v291.84zM586.24 588.8v143.36512H298.66496V586.24h-66.56v212.48512H586.24V1013.76H1008.64v-424.96h-422.4z m355.84 358.4h-289.28v-291.84H942.08v291.84z" p-id="1154" fill="#ffffff"></path></svg>
src/assets/svgs/bpm/condition.svg
New file
@@ -0,0 +1 @@
<svg t="1729585232424" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1602" width="200" height="200"><path d="M925.5 898.9H804.9c-19 0-34.5-15.4-34.5-34.4V761.3c0-19 15.4-34.4 34.5-34.4h34.5V572.2c0-19-15.4-34.4-34.5-34.4H529.2V727h34.5c19 0 34.5 15.4 34.5 34.4v103.2c0 19-15.4 34.4-34.5 34.4H443.1c-19 0-34.5-15.4-34.5-34.4V761.3c0-19 15.4-34.4 34.5-34.4h34.5V537.8H219.1c-19 0-34.5 15.4-34.5 34.4V727h34.5c19 0 34.5 15.4 34.5 34.4v103.2c0 19-15.4 34.4-34.5 34.4H98.5c-19 0-34.5-15.4-34.5-34.4V761.3c0-19 15.4-34.4 34.5-34.4H133V555c0-38 30.9-68.8 68.9-68.8h275.7V297.1h-34.5c-19 0-34.5-15.4-34.5-34.4V159.5c0-19 15.4-34.4 34.5-34.4h120.6c19 0 34.5 15.4 34.5 34.4v103.2c0 19-15.4 34.4-34.5 34.4h-34.5v189.2h292.9c38.1 0 68.9 30.8 68.9 68.8v172h34.5c19 0 34.5 15.4 34.5 34.4v103.2c0 18.8-15.4 34.2-34.5 34.2z m0 0" p-id="1603" fill="#fff"></path></svg>
src/assets/svgs/bpm/copy.svg
New file
@@ -0,0 +1 @@
<svg t="1729649333541" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1644" width="200" height="200"><path d="M647.888 893.84L491.904 571.52l393.888-393.888-237.904 716.208zM872.32 123.232L459.872 535.68 134.96 380.88 872.32 123.232z m90.72-68.32a23.968 23.968 0 0 0-24.784-5.568L64.08 354.816a23.984 23.984 0 0 0-2.4 44.32l381.392 181.728 187.36 387.088a24.048 24.048 0 0 0 23.152 13.504 24.032 24.032 0 0 0 21.232-16.4L968.96 79.552c2.88-8.672 0.592-18.24-5.92-24.64z" fill="#fff" p-id="1645"></path></svg>
src/assets/svgs/bpm/delay.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1735905505218" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4277" width="200" height="200" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M561.778 454.929h198.117c0.549 0 0.994 0.444 0.994 1.001v97.553a0.998 0.998 0 0 1-0.994 1.001H463.224a1.005 1.005 0 0 1-1.002-1V207.04c0-0.552 0.444-1 1.002-1h97.552c0.553 0 1.002 0.455 1.002 1v247.89zM512 952.706c-247.424 0-448-200.576-448-448 0-247.423 200.576-448 448-448s448 200.577 448 448c0 247.424-200.576 448-448 448z m0-99.555c192.44 0 348.444-156.004 348.444-348.445 0-192.44-156.003-348.444-348.444-348.444-192.44 0-348.444 156.004-348.444 348.444 0 192.441 156.003 348.445 348.444 348.445z" fill="#3296FA" p-id="4278"></path></svg>
src/assets/svgs/bpm/finish.svg
New file
@@ -0,0 +1 @@
<svg t="1730189225011" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2651" id="mx_n_1730189225011" width="200" height="200"><path d="M793.889347 200.380242c27.648573 20.615681 42.196018 32.710677 63.781037 56.119312 25.313864 27.453234 43.242957 48.52047 64.502857 86.507991 44.537416 79.580127 53.527718 136.949077 53.517684 212.063821 0 64.933675-15.452562 130.459388-40.138263 187.311893-22.076044 50.841799-61.545336 104.359483-101.886297 138.933914-45.506755 39.001681-81.214423 60.462941-137.605337 81.826531-55.699867 21.102023-114.070267 28.641326-181.379458 27.791064-68.274516-0.862973-129.364283-11.040029-180.533878-31.80489-46.159002-18.731189-98.338744-46.827973-141.596418-87.541551-43.946046-41.361142-70.369064-75.958317-93.88139-127.198155-26.157437-57.004361-40.094111-129.065922-39.680686-191.781288 0-36.980719 4.033895-70.902234 12.252873-105.241856 8.532726-35.651474 20.069131-69.572989 38.13135-102.35257 18.856956-34.221214 36.754607-62.067803 58.869452-88.973149 23.248751-28.285434 39.2104-46.417894 64.295476-63.475987 18.297696-12.442861 36.879036-9.295353 47.199252-2.306612 4.403836 2.982273 8.919391 6.577992 12.933218 12.933217 9.572307 15.156208-0.334486 29.769212-6.69038 38.465836-7.148625 9.781026-23.130343 26.023643-38.738775 43.218205-38.192895 42.075603-55.133918 65.965228-74.986303 106.965794-30.772668 63.552249-37.495827 115.718611-38.131349 166.573791-0.668971 53.517684 9.995096 99.647251 27.427813 140.483919 33.916163 80.572211 94.807915 144.44289 175.270414 178.615938 41.108271 17.845472 113.812713 37.319888 181.960793 38.13135 56.193568 0.668971 125.919751-11.321666 166.574459-28.096784 45.935566-18.954626 97.223569-56.862539 127.10383-94.324918 23.013273-28.852721 52.179742-70.910931 64.413884-105.694749 14.863868-42.260239 24.806784-87.661297 24.559934-132.458943 0-54.414105-11.53373-108.417461-36.918505-156.856317-20.16747-38.483228-46.480777-74.607665-84.66899-108.048189-13.377414-11.714352-23.822728-20.067124-38.808348-31.619586-10.191774-7.857065-36.059546-25.027545-28.923632-47.326356 4.970455-15.53217 18.303717-25.294464 31.887843-27.205046 19.456354-2.736092 28.565733 2.427027 43.705885 12.041479l6.179955 4.322891zM510.755379 531.65738c-8.696624-0.668971-10.034566-0.446204-20.738102-6.689711-11.031333-6.434832-17.839451-21.183637-16.514219-35.175166V92.220334c0-18.178619 0.386665-22.815926 8.988295-31.685813 5.351768-5.519011 10.963097-11.381873 26.08987-11.539751 16.055305-0.167243 21.407073 3.846584 27.929542 9.700081 9.70677 8.711341 10.703537 17.56049 10.377078 33.525483v397.5715c-0.509756 15.273947 0.326458 22.967114-11.380535 33.502739-3.884046 3.495374-8.027653 7.693167-20.96087 8.362138l-3.791059 0.000669z m4.453341 0.573308" p-id="2652" fill="#ffffff"></path></svg>
src/assets/svgs/bpm/parallel.svg
New file
@@ -0,0 +1 @@
<svg t="1729585239190" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1755" width="200" height="200"><path d="M901.489435 536.822664v-0.931601l-1.001722-198.240726c-0.100172-19.162936-9.21584-37.474409-25.043042-50.246361-14.024104-11.349507-32.265456-17.60025-51.348255-17.610268l-618.062295-0.18031c-19.142902 0-37.424323 6.280795-51.478478 17.690405-15.827203 12.842072-24.902802 31.2437-24.892785 50.486775v196.798247A114.987635 114.987635 0 1 0 195.295664 536.922836V338.782282c1.15198-1.252152 4.808264-3.596181 10.768509-3.596181l276.725622 0.090155v199.753326a114.987635 114.987635 0 1 0 65.612772 1.412428V335.326342l275.693849 0.080138c6.01033 0 9.626546 2.344029 10.768508 3.596181l1.001722 195.70637a114.987635 114.987635 0 1 0 65.592737 2.113633zM214.979496 645.910158a56.437001 56.437001 0 1 1-56.437001-56.437001 56.507122 56.507122 0 0 1 56.437001 56.437001z m354.689623 0a56.437001 56.437001 0 1 1-56.437001-56.437001 56.507122 56.507122 0 0 1 56.437001 56.437001z m295.507904 56.437001a56.437001 56.437001 0 1 1 56.437001-56.437001 56.507122 56.507122 0 0 1-56.457035 56.437001z" p-id="1756" fill='#fff'></path></svg>
src/assets/svgs/bpm/reject.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1724316570161" class="icon" viewBox="0 0 1185 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1505" xmlns:xlink="http://www.w3.org/1999/xlink" width="231.4453125" height="200"><path d="M414.276535 230.004913l-2.443086-31.647244 26.446614 17.351559 29.437984-11.852598-8.143622 30.31685 20.423559 24.221229-31.623055 1.475527-16.722646 26.801386-11.239811-29.760504-30.663559-7.522772zM581.664252 176.902047l13.884472-28.542992 14.206993 28.220473 31.42148 4.321763-22.350614 22.092599 5.684409 31.123149-28.180157-14.513385-27.897953 14.819779 5.28126-31.066709-22.76989-21.689448zM896.507969 672.735748l17.754708 26.398236-31.494047-2.064126-19.560819 24.705008-7.95011-30.502299-29.575055-11.02211 26.744945-16.771024 1.104629-31.526299 24.414741 20.197795 30.268472-8.619338zM777.030551 801.961323l2.112504 31.647244-26.446614-17.682142-29.413795 11.546205 8.466141-30.308787-20.092976-24.221229 31.606929-1.153008 17.045166-26.793323 10.86085 29.704063 30.647433 7.837229zM609.312252 853.451591l-14.198929 28.518803-14.110236-28.542992-31.405355-4.636221 22.673134-22.084535-5.36189-31.12315 27.833449 14.835906 28.188221-14.803654-5.28126 31.066709 22.76989 22.060346zM298.435528 354.828094l-17.448315-26.390173 31.485984 2.394709 19.875275-24.753386 7.611465 30.865134 29.583118 11.288189-27.011024 16.779087-1.419086 31.526299-24.084158-20.504189-30.518425 8.280693zM962.56 91.53915a43.636913 43.636913 0 0 1 59.375874 15.601889l138.627024 236.753638c12.175118 20.447748 5.12 47.208819-15.609953 59.375874L229.13411 938.185575a43.636913 43.636913 0 0 1-59.375874-15.60189L31.12315 685.773606a43.636913 43.636913 0 0 1 15.601889-59.319433z m25.672567 24.108346a13.594205 13.594205 0 0 0-10.441575 1.548095L61.625449 652.054173a13.586142 13.586142 0 0 0-4.853921 18.83515l138.643149 236.793953a13.586142 13.586142 0 0 0 18.843213 4.837795l915.818834-534.915024a13.957039 13.957039 0 0 0 5.160315-18.778708l-138.602834-236.78589a13.594205 13.594205 0 0 0-8.401638-6.393953z" fill="#F5222D" p-id="1506"></path><path d="M395.981606 172.338394c123.670173-72.349228 271.11811-69.462677 388.394331-5.12l29.623433-17.335433a414.574866 414.574866 0 0 0-112.107842-47.071748 429.991307 429.991307 0 0 0-162.009701-10.498016 412.792945 412.792945 0 0 0-158.80063 54.707401 417.856504 417.856504 0 0 0-125.363402 111.922394A426.282331 426.282331 0 0 0 185.206929 405.004094a417.348535 417.348535 0 0 0-13.529701 120.977134l29.623433-17.335433c1.386835-133.958551 70.688252-263.958173 194.672882-336.307401z m397.666772 679.484472c-123.670173 72.365354-271.110047 69.462677-388.394331 5.128063l-29.623433 17.335433a414.679685 414.679685 0 0 0 112.075591 47.087874 429.991307 429.991307 0 0 0 162.009701 10.498016 412.744567 412.744567 0 0 0 158.808692-54.707402 423.145827 423.145827 0 0 0 209.105638-378.976756l-29.623433 17.335434c-1.072378 133.974677-70.712441 263.95011-194.350362 336.307401h-0.008063z" fill="#F5222D" p-id="1507"></path><path d="M478.377323 313.110173a226.271748 226.271748 0 0 1 109.979212-31.219905l45.668788-26.761071c-58.634079-9.13537-118.316346 2.314079-170.612914 32.735748a258.693039 258.693039 0 0 0-111.91433 132.71685l45.67685-26.761071a230.359685 230.359685 0 0 1 81.097575-80.589606l0.104819-0.120945z m232.568945 397.674835a226.328189 226.328189 0 0 1-109.979213 31.227968l-45.668787 26.753008c58.634079 9.13537 118.316346-2.314079 170.612913-32.735748a258.709165 258.709165 0 0 0 111.914331-132.71685l-45.676851 26.761071a225.215496 225.215496 0 0 1-81.097574 80.597669l-0.104819 0.112882zM188.57726 706.938961l-10.062614-17.424126 109.938897-63.471874 9.578835 16.585574 17.093543-9.869102-18.770645-32.509984-63.689575 36.767244c-4.047622-3.918614-7.804976-7.337323-11.272063-10.24l-16.859717 13.747401c3.249386 2.144756 6.595528 4.458835 9.869103 7.038993l-62.173733 35.896441 19.254426 33.348535 17.093543-9.869102zM317.44 781.142677l-19.060913-33.017953 32.679307-18.867401 4.741039 8.216189 17.093543-9.869103-48.474708-83.959937-49.772851 28.736504-7.933984-13.747401-17.432189 10.062614 7.933984 13.747402-49.264882 28.446236 48.764977 84.459842 17.093543-9.869102-5.031307-8.708032 32.171339-18.585196 19.060913 33.017952 17.432189-10.062614z m-12.505701-97.126803l-32.679307 18.867402-8.321008-14.41663 32.679307-18.867402 8.321008 14.41663z m-50.111496 28.930016l-32.171338 18.577134-8.321008-14.41663 32.171338-18.577134 8.321008 14.41663z m16.932284 29.325102l-32.171339 18.577134-8.127496-14.077984 32.171339-18.577134 8.127496 14.077984z m50.111496-28.930016l-32.679307 18.867402-8.127496-14.077984 32.679307-18.867402 8.127496 14.077984z m95.828661 7.684032c11.062425-6.38589 13.368441-15.537386 6.692284-27.099717l-25.05978-43.411149c3.55578-4.289512 7.014803-8.740283 10.48189-13.199118l-9.482079-16.424315c-3.467087 4.458835-6.92611 8.917669-10.48189 13.199118l-17.803086-30.832882 14.755275-8.51452-9.780409-16.932283-14.747213 8.522582-16.738771-28.994519-17.093544 9.869102 16.738772 28.99452-16.924221 9.772346 9.772347 16.924221 16.932283-9.772347 20.891213 36.202835a299.927181 299.927181 0 0 1-16.690394 15.214866l13.868347 14.344063a572.617575 572.617575 0 0 0 12.497638-12.804031l19.157669 33.179212c2.322142 4.031496 1.475528 7.200252-2.20926 9.328882-3.85411 2.225386-8.167811 4.039559-12.578268 5.692472l13.55389 14.964914 14.247307-8.224252z m111.390236-65.205417c6.369764-3.676724 10.15937-8.329071 11.151118-13.586142 1.225575-5.619906-3.201008-18.706142-13.182992-39.089386l-18.827086 4.160504c7.627591 14.368252 11.368819 23.164976 11.570393 26.615937 0.112882 3.289701-0.959496 5.692472-3.467086 7.143811l-6.539087 3.77348c-3.354205 1.935118-6.095622 1.064315-8.224252-2.628535l-38.702362-67.027654c8.933795-10.07874 17.762772-21.874898 26.390173-35.573921l-18.383622-8.603213a168.443969 168.443969 0 0 1-17.972409 26.914268l-26.801386-46.426709-17.254803 9.965859 77.686929 134.571338c6.966425 12.070299 16.077606 15.077795 27.478677 8.498394l15.077795-8.708031z m-78.501291 45.547842c13.626457-12.779843 25.285543-25.100094 34.783748-37.291339l-12.473449-14.247307a157.808882 157.808882 0 0 1-14.706897 17.875654l-38.412095-66.535811 20.617071-11.900976-9.869102-17.093544-20.617071 11.900977-27.18841-47.087874-17.254803 9.965858 72.94589 126.363212c2.999433 5.192567 2.418898 9.99811-1.564221 14.311811l13.739339 13.739339z m201.663496-113.978457l-65.21348-112.946393c0.137071-7.901732-0.16126-15.771213-0.886929-23.624567l53.78822-31.050583-9.869102-17.093543-144.795213 83.597102 9.869102 17.093543 71.05915-41.024504c1.894803 37.331654-9.45789 76.517795-33.848441 117.856756l20.367118 8.570961c14.860094-26.898142 25.05978-53.344756 30.445859-79.243087l50.990362 88.313953 18.093354-10.449638z m28.728441-76.017889l5.716661-21.850709c-21.157291-7.224441-45.330142-12.707276-72.349228-16.54526l-5.603779 19.318929c29.163843 4.837795 53.385071 11.191433 72.244409 19.07704z m18.738394-105.33493l5.265134-19.13348c-12.739528-4.25726-27.414173-7.627591-43.612725-10.127118l-5.410268 18.101417c17.674079 2.74948 32.380976 6.555213 43.757859 11.159181z m88.934803 67.74526l-15.76315-27.317417 21.786205-12.578268 15.674457 27.148095 16.085669-9.288567-15.674457-27.148095 22.455433-12.965291 4.063748 7.038992c2.031874 3.523528 1.249764 6.426205-2.435023 8.554835l-11.852599 6.176252 12.175118 12.183181 12.570205-7.256693c11.393008-6.579402 13.997354-15.230992 7.998488-25.616126l-42.862866-74.244032-33.848441 19.544693-0.532157-0.145133a202.445606 202.445606 0 0 0 18.738393-38.750741L790.173228 306.87748l-92.676031 53.506016 8.321008 14.41663 31.679496-18.286866-3.85411 13.836094c8.401638-0.16126 16.125984 0.08063 23.261732 0.427339l-37.202646 21.479811 52.538457 90.998929 16.424315-9.482079z m-25.35811-117.856756c-6.724535-0.806299-14.126362-1.233638-21.947465-1.628724l33.517858-19.351181c-3.305827 7.047055-7.143811 13.948976-11.570393 20.979905z m47.571653 16.996788l-22.455433 12.965291-6.095622-10.56252 22.455433-12.965291 6.095622 10.56252z m-38.541102 22.253858l-21.786205 12.578268-6.095622-10.56252 21.786205-12.578268 6.095622 10.56252z m-24.253481 137.570772c-0.330583-19.915591 1.112693-30.582929 4.458835-32.518048 1.846425-1.064315 4.628157-0.886929 8.627402 0.604725 8.304882 2.797858 16.400126 3.265512 24.269606 1.402961 8.006551-2.386646 17.464441-6.506835 28.462362-12.626646 10.812472-6.031118 20.96378-11.66715 30.187843-16.988725l38.379842-22.157102-5.781165-19.673701c-4.329827 2.942992-10.675402 7.055118-19.028662 12.320252-8.708031 5.031307-16.996787 10.038425-25.374236 14.876221-13.07011 7.546961-24.398614 13.868346-34.211275 19.302803-10.07874 5.378016-18.230425 8.296819-24.543748 8.587087-5.28126 0.145134-11.070488-0.983685-17.440252-3.120378l-2.902678-0.774048-36.767244-63.681511-38.379842 22.157102 9.288567 16.085669 22.116787-12.771779 26.511118 45.91874c-4.571717 7.555024-7.014803 20.359055-7.651779 38.605606l19.778519 4.450772z m38.476599-112.938331l-21.786205 12.578268-6.095622-10.56252 21.786205-12.578268 6.095622 10.56252z m38.541102-22.253858l-22.455433 12.965291-6.095622-10.56252 22.455433-12.957228 6.095622 10.56252z m172.241638-43.798173c12.062236-6.966425 14.610142-16.488819 7.740472-28.381733l-39.863433-69.051464 23.302048-13.449071-9.869103-17.093543-23.302047 13.44907-14.513386-25.132346-17.424126 10.062614 14.513386 25.132347-62.681701 36.186708 9.869103 17.093544 62.6817-36.186709 37.34778 64.689386c2.515654 4.354016 1.523906 8.062992-2.838173 10.578645-6.692283 3.870236-14.190866 7.522772-21.955528 11.110804l13.529701 14.537574 23.463307-13.545826z m-130.942992-43.725607l5.386079-20.092976c-12.900787-4.168567-27.389984-7.200252-43.65304-9.433701l-5.321575 18.27074c17.682142 2.74948 32.219717 6.643906 43.596599 11.255937z m80.702488 27.148095l8.466142-17.851465c-10.756031-5.853732-24.825953-12.038047-41.846929-18.302992l-8.740284 16.22274c16.883906 6.789039 30.808693 13.497449 42.121071 19.931717z m-31.219905 99.577952c-0.354772-20.350992 1.064315-31.445669 4.418519-33.380787 2.007685-1.161071 5.128063-1.177197 9.119244 0.32252a42.951559 42.951559 0 0 0 24.938835 1.007874c8.175874-2.483402 18.141732-6.893858 29.639559-13.303937 11.320441-6.321386 21.810394-12.150929 31.365039-17.657953l35.525544-20.520315-5.966614-20.012346c-3.999244 2.74948-10.006173 6.668094-17.859528 11.651023-7.95011 4.805543-15.722835 9.522394-23.439118 13.973166a2406.72252 2406.72252 0 0 1-35.719055 20.181669c-10.586709 5.66022-19.165732 8.603213-25.712882 9.256315-5.28126 0.145134-11.401071-0.790173-17.940158-2.822047l-3.080063-0.685355-36.767244-63.681512-39.041008 22.544126 9.482079 16.424315 22.455433-12.965291 26.511118 45.91874c-4.57978 7.555024-7.256693 20.72189-7.700157 39.299024l19.770457 4.450771z" fill="#F5222D" p-id="1508"></path></svg>
src/assets/svgs/bpm/running.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1724304256588" class="icon" viewBox="0 0 1300 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1272" xmlns:xlink="http://www.w3.org/1999/xlink" width="253.90625" height="200"><path d="M784.058182 99.258182l10.938182 18.385454-21.294546-2.56-14.196363 16.058182-4.072728-21.061818-19.781818-8.494545 18.734546-10.472728 2.094545-21.294545 15.709091 14.545454 20.945454-4.654545-9.076363 19.549091zM1067.287273 642.443636l-18.501818 10.821819 2.56-21.294546-16.058182-14.196364 21.061818-4.072727 8.494545-19.665454 10.472728 18.734545 21.294545 1.978182-14.661818 15.709091 4.770909 20.945454-19.432727-8.96z" fill="#2196F3" p-id="1273"></path><path d="M1067.287273 642.443636l-18.501818 10.821819 2.56-21.294546-16.058182-14.196364 21.061818-4.072727 8.494545-19.665454 10.472728 18.734545 21.294545 1.978182-14.661818 15.709091 4.770909 20.945454-19.432727-8.96zM571.927273 100.072727l-17.454546-12.567272 20.596364-6.167273 6.516364-20.48 12.218181 17.570909 21.410909-0.116364-12.916363 17.105455 6.749091 20.363636-20.247273-6.981818-17.338182 12.683636 0.465455-21.410909zM991.418182 784.407273l-21.178182 3.490909 10.123636-18.967273-9.774545-18.967273 21.061818 3.723637 15.127273-15.243637 2.909091 21.294546 19.2 9.658182-19.316364 9.309091-3.258182 21.178181-14.894545-15.476363zM427.985455 156.741818L407.272727 151.505455l16.872728-13.265455-1.396364-21.410909 17.803636 11.985454 20.014546-7.912727-5.934546 20.596364 13.730909 16.523636-21.410909 0.814546-11.52 18.152727-7.447272-20.247273zM854.225455 896.465455l-20.712728-5.352728 16.872728-13.265454-1.396364-21.294546 17.803636 11.869091 20.014546-7.912727-5.934546 20.712727 13.730909 16.523637-21.527272 0.814545-11.403637 18.036364-7.447272-20.130909zM562.501818 923.694545l10.821818 18.385455-21.294545-2.56-14.196364 16.058182-4.072727-21.061818-19.665455-8.494546 18.734546-10.356363 1.978182-21.41091 15.709091 14.661819 20.945454-4.770909-8.96 19.54909zM242.734545 420.770909l-18.385454 10.938182 2.56-21.294546-16.058182-14.196363 21.061818-4.189091 8.494546-19.665455 10.356363 18.734546 21.410909 2.094545-14.545454 15.709091 4.654545 20.945455-19.549091-9.076364z" fill="#2196F3" p-id="1274"></path><path d="M242.734545 420.770909l-18.385454 10.938182 2.56-21.294546-16.058182-14.196363 21.061818-4.189091 8.494546-19.665455 10.356363 18.734546 21.410909 2.094545-14.545454 15.709091 4.654545 20.945455-19.549091-9.076364zM700.858182 943.941818l-17.454546-12.450909 20.48-6.283636 6.516364-20.48 12.334545 17.687272 21.41091-0.116363-12.916364 17.105454 6.632727 20.363637-20.247273-7.098182-17.221818 12.683636 0.465455-21.410909zM303.592727 278.807273l-21.178182 3.490909 10.123637-18.967273-9.890909-18.967273 21.178182 3.723637 15.010909-15.243637 2.909091 21.294546 19.2 9.541818-19.316364 9.425455-3.258182 21.178181-14.778182-15.476363z" fill="#2196F3" p-id="1275"></path><path d="M407.272727 90.647273a486.632727 486.632727 0 0 1 504.552728 11.636363l25.018181-14.429091A512 512 0 0 0 139.636364 546.909091l25.018181-14.429091A486.981818 486.981818 0 0 1 407.272727 90.647273zM893.323636 933.352727a486.749091 486.749091 0 0 1-504.669091-11.636363l-24.901818 14.429091A512 512 0 0 0 1161.192727 477.090909l-24.901818 13.963636a486.981818 486.981818 0 0 1-242.967273 442.298182z" fill="#2196F3" p-id="1276"></path><path d="M814.545455 795.927273a327.447273 327.447273 0 0 1-258.21091 29.556363l-29.78909 17.105455A353.163636 353.163636 0 0 0 998.865455 570.181818l-29.789091 17.105455A326.865455 326.865455 0 0 1 814.545455 795.927273zM486.865455 228.072727A327.447273 327.447273 0 0 1 744.727273 198.516364l29.789091-17.105455A353.163636 353.163636 0 0 0 302.545455 453.818182l29.78909-17.105455A326.865455 326.865455 0 0 1 486.865455 228.072727zM1288.378182 374.690909a53.294545 53.294545 0 0 1-14.429091 11.636364L229.469091 989.090909a53.876364 53.876364 0 0 1-73.425455-19.665454L7.214545 710.632727a53.527273 53.527273 0 0 1 19.781819-73.309091L1071.476364 34.909091a53.876364 53.876364 0 0 1 73.425454 19.665454l148.829091 258.327273a53.061818 53.061818 0 0 1 5.352727 40.727273 55.272727 55.272727 0 0 1-10.705454 21.061818zM32.232727 665.716364A28.043636 28.043636 0 0 0 29.323636 698.181818l148.829091 257.978182a28.392727 28.392727 0 0 0 38.516364 10.356364l1044.48-601.949091a28.16 28.16 0 0 0 10.356364-38.516364L1122.676364 67.84a28.276364 28.276364 0 0 0-38.4-10.356364L39.68 659.432727a27.810909 27.810909 0 0 0-7.447273 6.283637z" fill="#2196F3" p-id="1277"></path><path d="M477.090909 500.945455l22.109091 38.283636-15.36 8.843636-13.963636-24.436363-151.272728 87.621818 14.545455 25.134545-15.243636 8.843637-23.272728-39.330909L377.949091 558.545455c-6.050909-4.887273-11.636364-8.843636-15.825455-11.636364l14.894546-12.450909c3.956364 3.141818 9.658182 8.145455 17.105454 14.894545zM459.869091 698.181818l-48.407273 28.043637 7.447273 12.334545-15.36 8.843636-61.207273-106.007272L406.225455 605.090909l-12.683637-21.876364 15.709091-9.076363 12.683636 21.876363L486.4 558.545455l60.509091 104.727272-15.36 8.843637-7.098182-12.218182-49.105454 28.392727L501.294545 733.090909l-15.70909 9.076364z m-45.381818-78.661818l-48.523637 27.461818 14.545455 25.134546 48.523636-28.043637zM388.538182 686.545455l14.545454 25.134545 48.523637-28.043636-14.545455-25.134546z m105.425454-79.476364L479.418182 581.818182 430.545455 609.861818l14.545454 25.134546z m-26.647272 67.490909l49.221818-28.392727-14.545455-25.134546-49.105454 28.392728zM624.058182 541.090909c-4.654545 6.167273-10.123636 13.149091-16.290909 20.829091l34.909091 61.207273a18.734545 18.734545 0 0 1-6.632728 29.207272l-18.734545 10.938182-11.636364-13.614545a174.545455 174.545455 0 0 0 17.454546-8.610909 8.378182 8.378182 0 0 0 2.327272-12.683637l-30.021818-52.363636-9.774545 10.24-9.890909 10.123636-12.450909-12.916363c9.076364-8.145455 16.872727-15.709091 23.272727-22.574546l-30.836364-53.527272-24.785454 14.196363-8.727273-15.010909L546.909091 492.218182l-23.272727-40.378182 15.36-8.843636 23.272727 40.378181 21.643636-12.450909 8.727273 15.127273-21.643636 12.450909L599.156364 546.909091c5.352727-6.4 10.821818-13.381818 16.290909-20.712727z m8.843636-45.032727L689.221818 593.454545a193.745455 193.745455 0 0 0 22.574546-27.112727l11.636363 13.032727a363.985455 363.985455 0 0 1-41.192727 44.8l-12.334545-12.450909a10.821818 10.821818 0 0 0 1.62909-13.730909l-98.90909-171.403636 15.476363-8.96 36.305455 62.952727 30.836363-17.803636 8.029091 15.476363z m128 81.454545a20.130909 20.130909 0 0 1-30.836363-9.541818L628.363636 392.378182l15.36-8.378182 38.050909 66.094545A206.08 206.08 0 0 0 709.818182 409.018182l16.64 7.563636a297.890909 297.890909 0 0 1-34.909091 48.64l52.712727 91.112727a8.843636 8.843636 0 0 0 13.614546 4.072728l10.821818-6.167273a14.429091 14.429091 0 0 0 7.912727-11.636364 102.981818 102.981818 0 0 0-15.010909-38.516363l17.105455-3.723637c12.334545 24.669091 17.687273 41.076364 16.058181 48.989091a28.16 28.16 0 0 1-15.127272 18.152728zM805.236364 288.116364l16.174545-9.309091 23.272727 39.330909 78.429091-45.265455 59.345455 102.749091-16.64 9.076364-7.912727-13.847273L896 407.272727l42.938182 74.472728-16.174546 9.30909-42.938181-74.472727-62.603637 36.072727 8.029091 13.73091-15.825454 9.192727L749.730909 372.363636l78.196364-45.265454z m2.676363 149.061818l62.603637-36.072727-33.745455-58.181819-62.487273 36.072728z m78.778182-45.381818l62.72-36.189091-33.745454-58.181818-62.72 36.072727z" fill="#2196F3" p-id="1278"></path></svg>
src/assets/svgs/bpm/simple-process-bg.svg
New file
@@ -0,0 +1 @@
<svg width="22" height="22" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path fill="#FAFAFA" d="M0 0h22v22H0z"/><circle fill="#919BAE" cx="1" cy="1" r="1"/></g></svg>
src/assets/svgs/bpm/starter.svg
New file
@@ -0,0 +1 @@
<svg t="1729561814171" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1359" width="200" height="200"><path d="M674.496 603.456c120.256 0 218.176 90.752 221.44 203.84l0.064 5.888v125.888c0 11.52-9.92 20.928-22.144 20.928h-44.352a21.568 21.568 0 0 1-22.144-20.928v-125.888c0-67.712-56.512-123.264-128-125.76l-4.928-0.064H349.568c-71.488 0-130.176 53.504-132.864 121.152l-0.064 4.672v125.888c0 11.52-9.92 20.928-22.144 20.928h-44.352A21.568 21.568 0 0 1 128 939.072v-125.888c0-113.92 95.872-206.528 215.36-209.664l6.208-0.064h324.928zM497.216 128c122.368 0 221.568 93.888 221.568 209.728s-99.2 209.792-221.568 209.792c-122.304 0-221.44-93.952-221.44-209.728C275.712 221.952 374.848 128 497.152 128z m0 83.904c-73.408 0-132.864 56.32-132.864 125.888 0 69.504 59.52 125.824 132.864 125.824 73.408 0 132.928-56.32 132.928-125.824 0-69.504-59.52-125.888-132.928-125.888z" fill="#fff" p-id="1360"></path></svg>
src/assets/svgs/bpm/transactor.svg
New file
@@ -0,0 +1 @@
<svg t="1739406626368" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1300" width="200" height="200"><path d="M803.221 925.573H224.356c-68.568 0-124.352-55.784-124.352-124.353V222.356c0-68.568 55.784-124.352 124.352-124.352h355.311v64H224.356c-33.278 0-60.352 27.074-60.352 60.352V801.22c0 33.278 27.074 60.353 60.352 60.353H803.22c33.278 0 60.353-27.074 60.353-60.353V448.208h64V801.22c0 68.569-55.784 124.353-124.352 124.353z" fill="#ffffff" p-id="1301"></path><path d="M300.357 756.916l35.024-195.867L770.117 84.404c10.05-11.02 25.015-18.052 41.058-19.293 16.017-1.247 31.987 3.379 43.841 12.667l83.662 65.549c21.643 16.956 24.254 45.964 5.942 66.038l-437.613 479.8-206.65 67.751z m104.994-170.751l-13.14 73.487 69.671-22.842 415.465-455.517-59.909-46.939-412.087 451.811z" fill="#ffffff" p-id="1302"></path><path d="M732.25 220.897l41.144-49.023 81.151 68.11-41.145 49.023z" fill="#ffffff" p-id="1303"></path></svg>
src/assets/svgs/icon.svg
New file
@@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.147.062a13 13 0 014.94.945c1.55.63 2.907 1.526 4.069 2.688a13.148 13.148 0 012.761 4.069c.678 1.55 1.017 3.245 1.017 5.086v102.3c0 3.681-1.187 6.733-3.56 9.155-2.373 2.422-5.352 3.633-8.937 3.633H12.992c-3.875 0-7-1.26-9.373-3.779-2.373-2.518-3.56-5.667-3.56-9.445V12.704c0-3.39 1.163-6.345 3.488-8.863C5.872 1.32 8.972.062 12.847.062h102.3zM81.434 109.047c1.744 0 3.003-.412 3.778-1.235.775-.824 1.163-1.914 1.163-3.27 0-1.26-.388-2.325-1.163-3.197-.775-.872-2.034-1.307-3.778-1.307H72.57c.097-.194.145-.485.145-.872V27.09h9.01c1.743 0 2.954-.436 3.633-1.308.678-.872 1.017-1.938 1.017-3.197 0-1.26-.34-2.325-1.017-3.197-.679-.872-1.89-1.308-3.633-1.308H46.268c-1.743 0-2.954.436-3.632 1.308-.678.872-1.018 1.938-1.018 3.197 0 1.26.34 2.325 1.018 3.197.678.872 1.889 1.308 3.632 1.308h8.138v72.075c0 .193.024.339.073.436.048.096.072.242.072.436H46.56c-1.744 0-3.003.435-3.778 1.307-.775.872-1.163 1.938-1.163 3.197 0 1.356.388 2.446 1.163 3.27.775.823 2.034 1.235 3.778 1.235h34.875z"/></svg>
src/assets/svgs/iot/card-fill.svg
New file
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" class="design-iconfont" viewBox="0 0 12 12"><path fill="url(#a)" fill-rule="evenodd" d="M1 0a1 1 0 0 0-1 1v3.538a1 1 0 0 0 1 1h3.538a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1H1Zm0 6.462a1 1 0 0 0-1 1V11a1 1 0 0 0 1 1h3.538a1 1 0 0 0 1-1V7.462a1 1 0 0 0-1-1H1ZM6.462 1a1 1 0 0 1 1-1H11a1 1 0 0 1 1 1v3.538a1 1 0 0 1-1 1H7.462a1 1 0 0 1-1-1V1Zm1 5.462a1 1 0 0 0-1 1V11a1 1 0 0 0 1 1H11a1 1 0 0 0 1-1V7.462a1 1 0 0 0-1-1H7.462Z" clip-rule="evenodd"/><defs><linearGradient id="a" x1="0" x2="12" y1="0" y2="12" gradientUnits="userSpaceOnUse"><stop stop-color="#1B3149"/><stop offset="1" stop-color="#717D8A"/></linearGradient></defs></svg>
src/assets/svgs/iot/cube.svg
New file
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 12 12"><g clip-path="url(#a)"><path fill="url(#b)" fill-rule="evenodd" d="M6.958.42C6.444.216 5.61.216 5.098.42L1.15 1.975c-.77.304-.77.797 0 1.1l3.947 1.558c.514.202 1.347.202 1.86 0l3.948-1.557c.77-.304.77-.797 0-1.1L6.958.418ZM4.715 11.788a.857.857 0 0 0 .3.056c.383 0 .671-.295.671-.7V6.404c0-.49-.364-1.007-.817-1.177L1.09 3.805a.808.808 0 0 0-.284-.056c-.353 0-.581.275-.581.7V9.19c0 .508.33 1.014.763 1.177l3.726 1.422Zm2.229-.024h-.02l.073.003c.074.004.154.009.227-.019L11 10.367c.45-.168.83-.686.83-1.177V4.45c0-.413-.29-.7-.673-.7a.965.965 0 0 0-.317.055l-3.72 1.422c-.44.165-.75.67-.75 1.177v4.74c0 .42.218.621.575.621Z" clip-rule="evenodd"/></g><defs><linearGradient id="b" x1=".226" x2="11.803" y1=".267" y2="11.871" gradientUnits="userSpaceOnUse"><stop stop-color="#1B3149"/><stop offset="1" stop-color="#717D8A"/></linearGradient><clipPath id="a"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg>
src/assets/svgs/login-bg.svg
New file
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="5760" height="3040"><image width="5760" height="3040" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAFoAAAAvgAQMAAAC1QKagAAAABGdBTUEAALGPC/xhBQAAACBjSFJN AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABlBMVEUsNEr///91v/yPAAAA AWJLR0QB/wIt3gAAAAd0SU1FB+YBBQYyN1c3BnEAAAhjSURBVHja7cExAQAAAMKg9U9tDB+gAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAACAtwFzzwABY3VrRQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMi0wMS0wNVQwNjo1 MDo1MyswMDowMCfNlVoAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjItMDEtMDVUMDY6NTA6NTQrMDA6 MDCTNxNoAAAAAElFTkSuQmCC"/></svg>
src/assets/svgs/login-box-bg.svg
New file
@@ -0,0 +1 @@
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 700 700" xml:space="preserve" enable-background="new 0 0 700 700"><style>.st0{fill:#e5e6eb}.st1{fill:#fff}.st2{fill:#84a9ff}.st3{fill:#050f64}.st4{fill:#155bcd}.st5{fill:#ffbd00}.st6{fill:#ff654f}.st9{fill:#f5bdc8}.st10{fill:#ea8096}.st11{opacity:0}.st13{fill:#dca000}</style><path class="st0" d="M101.8 176.7c21.4-19.8 48.8-33.2 77.8-37.2 92.4-12.6 158.2 78.1 240.3 104.9 40.8 13.3 85.4 12.6 125.4 28 68.5 26.2 131.4 117.8 101 191.6-23.7 57.5-79.6 71.8-134.6 54-33.5-10.9-64.1-29.4-97.6-40.5-38.1-12.6-78.7-15.1-118.9-16.7s-80.6-2.4-119.6-12-77-28.9-101.2-60.9C40.8 343.4 48 260.8 73.1 213.7c7.4-13.9 17.2-26.3 28.7-37z"/><path class="st1" d="M82 257.1c5.7-23.2 18.9-44.7 37.3-60.4l1.7-1.5 1.8-1.4 1.8-1.4 1.8-1.3c.6-.4 1.2-.9 1.8-1.3l1.9-1.3c.6-.4 1.2-.9 1.9-1.3l1.9-1.2c5.1-3.2 10.5-6 16.1-8.4 11.1-4.7 23-7.8 35.1-9 12.1-1.1 24.3-.5 36.1 1.5 5.9 1 11.8 2.4 17.6 4 .7.2 1.5.4 2.2.6l2.2.7 2.2.7 2.1.7 2.1.7 2.1.8 2.1.8 2.1.8c5.6 2.2 11.1 4.6 16.5 7.2 5.4 2.6 10.7 5.4 15.9 8.3 10.4 5.9 20.6 12.2 30.5 18.8-10.4-5.9-20.7-11.8-31.4-17.2-5.3-2.7-10.7-5.3-16.1-7.7-5.4-2.4-10.9-4.7-16.5-6.7l-2.1-.8-2.1-.7-2.1-.7-2.1-.7-2.1-.7-2.1-.6-2.1-.6-2.1-.6c-5.7-1.5-11.5-2.8-17.3-3.7-11.6-1.9-23.5-2.5-35.2-1.3-11.7 1.1-23.2 4-34.1 8.5-5.4 2.2-10.7 4.9-15.8 7.9l-1.9 1.1c-.6.4-1.2.8-1.9 1.2l-1.8 1.2c-.6.4-1.2.8-1.8 1.3l-1.8 1.3-1.8 1.3-1.8 1.3-1.7 1.4c-18.2 15.2-32 35.7-39.1 58.4z"/><path class="st2" d="M183.1 543.2c-.3 1.2-.5 1.8-.5 1.8-.7-.5-1.4-.9-2.1-1.4-120.8-82.8-72.6-232.2-72.6-232.2 115.7 67.3 80.1 213.8 75.2 231.8z"/><path class="st3" d="M183.1 543.2c-.3 1.2-.5 1.8-.5 1.8-.7-.5-1.4-.9-2.1-1.4-10.1-29.9-20.1-59.8-29.8-89.8-5-15.5-10-31.1-14.8-46.7l-3.6-11.7-3.5-11.7c-1.2-3.9-2.2-7.8-3.4-11.8-.6-2-1.1-3.9-1.6-5.9l-1.6-5.9 1.6 5.9c.5 2 1.1 3.9 1.7 5.9 1.2 3.9 2.3 7.8 3.5 11.7l3.6 11.7 3.7 11.7c5 15.5 10.2 31 15.4 46.5 10.4 30 20.8 59.9 31.4 89.7zM137.9 384.9c-.1 0-.2 0-.4-.1-.3-.1-.4-.5-.2-.8 3.7-7.2 6-15.3 6.7-23.4 0-.3.3-.5.6-.5s.5.3.5.6c-.7 8.2-3.1 16.5-6.9 23.8 0 .3-.2.4-.3.4zM154 430.5h-.3c-.3-.1-.4-.5-.3-.7 3.4-8.3 7.6-16.4 12.3-24.1.2-.3.5-.3.8-.2.3.2.3.5.2.8-4.7 7.6-8.8 15.6-12.2 23.9-.1.1-.3.3-.5.3zM137.4 440.3h-.3c-9.5-3.9-18.3-9.3-26.1-16.1-.2-.2-.3-.6-.1-.8.2-.2.6-.3.8-.1 7.7 6.7 16.3 12 25.7 15.9.3.1.4.5.3.7 0 .2-.1.3-.3.4zM125.9 390.5c-.2.1-.4.1-.6-.1l-19.2-15c-.2-.2-.3-.6-.1-.8.2-.2.6-.3.8-.1l19.2 15c.2.2.3.6.1.8 0 .1-.1.2-.2.2zM170.7 478.4h-.3c-.3-.1-.4-.5-.3-.7l10.1-23.5c.1-.3.5-.4.7-.3.3.1.4.5.3.7l-10.1 23.5c0 .1-.2.3-.4.3zM151.6 481.6h-.3l-24.3-10c-.3-.1-.4-.5-.3-.7.1-.3.5-.4.7-.3l24.3 10c.3.1.4.5.3.7-.1.1-.3.3-.4.3z"/><path class="st4" d="M182.3 543.2c.3 1.2.4 1.9.4 1.9-.8-.1-1.7-.2-2.5-.3C35 525 11 369.8 11 369.8c133.5 8.2 167.5 155.1 171.3 173.4z"/><path class="st1" d="M182.3 543.2c.3 1.2.4 1.9.4 1.9-.8-.1-1.7-.2-2.5-.3-22.5-22.1-44.8-44.4-66.9-66.8-11.5-11.6-22.9-23.3-34.2-35.1l-8.5-8.8-8.4-8.9c-2.8-3-5.5-6-8.3-9-1.4-1.5-2.7-3-4.1-4.6l-4-4.6 4.1 4.5c1.4 1.5 2.7 3 4.1 4.5 2.8 3 5.6 6 8.4 8.9l8.5 8.8 8.6 8.7c11.5 11.6 23 23.1 34.7 34.6 22.5 22.2 45.2 44.3 68.1 66.2zM70.7 422.1c-.1.1-.2.1-.3.1-.3 0-.6-.3-.6-.6.1-8.1-1.5-16.4-4.5-23.9-.1-.3 0-.6.3-.7.3-.1.6 0 .7.3 3 7.7 4.6 16.1 4.6 24.4 0 .1-.1.3-.2.4zM105.6 455.5c-.1.1-.2.1-.3.1-.3 0-.6-.2-.6-.5-.7-9-.6-18.1.2-27 0-.3.3-.5.6-.5s.5.3.5.6c-.8 8.9-.9 17.9-.2 26.8.1.2 0 .4-.2.5zM95.2 471.7c-.1.1-.2.1-.3.1-10.3.8-20.5-.1-30.5-2.7-.3-.1-.5-.4-.4-.7.1-.3.4-.5.7-.4 9.9 2.5 20 3.4 30.1 2.6.3 0 .6.2.6.5 0 .4-.1.5-.2.6zM62.6 432.4c-.1.1-.3.2-.5.2l-23.9-4.8c-.3-.1-.5-.4-.4-.7.1-.3.4-.5.7-.4l23.9 4.8c.3.1.5.4.4.7-.1.1-.1.2-.2.2zM142.1 490.8c-.1.1-.2.1-.3.1-.3 0-.6-.2-.6-.5l-1.5-25.5c0-.3.2-.6.5-.6s.6.2.6.5l1.5 25.5c0 .2-.1.4-.2.5zM126.4 502.3c-.1.1-.2.1-.3.1l-26.2 2c-.3 0-.6-.2-.6-.5s.2-.6.5-.6l26.2-2c.3 0 .6.2.6.5 0 .2-.1.4-.2.5z"/><g><path class="st5" d="M259.6 503.3c1.2.5 1.8.7 1.8.7-.5.7-1.1 1.3-1.7 1.9C164 616.8 20.9 552.3 20.9 552.3c79.7-107.4 221.4-55.9 238.7-49z"/><path class="st1" d="M259.6 503.3c1.2.5 1.8.7 1.8.7-.5.7-1.1 1.3-1.7 1.9-30.8 6.8-61.6 13.3-92.5 19.7-16 3.3-32 6.5-48 9.6l-12 2.3-12 2.2c-4 .7-8 1.4-12.1 2-2 .4-4 .6-6 .9l-6.1.9 6-1c2-.3 4-.6 6-1 4-.7 8-1.4 12-2.2l12-2.3 12-2.4c16-3.3 31.9-6.7 47.9-10.2 31-6.9 61.9-13.9 92.7-21.1zM97.3 530.8c0 .1 0 .2-.1.3-.2.3-.5.3-.8.2-6.8-4.5-14.6-7.7-22.5-9.3-.3-.1-.5-.4-.4-.7.1-.3.4-.5.7-.4 8.1 1.6 16 4.9 22.9 9.5.1 0 .1.2.2.4zM144.3 519.7c0 .1 0 .2-.1.3-.2.3-.5.4-.8.2-7.9-4.3-15.5-9.4-22.5-14.9-.2-.2-.3-.6-.1-.8.2-.2.6-.3.8-.1 7 5.5 14.6 10.5 22.4 14.8.2.1.3.3.3.5zM152.2 537.3c0 .1 0 .2-.1.3-4.9 9-11.3 17.2-18.8 24.1-.2.2-.6.2-.8 0-.2-.2-.2-.6 0-.8 7.5-6.9 13.7-14.9 18.6-23.8.2-.3.5-.4.8-.2.2.1.3.3.3.4zM101.5 543.2c.1.2 0 .4-.1.6l-17 17.5c-.2.2-.6.2-.8 0-.2-.2-.2-.6 0-.8l17-17.5c.2-.2.6-.2.8 0 .1 0 .1.1.1.2zM193.8 508.4c0 .1 0 .2-.1.3-.2.3-.5.4-.8.2l-22.2-12.7c-.3-.2-.4-.5-.2-.8.2-.3.5-.4.8-.2l22.2 12.7c.2.2.3.3.3.5zM194.9 527.8c0 .1 0 .2-.1.3l-12.7 23.1c-.2.3-.5.4-.8.2-.3-.2-.4-.5-.2-.8l12.7-23.1c.2-.3.5-.4.8-.2.1.2.3.3.3.5z"/></g><g><path class="st2" d="M608.8 430.3c-1 .2-2.4-.3-4.4-1.4-3.2-1.9-8.3-4.9-10.2-6.1 3 6.3 5.8 12.7 8.3 19.2 4.5-1 7.9-.1 10.1 1.4 2.2 1.5 3.3 3.6 3.3 4.6-.1 2-1.8 2.4-4.9.3-1.6-1.1-3.7-2.6-5.5-3.9-1.3-.9-2.3-1.7-2.8-2 .8 2 1.5 4 2.2 6h.2c1.3.2 3.1 3.1 3.9 4.1 1.7 2.3 3 4.9 3.2 7.8.1 1.2-.1 2.6-1.2 3.2-1.2.6-2.6-.3-3.5-1.3-2.5-2.8-4-6.5-4.1-10.2 0-1-.1-3.3 1.2-3.5-.8-2-1.5-3.9-2.3-5.9-.1.6-.4 1.9-.7 3.4-.5 2.1-1.1 4.7-1.7 6.4-1.1 3.5-2.7 4.1-4 2.8-.7-.7-1.1-2.7-.3-5.2.8-2.4 2.6-5.3 6.6-7.7-2.7-6.4-5.6-12.7-8.8-18.9-.1.8-.3 2.2-.5 3.7-.3 2.6-.9 5.7-1.4 7.8-.5 2.1-1.2 3.4-2 4-.8.6-1.7.4-2.5-.3-.9-.7-1.6-3.1-.9-6.2.6-2.9 2.6-6.5 7-9.6-3.5-6.6-7.2-13.1-11.2-19.4v.3c0 1 0 2.5-.1 4.1-.1 1.6-.2 3.4-.3 5-.1 1.7-.4 3.3-.5 4.6-.8 5.3-3 6.6-5.2 5-1.2-.8-2.1-3.7-1.7-7.4.2-1.9.9-4 2.2-6.2 1.1-2 2.8-4.2 5.2-6.3-3.8-5.8-7.8-11.5-12-17 .1 1.2.2 2.8.2 4.6.1 1.8.1 3.9.1 5.8v2.8c0 .9-.1 1.8-.1 2.5-.4 6.1-2.8 7.8-5.5 6.2-.7-.4-1.4-1.4-1.9-2.8s-.8-3.3-.7-5.4c.1-2.2.7-4.6 1.9-7.3 1.1-2.4 2.8-5 5.2-7.6-4.2-5.4-8.5-10.5-13.1-15.5l2-1.8c4.5 5.2 8.8 10.5 12.9 16 3.1-1.6 6.1-2.5 8.8-2.7 3-.3 5.6.1 7.8.9s4 1.9 5.3 3.1c1.2 1.2 2 2.4 2.2 3.3.7 3.5-2 4.7-8 2.5-3.1-1.2-7.3-2.8-10.7-4.2-1.7-.6-3.3-1.2-4.4-1.6 4.1 5.6 8 11.5 11.6 17.4 2.9-1.2 5.6-1.7 8-1.8 2.6 0 4.8.5 6.7 1.4 3.8 1.7 5.8 4.5 6 6 .3 3.1-2 4-7.1 1.6-2.6-1.3-6.1-3-9-4.4-1.4-.7-2.8-1.3-3.7-1.8-.1 0-.1-.1-.2-.1 3.9 6.4 7.5 13 10.8 19.8 5.1-1.6 9.2-.9 12 .7 2.8 1.6 4.3 4 4.4 5.2-.7 1.1-1.2 1.8-2.2 2z"/></g><g><path class="st2" d="M552.1 373.7c-.5 1.1-.8 1.7-.8 1.7l-1.8-1.8c-105.3-101.8-32.8-241.1-32.8-241.1 102.7 85.7 43.2 224.2 35.4 241.2z"/><path class="st1" d="M552.1 373.7c-.5 1.1-.8 1.7-.8 1.7l-1.8-1.8c-5-31.1-9.8-62.3-14.4-93.5-2.4-16.1-4.7-32.3-6.8-48.5l-1.6-12.1-1.5-12.2c-.5-4.1-.9-8.1-1.4-12.2-.2-2-.4-4.1-.6-6.1l-.5-6.1.6 6.1c.2 2 .4 4.1.7 6.1.5 4 1 8.1 1.5 12.1l1.6 12.1 1.7 12.1c2.4 16.1 4.9 32.3 7.5 48.4 5.1 31.4 10.3 62.7 15.8 93.9zM533.9 210c-.1 0-.2 0-.3-.1-.3-.2-.3-.5-.1-.8 4.9-6.5 8.5-14.1 10.6-21.9.1-.3.4-.5.7-.4.3.1.5.4.4.7-2.1 8-5.8 15.7-10.7 22.3-.3.1-.5.2-.6.2zM542.2 257.6c-.1 0-.2 0-.3-.1-.3-.2-.3-.5-.2-.8 4.8-7.6 10.2-14.9 16.2-21.7.2-.2.6-.3.8-.1.2.2.3.6.1.8-5.9 6.7-11.3 13.9-16.1 21.5-.1.3-.3.4-.5.4zM524.2 264.5c-.1 0-.2 0-.3-.1-8.7-5.4-16.5-12.2-23-20.2-.2-.2-.2-.6.1-.8.2-.2.6-.2.8.1 6.4 7.9 14.1 14.6 22.7 19.9.3.2.3.5.2.8-.2.2-.4.3-.5.3zM521.2 213.5c-.2 0-.4 0-.5-.2l-16.5-18c-.2-.2-.2-.6 0-.8.2-.2.6-.2.8 0l16.5 18c.2.2.2.6 0 .8-.1.2-.2.2-.3.2zM550.7 307.7c-.1 0-.2 0-.3-.1-.3-.2-.3-.5-.2-.8l13.9-21.5c.2-.3.5-.3.8-.2.3.2.3.5.2.8l-13.9 21.5c-.1.2-.3.3-.5.3zM531.2 307.6c-.1 0-.2 0-.3-.1l-22.3-13.9c-.3-.2-.3-.5-.2-.8.2-.3.5-.3.8-.2l22.3 13.9c.3.2.3.5.2.8-.1.2-.3.3-.5.3z"/><g><path class="st4" d="M526.6 382.8c-1 .7-1.6 1-1.6 1-.2-.8-.4-1.6-.6-2.5-35-142.2 100.5-221.5 100.5-221.5 41.5 127.2-82.7 212.8-98.3 223z"/><path class="st3" d="M526.6 382.8c-1 .7-1.6 1-1.6 1-.2-.8-.4-1.6-.6-2.5 12.3-29 24.8-58 37.5-86.8 6.6-14.9 13.3-29.8 20-44.7l5.1-11.1 5.2-11.1c1.7-3.7 3.6-7.3 5.3-11 .9-1.8 1.8-3.6 2.7-5.5l2.8-5.4-2.7 5.5c-.9 1.8-1.8 3.6-2.7 5.5-1.7 3.7-3.5 7.4-5.2 11.1l-5.1 11.1-5 11.2c-6.6 14.9-13 29.9-19.4 44.9-12.2 29.2-24.3 58.5-36.3 87.8zM598.2 234.5c-.1-.1-.2-.2-.2-.3-.1-.3 0-.6.3-.7 7.6-2.9 14.7-7.4 20.6-13 .2-.2.6-.2.8 0 .2.2.2.6 0 .8-6 5.7-13.3 10.2-21 13.2-.1.1-.3.1-.5 0zM580 279.3c-.1-.1-.2-.1-.2-.2-.1-.3 0-.6.3-.8 8.1-3.9 16.6-7.2 25.2-9.7.3-.1.6.1.7.4.1.3-.1.6-.4.7-8.6 2.5-17 5.8-25 9.7-.3 0-.5 0-.6-.1zM561 275.5c-.1-.1-.2-.1-.2-.3-4.5-9.3-7.4-19.1-8.7-29.3 0-.3.2-.6.5-.6s.6.2.6.5c1.3 10.1 4.2 19.8 8.6 29 .1.3 0 .6-.3.8-.1 0-.3 0-.5-.1zM585.6 230.8c-.2-.1-.3-.2-.4-.4l-4.4-24c-.1-.3.1-.6.5-.7.3-.1.6.1.7.5l4.4 24c.1.3-.1.6-.5.7-.1-.1-.2-.1-.3-.1zM560.5 326.2c-.1-.1-.2-.1-.2-.2-.1-.3 0-.6.3-.8l23.2-10.8c.3-.1.6 0 .8.3.1.3 0 .6-.3.8l-23.2 10.8c-.2 0-.4 0-.6-.1zM544.1 315.8c-.1-.1-.2-.1-.2-.2l-11.5-23.7c-.1-.3 0-.6.3-.8.3-.1.6 0 .8.3l11.5 23.7c.1.3 0 .6-.3.8-.2 0-.5 0-.6-.1z"/></g><g><path class="st5" d="M482.2 415.1c-1.2 0-1.9-.1-1.9-.1l.9-2.4C532.4 275.4 689 286.2 689 286.2c-37.4 128.5-188.2 129.3-206.8 128.9z"/><path class="st1" d="M482.2 415.1c-1.2 0-1.9-.1-1.9-.1l.9-2.4c26.5-17 53.2-33.9 79.9-50.6 13.9-8.6 27.8-17.2 41.7-25.6l10.5-6.3 10.5-6.2c3.5-2.1 7.1-4.1 10.6-6.1 1.8-1 3.6-2 5.3-3l5.4-2.9-5.3 3c-1.8 1-3.6 2-5.3 3-3.5 2.1-7 4.1-10.5 6.2l-10.5 6.4-10.4 6.4c-13.8 8.6-27.6 17.4-41.4 26.2-26.6 17.2-53.1 34.5-79.5 52zM624.9 333c0-.1-.1-.2 0-.4.1-.3.4-.5.7-.4 7.9 1.8 16.3 2.2 24.3.9.3 0 .6.2.7.5 0 .3-.2.6-.5.7-8.2 1.3-16.7 1-24.8-.9l-.4-.4zM584.6 359.7c0-.1-.1-.2 0-.3 0-.3.3-.5.6-.5 8.9 1.3 17.8 3.4 26.3 6.2.3.1.5.4.4.7-.1.3-.4.5-.7.4-8.5-2.7-17.3-4.8-26.1-6.1-.3-.1-.4-.3-.5-.4zM571.1 345.9c-.1-.1-.1-.2-.1-.3 1.5-10.2 4.6-20 9.3-29.2.1-.3.5-.4.8-.2.3.1.4.5.2.8-4.6 9.1-7.7 18.7-9.2 28.8 0 .3-.3.5-.6.5-.2-.2-.4-.3-.4-.4zM616.6 322.8c-.1-.2-.1-.4-.1-.6l9.9-22.3c.1-.3.5-.4.8-.3.3.1.4.5.3.8l-9.9 22.3c-.1.3-.5.4-.8.3l-.2-.2zM542.1 387.4c0-.1-.1-.2 0-.3.1-.3.3-.5.7-.5l25.2 4.2c.3.1.5.3.5.7-.1.3-.3.5-.7.5l-25.2-4.2c-.3-.1-.4-.2-.5-.4zM534.4 369.6c0-.1-.1-.2 0-.3l3.9-26c0-.3.3-.5.6-.5s.5.3.5.6l-3.9 26c0 .3-.3.5-.6.5s-.4-.2-.5-.3z"/></g></g><g><path class="st2" d="M445 229c-.1 1 .4 2.4 1.6 4.3 2.1 3.1 5.4 8 6.6 9.9-6.4-2.7-13-5.1-19.6-7.3.8-4.5-.3-7.9-1.9-10-1.6-2.2-3.7-3.1-4.8-3-2 .2-2.3 1.9 0 4.9 1.1 1.5 2.8 3.5 4.2 5.3 1 1.2 1.8 2.2 2.2 2.7-2-.7-4.1-1.3-6.1-1.9v-.2c-.3-1.3-3.3-3-4.3-3.7-2.4-1.6-5.1-2.7-7.9-2.8-1.2 0-2.6.3-3.1 1.4-.5 1.2.5 2.6 1.5 3.4 2.9 2.4 6.7 3.6 10.4 3.5 1 0 3.3 0 3.5-1.4 2 .7 4 1.3 6 2-.6.2-1.9.5-3.4.9-2.1.6-4.6 1.4-6.3 2-3.4 1.3-4 2.9-2.6 4.2.7.6 2.8 1 5.2 0 2.4-.9 5.2-2.9 7.3-7 6.6 2.3 13 4.9 19.3 7.7-.8.1-2.2.4-3.7.7-2.5.5-5.6 1.2-7.7 1.8-2.1.6-3.3 1.4-3.9 2.2-.5.8-.4 1.7.4 2.5s3.2 1.4 6.2.5c2.9-.8 6.3-2.9 9.3-7.5 6.8 3.1 13.5 6.5 20 10.2h-.3c-1 .1-2.5.2-4.1.4-1.6.2-3.3.4-5 .6-1.7.2-3.3.5-4.6.8-5.2 1.1-6.4 3.3-4.7 5.5.9 1.1 3.8 1.9 7.5 1.3 1.9-.3 4-1.1 6.1-2.5 2-1.3 4-3 6-5.5 6 3.4 11.9 7.1 17.7 11.1h-4.6c-1.8 0-3.9.1-5.8.2-1 .1-1.9.1-2.8.2-.9.1-1.7.2-2.5.3-6.1.8-7.6 3.2-5.9 5.8.4.7 1.5 1.3 2.9 1.7 1.5.4 3.3.7 5.5.4 2.2-.3 4.6-.9 7.2-2.3 2.3-1.2 4.8-3 7.3-5.6 5.6 3.9 11 8 16.2 12.3l1.7-2.1c-5.4-4.2-11-8.2-16.7-12 1.4-3.2 2.1-6.2 2.2-8.9.1-3-.4-5.6-1.3-7.7-.9-2.1-2.1-3.9-3.4-5.1-1.3-1.2-2.5-1.9-3.4-2-3.5-.5-4.6 2.2-2 8.1 1.4 3 3.2 7.1 4.8 10.5.7 1.7 1.4 3.2 1.9 4.3-5.9-3.8-11.9-7.4-18-10.7 1-3 1.4-5.7 1.3-8.1-.1-2.6-.8-4.8-1.7-6.6-1.9-3.7-4.8-5.5-6.3-5.6-3.1-.2-3.9 2.3-1.2 7.2 1.4 2.5 3.3 5.9 4.9 8.8.8 1.4 1.5 2.7 2 3.6 0 .1.1.1.1.2-6.6-3.5-13.4-6.8-20.3-9.7 1.3-5.2.4-9.2-1.3-11.9-1.8-2.8-4.2-4.1-5.4-4.1-1.6.3-2.3.8-2.4 1.8z"/></g><g><path class="st2" d="M100.2 255.8c1-.1 2.4.5 4.3 1.8 3 2.2 7.8 5.7 9.6 7-2.4-6.5-4.6-13.2-6.4-19.9-4.6.6-7.9-.6-9.9-2.3-2.1-1.7-3-3.9-2.8-4.9.3-2 2-2.2 4.9.2 1.5 1.2 3.4 3 5.1 4.4 1.2 1 2.2 1.9 2.6 2.3-.6-2.1-1.1-4.1-1.6-6.2h-.2c-1.3-.3-2.8-3.4-3.5-4.5-1.5-2.4-2.5-5.2-2.5-8 0-1.2.4-2.6 1.5-3 1.3-.5 2.6.6 3.4 1.6 2.3 3 3.3 6.8 3.1 10.5-.1 1-.2 3.3-1.5 3.4.6 2 1.2 4.1 1.8 6.1.2-.6.6-1.9 1-3.4.7-2.1 1.6-4.5 2.3-6.2 1.4-3.4 3.1-3.9 4.3-2.4.6.7.8 2.8-.2 5.2-1 2.4-3.1 5-7.3 7 2 6.6 4.4 13.2 6.9 19.6.2-.8.5-2.2.8-3.7.6-2.5 1.4-5.6 2.1-7.6.7-2.1 1.5-3.3 2.4-3.8.9-.5 1.7-.3 2.5.5s1.2 3.3.3 6.2c-.9 2.8-3.2 6.2-7.8 8.9 2.8 6.9 5.9 13.8 9.3 20.4v-.3c.1-1 .3-2.4.5-4s.5-3.3.8-5c.3-1.7.7-3.3 1-4.6 1.3-5.2 3.6-6.3 5.7-4.5 1.1.9 1.8 3.9 1 7.5-.4 1.8-1.3 3.9-2.8 6-1.3 1.9-3.2 3.9-5.8 5.8 3.2 6.2 6.6 12.2 10.3 18.1 0-1.2.1-2.8.2-4.6.1-1.8.3-3.9.5-5.8.1-1 .2-1.9.3-2.8.1-.9.3-1.7.4-2.5 1-6 3.5-7.5 6.1-5.6.6.5 1.2 1.5 1.6 3 .3 1.5.5 3.3.2 5.5s-1.1 4.5-2.6 7.1c-1.3 2.3-3.2 4.7-5.9 7 3.6 5.7 7.5 11.3 11.6 16.7l-2.2 1.6c-4-5.6-7.8-11.3-11.3-17.2-3.3 1.3-6.3 1.9-9 1.9-3 0-5.6-.6-7.7-1.6-2.1-1-3.8-2.3-4.9-3.6-1.1-1.3-1.8-2.6-1.8-3.4-.3-3.5 2.4-4.5 8.2-1.7 2.9 1.5 7 3.5 10.3 5.2 1.7.8 3.1 1.5 4.2 2-3.6-6-6.9-12.2-9.9-18.5-3 .9-5.7 1.2-8.1 1-2.6-.2-4.7-1-6.5-2-3.6-2-5.3-5-5.4-6.6 0-3.1 2.4-3.8 7.2-.9 2.4 1.5 5.8 3.5 8.6 5.2 1.4.9 2.6 1.6 3.5 2.1.1 0 .1.1.2.1-3.3-6.8-6.2-13.7-8.8-20.7-5.3 1.1-9.2 0-11.9-1.8-2.7-1.9-3.9-4.4-3.8-5.6-.1-.9.5-1.6 1.5-1.7z"/></g><g><path class="st4" d="M106.8 558.3c0 13.1 8.1 23.7 18.2 23.7h455c10.1 0 18.2-10.6 18.2-23.7H106.8z"/><path class="st2" d="M155.4 290.9H549.6V538.5H155.4z"/><path class="st3" d="M556.6 264.8h-408c-7.6 0-13.8 6.2-13.8 13.8V540c0 7.6 6.2 13.8 13.8 13.8h408c7.6 0 13.8-6.2 13.8-13.8V278.6c0-7.7-6.2-13.8-13.8-13.8z"/><path class="st1" d="M155.4 285.5H549.6V533.1H155.4z"/><path class="st0" d="M295.7 558.3L196.6 558.3 196.9 553.9 197.3 548.4 294.9 548.4zM508.6 558.3L409.4 558.3 409.8 553.9 410.2 548.4 507.8 548.4z"/></g><g><path class="st0" d="M188 451.7H222.4V455.59999999999997H188zM235 451.7H269.4V455.59999999999997H235zM328.6 451.7H353.5V455.59999999999997H328.6zM374.8 451.7H413.5V455.59999999999997H374.8zM342.3 465.1H359.90000000000003V469H342.3zM342.3 475.3H359.90000000000003V479.2H342.3zM342.3 485.6H359.90000000000003V489.5H342.3zM342.3 495.8H359.90000000000003V499.7H342.3z"/><path class="st6" d="M209.7 465.1H222.39999999999998V469H209.7z"/><path class="st2" d="M209.7 475.3H222.39999999999998V479.2H209.7z"/><path class="st4" d="M209.7 485.6H222.39999999999998V489.5H209.7z"/><path class="st5" d="M209.7 495.8H222.39999999999998V499.7H209.7z"/><path class="st0" d="M399.7 465.1H417.3V469H399.7zM399.7 475.3H417.3V479.2H399.7zM399.7 485.6H417.3V489.5H399.7zM399.7 495.8H417.3V499.7H399.7zM234.6 465.1H252.2V469H234.6zM234.6 475.3H260.7V479.2H234.6zM234.6 485.6H267.5V489.5H234.6zM234.6 495.8H249.7V499.7H234.6zM180.4 314.6H306V321.5H180.4z"/><path class="st4" d="M180.4 340.4H198.20000000000002V347.9H180.4zM216.1 340.4H233.9V347.9H216.1zM251.8 340.4H269.6V347.9H251.8zM287.5 340.4H305.3V347.9H287.5zM323.3 340.4H341.1V347.9H323.3zM359 340.4H376.8V347.9H359zM394.7 340.4H412.5V347.9H394.7z"/><g><path class="st0" d="M180.4 355.7H430.20000000000005V358H180.4z"/></g><g><path class="st0" d="M427.7 446.2H181v-90.4h-2v92.5h250.7v-92.5h-2v90.4z"/><path class="st0" d="M405.1 355.7H407.1V447.2H405.1zM382.4 355.7H384.5V447.2H382.4zM359.8 355.7H361.8V447.2H359.8zM337.2 355.7H339.2V447.2H337.2zM314.6 355.7H316.6V447.2H314.6zM292 355.7H294V447.2H292zM269.4 355.7H271.4V447.2H269.4zM246.8 355.7H248.8V447.2H246.8zM224.2 355.7H226.2V447.2H224.2zM201.6 355.7H203.7V447.2H201.6z"/><path class="st0" d="M179 355.7H429.7V357.7H179zM180 378.4H428.7V380.4H180zM180 401H428.7V403H180zM180 423.6H428.7V425.6H180z"/><g><path class="st2" d="M203.6 396.2H219.79999999999998V446.3H203.6zM248.8 385.8H265V446.3H248.8zM294.1 410.5H310.3V446.3H294.1zM339.3 373.7H355.5V446.29999999999995H339.3zM384.5 393.3H400.7V446.3H384.5z"/></g><g><path class="st6" d="M201.6 396.2H217.79999999999998V446.3H201.6zM246.8 385.8H263V446.3H246.8zM292 410.5H308.2V446.3H292zM337.2 373.7H353.4V446.29999999999995H337.2zM382.5 393.3H398.7V446.3H382.5z"/></g></g><g><path class="st0" d="M179 471.1H429.7V473.20000000000005H179z"/></g><g><path class="st0" d="M179 481.3H429.7V483.40000000000003H179z"/></g><g><path class="st0" d="M179 491.6H429.7V493.70000000000005H179z"/></g><g><path class="st0" d="M179 501.8H429.7V503.90000000000003H179z"/></g><g><path class="st6" d="M473.5 352.4c.9-5.5 5.4-9.8 10.9-10.6l-.2-5.1-.5-12.6c-14.7 1.2-26.4 12.7-27.9 27.2l12.6.8 5.1.3z"/><path class="st5" d="M491.1 366.7c-1.5.6-3.1.9-4.8.9-2.9 0-5.6-.9-7.7-2.5l-3.5 3.8-8.5 9.2c5.3 4.5 12.2 7.2 19.7 7.2 4.7 0 9.1-1 13-2.9l-5.9-11.1-2.3-4.6zM516.3 361.3l-12.4-2.1c-1.2 4.6-4 8.4-7.9 10.9l5.9 11.1 2.7 5.2c8.8-5.1 15.3-13.8 17.5-24.1l-5.8-1z"/><path class="st6" d="M468.2 354.9l-12.6-.8-5.9-.4v.9c0 10.1 4.1 19.3 10.7 25.9l4-4.3 8.5-9.2c-2.8-3.2-4.6-7.4-4.7-12.1z"/><path class="st4" d="M495.9 339.3l-2.4 4.6c3.5 2.3 5.7 6.3 5.7 10.8v.8l5.1.9 12.4 2.1c.2-1.3.2-2.5.2-3.8 0-11.3-6.1-21.2-15.2-26.5l-5.8 11.1zM487 336.6c2.3.1 4.4.6 6.4 1.4l5.8-11.2 2.7-5.2c-4.7-2.3-10-3.5-15.7-3.5l.2 5.9.6 12.6z"/></g><g><path class="st0" d="M446.7 407.2H525.1V411.09999999999997H446.7zM446.7 441.5H450.59999999999997V445.4H446.7zM454.4 441.5H525.1V445.4H454.4z"/><path class="st4" d="M446.7 456.1H450.59999999999997V460H446.7z"/><path class="st0" d="M454.4 456.1H525.1V460H454.4z"/><path d="M446.7 470.8H450.59999999999997V474.7H446.7z" style="fill:#6292ff"/><path class="st0" d="M454.4 470.8H525.1V474.7H454.4z"/><path d="M446.7 485.4H450.59999999999997V489.29999999999995H446.7z" style="fill:#da5544"/><path class="st0" d="M454.4 485.4H525.1V489.29999999999995H454.4z"/><path class="st5" d="M446.7 500H450.59999999999997V503.9H446.7z"/><path class="st0" d="M454.4 500H525.1V503.9H454.4zM446.7 417.7H525.1V430.7H446.7z"/></g></g><g><path class="st3" d="M522.8 556.7c.3-.3.7-.5 1.1-.6.4-.1.8-.1 1.3-.1 1-.1 2-.3 2.9-.8.5-.3.9-.6 1.4-.8l2.9.1c.4.4.7 1 .8 1.6.1.5.1 1.1.1 1.6v.6h-10.8v-.6c0-.4 0-.8.3-1z"/><path class="st9" d="M532.7 551.2L532.4 554.5 529.4 554.4 529.2 551.4z"/><path class="st3" d="M494 555.5c.3-.3.7-.4 1.1-.5.4 0 .8 0 1.3.1 1 .1 2.1-.1 3-.5.5-.2 1-.5 1.5-.6l2.9.4c.4.5.5 1.1.6 1.7.1.5 0 1.1-.1 1.6l-.1.6-10.7-1.2.1-.6c0-.4.1-.8.4-1z"/><path class="st4" d="M535.3 503.7c.6-11.4.5-27.5-2.6-36.6 0-.2-23.9 2-23.9 2l-5.6 22.9c-2 8.1-2.9 16.3-2.8 24.6l.3 34.4 4 .3 7.5-45.5c2.8-5.4 5.8-11.6 8.1-17.7l8.7 63.4 4-.2c0-.1 2.3-47.6 2.3-47.6z"/><path class="st9" d="M504.5 551.2L503.8 554.4 500.9 554 501 551z"/><path class="st10" d="M481.6 394.3c.7-.3 1.6 0 1.9.7 2 4 4.2 7.8 6.6 11.5 2.4 3.7 5 7.2 7.8 10.5s5.8 6.4 9.1 9.1c1.6 1.4 3.3 2.7 5 3.9.4.3.9.6 1.3.9l1.3.9c.9.6 1.8 1.1 2.7 1.7.3.2.5.4.8.6.2.2.4.5.6.7.3.5.6 1.1.7 1.8.3 1.3.1 2.7-.7 4-.8 1.3-2 2.1-3.3 2.3-.7.1-1.4.1-2.1 0-.3-.1-.7-.2-1-.3l-.9-.6c-.9-.7-1.8-1.5-2.7-2.3l-1.3-1.2c-.4-.4-.9-.8-1.3-1.2-1.7-1.6-3.4-3.4-4.9-5.1-3.1-3.5-6-7.3-8.5-11.2-2.5-3.9-4.7-8-6.6-12.2-1.9-4.2-3.6-8.4-5.1-12.7-.5-.7-.1-1.5.6-1.8z"/><path class="st2" d="M500.2 434.6l9.4 7.3c2.8 2.2 6.8 1.9 9-.9s1.8-7.2-1.1-9.4l-9.4-7.3-7.9 10.3z"/><path class="st2" d="M521.8 428.5c-9-.1-16 7.9-14.8 16.8l1.8 23.7c10 3.6 17.5 1.6 23.9-2l1.1-25.2c.7-7.1-4.9-13.2-12-13.3z"/><path class="st1" d="M531.8 433.5l-.2.2c1 1.4 1.7 3 2 4.7h.3c-.3-1.7-1-3.4-2.1-4.9zm-9.9 37.3v.3c2.2-.2 4.4-.8 6.6-1.7l-.1-.2c-2.1.8-4.2 1.3-6.5 1.6zm5.1-41.3c-1.6-.8-3.4-1.2-5.2-1.2h-.2c-4.3 0-8.5 1.9-11.3 5.2-1.7 1.9-2.8 4.2-3.3 6.6l.3.1c1.5-6.6 7.4-11.6 14.5-11.5 1.9 0 3.6.5 5.2 1.2v-.4zM508.6 466c-.1 0-.2.1-.3.1l.2 3 .2.1c2.2.8 4.5 1.4 6.6 1.7v-.3c-2.1-.3-4.2-.8-6.5-1.7l-.2-2.9zm-1.8-20.6l.9 12h.3l-.9-12h-.3z"/><path class="st3" d="M524 412.1s6.2 1.5 4.7 8.4c-1 4.6-4.4 7-9.2 7.8l4.5-16.2z"/><path class="st9" d="M517.5 423.7l.5 7.1c2 1.2 4 1.1 5.9-.3l-.5-7.1-5.9.3z"/><path class="st10" d="M517.6 424.6l.1 2.2c.9.5 1.9.7 3 .7h.2c1-.1 2-.5 2.7-1.2l-.1-2.1-5.9.4z"/><path class="st9" d="M514.6 415.4l.4 5.3.1 1.2c.3 2.9 2.7 5.1 5.6 5.1.3 0 .6 0 .9-.1.1 0 .2-.1.3-.1h.1c.4-.2.8-.4 1.1-.8.7-.8 1.1-1.6 1.5-2.5.3-.7.6-1.5.8-2.2.2-.9.4-1.8.2-2.8l-.4-4.6-9-.7-1.6 2.2z"/><path class="st3" d="M523.9 414s-10.3.6-8.2 9.7c0 0-3.2-6.5.1-10.9 3.6-4.8 8.5-3.2 10.2-.9 1.7 2.3 3 6.1-1.8 8.9-.1-.1 1.5-3.5-.3-6.8z"/><path class="st9" d="M523.7 419.5c.1 1.2 1.1 2.1 2.3 2 1.2-.1 2.1-1.1 2-2.3-.1-1.2-1.1-2.1-2.3-2-1.2.1-2.1 1.1-2 2.3z"/><g><path class="st3" d="M503.8 450.8l-7.4-8c4.5-4.2 6.9-9.8 6.9-15.9h10.9c0 9.1-3.8 17.8-10.4 23.9z"/><path class="st4" d="M514.2 427h-10.9c0-12-9.7-21.7-21.7-21.7-2.6 0-5.1.4-7.5 1.3l-3.8-10.2c3.6-1.3 7.4-2 11.3-2 18-.1 32.6 14.6 32.6 32.6z"/><path class="st2" d="M481.6 459.6c-18 0-32.6-14.6-32.6-32.6 0-13.6 8.6-25.9 21.4-30.6l3.8 10.2c-8.5 3.1-14.2 11.3-14.2 20.4 0 12 9.7 21.7 21.7 21.7 5.5 0 10.8-2.1 14.8-5.8l7.4 8c-6.1 5.6-14 8.7-22.3 8.7z"/></g><g><path class="st9" d="M471.1 455.3c0-.8.5-1.5 1.3-1.5 4.4-.5 8.8-1.1 13.1-2.1 4.3-.9 8.5-2.1 12.6-3.5 4.1-1.5 8-3.2 11.8-5.2 1.9-1 3.7-2.1 5.5-3.3.4-.3.9-.6 1.3-.9l1.3-.9c.8-.6 1.7-1.2 2.5-1.9.3-.2.6-.4.8-.5l.9-.3c.6-.1 1.3-.1 1.9 0 1.3.2 2.6.9 3.5 2.1.9 1.2 1.2 2.6 1 3.9-.1.7-.4 1.3-.8 1.9-.2.3-.4.6-.7.8-.3.3-.6.5-.9.7-1 .6-2.1 1.2-3.1 1.7l-1.6.8c-.5.3-1.1.5-1.6.8-2.1 1-4.3 2-6.5 2.8-4.4 1.7-9 3-13.5 3.9-4.6.9-9.2 1.5-13.7 1.9-4.6.3-9.1.4-13.7.3-.8 0-1.4-.7-1.4-1.5z"/><path class="st2" d="M515.5 452.5l10.1-6.2c3.1-1.9 4.3-5.7 2.4-8.8-1.9-3.1-6.1-4.2-9.1-2.3l-10.1 6.2 6.7 11.1z"/><path class="st1" d="M529.1 439.4c-.1-.7-.4-1.4-.8-2-.9-1.5-2.5-2.7-4.3-3.1-.3-.1-.6-.1-.9-.2v.3c2 .3 3.9 1.4 4.9 3.2 1.4 2.3 1.1 5-.5 7l.2.1c1.3-1.5 1.8-3.4 1.4-5.3zm-3.3 7.1s.1 0 .1-.1l-.3-.1-3 1.8.2.2 3-1.8zm-4.2 2.6l-.2-.2-2.9 1.7.2.2 2.9-1.7zm-4.4 2.6l-.2-.2-1.5.9-5.2-8.5-.2.1 5.3 8.8 1.8-1.1zm.2-15.9l-7.4 4.5.1.2 7.4-4.5-.1-.2z"/></g></g><g><path class="st10" d="M234.4 464c0-.8-.5-1.5-1.3-1.6-2.3-.3-4.6-.6-6.9-1-2.3-.4-4.5-.8-6.7-1.3s-4.3-1.2-6.2-2c-1.9-.8-3.7-1.9-5.3-3.1-3.2-2.5-5.7-6-8-9.7-.3-.5-.6-.9-.9-1.4l-.8-1.4c-.6-1-1.1-2-1.7-3-1.1-2-2.2-4-3.2-6.1-1.4-2.6-4.7-3.5-7.2-2s-3.3 4.8-1.7 7.3c1.4 1.9 2.7 3.9 4.1 5.8.7 1 1.4 1.9 2.2 2.9l1.1 1.4c.4.5.8.9 1.1 1.4 1.6 1.9 3.2 3.7 5 5.5 1.8 1.8 3.9 3.4 6.1 4.8 2.3 1.3 4.7 2.3 7.2 3 2.5.7 4.9 1.1 7.3 1.3 2.4.2 4.8.4 7.1.4 2.4.1 4.7.1 7 .1 1 0 1.7-.6 1.7-1.3z"/><path class="st3" d="M190.5 450.4l-6.3-10c-1.9-3-1.3-7 1.8-8.9 3-1.9 7.3-1.1 9.2 2l6.3 10-11 6.9z"/><path class="st9" d="M181.4 505.2L189.7 554.4 192.6 553.9 193.4 504.8z"/><path class="st4" d="M194.2 504.7l-13.6.5c-3.7-9-6.9-28.9-3.1-38.1l15.2 3.4 1.5 34.2z"/><circle transform="rotate(-16.739 184.847 470.406)" class="st4" cx="184.8" cy="470.4" r="7.9"/><g class="st11"><path class="st4" d="M184.8 470.4L184.8 470.4 184.8 470.4 184.8 470.3z"/></g><path class="st9" d="M165.9 503.2L161.1 553.4 164.1 553.6 177.6 505.8z"/><path class="st4" d="M180.4 462.7c-3.2-1-6.5.2-8.5 2.7-.1.2-.3.4-.4.6-5.7 8.3-7.5 27.6-6.3 37l13.2 3 7.3-33.4c1.3-4.2-1.1-8.6-5.3-9.9z"/><path class="st2" d="M180.4 497.1l-1.9 8.9-2.2-.5v.3l2.4.5 2-9.1-.3-.1zm-11.9-25.8c-1.3 3.5-2.4 7.8-3.1 12.8v.3h.3c.6-4.6 1.7-9.1 3.1-12.9l-.3-.2zm-3.9 23.7h.3c0-2.2.2-4.5.4-6.8h-.3c-.3 2.3-.4 4.6-.4 6.8zm.6 8c-.2-1.3-.3-2.8-.3-4.4h-.3c.1 1.6.2 3.1.3 4.4v.2l8 1.8.1-.2-7.8-1.8zm18.6-21.8l-1.7 7.9h.3l1.7-7.9h-.3z"/><path class="st3" d="M170.4 556.6c-.2-.4-.6-.6-1-.7-.4-.1-.8-.1-1.2-.2-1-.2-2-.6-2.8-1.2-.4-.3-.8-.7-1.3-.9l-2.9-.3c-.4.4-.8.9-1 1.5-.2.5-.2 1.1-.3 1.6l-.1.6 10.7 1.2.1-.6c.1-.3 0-.7-.2-1zM199.5 555.1c-.3-.3-.7-.4-1.2-.4-.4 0-.8.1-1.3.1-1 .1-2.1 0-3-.4l-1.5-.6-2.9.5c-.3.5-.5 1.1-.5 1.7 0 .5 0 1.1.1 1.6l.1.6 10.7-1.6-.1-.6c0-.3-.1-.6-.4-.9zM182 428.8c9 .1 15.8 8.2 14.4 17.1l-3.6 24c-6.5 2.3-15.6 1.5-23.1-.7v-27.4c-.5-7.1 5.2-13.1 12.3-13z"/><path class="st1" d="M169.4 457.4v10.4h.3v-10.4h-.3zm12.6-28.8h-.1c-.4 0-.8 0-1.2.1v.3c.4 0 .8-.1 1.3-.1 2.1 0 4 .5 5.8 1.2l.1-.2c-1.8-.9-3.8-1.3-5.9-1.3zm11.3 5.3c-.8-.9-1.7-1.8-2.7-2.5l-.2.2c3.7 2.7 6.1 7.1 6.1 11.9 0 .8-.1 1.6-.2 2.4l-.8 5.3.3.1.8-5.3c.7-4.4-.5-8.8-3.3-12.1zm-.6 36c-5.9 2.1-13.9 1.6-20.9-.1v.3c4 1 8.1 1.5 11.8 1.5 3.5 0 6.6-.5 9.2-1.4l.1-.1 2.1-13.8h-.3l-2 13.6zm-16.9-39.5l-.1-.3c-1.1.6-2.1 1.4-2.9 2.3-2.4 2.5-3.6 5.9-3.3 9.3v6.4h.3v-6.4c-.4-4.7 2.1-9 6-11.3z"/><g><path class="st9" d="M186.2 424.7l-.4 7.3c-2.1 1.1-4 1-5.9-.4l.4-7.3 5.9.4z"/><path class="st10" d="M186.1 426.9v.8c-.9.5-2 .7-3.1.7h-.2c-1-.1-1.9-.5-2.6-1.2l.1-2.1 5.8 1.8z"/><path class="st9" d="M189.3 416.4l-.5 5.2-.1 1.2c-.3 2.9-2.8 5.1-5.7 5-.3 0-.6-.1-.9-.1-.1 0-.2-.1-.3-.1h-.1c-.4-.2-.8-.5-1.1-.8-.6-.8-1-1.6-1.4-2.5-.3-.8-.6-1.5-.8-2.3-.2-.9-.3-1.8-.2-2.8l.2-3.6 9.3-1.5 1.6 2.3z"/><path class="st3" d="M189 424.6s0-3.1-.1-4.6c-.1-1.4-.4-2.8-1.5-2.6-2.1.4-2.9-1.4-2.9-1.4-.6 0-1.2.1-1.9.3-3.1.8-3.6 0-4-.5-.8 2.4-.5 5.5-.5 5.8 0 .1.1.3.1.4.2.8.5 1.5.8 2.3.3.7.6 1.4 1 2v.5c-2.2-.4-4.9-2.8-5.6-4.7-2.3-7.2 1.6-11.5 7.1-12.6 4.8-.9 7.4 3.5 8.4 7.5.8 2.3-.3 7-.9 7.6z"/><path class="st9" d="M180.2 420.3c-.1 1.2-1.1 2.1-2.3 2-1.2-.1-2.1-1.1-2-2.3.1-1.2 1.1-2.1 2.3-2 1.2.1 2 1.1 2 2.3z"/></g><g><path transform="rotate(-180 274.437 454.01)" class="st2" d="M269 446.1H279.8V462H269z"/><path transform="rotate(-180 260.511 447.387)" class="st2" d="M255.1 432.8H265.9V461.90000000000003H255.1z"/><path transform="rotate(-180 246.585 443.424)" class="st4" d="M241.2 424.9H252V461.9H241.2z"/><path transform="rotate(-180 232.659 439.712)" class="st4" d="M227.2 417.5H238V461.9H227.2z"/><path transform="rotate(-180 218.732 441.217)" class="st4" d="M213.3 420.5H224.10000000000002V461.9H213.3z"/><path transform="rotate(-180 204.806 443.424)" class="st2" d="M199.4 424.9H210.20000000000002V461.9H199.4z"/><path transform="rotate(-180 190.88 447.387)" class="st4" d="M185.5 432.8H196.3V461.90000000000003H185.5z"/><g><path transform="rotate(-180 232.659 462.663)" class="st3" d="M183.1 461.9H282.3V463.4H183.1z"/></g></g><g><path class="st9" d="M227.5 461.9c-.1-.8-.7-1.4-1.5-1.4h-6.9c-2.3-.1-4.6-.2-6.8-.4s-4.4-.6-6.4-1.1c-2-.6-3.9-1.3-5.7-2.4-3.5-2.1-6.5-5.1-9.3-8.5-.4-.4-.7-.8-1.1-1.3l-1-1.3c-.7-.9-1.4-1.8-2-2.7-1.4-1.8-2.7-3.7-4-5.6-1.7-2.3-5.1-2.8-7.4-.9-2.3 1.8-2.6 5.3-.6 7.5 1.6 1.7 3.2 3.4 4.9 5.2.8.9 1.7 1.7 2.5 2.6l1.3 1.3c.4.4.9.8 1.3 1.2 1.8 1.7 3.7 3.3 5.8 4.8 2.1 1.5 4.3 2.8 6.7 3.9 2.4 1 5 1.7 7.5 2 2.5.3 5 .4 7.4.3 2.4-.1 4.8-.3 7.1-.6s4.7-.6 7-.9c.7-.3 1.2-1 1.2-1.7z"/><path class="st3" d="M181.9 454.2l-7.7-9c-2.3-2.7-2.2-6.7.5-9.1 2.7-2.3 7.1-2.1 9.4.7l7.7 9-9.9 8.4z"/><path class="st1" d="M179.6 434.3c-1.2-.1-2.3.1-3.4.6l.1.2c2.6-1.2 5.9-.6 7.8 1.7l.7.8.2-.2-.7-.8c-1.1-1.3-2.8-2.2-4.7-2.3zm12.2 11.6l-8.1 6.8.2.2 8.3-7-4.4-5.2-.2.2 4.2 5zm-18-9.1c-1.8 2.1-1.9 5.2-.4 7.7l.2-.1c-1.4-2.3-1.4-5.3.3-7.4l-.1-.2zm7.4 17l.2-.2-3.7-4.4-.2.2 3.7 4.4z"/></g></g><g><path class="st3" d="M630.9 587.7H74.2c-1.6 0-2.9-1.3-2.9-2.9 0-1.6 1.3-2.9 2.9-2.9H631c1.6 0 2.9 1.3 2.9 2.9-.1 1.6-1.4 2.9-3 2.9z"/></g><g><path transform="rotate(-40.957 194.403 297.627)" class="st2" d="M179.5 288.7H209.2V306.4H179.5z"/><path transform="rotate(-40.957 148.955 337.083)" class="st4" d="M103.6 323.8H194.2V350.40000000000003H103.6z"/><path class="st4" d="M294.2 300.4c28.1-24.4 31.2-67.2 6.7-95.3-24.4-28.1-67.2-31.2-95.3-6.7-25.9 22.5-30.5 60.4-12.1 88.2 1.6 2.4 3.4 4.8 5.4 7.1 2 2.3 4.1 4.4 6.2 6.3 25 22.1 63.3 22.9 89.1.4zm-76.9-88.6c20.7-18 52.3-15.8 70.3 5s15.8 52.3-5 70.3-52.3 15.8-70.3-5-15.8-52.3 5-70.3z"/><g style="opacity:.5"><path class="st2" d="M212.3 282.1c-18-20.8-15.8-52.3 5-70.3 20.7-18 52.3-15.8 70.3 5s15.8 52.3-5 70.3c-20.7 17.9-52.3 15.7-70.3-5z"/></g><g><path class="st1" d="M263.6 217c.2-.4.4-.7.8-1 1-.8 2.5-.5 3.2.5l20.8 28.3c.8 1 .5 2.5-.5 3.2-1 .8-2.5.5-3.2-.5l-20.8-28.3c-.5-.6-.6-1.5-.3-2.2zM252.5 225.2c.2-.4.4-.7.8-1 1-.8 2.5-.5 3.2.5l20.8 28.3c.8 1 .5 2.5-.5 3.2-1 .8-2.5.5-3.2-.5l-20.8-28.3c-.5-.6-.6-1.5-.3-2.2z"/></g></g><g><path class="st3" d="M410 551.8l-12.9 6.5c-.2-.4-.3-.9-.2-1.4.1-.6.5-1 .9-1.3.5-.3 1-.6 1.5-.8 1.2-.7 2.2-1.6 3-2.8.4-.6.7-1.2 1.2-1.8l3.6-1.7c.7.3 1.4.8 1.9 1.4.4.5.7 1.2 1 1.9zM422.6 556.4l-14.4 1.9c-.1-.5 0-1 .2-1.4.3-.5.8-.8 1.3-1 .5-.2 1.1-.2 1.7-.3 1.4-.2 2.6-.8 3.7-1.6.6-.4 1.1-.9 1.7-1.3l3.9-.4c.6.5 1.1 1.2 1.3 2 .4.7.5 1.4.6 2.1zM416.5 508.6L416.5 508.6 416.5 508.6z"/><g class="st11"><path class="st3" d="M414.6 478.3L414.6 478.3 414.6 478.3 414.6 478.3z"/></g><path class="st3" d="M416.5 508.6L416.5 508.6 416.5 508.6zM416.5 508.6L416.5 508.6 416.5 508.6z"/><path class="st2" d="M384.1 510.1l18.8 40.3 4.7-1.9-12-37.6 9.7-15.3 11 57.2 5.1-.3.1-73.2c.1-.7-30.9-2.6-30.9-2.6l-6.8 30.4c-.1 1.1 0 2 .3 3zm32.4-1.5z"/><g class="st11"><path class="st3" d="M416.5 508.6L416.5 508.6 416.5 508.6z"/></g><path class="st10" d="M352.8 484.7c1.5-1.5 3-2.8 4.5-4.2.4-.3.7-.7 1.1-1 .4-.4.7-.7 1.1-1l1-1.1.5-.5.5-.5c2.7-2.9 5.1-6 7.3-9.3 1-1.7 2.1-3.3 3.1-5l.7-1.3c.1-.2.2-.4.4-.6l.3-.7 1.3-2.6c.1-.2.2-.4.3-.7l.3-.7.6-1.3.6-1.3.3-.7.2-.3.1-.3 1.1-2.7c.4-.9.7-1.8 1.1-2.8.4-1.2 1.4-2 2.6-2.4 1.2-.4 2.6-.4 3.9.2 1.3.6 2.3 1.6 2.8 2.7.5 1.2.5 2.5-.1 3.7-.5.9-1 1.8-1.6 2.8l-1.6 2.7-.2.3-.2.3-.4.7-.9 1.3-.9 1.3-.4.7c-.1.2-.3.4-.5.7l-1.8 2.6-.5.6c-.2.2-.3.4-.5.6l-1 1.3c-1.3 1.7-2.7 3.3-4.1 4.9-2.9 3.1-6 6.1-9.2 8.7l-.6.5-.6.5-1.3.9c-.4.3-.8.6-1.3.9-.4.3-.8.6-1.3.9-1.7 1.2-3.4 2.3-5 3.4-.5.4-1.3.3-1.9-.3-.3-.6-.3-1.4.2-1.9z"/><path class="st4" d="M383.8 465.5l5.6-12.2c1.7-3.7.4-8-3.3-9.7-3.7-1.7-8.4-.1-10 3.6l-5.6 12.2 13.3 6.1z"/><g><path class="st4" d="M389.8 435.7c-7.7 1.9-12.2 9.9-9.6 17.5l11.9 36.1c13.9 1.7 20.3-2.7 29.7-9.7l-12.4-33.5c-3-7.9-11.4-12.4-19.6-10.4z"/></g><g><path class="st1" d="M403.3 438.2c1.4 1 2.7 2.2 3.8 3.7l.3-.3c-1.1-1.4-2.4-2.7-3.8-3.7l-.3.3zm16 43.1l.2.3c.8-.6 1.5-1.1 2.3-1.7l.2-.2-3.2-8.7-.4.1 3.1 8.5c-.6.5-1.4 1.1-2.2 1.7zm-27.6 8.3h.3c2.7.3 5.1.5 7.3.4l-.1-.4c-2.2.1-4.5 0-7.2-.3l-7-21.2-.4.1 7.1 21.4zm20.6-3.7c-1 .5-1.9 1-3 1.4l.2.4c1.1-.5 2.1-1 3.1-1.5l-.3-.3zm2.1-26l.4-.2-3-8-.4.2 3 8zm-32.6-.2l.4-.1-2.1-6.5c-2.3-6.8 1.2-14.1 7.6-16.8.3-.1.6-.3 1-.4l-.2-.4-.9.3c-6.8 2.8-10.3 10.4-7.9 17.4l2.1 6.5z"/></g><g><path class="st4" d="M353.2 491.4c8.2 7.9 20.6 10.6 31.7 6l-11.3-26.9-20.4 20.9z"/><path class="st3" d="M373.6 470.4l29.2-1.4c-.2-3.3-.9-6.7-2.3-9.9-2.7-6.4-7.4-11.3-13.1-14.4l-13.8 25.7zM362.2 443.5l11.3 26.9 13.9-25.7c-7.4-4-16.7-4.8-25.2-1.2z"/><path class="st3" d="M373.6 470.4l11.3 26.9c11.6-4.9 18.4-16.4 17.8-28.3l-29.1 1.4z"/><path class="st4" d="M346.7 481.8c1.6 3.7 3.8 7 6.6 9.6l20.4-21-29-3.4c-.7 4.9-.1 9.9 2 14.8z"/></g><g><path class="st9" d="M371.3 467.3c.5-.6 1.3-.7 1.9-.3 1.8 1.2 3.7 2.4 5.6 3.4.9.5 1.9 1 2.9 1.4 1 .4 1.9.8 2.9 1.1 1 .3 1.9.5 2.8.5h1.2c.4 0 .8-.1 1.1-.2.3-.1.6-.3.9-.4.3-.2.5-.4.8-.6.2-.2.5-.5.7-.8.2-.3.4-.6.6-1 .4-.7.7-1.6 1-2.5.3-.9.5-1.8.7-2.8.4-2 .6-4 .7-6.1.1-2.1.2-4.2.2-6.4 0-2.1-.1-4.3-.2-6.5 0-1.4.5-2.6 1.5-3.6.9-.9 2.2-1.5 3.7-1.5 1.4 0 2.7.6 3.7 1.6.9 1 1.4 2.3 1.3 3.7-.2 2.3-.4 4.6-.8 6.8-.3 2.3-.7 4.6-1.1 6.9-.5 2.3-1 4.6-1.8 7-.4 1.2-.8 2.3-1.4 3.5-.6 1.2-1.2 2.3-2 3.4-.4.6-.9 1.1-1.4 1.6-.5.5-1.1 1-1.7 1.4-.6.4-1.3.8-2.1 1.1-.7.3-1.5.5-2.2.6-.7.1-1.5.1-2.2.1h-.6l-.5-.1c-.3-.1-.7-.1-1-.2-1.3-.3-2.5-.7-3.6-1.2s-2.2-1.1-3.2-1.7c-1-.6-2-1.3-2.9-2-1.9-1.4-3.6-2.8-5.3-4.3-.6-.5-.7-1.3-.2-1.9z"/><path class="st4" d="M406.8 461.8l.4-13.4c.1-4.1-2.8-7.6-6.8-7.7-4.1-.1-7.7 3.2-7.9 7.2l-.4 13.4 14.7.5z"/><path class="st1" d="M392.2 449.3h.4V448c0-.5.1-.9.2-1.4l-.4-.1c-.1.5-.2 1-.2 1.5v1.3zm11.3 12.8l3.7.1.1-4.1-.4-.1-.1 3.8-3.3-.1v.4zm3.7-11.4l-.2 4.9h.4l.2-5-.4.1zm-12.7-7.9l.4.1c1.5-1.4 3.4-2.2 5.5-2.2 1.7.1 3.3.7 4.4 1.8l.2-.3c-1.3-1.2-2.9-1.8-4.6-1.9-1.1 0-2.2.2-3.3.6-1 .5-1.9 1.1-2.6 1.9zm-2.6 15.2l.4.1.1-3.4h-.4l-.1 3.3zm4.5 3.9l3.4.1v-.4l-3.3-.1-.1.4z"/></g><g><path class="st9" d="M383 434.5l4.8 8.4c2.5.2 4.3-.9 5.5-3.1l-4.8-8.4-5.5 3.1z"/><path class="st10" d="M383 434.5l2.2 3.8c.5-.1.9-.2 1.4-.4.1-.1.3-.1.4-.2 1.5-.9 2.5-2.4 2.8-4l-1.3-2.3-5.5 3.1z"/><path class="st9" d="M377.6 430.8l2.1 3.5.9 1.4c1.2 1.9 3.7 2.7 5.7 1.7.7-.3 1.3-.8 1.7-1.3.1-.1.2-.3.3-.4.1-.1.1-.2.2-.3.5-.9.8-1.8.7-2.9-.1-.9-.2-1.8-.3-2.8-.1-.6-.2-1.1-.3-1.7-.5-2.5-2.3-4.6-4.7-5.3-2.1-.6-4-.1-5.6 1.6-1.7 1.8-2 4.4-.7 6.5z"/><path class="st3" d="M385.7 429.1h-.8s0-3.2-.8-3.9c-1.2-1-4.5.3-5.9 1.4-.4.4-.7.7-.7 1.3.1 1.2.5 3.5 1.7 5.5 0 0-5-5.2-4.5-9.4.3-2.8.8-4.8 4.3-4.8 5.5 0 9.6 2.7 11.2 8.4l-3.5.2-1 1.3z"/><g><path class="st9" d="M385.9 429.5c.6 1 2 1.3 3.1.7s1.6-2 1-3c-.6-1-2-1.3-3.1-.7-1.2.6-1.6 2-1 3z"/></g></g></g><g><path class="st5" d="M305 499.7H375.1V558.3H305z"/><path class="st13" d="M281.2 499.7H305V558.3H281.2z"/><path class="st13" d="M305 499.7L295.6 517.6 269.4 517.6 281.2 499.7zM386 519.6L316 524.1 305 499.7 375.1 504.2z"/><path class="st5" d="M386 519.6L316 519.6 305 499.7 375.1 499.7zM305 499.7L299.7 519.7 269.4 517.6 295.6 517.6z"/></g><g><path class="st0" d="M38.9 241.8c3.5-18.6 10.8-36.5 20.7-52.7 5-8.1 10.7-15.8 17.1-22.9 3.2-3.6 6.5-7 10-10.3 3.5-3.3 7.1-6.4 10.8-9.4 15-11.9 32.3-20.9 50.6-26.7 9.2-2.9 18.6-4.9 28.1-6.1 2.4-.3 4.8-.5 7.1-.8l3.6-.3c1.2-.1 2.4-.1 3.6-.2 4.8-.2 9.6-.2 14.4 0 4.8.2 9.6.7 14.3 1.3 4.8.6 9.5 1.5 14.2 2.5 2.3.5 4.7 1.1 7 1.7l3.5 1c1.2.3 2.3.7 3.4 1.1.6.2 1.1.4 1.7.5l1.7.6c1.1.4 2.3.8 3.4 1.2 1.1.4 2.2.8 3.4 1.3l3.3 1.4c.6.2 1.1.5 1.7.7l1.6.7 3.3 1.5 3.2 1.6 1.6.8 1.6.8 3.2 1.7 3.1 1.7 1.6.9 1.5.9 3.1 1.8c4.1 2.4 8.1 4.9 12.1 7.5 4 2.6 7.9 5.2 11.9 7.9 7.8 5.3 15.6 10.7 23.5 15.9 3.9 2.6 7.9 5.1 11.9 7.6 4 2.4 8.1 4.8 12.2 7.1 2 1.2 4.1 2.2 6.2 3.3 1 .6 2.1 1 3.2 1.6 1.1.5 2.1 1.1 3.2 1.5 2.1 1 4.3 2 6.5 2.8 1.1.4 2.2.9 3.3 1.3l3.3 1.2 3.3 1.2c1.1.4 2.2.8 3.4 1.1l3.4 1c.6.2 1.1.3 1.7.5l1.7.4c1.1.3 2.3.6 3.4.8l3.5.7c.6.1 1.2.2 1.7.3l1.7.3 3.5.5c-9.4-.8-18.8-2.7-27.8-5.6-9-2.9-17.8-6.7-26.3-11-4.3-2.1-8.4-4.4-12.5-6.8-4.1-2.4-8.2-4.8-12.2-7.3s-8-5.1-12-7.6l-11.9-7.7c-4-2.6-7.9-5.1-11.9-7.6s-8-4.9-12.1-7.3l-3.1-1.7-1.5-.9-1.5-.8-3.1-1.7-3.1-1.6-1.6-.8-1.6-.8-3.2-1.5-3.2-1.4-1.6-.7c-.5-.2-1.1-.4-1.6-.7-17.2-7.2-35.7-11.2-54.3-11.9-18.6-.8-37.4 1.5-55.2 6.9-4.5 1.3-8.9 2.9-13.2 4.6-4.3 1.7-8.6 3.7-12.7 5.8-8.3 4.2-16.2 9.2-23.7 14.8-7.4 5.7-14.4 11.9-20.8 18.8-6.4 6.8-12.2 14.2-17.4 22-10.6 15.9-18.3 33.3-22.9 51.7z"/></g><g><path class="st0" d="M658 370.2c6.5 13.9 10.3 29.1 11.5 44.5 1.1 15.4-.4 31.1-4.6 46.1-4.2 14.9-11.2 29.1-20.3 41.6-9.1 12.5-20.3 23.5-33.2 31.9 11.9-9.7 22.3-21 30.7-33.6 8.4-12.6 14.9-26.4 19-41 4.1-14.5 5.9-29.7 5.3-44.9-.4-15.1-3.3-30.2-8.4-44.6z"/></g><g><path class="st1" d="M639.8 422.2c.4 9.5-.9 19.2-3.6 28.3-1.4 4.6-3.1 9.1-5.2 13.4-2.1 4.3-4.6 8.5-7.3 12.4-2.8 3.9-5.9 7.6-9.2 11.1-3.4 3.4-7 6.6-10.9 9.4-7.7 5.7-16.4 10.1-25.5 12.9 8.8-3.5 17.1-8.3 24.6-14.1 3.7-2.9 7.2-6.1 10.5-9.5 3.3-3.4 6.3-7 9-10.9 2.7-3.8 5.1-7.9 7.3-12.1 2.1-4.2 3.9-8.6 5.4-13.1 2.9-8.8 4.5-18.2 4.9-27.8z"/></g></svg>
src/assets/svgs/member_balance.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1693028338187" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22985" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M983.8 312.7C958 251.7 921 197 874 150c-47-47-101.8-83.9-162.7-109.7C648.2 13.5 581.1 0 512 0S375.8 13.5 312.7 40.2C251.7 66 197 102.9 150 150c-47 47-83.9 101.8-109.7 162.7C13.5 375.8 0 442.9 0 512s13.5 136.2 40.2 199.3C66 772.3 102.9 827 150 874c47 47 101.8 83.9 162.7 109.7 63.1 26.7 130.2 40.2 199.3 40.2s136.2-13.5 199.3-40.2C772.3 958 827 921 874 874c47-47 83.9-101.8 109.7-162.7 26.7-63.1 40.2-130.2 40.2-199.3s-13.4-136.2-40.1-199.3z m-55.3 375.2c-22.8 53.8-55.4 102.2-96.9 143.7s-89.9 74.1-143.7 96.9C632.2 952.1 573 964 512 964s-120.2-11.9-175.9-35.5c-53.8-22.8-102.2-55.4-143.7-96.9s-74.1-89.9-96.9-143.7C71.9 632.2 60 573 60 512s11.9-120.2 35.5-175.9c22.8-53.8 55.4-102.2 96.9-143.7s89.9-74.1 143.7-96.9C391.8 71.9 451 60 512 60s120.2 11.9 175.9 35.5c53.8 22.8 102.2 55.4 143.7 96.9s74.1 89.9 96.9 143.7C952.1 391.8 964 451 964 512s-11.9 120.2-35.5 175.9z" fill="#000000" p-id="22986"></path><path d="M706 469.1H574.7l84.2-180.6c7-15 0.4-32.9-14.5-39.9-15-7-32.9-0.4-39.9 14.5L512 461.5l-92.5-198.3c-7-15-24.9-21.5-39.9-14.5s-21.5 24.9-14.5 39.9l84.2 180.6H318c-16.5 0-30 13.5-30 30s13.5 30 30 30h164v64h-92.5c-20.6 0-37.5 13.5-37.5 30s16.9 30 37.5 30H482v95c0 16.5 13.5 30 30 30s30-13.5 30-30v-95h92.5c20.6 0 37.5-13.5 37.5-30s-16.9-30-37.5-30H542v-64h164c16.5 0 30-13.5 30-30 0-16.6-13.5-30.1-30-30.1z" fill="#000000" p-id="22987"></path></svg>
src/assets/svgs/member_expenditure_balance.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1693028553383" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="28918" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M510.72 962.56C262.4 960 61.44 757.76 64 509.44 66.56 263.68 264.96 65.28 510.72 62.72c17.92 0 34.56 14.08 34.56 32s-14.08 34.56-32 34.56h-2.56C299.52 130.56 128 300.8 128 512s171.52 382.72 382.72 382.72S893.44 723.2 893.44 512c0-17.92 16.64-33.28 34.56-32 17.92 0 32 15.36 32 32 0 248.32-200.96 450.56-449.28 450.56z" fill="#000000" p-id="28919"></path><path d="M645.12 480H375.04c-17.92 0-34.56-14.08-34.56-32s14.08-34.56 32-34.56h272.64c17.92 0 33.28 16.64 32 34.56 0 17.92-14.08 32-32 32z m0 130.56H375.04c-17.92 0-33.28-16.64-32-34.56 0-17.92 15.36-32 32-32h270.08c17.92 0 33.28 16.64 32 34.56 0 16.64-14.08 32-32 32z" fill="#000000" p-id="28920"></path><path d="M510.72 746.24c-17.92 0-33.28-15.36-33.28-33.28V441.6c0-17.92 16.64-33.28 34.56-32 17.92 0 32 15.36 32 32v270.08c0 19.2-15.36 34.56-33.28 34.56z" fill="#000000" p-id="28921"></path><path d="M510.72 458.24c-8.96 0-17.92-3.84-24.32-10.24l-111.36-111.36c-14.08-12.8-15.36-33.28-2.56-47.36s33.28-15.36 47.36-2.56l2.56 2.56 111.36 111.36c12.8 12.8 12.8 34.56 0 47.36-6.4 6.4-15.36 10.24-23.04 10.24z" fill="#000000" p-id="28922"></path><path d="M510.72 458.24c-8.96 0-17.92-3.84-24.32-10.24-12.8-12.8-12.8-34.56 0-47.36l111.36-111.36c14.08-12.8 35.84-10.24 47.36 2.56 11.52 12.8 11.52 32 0 44.8L533.76 448c-6.4 6.4-15.36 10.24-23.04 10.24zM925.44 241.92c17.92 0 33.28-15.36 33.28-33.28 0-8.96-3.84-17.92-10.24-24.32l-111.36-111.36c-12.8-14.08-33.28-14.08-47.36-1.28s-14.08 33.28-1.28 47.36l1.28 1.28 111.36 111.36c7.68 6.4 15.36 10.24 24.32 10.24z" fill="#000000" p-id="28923"></path><path d="M815.36 353.28c8.96 0 17.92-3.84 24.32-10.24l111.36-111.36c12.8-14.08 10.24-35.84-2.56-47.36-12.8-11.52-32-11.52-44.8 0l-111.36 111.36c-12.8 12.8-12.8 34.56 0 47.36 5.12 6.4 14.08 10.24 23.04 10.24z" fill="#000000" p-id="28924"></path><path d="M920.32 241.92c17.92 0 34.56-14.08 34.56-32s-14.08-34.56-32-34.56H695.04c-17.92 0-33.28 16.64-32 34.56 0 17.92 15.36 32 32 32h225.28z" fill="#000000" p-id="28925"></path></svg>
src/assets/svgs/member_level.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1693027700643" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8876" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M936.96 385.877333l-203.434667-204.8-18.090667-7.68L308.565333 173.397333l-18.090667 7.68L87.04 385.877333c-9.728 9.898667-9.898667 25.941333-0.170667 35.84l406.869333 421.034667c4.778667 4.949333 11.434667 7.850667 18.432 7.850667 6.997333 0 13.653333-2.901333 18.432-7.850667l406.869333-421.034667C946.858667 411.648 946.688 395.776 936.96 385.877333zM868.522667 389.632l-141.994667 0-163.84-165.034667 141.994667 0L868.522667 389.632zM319.317333 224.768l143.018667 0-163.84 165.034667L155.477333 389.802667 319.317333 224.768zM176.469333 440.832l132.608 0 18.090667-7.509333 185.173333-186.538667 185.173333 186.538667 18.090667 7.509333 131.584 0L512 787.968 176.469333 440.832z" p-id="8877" fill="#000000"></path></svg>
src/assets/svgs/member_point.svg
New file
@@ -0,0 +1 @@
<svg t="1693027780777" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10083" width="128" height="128"><path d="M509.091764 501.653351c241.775532 0 424.086741-78.085426 424.086741-181.63992 0-103.543238-182.311209-181.628664-424.086741-181.628664S84.993766 216.471217 84.993766 320.014454C84.993766 423.568948 267.316232 501.653351 509.091764 501.653351zM509.091764 184.220698c222.908836 0 378.251833 71.561849 378.251833 135.793756S732.001623 455.818443 509.091764 455.818443c-222.920092 0-378.26309-71.573105-378.26309-135.803989S286.171672 184.220698 509.091764 184.220698z" fill="#000000" p-id="10084"></path><path d="M509.083577 694.061522c241.1155 0 422.937568-77.598332 422.937568-180.482561 0-27.169803-13.127995-52.453652-36.241412-75.131141-0.148379-0.153496-0.26606-0.320295-0.418532-0.468674-0.170892-0.166799-0.285502-0.345877-0.456395-0.51063l-0.11461 0.125867c-3.717671-3.40761-8.576329-5.608741-14.017248-5.608741-11.542894 0-20.898982 9.356089-20.898982 20.898982 0 6.110161 2.721994 11.481496 6.901177 15.302521l-0.082888 0.091074c13.948687 14.024411 21.809725 31.154557 21.809725 45.300742 0 64.785515-155.813718 136.966465-379.419426 136.966465-223.595474 0-379.410216-72.180949-379.410216-136.966465 0-16.139585 4.53734-29.952172 22.323425-45.670156 0.213871-0.204661 0.429789-0.381693 0.635473-0.594541 0.137123-0.118704 0.240477-0.233314 0.378623-0.354064l-0.084934-0.080841c3.416819-3.719718 5.623068-8.588609 5.623068-14.037714 0-11.542894-9.356089-20.898982-20.898982-20.898982-5.770424 0-10.993378 2.340301-14.773472 6.119371l-0.122797-0.118704c-23.408129 22.797215-36.594453 48.27754-36.594453 75.635631C86.158289 616.462167 267.979334 694.061522 509.083577 694.061522z" fill="#000000" p-id="10085"></path><path d="M895.577119 629.529787c-0.168846-0.164752-0.282433-0.342808-0.453325-0.50756l-0.11461 0.124843c-3.717671-3.40761-8.577353-5.608741-14.018272-5.608741-11.540847 0-20.897959 9.356089-20.897959 20.898982 0 6.110161 2.720971 11.482519 6.901177 15.302521l-0.083911 0.091074c13.94971 14.024411 21.810748 31.154557 21.810748 45.300742 0 64.787562-155.813718 136.966465-379.419426 136.966465-223.595474 0-379.410216-72.179926-379.410216-136.966465 0-16.139585 4.53734-29.952172 22.321378-45.670156 0.213871-0.202615 0.429789-0.381693 0.635473-0.594541 0.137123-0.118704 0.240477-0.233314 0.378623-0.354064l-0.084934-0.080841c3.416819-3.719718 5.623068-8.588609 5.623068-14.037714 0-11.542894-9.356089-20.898982-20.897959-20.898982-5.770424 0-10.993378 2.340301-14.773472 6.119371l-0.122797-0.118704c-23.410176 22.797215-36.594453 48.278563-36.594453 75.635631 0 102.884228 181.821045 180.482561 422.926312 180.482561 241.114476 0 422.935522-77.598332 422.935522-180.482561 0-27.166733-13.125949-52.452629-36.235272-75.127048C895.851365 629.847012 895.730615 629.681236 895.577119 629.529787z" fill="#000000" p-id="10086"></path></svg>
src/assets/svgs/member_recharge_balance.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1693028440322" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25843" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512 750.509317c-19.080745 0-31.801242-12.720497-31.801242-31.801242L480.198758 432.496894c0-19.080745 12.720497-31.801242 31.801242-31.801242s31.801242 12.720497 31.801242 31.801242l0 286.21118C537.440994 737.78882 524.720497 750.509317 512 750.509317z" fill="#000000" p-id="25844"></path><path d="M651.925466 534.26087 365.714286 534.26087c-19.080745 0-31.801242-12.720497-31.801242-31.801242 0-19.080745 12.720497-31.801242 31.801242-31.801242l286.21118 0c19.080745 0 31.801242 12.720497 31.801242 31.801242C683.726708 521.540373 671.006211 534.26087 651.925466 534.26087z" fill="#000000" p-id="25845"></path><path d="M651.925466 648.745342 365.714286 648.745342c-19.080745 0-31.801242-12.720497-31.801242-31.801242 0-19.080745 12.720497-31.801242 31.801242-31.801242l286.21118 0c19.080745 0 31.801242 12.720497 31.801242 31.801242C683.726708 636.024845 671.006211 648.745342 651.925466 648.745342z" fill="#000000" p-id="25846"></path><path d="M512 464.298137c-6.360248 0-19.080745 0-25.440994-6.360248L352.993789 324.372671c-12.720497-12.720497-12.720497-31.801242 0-44.521739 12.720497-12.720497 31.801242-12.720497 44.521739 0l133.565217 133.565217c12.720497 12.720497 12.720497 31.801242 0 44.521739C524.720497 464.298137 518.360248 464.298137 512 464.298137z" fill="#000000" p-id="25847"></path><path d="M512 464.298137c-6.360248 0-19.080745 0-25.440994-6.360248-12.720497-12.720497-12.720497-31.801242 0-44.521739l133.565217-133.565217c12.720497-12.720497 31.801242-12.720497 44.521739 0 12.720497 12.720497 12.720497 31.801242 0 44.521739L531.080745 457.937888C524.720497 464.298137 518.360248 464.298137 512 464.298137z" fill="#000000" p-id="25848"></path><path d="M512 1017.639752c-279.850932 0-508.819876-228.968944-508.819876-508.819876s228.968944-508.819876 508.819876-508.819876 508.819876 228.968944 508.819876 508.819876c0 25.440994 0 50.881988-6.360248 82.68323 0 19.080745-19.080745 31.801242-38.161491 25.440994-19.080745 0-31.801242-19.080745-25.440994-38.161491 6.360248-25.440994 6.360248-44.521739 6.360248-69.962733 0-248.049689-197.167702-445.217391-445.217391-445.217391S66.782609 267.130435 66.782609 515.180124s197.167702 445.217391 445.217391 445.217391c25.440994 0 57.242236 0 82.68323-6.360248 19.080745-6.360248 31.801242 6.360248 38.161491 25.440994 6.360248 19.080745-6.360248 31.801242-25.440994 38.161491C575.602484 1017.639752 543.801242 1017.639752 512 1017.639752z" fill="#000000" p-id="25849"></path><path d="M989.018634 864.993789l-318.012422 0c-19.080745 0-31.801242-12.720497-31.801242-31.801242s12.720497-31.801242 31.801242-31.801242l318.012422 0c19.080745 0 31.801242 12.720497 31.801242 31.801242S1001.73913 864.993789 989.018634 864.993789z" fill="#000000" p-id="25850"></path><path d="M830.012422 1024c-19.080745 0-31.801242-12.720497-31.801242-31.801242l0-318.012422c0-19.080745 12.720497-31.801242 31.801242-31.801242s31.801242 12.720497 31.801242 31.801242l0 318.012422C861.813665 1004.919255 842.732919 1024 830.012422 1024z" fill="#000000" p-id="25851"></path></svg>
src/assets/svgs/message.svg
New file
@@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 20.967v59.59c0 11.59 8.537 20.966 19.075 20.966h28.613l1 26.477L76.8 101.523h32.125c10.538 0 19.075-9.377 19.075-20.966v-59.59C128 9.377 119.463 0 108.925 0h-89.85C8.538 0 0 9.377 0 20.967zm82.325 33.1c0-5.524 4.013-9.935 9.037-9.935 5.026 0 9.038 4.41 9.038 9.934 0 5.524-4.025 9.934-9.038 9.934-5.024 0-9.037-4.41-9.037-9.934zm-27.613 0c0-5.524 4.013-9.935 9.038-9.935s9.037 4.41 9.037 9.934c0 5.524-4.025 9.934-9.037 9.934-5.025 0-9.038-4.41-9.038-9.934zm-27.1 0c0-5.524 4.013-9.935 9.038-9.935s9.038 4.41 9.038 9.934c0 5.524-4.026 9.934-9.05 9.934-5.013 0-9.025-4.41-9.025-9.934z"/></svg>
src/assets/svgs/money.svg
New file
@@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.122 127.892v-28.68H7.513V87.274h46.609v-12.4H7.513v-12.86h38.003L.099 0h22.6l32.556 45.07c3.617 5.144 6.44 9.611 8.487 13.385 1.788-3.05 4.89-7.779 9.301-14.186L103.93 0h24.01L82.385 62.013h38.34v12.862h-46.41v12.4h46.41v11.937h-46.41v28.68H54.123z"/></svg>
src/assets/svgs/pay/icon/alipay_app.svg
New file
@@ -0,0 +1 @@
<svg t="1627279997305" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11904" width="40" height="40"><path d="M938.7008 669.525333L938.7008 249.412267c0-90.555733-73.5232-164.078933-164.1472-164.078933L249.378133 85.333333c-90.555733 0-164.078933 73.48906699-164.078933 164.078933l0 525.2096c0 90.555733 73.454933 164.078933 164.07893301 164.078933l525.20959999 0c80.725333 0 147.8656-58.368 161.553067-135.099733-43.52-18.8416-232.106667-100.283733-330.376533-147.182933-74.786133 90.589867-153.088 144.930133-271.121067 144.930133s-196.81279999-72.704-187.357867-161.655467c6.2464-58.402133 46.2848-153.9072 220.296533-137.5232 91.682133 8.6016 133.666133 25.736533 208.418133 50.414933 19.3536-35.4304 35.4304-74.513067 47.616-116.0192L292.0448 436.565333l0-32.8704 164.0448 0 0-58.9824L256 344.712533l1e-8-36.181333 200.12373299 0L456.123733 223.3344c0 0 1.809067-13.312 16.520533-13.31200001l82.056533 1e-8 0 98.474667 213.333333 0 0 36.181333-213.333333 1e-8 0 58.98239999 174.045867 0c-16.00853301 65.1264-40.277333 124.962133-70.690133 177.220267C708.608 599.176533 938.7008 669.525333 938.7008 669.525333L938.7008 669.525333 938.7008 669.525333 938.7008 669.525333zM321.57013299 744.994133c-124.7232 0-144.452267-78.7456-137.83039999-111.65013299 6.5536-32.733867 42.666667-75.502933 112.0256-75.50293301 79.6672 0 151.04 20.445867 236.714667 62.088533C472.302933 698.333867 398.370133 744.994133 321.57013299 744.994133L321.57013299 744.994133 321.57013299 744.994133zM321.57013299 744.994133" fill="#1296db" p-id="11905"></path></svg>
src/assets/svgs/pay/icon/alipay_bar.svg
New file
@@ -0,0 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1627279586085" class="icon" viewBox="0 0 1036 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6737" xmlns:xlink="http://www.w3.org/1999/xlink" width="40.46875" height="40"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.eot?#iefix") format("embedded-opentype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff2") format("woff2"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff") format("woff"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.ttf") format("truetype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.svg#iconfont") format("svg"); }
</style></defs><path d="M27.587124 336.619083h69.148134a13.978733 13.978733 0 0 0 13.79235-13.978733V13.989916A13.978733 13.978733 0 0 0 96.735258 0.011183H27.587124a13.978733 13.978733 0 0 0-13.792351 13.978733v308.650434a13.978733 13.978733 0 0 0 13.792351 13.978733z m165.880969 0h27.584701a13.978733 13.978733 0 0 0 13.79235-13.978733V13.989916a13.978733 13.978733 0 0 0-13.79235-13.978733h-27.584701a13.978733 13.978733 0 0 0-13.79235 13.978733v308.650434a13.978733 13.978733 0 0 0 13.79235 13.978733z m138.109886 322.629167h-110.525185a27.771084 27.771084 0 0 0-27.584701 28.14385v111.829867a27.771084 27.771084 0 0 0 27.584701 28.14385h110.525185a27.957467 27.957467 0 0 0 27.584701-28.14385v-111.829867a27.957467 27.957467 0 0 0-27.584701-28.14385z m484.596091-322.629167h27.584701a13.978733 13.978733 0 0 0 13.79235-13.978733V13.989916a13.978733 13.978733 0 0 0-14.537883-13.978733h-27.5847a13.978733 13.978733 0 0 0-13.978734 13.978733v308.650434a13.978733 13.978733 0 0 0 13.978734 13.978733z m-469.871825 0H428.68358a13.978733 13.978733 0 0 0 13.792351-13.978733V13.989916A13.978733 13.978733 0 0 0 428.68358 0.011183h-83.126867a13.978733 13.978733 0 0 0-13.792351 13.978733v308.650434a13.978733 13.978733 0 0 0 13.792351 13.978733z m594.189361 0h69.148134a13.978733 13.978733 0 0 0 13.792351-13.978733V13.989916a13.978733 13.978733 0 0 0-14.537883-13.978733h-69.148135a13.978733 13.978733 0 0 0-13.79235 13.978733v308.650434a13.978733 13.978733 0 0 0 13.79235 13.978733z m-412.279444 126.181367H66.91396A67.470687 67.470687 0 0 0 0.002423 530.830286v425.139878a67.470687 67.470687 0 0 0 66.911537 68.029836h418.802853a67.470687 67.470687 0 0 0 66.911537-68.029836V487.775787a24.788954 24.788954 0 0 0-24.416188-24.975337z m-58.337914 433.899885a42.681733 42.681733 0 0 1-42.495349 43.054498H125.438257a42.681733 42.681733 0 0 1-42.495349-43.054498V590.100115a42.681733 42.681733 0 0 1 42.495349-43.054498h301.940642a42.681733 42.681733 0 0 1 42.495349 43.054498z m525.22761-433.899885a41.749817 41.749817 0 0 0-41.377051 42.122583v55.914934a41.377051 41.377051 0 1 0 82.940485 0v-55.914934a41.749817 41.749817 0 0 0-41.563434-42.122583z m0 223.659734a41.749817 41.749817 0 0 0-41.377051 42.122584V894.65012a45.477479 45.477479 0 0 1-45.291096 45.850246h-159.730327a43.240882 43.240882 0 0 0-43.613649 37.276622A41.9362 41.9362 0 0 0 745.534871 1024h233.538039a57.778765 57.778765 0 0 0 57.405999-58.337914V729.3283a41.749817 41.749817 0 0 0-41.377051-41.9362zM732.488053 322.64035V13.989916a13.978733 13.978733 0 0 0-13.79235-13.978733h-82.940485a13.978733 13.978733 0 0 0-13.79235 13.978733v308.650434a13.978733 13.978733 0 0 0 13.79235 13.978733h82.940485a13.978733 13.978733 0 0 0 13.79235-13.978733zM532.126208 0.011183c-11.36937 0-20.688525 6.337026-20.688526 13.978733v308.650434c0 7.828091 9.319156 13.978733 20.688526 13.978733s20.688525-6.337026 20.688525-13.978733V13.989916c0-7.641708-9.319156-13.978733-20.688525-13.978733z" p-id="6738" fill="#1977FD"></path><path d="M745.534871 462.80045a41.749817 41.749817 0 0 0-41.377051 42.122583v252.549117a41.377051 41.377051 0 1 0 82.940485 0V504.923033A41.749817 41.749817 0 0 0 745.534871 462.80045" p-id="6739" fill="#1977FD"></path></svg>
src/assets/svgs/pay/icon/alipay_pc.svg
New file
@@ -0,0 +1 @@
<svg t="1627279878333" class="icon" viewBox="0 0 1285 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8535" width="40" height="40"><path d="M1141.76 855.04h-286.72c0 40.96 30.72 71.68 71.68 71.68h107.52c20.48 0 35.84 15.36 35.84 35.84s-15.36 35.84-35.84 35.84h-783.36c-20.48 0-35.84-15.36-35.84-35.84s15.36-35.84 35.84-35.84h107.52c40.96 0 71.68-30.72 71.68-71.68h-286.72c-76.8 0-143.36-61.44-143.36-143.36v-568.32c0-76.8 61.44-143.36 143.36-143.36h993.28c76.8 0 143.36 61.44 143.36 143.36v568.32c5.12 76.8-56.32 143.36-138.24 143.36z m71.68-711.68c0-40.96-30.72-71.68-71.68-71.68h-993.28c-40.96 0-71.68 30.72-71.68 71.68v568.32c0 40.96 30.72 71.68 71.68 71.68h993.28c40.96 0 71.68-30.72 71.68-71.68v-568.32z m-143.36 568.32h-855.04c-40.96 0-71.68-30.72-71.68-71.68v-424.96c0-40.96 30.72-71.68 71.68-71.68h855.04c40.96 0 71.68 30.72 71.68 71.68v424.96c0 40.96-30.72 71.68-71.68 71.68z" p-id="8536" fill="#1977FD"></path></svg>
src/assets/svgs/pay/icon/alipay_qr.svg
New file
@@ -0,0 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1627279238245" class="icon" viewBox="0 0 1115 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4112" width="43.5546875" height="40" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.eot?#iefix") format("embedded-opentype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff2") format("woff2"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff") format("woff"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.ttf") format("truetype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.svg#iconfont") format("svg"); }
</style></defs><path d="M751.388 68.267a34.133 34.133 0 0 1 0-68.267h227.556a91.022 91.022 0 0 1 91.022 91.022v227.556a34.133 34.133 0 1 1-68.266 0V91.022a22.756 22.756 0 0 0-22.756-22.755H751.388M1001.7 705.422a34.133 34.133 0 0 1 68.266 0v227.556A91.022 91.022 0 0 1 978.944 1024H748.885a34.133 34.133 0 0 1 0-68.267H978.49a22.756 22.756 0 0 0 22.755-22.755V705.422M364.09 955.733a34.133 34.133 0 1 1 0 68.267H136.533a91.022 91.022 0 0 1-91.022-91.022V705.422a34.133 34.133 0 0 1 68.267 0v227.556a22.756 22.756 0 0 0 22.755 22.755H364.09M113.778 318.578a34.133 34.133 0 1 1-68.267 0V91.022A91.022 91.022 0 0 1 136.533 0H364.09a34.133 34.133 0 0 1 0 68.267H136.533a22.756 22.756 0 0 0-22.755 22.755v227.556M34.133 477.867a34.133 34.133 0 0 0 0 68.266h168.619v-68.266z m1046.756 0H912.27v68.266h168.619a34.133 34.133 0 0 0 0-68.266zM202.752 157.24h709.746v320.627H202.752z m0 388.893h709.746V866.76H202.752z" fill="#1977FD" p-id="4113"></path></svg>
src/assets/svgs/pay/icon/alipay_wap.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1645964864184" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8460" xmlns:xlink="http://www.w3.org/1999/xlink" width="40" height="40"><defs><style type="text/css"></style></defs><path d="M768.3 0 255.7 0c-70.8 0-128.1 57.4-128.1 128.1l0 767.8c0 70.8 57.4 128.1 128.1 128.1L512 1024l256.3 0c70.8 0 128.1-57.4 128.1-128.1L896.4 128.1C896.4 57.3 839 0 768.3 0zM383.9 96.1c0-17.7 14.3-32 32-32l192.2 0c17.7 0 32 14.3 32 32l0 0c0 17.7-14.3 32-32 32L415.9 128.1C398.2 128.1 383.9 113.8 383.9 96.1L383.9 96.1zM512 959.9 512 959.9 512 959.9c-35.4 0-64.1-28.8-64.1-64.1 0-35.4 28.7-64.1 64.1-64.1l0 0 0 0c35.4 0 64.1 28.7 64.1 64.1C576.1 931.1 547.4 959.9 512 959.9zM832.3 755.6c0 6.7-5.4 12.2-12.2 12.2L203.9 767.8c-6.7 0-12.2-5.4-12.2-12.2L191.7 204.3c0-6.7 5.4-12.2 12.2-12.2l616.3 0c6.7 0 12.2 5.4 12.2 12.2L832.4 755.6z" p-id="8461" fill="#1977FD"></path></svg>
src/assets/svgs/pay/icon/mock.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747409043186" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4834" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M44.416 853.333333v-85.205333a170.666667 170.666667 0 0 1 170.666667-170.666667h170.837333a37637.589333 37637.589333 0 0 1 0-206.165333C324.309333 352.170667 281.6 285.141333 281.6 211.968c0-116.906667 90.197333-211.072 231.168-211.072 140.970667 0 230.741333 94.208 230.741333 211.072 0 73.216-40.96 140.245333-102.528 179.328 0.256 0.170667 0.256 68.906667 0 206.165333h171.989334a170.666667 170.666667 0 0 1 170.666666 170.666667V853.333333a170.666667 170.666667 0 0 1-170.666666 170.666667H215.082667a170.666667 170.666667 0 0 1-170.666667-170.666667z m84.266667-84.650666v104.277333a85.333333 85.333333 0 0 0 85.333333 85.333333H811.52a85.333333 85.333333 0 0 0 85.333333-85.333333v-104.277333a85.333333 85.333333 0 0 0-85.333333-85.333334h-256.64l8.96-342.698666c66.944-21.333333 100.394667-64.256 100.394667-128.682667 0-61.952-57.344-129.322667-151.466667-129.322667-94.122667 0-146.645333 61.610667-146.645333 129.322667 0 71.466667 34.816 114.346667 104.362666 128.682667v342.698666H214.016a85.333333 85.333333 0 0 0-85.333333 85.333334z m167.125333 138.368c-50.432 0-91.434667-41.557333-91.434667-92.586667s41.002667-92.586667 91.434667-92.586667c50.389333 0 91.434667 41.557333 91.434667 92.586667 0 24.832-9.6 48.170667-27.008 65.706667-17.237333 17.322667-40.106667 26.88-64.426667 26.88z m0-119.466667a27.093333 27.093333 0 0 0-27.306667 26.88c0 14.805333 12.245333 26.88 27.306667 26.88a27.306667 27.306667 0 0 0 19.498667-8.106667 26.453333 26.453333 0 0 0 7.808-18.773333 27.093333 27.093333 0 0 0-27.306667-26.88z" fill="#1296db" p-id="4835"></path></svg>
src/assets/svgs/pay/icon/wallet.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1676209854312" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3033" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M173.077333 362.666667l91.114667-214.677334a65.6 65.6 0 0 1 86.016-34.773333c11.584 4.906667 24.96 10.282667 40.896 16.448 8.277333 3.2 16.789333 6.464 27.904 10.666667 28.202667 10.709333 39.296 14.933333 46.144 17.642666l51.477333-51.669333c28.181333-28.16 74.112-27.946667 102.570667 0.533333l195.925333 195.925334c16.426667 16.426667 23.445333 38.634667 21.056 59.904H896a42.666667 42.666667 0 0 1 42.666667 42.666666v490.666667a42.666667 42.666667 0 0 1-42.666667 42.666667H128a42.666667 42.666667 0 0 1-42.666667-42.666667V405.333333a42.666667 42.666667 0 0 1 42.666667-42.666666h45.077333z m48.96 0h39.104l169.194667-169.770667-27.328-10.389333c-11.2-4.245333-19.818667-7.530667-28.224-10.794667a1459.2 1459.2 0 0 1-42.197333-17.002667 20.522667 20.522667 0 0 0-26.901334 10.88L222.037333 362.666667z m108.842667 0h454.954667a23.509333 23.509333 0 0 0-5.290667-25.322667l-195.925333-195.925333a23.36 23.36 0 0 0-33.024-0.213334L330.88 362.666667zM128 405.333333v490.666667h768V405.333333H128z m597.333333 320a85.333333 85.333333 0 1 1 0-170.666666 85.333333 85.333333 0 0 1 0 170.666666z m0-42.666666a42.666667 42.666667 0 1 0 0-85.333334 42.666667 42.666667 0 0 0 0 85.333334z" fill="#4296d5" p-id="3034"></path></svg>
src/assets/svgs/pay/icon/wx_app.svg
New file
@@ -0,0 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1627279375144" class="icon" viewBox="0 0 1115 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4399" width="43.5546875" height="40" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.eot?#iefix") format("embedded-opentype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff2") format("woff2"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff") format("woff"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.ttf") format("truetype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.svg#iconfont") format("svg"); }
</style></defs><path d="M751.388 68.267a34.133 34.133 0 0 1 0-68.267h227.556a91.022 91.022 0 0 1 91.022 91.022v227.556a34.133 34.133 0 1 1-68.266 0V91.022a22.756 22.756 0 0 0-22.756-22.755H751.388M1001.7 705.422a34.133 34.133 0 0 1 68.266 0v227.556A91.022 91.022 0 0 1 978.944 1024H748.885a34.133 34.133 0 0 1 0-68.267H978.49a22.756 22.756 0 0 0 22.755-22.755V705.422M364.09 955.733a34.133 34.133 0 1 1 0 68.267H136.533a91.022 91.022 0 0 1-91.022-91.022V705.422a34.133 34.133 0 0 1 68.267 0v227.556a22.756 22.756 0 0 0 22.755 22.755H364.09M113.778 318.578a34.133 34.133 0 1 1-68.267 0V91.022A91.022 91.022 0 0 1 136.533 0H364.09a34.133 34.133 0 0 1 0 68.267H136.533a22.756 22.756 0 0 0-22.755 22.755v227.556M34.133 477.867a34.133 34.133 0 0 0 0 68.266h168.619v-68.266z m1046.756 0H912.27v68.266h168.619a34.133 34.133 0 0 0 0-68.266zM202.752 157.24h709.746v320.627H202.752z m0 388.893h709.746V866.76H202.752z" fill="#04C361" p-id="4400"></path></svg>
src/assets/svgs/pay/icon/wx_bar.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1627279586085" class="icon" viewBox="0 0 1036 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6737" xmlns:xlink="http://www.w3.org/1999/xlink" width="40.46875" height="40"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.eot?#iefix&quot;) format(&quot;embedded-opentype&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff2&quot;) format(&quot;woff2&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff&quot;) format(&quot;woff&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.ttf&quot;) format(&quot;truetype&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.svg#iconfont&quot;) format(&quot;svg&quot;); }</style></defs><path d="M27.587124 336.619083h69.148134a13.978733 13.978733 0 0 0 13.79235-13.978733V13.989916A13.978733 13.978733 0 0 0 96.735258 0.011183H27.587124a13.978733 13.978733 0 0 0-13.792351 13.978733v308.650434a13.978733 13.978733 0 0 0 13.792351 13.978733z m165.880969 0h27.584701a13.978733 13.978733 0 0 0 13.79235-13.978733V13.989916a13.978733 13.978733 0 0 0-13.79235-13.978733h-27.584701a13.978733 13.978733 0 0 0-13.79235 13.978733v308.650434a13.978733 13.978733 0 0 0 13.79235 13.978733z m138.109886 322.629167h-110.525185a27.771084 27.771084 0 0 0-27.584701 28.14385v111.829867a27.771084 27.771084 0 0 0 27.584701 28.14385h110.525185a27.957467 27.957467 0 0 0 27.584701-28.14385v-111.829867a27.957467 27.957467 0 0 0-27.584701-28.14385z m484.596091-322.629167h27.584701a13.978733 13.978733 0 0 0 13.79235-13.978733V13.989916a13.978733 13.978733 0 0 0-14.537883-13.978733h-27.5847a13.978733 13.978733 0 0 0-13.978734 13.978733v308.650434a13.978733 13.978733 0 0 0 13.978734 13.978733z m-469.871825 0H428.68358a13.978733 13.978733 0 0 0 13.792351-13.978733V13.989916A13.978733 13.978733 0 0 0 428.68358 0.011183h-83.126867a13.978733 13.978733 0 0 0-13.792351 13.978733v308.650434a13.978733 13.978733 0 0 0 13.792351 13.978733z m594.189361 0h69.148134a13.978733 13.978733 0 0 0 13.792351-13.978733V13.989916a13.978733 13.978733 0 0 0-14.537883-13.978733h-69.148135a13.978733 13.978733 0 0 0-13.79235 13.978733v308.650434a13.978733 13.978733 0 0 0 13.79235 13.978733z m-412.279444 126.181367H66.91396A67.470687 67.470687 0 0 0 0.002423 530.830286v425.139878a67.470687 67.470687 0 0 0 66.911537 68.029836h418.802853a67.470687 67.470687 0 0 0 66.911537-68.029836V487.775787a24.788954 24.788954 0 0 0-24.416188-24.975337z m-58.337914 433.899885a42.681733 42.681733 0 0 1-42.495349 43.054498H125.438257a42.681733 42.681733 0 0 1-42.495349-43.054498V590.100115a42.681733 42.681733 0 0 1 42.495349-43.054498h301.940642a42.681733 42.681733 0 0 1 42.495349 43.054498z m525.22761-433.899885a41.749817 41.749817 0 0 0-41.377051 42.122583v55.914934a41.377051 41.377051 0 1 0 82.940485 0v-55.914934a41.749817 41.749817 0 0 0-41.563434-42.122583z m0 223.659734a41.749817 41.749817 0 0 0-41.377051 42.122584V894.65012a45.477479 45.477479 0 0 1-45.291096 45.850246h-159.730327a43.240882 43.240882 0 0 0-43.613649 37.276622A41.9362 41.9362 0 0 0 745.534871 1024h233.538039a57.778765 57.778765 0 0 0 57.405999-58.337914V729.3283a41.749817 41.749817 0 0 0-41.377051-41.9362zM732.488053 322.64035V13.989916a13.978733 13.978733 0 0 0-13.79235-13.978733h-82.940485a13.978733 13.978733 0 0 0-13.79235 13.978733v308.650434a13.978733 13.978733 0 0 0 13.79235 13.978733h82.940485a13.978733 13.978733 0 0 0 13.79235-13.978733zM532.126208 0.011183c-11.36937 0-20.688525 6.337026-20.688526 13.978733v308.650434c0 7.828091 9.319156 13.978733 20.688526 13.978733s20.688525-6.337026 20.688525-13.978733V13.989916c0-7.641708-9.319156-13.978733-20.688525-13.978733z" p-id="6738" fill="#04C361"/><path d="M745.534871 462.80045a41.749817 41.749817 0 0 0-41.377051 42.122583v252.549117a41.377051 41.377051 0 1 0 82.940485 0V504.923033A41.749817 41.749817 0 0 0 745.534871 462.80045" p-id="6739" fill="#04C361"/></svg>
src/assets/svgs/pay/icon/wx_lite.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1676209433089" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2990" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M608.6 290.3c67.1 0 121.7 50.5 121.7 112.9 0 19.4-5.6 38.4-15.7 55.5-15.3 25-39.8 43.5-69.4 52.3-7.9 2.3-13.9 3.2-19.4 3.2-13 0-23.1-10.2-23.1-23.1 0-13 10.2-23.1 23.1-23.1 0.9 0 2.8 0 5.1-0.9 19.9-5.6 35.6-17.1 44.4-32.4 6-9.7 8.8-20.4 8.8-31.5 0-36.6-33.8-66.6-75-66.6-14.4 0-28.2 3.7-40.7 10.6-21.8 12.5-34.7 33.3-34.7 56v193.9c0 39.3-21.8 75.4-57.9 95.8-19.4 11.1-41.2 16.7-63.4 16.7-67.1 0-121.7-50.5-121.7-112.9 0-19.4 5.6-38.4 15.7-55.5 15.3-25 39.8-43.5 69.4-52.3 8.3-2.3 13.9-3.2 19.4-3.2 13 0 23.1 10.2 23.1 23.1 0 13-10.2 23.1-23.1 23.1-0.9 0-2.8 0-5.1 0.9-19.9 6-35.6 17.6-44.4 32.4-6 9.7-8.8 20.4-8.8 31.5 0 36.6 33.8 66.6 75.4 66.6 14.4 0 28.2-3.7 40.7-10.6 21.8-12.5 34.7-33.3 34.7-56V403.3c0-39.3 21.8-75.4 57.9-95.8 19-11.6 40.7-17.2 63-17.2zM510.8 929c231.1 0 418.4-187.3 418.4-418.4S741.9 92.1 510.8 92.1 92.4 279.5 92.4 510.6 279.7 929 510.8 929z m0 22C267.5 951 70.3 753.8 70.3 510.6S267.5 70.1 510.8 70.1s440.5 197.2 440.5 440.5S754.1 951 510.8 951z" p-id="2991" fill="#58bf6b"></path></svg>
src/assets/svgs/pay/icon/wx_native.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1627279375144" class="icon" viewBox="0 0 1115 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4399" width="43.5546875" height="40" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.eot?#iefix&quot;) format(&quot;embedded-opentype&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff2&quot;) format(&quot;woff2&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff&quot;) format(&quot;woff&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.ttf&quot;) format(&quot;truetype&quot;), url(&quot;//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.svg#iconfont&quot;) format(&quot;svg&quot;); }</style></defs><path d="M751.388 68.267a34.133 34.133 0 0 1 0-68.267h227.556a91.022 91.022 0 0 1 91.022 91.022v227.556a34.133 34.133 0 1 1-68.266 0V91.022a22.756 22.756 0 0 0-22.756-22.755H751.388M1001.7 705.422a34.133 34.133 0 0 1 68.266 0v227.556A91.022 91.022 0 0 1 978.944 1024H748.885a34.133 34.133 0 0 1 0-68.267H978.49a22.756 22.756 0 0 0 22.755-22.755V705.422M364.09 955.733a34.133 34.133 0 1 1 0 68.267H136.533a91.022 91.022 0 0 1-91.022-91.022V705.422a34.133 34.133 0 0 1 68.267 0v227.556a22.756 22.756 0 0 0 22.755 22.755H364.09M113.778 318.578a34.133 34.133 0 1 1-68.267 0V91.022A91.022 91.022 0 0 1 136.533 0H364.09a34.133 34.133 0 0 1 0 68.267H136.533a22.756 22.756 0 0 0-22.755 22.755v227.556M34.133 477.867a34.133 34.133 0 0 0 0 68.266h168.619v-68.266z m1046.756 0H912.27v68.266h168.619a34.133 34.133 0 0 0 0-68.266zM202.752 157.24h709.746v320.627H202.752z m0 388.893h709.746V866.76H202.752z" fill="#04C361" p-id="4400"/></svg>
src/assets/svgs/pay/icon/wx_pub.svg
New file
@@ -0,0 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1627279797174" class="icon" viewBox="0 0 1260 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7665" xmlns:xlink="http://www.w3.org/1999/xlink" width="49.21875" height="40"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.eot?#iefix") format("embedded-opentype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff2") format("woff2"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.woff") format("woff"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.ttf") format("truetype"), url("//at.alicdn.com/t/font_1031158_1uhr8ri0pk5.svg#iconfont") format("svg"); }
</style></defs><path d="M797.14798 481.753a269.194 269.194 0 0 0 102.892-211.929C900.03998 120.99 779.02998 0 630.15698 0 481.28298 0 360.27398 120.99 360.27398 269.824c0 85.878 40.33 162.462 102.912 211.929A450.974 450.974 0 0 0 309.84198 582.774c-85.543 85.524-132.608 199.208-132.608 320.236 0 25.01 0 51.712 0.197 76.367a44.898 44.898 0 0 0 44.82 44.623h816.01a44.8 44.8 0 0 0 44.82-44.623V903.01c0-121.009-47.066-234.732-132.609-320.236a451.072 451.072 0 0 0-153.344-101.021z" p-id="7666" fill="#04C361"></path><path d="M1186.18898 580.391A378.644 378.644 0 0 0 1061.81198 473.03a223.783 223.783 0 0 0 64.237-157.657c0-49.742-15.872-96.67-45.746-136.074A225.34 225.34 0 0 0 964.70998 99.9a37.297 37.297 0 0 0-46.14 25.718c-5.592 19.89 5.79 40.724 25.6 46.356 63.114 18.196 107.363 77.135 107.363 143.4a148.913 148.913 0 0 1-81.23 133.06 38.065 38.065 0 0 0-20.363 36.608c1.32 15.203 11.58 28.16 25.975 32.65 125.479 39.601 209.703 155.038 209.703 287.173v63.074c0 20.638 16.62 37.534 37.16 37.711h0.196a37.396 37.396 0 0 0 37.337-37.336V805.06c-0.197-81.644-25.777-159.35-74.142-224.69z m-901.77-62.503a36.982 36.982 0 0 0 25.955-32.65 37.455 37.455 0 0 0-20.362-36.628 148.913 148.913 0 0 1-81.231-133.06c0-66.245 44.071-125.184 107.382-143.4a37.612 37.612 0 0 0 25.58-46.356 37.376 37.376 0 0 0-46.139-25.718 225.32 225.32 0 0 0-115.593 79.4 223.252 223.252 0 0 0-45.746 136.074c0 60.258 23.533 116.381 64.237 157.676A380.475 380.475 0 0 0 74.14498 580.569 373.839 373.839 0 0 0 0.00198 805.258v63.232c0 20.657 16.798 37.356 37.356 37.356h0.197a37.317 37.317 0 0 0 37.14-37.73V805.06c0-132.332 84.401-247.769 209.723-287.173z" p-id="7667" fill="#04C361"></path></svg>
src/assets/svgs/peoples.svg
New file
@@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M95.648 118.762c0 5.035-3.563 9.121-7.979 9.121H7.98c-4.416 0-7.979-4.086-7.979-9.121C0 100.519 15.408 83.47 31.152 76.75c-9.099-6.43-15.216-17.863-15.216-30.987v-9.128c0-20.16 14.293-36.518 31.893-36.518s31.894 16.358 31.894 36.518v9.122c0 13.137-6.123 24.556-15.216 30.993 15.738 6.726 31.141 23.769 31.141 42.012z"/><path d="M106.032 118.252h15.867c3.376 0 6.101-3.125 6.101-6.972 0-13.957-11.787-26.984-23.819-32.123 6.955-4.919 11.638-13.66 11.638-23.704v-6.985c0-15.416-10.928-27.926-24.39-27.926-1.674 0-3.306.193-4.89.561 1.936 4.713 3.018 9.974 3.018 15.526v9.121c0 13.137-3.056 23.111-11.066 30.993 14.842 4.41 27.312 23.42 27.541 41.509z"/></svg>
src/assets/svgs/send.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1724297262365" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1396" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M707.91 103c16.28 0 29.522 13.007 29.897 29.195l0.009 0.706v111.878a29.96 29.96 0 0 1-0.898 7.3l171.177-0.001c16.28 0 29.522 13.007 29.897 29.195l0.008 0.706v637.12c0 16.278-13.01 29.518-29.2 29.893l-0.705 0.008H270.884c-16.28 0-29.522-13.007-29.897-29.195l-0.008-0.706V787.274c0-16.514 13.389-29.9 29.905-29.9 16.28 0 29.522 13.007 29.897 29.194l0.008 0.706v101.924h577.4V311.88h-577.4v88.787c0 16.278-13.009 29.518-29.2 29.893l-0.705 0.008c-16.28 0-29.522-13.008-29.897-29.195l-0.008-0.706V281.979c0-16.278 13.009-29.518 29.2-29.893l0.705-0.008h408.019a29.916 29.916 0 0 1-0.89-6.593l-0.008-0.706v-81.978H132.808v407.113h385.787L408.223 456.982c-11.36-11.624-11.329-30.143-0.066-41.729l0.554-0.555c11.625-11.358 30.147-11.327 41.734-0.066l0.555 0.554 161.028 164.762c11.244 11.504 11.344 29.793 0.362 41.42l-0.55 0.565-161.027 161.849c-11.648 11.707-30.583 11.757-42.292 0.11-11.524-11.461-11.754-29.979-0.657-41.723l0.546-0.563 111.319-111.89H102.905c-16.28 0-29.522-13.007-29.897-29.195l-0.008-0.705V132.9c0-16.278 13.01-29.518 29.2-29.893l0.705-0.008H707.91z" p-id="1397"></path></svg>
src/assets/svgs/shopping.svg
New file
@@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M42.913 101.36c1.642 0 3.198.332 4.667.996a12.28 12.28 0 013.89 2.772c1.123 1.184 1.987 2.582 2.592 4.193.605 1.612.908 3.318.908 5.118 0 1.8-.303 3.507-.908 5.118-.605 1.611-1.469 3.01-2.593 4.194a13.3 13.3 0 01-3.889 2.843 10.582 10.582 0 01-4.667 1.066c-1.729 0-3.306-.355-4.732-1.066a13.604 13.604 0 01-3.825-2.843c-1.123-1.185-1.988-2.583-2.593-4.194a14.437 14.437 0 01-.907-5.118c0-1.8.302-3.506.907-5.118.605-1.61 1.47-3.009 2.593-4.193a12.515 12.515 0 013.825-2.772c1.426-.664 3.003-.996 4.732-.996zm53.932.285c1.643 0 3.22.331 4.733.995a11.386 11.386 0 013.889 2.772c1.08 1.185 1.945 2.583 2.593 4.194.648 1.61.972 3.317.972 5.118 0 1.8-.324 3.506-.972 5.117-.648 1.611-1.513 3.01-2.593 4.194a12.253 12.253 0 01-3.89 2.843 11 11 0 01-4.732 1.066 10.58 10.58 0 01-4.667-1.066 12.478 12.478 0 01-3.824-2.843c-1.08-1.185-1.945-2.583-2.593-4.194a13.581 13.581 0 01-.973-5.117c0-1.801.325-3.507.973-5.118.648-1.611 1.512-3.01 2.593-4.194a11.559 11.559 0 013.824-2.772 11.212 11.212 0 014.667-.995zm21.781-80.747c2.42 0 4.3.355 5.64 1.066 1.34.71 2.29 1.587 2.852 2.63a6.427 6.427 0 01.778 3.34c-.044 1.185-.195 2.204-.454 3.057-.26.853-.8 2.606-1.62 5.26a589.268 589.268 0 01-2.788 8.743 1236.373 1236.373 0 00-3.047 9.453c-.994 3.128-1.75 5.592-2.269 7.393-1.123 3.79-2.55 6.42-4.278 7.89-1.728 1.469-3.846 2.203-6.352 2.203H39.023l1.945 12.795h65.342c4.148 0 6.223 1.943 6.223 5.828 0 1.896-.41 3.53-1.232 4.905-.821 1.374-2.442 2.061-4.862 2.061H38.505c-1.729 0-3.176-.426-4.343-1.28-1.167-.852-2.14-1.966-2.917-3.34a21.277 21.277 0 01-1.88-4.478 44.128 44.128 0 01-1.102-4.55c-.087-.568-.324-1.942-.713-4.122-.39-2.18-.865-4.904-1.426-8.174l-1.88-10.947c-.692-4.027-1.383-8.079-2.075-12.154-1.642-9.572-3.5-20.234-5.574-31.986H6.87c-1.296 0-2.377-.356-3.24-1.067a9.024 9.024 0 01-2.14-2.558 10.416 10.416 0 01-1.167-3.2C.108 8.53 0 7.488 0 6.54c0-1.896.583-3.46 1.75-4.69C2.917.615 4.494 0 6.482 0h13.095c1.728 0 3.111.284 4.148.853 1.037.569 1.858 1.28 2.463 2.132a8.548 8.548 0 011.297 2.701c.26.948.475 1.754.648 2.417.173.758.346 1.825.519 3.199.173 1.374.345 2.772.518 4.193.26 1.706.519 3.507.778 5.403h88.678z"/></svg>
src/components/AppLinkInput/AppLinkSelectDialog.vue
New file
@@ -0,0 +1,211 @@
<template>
  <Dialog v-model="dialogVisible" title="选择链接" width="65%">
    <div class="h-500px flex gap-8px">
      <!-- å·¦ä¾§åˆ†ç»„列表 -->
      <el-scrollbar wrap-class="h-full" ref="groupScrollbar" view-class="flex flex-col">
        <el-button
          v-for="(group, groupIndex) in APP_LINK_GROUP_LIST"
          :key="groupIndex"
          :class="[
            'm-r-16px m-l-0px! justify-start! w-90px',
            { active: activeGroup === group.name }
          ]"
          ref="groupBtnRefs"
          :text="activeGroup !== group.name"
          :type="activeGroup === group.name ? 'primary' : 'default'"
          @click="handleGroupSelected(group.name)"
        >
          {{ group.name }}
        </el-button>
      </el-scrollbar>
      <!-- å³ä¾§é“¾æŽ¥åˆ—表 -->
      <el-scrollbar class="h-full flex-1" @scroll="handleScroll" ref="linkScrollbar">
        <div v-for="(group, groupIndex) in APP_LINK_GROUP_LIST" :key="groupIndex">
          <!-- åˆ†ç»„标题 -->
          <div class="font-bold" ref="groupTitleRefs">{{ group.name }}</div>
          <!-- é“¾æŽ¥åˆ—表 -->
          <el-tooltip
            v-for="(appLink, appLinkIndex) in group.links"
            :key="appLinkIndex"
            :content="appLink.path"
            placement="bottom"
            :show-after="300"
          >
            <el-button
              class="m-b-8px m-r-8px m-l-0px!"
              :type="isSameLink(appLink.path, activeAppLink.path) ? 'primary' : 'default'"
              @click="handleAppLinkSelected(appLink)"
            >
              {{ appLink.name }}
            </el-button>
          </el-tooltip>
        </div>
      </el-scrollbar>
    </div>
    <!-- åº•部对话框操作按钮 -->
    <template #footer>
      <el-button type="primary" @click="handleSubmit">ç¡® å®š</el-button>
      <el-button @click="dialogVisible = false">取 æ¶ˆ</el-button>
    </template>
  </Dialog>
  <Dialog v-model="detailSelectDialog.visible" title="" width="50%">
    <el-form class="min-h-200px">
      <el-form-item
        label="选择分类"
        v-if="detailSelectDialog.type === APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST"
      >
        <ProductCategorySelect
          v-model="detailSelectDialog.id"
          :parent-id="0"
          @update:model-value="handleProductCategorySelected"
        />
      </el-form-item>
    </el-form>
  </Dialog>
</template>
<script lang="ts" setup>
import { APP_LINK_GROUP_LIST, APP_LINK_TYPE_ENUM, AppLink } from './data'
import { ButtonInstance, ScrollbarInstance } from 'element-plus'
import { split } from 'lodash-es'
import ProductCategorySelect from '@/views/mall/product/category/components/ProductCategorySelect.vue'
import { getUrlNumberValue } from '@/utils'
// APP é“¾æŽ¥é€‰æ‹©å¼¹æ¡†
defineOptions({ name: 'AppLinkSelectDialog' })
// é€‰ä¸­çš„分组,默认选中第一个
const activeGroup = ref(APP_LINK_GROUP_LIST[0].name)
// é€‰ä¸­çš„ APP é“¾æŽ¥
const activeAppLink = ref({} as AppLink)
/** æ‰“开弹窗 */
const dialogVisible = ref(false)
const open = (link: string) => {
  // è¿›å…¥é¡µé¢æ—¶å…ˆé‡ç½® activeAppLink
  activeAppLink.value = { name: '', path: '' }
  dialogVisible.value = true
  // æ»šåŠ¨åˆ°å½“å‰çš„é“¾æŽ¥
  const group = APP_LINK_GROUP_LIST.find((group) =>
    group.links.some((linkItem) => {
      const sameLink = isSameLink(linkItem.path, link)
      if (sameLink) {
        activeAppLink.value = { ...linkItem, path: link }
      }
      return sameLink
    })
  )
  if (group) {
    // ä½¿ç”¨ nextTick çš„原因:可能 Dom è¿˜æ²¡ç”Ÿæˆï¼Œå¯¼è‡´æ»šåŠ¨å¤±è´¥
    nextTick(() => handleGroupSelected(group.name))
  }
}
defineExpose({ open })
// å¤„理 APP é“¾æŽ¥é€‰ä¸­
const handleAppLinkSelected = (appLink: AppLink) => {
  // åªæœ‰ä¸åŒé“¾æŽ¥æ—¶æ‰æ›´æ–°ï¼ˆé¿å…é‡å¤è§¦å‘)
  if (!isSameLink(appLink.path, activeAppLink.value.path)) {
    // å¦‚果新链接的 path ä¸ºç©ºï¼Œåˆ™æ²¿ç”¨å½“前 activeAppLink çš„ path
    const path = appLink.path || activeAppLink.value.path
    activeAppLink.value = { ...appLink, path: path }
  }
  switch (appLink.type) {
    case APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST:
      detailSelectDialog.value.visible = true
      detailSelectDialog.value.type = appLink.type
      // è¿”显
      detailSelectDialog.value.id =
        getUrlNumberValue('id', 'http://127.0.0.1' + activeAppLink.value.path) || undefined
      break
    default:
      break
  }
}
// å¤„理绑定值更新
const emit = defineEmits<{
  change: [link: string]
  appLinkChange: [appLink: AppLink]
}>()
const handleSubmit = () => {
  dialogVisible.value = false
  emit('change', activeAppLink.value.path)
  emit('appLinkChange', activeAppLink.value)
}
// åˆ†ç»„标题引用列表
const groupTitleRefs = ref<HTMLInputElement[]>([])
/**
 * å¤„理右侧链接列表滚动
 * @param scrollTop æ»šåŠ¨æ¡çš„ä½ç½®
 */
const handleScroll = ({ scrollTop }: { scrollTop: number }) => {
  const titleEl = groupTitleRefs.value.find((titleEl: HTMLInputElement) => {
    // èŽ·å–æ ‡é¢˜çš„ä½ç½®ä¿¡æ¯
    const { offsetHeight, offsetTop } = titleEl
    // åˆ¤æ–­æ ‡é¢˜æ˜¯å¦åœ¨å¯è§†èŒƒå›´å†…
    return scrollTop >= offsetTop && scrollTop < offsetTop + offsetHeight
  })
  // åªéœ€å¤„理一次
  if (titleEl && activeGroup.value !== titleEl.textContent) {
    activeGroup.value = titleEl.textContent || ''
    // åŒæ­¥å·¦ä¾§çš„æ»šåŠ¨æ¡ä½ç½®
    scrollToGroupBtn(activeGroup.value)
  }
}
// å³ä¾§æ»šåŠ¨æ¡
const linkScrollbar = ref<ScrollbarInstance>()
// å¤„理分组选中
const handleGroupSelected = (group: string) => {
  activeGroup.value = group
  const titleRef = groupTitleRefs.value.find((item: HTMLInputElement) => item.textContent === group)
  if (titleRef) {
    // æ»šåŠ¨åˆ†ç»„æ ‡é¢˜
    linkScrollbar.value?.setScrollTop(titleRef.offsetTop)
  }
}
// åˆ†ç»„滚动条
const groupScrollbar = ref<ScrollbarInstance>()
// åˆ†ç»„引用列表
const groupBtnRefs = ref<ButtonInstance[]>([])
// è‡ªåŠ¨æ»šåŠ¨åˆ†ç»„æŒ‰é’®ï¼Œç¡®ä¿åˆ†ç»„æŒ‰é’®ä¿æŒåœ¨å¯è§†åŒºåŸŸå†…
const scrollToGroupBtn = (group: string) => {
  const groupBtn = groupBtnRefs.value
    .map((btn: ButtonInstance) => btn['ref'])
    .find((ref: HTMLButtonElement) => ref.textContent === group)
  if (groupBtn) {
    groupScrollbar.value?.setScrollTop(groupBtn.offsetTop)
  }
}
// æ˜¯å¦ä¸ºç›¸åŒçš„链接(不比较参数,只比较链接)
const isSameLink = (link1: string, link2: string) => {
  return split(link1, '?', 1)[0] === split(link2, '?', 1)[0]
}
// è¯¦æƒ…选择对话框
const detailSelectDialog = ref<{
  visible: boolean
  id?: number
  type?: APP_LINK_TYPE_ENUM
}>({
  visible: false,
  id: undefined,
  type: undefined
})
// å¤„理详情选择
const handleProductCategorySelected = (id: number) => {
  const url = new URL(activeAppLink.value.path, 'http://127.0.0.1')
  // ä¿®æ”¹ id å‚æ•°
  url.searchParams.set('id', `${id}`)
  // æŽ’除域名
  activeAppLink.value.path = `${url.pathname}${url.search}`
  // å…³é—­å¯¹è¯æ¡†
  detailSelectDialog.value.visible = false
  // é‡ç½® id
  detailSelectDialog.value.id = undefined
}
</script>
<style lang="scss" scoped></style>
src/components/AppLinkInput/data.ts
New file
@@ -0,0 +1,236 @@
// APP é“¾æŽ¥åˆ†ç»„
export interface AppLinkGroup {
  // åˆ†ç»„名称
  name: string
  // é“¾æŽ¥åˆ—表
  links: AppLink[]
}
// APP é“¾æŽ¥
export interface AppLink {
  // é“¾æŽ¥åç§°
  name: string
  // é“¾æŽ¥åœ°å€
  path: string
  // é“¾æŽ¥çš„类型
  type?: APP_LINK_TYPE_ENUM
}
// APP é“¾æŽ¥ç±»åž‹ï¼ˆéœ€è¦ç‰¹æ®Šå¤„理,例如商品详情)
export const enum APP_LINK_TYPE_ENUM {
  // æ‹¼å›¢æ´»åЍ
  ACTIVITY_COMBINATION,
  // ç§’杀活动
  ACTIVITY_SECKILL,
  // ç§¯åˆ†å•†åŸŽæ´»åЍ
  ACTIVITY_POINT,
  // æ–‡ç« è¯¦æƒ…
  ARTICLE_DETAIL,
  // ä¼˜æƒ åˆ¸è¯¦æƒ…
  COUPON_DETAIL,
  // è‡ªå®šä¹‰é¡µé¢è¯¦æƒ…
  DIY_PAGE_DETAIL,
  // å“ç±»åˆ—表
  PRODUCT_CATEGORY_LIST,
  // å•†å“åˆ—表
  PRODUCT_LIST,
  // å•†å“è¯¦æƒ…
  PRODUCT_DETAIL_NORMAL,
  // æ‹¼å›¢å•†å“è¯¦æƒ…
  PRODUCT_DETAIL_COMBINATION,
  // ç§’杀商品详情
  PRODUCT_DETAIL_SECKILL
}
// APP é“¾æŽ¥åˆ—表(做一下持久化?)
export const APP_LINK_GROUP_LIST = [
  {
    name: '商城',
    links: [
      {
        name: '首页',
        path: '/pages/index/index'
      },
      {
        name: '商品分类',
        path: '/pages/index/category',
        type: APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST
      },
      {
        name: '购物车',
        path: '/pages/index/cart'
      },
      {
        name: '个人中心',
        path: '/pages/index/user'
      },
      {
        name: '商品搜索',
        path: '/pages/index/search'
      },
      {
        name: '自定义页面',
        path: '/pages/index/page',
        type: APP_LINK_TYPE_ENUM.DIY_PAGE_DETAIL
      },
      {
        name: '客服',
        path: '/pages/chat/index'
      },
      {
        name: '系统设置',
        path: '/pages/public/setting'
      },
      {
        name: '常见问题',
        path: '/pages/public/faq'
      }
    ]
  },
  {
    name: '商品',
    links: [
      {
        name: '商品列表',
        path: '/pages/goods/list',
        type: APP_LINK_TYPE_ENUM.PRODUCT_LIST
      },
      {
        name: '商品详情',
        path: '/pages/goods/index',
        type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_NORMAL
      },
      {
        name: '拼团商品详情',
        path: '/pages/goods/groupon',
        type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_COMBINATION
      },
      {
        name: '秒杀商品详情',
        path: '/pages/goods/seckill',
        type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_SECKILL
      }
    ]
  },
  {
    name: '营销活动',
    links: [
      {
        name: '拼团订单',
        path: '/pages/activity/groupon/order'
      },
      {
        name: '营销商品',
        path: '/pages/activity/index'
      },
      {
        name: '拼团活动',
        path: '/pages/activity/groupon/list',
        type: APP_LINK_TYPE_ENUM.ACTIVITY_COMBINATION
      },
      {
        name: '秒杀活动',
        path: '/pages/activity/seckill/list',
        type: APP_LINK_TYPE_ENUM.ACTIVITY_SECKILL
      },
      {
        name: '积分商城活动',
        path: '/pages/activity/point/list',
        type: APP_LINK_TYPE_ENUM.ACTIVITY_POINT
      },
      {
        name: '签到中心',
        path: '/pages/app/sign'
      },
      {
        name: '优惠券中心',
        path: '/pages/coupon/list'
      },
      {
        name: '优惠券详情',
        path: '/pages/coupon/detail',
        type: APP_LINK_TYPE_ENUM.COUPON_DETAIL
      },
      {
        name: '文章详情',
        path: '/pages/public/richtext',
        type: APP_LINK_TYPE_ENUM.ARTICLE_DETAIL
      }
    ]
  },
  {
    name: '分销商城',
    links: [
      {
        name: '分销中心',
        path: '/pages/commission/index'
      },
      {
        name: '推广商品',
        path: '/pages/commission/goods'
      },
      {
        name: '分销订单',
        path: '/pages/commission/order'
      },
      {
        name: '我的团队',
        path: '/pages/commission/team'
      }
    ]
  },
  {
    name: '支付',
    links: [
      {
        name: '充值余额',
        path: '/pages/pay/recharge'
      },
      {
        name: '充值记录',
        path: '/pages/pay/recharge-log'
      }
    ]
  },
  {
    name: '用户中心',
    links: [
      {
        name: '用户信息',
        path: '/pages/user/info'
      },
      {
        name: '用户订单',
        path: '/pages/order/list'
      },
      {
        name: '售后订单',
        path: '/pages/order/aftersale/list'
      },
      {
        name: '商品收藏',
        path: '/pages/user/goods-collect'
      },
      {
        name: '浏览记录',
        path: '/pages/user/goods-log'
      },
      {
        name: '地址管理',
        path: '/pages/user/address/list'
      },
      {
        name: '用户佣金',
        path: '/pages/user/wallet/commission'
      },
      {
        name: '用户余额',
        path: '/pages/user/wallet/money'
      },
      {
        name: '用户积分',
        path: '/pages/user/wallet/score'
      }
    ]
  }
] as AppLinkGroup[]
src/components/AppLinkInput/index.vue
New file
@@ -0,0 +1,43 @@
<template>
  <el-input v-model="appLink" placeholder="输入或选择链接">
    <template #append>
      <el-button @click="handleOpenDialog">选择</el-button>
    </template>
  </el-input>
  <AppLinkSelectDialog ref="dialogRef" @change="handleLinkSelected" />
</template>
<script lang="ts" setup>
import { propTypes } from '@/utils/propTypes'
// APP é“¾æŽ¥è¾“入框
defineOptions({ name: 'AppLinkInput' })
// å®šä¹‰å±žæ€§
const props = defineProps({
  // å½“前选中的链接
  modelValue: propTypes.string.def('')
})
// å½“前的链接
const appLink = ref('')
// é€‰æ‹©å¯¹è¯æ¡†
const dialogRef = ref()
// å¤„理打开对话框
const handleOpenDialog = () => dialogRef.value?.open(appLink.value)
// å¤„理 APP é“¾æŽ¥é€‰ä¸­
const handleLinkSelected = (link: string) => (appLink.value = link)
// getter
watch(
  () => props.modelValue,
  () => (appLink.value = props.modelValue),
  { immediate: true }
)
// setter
const emit = defineEmits<{
  'update:modelValue': [link: string]
}>()
watch(
  () => appLink.value,
  () => emit('update:modelValue', appLink.value)
)
</script>
src/components/Backtop/index.ts
New file
@@ -0,0 +1,3 @@
import Backtop from './src/Backtop.vue'
export { Backtop }
src/components/Backtop/src/Backtop.vue
New file
@@ -0,0 +1,17 @@
<script lang="ts" setup>
import { ElBacktop } from 'element-plus'
import { useDesign } from '@/hooks/web/useDesign'
defineOptions({ name: 'BackTop' })
const { getPrefixCls, variables } = useDesign()
const prefixCls = getPrefixCls('backtop')
</script>
<template>
  <ElBacktop
    :class="`${prefixCls}-backtop`"
    :target="`.${variables.namespace}-layout-content-scrollbar .${variables.elNamespace}-scrollbar__wrap`"
  />
</template>
src/components/Card/index.ts
New file
@@ -0,0 +1,3 @@
import CardTitle from './src/CardTitle.vue'
export { CardTitle }
src/components/Card/src/CardTitle.vue
New file
@@ -0,0 +1,37 @@
<script lang="ts" setup>
defineComponent({
  name: 'CardTitle'
})
defineProps({
  title: {
    type: String,
    required: true
  }
})
</script>
<template>
  <span class="card-title">{{ title }}</span>
</template>
<style scoped lang="scss">
.card-title {
  font-size: 14px;
  font-weight: 600;
  &::before {
    position: relative;
    top: 8px;
    left: -5px;
    display: inline-block;
    width: 3px;
    height: 14px;
    //background-color: #105cfb;
    background: var(--el-color-primary);
    border-radius: 5px;
    content: '';
    transform: translateY(-50%);
  }
}
</style>
src/components/ColorInput/index.vue
New file
@@ -0,0 +1,34 @@
<template>
  <el-input v-model="color">
    <template #prepend>
      <el-color-picker v-model="color" :predefine="PREDEFINE_COLORS" />
    </template>
  </el-input>
</template>
<script setup lang="ts">
import { propTypes } from '@/utils/propTypes'
import { PREDEFINE_COLORS } from '@/utils/color'
// é¢œè‰²è¾“入框
defineOptions({ name: 'ColorInput' })
const props = defineProps({
  modelValue: propTypes.string.def('')
})
const emit = defineEmits(['update:modelValue'])
const color = computed({
  get: () => {
    return props.modelValue
  },
  set: (val: string) => {
    emit('update:modelValue', val)
  }
})
</script>
<style scoped lang="scss">
:deep(.el-input-group__prepend) {
  padding: 0;
}
</style>
src/components/ConfigGlobal/index.ts
New file
@@ -0,0 +1,3 @@
import ConfigGlobal from './src/ConfigGlobal.vue'
export { ConfigGlobal }
src/components/ConfigGlobal/src/ConfigGlobal.vue
New file
@@ -0,0 +1,62 @@
<script setup lang="ts">
import { provide, computed, watch, onMounted } from 'vue'
import { propTypes } from '@/utils/propTypes'
import { ComponentSize, ElConfigProvider } from 'element-plus'
import { useLocaleStore } from '@/store/modules/locale'
import { useWindowSize } from '@vueuse/core'
import { useAppStore } from '@/store/modules/app'
import { setCssVar } from '@/utils'
import { useDesign } from '@/hooks/web/useDesign'
const { variables } = useDesign()
const appStore = useAppStore()
const props = defineProps({
  size: propTypes.oneOf<ComponentSize>(['default', 'small', 'large']).def('default')
})
provide('configGlobal', props)
// åˆå§‹åŒ–所有主题色
onMounted(() => {
  appStore.setCssVarTheme()
})
const { width } = useWindowSize()
// ç›‘听窗口变化
watch(
  () => width.value,
  (width: number) => {
    if (width < 768) {
      !appStore.getMobile ? appStore.setMobile(true) : undefined
      setCssVar('--left-menu-min-width', '0')
      appStore.setCollapse(true)
      appStore.getLayout !== 'classic' ? appStore.setLayout('classic') : undefined
    } else {
      appStore.getMobile ? appStore.setMobile(false) : undefined
      setCssVar('--left-menu-min-width', '64px')
    }
  },
  {
    immediate: true
  }
)
// å¤šè¯­è¨€ç›¸å…³
const localeStore = useLocaleStore()
const currentLocale = computed(() => localeStore.currentLocale)
</script>
<template>
  <ElConfigProvider
    :namespace="variables.elNamespace"
    :locale="currentLocale.elLocale"
    :message="{ max: 5 }"
    :size="size"
  >
    <slot></slot>
  </ElConfigProvider>
</template>
src/components/ContentDetailWrap/index.ts
New file
@@ -0,0 +1,3 @@
import ContentDetailWrap from './src/ContentDetailWrap.vue'
export { ContentDetailWrap }
src/components/ContentDetailWrap/src/ContentDetailWrap.vue
New file
@@ -0,0 +1,58 @@
<script lang="ts" setup>
import { propTypes } from '@/utils/propTypes'
import { useDesign } from '@/hooks/web/useDesign'
defineOptions({ name: 'ContentDetailWrap' })
const { t } = useI18n()
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('content-detail-wrap')
defineProps({
  title: propTypes.string.def(''),
  message: propTypes.string.def('')
})
const emit = defineEmits(['back'])
const offset = ref(85)
const contentDetailWrap = ref()
onMounted(() => {
  offset.value = contentDetailWrap.value.getBoundingClientRect().top
})
</script>
<template>
  <div ref="contentDetailWrap" :class="[`${prefixCls}-container`]">
    <Sticky :offset="offset">
      <div
        :class="[
          `${prefixCls}-header`,
          'flex b-b-1 h-50px items-center text-center bg-white pr-10px'
        ]"
      >
        <div :class="[`${prefixCls}-header__back`, 'flex pl-10px pr-10px ']">
          <ElButton @click="emit('back')">
            <Icon class="mr-5px" icon="ep:arrow-left" />
            {{ t('common.back') }}
          </ElButton>
        </div>
        <div :class="[`${prefixCls}-header__title`, 'flex flex-1  justify-center']">
          <slot name="title">
            <label class="text-16px font-700">{{ title }}</label>
          </slot>
        </div>
        <div :class="[`${prefixCls}-header__right`, 'flex  pl-10px pr-10px']">
          <slot name="right"></slot>
        </div>
      </div>
    </Sticky>
    <div style="padding: var(--app-content-padding)">
      <ElCard :class="[`${prefixCls}-body`, 'mb-20px']" shadow="never">
        <div>
          <slot></slot>
        </div>
      </ElCard>
    </div>
  </div>
</template>
src/components/ContentWrap/index.ts
New file
@@ -0,0 +1,3 @@
import ContentWrap from './src/ContentWrap.vue'
export { ContentWrap }
src/components/ContentWrap/src/ContentWrap.vue
New file
@@ -0,0 +1,36 @@
<script lang="ts" setup>
import { propTypes } from '@/utils/propTypes'
import { useDesign } from '@/hooks/web/useDesign'
defineOptions({ name: 'ContentWrap' })
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('content-wrap')
defineProps({
  title: propTypes.string.def(''),
  message: propTypes.string.def(''),
  bodyStyle: propTypes.object.def({ padding: '10px' })
})
</script>
<template>
  <ElCard :body-style="bodyStyle" :class="[prefixCls, 'mb-15px']" shadow="never">
    <template v-if="title" #header>
      <div class="flex items-center">
        <span class="text-16px font-700">{{ title }}</span>
        <ElTooltip v-if="message" effect="dark" placement="right">
          <template #content>
            <div class="max-w-200px">{{ message }}</div>
          </template>
          <Icon :size="14" class="ml-5px" icon="ep:question-filled" />
        </ElTooltip>
        <div class="flex flex-grow pl-20px">
          <slot name="header"></slot>
        </div>
      </div>
    </template>
    <slot></slot>
  </ElCard>
</template>
src/components/CountTo/index.ts
New file
@@ -0,0 +1,3 @@
import CountTo from './src/CountTo.vue'
export { CountTo }
src/components/CountTo/src/CountTo.vue
New file
@@ -0,0 +1,182 @@
<script lang="ts" setup>
import { PropType } from 'vue'
import { isNumber } from '@/utils/is'
import { propTypes } from '@/utils/propTypes'
import { useDesign } from '@/hooks/web/useDesign'
defineOptions({ name: 'CountTo' })
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('count-to')
const props = defineProps({
  startVal: propTypes.number.def(0), // å¼€å§‹æ’­æ”¾å€¼
  endVal: propTypes.number.def(2021), // æœ€ç»ˆå€¼
  duration: propTypes.number.def(3000), // åŠ¨ç”»æ—¶é•¿
  autoplay: propTypes.bool.def(true), // æ˜¯å¦è‡ªåŠ¨æ’­æ”¾åŠ¨ç”», é»˜è®¤æ’­æ”¾
  decimals: propTypes.number.validate((value: number) => value >= 0).def(0), // æ˜¾ç¤ºçš„小数位数, é»˜è®¤ä¸æ˜¾ç¤ºå°æ•°
  decimal: propTypes.string.def('.'), // å°æ•°åˆ†éš”符号, é»˜è®¤ä¸ºç‚¹
  separator: propTypes.string.def(','), // æ•°å­—每三位的分隔符, é»˜è®¤ä¸ºé€—号
  prefix: propTypes.string.def(''), // å‰ç¼€, æ•°å€¼å‰é¢æ˜¾ç¤ºçš„内容
  suffix: propTypes.string.def(''), // åŽç¼€, æ•°å€¼åŽé¢æ˜¾ç¤ºçš„内容
  useEasing: propTypes.bool.def(true), // æ˜¯å¦ä½¿ç”¨ç¼“动效果, é»˜è®¤å¯ç”¨
  easingFn: {
    type: Function as PropType<(t: number, b: number, c: number, d: number) => number>,
    default(t: number, b: number, c: number, d: number) {
      return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b
    } // ç¼“动函数
  }
})
const emit = defineEmits(['mounted', 'callback'])
const formatNumber = (num: number | string) => {
  const { decimals, decimal, separator, suffix, prefix } = props
  num = Number(num).toFixed(decimals)
  num += ''
  const x = num.split('.')
  let x1 = x[0]
  const x2 = x.length > 1 ? decimal + x[1] : ''
  const rgx = /(\d+)(\d{3})/
  if (separator && !isNumber(separator)) {
    while (rgx.test(x1)) {
      x1 = x1.replace(rgx, '$1' + separator + '$2')
    }
  }
  return prefix + x1 + x2 + suffix
}
const state = reactive<{
  localStartVal: number
  printVal: number | null
  displayValue: string
  paused: boolean
  localDuration: number | null
  startTime: number | null
  timestamp: number | null
  rAF: any
  remaining: number | null
}>({
  localStartVal: props.startVal,
  displayValue: formatNumber(props.startVal),
  printVal: null,
  paused: false,
  localDuration: props.duration,
  startTime: null,
  timestamp: null,
  remaining: null,
  rAF: null
})
const displayValue = toRef(state, 'displayValue')
onMounted(() => {
  if (props.autoplay) {
    start()
  }
  emit('mounted')
})
const getCountDown = computed(() => {
  return props.startVal > props.endVal
})
watch([() => props.startVal, () => props.endVal], () => {
  if (props.autoplay) {
    start()
  }
})
const start = () => {
  const { startVal, duration } = props
  state.localStartVal = startVal
  state.startTime = null
  state.localDuration = duration
  state.paused = false
  state.rAF = requestAnimationFrame(count)
}
const pauseResume = () => {
  if (state.paused) {
    resume()
    state.paused = false
  } else {
    pause()
    state.paused = true
  }
}
const pause = () => {
  cancelAnimationFrame(state.rAF)
}
const resume = () => {
  state.startTime = null
  state.localDuration = +(state.remaining as number)
  state.localStartVal = +(state.printVal as number)
  requestAnimationFrame(count)
}
const reset = () => {
  state.startTime = null
  cancelAnimationFrame(state.rAF)
  state.displayValue = formatNumber(props.startVal)
}
const count = (timestamp: number) => {
  const { useEasing, easingFn, endVal } = props
  if (!state.startTime) state.startTime = timestamp
  state.timestamp = timestamp
  const progress = timestamp - state.startTime
  state.remaining = (state.localDuration as number) - progress
  if (useEasing) {
    if (unref(getCountDown)) {
      state.printVal =
        state.localStartVal -
        easingFn(progress, 0, state.localStartVal - endVal, state.localDuration as number)
    } else {
      state.printVal = easingFn(
        progress,
        state.localStartVal,
        endVal - state.localStartVal,
        state.localDuration as number
      )
    }
  } else {
    if (unref(getCountDown)) {
      state.printVal =
        state.localStartVal -
        (state.localStartVal - endVal) * (progress / (state.localDuration as number))
    } else {
      state.printVal =
        state.localStartVal +
        (endVal - state.localStartVal) * (progress / (state.localDuration as number))
    }
  }
  if (unref(getCountDown)) {
    state.printVal = state.printVal < endVal ? endVal : state.printVal
  } else {
    state.printVal = state.printVal > endVal ? endVal : state.printVal
  }
  state.displayValue = formatNumber(state.printVal!)
  if (progress < (state.localDuration as number)) {
    state.rAF = requestAnimationFrame(count)
  } else {
    emit('callback')
  }
}
defineExpose({
  pauseResume,
  reset,
  start,
  pause
})
</script>
<template>
  <span :class="prefixCls">
    {{ displayValue }}
  </span>
</template>
src/components/Crontab/index.ts
New file
@@ -0,0 +1,2 @@
import Crontab from './src/Crontab.vue'
export { Crontab }
src/components/Crontab/src/Crontab.vue
New file
@@ -0,0 +1,1015 @@
<script lang="ts" setup>
import { ElMessage } from 'element-plus'
import { PropType } from 'vue'
defineOptions({ name: 'Crontab' })
interface shortcutsType {
  text: string
  value: string
}
const props = defineProps({
  modelValue: {
    type: String,
    default: '* * * * * ?'
  },
  shortcuts: { type: Array as PropType<shortcutsType[]>, default: () => [] }
})
const defaultValue = ref('')
const dialogVisible = ref(false)
const getYear = () => {
  let v: number[] = []
  let y = new Date().getFullYear()
  for (let i = 0; i < 11; i++) {
    v.push(y + i)
  }
  return v
}
const cronValue = reactive({
  second: {
    type: '0',
    range: {
      start: 1,
      end: 2
    },
    loop: {
      start: 0,
      end: 1
    },
    appoint: [] as string[]
  },
  minute: {
    type: '0',
    range: {
      start: 1,
      end: 2
    },
    loop: {
      start: 0,
      end: 1
    },
    appoint: [] as string[]
  },
  hour: {
    type: '0',
    range: {
      start: 1,
      end: 2
    },
    loop: {
      start: 0,
      end: 1
    },
    appoint: [] as string[]
  },
  day: {
    type: '0',
    range: {
      start: 1,
      end: 2
    },
    loop: {
      start: 1,
      end: 1
    },
    appoint: [] as string[]
  },
  month: {
    type: '0',
    range: {
      start: 1,
      end: 2
    },
    loop: {
      start: 1,
      end: 1
    },
    appoint: [] as string[]
  },
  week: {
    type: '5',
    range: {
      start: '2',
      end: '3'
    },
    loop: {
      start: 0,
      end: '2'
    },
    last: '2',
    appoint: [] as string[]
  },
  year: {
    type: '-1',
    range: {
      start: getYear()[0],
      end: getYear()[1]
    },
    loop: {
      start: getYear()[0],
      end: 1
    },
    appoint: [] as string[]
  }
})
const data = reactive({
  second: ['0', '5', '15', '20', '25', '30', '35', '40', '45', '50', '55', '59'],
  minute: ['0', '5', '15', '20', '25', '30', '35', '40', '45', '50', '55', '59'],
  hour: [
    '0',
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
    '10',
    '11',
    '12',
    '13',
    '14',
    '15',
    '16',
    '17',
    '18',
    '19',
    '20',
    '21',
    '22',
    '23'
  ],
  day: [
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
    '10',
    '11',
    '12',
    '13',
    '14',
    '15',
    '16',
    '17',
    '18',
    '19',
    '20',
    '21',
    '22',
    '23',
    '24',
    '25',
    '26',
    '27',
    '28',
    '29',
    '30',
    '31'
  ],
  month: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
  week: [
    {
      value: '1',
      label: '周日'
    },
    {
      value: '2',
      label: '周一'
    },
    {
      value: '3',
      label: '周二'
    },
    {
      value: '4',
      label: '周三'
    },
    {
      value: '5',
      label: '周四'
    },
    {
      value: '6',
      label: '周五'
    },
    {
      value: '7',
      label: '周六'
    }
  ],
  year: getYear()
})
const value_second = computed(() => {
  let v = cronValue.second
  if (v.type == '0') {
    return '*'
  } else if (v.type == '1') {
    return v.range.start + '-' + v.range.end
  } else if (v.type == '2') {
    return v.loop.start + '/' + v.loop.end
  } else if (v.type == '3') {
    return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  } else {
    return '*'
  }
})
const value_minute = computed(() => {
  let v = cronValue.minute
  if (v.type == '0') {
    return '*'
  } else if (v.type == '1') {
    return v.range.start + '-' + v.range.end
  } else if (v.type == '2') {
    return v.loop.start + '/' + v.loop.end
  } else if (v.type == '3') {
    return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  } else {
    return '*'
  }
})
const value_hour = computed(() => {
  let v = cronValue.hour
  if (v.type == '0') {
    return '*'
  } else if (v.type == '1') {
    return v.range.start + '-' + v.range.end
  } else if (v.type == '2') {
    return v.loop.start + '/' + v.loop.end
  } else if (v.type == '3') {
    return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  } else {
    return '*'
  }
})
const value_day = computed(() => {
  let v = cronValue.day
  if (v.type == '0') {
    return '*'
  } else if (v.type == '1') {
    return v.range.start + '-' + v.range.end
  } else if (v.type == '2') {
    return v.loop.start + '/' + v.loop.end
  } else if (v.type == '3') {
    return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  } else if (v.type == '4') {
    return 'L'
  } else if (v.type == '5') {
    return '?'
  } else {
    return '*'
  }
})
const value_month = computed(() => {
  let v = cronValue.month
  if (v.type == '0') {
    return '*'
  } else if (v.type == '1') {
    return v.range.start + '-' + v.range.end
  } else if (v.type == '2') {
    return v.loop.start + '/' + v.loop.end
  } else if (v.type == '3') {
    return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  } else {
    return '*'
  }
})
const value_week = computed(() => {
  let v = cronValue.week
  if (v.type == '0') {
    return '*'
  } else if (v.type == '1') {
    return v.range.start + '-' + v.range.end
  } else if (v.type == '2') {
    return v.loop.end + '#' + v.loop.start
  } else if (v.type == '3') {
    return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  } else if (v.type == '4') {
    return v.last + 'L'
  } else if (v.type == '5') {
    return '?'
  } else {
    return '*'
  }
})
const value_year = computed(() => {
  let v = cronValue.year
  if (v.type == '-1') {
    return ''
  } else if (v.type == '0') {
    return '*'
  } else if (v.type == '1') {
    return v.range.start + '-' + v.range.end
  } else if (v.type == '2') {
    return v.loop.start + '/' + v.loop.end
  } else if (v.type == '3') {
    return v.appoint.length > 0 ? v.appoint.join(',') : ''
  } else {
    return ''
  }
})
watch(
  () => cronValue.week.type,
  (val) => {
    if (val != '5') {
      cronValue.day.type = '5'
    }
  }
)
watch(
  () => cronValue.day.type,
  (val) => {
    if (val != '5') {
      cronValue.week.type = '5'
    }
  }
)
watch(
  () => props.modelValue,
  () => {
    defaultValue.value = props.modelValue
  }
)
onMounted(() => {
  defaultValue.value = props.modelValue
})
const emit = defineEmits(['update:modelValue'])
const select = ref()
watch(
  () => select.value,
  () => {
    if (select.value == 'custom') {
      open()
    } else {
      defaultValue.value = select.value
      emit('update:modelValue', defaultValue.value)
    }
  }
)
const open = () => {
  set()
  dialogVisible.value = true
}
const set = () => {
  defaultValue.value = props.modelValue
  let arr = (props.modelValue || '* * * * * ?').split(' ')
  //简单检查
  if (arr.length < 6) {
    ElMessage.warning('cron表达式错误,已转换为默认表达式')
    arr = '* * * * * ?'.split(' ')
  }
  //秒
  if (arr[0] == '*') {
    cronValue.second.type = '0'
  } else if (arr[0].includes('-')) {
    cronValue.second.type = '1'
    cronValue.second.range.start = Number(arr[0].split('-')[0])
    cronValue.second.range.end = Number(arr[0].split('-')[1])
  } else if (arr[0].includes('/')) {
    cronValue.second.type = '2'
    cronValue.second.loop.start = Number(arr[0].split('/')[0])
    cronValue.second.loop.end = Number(arr[0].split('/')[1])
  } else {
    cronValue.second.type = '3'
    cronValue.second.appoint = arr[0].split(',')
  }
  //分
  if (arr[1] == '*') {
    cronValue.minute.type = '0'
  } else if (arr[1].includes('-')) {
    cronValue.minute.type = '1'
    cronValue.minute.range.start = Number(arr[1].split('-')[0])
    cronValue.minute.range.end = Number(arr[1].split('-')[1])
  } else if (arr[1].includes('/')) {
    cronValue.minute.type = '2'
    cronValue.minute.loop.start = Number(arr[1].split('/')[0])
    cronValue.minute.loop.end = Number(arr[1].split('/')[1])
  } else {
    cronValue.minute.type = '3'
    cronValue.minute.appoint = arr[1].split(',')
  }
  //小时
  if (arr[2] == '*') {
    cronValue.hour.type = '0'
  } else if (arr[2].includes('-')) {
    cronValue.hour.type = '1'
    cronValue.hour.range.start = Number(arr[2].split('-')[0])
    cronValue.hour.range.end = Number(arr[2].split('-')[1])
  } else if (arr[2].includes('/')) {
    cronValue.hour.type = '2'
    cronValue.hour.loop.start = Number(arr[2].split('/')[0])
    cronValue.hour.loop.end = Number(arr[2].split('/')[1])
  } else {
    cronValue.hour.type = '3'
    cronValue.hour.appoint = arr[2].split(',')
  }
  //日
  if (arr[3] == '*') {
    cronValue.day.type = '0'
  } else if (arr[3] == 'L') {
    cronValue.day.type = '4'
  } else if (arr[3] == '?') {
    cronValue.day.type = '5'
  } else if (arr[3].includes('-')) {
    cronValue.day.type = '1'
    cronValue.day.range.start = Number(arr[3].split('-')[0])
    cronValue.day.range.end = Number(arr[3].split('-')[1])
  } else if (arr[3].includes('/')) {
    cronValue.day.type = '2'
    cronValue.day.loop.start = Number(arr[3].split('/')[0])
    cronValue.day.loop.end = Number(arr[3].split('/')[1])
  } else {
    cronValue.day.type = '3'
    cronValue.day.appoint = arr[3].split(',')
  }
  //月
  if (arr[4] == '*') {
    cronValue.month.type = '0'
  } else if (arr[4].includes('-')) {
    cronValue.month.type = '1'
    cronValue.month.range.start = Number(arr[4].split('-')[0])
    cronValue.month.range.end = Number(arr[4].split('-')[1])
  } else if (arr[4].includes('/')) {
    cronValue.month.type = '2'
    cronValue.month.loop.start = Number(arr[4].split('/')[0])
    cronValue.month.loop.end = Number(arr[4].split('/')[1])
  } else {
    cronValue.month.type = '3'
    cronValue.month.appoint = arr[4].split(',')
  }
  //周
  if (arr[5] == '*') {
    cronValue.week.type = '0'
  } else if (arr[5] == '?') {
    cronValue.week.type = '5'
  } else if (arr[5].includes('-')) {
    cronValue.week.type = '1'
    cronValue.week.range.start = arr[5].split('-')[0]
    cronValue.week.range.end = arr[5].split('-')[1]
  } else if (arr[5].includes('#')) {
    cronValue.week.type = '2'
    cronValue.week.loop.start = Number(arr[5].split('#')[1])
    cronValue.week.loop.end = arr[5].split('#')[0]
  } else if (arr[5].includes('L')) {
    cronValue.week.type = '4'
    cronValue.week.last = arr[5].split('L')[0]
  } else {
    cronValue.week.type = '3'
    cronValue.week.appoint = arr[5].split(',')
  }
  //å¹´
  if (!arr[6]) {
    cronValue.year.type = '-1'
  } else if (arr[6] == '*') {
    cronValue.year.type = '0'
  } else if (arr[6].includes('-')) {
    cronValue.year.type = '1'
    cronValue.year.range.start = Number(arr[6].split('-')[0])
    cronValue.year.range.end = Number(arr[6].split('-')[1])
  } else if (arr[6].includes('/')) {
    cronValue.year.type = '2'
    cronValue.year.loop.start = Number(arr[6].split('/')[1])
    cronValue.year.loop.end = Number(arr[6].split('/')[0])
  } else {
    cronValue.year.type = '3'
    cronValue.year.appoint = arr[6].split(',')
  }
}
const submit = () => {
  let year = value_year.value ? ' ' + value_year.value : ''
  defaultValue.value =
    value_second.value +
    ' ' +
    value_minute.value +
    ' ' +
    value_hour.value +
    ' ' +
    value_day.value +
    ' ' +
    value_month.value +
    ' ' +
    value_week.value +
    year
  emit('update:modelValue', defaultValue.value)
  dialogVisible.value = false
}
const inputChange = () => {
  emit('update:modelValue', defaultValue.value)
}
</script>
<template>
  <el-input v-model="defaultValue" class="input-with-select" v-bind="$attrs" @input="inputChange">
    <template #append>
      <el-select v-model="select" placeholder="生成器" style="width: 115px">
        <el-option label="每分钟" value="0 * * * * ?" />
        <el-option label="每小时" value="0 0 * * * ?" />
        <el-option label="每天零点" value="0 0 0 * * ?" />
        <el-option label="每月一号零点" value="0 0 0 1 * ?" />
        <el-option label="每月最后一天零点" value="0 0 0 L * ?" />
        <el-option label="每周星期日零点" value="0 0 0 ? * 1" />
        <el-option
          v-for="(item, index) in shortcuts"
          :key="index"
          :label="item.text"
          :value="item.value"
        />
        <el-option label="自定义" value="custom" />
      </el-select>
    </template>
  </el-input>
  <el-dialog
    v-model="dialogVisible"
    :width="580"
    append-to-body
    destroy-on-close
    title="cron规则生成器"
  >
    <div class="sc-cron">
      <el-tabs>
        <el-tab-pane>
          <template #label>
            <div class="sc-cron-num">
              <h2>秒</h2>
              <h4>{{ value_second }}</h4>
            </div>
          </template>
          <el-form>
            <el-form-item label="类型">
              <el-radio-group v-model="cronValue.second.type">
                <el-radio-button value="0">任意值</el-radio-button>
                <el-radio-button value="1">范围</el-radio-button>
                <el-radio-button value="2">间隔</el-radio-button>
                <el-radio-button value="3">指定</el-radio-button>
              </el-radio-group>
            </el-form-item>
            <el-form-item v-if="cronValue.second.type == '1'" label="范围">
              <el-input-number
                v-model="cronValue.second.range.start"
                :max="59"
                :min="0"
                controls-position="right"
              />
              <span style="padding: 0 15px">-</span>
              <el-input-number
                v-model="cronValue.second.range.end"
                :max="59"
                :min="0"
                controls-position="right"
              />
            </el-form-item>
            <el-form-item v-if="cronValue.second.type == '2'" label="间隔">
              <el-input-number
                v-model="cronValue.second.loop.start"
                :max="59"
                :min="0"
                controls-position="right"
              />
              ç§’开始,每
              <el-input-number
                v-model="cronValue.second.loop.end"
                :max="59"
                :min="0"
                controls-position="right"
              />
              ç§’执行一次
            </el-form-item>
            <el-form-item v-if="cronValue.second.type == '3'" label="指定">
              <el-select v-model="cronValue.second.appoint" multiple style="width: 100%">
                <el-option
                  v-for="(item, index) in data.second"
                  :key="index"
                  :label="item"
                  :value="item"
                />
              </el-select>
            </el-form-item>
          </el-form>
        </el-tab-pane>
        <el-tab-pane>
          <template #label>
            <div class="sc-cron-num">
              <h2>分钟</h2>
              <h4>{{ value_minute }}</h4>
            </div>
          </template>
          <el-form>
            <el-form-item label="类型">
              <el-radio-group v-model="cronValue.minute.type">
                <el-radio-button value="0">任意值</el-radio-button>
                <el-radio-button value="1">范围</el-radio-button>
                <el-radio-button value="2">间隔</el-radio-button>
                <el-radio-button value="3">指定</el-radio-button>
              </el-radio-group>
            </el-form-item>
            <el-form-item v-if="cronValue.minute.type == '1'" label="范围">
              <el-input-number
                v-model="cronValue.minute.range.start"
                :max="59"
                :min="0"
                controls-position="right"
              />
              <span style="padding: 0 15px">-</span>
              <el-input-number
                v-model="cronValue.minute.range.end"
                :max="59"
                :min="0"
                controls-position="right"
              />
            </el-form-item>
            <el-form-item v-if="cronValue.minute.type == '2'" label="间隔">
              <el-input-number
                v-model="cronValue.minute.loop.start"
                :max="59"
                :min="0"
                controls-position="right"
              />
              åˆ†é’Ÿå¼€å§‹ï¼Œæ¯
              <el-input-number
                v-model="cronValue.minute.loop.end"
                :max="59"
                :min="0"
                controls-position="right"
              />
              åˆ†é’Ÿæ‰§è¡Œä¸€æ¬¡
            </el-form-item>
            <el-form-item v-if="cronValue.minute.type == '3'" label="指定">
              <el-select v-model="cronValue.minute.appoint" multiple style="width: 100%">
                <el-option
                  v-for="(item, index) in data.minute"
                  :key="index"
                  :label="item"
                  :value="item"
                />
              </el-select>
            </el-form-item>
          </el-form>
        </el-tab-pane>
        <el-tab-pane>
          <template #label>
            <div class="sc-cron-num">
              <h2>小时</h2>
              <h4>{{ value_hour }}</h4>
            </div>
          </template>
          <el-form>
            <el-form-item label="类型">
              <el-radio-group v-model="cronValue.hour.type">
                <el-radio-button value="0">任意值</el-radio-button>
                <el-radio-button value="1">范围</el-radio-button>
                <el-radio-button value="2">间隔</el-radio-button>
                <el-radio-button value="3">指定</el-radio-button>
              </el-radio-group>
            </el-form-item>
            <el-form-item v-if="cronValue.hour.type == '1'" label="范围">
              <el-input-number
                v-model="cronValue.hour.range.start"
                :max="23"
                :min="0"
                controls-position="right"
              />
              <span style="padding: 0 15px">-</span>
              <el-input-number
                v-model="cronValue.hour.range.end"
                :max="23"
                :min="0"
                controls-position="right"
              />
            </el-form-item>
            <el-form-item v-if="cronValue.hour.type == '2'" label="间隔">
              <el-input-number
                v-model="cronValue.hour.loop.start"
                :max="23"
                :min="0"
                controls-position="right"
              />
              å°æ—¶å¼€å§‹ï¼Œæ¯
              <el-input-number
                v-model="cronValue.hour.loop.end"
                :max="23"
                :min="0"
                controls-position="right"
              />
              å°æ—¶æ‰§è¡Œä¸€æ¬¡
            </el-form-item>
            <el-form-item v-if="cronValue.hour.type == '3'" label="指定">
              <el-select v-model="cronValue.hour.appoint" multiple style="width: 100%">
                <el-option
                  v-for="(item, index) in data.hour"
                  :key="index"
                  :label="item"
                  :value="item"
                />
              </el-select>
            </el-form-item>
          </el-form>
        </el-tab-pane>
        <el-tab-pane>
          <template #label>
            <div class="sc-cron-num">
              <h2>日</h2>
              <h4>{{ value_day }}</h4>
            </div>
          </template>
          <el-form>
            <el-form-item label="类型">
              <el-radio-group v-model="cronValue.day.type">
                <el-radio-button value="0">任意值</el-radio-button>
                <el-radio-button value="1">范围</el-radio-button>
                <el-radio-button value="2">间隔</el-radio-button>
                <el-radio-button value="3">指定</el-radio-button>
                <el-radio-button value="4">本月最后一天</el-radio-button>
                <el-radio-button value="5">不指定</el-radio-button>
              </el-radio-group>
            </el-form-item>
            <el-form-item v-if="cronValue.day.type == '1'" label="范围">
              <el-input-number
                v-model="cronValue.day.range.start"
                :max="31"
                :min="1"
                controls-position="right"
              />
              <span style="padding: 0 15px">-</span>
              <el-input-number
                v-model="cronValue.day.range.end"
                :max="31"
                :min="1"
                controls-position="right"
              />
            </el-form-item>
            <el-form-item v-if="cronValue.day.type == '2'" label="间隔">
              <el-input-number
                v-model="cronValue.day.loop.start"
                :max="31"
                :min="1"
                controls-position="right"
              />
              å·å¼€å§‹ï¼Œæ¯
              <el-input-number
                v-model="cronValue.day.loop.end"
                :max="31"
                :min="1"
                controls-position="right"
              />
              å¤©æ‰§è¡Œä¸€æ¬¡
            </el-form-item>
            <el-form-item v-if="cronValue.day.type == '3'" label="指定">
              <el-select v-model="cronValue.day.appoint" multiple style="width: 100%">
                <el-option
                  v-for="(item, index) in data.day"
                  :key="index"
                  :label="item"
                  :value="item"
                />
              </el-select>
            </el-form-item>
          </el-form>
        </el-tab-pane>
        <el-tab-pane>
          <template #label>
            <div class="sc-cron-num">
              <h2>月</h2>
              <h4>{{ value_month }}</h4>
            </div>
          </template>
          <el-form>
            <el-form-item label="类型">
              <el-radio-group v-model="cronValue.month.type">
                <el-radio-button value="0">任意值</el-radio-button>
                <el-radio-button value="1">范围</el-radio-button>
                <el-radio-button value="2">间隔</el-radio-button>
                <el-radio-button value="3">指定</el-radio-button>
              </el-radio-group>
            </el-form-item>
            <el-form-item v-if="cronValue.month.type == '1'" label="范围">
              <el-input-number
                v-model="cronValue.month.range.start"
                :max="12"
                :min="1"
                controls-position="right"
              />
              <span style="padding: 0 15px">-</span>
              <el-input-number
                v-model="cronValue.month.range.end"
                :max="12"
                :min="1"
                controls-position="right"
              />
            </el-form-item>
            <el-form-item v-if="cronValue.month.type == '2'" label="间隔">
              <el-input-number
                v-model="cronValue.month.loop.start"
                :max="12"
                :min="1"
                controls-position="right"
              />
              æœˆå¼€å§‹ï¼Œæ¯
              <el-input-number
                v-model="cronValue.month.loop.end"
                :max="12"
                :min="1"
                controls-position="right"
              />
              æœˆæ‰§è¡Œä¸€æ¬¡
            </el-form-item>
            <el-form-item v-if="cronValue.month.type == '3'" label="指定">
              <el-select v-model="cronValue.month.appoint" multiple style="width: 100%">
                <el-option
                  v-for="(item, index) in data.month"
                  :key="index"
                  :label="item"
                  :value="item"
                />
              </el-select>
            </el-form-item>
          </el-form>
        </el-tab-pane>
        <el-tab-pane>
          <template #label>
            <div class="sc-cron-num">
              <h2>周</h2>
              <h4>{{ value_week }}</h4>
            </div>
          </template>
          <el-form>
            <el-form>
              <el-form-item label="类型">
                <el-radio-group v-model="cronValue.week.type">
                  <el-radio-button value="0">任意值</el-radio-button>
                  <el-radio-button value="1">范围</el-radio-button>
                  <el-radio-button value="2">间隔</el-radio-button>
                  <el-radio-button value="3">指定</el-radio-button>
                  <el-radio-button value="4">本月最后一周</el-radio-button>
                  <el-radio-button value="5">不指定</el-radio-button>
                </el-radio-group>
              </el-form-item>
              <el-form-item v-if="cronValue.week.type == '1'" label="范围">
                <el-select v-model="cronValue.week.range.start">
                  <el-option
                    v-for="(item, index) in data.week"
                    :key="index"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
                <span style="padding: 0 15px">-</span>
                <el-select v-model="cronValue.week.range.end">
                  <el-option
                    v-for="(item, index) in data.week"
                    :key="index"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
              <el-form-item v-if="cronValue.week.type == '2'" label="间隔">
                ç¬¬
                <el-input-number
                  v-model="cronValue.week.loop.start"
                  :max="4"
                  :min="1"
                  controls-position="right"
                />
                å‘¨çš„æ˜ŸæœŸ
                <el-select v-model="cronValue.week.loop.end">
                  <el-option
                    v-for="(item, index) in data.week"
                    :key="index"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
                æ‰§è¡Œä¸€æ¬¡
              </el-form-item>
              <el-form-item v-if="cronValue.week.type == '3'" label="指定">
                <el-select v-model="cronValue.week.appoint" multiple style="width: 100%">
                  <el-option
                    v-for="(item, index) in data.week"
                    :key="index"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
              <el-form-item v-if="cronValue.week.type == '4'" label="最后一周">
                <el-select v-model="cronValue.week.last">
                  <el-option
                    v-for="(item, index) in data.week"
                    :key="index"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
            </el-form>
          </el-form>
        </el-tab-pane>
        <el-tab-pane>
          <template #label>
            <div class="sc-cron-num">
              <h2>å¹´</h2>
              <h4>{{ value_year }}</h4>
            </div>
          </template>
          <el-form>
            <el-form-item label="类型">
              <el-radio-group v-model="cronValue.year.type">
                <el-radio-button value="-1">忽略</el-radio-button>
                <el-radio-button value="0">任意值</el-radio-button>
                <el-radio-button value="1">范围</el-radio-button>
                <el-radio-button value="2">间隔</el-radio-button>
                <el-radio-button value="3">指定</el-radio-button>
              </el-radio-group>
            </el-form-item>
            <el-form-item v-if="cronValue.year.type == '1'" label="范围">
              <el-input-number v-model="cronValue.year.range.start" controls-position="right" />
              <span style="padding: 0 15px">-</span>
              <el-input-number v-model="cronValue.year.range.end" controls-position="right" />
            </el-form-item>
            <el-form-item v-if="cronValue.year.type == '2'" label="间隔">
              <el-input-number v-model="cronValue.year.loop.start" controls-position="right" />
              å¹´å¼€å§‹ï¼Œæ¯
              <el-input-number
                v-model="cronValue.year.loop.end"
                :min="1"
                controls-position="right"
              />
              å¹´æ‰§è¡Œä¸€æ¬¡
            </el-form-item>
            <el-form-item v-if="cronValue.year.type == '3'" label="指定">
              <el-select v-model="cronValue.year.appoint" multiple style="width: 100%">
                <el-option
                  v-for="(item, index) in data.year"
                  :key="index"
                  :label="item"
                  :value="item"
                />
              </el-select>
            </el-form-item>
          </el-form>
        </el-tab-pane>
      </el-tabs>
    </div>
    <template #footer>
      <el-button @click="dialogVisible = false">取 æ¶ˆ</el-button>
      <el-button type="primary" @click="submit()">ç¡® è®¤</el-button>
    </template>
  </el-dialog>
</template>
<style scoped>
.sc-cron:deep(.el-tabs__item) {
  height: auto;
  padding: 0 7px;
  line-height: 1;
  vertical-align: bottom;
}
.sc-cron-num {
  width: 100%;
  margin-bottom: 15px;
  text-align: center;
}
.sc-cron-num h2 {
  margin-bottom: 15px;
  font-size: 12px;
  font-weight: normal;
}
.sc-cron-num h4 {
  display: block;
  width: 100%;
  height: 32px;
  padding: 0 15px;
  font-size: 12px;
  line-height: 30px;
  background: var(--el-color-primary-light-9);
  border-radius: 4px;
}
.sc-cron:deep(.el-tabs__item.is-active) .sc-cron-num h4 {
  color: #fff;
  background: var(--el-color-primary);
}
[data-theme='dark'] .sc-cron-num h4 {
  background: var(--el-color-white);
}
.input-with-select .el-input-group__prepend {
  background-color: var(--el-fill-color-blank);
}
</style>
src/components/Cropper/index.ts
New file
@@ -0,0 +1,4 @@
import CropperImage from './src/Cropper.vue'
import CropperAvatar from './src/CropperAvatar.vue'
export { CropperImage, CropperAvatar }
src/components/Cropper/src/CopperModal.vue
New file
@@ -0,0 +1,261 @@
<template>
  <div @click.stop>
    <Dialog
      v-model="dialogVisible"
      :canFullscreen="false"
      :title="t('cropper.modalTitle')"
      maxHeight="380px"
      width="800px"
    >
      <div :class="prefixCls">
        <div :class="`${prefixCls}-left`">
          <div :class="`${prefixCls}-cropper`">
            <CropperImage
              v-if="src"
              :circled="circled"
              :src="src"
              height="300px"
              @cropend="handleCropend"
              @ready="handleReady"
            />
          </div>
          <div :class="`${prefixCls}-toolbar`">
            <el-upload :beforeUpload="handleBeforeUpload" :fileList="[]" accept="image/*">
              <el-tooltip :content="t('cropper.selectImage')" placement="bottom">
                <XButton preIcon="ant-design:upload-outlined" type="primary" />
              </el-tooltip>
            </el-upload>
            <el-space>
              <el-tooltip :content="t('cropper.btn_reset')" placement="bottom">
                <XButton
                  :disabled="!src"
                  preIcon="ant-design:reload-outlined"
                  size="small"
                  type="primary"
                  @click="handlerToolbar('reset')"
                />
              </el-tooltip>
              <el-tooltip :content="t('cropper.btn_rotate_left')" placement="bottom">
                <XButton
                  :disabled="!src"
                  preIcon="ant-design:rotate-left-outlined"
                  size="small"
                  type="primary"
                  @click="handlerToolbar('rotate', -45)"
                />
              </el-tooltip>
              <el-tooltip :content="t('cropper.btn_rotate_right')" placement="bottom">
                <XButton
                  :disabled="!src"
                  preIcon="ant-design:rotate-right-outlined"
                  size="small"
                  type="primary"
                  @click="handlerToolbar('rotate', 45)"
                />
              </el-tooltip>
              <el-tooltip :content="t('cropper.btn_scale_x')" placement="bottom">
                <XButton
                  :disabled="!src"
                  preIcon="vaadin:arrows-long-h"
                  size="small"
                  type="primary"
                  @click="handlerToolbar('scaleX')"
                />
              </el-tooltip>
              <el-tooltip :content="t('cropper.btn_scale_y')" placement="bottom">
                <XButton
                  :disabled="!src"
                  preIcon="vaadin:arrows-long-v"
                  size="small"
                  type="primary"
                  @click="handlerToolbar('scaleY')"
                />
              </el-tooltip>
              <el-tooltip :content="t('cropper.btn_zoom_in')" placement="bottom">
                <XButton
                  :disabled="!src"
                  preIcon="ant-design:zoom-in-outlined"
                  size="small"
                  type="primary"
                  @click="handlerToolbar('zoom', 0.1)"
                />
              </el-tooltip>
              <el-tooltip :content="t('cropper.btn_zoom_out')" placement="bottom">
                <XButton
                  :disabled="!src"
                  preIcon="ant-design:zoom-out-outlined"
                  size="small"
                  type="primary"
                  @click="handlerToolbar('zoom', -0.1)"
                />
              </el-tooltip>
            </el-space>
          </div>
        </div>
        <div :class="`${prefixCls}-right`">
          <div :class="`${prefixCls}-preview`">
            <img v-if="previewSource" :alt="t('cropper.preview')" :src="previewSource" />
          </div>
          <template v-if="previewSource">
            <div :class="`${prefixCls}-group`">
              <el-avatar :src="previewSource" size="large" />
              <el-avatar :size="48" :src="previewSource" />
              <el-avatar :size="64" :src="previewSource" />
              <el-avatar :size="80" :src="previewSource" />
            </div>
          </template>
        </div>
      </div>
      <template #footer>
        <el-button type="primary" @click="handleOk">{{ t('cropper.okText') }}</el-button>
      </template>
    </Dialog>
  </div>
</template>
<script lang="ts" setup>
import { useDesign } from '@/hooks/web/useDesign'
import { dataURLtoBlob } from '@/utils/filt'
import { useI18n } from 'vue-i18n'
import type { CropendResult, Cropper } from './types'
import { propTypes } from '@/utils/propTypes'
import { CropperImage } from '@/components/Cropper'
defineOptions({ name: 'CopperModal' })
const props = defineProps({
  srcValue: propTypes.string.def(''),
  circled: propTypes.bool.def(true)
})
const emit = defineEmits(['uploadSuccess'])
const { t } = useI18n()
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('cropper-am')
const src = ref(props.srcValue)
const previewSource = ref('')
const cropper = ref<Cropper>()
const dialogVisible = ref(false)
let filename = ''
let scaleX = 1
let scaleY = 1
// Block upload
function handleBeforeUpload(file: File) {
  const reader = new FileReader()
  reader.readAsDataURL(file)
  src.value = ''
  previewSource.value = ''
  reader.onload = function (e) {
    src.value = (e.target?.result as string) ?? ''
    filename = file.name
  }
  return false
}
function handleCropend({ imgBase64 }: CropendResult) {
  previewSource.value = imgBase64
}
function handleReady(cropperInstance: Cropper) {
  cropper.value = cropperInstance
}
function handlerToolbar(event: string, arg?: number) {
  if (event === 'scaleX') {
    scaleX = arg = scaleX === -1 ? 1 : -1
  }
  if (event === 'scaleY') {
    scaleY = arg = scaleY === -1 ? 1 : -1
  }
  cropper?.value?.[event]?.(arg)
}
async function handleOk() {
  const blob = dataURLtoBlob(previewSource.value)
  emit('uploadSuccess', { source: previewSource.value, data: blob, filename: filename })
}
function openModal() {
  dialogVisible.value = true
}
function closeModal() {
  dialogVisible.value = false
}
defineExpose({ openModal, closeModal })
</script>
<style lang="scss">
$prefix-cls: #{$namespace}-cropper-am;
.#{$prefix-cls} {
  display: flex;
  &-left,
  &-right {
    height: 340px;
  }
  &-left {
    width: 55%;
  }
  &-right {
    width: 45%;
  }
  &-cropper {
    height: 300px;
    background: #eee;
    background-image: linear-gradient(
        45deg,
        rgb(0 0 0 / 25%) 25%,
        transparent 0,
        transparent 75%,
        rgb(0 0 0 / 25%) 0
      ),
      linear-gradient(
        45deg,
        rgb(0 0 0 / 25%) 25%,
        transparent 0,
        transparent 75%,
        rgb(0 0 0 / 25%) 0
      );
    background-position:
      0 0,
      12px 12px;
    background-size: 24px 24px;
  }
  &-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 10px;
  }
  &-preview {
    width: 220px;
    height: 220px;
    margin: 0 auto;
    overflow: hidden;
    border: 1px solid;
    border-radius: 50%;
    img {
      width: 100%;
      height: 100%;
    }
  }
  &-group {
    display: flex;
    padding-top: 8px;
    margin-top: 8px;
    border-top: 1px solid;
    justify-content: space-around;
    align-items: center;
  }
}
</style>
src/components/Cropper/src/Cropper.vue
New file
@@ -0,0 +1,183 @@
<template>
  <div :class="getClass" :style="getWrapperStyle">
    <img
      v-show="isReady"
      ref="imgElRef"
      :alt="alt"
      :crossorigin="crossorigin"
      :src="src"
      :style="getImageStyle"
    />
  </div>
</template>
<script lang="ts" setup>
import { CSSProperties, PropType } from 'vue'
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'
import { useDesign } from '@/hooks/web/useDesign'
import { propTypes } from '@/utils/propTypes'
import { useDebounceFn } from '@vueuse/core'
defineOptions({ name: 'Cropper' })
type Options = Cropper.Options
const defaultOptions: Options = {
  aspectRatio: 1,
  zoomable: true,
  zoomOnTouch: true,
  zoomOnWheel: true,
  cropBoxMovable: true,
  cropBoxResizable: true,
  toggleDragModeOnDblclick: true,
  autoCrop: true,
  background: true,
  highlight: true,
  center: true,
  responsive: true,
  restore: true,
  checkCrossOrigin: true,
  checkOrientation: true,
  scalable: true,
  modal: true,
  guides: true,
  movable: true,
  rotatable: true
}
const props = defineProps({
  src: propTypes.string.def(''),
  alt: propTypes.string.def(''),
  circled: propTypes.bool.def(false),
  realTimePreview: propTypes.bool.def(true),
  height: propTypes.string.def('360px'),
  crossorigin: {
    type: String as PropType<'' | 'anonymous' | 'use-credentials' | undefined>,
    default: undefined
  },
  imageStyle: { type: Object as PropType<CSSProperties>, default: () => ({}) },
  options: { type: Object as PropType<Options>, default: () => ({}) }
})
const emit = defineEmits(['cropend', 'ready', 'cropendError'])
const attrs = useAttrs()
const imgElRef = ref<ElRef<HTMLImageElement>>()
const cropper = ref<Nullable<Cropper>>()
const isReady = ref(false)
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('cropper-image')
const debounceRealTimeCroppered = useDebounceFn(realTimeCroppered, 80)
const getImageStyle = computed((): CSSProperties => {
  return {
    height: props.height,
    maxWidth: '100%',
    ...props.imageStyle
  }
})
const getClass = computed(() => {
  return [
    prefixCls,
    attrs.class,
    {
      [`${prefixCls}--circled`]: props.circled
    }
  ]
})
const getWrapperStyle = computed((): CSSProperties => {
  return { height: `${props.height}`.replace(/px/, '') + 'px' }
})
onMounted(init)
onUnmounted(() => {
  cropper.value?.destroy()
})
async function init() {
  const imgEl = unref(imgElRef)
  if (!imgEl) {
    return
  }
  cropper.value = new Cropper(imgEl, {
    ...defaultOptions,
    ready: () => {
      isReady.value = true
      realTimeCroppered()
      emit('ready', cropper.value)
    },
    crop() {
      debounceRealTimeCroppered()
    },
    zoom() {
      debounceRealTimeCroppered()
    },
    cropmove() {
      debounceRealTimeCroppered()
    },
    ...props.options
  })
}
// Real-time display preview
function realTimeCroppered() {
  props.realTimePreview && croppered()
}
// event: return base64 and width and height information after cropping
function croppered() {
  if (!cropper.value) {
    return
  }
  let imgInfo = cropper.value.getData()
  const canvas = props.circled ? getRoundedCanvas() : cropper.value.getCroppedCanvas()
  canvas.toBlob((blob) => {
    if (!blob) {
      return
    }
    let fileReader: FileReader = new FileReader()
    fileReader.readAsDataURL(blob)
    fileReader.onloadend = (e) => {
      emit('cropend', {
        imgBase64: e.target?.result ?? '',
        imgInfo
      })
    }
    fileReader.onerror = () => {
      emit('cropendError')
    }
  }, 'image/png')
}
// Get a circular picture canvas
function getRoundedCanvas() {
  const sourceCanvas = cropper.value!.getCroppedCanvas()
  const canvas = document.createElement('canvas')
  const context = canvas.getContext('2d')!
  const width = sourceCanvas.width
  const height = sourceCanvas.height
  canvas.width = width
  canvas.height = height
  context.imageSmoothingEnabled = true
  context.drawImage(sourceCanvas, 0, 0, width, height)
  context.globalCompositeOperation = 'destination-in'
  context.beginPath()
  context.arc(width / 2, height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI, true)
  context.fill()
  return canvas
}
</script>
<style lang="scss">
$prefix-cls: #{$namespace}-cropper-image;
.#{$prefix-cls} {
  &--circled {
    .cropper-view-box,
    .cropper-face {
      border-radius: 50%;
    }
  }
}
</style>
src/components/Cropper/src/CropperAvatar.vue
New file
@@ -0,0 +1,142 @@
<template>
  <div class="user-info-head" @click="open()">
    <el-avatar v-if="sourceValue" :src="sourceValue" alt="avatar" class="img-circle img-lg" />
    <el-avatar v-if="!sourceValue" :src="avatar" alt="avatar" class="img-circle img-lg" />
    <el-button v-if="showBtn" :class="`${prefixCls}-upload-btn`" @click="open()">
      {{ btnText ? btnText : t('cropper.selectImage') }}
    </el-button>
    <CopperModal
      ref="cropperModelRef"
      :srcValue="sourceValue"
      @upload-success="handleUploadSuccess"
    />
  </div>
</template>
<script lang="ts" setup>
import { useDesign } from '@/hooks/web/useDesign'
import { propTypes } from '@/utils/propTypes'
import { useI18n } from 'vue-i18n'
import CopperModal from './CopperModal.vue'
import avatar from '@/assets/imgs/avatar.gif'
defineOptions({ name: 'CropperAvatar' })
const props = defineProps({
  width: propTypes.string.def('200px'),
  value: propTypes.string.def(''),
  showBtn: propTypes.bool.def(true),
  btnText: propTypes.string.def('')
})
const emit = defineEmits(['update:value', 'change'])
const sourceValue = ref(props.value)
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('cropper-avatar')
const message = useMessage()
const { t } = useI18n()
const cropperModelRef = ref()
watchEffect(() => {
  sourceValue.value = props.value
})
watch(
  () => sourceValue.value,
  (v: string) => {
    emit('update:value', v)
  }
)
function handleUploadSuccess({ source, data, filename }) {
  sourceValue.value = source
  emit('change', { source, data, filename })
  message.success(t('cropper.uploadSuccess'))
}
function open() {
  cropperModelRef.value.openModal()
}
function close() {
  cropperModelRef.value.closeModal()
}
defineExpose({
  open,
  close
})
</script>
<style lang="scss" scoped>
$prefix-cls: #{$namespace}--cropper-avatar;
.#{$prefix-cls} {
  display: inline-block;
  text-align: center;
  &-image-wrapper {
    overflow: hidden;
    cursor: pointer;
    border: 1px solid;
    border-radius: 50%;
    img {
      width: 100%;
    }
  }
  &-image-mask {
    position: absolute;
    width: inherit;
    height: inherit;
    cursor: pointer;
    background: rgb(0 0 0 / 40%);
    border: inherit;
    border-radius: inherit;
    opacity: 0;
    transition: opacity 0.4s;
    ::v-deep(svg) {
      margin: auto;
    }
  }
  &-image-mask:hover {
    opacity: 40;
  }
  &-upload-btn {
    margin: 10px auto;
  }
}
.user-info-head {
  position: relative;
  display: inline-block;
}
.img-circle {
  border-radius: 50%;
}
.img-lg {
  width: 120px;
  height: 120px;
}
.user-info-head:hover::after {
  position: absolute;
  inset: 0;
  font-size: 24px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-style: normal;
  line-height: 110px;
  color: #eee;
  cursor: pointer;
  background: rgb(0 0 0 / 50%);
  border-radius: 50%;
  content: '+';
}
</style>
src/components/Cropper/src/types.ts
New file
@@ -0,0 +1,8 @@
import type Cropper from 'cropperjs'
export interface CropendResult {
  imgBase64: string
  imgInfo: Cropper.Data
}
export type { Cropper }
src/components/DeptSelectForm/index.vue
New file
@@ -0,0 +1,122 @@
<template>
  <Dialog v-model="dialogVisible" title="部门选择" width="600">
    <el-row v-loading="formLoading">
      <el-col :span="24">
        <ContentWrap class="h-1/1">
          <el-tree
            ref="treeRef"
            :data="deptTree"
            :props="defaultProps"
            show-checkbox
            :check-strictly="checkStrictly"
            check-on-click-node
            default-expand-all
            highlight-current
            node-key="id"
            @check="handleCheck"
          />
        </ContentWrap>
      </el-col>
    </el-row>
    <template #footer>
      <el-button
        :disabled="formLoading || !selectedDeptIds?.length"
        type="primary"
        @click="submitForm"
      >
        ç¡® å®š
      </el-button>
      <el-button @click="dialogVisible = false">取 æ¶ˆ</el-button>
    </template>
  </Dialog>
</template>
<script lang="ts" setup>
import { defaultProps, handleTree } from '@/utils/tree'
import * as DeptApi from '@/api/system/dept'
defineOptions({ name: 'DeptSelectForm' })
const emit = defineEmits<{
  confirm: [deptList: any[]]
}>()
const { t } = useI18n() // å›½é™…化
const message = useMessage() // æ¶ˆæ¯å¼¹çª—
const props = defineProps({
  // æ˜¯å¦ä¸¥æ ¼çš„遵循父子不互相关联
  checkStrictly: {
    type: Boolean,
    default: false
  },
  // æ˜¯å¦æ”¯æŒå¤šé€‰
  multiple: {
    type: Boolean,
    default: true
  }
})
const treeRef = ref()
const deptTree = ref<Tree[]>([]) // éƒ¨é—¨æ ‘形结构
const selectedDeptIds = ref<number[]>([]) // é€‰ä¸­çš„部门 ID åˆ—表
const dialogVisible = ref(false) // å¼¹çª—的是否展示
const formLoading = ref(false) // è¡¨å•的加载中
/** æ‰“开弹窗 */
const open = async (selectedList?: DeptApi.DeptVO[]) => {
  resetForm()
  formLoading.value = true
  try {
    // åŠ è½½éƒ¨é—¨åˆ—è¡¨
    const deptData = await DeptApi.getSimpleDeptList()
    deptTree.value = handleTree(deptData)
  } finally {
    formLoading.value = false
  }
  dialogVisible.value = true
  // è®¾ç½®å·²é€‰æ‹©çš„部门
  if (selectedList?.length) {
    await nextTick()
    const selectedIds = selectedList
      .map((dept) => dept.id)
      .filter((id): id is number => id !== undefined)
    selectedDeptIds.value = selectedIds
    treeRef.value?.setCheckedKeys(selectedIds)
  }
}
/** å¤„理选中状态变化 */
const handleCheck = (data: any, checked: any) => {
  selectedDeptIds.value = treeRef.value.getCheckedKeys()
  if (!props.multiple && selectedDeptIds.value.length > 1) {
    // å•选模式下,只保留最后选择的节点
    const lastSelectedId = selectedDeptIds.value[selectedDeptIds.value.length - 1]
    selectedDeptIds.value = [lastSelectedId]
    treeRef.value.setCheckedKeys([lastSelectedId])
  }
}
/** æäº¤é€‰æ‹© */
const submitForm = async () => {
  try {
    // èŽ·å–é€‰ä¸­çš„å®Œæ•´éƒ¨é—¨æ•°æ®
    const checkedNodes = treeRef.value.getCheckedNodes()
    message.success(t('common.updateSuccess'))
    dialogVisible.value = false
    emit('confirm', checkedNodes)
  } finally {
  }
}
/** é‡ç½®è¡¨å• */
const resetForm = () => {
  deptTree.value = []
  selectedDeptIds.value = []
  if (treeRef.value) {
    treeRef.value.setCheckedKeys([])
  }
}
defineExpose({ open }) // æä¾› open æ–¹æ³•,用于打开弹窗
</script>
src/components/Descriptions/index.ts
New file
@@ -0,0 +1,4 @@
import Descriptions from './src/Descriptions.vue'
import DescriptionsItemLabel from './src/DescriptionsItemLabel.vue'
export { Descriptions, DescriptionsItemLabel }
src/components/Descriptions/src/Descriptions.vue
New file
@@ -0,0 +1,167 @@
<script lang="ts" setup>
import { PropType } from 'vue'
import dayjs from 'dayjs'
import { useDesign } from '@/hooks/web/useDesign'
import { propTypes } from '@/utils/propTypes'
import { useAppStore } from '@/store/modules/app'
import { DescriptionsSchema } from '@/types/descriptions'
defineOptions({ name: 'Descriptions' })
const appStore = useAppStore()
const mobile = computed(() => appStore.getMobile)
const attrs = useAttrs()
const slots = useSlots()
const props = defineProps({
  title: propTypes.string.def(''),
  message: propTypes.string.def(''),
  collapse: propTypes.bool.def(true),
  columns: propTypes.number.def(1),
  schema: {
    type: Array as PropType<DescriptionsSchema[]>,
    default: () => []
  },
  data: {
    type: Object as PropType<any>,
    default: () => ({})
  }
})
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('descriptions')
const getBindValue = computed(() => {
  const delArr: string[] = ['title', 'message', 'collapse', 'schema', 'data', 'class']
  const obj = { ...attrs, ...props }
  for (const key in obj) {
    if (delArr.indexOf(key) !== -1) {
      delete obj[key]
    }
  }
  return obj
})
const getBindItemValue = (item: DescriptionsSchema) => {
  const delArr: string[] = ['field']
  const obj = { ...item }
  for (const key in obj) {
    if (delArr.indexOf(key) !== -1) {
      delete obj[key]
    }
  }
  return obj
}
// æŠ˜å 
const show = ref(true)
const toggleClick = () => {
  if (props.collapse) {
    show.value = !unref(show)
  }
}
</script>
<template>
  <div
    :class="[
      prefixCls,
      'bg-[var(--el-color-white)] dark:bg-[var(--el-bg-color)] dark:border-[var(--el-border-color)] dark:border-1px'
    ]"
  >
    <div
      v-if="title"
      :class="[
        `${prefixCls}-header`,
        'h-50px flex justify-between items-center b-b-1 border-solid border-[var(--el-border-color)] px-10px cursor-pointer dark:border-[var(--el-border-color)]'
      ]"
      @click="toggleClick"
    >
      <div :class="[`${prefixCls}-header__title`, 'relative font-18px font-bold ml-10px']">
        <div class="flex items-center">
          {{ title }}
          <ElTooltip v-if="message" :content="message" placement="right">
            <Icon class="ml-5px" icon="ep:warning" />
          </ElTooltip>
        </div>
      </div>
      <Icon v-if="collapse" :icon="show ? 'ep:arrow-down' : 'ep:arrow-up'" />
    </div>
    <ElCollapseTransition>
      <div v-show="show" :class="[`${prefixCls}-content`, 'p-10px']">
        <ElDescriptions
          :column="props.columns"
          :direction="mobile ? 'vertical' : 'horizontal'"
          border
          v-bind="getBindValue"
        >
          <template v-if="slots['extra']" #extra>
            <slot name="extra"></slot>
          </template>
          <ElDescriptionsItem
            v-for="item in schema"
            :key="item.field"
            min-width="80"
            v-bind="getBindItemValue(item)"
          >
            <template #label>
              <slot
                :name="`${item.field}-label`"
                :row="{
                  label: item.label
                }"
                >{{ item.label }}
              </slot>
            </template>
            <template #default>
              <slot v-if="item.dateFormat">
                {{
                  data[item.field] !== null ? dayjs(data[item.field]).format(item.dateFormat) : ''
                }}
              </slot>
              <slot v-else-if="item.dictType">
                <DictTag :type="item.dictType" :value="data[item.field] + ''" />
              </slot>
              <slot v-else :name="item.field" :row="data">
                {{
                    item.mappedField ? data[item.mappedField] : data[item.field]
                }}
              </slot>
            </template>
          </ElDescriptionsItem>
        </ElDescriptions>
      </div>
    </ElCollapseTransition>
  </div>
</template>
<style lang="scss" scoped>
$prefix-cls: #{$namespace}-descriptions;
.#{$prefix-cls}-header {
  &__title {
    &::after {
      position: absolute;
      top: 3px;
      left: -10px;
      width: 4px;
      height: 70%;
      background: var(--el-color-primary);
      content: '';
    }
  }
}
.#{$prefix-cls}-content {
  :deep(.#{$elNamespace}-descriptions__cell) {
    width: 0;
  }
}
</style>
src/components/Descriptions/src/DescriptionsItemLabel.vue
New file
@@ -0,0 +1,29 @@
<script setup lang="ts">
const { label } = defineProps({
  label: {
    type: String,
    required: true
  },
  icon: {
    type: String,
    required: false
  }
})
</script>
<template>
  <div class="cell-item">
    <Icon :icon="icon" v-if="icon" style="vertical-align: middle" :size="18" />
    {{ label }}
  </div>
</template>
<style scoped lang="scss">
.cell-item {
  display: inline;
}
.cell-item::after {
  content: ':';
}
</style>
src/components/Dialog/index.ts
New file
@@ -0,0 +1,3 @@
import Dialog from './src/Dialog.vue'
export { Dialog }
src/components/Dialog/src/Dialog.vue
New file
@@ -0,0 +1,157 @@
<script lang="ts" setup>
import { propTypes } from '@/utils/propTypes'
import { isNumber } from '@/utils/is'
defineOptions({ name: 'Dialog' })
const slots = useSlots()
const emits = defineEmits(['update:modelValue'])
const props = defineProps({
  modelValue: propTypes.bool.def(false),
  title: propTypes.string.def('Dialog'),
  fullscreen: propTypes.bool.def(true),
  width: propTypes.oneOfType([String, Number]).def('40%'),
  scroll: propTypes.bool.def(false), // æ˜¯å¦å¼€å¯æ»šåŠ¨æ¡ã€‚å¦‚æžœæ˜¯çš„è¯ï¼ŒæŒ‰ç…§ maxHeight è®¾ç½®æœ€å¤§é«˜åº¦
  maxHeight: propTypes.oneOfType([String, Number]).def('400px')
})
const getBindValue = computed(() => {
  const delArr: string[] = ['fullscreen', 'title', 'maxHeight', 'appendToBody']
  const attrs = useAttrs()
  const obj = { ...attrs, ...props }
  for (const key in obj) {
    if (delArr.indexOf(key) !== -1) {
      delete obj[key]
    }
  }
  return obj
})
const isFullscreen = ref(false)
const toggleFull = () => {
  isFullscreen.value = !unref(isFullscreen)
}
const dialogHeight = ref(isNumber(props.maxHeight) ? `${props.maxHeight}px` : props.maxHeight)
watch(
  () => isFullscreen.value,
  async (val: boolean) => {
    await nextTick()
    if (val) {
      const windowHeight = document.documentElement.offsetHeight
      dialogHeight.value = `${windowHeight - 55 - 60 - (slots.footer ? 63 : 0)}px`
    } else {
      dialogHeight.value = isNumber(props.maxHeight) ? `${props.maxHeight}px` : props.maxHeight
    }
  },
  {
    immediate: true
  }
)
const dialogStyle = computed(() => {
  return {
    height: unref(dialogHeight)
  }
})
const closing = ref(false)
function closeHandler() {
  emits('update:modelValue', false)
  closing.value = true
}
function closedHandler() {
  closing.value = false
}
</script>
<template>
  <ElDialog
    v-bind="getBindValue"
    :close-on-click-modal="true"
    :fullscreen="isFullscreen"
    :width="width"
    destroy-on-close
    lock-scroll
    draggable
    class="com-dialog"
    :show-close="false"
    @close="closeHandler"
    @closed="closedHandler"
  >
    <template #header="{ close }">
      <div class="relative h-54px flex items-center justify-between pl-15px pr-15px">
        <slot name="title">
          {{ title }}
        </slot>
        <div
          class="absolute right-15px top-[50%] h-54px flex translate-y-[-50%] items-center justify-between"
        >
          <Icon
            v-if="fullscreen"
            class="is-hover mr-10px cursor-pointer"
            :icon="isFullscreen ? 'radix-icons:exit-full-screen' : 'radix-icons:enter-full-screen'"
            color="var(--el-color-info)"
            hover-color="var(--el-color-primary)"
            @click="toggleFull"
          />
          <Icon
            class="is-hover cursor-pointer"
            icon="ep:close"
            hover-color="var(--el-color-primary)"
            color="var(--el-color-info)"
            @click.stop="close"
          />
        </div>
      </div>
    </template>
    <ElScrollbar v-if="scroll" :style="dialogStyle">
      <slot></slot>
    </ElScrollbar>
    <slot v-else></slot>
    <template v-if="slots.footer" #footer>
      <div :style="{ 'pointer-events': closing ? 'none' : 'auto' }">
        <slot name="footer"></slot>
      </div>
    </template>
  </ElDialog>
</template>
<style lang="scss">
.com-dialog {
  .#{$elNamespace}-overlay-dialog {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .#{$elNamespace}-dialog {
    margin: 0 !important;
    &__header {
      height: 54px;
      padding: 0;
      margin-right: 0 !important;
      border-bottom: 1px solid var(--el-border-color);
    }
    &__body {
      padding: 15px !important;
    }
    &__footer {
      border-top: 1px solid var(--el-border-color);
    }
    &__headerbtn {
      top: 0;
    }
  }
}
</style>
src/components/DictTag/index.ts
New file
@@ -0,0 +1,3 @@
import DictTag from './src/DictTag.vue'
export { DictTag }
src/components/DictTag/src/DictTag.vue
New file
@@ -0,0 +1,90 @@
<script lang="tsx">
import { computed, defineComponent, PropType } from 'vue'
import { isHexColor } from '@/utils/color'
import { ElTag } from 'element-plus'
import { DictDataType, getDictOptions } from '@/utils/dict'
import { isArray, isBoolean, isNumber, isString } from '@/utils/is'
export default defineComponent({
  name: 'DictTag',
  props: {
    type: {
      type: String as PropType<string>,
      required: true
    },
    value: {
      type: [String, Number, Boolean, Array],
      required: true
    },
    // å­—符串分隔符 åªæœ‰å½“ props.value ä¼ å…¥å€¼ä¸ºå­—符串时有效
    separator: {
      type: String as PropType<string>,
      default: ','
    },
    // æ¯ä¸ª tag ä¹‹é—´çš„间隔,默认为 5px,参考的 el-row çš„ gutter
    gutter: {
      type: String as PropType<string>,
      default: '5px'
    }
  },
  setup(props) {
    const valueArr: any = computed(() => {
      // 1. æ˜¯ Number ç±»åž‹å’Œ Boolean ç±»åž‹çš„æƒ…况
      if (isNumber(props.value) || isBoolean(props.value)) {
        return [String(props.value)]
      }
      // 2. æ˜¯å­—符串(进一步判断是否有包含分隔符号 -> props.sepSymbol ï¼‰
      else if (isString(props.value)) {
        return props.value.split(props.separator)
      }
      // 3. æ•°ç»„
      else if (isArray(props.value)) {
        return props.value.map(String)
      }
      return []
    })
    const renderDictTag = () => {
      if (!props.type) {
        return null
      }
      // è§£å†³è‡ªå®šä¹‰å­—典标签值为零时标签不渲染的问题
      if (props.value === undefined || props.value === null || props.value === '') {
        return null
      }
      const dictOptions = getDictOptions(props.type)
      return (
        <div
          class="dict-tag"
          style={{
            display: 'inline-flex',
            gap: props.gutter,
            justifyContent: 'center',
            alignItems: 'center'
          }}
        >
          {dictOptions.map((dict: DictDataType) => {
            if (valueArr.value.includes(dict.value)) {
              if (dict.colorType + '' === 'primary' || dict.colorType + '' === 'default') {
                dict.colorType = ''
              }
              return (
                // æ·»åŠ æ ‡ç­¾çš„æ–‡å­—é¢œè‰²ä¸ºç™½è‰²ï¼Œè§£å†³è‡ªå®šä¹‰èƒŒæ™¯é¢œè‰²æ—¶æ ‡ç­¾æ–‡å­—çœ‹ä¸æ¸…çš„é—®é¢˜
                <ElTag
                  style={dict?.cssClass ? 'color: #fff' : ''}
                  type={dict?.colorType || null}
                  color={dict?.cssClass && isHexColor(dict?.cssClass) ? dict?.cssClass : ''}
                  disableTransitions={true}
                >
                  {dict?.label}
                </ElTag>
              )
            }
          })}
        </div>
      )
    }
    return () => renderDictTag()
  }
})
</script>
src/components/DiyEditor/components/ComponentContainer.vue
New file
@@ -0,0 +1,239 @@
<template>
  <div :class="['component', { active: active }]">
    <div
      :style="{
        ...style
      }"
    >
      <component :is="component.id" :property="component.property" />
    </div>
    <div class="component-wrap">
      <!-- å·¦ä¾§ï¼šç»„件名(悬浮的小贴条) -->
      <div class="component-name" v-if="component.name">
        {{ component.name }}
      </div>
      <!-- å³ä¾§ï¼šç»„件操作工具栏 -->
      <div class="component-toolbar" v-if="showToolbar && component.name && active">
        <VerticalButtonGroup type="primary">
          <el-tooltip content="上移" placement="right">
            <el-button :disabled="!canMoveUp" @click.stop="handleMoveComponent(-1)">
              <Icon icon="ep:arrow-up" />
            </el-button>
          </el-tooltip>
          <el-tooltip content="下移" placement="right">
            <el-button :disabled="!canMoveDown" @click.stop="handleMoveComponent(1)">
              <Icon icon="ep:arrow-down" />
            </el-button>
          </el-tooltip>
          <el-tooltip content="复制" placement="right">
            <el-button @click.stop="handleCopyComponent()">
              <Icon icon="ep:copy-document" />
            </el-button>
          </el-tooltip>
          <el-tooltip content="删除" placement="right">
            <el-button @click.stop="handleDeleteComponent()">
              <Icon icon="ep:delete" />
            </el-button>
          </el-tooltip>
        </VerticalButtonGroup>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
// æ³¨å†Œæ‰€æœ‰çš„组件
import { components } from '../components/mobile/index'
export default {
  components: { ...components }
}
</script>
<script setup lang="ts">
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
import { propTypes } from '@/utils/propTypes'
import { object } from 'vue-types'
/**
 * ç»„件容器:目前在中间部分
 * ç”¨äºŽåŒ…裹组件,为组件提供 èƒŒæ™¯ã€å¤–边距、内边距、边框等样式
 */
defineOptions({ name: 'ComponentContainer' })
type DiyComponentWithStyle = DiyComponent<any> & { property: { style?: ComponentStyle } }
const props = defineProps({
  component: object<DiyComponentWithStyle>().isRequired,
  active: propTypes.bool.def(false),
  canMoveUp: propTypes.bool.def(false),
  canMoveDown: propTypes.bool.def(false),
  showToolbar: propTypes.bool.def(true)
})
/**
 * ç»„件样式
 */
const style = computed(() => {
  let componentStyle = props.component.property.style
  if (!componentStyle) {
    return {}
  }
  return {
    marginTop: `${componentStyle.marginTop || 0}px`,
    marginBottom: `${componentStyle.marginBottom || 0}px`,
    marginLeft: `${componentStyle.marginLeft || 0}px`,
    marginRight: `${componentStyle.marginRight || 0}px`,
    paddingTop: `${componentStyle.paddingTop || 0}px`,
    paddingRight: `${componentStyle.paddingRight || 0}px`,
    paddingBottom: `${componentStyle.paddingBottom || 0}px`,
    paddingLeft: `${componentStyle.paddingLeft || 0}px`,
    borderTopLeftRadius: `${componentStyle.borderTopLeftRadius || 0}px`,
    borderTopRightRadius: `${componentStyle.borderTopRightRadius || 0}px`,
    borderBottomRightRadius: `${componentStyle.borderBottomRightRadius || 0}px`,
    borderBottomLeftRadius: `${componentStyle.borderBottomLeftRadius || 0}px`,
    overflow: 'hidden',
    background:
      componentStyle.bgType === 'color' ? componentStyle.bgColor : `url(${componentStyle.bgImg})`
  }
})
const emits = defineEmits<{
  (e: 'move', direction: number): void
  (e: 'copy'): void
  (e: 'delete'): void
}>()
/**
 * ç§»åŠ¨ç»„ä»¶
 * @param direction ç§»åŠ¨æ–¹å‘
 */
const handleMoveComponent = (direction: number) => {
  emits('move', direction)
}
/**
 * å¤åˆ¶ç»„ä»¶
 */
const handleCopyComponent = () => {
  emits('copy')
}
/**
 * åˆ é™¤ç»„ä»¶
 */
const handleDeleteComponent = () => {
  emits('delete')
}
</script>
<style scoped lang="scss">
$active-border-width: 2px;
$hover-border-width: 1px;
$name-position: -85px;
$toolbar-position: -55px;
/* ç»„ä»¶ */
.component {
  position: relative;
  cursor: move;
  .component-wrap {
    position: absolute;
    top: 0;
    left: -$active-border-width;
    display: block;
    width: 100%;
    height: 100%;
    /* é¼ æ ‡æ”¾åˆ°ç»„件上时 */
    &:hover {
      border: $hover-border-width dashed var(--el-color-primary);
      box-shadow: 0 0 5px 0 rgb(24 144 255 / 30%);
      .component-name {
        top: $hover-border-width;
        /* é˜²æ­¢åŠ äº†è¾¹æ¡†ä¹‹åŽï¼Œä½ç½®ç§»åŠ¨ */
        left: $name-position - $hover-border-width;
      }
    }
    /* å·¦ä¾§ï¼šç»„件名称 */
    .component-name {
      position: absolute;
      top: $active-border-width;
      left: $name-position;
      display: block;
      width: 80px;
      height: 25px;
      font-size: 12px;
      color: #6a6a6a;
      line-height: 25px;
      text-align: center;
      background: #fff;
      box-shadow:
        0 0 4px #00000014,
        0 2px 6px #0000000f,
        0 4px 8px 2px #0000000a;
      /* å³ä¾§å°ä¸‰è§’ */
      &::after {
        position: absolute;
        top: 7.5px;
        right: -10px;
        width: 0;
        height: 0;
        border: 5px solid transparent;
        border-left-color: #fff;
        content: ' ';
      }
    }
    /* å³ä¾§ï¼šç»„件操作工具栏 */
    .component-toolbar {
      position: absolute;
      top: 0;
      right: $toolbar-position;
      display: none;
      /* å·¦ä¾§å°ä¸‰è§’ */
      &::before {
        position: absolute;
        top: 10px;
        left: -10px;
        width: 0;
        height: 0;
        border: 5px solid transparent;
        border-right-color: #2d8cf0;
        content: ' ';
      }
    }
  }
  /* ç»„件选中时 */
  &.active {
    margin-bottom: 4px;
    .component-wrap {
      margin-bottom: $active-border-width + $active-border-width;
      border: $active-border-width solid var(--el-color-primary) !important;
      box-shadow: 0 0 10px 0 rgb(24 144 255 / 30%);
      .component-name {
        top: 0 !important;
        /* é˜²æ­¢åŠ äº†è¾¹æ¡†ä¹‹åŽï¼Œä½ç½®ç§»åŠ¨ */
        left: $name-position - $active-border-width !important;
        color: #fff;
        background: var(--el-color-primary);
        &::after {
          border-left-color: var(--el-color-primary);
        }
      }
      .component-toolbar {
        display: block;
      }
    }
  }
}
</style>
src/components/DiyEditor/components/ComponentContainerProperty.vue
New file
@@ -0,0 +1,168 @@
<template>
  <el-tabs stretch>
    <!-- æ¯ä¸ªç»„件的自定义内容 -->
    <el-tab-pane label="内容" v-if="$slots.default">
      <slot></slot>
    </el-tab-pane>
    <!-- æ¯ä¸ªç»„件的通用内容 -->
    <el-tab-pane label="样式" lazy>
      <el-card header="组件样式" class="property-group">
        <el-form :model="formData" label-width="80px">
          <el-form-item label="组件背景" prop="bgType">
            <el-radio-group v-model="formData.bgType">
              <el-radio value="color">纯色</el-radio>
              <el-radio value="img">图片</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="选择颜色" prop="bgColor" v-if="formData.bgType === 'color'">
            <ColorInput v-model="formData.bgColor" />
          </el-form-item>
          <el-form-item label="上传图片" prop="bgImg" v-else>
            <UploadImg v-model="formData.bgImg" :limit="1">
              <template #tip>建议宽度 750px</template>
            </UploadImg>
          </el-form-item>
          <el-tree :data="treeData" :expand-on-click-node="false" default-expand-all>
            <template #default="{ node, data }">
              <el-form-item
                :label="data.label"
                :prop="data.prop"
                :label-width="node.level === 1 ? '80px' : '62px'"
                class="w-full m-b-0!"
              >
                <el-slider
                  v-model="formData[data.prop]"
                  :max="100"
                  :min="0"
                  show-input
                  input-size="small"
                  :show-input-controls="false"
                  @input="handleSliderChange(data.prop)"
                />
              </el-form-item>
            </template>
          </el-tree>
          <slot name="style" :style="formData"></slot>
        </el-form>
      </el-card>
    </el-tab-pane>
  </el-tabs>
</template>
<script setup lang="ts">
import { ComponentStyle } from '@/components/DiyEditor/util'
import { useVModel } from '@vueuse/core'
/**
 * ç»„件容器属性:目前右边部分
 * ç”¨äºŽåŒ…裹组件,为组件提供 èƒŒæ™¯ã€å¤–边距、内边距、边框等样式
 */
defineOptions({ name: 'ComponentContainer' })
const props = defineProps<{ modelValue: ComponentStyle }>()
const emit = defineEmits(['update:modelValue'])
const formData = useVModel(props, 'modelValue', emit)
const treeData = [
  {
    label: '外部边距',
    prop: 'margin',
    children: [
      {
        label: '上',
        prop: 'marginTop'
      },
      {
        label: '右',
        prop: 'marginRight'
      },
      {
        label: '下',
        prop: 'marginBottom'
      },
      {
        label: 'å·¦',
        prop: 'marginLeft'
      }
    ]
  },
  {
    label: '内部边距',
    prop: 'padding',
    children: [
      {
        label: '上',
        prop: 'paddingTop'
      },
      {
        label: '右',
        prop: 'paddingRight'
      },
      {
        label: '下',
        prop: 'paddingBottom'
      },
      {
        label: 'å·¦',
        prop: 'paddingLeft'
      }
    ]
  },
  {
    label: '边框圆角',
    prop: 'borderRadius',
    children: [
      {
        label: '上左',
        prop: 'borderTopLeftRadius'
      },
      {
        label: '上右',
        prop: 'borderTopRightRadius'
      },
      {
        label: '下右',
        prop: 'borderBottomRightRadius'
      },
      {
        label: '下左',
        prop: 'borderBottomLeftRadius'
      }
    ]
  }
]
const handleSliderChange = (prop: string) => {
  switch (prop) {
    case 'margin':
      formData.value.marginTop = formData.value.margin
      formData.value.marginRight = formData.value.margin
      formData.value.marginBottom = formData.value.margin
      formData.value.marginLeft = formData.value.margin
      break
    case 'padding':
      formData.value.paddingTop = formData.value.padding
      formData.value.paddingRight = formData.value.padding
      formData.value.paddingBottom = formData.value.padding
      formData.value.paddingLeft = formData.value.padding
      break
    case 'borderRadius':
      formData.value.borderTopLeftRadius = formData.value.borderRadius
      formData.value.borderTopRightRadius = formData.value.borderRadius
      formData.value.borderBottomRightRadius = formData.value.borderRadius
      formData.value.borderBottomLeftRadius = formData.value.borderRadius
      break
  }
}
</script>
<style scoped lang="scss">
:deep(.el-slider__runway) {
  margin-right: 16px;
}
:deep(.el-input-number) {
  width: 50px;
}
</style>
src/components/DiyEditor/components/ComponentLibrary.vue
New file
@@ -0,0 +1,211 @@
<template>
  <el-aside class="editor-left" width="261px">
    <el-scrollbar>
      <el-collapse v-model="extendGroups">
        <el-collapse-item
          v-for="group in groups"
          :key="group.name"
          :name="group.name"
          :title="group.name"
        >
          <draggable
            class="component-container"
            ghost-class="draggable-ghost"
            item-key="index"
            :list="group.components"
            :sort="false"
            :group="{ name: 'component', pull: 'clone', put: false }"
            :clone="handleCloneComponent"
            :animation="200"
            :force-fallback="false"
          >
            <template #item="{ element }">
              <div>
                <div class="drag-placement">组件放置区域</div>
                <div class="component">
                  <Icon :icon="element.icon" :size="32" />
                  <span class="mt-4px text-12px">{{ element.name }}</span>
                </div>
              </div>
            </template>
          </draggable>
        </el-collapse-item>
      </el-collapse>
    </el-scrollbar>
  </el-aside>
</template>
<script setup lang="ts">
import draggable from 'vuedraggable'
import { componentConfigs } from '../components/mobile/index'
import { cloneDeep } from 'lodash-es'
import { DiyComponent, DiyComponentLibrary } from '@/components/DiyEditor/util'
/** ç»„件库:目前左侧的【基础组件】、【图文组件】部分 */
defineOptions({ name: 'ComponentLibrary' })
// ç»„件列表
const props = defineProps<{
  list: DiyComponentLibrary[]
}>()
// ç»„件分组
const groups = reactive<any[]>([])
// å±•开的折叠面板
const extendGroups = reactive<string[]>([])
// ç›‘听 list å±žæ€§ï¼ŒæŒ‰ç…§ DiyComponentLibrary çš„ name åˆ†ç»„
watch(
  () => props.list,
  () => {
    // æ¸…除旧数据
    extendGroups.length = 0
    groups.length = 0
    // é‡æ–°ç”Ÿæˆæ•°æ®
    props.list.forEach((group) => {
      // æ˜¯å¦å±•开分组
      if (group.extended) {
        extendGroups.push(group.name)
      }
      // æŸ¥æ‰¾ç»„ä»¶
      const components = group.components
        .map((name) => componentConfigs[name] as DiyComponent<any>)
        .filter((component) => component)
      if (components.length > 0) {
        groups.push({
          name: group.name,
          components
        })
      }
    })
  },
  {
    immediate: true
  }
)
// å…‹éš†ç»„ä»¶
const handleCloneComponent = (component: DiyComponent<any>) => {
  const instance = cloneDeep(component)
  instance.uid = new Date().getTime()
  return instance
}
</script>
<style scoped lang="scss">
.editor-left {
  z-index: 1;
  flex-shrink: 0;
  user-select: none;
  box-shadow: 8px 0 8px -8px rgb(0 0 0 / 12%);
  :deep(.el-collapse) {
    border-top: none;
  }
  :deep(.el-collapse-item__wrap) {
    border-bottom: none;
  }
  :deep(.el-collapse-item__content) {
    padding-bottom: 0;
  }
  :deep(.el-collapse-item__header) {
    height: 32px;
    padding: 0 24px;
    line-height: 32px;
    background-color: var(--el-bg-color-page);
    border-bottom: none;
  }
  .component-container {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
  }
  .component {
    display: flex;
    width: 86px;
    height: 86px;
    cursor: move;
    border-right: 1px solid var(--el-border-color-lighter);
    border-bottom: 1px solid var(--el-border-color-lighter);
    flex-direction: column;
    align-items: center;
    justify-content: center;
    .el-icon {
      margin-bottom: 4px;
      color: gray;
    }
  }
  .component.active,
  .component:hover {
    color: var(--el-color-white);
    background: var(--el-color-primary);
    .el-icon {
      color: var(--el-color-white);
    }
  }
  .component:nth-of-type(3n) {
    border-right: none;
  }
}
/* æ‹–拽占位提示,默认不显示 */
.drag-placement {
  display: none;
  color: #fff;
}
.drag-area {
  /* æ‹–拽到手机区域时的样式 */
  .draggable-ghost {
    display: flex;
    width: 100%;
    height: 40px;
    /* æ¡çº¹èƒŒæ™¯ */
    background: linear-gradient(
      45deg,
      #91a8d5 0,
      #91a8d5 10%,
      #94b4eb 10%,
      #94b4eb 50%,
      #91a8d5 50%,
      #91a8d5 60%,
      #94b4eb 60%,
      #94b4eb
    );
    background-size: 1rem 1rem;
    transition: all 0.5s;
    justify-content: center;
    align-items: center;
    span {
      display: inline-block;
      width: 140px;
      height: 25px;
      font-size: 12px;
      line-height: 25px;
      color: #fff;
      text-align: center;
      background: #5487df;
    }
    /* æ‹–拽时隐藏组件 */
    .component {
      display: none;
    }
    /* æ‹–拽时显示占位提示 */
    .drag-placement {
      display: block;
    }
  }
}
</style>
src/components/DiyEditor/components/mobile/Carousel/config.ts
New file
@@ -0,0 +1,53 @@
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
/** è½®æ’­å›¾å±žæ€§ */
export interface CarouselProperty {
  // ç±»åž‹ï¼šé»˜è®¤ | å¡ç‰‡
  type: 'default' | 'card'
  // æŒ‡ç¤ºå™¨æ ·å¼ï¼šç‚¹ | æ•°å­—
  indicator: 'dot' | 'number'
  // æ˜¯å¦è‡ªåŠ¨æ’­æ”¾
  autoplay: boolean
  // æ’­æ”¾é—´éš”
  interval: number
  // è½®æ’­é«˜åº¦
  height: number
  // è½®æ’­å†…容
  items: CarouselItemProperty[]
  // ç»„件样式
  style: ComponentStyle
}
// è½®æ’­å†…容属性
export interface CarouselItemProperty {
  // ç±»åž‹ï¼šå›¾ç‰‡ | è§†é¢‘
  type: 'img' | 'video'
  // å›¾ç‰‡é“¾æŽ¥
  imgUrl: string
  // è§†é¢‘链接
  videoUrl: string
  // è·³è½¬é“¾æŽ¥
  url: string
}
// å®šä¹‰ç»„ä»¶
export const component = {
  id: 'Carousel',
  name: '轮播图',
  icon: 'system-uicons:carousel',
  property: {
    type: 'default',
    indicator: 'dot',
    autoplay: false,
    interval: 3,
    height: 174,
    items: [
      { type: 'img', imgUrl: 'https://static.iocoder.cn/mall/banner-01.jpg', videoUrl: '' },
      { type: 'img', imgUrl: 'https://static.iocoder.cn/mall/banner-02.jpg', videoUrl: '' }
    ] as CarouselItemProperty[],
    style: {
      bgType: 'color',
      bgColor: '#fff',
      marginBottom: 8
    } as ComponentStyle
  }
} as DiyComponent<CarouselProperty>
src/components/DiyEditor/components/mobile/Carousel/index.vue
New file
@@ -0,0 +1,43 @@
<template>
  <!-- æ— å›¾ç‰‡ -->
  <div
    class="h-250px flex items-center justify-center bg-gray-3"
    v-if="property.items.length === 0"
  >
    <Icon icon="tdesign:image" class="text-gray-8 text-120px!" />
  </div>
  <div v-else class="relative">
    <el-carousel
      :height="property.height + 'px'"
      :type="property.type === 'card' ? 'card' : ''"
      :autoplay="property.autoplay"
      :interval="property.interval * 1000"
      :indicator-position="property.indicator === 'number' ? 'none' : undefined"
      @change="handleIndexChange"
    >
      <el-carousel-item v-for="(item, index) in property.items" :key="index">
        <el-image class="h-full w-full" :src="item.imgUrl" />
      </el-carousel-item>
    </el-carousel>
    <div
      v-if="property.indicator === 'number'"
      class="absolute bottom-10px right-10px rounded-xl bg-black p-x-8px p-y-2px text-10px text-white opacity-40"
      >{{ currentIndex }} / {{ property.items.length }}</div
    >
  </div>
</template>
<script setup lang="ts">
import { CarouselProperty } from './config'
/** è½®æ’­å›¾ */
defineOptions({ name: 'Carousel' })
defineProps<{ property: CarouselProperty }>()
const currentIndex = ref(0)
const handleIndexChange = (index: number) => {
  currentIndex.value = index + 1
}
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/Carousel/property.vue
New file
@@ -0,0 +1,109 @@
<template>
  <ComponentContainerProperty v-model="formData.style">
    <el-form label-width="80px" :model="formData">
      <el-card header="样式设置" class="property-group" shadow="never">
        <el-form-item label="样式" prop="type">
          <el-radio-group v-model="formData.type">
            <el-tooltip class="item" content="默认" placement="bottom">
              <el-radio-button value="default">
                <Icon icon="system-uicons:carousel" />
              </el-radio-button>
            </el-tooltip>
            <el-tooltip class="item" content="卡片" placement="bottom">
              <el-radio-button value="card">
                <Icon icon="ic:round-view-carousel" />
              </el-radio-button>
            </el-tooltip>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="高度" prop="height">
          <el-input-number class="!w-50% mr-10px" controls-position="right" v-model="formData.height" /> px
        </el-form-item>
        <el-form-item label="指示器" prop="indicator">
          <el-radio-group v-model="formData.indicator">
            <el-radio value="dot">小圆点</el-radio>
            <el-radio value="number">数字</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="是否轮播" prop="autoplay">
          <el-switch v-model="formData.autoplay" />
        </el-form-item>
        <el-form-item label="播放间隔" prop="interval" v-if="formData.autoplay">
          <el-slider
            v-model="formData.interval"
            :max="10"
            :min="0.5"
            :step="0.5"
            show-input
            input-size="small"
            :show-input-controls="false"
          />
          <el-text type="info">单位:秒</el-text>
        </el-form-item>
      </el-card>
      <el-card header="内容设置" class="property-group" shadow="never">
        <Draggable v-model="formData.items" :empty-item="{ type: 'img' }">
          <template #default="{ element }">
            <el-form-item label="类型" prop="type" class="m-b-8px!" label-width="40px">
              <el-radio-group v-model="element.type">
                <el-radio value="img">图片</el-radio>
                <el-radio value="video">视频</el-radio>
              </el-radio-group>
            </el-form-item>
            <el-form-item
              label="图片"
              class="m-b-8px!"
              label-width="40px"
              v-if="element.type === 'img'"
            >
              <UploadImg
                v-model="element.imgUrl"
                draggable="false"
                height="80px"
                width="100%"
                class="min-w-80px"
              />
            </el-form-item>
            <template v-else>
              <el-form-item label="封面" class="m-b-8px!" label-width="40px">
                <UploadImg
                  v-model="element.imgUrl"
                  draggable="false"
                  height="80px"
                  width="100%"
                  class="min-w-80px"
                />
              </el-form-item>
              <el-form-item label="视频" class="m-b-8px!" label-width="40px">
                <UploadFile
                  v-model="element.videoUrl"
                  :file-type="['mp4']"
                  :limit="1"
                  :file-size="100"
                  class="min-w-80px"
                />
              </el-form-item>
            </template>
            <el-form-item label="链接" class="m-b-8px!" label-width="40px">
              <AppLinkInput v-model="element.url" />
            </el-form-item>
          </template>
        </Draggable>
      </el-card>
    </el-form>
  </ComponentContainerProperty>
</template>
<script setup lang="ts">
import { CarouselProperty } from './config'
import { useVModel } from '@vueuse/core'
// è½®æ’­å›¾å±žæ€§é¢æ¿
defineOptions({ name: 'CarouselProperty' })
const props = defineProps<{ modelValue: CarouselProperty }>()
const emit = defineEmits(['update:modelValue'])
const formData = useVModel(props, 'modelValue', emit)
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/CouponCard/component.tsx
New file
@@ -0,0 +1,73 @@
import * as CouponTemplateApi from '@/api/mall/promotion/coupon/couponTemplate'
import { CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum } from '@/utils/constants'
import { floatToFixed2 } from '@/utils'
import { formatDate } from '@/utils/formatTime'
import { object } from 'vue-types'
// ä¼˜æƒ å€¼
export const CouponDiscount = defineComponent({
  name: 'CouponDiscount',
  props: {
    coupon: object<CouponTemplateApi.CouponTemplateVO>()
  },
  setup(props) {
    const coupon = props.coupon as CouponTemplateApi.CouponTemplateVO
    // æŠ˜æ‰£
    let value = coupon.discountPercent / 10 + ''
    let suffix = ' æŠ˜'
    // æ»¡å‡
    if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
      value = floatToFixed2(coupon.discountPrice)
      suffix = ' å…ƒ'
    }
    return () => (
      <div>
        <span class={'text-20px font-bold'}>{value}</span>
        <span>{suffix}</span>
      </div>
    )
  }
})
// ä¼˜æƒ æè¿°
export const CouponDiscountDesc = defineComponent({
  name: 'CouponDiscountDesc',
  props: {
    coupon: object<CouponTemplateApi.CouponTemplateVO>()
  },
  setup(props) {
    const coupon = props.coupon as CouponTemplateApi.CouponTemplateVO
    // ä½¿ç”¨æ¡ä»¶
    const useCondition = coupon.usePrice > 0 ? `满${floatToFixed2(coupon.usePrice)}元,` : ''
    // ä¼˜æƒ æè¿°
    const discountDesc =
      coupon.discountType === PromotionDiscountTypeEnum.PRICE.type
        ? `减${floatToFixed2(coupon.discountPrice)}元`
        : `打${coupon.discountPercent / 10.0}折`
    return () => (
      <div>
        <span>{useCondition}</span>
        <span>{discountDesc}</span>
      </div>
    )
  }
})
// æœ‰æ•ˆæœŸ
export const CouponValidTerm = defineComponent({
  name: 'CouponValidTerm',
  props: {
    coupon: object<CouponTemplateApi.CouponTemplateVO>()
  },
  setup(props) {
    const coupon = props.coupon as CouponTemplateApi.CouponTemplateVO
    const text =
      coupon.validityType === CouponTemplateValidityTypeEnum.DATE.type
        ? `有效期:${formatDate(coupon.validStartTime, 'YYYY-MM-DD')} è‡³ ${formatDate(
            coupon.validEndTime,
            'YYYY-MM-DD'
          )}`
        : `领取后第 ${coupon.fixedStartTerm} - ${coupon.fixedEndTerm} å¤©å†…可用`
    return () => <div>{text}</div>
  }
})
src/components/DiyEditor/components/mobile/CouponCard/config.ts
New file
@@ -0,0 +1,47 @@
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
/** å•†å“å¡ç‰‡å±žæ€§ */
export interface CouponCardProperty {
  // åˆ—æ•°
  columns: number
  // èƒŒæ™¯å›¾
  bgImg: string
  // æ–‡å­—颜色
  textColor: string
  // æŒ‰é’®æ ·å¼
  button: {
    // é¢œè‰²
    color: string
    // èƒŒæ™¯é¢œè‰²
    bgColor: string
  }
  // é—´è·
  space: number
  // ä¼˜æƒ åˆ¸ç¼–号列表
  couponIds: number[]
  // ç»„件样式
  style: ComponentStyle
}
// å®šä¹‰ç»„ä»¶
export const component = {
  id: 'CouponCard',
  name: '优惠券',
  icon: 'ep:ticket',
  property: {
    columns: 1,
    bgImg: '',
    textColor: '#E9B461',
    button: {
      color: '#434343',
      bgColor: ''
    },
    space: 0,
    couponIds: [],
    style: {
      bgType: 'color',
      bgColor: '',
      marginBottom: 8
    } as ComponentStyle
  }
} as DiyComponent<CouponCardProperty>
src/components/DiyEditor/components/mobile/CouponCard/index.vue
New file
@@ -0,0 +1,149 @@
<template>
  <el-scrollbar class="z-1 min-h-30px" wrap-class="w-full" ref="containerRef">
    <div
      class="flex flex-row text-12px"
      :style="{
        gap: `${property.space}px`,
        width: scrollbarWidth
      }"
    >
      <div
        class="box-content"
        :style="{
          background: property.bgImg
            ? `url(${property.bgImg}) 100% center / 100% 100% no-repeat`
            : '#fff',
          width: `${couponWidth}px`,
          color: property.textColor
        }"
        v-for="(coupon, index) in couponList"
        :key="index"
      >
        <!-- å¸ƒå±€1:1列-->
        <div v-if="property.columns === 1" class="m-l-16px flex flex-row justify-between p-8px">
          <div class="flex flex-col justify-evenly gap-4px">
            <!-- ä¼˜æƒ å€¼ -->
            <CouponDiscount :coupon="coupon" />
            <!-- ä¼˜æƒ æè¿° -->
            <CouponDiscountDesc :coupon="coupon" />
            <!-- æœ‰æ•ˆæœŸ -->
            <CouponValidTerm :coupon="coupon" />
          </div>
          <div class="flex flex-col justify-evenly">
            <div
              class="rounded-20px p-x-8px p-y-2px"
              :style="{
                color: property.button.color,
                background: property.button.bgColor
              }"
            >
              ç«‹å³é¢†å–
            </div>
          </div>
        </div>
        <!-- å¸ƒå±€2:2列-->
        <div
          v-else-if="property.columns === 2"
          class="m-l-16px flex flex-row justify-between p-8px"
        >
          <div class="flex flex-col justify-evenly gap-4px">
            <!-- ä¼˜æƒ å€¼ -->
            <CouponDiscount :coupon="coupon" />
            <!-- ä¼˜æƒ æè¿° -->
            <CouponDiscountDesc :coupon="coupon" />
            <!-- é¢†å–说明 -->
            <div v-if="coupon.totalCount >= 0">
              ä»…剩:{{ coupon.totalCount - coupon.takeCount }}å¼ 
            </div>
            <div v-else-if="coupon.totalCount === -1">仅剩:不限制</div>
          </div>
          <div class="flex flex-col">
            <div
              class="h-full w-20px rounded-20px p-x-2px p-y-8px text-center"
              :style="{
                color: property.button.color,
                background: property.button.bgColor
              }"
            >
              ç«‹å³é¢†å–
            </div>
          </div>
        </div>
        <!-- å¸ƒå±€3:3列-->
        <div v-else class="flex flex-col items-center justify-around gap-4px p-4px">
          <!-- ä¼˜æƒ å€¼ -->
          <CouponDiscount :coupon="coupon" />
          <!-- ä¼˜æƒ æè¿° -->
          <CouponDiscountDesc :coupon="coupon" />
          <div
            class="rounded-20px p-x-8px p-y-2px"
            :style="{
              color: property.button.color,
              background: property.button.bgColor
            }"
          >
            ç«‹å³é¢†å–
          </div>
        </div>
      </div>
    </div>
  </el-scrollbar>
</template>
<script setup lang="ts">
import { CouponCardProperty } from './config'
import * as CouponTemplateApi from '@/api/mall/promotion/coupon/couponTemplate'
import { CouponDiscount } from './component'
import {
  CouponDiscountDesc,
  CouponValidTerm
} from '@/components/DiyEditor/components/mobile/CouponCard/component'
/** å•†å“å¡ç‰‡ */
defineOptions({ name: 'CouponCard' })
// å®šä¹‰å±žæ€§
const props = defineProps<{ property: CouponCardProperty }>()
// å•†å“åˆ—表
const couponList = ref<CouponTemplateApi.CouponTemplateVO[]>([])
watch(
  () => props.property.couponIds,
  async () => {
    if (props.property.couponIds?.length > 0) {
      couponList.value = await CouponTemplateApi.getCouponTemplateList(props.property.couponIds)
    }
  },
  {
    immediate: true,
    deep: true
  }
)
// æ‰‹æœºå®½åº¦
const phoneWidth = ref(375)
// å®¹å™¨
const containerRef = ref()
// æ»šåŠ¨æ¡å®½åº¦
const scrollbarWidth = ref('100%')
// ä¼˜æƒ åˆ¸çš„宽度
const couponWidth = ref(375)
// è®¡ç®—布局参数
watch(
  () => [props.property, phoneWidth, couponList.value.length],
  () => {
    // æ¯åˆ—的宽度为:(总宽度 - é—´è· * (列数 - 1))/ åˆ—æ•°
    couponWidth.value =
      (phoneWidth.value - props.property.space * (props.property.columns - 1)) /
      props.property.columns
    // æ˜¾ç¤ºæ»šåŠ¨æ¡
    scrollbarWidth.value = `${
      couponWidth.value * couponList.value.length +
      props.property.space * (couponList.value.length - 1)
    }px`
  },
  { immediate: true, deep: true }
)
onMounted(() => {
  // æå–手机宽度
  phoneWidth.value = containerRef.value?.wrapRef?.offsetWidth || 375
})
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/CouponCard/property.vue
New file
@@ -0,0 +1,119 @@
<template>
  <ComponentContainerProperty v-model="formData.style">
    <el-form label-width="80px" :model="formData">
      <el-card header="优惠券列表" class="property-group" shadow="never">
        <div
          v-for="(coupon, index) in couponList"
          :key="index"
          class="flex items-center justify-between"
        >
          <el-text size="large" truncated>{{ coupon.name }}</el-text>
          <el-text type="info" truncated>
            <span v-if="coupon.usePrice > 0">满{{ floatToFixed2(coupon.usePrice) }}元,</span>
            <span v-if="coupon.discountType === PromotionDiscountTypeEnum.PRICE.type">
              å‡{{ floatToFixed2(coupon.discountPrice) }}元
            </span>
            <span v-else> æ‰“{{ coupon.discountPercent }}折 </span>
          </el-text>
        </div>
        <el-form-item label-width="0">
          <el-button @click="handleAddCoupon" type="primary" plain class="m-t-8px w-full">
            <Icon icon="ep:plus" class="mr-5px" /> æ·»åŠ 
          </el-button>
        </el-form-item>
      </el-card>
      <el-card header="优惠券样式" class="property-group" shadow="never">
        <el-form-item label="列数" prop="type">
          <el-radio-group v-model="formData.columns">
            <el-tooltip class="item" content="一列" placement="bottom">
              <el-radio-button :value="1">
                <Icon icon="fluent:text-column-one-24-filled" />
              </el-radio-button>
            </el-tooltip>
            <el-tooltip class="item" content="二列" placement="bottom">
              <el-radio-button :value="2">
                <Icon icon="fluent:text-column-two-24-filled" />
              </el-radio-button>
            </el-tooltip>
            <el-tooltip class="item" content="三列" placement="bottom">
              <el-radio-button :value="3">
                <Icon icon="fluent:text-column-three-24-filled" />
              </el-radio-button>
            </el-tooltip>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="背景图片" prop="bgImg">
          <UploadImg v-model="formData.bgImg" height="80px" width="100%" class="min-w-160px" />
        </el-form-item>
        <el-form-item label="文字颜色" prop="textColor">
          <ColorInput v-model="formData.textColor" />
        </el-form-item>
        <el-form-item label="按钮背景" prop="button.bgColor">
          <ColorInput v-model="formData.button.bgColor" />
        </el-form-item>
        <el-form-item label="按钮文字" prop="button.color">
          <ColorInput v-model="formData.button.color" />
        </el-form-item>
        <el-form-item label="间隔" prop="space">
          <el-slider
            v-model="formData.space"
            :max="100"
            :min="0"
            show-input
            input-size="small"
            :show-input-controls="false"
          />
        </el-form-item>
      </el-card>
    </el-form>
  </ComponentContainerProperty>
  <!-- ä¼˜æƒ åˆ¸é€‰æ‹© -->
  <CouponSelect
    ref="couponSelectDialog"
    v-model:multiple-selection="couponList"
    :take-type="CouponTemplateTakeTypeEnum.USER.type"
    @change="handleCouponSelect"
  />
</template>
<script setup lang="ts">
import { CouponCardProperty } from './config'
import { useVModel } from '@vueuse/core'
import * as CouponTemplateApi from '@/api/mall/promotion/coupon/couponTemplate'
import { floatToFixed2 } from '@/utils'
import { CouponTemplateTakeTypeEnum, PromotionDiscountTypeEnum } from '@/utils/constants'
import CouponSelect from '@/views/mall/promotion/coupon/components/CouponSelect.vue'
// ä¼˜æƒ åˆ¸å¡ç‰‡å±žæ€§é¢æ¿
defineOptions({ name: 'CouponCardProperty' })
const props = defineProps<{ modelValue: CouponCardProperty }>()
const emit = defineEmits(['update:modelValue'])
const formData = useVModel(props, 'modelValue', emit)
// ä¼˜æƒ åˆ¸åˆ—表
const couponList = ref<CouponTemplateApi.CouponTemplateVO[]>([])
const couponSelectDialog = ref()
// æ·»åŠ ä¼˜æƒ åˆ¸
const handleAddCoupon = () => {
  couponSelectDialog.value.open()
}
const handleCouponSelect = () => {
  formData.value.couponIds = couponList.value.map((coupon) => coupon.id)
}
watch(
  () => formData.value.couponIds,
  async () => {
    if (formData.value.couponIds?.length > 0) {
      couponList.value = await CouponTemplateApi.getCouponTemplateList(formData.value.couponIds)
    }
  },
  {
    immediate: true,
    deep: true
  }
)
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/Divider/config.ts
New file
@@ -0,0 +1,29 @@
import { DiyComponent } from '@/components/DiyEditor/util'
/** åˆ†å‰²çº¿å±žæ€§ */
export interface DividerProperty {
  // é«˜åº¦
  height: number
  // çº¿å®½
  lineWidth: number
  // è¾¹è·ç±»åž‹
  paddingType: 'none' | 'horizontal'
  // é¢œè‰²
  lineColor: string
  // ç±»åž‹
  borderType: 'solid' | 'dashed' | 'dotted' | 'none'
}
// å®šä¹‰ç»„ä»¶
export const component = {
  id: 'Divider',
  name: '分割线',
  icon: 'tdesign:component-divider-vertical',
  property: {
    height: 30,
    lineWidth: 1,
    paddingType: 'none',
    lineColor: '#dcdfe6',
    borderType: 'solid'
  }
} as DiyComponent<DividerProperty>
src/components/DiyEditor/components/mobile/Divider/index.vue
New file
@@ -0,0 +1,29 @@
<template>
  <div
    class="flex items-center"
    :style="{
      height: property.height + 'px'
    }"
  >
    <div
      class="w-full"
      :style="{
        borderTopStyle: property.borderType,
        borderTopColor: property.lineColor,
        borderTopWidth: `${property.lineWidth}px`,
        margin: property.paddingType === 'none' ? '0' : '0px 16px'
      }"
    ></div>
  </div>
</template>
<script setup lang="ts">
import { DividerProperty } from './config'
/** é¡µé¢é¡¶éƒ¨å¯¼èˆªæ  */
defineOptions({ name: 'Divider' })
defineProps<{ property: DividerProperty }>()
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/Divider/property.vue
New file
@@ -0,0 +1,80 @@
<template>
  <el-form label-width="80px" :model="formData">
    <el-form-item label="高度" prop="height">
      <el-slider v-model="formData.height" :min="1" :max="100" show-input input-size="small" />
    </el-form-item>
    <el-form-item label="选择样式" prop="borderType">
      <el-radio-group v-model="formData!.borderType">
        <el-tooltip
          placement="top"
          v-for="(item, index) in BORDER_TYPES"
          :key="index"
          :content="item.text"
        >
          <el-radio-button :value="item.type">
            <Icon :icon="item.icon" />
          </el-radio-button>
        </el-tooltip>
      </el-radio-group>
    </el-form-item>
    <template v-if="formData.borderType !== 'none'">
      <el-form-item label="线宽" prop="lineWidth">
        <el-slider v-model="formData.lineWidth" :min="1" :max="30" show-input input-size="small" />
      </el-form-item>
      <el-form-item label="左右边距" prop="paddingType">
        <el-radio-group v-model="formData!.paddingType">
          <el-tooltip content="无边距" placement="top">
            <el-radio-button value="none">
              <Icon icon="tabler:box-padding" />
            </el-radio-button>
          </el-tooltip>
          <el-tooltip content="左右留边" placement="top">
            <el-radio-button value="horizontal">
              <Icon icon="vaadin:padding" />
            </el-radio-button>
          </el-tooltip>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="颜色">
        <!-- åˆ†å‰²çº¿é¢œè‰² -->
        <ColorInput v-model="formData.lineColor" />
      </el-form-item>
    </template>
  </el-form>
</template>
<script setup lang="ts">
import { DividerProperty } from './config'
import { useVModel } from '@vueuse/core'
// å¯¼èˆªæ å±žæ€§é¢æ¿
defineOptions({ name: 'DividerProperty' })
const props = defineProps<{ modelValue: DividerProperty }>()
const emit = defineEmits(['update:modelValue'])
const formData = useVModel(props, 'modelValue', emit)
//线类型
const BORDER_TYPES = [
  {
    icon: 'vaadin:line-h',
    text: '实线',
    type: 'solid'
  },
  {
    icon: 'tabler:line-dashed',
    text: '虚线',
    type: 'dashed'
  },
  {
    icon: 'tabler:line-dotted',
    text: '点线',
    type: 'dotted'
  },
  {
    icon: 'entypo:progress-empty',
    text: '无',
    type: 'none'
  }
]
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/FloatingActionButton/config.ts
New file
@@ -0,0 +1,36 @@
import { DiyComponent } from '@/components/DiyEditor/util'
// æ‚¬æµ®æŒ‰é’®å±žæ€§
export interface FloatingActionButtonProperty {
  // å±•开方向
  direction: 'horizontal' | 'vertical'
  // æ˜¯å¦æ˜¾ç¤ºæ–‡å­—
  showText: boolean
  // æŒ‰é’®åˆ—表
  list: FloatingActionButtonItemProperty[]
}
// æ‚¬æµ®æŒ‰é’®é¡¹å±žæ€§
export interface FloatingActionButtonItemProperty {
  // å›¾ç‰‡åœ°å€
  imgUrl: string
  // è·³è½¬è¿žæŽ¥
  url: string
  // æ–‡å­—
  text: string
  // æ–‡å­—颜色
  textColor: string
}
// å®šä¹‰ç»„ä»¶
export const component = {
  id: 'FloatingActionButton',
  name: '悬浮按钮',
  icon: 'tabler:float-right',
  position: 'fixed',
  property: {
    direction: 'vertical',
    showText: true,
    list: [{ textColor: '#fff' }]
  }
} as DiyComponent<FloatingActionButtonProperty>
src/components/DiyEditor/components/mobile/FloatingActionButton/index.vue
New file
@@ -0,0 +1,74 @@
<template>
  <div
    :class="[
      'absolute bottom-32px right-[calc(50%-375px/2+32px)] flex z-12 gap-12px items-center',
      {
        'flex-row': property.direction === 'horizontal',
        'flex-col': property.direction === 'vertical'
      }
    ]"
  >
    <template v-if="expanded">
      <div
        v-for="(item, index) in property.list"
        :key="index"
        class="flex flex-col items-center"
        @click="handleActive(index)"
      >
        <el-image :src="item.imgUrl" fit="contain" class="h-27px w-27px">
          <template #error>
            <div class="h-full w-full flex items-center justify-center">
              <Icon icon="ep:picture" :color="item.textColor" />
            </div>
          </template>
        </el-image>
        <span v-if="property.showText" class="mt-4px text-12px" :style="{ color: item.textColor }">
          {{ item.text }}
        </span>
      </div>
    </template>
    <!-- todo: @owen ä½¿ç”¨APP主题色 -->
    <el-button type="primary" size="large" circle @click="handleToggleFab">
      <Icon icon="ep:plus" :class="['fab-icon', { active: expanded }]" />
    </el-button>
  </div>
  <!-- æ¨¡æ€èƒŒæ™¯ï¼šå±•开时显示,点击后折叠 -->
  <div v-if="expanded" class="modal-bg" @click="handleToggleFab"></div>
</template>
<script setup lang="ts">
import { FloatingActionButtonProperty } from './config'
/** æ‚¬æµ®æŒ‰é’® */
defineOptions({ name: 'FloatingActionButton' })
// å®šä¹‰å±žæ€§
defineProps<{ property: FloatingActionButtonProperty }>()
// æ˜¯å¦å±•å¼€
const expanded = ref(false)
// å¤„理展开/折叠
const handleToggleFab = () => {
  expanded.value = !expanded.value
}
</script>
<style scoped lang="scss">
/* æ¨¡æ€èƒŒæ™¯ */
.modal-bg {
  position: absolute;
  left: calc(50% - 375px / 2);
  top: 0;
  z-index: 11;
  width: 375px;
  height: 100%;
  background-color: rgba(#000000, 0.4);
}
.fab-icon {
  transform: rotate(0deg);
  transition: transform 0.3s;
  &.active {
    transform: rotate(135deg);
  }
}
</style>
src/components/DiyEditor/components/mobile/FloatingActionButton/property.vue
New file
@@ -0,0 +1,44 @@
<template>
  <el-form label-width="80px" :model="formData">
    <el-card header="按钮配置" class="property-group" shadow="never">
      <el-form-item label="展开方向" prop="direction">
        <el-radio-group v-model="formData.direction">
          <el-radio value="vertical">垂直</el-radio>
          <el-radio value="horizontal">æ°´å¹³</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="显示文字" prop="showText">
        <el-switch v-model="formData.showText" />
      </el-form-item>
    </el-card>
    <el-card header="按钮列表" class="property-group" shadow="never">
      <Draggable v-model="formData.list" :empty-item="{ textColor: '#fff' }">
        <template #default="{ element, index }">
          <el-form-item label="图标" :prop="`list[${index}].imgUrl`">
            <UploadImg v-model="element.imgUrl" height="56px" width="56px" />
          </el-form-item>
          <el-form-item label="文字" :prop="`list[${index}].text`">
            <InputWithColor v-model="element.text" v-model:color="element.textColor" />
          </el-form-item>
          <el-form-item label="跳转链接" :prop="`list[${index}].url`">
            <AppLinkInput v-model="element.url" />
          </el-form-item>
        </template>
      </Draggable>
    </el-card>
  </el-form>
</template>
<script setup lang="ts">
import { FloatingActionButtonProperty } from './config'
import { useVModel } from '@vueuse/core'
// æ‚¬æµ®æŒ‰é’®å±žæ€§é¢æ¿
defineOptions({ name: 'FloatingActionButtonProperty' })
const props = defineProps<{ modelValue: FloatingActionButtonProperty }>()
const emit = defineEmits(['update:modelValue'])
const formData = useVModel(props, 'modelValue', emit)
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/HotZone/components/HotZoneEditDialog/controller.ts
New file
@@ -0,0 +1,143 @@
import { HotZoneItemProperty } from '@/components/DiyEditor/components/mobile/HotZone/config'
import { StyleValue } from 'vue'
// çƒ­åŒºçš„æœ€å°å®½é«˜
export const HOT_ZONE_MIN_SIZE = 100
// æŽ§åˆ¶çš„类型
export enum CONTROL_TYPE_ENUM {
  LEFT,
  TOP,
  WIDTH,
  HEIGHT
}
// å®šä¹‰çƒ­åŒºçš„æŽ§åˆ¶ç‚¹
export interface ControlDot {
  position: string
  types: CONTROL_TYPE_ENUM[]
  style: StyleValue
}
// çƒ­åŒºçš„8个控制点
export const CONTROL_DOT_LIST = [
  {
    position: '左上角',
    types: [
      CONTROL_TYPE_ENUM.LEFT,
      CONTROL_TYPE_ENUM.TOP,
      CONTROL_TYPE_ENUM.WIDTH,
      CONTROL_TYPE_ENUM.HEIGHT
    ],
    style: { left: '-5px', top: '-5px', cursor: 'nwse-resize' }
  },
  {
    position: '上方中间',
    types: [CONTROL_TYPE_ENUM.TOP, CONTROL_TYPE_ENUM.HEIGHT],
    style: { left: '50%', top: '-5px', cursor: 'n-resize', transform: 'translateX(-50%)' }
  },
  {
    position: '右上角',
    types: [CONTROL_TYPE_ENUM.TOP, CONTROL_TYPE_ENUM.WIDTH, CONTROL_TYPE_ENUM.HEIGHT],
    style: { right: '-5px', top: '-5px', cursor: 'nesw-resize' }
  },
  {
    position: '右侧中间',
    types: [CONTROL_TYPE_ENUM.WIDTH],
    style: { right: '-5px', top: '50%', cursor: 'e-resize', transform: 'translateX(-50%)' }
  },
  {
    position: '右下角',
    types: [CONTROL_TYPE_ENUM.WIDTH, CONTROL_TYPE_ENUM.HEIGHT],
    style: { right: '-5px', bottom: '-5px', cursor: 'nwse-resize' }
  },
  {
    position: '下方中间',
    types: [CONTROL_TYPE_ENUM.HEIGHT],
    style: { left: '50%', bottom: '-5px', cursor: 's-resize', transform: 'translateX(-50%)' }
  },
  {
    position: '左下角',
    types: [CONTROL_TYPE_ENUM.LEFT, CONTROL_TYPE_ENUM.WIDTH, CONTROL_TYPE_ENUM.HEIGHT],
    style: { left: '-5px', bottom: '-5px', cursor: 'nesw-resize' }
  },
  {
    position: '左侧中间',
    types: [CONTROL_TYPE_ENUM.LEFT, CONTROL_TYPE_ENUM.WIDTH],
    style: { left: '-5px', top: '50%', cursor: 'w-resize', transform: 'translateX(-50%)' }
  }
] as ControlDot[]
//region çƒ­åŒºçš„缩放
// çƒ­åŒºçš„缩放比例
export const HOT_ZONE_SCALE_RATE = 2
// ç¼©å°ï¼šç¼©å›žé€‚合手机屏幕的大小
export const zoomOut = (list?: HotZoneItemProperty[]) => {
  return (
    list?.map((hotZone) => ({
      ...hotZone,
      left: (hotZone.left /= HOT_ZONE_SCALE_RATE),
      top: (hotZone.top /= HOT_ZONE_SCALE_RATE),
      width: (hotZone.width /= HOT_ZONE_SCALE_RATE),
      height: (hotZone.height /= HOT_ZONE_SCALE_RATE)
    })) || []
  )
}
// æ”¾å¤§ï¼šä½œç”¨æ˜¯ä¸ºäº†æ–¹ä¾¿åœ¨ç”µè„‘屏幕上编辑
export const zoomIn = (list?: HotZoneItemProperty[]) => {
  return (
    list?.map((hotZone) => ({
      ...hotZone,
      left: (hotZone.left *= HOT_ZONE_SCALE_RATE),
      top: (hotZone.top *= HOT_ZONE_SCALE_RATE),
      width: (hotZone.width *= HOT_ZONE_SCALE_RATE),
      height: (hotZone.height *= HOT_ZONE_SCALE_RATE)
    })) || []
  )
}
//endregion
/**
 * å°è£…热区拖拽
 *
 * æ³¨ï¼šä¸ºä»€ä¹ˆä¸ä½¿ç”¨vueuse的useDraggable。在本场景下,其使用方式比较复杂
 * @param hotZone çƒ­åŒº
 * @param downEvent é¼ æ ‡æŒ‰ä¸‹äº‹ä»¶
 * @param callback å›žè°ƒå‡½æ•°
 */
export const useDraggable = (
  hotZone: HotZoneItemProperty,
  downEvent: MouseEvent,
  callback: (
    left: number,
    top: number,
    width: number,
    height: number,
    moveWidth: number,
    moveHeight: number
  ) => void
) => {
  // é˜»æ­¢äº‹ä»¶å†’泡
  downEvent.stopPropagation()
  // ç§»åŠ¨å‰çš„é¼ æ ‡åæ ‡
  const { clientX: startX, clientY: startY } = downEvent
  // ç§»åŠ¨å‰çš„çƒ­åŒºåæ ‡ã€å¤§å°
  const { left, top, width, height } = hotZone
  // ç›‘听鼠标移动
  document.onmousemove = (e) => {
    // ç§»åŠ¨å®½åº¦
    const moveWidth = e.clientX - startX
    // ç§»åŠ¨é«˜åº¦
    const moveHeight = e.clientY - startY
    // ç§»åŠ¨å›žè°ƒ
    callback(left, top, width, height, moveWidth, moveHeight)
  }
  // æ¾å¼€é¼ æ ‡åŽï¼Œç»“束拖拽
  document.onmouseup = () => {
    document.onmousemove = null
    document.onmouseup = null
  }
}
src/components/DiyEditor/components/mobile/HotZone/components/HotZoneEditDialog/index.vue
New file
@@ -0,0 +1,236 @@
<template>
  <Dialog v-model="dialogVisible" title="设置热区" width="780" @close="handleClose">
    <div ref="container" class="relative h-full w-750px">
      <el-image :src="imgUrl" class="pointer-events-none h-full w-750px select-none" />
      <div
        v-for="(item, hotZoneIndex) in formData"
        :key="hotZoneIndex"
        class="hot-zone"
        :style="{
          width: `${item.width}px`,
          height: `${item.height}px`,
          top: `${item.top}px`,
          left: `${item.left}px`
        }"
        @mousedown="handleMove(item, $event)"
        @dblclick="handleShowAppLinkDialog(item)"
      >
        <span class="pointer-events-none select-none">{{ item.name || '双击选择链接' }}</span>
        <Icon icon="ep:close" class="delete" :size="14" @click="handleRemove(item)" />
        <!-- 8个控制点 -->
        <span
          class="ctrl-dot"
          v-for="(dot, dotIndex) in CONTROL_DOT_LIST"
          :key="dotIndex"
          :style="dot.style"
          @mousedown="handleResize(item, dot, $event)"
        ></span>
      </div>
    </div>
    <template #footer>
      <el-button @click="handleAdd" type="primary" plain>
        <Icon icon="ep:plus" class="mr-5px" />
        æ·»åŠ çƒ­åŒº
      </el-button>
      <el-button @click="handleSubmit" type="primary" plain>
        <Icon icon="ep:check" class="mr-5px" />
        ç¡®å®š
      </el-button>
    </template>
  </Dialog>
  <AppLinkSelectDialog ref="appLinkDialogRef" @app-link-change="handleAppLinkChange" />
</template>
<script setup lang="ts">
import { HotZoneItemProperty } from '@/components/DiyEditor/components/mobile/HotZone/config'
import { array, string } from 'vue-types'
import {
  CONTROL_DOT_LIST,
  CONTROL_TYPE_ENUM,
  ControlDot,
  HOT_ZONE_MIN_SIZE,
  useDraggable,
  zoomIn,
  zoomOut
} from './controller'
import { AppLink } from '@/components/AppLinkInput/data'
import { remove } from 'lodash-es'
/** çƒ­åŒºç¼–辑对话框 */
defineOptions({ name: 'HotZoneEditDialog' })
// å®šä¹‰å±žæ€§
const props = defineProps({
  modelValue: array<HotZoneItemProperty>(),
  imgUrl: string().def('')
})
const emit = defineEmits(['update:modelValue'])
const formData = ref<HotZoneItemProperty[]>([])
// å¼¹çª—的是否显示
const dialogVisible = ref(false)
// æ‰“开弹窗
const open = () => {
  // æ”¾å¤§
  formData.value = zoomIn(props.modelValue)
  dialogVisible.value = true
}
// æä¾› open æ–¹æ³•,用于打开弹窗
defineExpose({ open })
// çƒ­åŒºå®¹å™¨
const container = ref<HTMLDivElement>()
// å¢žåŠ çƒ­åŒº
const handleAdd = () => {
  formData.value.push({
    width: HOT_ZONE_MIN_SIZE,
    height: HOT_ZONE_MIN_SIZE,
    top: 0,
    left: 0
  } as HotZoneItemProperty)
}
// åˆ é™¤çƒ­åŒº
const handleRemove = (hotZone: HotZoneItemProperty) => {
  remove(formData.value, hotZone)
}
// ç§»åŠ¨çƒ­åŒº
const handleMove = (item: HotZoneItemProperty, e: MouseEvent) => {
  useDraggable(item, e, (left, top, _, __, moveWidth, moveHeight) => {
    setLeft(item, left + moveWidth)
    setTop(item, top + moveHeight)
  })
}
// è°ƒæ•´çƒ­åŒºå¤§å°ã€ä½ç½®
const handleResize = (item: HotZoneItemProperty, ctrlDot: ControlDot, e: MouseEvent) => {
  useDraggable(item, e, (left, top, width, height, moveWidth, moveHeight) => {
    ctrlDot.types.forEach((type) => {
      switch (type) {
        case CONTROL_TYPE_ENUM.LEFT:
          setLeft(item, left + moveWidth)
          break
        case CONTROL_TYPE_ENUM.TOP:
          setTop(item, top + moveHeight)
          break
        case CONTROL_TYPE_ENUM.WIDTH:
          {
            // ä¸Šç§»æ—¶ï¼Œé«˜åº¦ä¸ºå‡å°‘
            const direction = ctrlDot.types.includes(CONTROL_TYPE_ENUM.LEFT) ? -1 : 1
            setWidth(item, width + moveWidth * direction)
          }
          break
        case CONTROL_TYPE_ENUM.HEIGHT:
          {
            // å·¦ç§»æ—¶ï¼Œå®½åº¦ä¸ºå‡å°‘
            const direction = ctrlDot.types.includes(CONTROL_TYPE_ENUM.TOP) ? -1 : 1
            setHeight(item, height + moveHeight * direction)
          }
          break
      }
    })
  })
}
// è®¾ç½®X轴坐标
const setLeft = (item: HotZoneItemProperty, left: number) => {
  // ä¸èƒ½è¶…出容器
  if (left >= 0 && left <= container.value!.offsetWidth - item.width) {
    item.left = left
  }
}
// è®¾ç½®Y轴坐标
const setTop = (item: HotZoneItemProperty, top: number) => {
  // ä¸èƒ½è¶…出容器
  if (top >= 0 && top <= container.value!.offsetHeight - item.height) {
    item.top = top
  }
}
// è®¾ç½®å®½åº¦
const setWidth = (item: HotZoneItemProperty, width: number) => {
  // ä¸èƒ½å°äºŽæœ€å°å®½åº¦ && ä¸èƒ½è¶…出容器右边
  if (width >= HOT_ZONE_MIN_SIZE && item.left + width <= container.value!.offsetWidth) {
    item.width = width
  }
}
// è®¾ç½®é«˜åº¦
const setHeight = (item: HotZoneItemProperty, height: number) => {
  // ä¸èƒ½å°äºŽæœ€å°é«˜åº¦ && ä¸èƒ½è¶…出容器底部
  if (height >= HOT_ZONE_MIN_SIZE && item.top + height <= container.value!.offsetHeight) {
    item.height = height
  }
}
// å¤„理对话框关闭
const handleSubmit = () => {
  // ä¼šè‡ªåŠ¨è§¦å‘handleClose
  dialogVisible.value = false
}
// å¤„理对话框关闭
const handleClose = () => {
  // ç¼©å°
  const list = zoomOut(formData.value)
  emit('update:modelValue', list)
}
const activeHotZone = ref<HotZoneItemProperty>()
const appLinkDialogRef = ref()
const handleShowAppLinkDialog = (hotZone: HotZoneItemProperty) => {
  activeHotZone.value = hotZone
  appLinkDialogRef.value.open(hotZone.url)
}
const handleAppLinkChange = (appLink: AppLink) => {
  if (!appLink || !activeHotZone.value) return
  activeHotZone.value.name = appLink.name
  activeHotZone.value.url = appLink.path
}
</script>
<style scoped lang="scss">
.hot-zone {
  position: absolute;
  background: var(--el-color-primary-light-7);
  opacity: 0.8;
  border: 1px solid var(--el-color-primary);
  color: var(--el-color-primary);
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: move;
  z-index: 10;
  /* æŽ§åˆ¶ç‚¹ */
  .ctrl-dot {
    position: absolute;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    border: inherit;
    background-color: #fff;
    z-index: 11;
  }
  .delete {
    display: none;
    position: absolute;
    top: 0;
    right: 0;
    padding: 2px 2px 6px 6px;
    background-color: var(--el-color-primary);
    border-radius: 0 0 0 80%;
    cursor: pointer;
    color: #fff;
    text-align: right;
  }
  &:hover {
    .delete {
      display: block;
    }
  }
}
</style>
src/components/DiyEditor/components/mobile/HotZone/config.ts
New file
@@ -0,0 +1,43 @@
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
/** çƒ­åŒºå±žæ€§ */
export interface HotZoneProperty {
  // å›¾ç‰‡åœ°å€
  imgUrl: string
  // å¯¼èˆªèœå•列表
  list: HotZoneItemProperty[]
  // ç»„件样式
  style: ComponentStyle
}
/** çƒ­åŒºé¡¹ç›®å±žæ€§ */
export interface HotZoneItemProperty {
  // é“¾æŽ¥çš„名称
  name: string
  // é“¾æŽ¥
  url: string
  // å®½
  width: number
  // é«˜
  height: number
  // ä¸Š
  top: number
  // å·¦
  left: number
}
// å®šä¹‰ç»„ä»¶
export const component = {
  id: 'HotZone',
  name: '热区',
  icon: 'tabler:hand-click',
  property: {
    imgUrl: '',
    list: [] as HotZoneItemProperty[],
    style: {
      bgType: 'color',
      bgColor: '#fff',
      marginBottom: 8
    } as ComponentStyle
  }
} as DiyComponent<HotZoneProperty>
src/components/DiyEditor/components/mobile/HotZone/index.vue
New file
@@ -0,0 +1,42 @@
<template>
  <div class="relative h-full min-h-30px w-full">
    <el-image :src="property.imgUrl" class="pointer-events-none h-full w-full select-none" />
    <div
      v-for="(item, index) in property.list"
      :key="index"
      class="hot-zone"
      :style="{
        width: `${item.width}px`,
        height: `${item.height}px`,
        top: `${item.top}px`,
        left: `${item.left}px`
      }"
    >
      {{ item.name }}
    </div>
  </div>
</template>
<script setup lang="ts">
import { HotZoneProperty } from './config'
/** çƒ­åŒº */
defineOptions({ name: 'HotZone' })
const props = defineProps<{ property: HotZoneProperty }>()
</script>
<style scoped lang="scss">
.hot-zone {
  position: absolute;
  background: var(--el-color-primary-light-7);
  opacity: 0.8;
  border: 1px solid var(--el-color-primary);
  color: var(--el-color-primary);
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: move;
  z-index: 10;
}
</style>
src/components/DiyEditor/components/mobile/HotZone/property.vue
New file
@@ -0,0 +1,63 @@
<template>
  <ComponentContainerProperty v-model="formData.style">
    <!-- è¡¨å• -->
    <el-form label-width="80px" :model="formData" class="m-t-8px">
      <el-form-item label="上传图片" prop="imgUrl">
        <UploadImg v-model="formData.imgUrl" height="50px" width="auto" class="min-w-80px">
          <template #tip>
            <el-text type="info" size="small"> æŽ¨èå®½åº¦ 750</el-text>
          </template>
        </UploadImg>
      </el-form-item>
    </el-form>
    <el-button type="primary" plain class="w-full" @click="handleOpenEditDialog">
      è®¾ç½®çƒ­åŒº
    </el-button>
  </ComponentContainerProperty>
  <!-- çƒ­åŒºç¼–辑对话框 -->
  <HotZoneEditDialog ref="editDialogRef" v-model="formData.list" :img-url="formData.imgUrl" />
</template>
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import { HotZoneProperty } from '@/components/DiyEditor/components/mobile/HotZone/config'
import HotZoneEditDialog from './components/HotZoneEditDialog/index.vue'
/** çƒ­åŒºå±žæ€§é¢æ¿ */
defineOptions({ name: 'HotZoneProperty' })
const props = defineProps<{ modelValue: HotZoneProperty }>()
const emit = defineEmits(['update:modelValue'])
const formData = useVModel(props, 'modelValue', emit)
// çƒ­åŒºç¼–辑对话框
const editDialogRef = ref()
// æ‰“开热区编辑对话框
const handleOpenEditDialog = () => {
  editDialogRef.value.open()
}
</script>
<style scoped lang="scss">
.hot-zone {
  position: absolute;
  background: #409effbf;
  border: 1px solid var(--el-color-primary);
  color: #fff;
  font-size: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: move;
  /* æŽ§åˆ¶ç‚¹ */
  .ctrl-dot {
    position: absolute;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background-color: #fff;
  }
}
</style>
src/components/DiyEditor/components/mobile/ImageBar/config.ts
New file
@@ -0,0 +1,27 @@
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
/** å›¾ç‰‡å±•示属性 */
export interface ImageBarProperty {
  // å›¾ç‰‡é“¾æŽ¥
  imgUrl: string
  // è·³è½¬é“¾æŽ¥
  url: string
  // ç»„件样式
  style: ComponentStyle
}
// å®šä¹‰ç»„ä»¶
export const component = {
  id: 'ImageBar',
  name: '图片展示',
  icon: 'ep:picture',
  property: {
    imgUrl: '',
    url: '',
    style: {
      bgType: 'color',
      bgColor: '#fff',
      marginBottom: 8
    } as ComponentStyle
  }
} as DiyComponent<ImageBarProperty>
src/components/DiyEditor/components/mobile/ImageBar/index.vue
New file
@@ -0,0 +1,24 @@
<template>
  <!-- æ— å›¾ç‰‡ -->
  <div class="h-50px flex items-center justify-center bg-gray-3" v-if="!property.imgUrl">
    <Icon icon="ep:picture" class="text-gray-8 text-30px!" />
  </div>
  <el-image class="min-h-30px" v-else :src="property.imgUrl" />
</template>
<script setup lang="ts">
import { ImageBarProperty } from './config'
/** å›¾ç‰‡å±•示 */
defineOptions({ name: 'ImageBar' })
defineProps<{ property: ImageBarProperty }>()
</script>
<style scoped lang="scss">
/* å›¾ç‰‡ */
img {
  display: block;
  width: 100%;
  height: 100%;
}
</style>
src/components/DiyEditor/components/mobile/ImageBar/property.vue
New file
@@ -0,0 +1,34 @@
<template>
  <ComponentContainerProperty v-model="formData.style">
    <el-form label-width="80px" :model="formData">
      <el-form-item label="上传图片" prop="imgUrl">
        <UploadImg
          v-model="formData.imgUrl"
          draggable="false"
          height="80px"
          width="100%"
          class="min-w-80px"
        >
          <template #tip> å»ºè®®å®½åº¦750 </template>
        </UploadImg>
      </el-form-item>
      <el-form-item label="链接" prop="url">
        <AppLinkInput v-model="formData.url" />
      </el-form-item>
    </el-form>
  </ComponentContainerProperty>
</template>
<script setup lang="ts">
import { ImageBarProperty } from './config'
import { useVModel } from '@vueuse/core'
// å›¾ç‰‡å±•示属性面板
defineOptions({ name: 'ImageBarProperty' })
const props = defineProps<{ modelValue: ImageBarProperty }>()
const emit = defineEmits(['update:modelValue'])
const formData = useVModel(props, 'modelValue', emit)
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/MagicCube/config.ts
New file
@@ -0,0 +1,49 @@
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
/** å¹¿å‘Šé­”方属性 */
export interface MagicCubeProperty {
  // ä¸Šåœ†è§’
  borderRadiusTop: number
  // ä¸‹åœ†è§’
  borderRadiusBottom: number
  // é—´éš”
  space: number
  // å¯¼èˆªèœå•列表
  list: MagicCubeItemProperty[]
  // ç»„件样式
  style: ComponentStyle
}
/** å¹¿å‘Šé­”方项目属性 */
export interface MagicCubeItemProperty {
  // å›¾æ ‡é“¾æŽ¥
  imgUrl: string
  // é“¾æŽ¥
  url: string
  // å®½
  width: number
  // é«˜
  height: number
  // ä¸Š
  top: number
  // å·¦
  left: number
}
// å®šä¹‰ç»„ä»¶
export const component = {
  id: 'MagicCube',
  name: '广告魔方',
  icon: 'bi:columns',
  property: {
    borderRadiusTop: 0,
    borderRadiusBottom: 0,
    space: 0,
    list: [],
    style: {
      bgType: 'color',
      bgColor: '#fff',
      marginBottom: 8
    } as ComponentStyle
  }
} as DiyComponent<MagicCubeProperty>
src/components/DiyEditor/components/mobile/MagicCube/index.vue
New file
@@ -0,0 +1,76 @@
<template>
  <div
    class="relative"
    :style="{
      height: `${rowCount * CUBE_SIZE}px`,
      width: `${4 * CUBE_SIZE}px`,
      padding: `${property.space}px`
    }"
  >
    <div
      v-for="(item, index) in property.list"
      :key="index"
      class="absolute"
      :style="{
        width: `${item.width * CUBE_SIZE - property.space}px`,
        height: `${item.height * CUBE_SIZE - property.space}px`,
        top: `${item.top * CUBE_SIZE}px`,
        left: `${item.left * CUBE_SIZE}px`
      }"
    >
      <el-image
        class="h-full w-full"
        fit="cover"
        :src="item.imgUrl"
        :style="{
          borderTopLeftRadius: `${property.borderRadiusTop}px`,
          borderTopRightRadius: `${property.borderRadiusTop}px`,
          borderBottomLeftRadius: `${property.borderRadiusBottom}px`,
          borderBottomRightRadius: `${property.borderRadiusBottom}px`
        }"
      >
        <template #error>
          <div class="image-slot">
            <div
              class="flex items-center justify-center"
              :style="{
                width: `${item.width * CUBE_SIZE}px`,
                height: `${item.height * CUBE_SIZE}px`
              }"
            >
              <Icon icon="ep-picture" color="gray" :size="CUBE_SIZE" />
            </div>
          </div>
        </template>
      </el-image>
    </div>
  </div>
</template>
<script setup lang="ts">
import { MagicCubeProperty } from './config'
/** å¹¿å‘Šé­”æ–¹ */
defineOptions({ name: 'MagicCube' })
const props = defineProps<{ property: MagicCubeProperty }>()
// ä¸€ä¸ªæ–¹å—的大小
const CUBE_SIZE = 93.75
/**
 * è®¡ç®—方块的行数
 * è¡Œæ•°ç”¨äºŽè®¡ç®—魔方的总体高度,存在以下情况:
 * 1. æ²¡æœ‰æ•°æ®æ—¶ï¼Œé»˜è®¤å°±åªæ˜¾ç¤ºä¸€è¡Œçš„高度
 * 2. åº•部的空白不算高度,例如只有第一行有数据,那么就只显示一行的高度
 * 3. é¡¶éƒ¨åŠä¸­é—´çš„空白算高度,例如一共有四行,只有最后一行有数据,那么也显示四行的高度
 */
const rowCount = computed(() => {
  let count = 0
  if (props.property.list.length > 0) {
    // æœ€å¤§è¡Œå·
    count = Math.max(...props.property.list.map((item) => item.top + item.height))
  }
  // ä¿è¯è‡³å°‘有一行
  return count == 0 ? 1 : count
})
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/MagicCube/property.vue
New file
@@ -0,0 +1,76 @@
<template>
  <ComponentContainerProperty v-model="formData.style">
    <!-- è¡¨å• -->
    <el-form label-width="80px" :model="formData" class="m-t-8px">
      <el-text tag="p"> é­”方设置 </el-text>
      <el-text type="info" size="small"> æ¯æ ¼å°ºå¯¸187 * 187 </el-text>
      <MagicCubeEditor
        class="m-y-16px"
        v-model="formData.list"
        :rows="4"
        :cols="4"
        @hot-area-selected="handleHotAreaSelected"
      />
      <template v-for="(hotArea, index) in formData.list" :key="index">
        <template v-if="selectedHotAreaIndex === index">
          <el-form-item label="上传图片" :prop="`list[${index}].imgUrl`">
            <UploadImg v-model="hotArea.imgUrl" height="80px" width="80px" />
          </el-form-item>
          <el-form-item label="链接" :prop="`list[${index}].url`">
            <AppLinkInput v-model="hotArea.url" />
          </el-form-item>
        </template>
      </template>
      <el-form-item label="上圆角" prop="borderRadiusTop">
        <el-slider
          v-model="formData.borderRadiusTop"
          :max="100"
          :min="0"
          show-input
          input-size="small"
          :show-input-controls="false"
        />
      </el-form-item>
      <el-form-item label="下圆角" prop="borderRadiusBottom">
        <el-slider
          v-model="formData.borderRadiusBottom"
          :max="100"
          :min="0"
          show-input
          input-size="small"
          :show-input-controls="false"
        />
      </el-form-item>
      <el-form-item label="间隔" prop="space">
        <el-slider
          v-model="formData.space"
          :max="100"
          :min="0"
          show-input
          input-size="small"
          :show-input-controls="false"
        />
      </el-form-item>
    </el-form>
  </ComponentContainerProperty>
</template>
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import { MagicCubeProperty } from '@/components/DiyEditor/components/mobile/MagicCube/config'
/** å¹¿å‘Šé­”方属性面板 */
defineOptions({ name: 'MagicCubeProperty' })
const props = defineProps<{ modelValue: MagicCubeProperty }>()
const emit = defineEmits(['update:modelValue'])
const formData = useVModel(props, 'modelValue', emit)
// é€‰ä¸­çš„热区
const selectedHotAreaIndex = ref(-1)
const handleHotAreaSelected = (_: any, index: number) => {
  selectedHotAreaIndex.value = index
}
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/MenuGrid/config.ts
New file
@@ -0,0 +1,79 @@
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
import { cloneDeep } from 'lodash-es'
/** å®«æ ¼å¯¼èˆªå±žæ€§ */
export interface MenuGridProperty {
  // åˆ—æ•°
  column: number
  // å¯¼èˆªèœå•列表
  list: MenuGridItemProperty[]
  // ç»„件样式
  style: ComponentStyle
}
/** å®«æ ¼å¯¼èˆªé¡¹ç›®å±žæ€§ */
export interface MenuGridItemProperty {
  // å›¾æ ‡é“¾æŽ¥
  iconUrl: string
  // æ ‡é¢˜
  title: string
  // æ ‡é¢˜é¢œè‰²
  titleColor: string
  // å‰¯æ ‡é¢˜
  subtitle: string
  // å‰¯æ ‡é¢˜é¢œè‰²
  subtitleColor: string
  // é“¾æŽ¥
  url: string
  // è§’æ ‡
  badge: {
    // æ˜¯å¦æ˜¾ç¤º
    show: boolean
    // è§’标文字
    text: string
    // è§’标文字颜色
    textColor: string
    // è§’标背景颜色
    bgColor: string
  }
}
export const EMPTY_MENU_GRID_ITEM_PROPERTY = {
  title: '标题',
  titleColor: '#333',
  subtitle: '副标题',
  subtitleColor: '#bbb',
  badge: {
    show: false,
    textColor: '#fff',
    bgColor: '#FF6000'
  }
} as MenuGridItemProperty
// å®šä¹‰ç»„ä»¶
export const component = {
  id: 'MenuGrid',
  name: '宫格导航',
  icon: 'bi:grid-3x3-gap',
  property: {
    column: 3,
    list: [cloneDeep(EMPTY_MENU_GRID_ITEM_PROPERTY)],
    style: {
      bgType: 'color',
      bgColor: '#fff',
      marginBottom: 8,
      marginLeft: 8,
      marginRight: 8,
      padding: 8,
      paddingTop: 8,
      paddingRight: 8,
      paddingBottom: 8,
      paddingLeft: 8,
      borderRadius: 8,
      borderTopLeftRadius: 8,
      borderTopRightRadius: 8,
      borderBottomRightRadius: 8,
      borderBottomLeftRadius: 8
    } as ComponentStyle
  }
} as DiyComponent<MenuGridProperty>
src/components/DiyEditor/components/mobile/MenuGrid/index.vue
New file
@@ -0,0 +1,35 @@
<template>
  <div class="flex flex-row flex-wrap">
    <div
      v-for="(item, index) in property.list"
      :key="index"
      class="relative flex flex-col items-center p-b-14px p-t-20px"
      :style="{ width: `${100 * (1 / property.column)}%` }"
    >
      <!-- å³ä¸Šè§’è§’æ ‡ -->
      <span
        v-if="item.badge?.show"
        class="absolute left-50% top-10px z-1 h-20px rounded-50% p-x-6px text-center text-12px leading-20px"
        :style="{ color: item.badge.textColor, backgroundColor: item.badge.bgColor }"
      >
        {{ item.badge.text }}
      </span>
      <el-image v-if="item.iconUrl" class="h-28px w-28px" :src="item.iconUrl" />
      <span class="m-t-8px h-16px text-12px leading-16px" :style="{ color: item.titleColor }">
        {{ item.title }}
      </span>
      <span class="m-t-6px h-12px text-10px leading-12px" :style="{ color: item.subtitleColor }">
        {{ item.subtitle }}
      </span>
    </div>
  </div>
</template>
<script setup lang="ts">
import { MenuGridProperty } from './config'
/** å®«æ ¼å¯¼èˆª */
defineOptions({ name: 'MenuGrid' })
defineProps<{ property: MenuGridProperty }>()
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/MenuGrid/property.vue
New file
@@ -0,0 +1,65 @@
<template>
  <ComponentContainerProperty v-model="formData.style">
    <!-- è¡¨å• -->
    <el-form label-width="80px" :model="formData" class="m-t-8px">
      <el-form-item label="每行数量" prop="column">
        <el-radio-group v-model="formData.column">
          <el-radio :value="3">3个</el-radio>
          <el-radio :value="4">4个</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-card header="菜单设置" class="property-group" shadow="never">
        <Draggable v-model="formData.list" :empty-item="EMPTY_MENU_GRID_ITEM_PROPERTY">
          <template #default="{ element }">
            <el-form-item label="图标" prop="iconUrl">
              <UploadImg v-model="element.iconUrl" height="80px" width="80px">
                <template #tip> å»ºè®®å°ºå¯¸ï¼š44 * 44 </template>
              </UploadImg>
            </el-form-item>
            <el-form-item label="标题" prop="title">
              <InputWithColor v-model="element.title" v-model:color="element.titleColor" />
            </el-form-item>
            <el-form-item label="副标题" prop="subtitle">
              <InputWithColor v-model="element.subtitle" v-model:color="element.subtitleColor" />
            </el-form-item>
            <el-form-item label="链接" prop="url">
              <AppLinkInput v-model="element.url" />
            </el-form-item>
            <el-form-item label="显示角标" prop="badge.show">
              <el-switch v-model="element.badge.show" />
            </el-form-item>
            <template v-if="element.badge.show">
              <el-form-item label="角标内容" prop="badge.text">
                <InputWithColor
                  v-model="element.badge.text"
                  v-model:color="element.badge.textColor"
                />
              </el-form-item>
              <el-form-item label="背景颜色" prop="badge.bgColor">
                <ColorInput v-model="element.badge.bgColor" />
              </el-form-item>
            </template>
          </template>
        </Draggable>
      </el-card>
    </el-form>
  </ComponentContainerProperty>
</template>
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import {
  EMPTY_MENU_GRID_ITEM_PROPERTY,
  MenuGridProperty
} from '@/components/DiyEditor/components/mobile/MenuGrid/config'
/** å®«æ ¼å¯¼èˆªå±žæ€§é¢æ¿ */
defineOptions({ name: 'MenuGridProperty' })
const props = defineProps<{ modelValue: MenuGridProperty }>()
const emit = defineEmits(['update:modelValue'])
const formData = useVModel(props, 'modelValue', emit)
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/MenuList/config.ts
New file
@@ -0,0 +1,48 @@
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
import { cloneDeep } from 'lodash-es'
/** åˆ—表导航属性 */
export interface MenuListProperty {
  // å¯¼èˆªèœå•列表
  list: MenuListItemProperty[]
  // ç»„件样式
  style: ComponentStyle
}
/** åˆ—表导航项目属性 */
export interface MenuListItemProperty {
  // å›¾æ ‡é“¾æŽ¥
  iconUrl: string
  // æ ‡é¢˜
  title: string
  // æ ‡é¢˜é¢œè‰²
  titleColor: string
  // å‰¯æ ‡é¢˜
  subtitle: string
  // å‰¯æ ‡é¢˜é¢œè‰²
  subtitleColor: string
  // é“¾æŽ¥
  url: string
}
export const EMPTY_MENU_LIST_ITEM_PROPERTY = {
  title: '标题',
  titleColor: '#333',
  subtitle: '副标题',
  subtitleColor: '#bbb'
}
// å®šä¹‰ç»„ä»¶
export const component = {
  id: 'MenuList',
  name: '列表导航',
  icon: 'fa-solid:list',
  property: {
    list: [cloneDeep(EMPTY_MENU_LIST_ITEM_PROPERTY)],
    style: {
      bgType: 'color',
      bgColor: '#fff',
      marginBottom: 8
    } as ComponentStyle
  }
} as DiyComponent<MenuListProperty>
src/components/DiyEditor/components/mobile/MenuList/index.vue
New file
@@ -0,0 +1,31 @@
<template>
  <div class="min-h-42px flex flex-col">
    <div
      v-for="(item, index) in property.list"
      :key="index"
      class="item h-42px flex flex-row items-center justify-between gap-4px p-x-12px"
    >
      <div class="flex flex-1 flex-row items-center gap-8px">
        <el-image v-if="item.iconUrl" class="h-16px w-16px" :src="item.iconUrl" />
        <span class="text-16px" :style="{ color: item.titleColor }">{{ item.title }}</span>
      </div>
      <div class="item-center flex flex-row justify-center gap-4px">
        <span class="text-12px" :style="{ color: item.subtitleColor }">{{ item.subtitle }}</span>
        <Icon icon="ep-arrow-right" color="#000" :size="16" />
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { MenuListProperty } from './config'
/** åˆ—表导航 */
defineOptions({ name: 'MenuList' })
defineProps<{ property: MenuListProperty }>()
</script>
<style scoped lang="scss">
.item + .item {
  border-top: 1px solid #eee;
}
</style>
src/components/DiyEditor/components/mobile/MenuList/property.vue
New file
@@ -0,0 +1,45 @@
<template>
  <ComponentContainerProperty v-model="formData.style">
    <el-text tag="p"> èœå•设置 </el-text>
    <el-text type="info" size="small"> æ‹–动左侧的小圆点可以调整顺序 </el-text>
    <!-- è¡¨å• -->
    <el-form label-width="60px" :model="formData" class="m-t-8px">
      <Draggable v-model="formData.list" :empty-item="EMPTY_MENU_LIST_ITEM_PROPERTY">
        <template #default="{ element }">
          <el-form-item label="图标" prop="iconUrl">
            <UploadImg v-model="element.iconUrl" height="80px" width="80px">
              <template #tip> å»ºè®®å°ºå¯¸ï¼š44 * 44 </template>
            </UploadImg>
          </el-form-item>
          <el-form-item label="标题" prop="title">
            <InputWithColor v-model="element.title" v-model:color="element.titleColor" />
          </el-form-item>
          <el-form-item label="副标题" prop="subtitle">
            <InputWithColor v-model="element.subtitle" v-model:color="element.subtitleColor" />
          </el-form-item>
          <el-form-item label="链接" prop="url">
            <AppLinkInput v-model="element.url" />
          </el-form-item>
        </template>
      </Draggable>
    </el-form>
  </ComponentContainerProperty>
</template>
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import {
  EMPTY_MENU_LIST_ITEM_PROPERTY,
  MenuListProperty
} from '@/components/DiyEditor/components/mobile/MenuList/config'
/** åˆ—表导航属性面板 */
defineOptions({ name: 'MenuListProperty' })
const props = defineProps<{ modelValue: MenuListProperty }>()
const emit = defineEmits(['update:modelValue'])
const formData = useVModel(props, 'modelValue', emit)
</script>
<style scoped lang="scss"></style>
src/components/DiyEditor/components/mobile/MenuSwiper/config.ts
New file
@@ -0,0 +1,66 @@
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
import { cloneDeep } from 'lodash-es'
/** èœå•导航属性 */
export interface MenuSwiperProperty {
  // å¸ƒå±€ï¼š å›¾æ ‡+文字 | å›¾æ ‡
  layout: 'iconText' | 'icon'
  // è¡Œæ•°
  row: number
  // åˆ—æ•°
  column: number
  // å¯¼èˆªèœå•列表
  list: MenuSwiperItemProperty[]
  // ç»„件样式
  style: ComponentStyle
}
/** èœå•导航项目属性 */
export interface MenuSwiperItemProperty {
  // å›¾æ ‡é“¾æŽ¥
  iconUrl: string
  // æ ‡é¢˜
  title: string
  // æ ‡é¢˜é¢œè‰²
  titleColor: string
  // é“¾æŽ¥
  url: string
  // è§’æ ‡
  badge: {
    // æ˜¯å¦æ˜¾ç¤º
    show: boolean
    // è§’标文字
    text: string
    // è§’标文字颜色
    textColor: string
    // è§’标背景颜色
    bgColor: string
  }
}
export const EMPTY_MENU_SWIPER_ITEM_PROPERTY = {
  title: '标题',
  titleColor: '#333',
  badge: {
    show: false,
    textColor: '#fff',
    bgColor: '#FF6000'
  }
} as MenuSwiperItemProperty
// å®šä¹‰ç»„ä»¶
export const component = {
  id: 'MenuSwiper',
  name: '菜单导航',
  icon: 'bi:grid-3x2-gap',
  property: {
    layout: 'iconText',
    row: 1,
    column: 3,
    list: [cloneDeep(EMPTY_MENU_SWIPER_ITEM_PROPERTY)],
    style: {
      bgType: 'color',
      bgColor: '#fff',
      marginBottom: 8
    } as ComponentStyle
  }
} as DiyComponent<MenuSwiperProperty>
Diff truncated after the above file
src/components/DiyEditor/components/mobile/MenuSwiper/index.vue src/components/DiyEditor/components/mobile/MenuSwiper/property.vue src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue src/components/DiyEditor/components/mobile/NavigationBar/config.ts src/components/DiyEditor/components/mobile/NavigationBar/index.vue src/components/DiyEditor/components/mobile/NavigationBar/property.vue src/components/DiyEditor/components/mobile/NoticeBar/config.ts src/components/DiyEditor/components/mobile/NoticeBar/index.vue src/components/DiyEditor/components/mobile/NoticeBar/property.vue src/components/DiyEditor/components/mobile/PageConfig/config.ts src/components/DiyEditor/components/mobile/PageConfig/property.vue src/components/DiyEditor/components/mobile/Popover/config.ts src/components/DiyEditor/components/mobile/Popover/index.vue src/components/DiyEditor/components/mobile/Popover/property.vue src/components/DiyEditor/components/mobile/ProductCard/config.ts src/components/DiyEditor/components/mobile/ProductCard/index.vue src/components/DiyEditor/components/mobile/ProductCard/property.vue src/components/DiyEditor/components/mobile/ProductList/config.ts src/components/DiyEditor/components/mobile/ProductList/index.vue src/components/DiyEditor/components/mobile/ProductList/property.vue src/components/DiyEditor/components/mobile/PromotionArticle/config.ts src/components/DiyEditor/components/mobile/PromotionArticle/index.vue src/components/DiyEditor/components/mobile/PromotionArticle/property.vue src/components/DiyEditor/components/mobile/PromotionCombination/config.ts src/components/DiyEditor/components/mobile/PromotionCombination/index.vue src/components/DiyEditor/components/mobile/PromotionCombination/property.vue src/components/DiyEditor/components/mobile/PromotionPoint/config.ts src/components/DiyEditor/components/mobile/PromotionPoint/index.vue src/components/DiyEditor/components/mobile/PromotionPoint/property.vue src/components/DiyEditor/components/mobile/PromotionSeckill/config.ts src/components/DiyEditor/components/mobile/PromotionSeckill/index.vue src/components/DiyEditor/components/mobile/PromotionSeckill/property.vue src/components/DiyEditor/components/mobile/SearchBar/config.ts src/components/DiyEditor/components/mobile/SearchBar/index.vue src/components/DiyEditor/components/mobile/SearchBar/property.vue src/components/DiyEditor/components/mobile/TabBar/config.ts src/components/DiyEditor/components/mobile/TabBar/index.vue src/components/DiyEditor/components/mobile/TabBar/property.vue src/components/DiyEditor/components/mobile/TitleBar/config.ts src/components/DiyEditor/components/mobile/TitleBar/index.vue src/components/DiyEditor/components/mobile/TitleBar/property.vue src/components/DiyEditor/components/mobile/UserCard/config.ts src/components/DiyEditor/components/mobile/UserCard/index.vue src/components/DiyEditor/components/mobile/UserCard/property.vue src/components/DiyEditor/components/mobile/UserCoupon/config.ts src/components/DiyEditor/components/mobile/UserCoupon/index.vue src/components/DiyEditor/components/mobile/UserCoupon/property.vue src/components/DiyEditor/components/mobile/UserOrder/config.ts src/components/DiyEditor/components/mobile/UserOrder/index.vue src/components/DiyEditor/components/mobile/UserOrder/property.vue src/components/DiyEditor/components/mobile/UserWallet/config.ts src/components/DiyEditor/components/mobile/UserWallet/index.vue src/components/DiyEditor/components/mobile/UserWallet/property.vue src/components/DiyEditor/components/mobile/VideoPlayer/config.ts src/components/DiyEditor/components/mobile/VideoPlayer/index.vue src/components/DiyEditor/components/mobile/VideoPlayer/property.vue src/components/DiyEditor/components/mobile/index.ts src/components/DiyEditor/index.vue src/components/DiyEditor/util.ts src/components/DocAlert/index.vue src/components/Draggable/index.vue src/components/Echart/index.ts src/components/Echart/src/Echart.vue src/components/Editor/index.ts src/components/Editor/src/Editor.vue src/components/Error/index.ts src/components/Error/src/Error.vue src/components/Form/index.ts src/components/Form/src/Form.vue src/components/Form/src/componentMap.ts src/components/Form/src/components/useRenderCheckbox.tsx src/components/Form/src/components/useRenderRadio.tsx src/components/Form/src/components/useRenderSelect.tsx src/components/Form/src/helper.ts src/components/Form/src/types.ts src/components/FormCreate/index.ts src/components/FormCreate/src/components/DictSelect.vue src/components/FormCreate/src/components/useApiSelect.tsx src/components/FormCreate/src/config/index.ts src/components/FormCreate/src/config/selectRule.ts src/components/FormCreate/src/config/useDictSelectRule.ts src/components/FormCreate/src/config/useEditorRule.ts src/components/FormCreate/src/config/useSelectRule.ts src/components/FormCreate/src/config/useUploadFileRule.ts src/components/FormCreate/src/config/useUploadImgRule.ts src/components/FormCreate/src/config/useUploadImgsRule.ts src/components/FormCreate/src/type/index.ts src/components/FormCreate/src/useFormCreateDesigner.ts src/components/FormCreate/src/utils/index.ts src/components/Highlight/index.ts src/components/Highlight/src/Highlight.vue src/components/IFrame/index.ts src/components/IFrame/src/IFrame.vue src/components/Icon/index.ts src/components/Icon/src/Icon.vue src/components/Icon/src/IconSelect.vue src/components/Icon/src/data.ts src/components/ImageViewer/index.ts src/components/ImageViewer/src/ImageViewer.vue src/components/ImageViewer/src/types.ts src/components/Infotip/index.ts src/components/Infotip/src/Infotip.vue src/components/InputPassword/index.ts src/components/InputPassword/src/InputPassword.vue src/components/InputWithColor/index.vue src/components/JsonEditor/index.ts src/components/JsonEditor/src/JsonEditor.vue src/components/JsonEditor/types/index.ts src/components/MagicCubeEditor/index.vue src/components/MagicCubeEditor/util.ts src/components/Map/index.vue src/components/MarkdownView/index.vue src/components/OperateLogV2/index.ts src/components/OperateLogV2/src/OperateLogV2.vue src/components/Pagination/index.vue src/components/Qrcode/index.ts src/components/Qrcode/src/Qrcode.vue src/components/RouterSearch/index.vue src/components/Search/index.ts src/components/Search/src/Search.vue src/components/ShortcutDateRangePicker/index.vue src/components/SimpleProcessDesignerV2/src/NodeHandler.vue src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue src/components/SimpleProcessDesignerV2/src/SimpleProcessViewer.vue src/components/SimpleProcessDesignerV2/src/consts.ts src/components/SimpleProcessDesignerV2/src/index.ts src/components/SimpleProcessDesignerV2/src/node.ts src/components/SimpleProcessDesignerV2/src/nodes-config/ChildProcessNodeConfig.vue src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue src/components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue src/components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue src/components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue src/components/SimpleProcessDesignerV2/src/nodes-config/TriggerNodeConfig.vue src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue src/components/SimpleProcessDesignerV2/src/nodes-config/components/ConditionDialog.vue src/components/SimpleProcessDesignerV2/src/nodes-config/components/HttpRequestParamSetting.vue src/components/SimpleProcessDesignerV2/src/nodes-config/components/HttpRequestSetting.vue src/components/SimpleProcessDesignerV2/src/nodes-config/components/UserTaskListener.vue src/components/SimpleProcessDesignerV2/src/nodes/ChildProcessNode.vue src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue src/components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue src/components/SimpleProcessDesignerV2/src/nodes/ParallelNode.vue src/components/SimpleProcessDesignerV2/src/nodes/RouterNode.vue src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue src/components/SimpleProcessDesignerV2/src/nodes/TriggerNode.vue src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue src/components/SimpleProcessDesignerV2/src/utils.ts src/components/SimpleProcessDesignerV2/theme/iconfont.ttf src/components/SimpleProcessDesignerV2/theme/iconfont.woff src/components/SimpleProcessDesignerV2/theme/iconfont.woff2 src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss src/components/Sticky/index.ts src/components/Sticky/src/Sticky.vue src/components/SummaryCard/index.vue src/components/Table/index.ts src/components/Table/src/Table.vue src/components/Table/src/TableSelectForm.vue src/components/Table/src/helper.ts src/components/Table/src/types.ts src/components/Tinyflow/Tinyflow.vue src/components/Tinyflow/ui/index.css src/components/Tinyflow/ui/index.d.ts src/components/Tinyflow/ui/index.js src/components/Tinyflow/ui/index.umd.js src/components/Tooltip/index.ts src/components/Tooltip/src/Tooltip.vue src/components/UploadFile/index.ts src/components/UploadFile/src/UploadFile.vue src/components/UploadFile/src/UploadImg.vue src/components/UploadFile/src/UploadImgs.vue src/components/UploadFile/src/useUpload.ts src/components/UserSelectForm/index.vue src/components/Verifition/index.ts src/components/Verifition/src/Verify.vue src/components/Verifition/src/Verify/VerifyPictureWord.vue src/components/Verifition/src/Verify/VerifyPoints.vue src/components/Verifition/src/Verify/VerifySlide.vue src/components/Verifition/src/Verify/index.ts src/components/Verifition/src/utils/ase.ts src/components/Verifition/src/utils/util.ts src/components/VerticalButtonGroup/index.vue src/components/XButton/index.ts src/components/XButton/src/XButton.vue src/components/XButton/src/XTextButton.vue src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue src/components/bpmnProcessDesigner/package/designer/index.ts src/components/bpmnProcessDesigner/package/designer/index2.ts src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/contentPadProvider.js src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/index.js src/components/bpmnProcessDesigner/package/designer/plugins/defaultEmpty.js src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/activitiDescriptor.json src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/camundaDescriptor.json src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/activitiExtension.js src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/index.js src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/extension.js src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/index.js src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/flowableExtension.js src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/index.js src/components/bpmnProcessDesigner/package/designer/plugins/palette/CustomPalette.js src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js src/components/bpmnProcessDesigner/package/designer/plugins/palette/paletteProvider.js src/components/bpmnProcessDesigner/package/designer/plugins/translate/customTranslate.js src/components/bpmnProcessDesigner/package/designer/plugins/translate/zh.js src/components/bpmnProcessDesigner/package/index.ts src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue src/components/bpmnProcessDesigner/package/penal/custom-config/components/BoundaryEventTimer.vue src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue src/components/bpmnProcessDesigner/package/penal/custom-config/data.ts src/components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue src/components/bpmnProcessDesigner/package/penal/form/ElementForm.vue src/components/bpmnProcessDesigner/package/penal/index.js src/components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue src/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue src/components/bpmnProcessDesigner/package/penal/listeners/template.js src/components/bpmnProcessDesigner/package/penal/listeners/utilSelf.ts src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue src/components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue src/components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue src/components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue src/components/bpmnProcessDesigner/package/penal/task/ElementTask.vue src/components/bpmnProcessDesigner/package/penal/task/data.ts src/components/bpmnProcessDesigner/package/penal/task/task-components/CallActivity.vue src/components/bpmnProcessDesigner/package/penal/task/task-components/HttpHeaderEditor.vue src/components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue src/components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue src/components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue src/components/bpmnProcessDesigner/package/penal/task/task-components/ServiceTask.vue src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue src/components/bpmnProcessDesigner/package/penal/time-event-config/CycleConfig.vue src/components/bpmnProcessDesigner/package/penal/time-event-config/DurationConfig.vue src/components/bpmnProcessDesigner/package/penal/time-event-config/TimeEventConfig.vue src/components/bpmnProcessDesigner/package/theme/element-variables.scss src/components/bpmnProcessDesigner/package/theme/index.scss src/components/bpmnProcessDesigner/package/theme/process-designer.scss src/components/bpmnProcessDesigner/package/theme/process-panel.scss src/components/bpmnProcessDesigner/package/utils.ts src/components/bpmnProcessDesigner/src/highlight/index.js src/components/bpmnProcessDesigner/src/modules/custom-renderer/CustomRenderer.js src/components/bpmnProcessDesigner/src/modules/custom-renderer/index.js src/components/bpmnProcessDesigner/src/modules/rules/CustomRules.js src/components/bpmnProcessDesigner/src/modules/rules/index.js src/components/bpmnProcessDesigner/src/translations.ts src/components/bpmnProcessDesigner/src/utils/directive/clickOutSide.js src/components/bpmnProcessDesigner/src/utils/index.js src/components/bpmnProcessDesigner/src/utils/xml2json.js src/components/index.ts src/config/axios/config.ts src/config/axios/errorCode.ts src/config/axios/index.ts src/config/axios/service.ts src/directives/index.ts src/directives/permission/hasPermi.ts src/directives/permission/hasRole.ts src/hooks/event/useScrollTo.ts src/hooks/web/useCache.ts src/hooks/web/useConfigGlobal.ts src/hooks/web/useCrudSchemas.ts src/hooks/web/useDesign.ts src/hooks/web/useEmitt.ts src/hooks/web/useForm.ts src/hooks/web/useGuide.ts src/hooks/web/useI18n.ts src/hooks/web/useIcon.ts src/hooks/web/useLocale.ts src/hooks/web/useMessage.ts src/hooks/web/useNProgress.ts src/hooks/web/useNetwork.ts src/hooks/web/useNow.ts src/hooks/web/usePageLoading.ts src/hooks/web/useTable.ts src/hooks/web/useTagsView.ts src/hooks/web/useTimeAgo.ts src/hooks/web/useTitle.ts src/hooks/web/useValidator.ts src/hooks/web/useWatermark.ts src/layout/Layout.vue src/layout/components/AppView.vue src/layout/components/Breadcrumb/index.ts src/layout/components/Breadcrumb/src/Breadcrumb.vue src/layout/components/Breadcrumb/src/helper.ts src/layout/components/Collapse/index.ts src/layout/components/Collapse/src/Collapse.vue src/layout/components/ContextMenu/index.ts src/layout/components/ContextMenu/src/ContextMenu.vue src/layout/components/Footer/index.ts src/layout/components/Footer/src/Footer.vue src/layout/components/LocaleDropdown/index.ts src/layout/components/LocaleDropdown/src/LocaleDropdown.vue src/layout/components/Logo/index.ts src/layout/components/Logo/src/Logo.vue src/layout/components/Menu/index.ts src/layout/components/Menu/src/Menu.vue src/layout/components/Menu/src/components/useRenderMenuItem.tsx src/layout/components/Menu/src/components/useRenderMenuTitle.tsx src/layout/components/Menu/src/helper.ts src/layout/components/Message/index.ts src/layout/components/Message/src/Message.vue src/layout/components/Screenfull/index.ts src/layout/components/Screenfull/src/Screenfull.vue src/layout/components/Setting/index.ts src/layout/components/Setting/src/Setting.vue src/layout/components/Setting/src/components/ColorRadioPicker.vue src/layout/components/Setting/src/components/InterfaceDisplay.vue src/layout/components/Setting/src/components/LayoutRadioPicker.vue src/layout/components/SizeDropdown/index.ts src/layout/components/SizeDropdown/src/SizeDropdown.vue src/layout/components/TabMenu/index.ts src/layout/components/TabMenu/src/TabMenu.vue src/layout/components/TabMenu/src/helper.ts src/layout/components/TagsView/index.ts src/layout/components/TagsView/src/TagsView.vue src/layout/components/TagsView/src/helper.ts src/layout/components/TenantVisit/index.vue src/layout/components/ThemeSwitch/index.ts src/layout/components/ThemeSwitch/src/ThemeSwitch.vue src/layout/components/ToolHeader.vue src/layout/components/UserInfo/index.ts src/layout/components/UserInfo/src/UserInfo.vue src/layout/components/UserInfo/src/components/LockDialog.vue src/layout/components/UserInfo/src/components/LockPage.vue src/layout/components/useRenderLayout.tsx src/locales/en.ts src/locales/zh-CN.ts src/main.ts src/permission.ts src/plugins/animate.css/index.ts src/plugins/echarts/index.ts src/plugins/elementPlus/index.ts src/plugins/formCreate/index.ts src/plugins/svgIcon/index.ts src/plugins/tongji/index.ts src/plugins/unocss/index.ts src/plugins/vueI18n/helper.ts src/plugins/vueI18n/index.ts src/router/index.ts src/router/modules/remaining.ts src/store/index.ts src/store/modules/app.ts src/store/modules/bpm/simpleWorkflow.ts src/store/modules/dict.ts src/store/modules/locale.ts src/store/modules/lock.ts src/store/modules/mall/kefu.ts src/store/modules/permission.ts src/store/modules/tagsView.ts src/store/modules/user.ts src/styles/FormCreate/fonts/fontello.woff src/styles/FormCreate/index.scss src/styles/global.module.scss src/styles/index.scss src/styles/theme.scss src/styles/var.css src/styles/variables.scss src/types/components.d.ts src/types/configGlobal.d.ts src/types/contextMenu.d.ts src/types/descriptions.d.ts src/types/elementPlus.d.ts src/types/form.d.ts src/types/icon.d.ts src/types/infoTip.d.ts src/types/layout.d.ts src/types/localeDropdown.d.ts src/types/qrcode.d.ts src/types/table.d.ts src/types/theme.d.ts src/utils/Logger.ts src/utils/auth.ts src/utils/color.ts src/utils/constants.ts src/utils/cron.ts src/utils/dateUtil.ts src/utils/dict.ts src/utils/domUtils.ts src/utils/download.ts src/utils/encrypt.ts src/utils/file.ts src/utils/filt.ts src/utils/formCreate.ts src/utils/formRules.ts src/utils/formatTime.ts src/utils/formatter.ts src/utils/index.ts src/utils/is.ts src/utils/jsencrypt.ts src/utils/permission.ts src/utils/propTypes.ts src/utils/routerHelper.ts src/utils/tree.ts src/utils/tsxHelper.ts src/views/Error/403.vue src/views/Error/404.vue src/views/Error/500.vue src/views/Home/Index.vue src/views/Home/Index2.vue src/views/Home/echarts-data.ts src/views/Home/types.ts src/views/Login/Login.vue src/views/Login/SocialLogin.vue src/views/Login/components/ForgetPasswordForm.vue src/views/Login/components/LoginForm.vue src/views/Login/components/LoginFormTitle.vue src/views/Login/components/MobileForm.vue src/views/Login/components/QrCodeForm.vue src/views/Login/components/RegisterForm.vue src/views/Login/components/SSOLogin.vue src/views/Login/components/index.ts src/views/Login/components/useLogin.ts src/views/Profile/Index.vue src/views/Profile/components/BasicInfo.vue src/views/Profile/components/ProfileUser.vue src/views/Profile/components/ResetPwd.vue src/views/Profile/components/UserAvatar.vue src/views/Profile/components/UserSocial.vue src/views/Profile/components/index.ts src/views/Redirect/Redirect.vue src/views/ai/chat/index/components/conversation/ConversationList.vue src/views/ai/chat/index/components/conversation/ConversationUpdateForm.vue src/views/ai/chat/index/components/message/MessageFileUpload.vue src/views/ai/chat/index/components/message/MessageFiles.vue src/views/ai/chat/index/components/message/MessageKnowledge.vue src/views/ai/chat/index/components/message/MessageList.vue src/views/ai/chat/index/components/message/MessageListEmpty.vue src/views/ai/chat/index/components/message/MessageLoading.vue src/views/ai/chat/index/components/message/MessageNewConversation.vue src/views/ai/chat/index/components/message/MessageReasoning.vue src/views/ai/chat/index/components/message/MessageWebSearch.vue src/views/ai/chat/index/components/role/RoleCategoryList.vue src/views/ai/chat/index/components/role/RoleList.vue src/views/ai/chat/index/components/role/RoleRepository.vue src/views/ai/chat/index/index.vue src/views/ai/chat/manager/ChatConversationList.vue src/views/ai/chat/manager/ChatMessageList.vue src/views/ai/chat/manager/index.vue src/views/ai/image/index/components/ImageCard.vue src/views/ai/image/index/components/ImageDetail.vue src/views/ai/image/index/components/ImageList.vue src/views/ai/image/index/components/common/index.vue src/views/ai/image/index/components/dall3/index.vue src/views/ai/image/index/components/midjourney/index.vue src/views/ai/image/index/components/stableDiffusion/index.vue src/views/ai/image/index/index.vue src/views/ai/image/manager/index.vue src/views/ai/image/square/index.vue src/views/ai/knowledge/document/form/ProcessStep.vue src/views/ai/knowledge/document/form/SplitStep.vue src/views/ai/knowledge/document/form/UploadStep.vue src/views/ai/knowledge/document/form/index.vue src/views/ai/knowledge/document/index.vue src/views/ai/knowledge/knowledge/KnowledgeForm.vue src/views/ai/knowledge/knowledge/index.vue src/views/ai/knowledge/knowledge/retrieval/index.vue src/views/ai/knowledge/segment/KnowledgeSegmentForm.vue src/views/ai/knowledge/segment/index.vue src/views/ai/mindmap/index/components/Left.vue src/views/ai/mindmap/index/components/Right.vue src/views/ai/mindmap/index/index.vue src/views/ai/mindmap/manager/index.vue src/views/ai/model/apiKey/ApiKeyForm.vue src/views/ai/model/apiKey/index.vue src/views/ai/model/chatRole/ChatRoleForm.vue src/views/ai/model/chatRole/index.vue src/views/ai/model/model/ModelForm.vue src/views/ai/model/model/index.vue src/views/ai/model/tool/ToolForm.vue src/views/ai/model/tool/index.vue src/views/ai/music/index/index.vue src/views/ai/music/index/list/audioBar/index.vue src/views/ai/music/index/list/index.vue src/views/ai/music/index/list/songCard/index.vue src/views/ai/music/index/list/songInfo/index.vue src/views/ai/music/index/mode/desc.vue src/views/ai/music/index/mode/index.vue src/views/ai/music/index/mode/lyric.vue src/views/ai/music/index/title/index.vue src/views/ai/music/manager/index.vue src/views/ai/utils/constants.ts src/views/ai/utils/utils.ts src/views/ai/workflow/form/BasicInfo.vue src/views/ai/workflow/form/WorkflowDesign.vue src/views/ai/workflow/form/index.vue src/views/ai/workflow/index.vue src/views/ai/write/index/components/Left.vue src/views/ai/write/index/components/Right.vue src/views/ai/write/index/components/Tag.vue src/views/ai/write/index/index.vue src/views/ai/write/manager/index.vue src/views/bpm/category/CategoryForm.vue src/views/bpm/category/index.vue src/views/bpm/form/editor/index.vue src/views/bpm/form/index.vue src/views/bpm/group/UserGroupForm.vue src/views/bpm/group/index.vue src/views/bpm/model/CategoryDraggableModel.vue src/views/bpm/model/definition/index.vue src/views/bpm/model/form/BasicInfo.vue src/views/bpm/model/form/ExtraSettings.vue src/views/bpm/model/form/FormDesign.vue src/views/bpm/model/form/PrintTemplate/Index.vue src/views/bpm/model/form/PrintTemplate/MentionModal.vue src/views/bpm/model/form/PrintTemplate/index.ts src/views/bpm/model/form/PrintTemplate/module/elem-to-html.ts src/views/bpm/model/form/PrintTemplate/module/index.ts src/views/bpm/model/form/PrintTemplate/module/menu/ProcessRecordMenu.ts src/views/bpm/model/form/PrintTemplate/module/parse-elem-html.ts src/views/bpm/model/form/PrintTemplate/module/plugin.ts src/views/bpm/model/form/PrintTemplate/module/render-elem.ts src/views/bpm/model/form/PrintTemplate/module/utils/dom.ts src/views/bpm/model/form/ProcessDesign.vue src/views/bpm/model/form/editor/index.vue src/views/bpm/model/form/index.vue src/views/bpm/model/index.vue src/views/bpm/oa/leave/create.vue src/views/bpm/oa/leave/detail.vue src/views/bpm/oa/leave/index.vue src/views/bpm/processExpression/ProcessExpressionForm.vue src/views/bpm/processExpression/index.vue src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue src/views/bpm/processInstance/create/index.vue src/views/bpm/processInstance/detail/PrintDialog.vue src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue src/views/bpm/processInstance/detail/SignDialog.vue src/views/bpm/processInstance/detail/index.vue src/views/bpm/processInstance/index.vue src/views/bpm/processInstance/manager/index.vue src/views/bpm/processInstance/report/index.vue src/views/bpm/processListener/ProcessListenerForm.vue src/views/bpm/processListener/index.vue src/views/bpm/simple/SimpleModelDesign.vue src/views/bpm/task/copy/index.vue src/views/bpm/task/done/index.vue src/views/bpm/task/manager/index.vue src/views/bpm/task/todo/index.vue src/views/crm/backlog/components/ClueFollowList.vue src/views/crm/backlog/components/ContractAuditList.vue src/views/crm/backlog/components/ContractRemindList.vue src/views/crm/backlog/components/CustomerFollowList.vue src/views/crm/backlog/components/CustomerPutPoolRemindList.vue src/views/crm/backlog/components/CustomerTodayContactList.vue src/views/crm/backlog/components/ReceivableAuditList.vue src/views/crm/backlog/components/ReceivablePlanRemindList.vue src/views/crm/backlog/components/common.ts src/views/crm/backlog/index.vue src/views/crm/business/BusinessForm.vue src/views/crm/business/BusinessUpdateStatusForm.vue src/views/crm/business/components/BusinessList.vue src/views/crm/business/components/BusinessListModal.vue src/views/crm/business/components/BusinessProductForm.vue src/views/crm/business/detail/BusinessDetailsHeader.vue src/views/crm/business/detail/BusinessDetailsInfo.vue src/views/crm/business/detail/BusinessProductList.vue src/views/crm/business/detail/index.vue src/views/crm/business/index.vue src/views/crm/business/status/BusinessStatusForm.vue src/views/crm/business/status/index.vue src/views/crm/clue/ClueForm.vue src/views/crm/clue/detail/ClueDetailsHeader.vue src/views/crm/clue/detail/ClueDetailsInfo.vue src/views/crm/clue/detail/index.vue src/views/crm/clue/index.vue src/views/crm/contact/ContactForm.vue src/views/crm/contact/components/ContactList.vue src/views/crm/contact/components/ContactListModal.vue src/views/crm/contact/detail/ContactDetailsHeader.vue src/views/crm/contact/detail/ContactDetailsInfo.vue src/views/crm/contact/detail/index.vue src/views/crm/contact/index.vue src/views/crm/contract/ContractForm.vue src/views/crm/contract/components/ContractList.vue src/views/crm/contract/components/ContractProductForm.vue src/views/crm/contract/config/index.vue src/views/crm/contract/detail/ContractDetailsHeader.vue src/views/crm/contract/detail/ContractDetailsInfo.vue src/views/crm/contract/detail/ContractProductList.vue src/views/crm/contract/detail/index.vue src/views/crm/contract/index.vue src/views/crm/customer/CustomerForm.vue src/views/crm/customer/CustomerImportForm.vue src/views/crm/customer/detail/CustomerDetailsHeader.vue src/views/crm/customer/detail/CustomerDetailsInfo.vue src/views/crm/customer/detail/index.vue src/views/crm/customer/index.vue src/views/crm/customer/limitConfig/CustomerLimitConfigForm.vue src/views/crm/customer/limitConfig/CustomerLimitConfigList.vue src/views/crm/customer/limitConfig/index.vue src/views/crm/customer/pool/CustomerDistributeForm.vue src/views/crm/customer/pool/index.vue src/views/crm/customer/poolConfig/index.vue src/views/crm/followup/FollowUpRecordForm.vue src/views/crm/followup/components/FollowUpRecordBusinessForm.vue src/views/crm/followup/components/FollowUpRecordContactForm.vue src/views/crm/followup/index.vue src/views/crm/permission/components/PermissionForm.vue src/views/crm/permission/components/PermissionList.vue src/views/crm/permission/components/TransferForm.vue src/views/crm/product/ProductForm.vue src/views/crm/product/category/ProductCategoryForm.vue src/views/crm/product/category/index.vue src/views/crm/product/detail/ProductDetailsHeader.vue src/views/crm/product/detail/ProductDetailsInfo.vue src/views/crm/product/detail/index.vue src/views/crm/product/index.vue src/views/crm/receivable/ReceivableForm.vue src/views/crm/receivable/components/ReceivableList.vue src/views/crm/receivable/detail/ReceivableDetailsHeader.vue src/views/crm/receivable/detail/ReceivableDetailsInfo.vue src/views/crm/receivable/detail/index.vue src/views/crm/receivable/index.vue src/views/crm/receivable/plan/ReceivablePlanForm.vue src/views/crm/receivable/plan/components/ReceivablePlanList.vue src/views/crm/receivable/plan/detail/ReceivablePlanDetailsHeader.vue src/views/crm/receivable/plan/detail/ReceivablePlanDetailsInfo.vue src/views/crm/receivable/plan/detail/index.vue src/views/crm/receivable/plan/index.vue src/views/crm/statistics/customer/components/CustomerConversionStat.vue src/views/crm/statistics/customer/components/CustomerDealCycleByArea.vue src/views/crm/statistics/customer/components/CustomerDealCycleByProduct.vue src/views/crm/statistics/customer/components/CustomerDealCycleByUser.vue src/views/crm/statistics/customer/components/CustomerFollowUpSummary.vue src/views/crm/statistics/customer/components/CustomerFollowUpType.vue src/views/crm/statistics/customer/components/CustomerPoolSummary.vue src/views/crm/statistics/customer/components/CustomerSummary.vue src/views/crm/statistics/customer/index.vue src/views/crm/statistics/funnel/components/BusinessInversionRateSummary.vue src/views/crm/statistics/funnel/components/BusinessSummary.vue src/views/crm/statistics/funnel/components/FunnelBusiness.vue src/views/crm/statistics/funnel/index.vue src/views/crm/statistics/performance/components/ContractCountPerformance.vue src/views/crm/statistics/performance/components/ContractPricePerformance.vue src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue src/views/crm/statistics/performance/index.vue src/views/crm/statistics/portrait/components/PortraitCustomerArea.vue src/views/crm/statistics/portrait/components/PortraitCustomerIndustry.vue src/views/crm/statistics/portrait/components/PortraitCustomerLevel.vue src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue src/views/crm/statistics/portrait/index.vue src/views/crm/statistics/rank/components/ContactCountRank.vue src/views/crm/statistics/rank/components/ContractCountRank.vue src/views/crm/statistics/rank/components/ContractPriceRank.vue src/views/crm/statistics/rank/components/CustomerCountRank.vue src/views/crm/statistics/rank/components/FollowCountRank.vue src/views/crm/statistics/rank/components/FollowCustomerCountRank.vue src/views/crm/statistics/rank/components/ProductSalesRank.vue src/views/crm/statistics/rank/components/ReceivablePriceRank.vue src/views/crm/statistics/rank/index.vue src/views/erp/finance/account/AccountForm.vue src/views/erp/finance/account/index.vue src/views/erp/finance/payment/FinancePaymentForm.vue src/views/erp/finance/payment/components/FinancePaymentItemForm.vue src/views/erp/finance/payment/index.vue src/views/erp/finance/receipt/FinanceReceiptForm.vue src/views/erp/finance/receipt/components/FinanceReceiptItemForm.vue src/views/erp/finance/receipt/index.vue src/views/erp/home/components/SummaryCard.vue src/views/erp/home/components/TimeSummaryChart.vue src/views/erp/home/index.vue src/views/erp/product/category/ProductCategoryForm.vue src/views/erp/product/category/index.vue src/views/erp/product/product/ProductForm.vue src/views/erp/product/product/index.vue src/views/erp/product/unit/ProductUnitForm.vue src/views/erp/product/unit/index.vue src/views/erp/purchase/in/PurchaseInForm.vue src/views/erp/purchase/in/components/PurchaseInItemForm.vue src/views/erp/purchase/in/components/PurchaseInPaymentEnableList.vue src/views/erp/purchase/in/index.vue src/views/erp/purchase/order/PurchaseOrderForm.vue src/views/erp/purchase/order/components/PurchaseOrderInEnableList.vue src/views/erp/purchase/order/components/PurchaseOrderItemForm.vue src/views/erp/purchase/order/components/PurchaseOrderReturnEnableList.vue src/views/erp/purchase/order/index.vue src/views/erp/purchase/return/PurchaseReturnForm.vue src/views/erp/purchase/return/components/PurchaseReturnItemForm.vue src/views/erp/purchase/return/components/PurchaseReturnRefundEnableList.vue src/views/erp/purchase/return/index.vue src/views/erp/purchase/supplier/SupplierForm.vue src/views/erp/purchase/supplier/index.vue src/views/erp/sale/customer/CustomerForm.vue src/views/erp/sale/customer/index.vue src/views/erp/sale/order/SaleOrderForm.vue src/views/erp/sale/order/components/SaleOrderItemForm.vue src/views/erp/sale/order/components/SaleOrderOutEnableList.vue src/views/erp/sale/order/components/SaleOrderReturnEnableList.vue src/views/erp/sale/order/index.vue src/views/erp/sale/out/SaleOutForm.vue src/views/erp/sale/out/components/SaleOutItemForm.vue src/views/erp/sale/out/components/SaleOutReceiptEnableList.vue src/views/erp/sale/out/index.vue src/views/erp/sale/return/SaleReturnForm.vue src/views/erp/sale/return/components/SaleReturnItemForm.vue src/views/erp/sale/return/components/SaleReturnRefundEnableList.vue src/views/erp/sale/return/index.vue src/views/erp/stock/check/StockCheckForm.vue src/views/erp/stock/check/components/StockCheckItemForm.vue src/views/erp/stock/check/index.vue src/views/erp/stock/in/StockInForm.vue src/views/erp/stock/in/components/StockInItemForm.vue src/views/erp/stock/in/index.vue src/views/erp/stock/move/StockMoveForm.vue src/views/erp/stock/move/components/StockMoveItemForm.vue src/views/erp/stock/move/index.vue src/views/erp/stock/out/StockOutForm.vue src/views/erp/stock/out/components/StockOutItemForm.vue src/views/erp/stock/out/index.vue src/views/erp/stock/record/index.vue src/views/erp/stock/stock/index.vue src/views/erp/stock/warehouse/WarehouseForm.vue src/views/erp/stock/warehouse/index.vue src/views/infra/apiAccessLog/ApiAccessLogDetail.vue src/views/infra/apiAccessLog/index.vue src/views/infra/apiErrorLog/ApiErrorLogDetail.vue src/views/infra/apiErrorLog/index.vue src/views/infra/build/index.vue src/views/infra/codegen/EditTable.vue src/views/infra/codegen/ImportTable.vue src/views/infra/codegen/PreviewCode.vue src/views/infra/codegen/components/BasicInfoForm.vue src/views/infra/codegen/components/ColumInfoForm.vue src/views/infra/codegen/components/GenerateInfoForm.vue src/views/infra/codegen/components/index.ts src/views/infra/codegen/index.vue src/views/infra/config/ConfigForm.vue src/views/infra/config/index.vue src/views/infra/dataSourceConfig/DataSourceConfigForm.vue src/views/infra/dataSourceConfig/index.vue src/views/infra/demo/demo01/Demo01ContactForm.vue src/views/infra/demo/demo01/index.vue src/views/infra/demo/demo02/Demo02CategoryForm.vue src/views/infra/demo/demo02/index.vue src/views/infra/demo/demo03/erp/Demo03StudentForm.vue src/views/infra/demo/demo03/erp/components/Demo03CourseForm.vue src/views/infra/demo/demo03/erp/components/Demo03CourseList.vue src/views/infra/demo/demo03/erp/components/Demo03GradeForm.vue src/views/infra/demo/demo03/erp/components/Demo03GradeList.vue src/views/infra/demo/demo03/erp/index.vue src/views/infra/demo/demo03/inner/Demo03StudentForm.vue src/views/infra/demo/demo03/inner/components/Demo03CourseForm.vue src/views/infra/demo/demo03/inner/components/Demo03CourseList.vue src/views/infra/demo/demo03/inner/components/Demo03GradeForm.vue src/views/infra/demo/demo03/inner/components/Demo03GradeList.vue src/views/infra/demo/demo03/inner/index.vue src/views/infra/demo/demo03/normal/Demo03StudentForm.vue src/views/infra/demo/demo03/normal/components/Demo03CourseForm.vue src/views/infra/demo/demo03/normal/components/Demo03GradeForm.vue src/views/infra/demo/demo03/normal/index.vue src/views/infra/druid/index.vue src/views/infra/file/FileForm.vue src/views/infra/file/index.vue src/views/infra/fileConfig/FileConfigForm.vue src/views/infra/fileConfig/index.vue src/views/infra/job/JobDetail.vue src/views/infra/job/JobForm.vue src/views/infra/job/index.vue src/views/infra/job/logger/JobLogDetail.vue src/views/infra/job/logger/index.vue src/views/infra/redis/index.vue src/views/infra/server/index.vue src/views/infra/skywalking/index.vue src/views/infra/swagger/index.vue src/views/infra/webSocket/index.vue src/views/iot/alert/config/AlertConfigForm.vue src/views/iot/alert/config/index.vue src/views/iot/alert/record/index.vue src/views/iot/device/device/DeviceForm.vue src/views/iot/device/device/DeviceGroupForm.vue src/views/iot/device/device/DeviceImportForm.vue src/views/iot/device/device/components/DeviceTableSelect.vue src/views/iot/device/device/detail/DeviceDetailConfig.vue src/views/iot/device/device/detail/DeviceDetailsHeader.vue src/views/iot/device/device/detail/DeviceDetailsInfo.vue src/views/iot/device/device/detail/DeviceDetailsMessage.vue src/views/iot/device/device/detail/DeviceDetailsSimulator.vue src/views/iot/device/device/detail/DeviceDetailsThingModel.vue src/views/iot/device/device/detail/DeviceDetailsThingModelEvent.vue src/views/iot/device/device/detail/DeviceDetailsThingModelProperty.vue src/views/iot/device/device/detail/DeviceDetailsThingModelPropertyHistory.vue src/views/iot/device/device/detail/DeviceDetailsThingModelService.vue src/views/iot/device/device/detail/index.vue src/views/iot/device/device/index.vue src/views/iot/device/group/DeviceGroupForm.vue src/views/iot/device/group/index.vue src/views/iot/home/components/ComparisonCard.vue src/views/iot/home/components/DeviceCountCard.vue src/views/iot/home/components/DeviceStateCountCard.vue src/views/iot/home/components/MessageTrendCard.vue src/views/iot/home/index.vue src/views/iot/ota/firmware/OtaFirmwareForm.vue src/views/iot/ota/firmware/detail/index.vue src/views/iot/ota/firmware/index.vue src/views/iot/ota/task/OtaTaskDetail.vue src/views/iot/ota/task/OtaTaskForm.vue src/views/iot/ota/task/OtaTaskList.vue src/views/iot/product/category/ProductCategoryForm.vue src/views/iot/product/category/index.vue src/views/iot/product/product/ProductForm.vue src/views/iot/product/product/components/ProductTableSelect.vue src/views/iot/product/product/detail/ProductDetailsHeader.vue src/views/iot/product/product/detail/ProductDetailsInfo.vue src/views/iot/product/product/detail/index.vue src/views/iot/product/product/index.vue src/views/iot/rule/data/index.vue src/views/iot/rule/data/rule/DataRuleForm.vue src/views/iot/rule/data/rule/components/SourceConfigForm.vue src/views/iot/rule/data/rule/index.vue src/views/iot/rule/data/sink/DataSinkForm.vue src/views/iot/rule/data/sink/config/HttpConfigForm.vue src/views/iot/rule/data/sink/config/KafkaMQConfigForm.vue src/views/iot/rule/data/sink/config/MqttConfigForm.vue src/views/iot/rule/data/sink/config/RabbitMQConfigForm.vue src/views/iot/rule/data/sink/config/RedisStreamConfigForm.vue src/views/iot/rule/data/sink/config/RocketMQConfigForm.vue src/views/iot/rule/data/sink/config/components/KeyValueEditor.vue src/views/iot/rule/data/sink/config/index.ts src/views/iot/rule/data/sink/index.vue src/views/iot/rule/scene/form/RuleSceneForm.vue src/views/iot/rule/scene/form/configs/AlertConfig.vue src/views/iot/rule/scene/form/configs/ConditionConfig.vue src/views/iot/rule/scene/form/configs/CurrentTimeConditionConfig.vue src/views/iot/rule/scene/form/configs/DeviceControlConfig.vue src/views/iot/rule/scene/form/configs/DeviceTriggerConfig.vue src/views/iot/rule/scene/form/configs/MainConditionInnerConfig.vue src/views/iot/rule/scene/form/configs/SubConditionGroupConfig.vue src/views/iot/rule/scene/form/inputs/JsonParamsInput.vue src/views/iot/rule/scene/form/inputs/ValueInput.vue src/views/iot/rule/scene/form/sections/ActionSection.vue src/views/iot/rule/scene/form/sections/BasicInfoSection.vue src/views/iot/rule/scene/form/sections/TriggerSection.vue src/views/iot/rule/scene/form/selectors/DeviceSelector.vue src/views/iot/rule/scene/form/selectors/OperatorSelector.vue src/views/iot/rule/scene/form/selectors/ProductSelector.vue src/views/iot/rule/scene/form/selectors/PropertySelector.vue src/views/iot/rule/scene/index.vue src/views/iot/thingmodel/ThingModelEvent.vue src/views/iot/thingmodel/ThingModelForm.vue src/views/iot/thingmodel/ThingModelInputOutputParam.vue src/views/iot/thingmodel/ThingModelProperty.vue src/views/iot/thingmodel/ThingModelService.vue src/views/iot/thingmodel/ThingModelTSL.vue src/views/iot/thingmodel/components/DataDefinition.vue src/views/iot/thingmodel/components/index.ts src/views/iot/thingmodel/dataSpecs/ThingModelArrayDataSpecs.vue src/views/iot/thingmodel/dataSpecs/ThingModelEnumDataSpecs.vue src/views/iot/thingmodel/dataSpecs/ThingModelNumberDataSpecs.vue src/views/iot/thingmodel/dataSpecs/ThingModelStructDataSpecs.vue src/views/iot/thingmodel/dataSpecs/index.ts src/views/iot/thingmodel/index.vue src/views/iot/utils/constants.ts src/views/mall/home/components/ComparisonCard.vue src/views/mall/home/components/MemberStatisticsCard.vue src/views/mall/home/components/OperationDataCard.vue src/views/mall/home/components/ShortcutCard.vue src/views/mall/home/components/TradeTrendCard.vue src/views/mall/home/index.vue src/views/mall/product/brand/BrandForm.vue src/views/mall/product/brand/index.vue src/views/mall/product/category/CategoryForm.vue src/views/mall/product/category/components/ProductCategorySelect.vue src/views/mall/product/category/index.vue src/views/mall/product/comment/CommentForm.vue src/views/mall/product/comment/ReplyForm.vue src/views/mall/product/comment/index.vue src/views/mall/product/property/PropertyForm.vue src/views/mall/product/property/index.vue src/views/mall/product/property/value/ValueForm.vue src/views/mall/product/property/value/index.vue src/views/mall/product/spu/components/SkuList.vue src/views/mall/product/spu/components/SkuTableSelect.vue src/views/mall/product/spu/components/SpuShowcase.vue src/views/mall/product/spu/components/SpuTableSelect.vue src/views/mall/product/spu/components/index.ts src/views/mall/product/spu/form/DeliveryForm.vue src/views/mall/product/spu/form/DescriptionForm.vue src/views/mall/product/spu/form/InfoForm.vue src/views/mall/product/spu/form/OtherForm.vue src/views/mall/product/spu/form/ProductAttributes.vue src/views/mall/product/spu/form/ProductPropertyAddForm.vue src/views/mall/product/spu/form/SkuForm.vue src/views/mall/product/spu/form/index.vue src/views/mall/product/spu/index.vue src/views/mall/promotion/article/ArticleForm.vue src/views/mall/promotion/article/category/ArticleCategoryForm.vue src/views/mall/promotion/article/category/index.vue src/views/mall/promotion/article/index.vue src/views/mall/promotion/banner/BannerForm.vue src/views/mall/promotion/banner/index.vue src/views/mall/promotion/bargain/activity/BargainActivityForm.vue src/views/mall/promotion/bargain/activity/bargainActivity.data.ts src/views/mall/promotion/bargain/activity/index.vue src/views/mall/promotion/bargain/record/BargainRecordListDialog.vue src/views/mall/promotion/bargain/record/index.vue src/views/mall/promotion/combination/activity/CombinationActivityForm.vue src/views/mall/promotion/combination/activity/combinationActivity.data.ts src/views/mall/promotion/combination/activity/index.vue src/views/mall/promotion/combination/components/CombinationShowcase.vue src/views/mall/promotion/combination/components/CombinationTableSelect.vue src/views/mall/promotion/combination/record/CombinationRecordListDialog.vue src/views/mall/promotion/combination/record/index.vue src/views/mall/promotion/components/SpuAndSkuList.vue src/views/mall/promotion/components/SpuSelect.vue src/views/mall/promotion/components/index.ts src/views/mall/promotion/coupon/components/CouponSelect.vue src/views/mall/promotion/coupon/components/CouponSendForm.vue src/views/mall/promotion/coupon/components/index.ts src/views/mall/promotion/coupon/formatter.ts src/views/mall/promotion/coupon/index.vue src/views/mall/promotion/coupon/template/CouponTemplateForm.vue src/views/mall/promotion/coupon/template/index.vue src/views/mall/promotion/discountActivity/DiscountActivityForm.vue src/views/mall/promotion/discountActivity/discountActivity.data.ts src/views/mall/promotion/discountActivity/index.vue src/views/mall/promotion/diy/page/DiyPageForm.vue src/views/mall/promotion/diy/page/decorate.vue src/views/mall/promotion/diy/page/index.vue src/views/mall/promotion/diy/template/DiyTemplateForm.vue src/views/mall/promotion/diy/template/decorate.vue src/views/mall/promotion/diy/template/index.vue src/views/mall/promotion/kefu/components/KeFuConversationList.vue src/views/mall/promotion/kefu/components/KeFuMessageList.vue src/views/mall/promotion/kefu/components/asserts/a.png src/views/mall/promotion/kefu/components/asserts/aini.png src/views/mall/promotion/kefu/components/asserts/aixin.png src/views/mall/promotion/kefu/components/asserts/baiyan.png src/views/mall/promotion/kefu/components/asserts/bizui.png src/views/mall/promotion/kefu/components/asserts/buhaoyisi.png src/views/mall/promotion/kefu/components/asserts/bukesiyi.png src/views/mall/promotion/kefu/components/asserts/dajing.png src/views/mall/promotion/kefu/components/asserts/danao.png src/views/mall/promotion/kefu/components/asserts/daxiao.png src/views/mall/promotion/kefu/components/asserts/dianzan.png src/views/mall/promotion/kefu/components/asserts/emo.png src/views/mall/promotion/kefu/components/asserts/esi.png src/views/mall/promotion/kefu/components/asserts/fadai.png src/views/mall/promotion/kefu/components/asserts/fankun.png src/views/mall/promotion/kefu/components/asserts/feiwen.png src/views/mall/promotion/kefu/components/asserts/fennu.png src/views/mall/promotion/kefu/components/asserts/ganga.png src/views/mall/promotion/kefu/components/asserts/ganmao.png src/views/mall/promotion/kefu/components/asserts/hanyan.png src/views/mall/promotion/kefu/components/asserts/haochi.png src/views/mall/promotion/kefu/components/asserts/hongxin.png src/views/mall/promotion/kefu/components/asserts/huaixiao.png src/views/mall/promotion/kefu/components/asserts/jingkong.png src/views/mall/promotion/kefu/components/asserts/jingshu.png src/views/mall/promotion/kefu/components/asserts/jingya.png src/views/mall/promotion/kefu/components/asserts/kaixin.png src/views/mall/promotion/kefu/components/asserts/keai.png src/views/mall/promotion/kefu/components/asserts/keshui.png src/views/mall/promotion/kefu/components/asserts/kun.png src/views/mall/promotion/kefu/components/asserts/lengku.png src/views/mall/promotion/kefu/components/asserts/liuhan.png src/views/mall/promotion/kefu/components/asserts/liukoushui.png src/views/mall/promotion/kefu/components/asserts/liulei.png src/views/mall/promotion/kefu/components/asserts/mengbi.png src/views/mall/promotion/kefu/components/asserts/mianwubiaoqing.png src/views/mall/promotion/kefu/components/asserts/nanguo.png src/views/mall/promotion/kefu/components/asserts/outu.png src/views/mall/promotion/kefu/components/asserts/picture.svg src/views/mall/promotion/kefu/components/asserts/shengqi.png src/views/mall/promotion/kefu/components/asserts/shuizhuo.png src/views/mall/promotion/kefu/components/asserts/tianshi.png src/views/mall/promotion/kefu/components/asserts/xiaodiaoya.png src/views/mall/promotion/kefu/components/asserts/xiaoku.png src/views/mall/promotion/kefu/components/asserts/xinsui.png src/views/mall/promotion/kefu/components/asserts/xiong.png src/views/mall/promotion/kefu/components/asserts/yiwen.png src/views/mall/promotion/kefu/components/asserts/yun.png src/views/mall/promotion/kefu/components/asserts/ziya.png src/views/mall/promotion/kefu/components/index.ts src/views/mall/promotion/kefu/components/member/MemberInfo.vue src/views/mall/promotion/kefu/components/member/OrderBrowsingHistory.vue src/views/mall/promotion/kefu/components/member/ProductBrowsingHistory.vue src/views/mall/promotion/kefu/components/message/MessageItem.vue src/views/mall/promotion/kefu/components/message/OrderItem.vue src/views/mall/promotion/kefu/components/message/ProductItem.vue src/views/mall/promotion/kefu/components/tools/EmojiSelectPopover.vue src/views/mall/promotion/kefu/components/tools/PictureSelectUpload.vue src/views/mall/promotion/kefu/components/tools/constants.ts src/views/mall/promotion/kefu/components/tools/emoji.ts src/views/mall/promotion/kefu/index.vue src/views/mall/promotion/point/activity/PointActivityForm.vue src/views/mall/promotion/point/activity/index.vue src/views/mall/promotion/point/activity/pointActivity.data.ts src/views/mall/promotion/point/components/PointShowcase.vue src/views/mall/promotion/point/components/PointTableSelect.vue src/views/mall/promotion/rewardActivity/RewardForm.vue src/views/mall/promotion/rewardActivity/components/RewardRule.vue src/views/mall/promotion/rewardActivity/components/RewardRuleCouponSelect.vue src/views/mall/promotion/rewardActivity/index.vue src/views/mall/promotion/seckill/activity/SeckillActivityForm.vue src/views/mall/promotion/seckill/activity/index.vue src/views/mall/promotion/seckill/activity/seckillActivity.data.ts src/views/mall/promotion/seckill/components/SeckillShowcase.vue src/views/mall/promotion/seckill/components/SeckillTableSelect.vue src/views/mall/promotion/seckill/config/SeckillConfigForm.vue src/views/mall/promotion/seckill/config/index.vue src/views/mall/statistics/member/components/MemberFunnelCard.vue src/views/mall/statistics/member/components/MemberTerminalCard.vue src/views/mall/statistics/member/index.vue src/views/mall/statistics/product/components/ProductRank.vue src/views/mall/statistics/product/components/ProductSummary.vue src/views/mall/statistics/product/index.vue src/views/mall/statistics/trade/components/TradeStatisticValue.vue src/views/mall/statistics/trade/index.vue src/views/mall/trade/afterSale/detail/index.vue src/views/mall/trade/afterSale/form/AfterSaleDisagreeForm.vue src/views/mall/trade/afterSale/index.vue src/views/mall/trade/brokerage/record/index.vue src/views/mall/trade/brokerage/user/BrokerageOrderListDialog.vue src/views/mall/trade/brokerage/user/BrokerageUserCreateForm.vue src/views/mall/trade/brokerage/user/BrokerageUserListDialog.vue src/views/mall/trade/brokerage/user/BrokerageUserUpdateForm.vue src/views/mall/trade/brokerage/user/index.vue src/views/mall/trade/brokerage/withdraw/BrokerageWithdrawRejectForm.vue src/views/mall/trade/brokerage/withdraw/index.vue src/views/mall/trade/config/index.vue src/views/mall/trade/delivery/express/ExpressForm.vue src/views/mall/trade/delivery/express/index.vue src/views/mall/trade/delivery/expressTemplate/ExpressTemplateForm.vue src/views/mall/trade/delivery/expressTemplate/index.vue src/views/mall/trade/delivery/pickUpOrder/index.vue src/views/mall/trade/delivery/pickUpStore/DeliveryPickUpStoreBindForm.vue src/views/mall/trade/delivery/pickUpStore/PickUpStoreForm.vue src/views/mall/trade/delivery/pickUpStore/components/StoreStaffTableSelect.vue src/views/mall/trade/delivery/pickUpStore/index.vue src/views/mall/trade/order/components/OrderTableColumn.vue src/views/mall/trade/order/components/index.ts src/views/mall/trade/order/detail/index.vue src/views/mall/trade/order/form/OrderDeliveryForm.vue src/views/mall/trade/order/form/OrderPickUpForm.vue src/views/mall/trade/order/form/OrderUpdateAddressForm.vue src/views/mall/trade/order/form/OrderUpdatePriceForm.vue src/views/mall/trade/order/form/OrderUpdateRemarkForm.vue src/views/mall/trade/order/index.vue src/views/member/config/index.vue src/views/member/group/GroupForm.vue src/views/member/group/components/MemberGroupSelect.vue src/views/member/group/index.vue src/views/member/level/LevelForm.vue src/views/member/level/components/MemberLevelSelect.vue src/views/member/level/index.vue src/views/member/point/record/index.vue src/views/member/signin/config/SignInConfigForm.vue src/views/member/signin/config/index.vue src/views/member/signin/record/index.vue src/views/member/tag/TagForm.vue src/views/member/tag/components/MemberTagSelect.vue src/views/member/tag/index.vue src/views/member/user/UserForm.vue src/views/member/user/components/UserBalanceUpdateForm.vue src/views/member/user/components/UserLevelUpdateForm.vue src/views/member/user/components/UserPointUpdateForm.vue src/views/member/user/detail/UserAccountInfo.vue src/views/member/user/detail/UserAddressList.vue src/views/member/user/detail/UserAftersaleList.vue src/views/member/user/detail/UserBalanceList.vue src/views/member/user/detail/UserBasicInfo.vue src/views/member/user/detail/UserBrokerageList.vue src/views/member/user/detail/UserCouponList.vue src/views/member/user/detail/UserExperienceRecordList.vue src/views/member/user/detail/UserFavoriteList.vue src/views/member/user/detail/UserOrderList.vue src/views/member/user/detail/UserPointList.vue src/views/member/user/detail/UserSignList.vue src/views/member/user/detail/index.vue src/views/member/user/index.vue src/views/mp/account/AccountForm.vue src/views/mp/account/index.vue src/views/mp/autoReply/components/ReplyForm.vue src/views/mp/autoReply/components/ReplyTable.vue src/views/mp/autoReply/components/types.ts src/views/mp/autoReply/index.vue src/views/mp/components/wx-account-select/index.ts src/views/mp/components/wx-account-select/main.vue src/views/mp/components/wx-location/index.ts src/views/mp/components/wx-location/main.vue src/views/mp/components/wx-material-select/index.ts src/views/mp/components/wx-material-select/main.vue src/views/mp/components/wx-material-select/types.ts src/views/mp/components/wx-msg/card.scss src/views/mp/components/wx-msg/comment.scss src/views/mp/components/wx-msg/components/Msg.vue src/views/mp/components/wx-msg/components/MsgEvent.vue src/views/mp/components/wx-msg/components/MsgList.vue src/views/mp/components/wx-msg/index.ts src/views/mp/components/wx-msg/main.vue src/views/mp/components/wx-msg/types.ts src/views/mp/components/wx-music/index.ts src/views/mp/components/wx-music/main.vue src/views/mp/components/wx-news/index.ts src/views/mp/components/wx-news/main.vue src/views/mp/components/wx-reply/components/TabImage.vue src/views/mp/components/wx-reply/components/TabMusic.vue src/views/mp/components/wx-reply/components/TabNews.vue src/views/mp/components/wx-reply/components/TabText.vue src/views/mp/components/wx-reply/components/TabVideo.vue src/views/mp/components/wx-reply/components/TabVoice.vue src/views/mp/components/wx-reply/components/types.ts src/views/mp/components/wx-reply/index.ts src/views/mp/components/wx-reply/main.vue src/views/mp/components/wx-video-play/index.ts src/views/mp/components/wx-video-play/main.vue src/views/mp/components/wx-voice-play/index.ts src/views/mp/components/wx-voice-play/main.vue src/views/mp/draft/components/CoverSelect.vue src/views/mp/draft/components/DraftTable.vue src/views/mp/draft/components/NewsForm.vue src/views/mp/draft/components/index.ts src/views/mp/draft/components/types.ts src/views/mp/draft/editor-config.ts src/views/mp/draft/index.vue src/views/mp/draft/mock.js src/views/mp/freePublish/index.vue src/views/mp/hooks/useUpload.ts src/views/mp/material/components/ImageTable.vue src/views/mp/material/components/UploadFile.vue src/views/mp/material/components/UploadVideo.vue src/views/mp/material/components/VideoTable.vue src/views/mp/material/components/VoiceTable.vue src/views/mp/material/components/upload.ts src/views/mp/material/index.vue src/views/mp/menu/assets/iphone_backImg.png src/views/mp/menu/assets/menu_foot.png src/views/mp/menu/assets/menu_head.png src/views/mp/menu/components/MenuEditor.vue src/views/mp/menu/components/MenuPreviewer.vue src/views/mp/menu/components/menuOptions.ts src/views/mp/menu/components/types.ts src/views/mp/menu/index.vue src/views/mp/message/MessageTable.vue src/views/mp/message/index.vue src/views/mp/messageTemplate/MessageTemplateSendForm.vue src/views/mp/messageTemplate/index.vue src/views/mp/statistics/index.vue src/views/mp/tag/TagForm.vue src/views/mp/tag/index.vue src/views/mp/user/UserForm.vue src/views/mp/user/index.vue src/views/pay/app/components/AppForm.vue src/views/pay/app/components/channel/AlipayChannelForm.vue src/views/pay/app/components/channel/MockChannelForm.vue src/views/pay/app/components/channel/WalletChannelForm.vue src/views/pay/app/components/channel/WeixinChannelForm.vue src/views/pay/app/index.vue src/views/pay/cashier/index.vue src/views/pay/demo/order/index.vue src/views/pay/demo/withdraw/DemoWithdrawForm.vue src/views/pay/demo/withdraw/index.vue src/views/pay/notify/NotifyDetail.vue src/views/pay/notify/index.vue src/views/pay/order/OrderDetail.vue src/views/pay/order/index.vue src/views/pay/refund/RefundDetail.vue src/views/pay/refund/index.vue src/views/pay/transfer/TransferDetail.vue src/views/pay/transfer/index.vue src/views/pay/wallet/balance/WalletForm.vue src/views/pay/wallet/balance/index.vue src/views/pay/wallet/rechargePackage/WalletRechargePackageForm.vue src/views/pay/wallet/rechargePackage/index.vue src/views/pay/wallet/transaction/WalletTransactionList.vue src/views/report/goview/index.vue src/views/report/jmreport/bi.vue src/views/report/jmreport/index.vue src/views/system/area/AreaForm.vue src/views/system/area/index.vue src/views/system/dept/DeptForm.vue src/views/system/dept/index.vue src/views/system/dict/DictTypeForm.vue src/views/system/dict/data/DictDataForm.vue src/views/system/dict/data/index.vue src/views/system/dict/index.vue src/views/system/loginlog/LoginLogDetail.vue src/views/system/loginlog/index.vue src/views/system/mail/account/MailAccountForm.vue src/views/system/mail/account/index.vue src/views/system/mail/log/MailLogDetail.vue src/views/system/mail/log/index.vue src/views/system/mail/template/MailTemplateForm.vue src/views/system/mail/template/MailTemplateSendForm.vue src/views/system/mail/template/index.vue src/views/system/menu/MenuForm.vue src/views/system/menu/index.vue src/views/system/notice/NoticeForm.vue src/views/system/notice/index.vue src/views/system/notify/message/NotifyMessageDetail.vue src/views/system/notify/message/index.vue src/views/system/notify/my/MyNotifyMessageDetail.vue src/views/system/notify/my/index.vue src/views/system/notify/template/NotifyTemplateForm.vue src/views/system/notify/template/NotifyTemplateSendForm.vue src/views/system/notify/template/index.vue src/views/system/oauth2/client/ClientForm.vue src/views/system/oauth2/client/index.vue src/views/system/oauth2/token/index.vue src/views/system/operatelog/OperateLogDetail.vue src/views/system/operatelog/index.vue src/views/system/post/PostForm.vue src/views/system/post/index.vue src/views/system/role/RoleAssignMenuForm.vue src/views/system/role/RoleDataPermissionForm.vue src/views/system/role/RoleForm.vue src/views/system/role/index.vue src/views/system/sms/channel/SmsChannelForm.vue src/views/system/sms/channel/index.vue src/views/system/sms/log/SmsLogDetail.vue src/views/system/sms/log/index.vue src/views/system/sms/template/SmsTemplateForm.vue src/views/system/sms/template/SmsTemplateSendForm.vue src/views/system/sms/template/index.vue src/views/system/social/client/SocialClientForm.vue src/views/system/social/client/index.vue src/views/system/social/user/SocialUserDetail.vue src/views/system/social/user/index.vue src/views/system/tenant/TenantForm.vue src/views/system/tenant/index.vue src/views/system/tenantPackage/TenantPackageForm.vue src/views/system/tenantPackage/index.vue src/views/system/user/DeptTree.vue src/views/system/user/UserAssignRoleForm.vue src/views/system/user/UserForm.vue src/views/system/user/UserImportForm.vue src/views/system/user/index.vue stylelint.config.js tsconfig.json types/components.d.ts types/env.d.ts types/global.d.ts types/router.d.ts types/wangeditor-types.d.ts uno.config.ts vite.config.ts web-types.json