Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66c6463f44 | ||
|
|
f4705ad4e1 | ||
|
|
143eb655b1 | ||
|
|
bbf009e15d | ||
|
|
ecf9052452 | ||
|
|
869cae0675 | ||
|
|
dd36bbce42 | ||
|
|
939ceb32ce | ||
|
|
e2fe04749b | ||
|
|
20a9780654 | ||
|
|
f75e8d1fd4 | ||
|
|
bde5597467 | ||
|
|
de967a0160 | ||
|
|
9527b41b62 | ||
|
|
ff14cf90f0 | ||
|
|
dcf66749af | ||
|
|
500b8632df | ||
|
|
730da857e1 | ||
|
|
c96902d622 | ||
|
|
0076236280 | ||
|
|
ae53ca6f4f | ||
|
|
9a36d9d663 | ||
|
|
f55c9b7273 | ||
|
|
6ff31b90c7 | ||
|
|
a0996bd0cf | ||
|
|
f405ac3293 | ||
|
|
2d999138ba | ||
|
|
1d533e49e4 | ||
|
|
dee479ce3c | ||
|
|
715f37eb0b | ||
|
|
56543b8db4 | ||
|
|
7f3950018e | ||
|
|
d26e0976db | ||
|
|
95a51ce4f3 | ||
|
|
0925253a9d | ||
|
|
98bf5a102e | ||
|
|
ff0c12c551 | ||
|
|
243da124a8 | ||
|
|
deb4585d4b | ||
|
|
afdee2cd48 | ||
|
|
f4dd1bed63 | ||
|
|
d96f951113 | ||
|
|
f5d013187b | ||
|
|
50ab864698 | ||
|
|
b1c832d27f | ||
|
|
5ba6c5ee00 | ||
|
|
ac6618a943 | ||
|
|
decdd1b25d | ||
|
|
97c8cefb7d | ||
|
|
bfb69ccccd | ||
|
|
958ec41f4e | ||
|
|
dc5bede084 | ||
|
|
755526834e | ||
|
|
221f78aa9a | ||
|
|
4e640bae88 | ||
|
|
014d1f8cd2 | ||
|
|
6acfc77d08 | ||
|
|
033462d25f | ||
|
|
2512253020 | ||
|
|
c331a83b74 | ||
|
|
56829ff921 | ||
|
|
6037ac4052 | ||
|
|
1f0ef78219 | ||
|
|
1c469300f5 | ||
|
|
7ba611bdb7 | ||
|
|
aba61120e4 | ||
|
|
e885bf2f2a | ||
|
|
ddfa0a5a0f | ||
|
|
855987d5fa | ||
|
|
bc95dc2959 | ||
|
|
3c49ed570a | ||
|
|
2f0fdd1d36 | ||
|
|
2d7bab8adb | ||
|
|
ab1c506226 | ||
|
|
99addf2cfa | ||
|
|
64af029c86 | ||
|
|
4793897511 | ||
|
|
786468f437 | ||
|
|
1f517c3faf | ||
|
|
4c15e6675a | ||
|
|
5358863fc6 | ||
|
|
0e15d6c9d2 | ||
|
|
f6e4753b34 | ||
|
|
e8a3745b5e | ||
|
|
091ce90359 | ||
|
|
b5fa188805 | ||
|
|
8f8edc9565 | ||
|
|
3c54f5f565 | ||
|
|
13cf1feefb | ||
|
|
6772568a58 | ||
|
|
8926dd1173 | ||
|
|
dcfad7a427 | ||
|
|
db4795744e | ||
|
|
f17dfb9a31 | ||
|
|
7b84ddd358 | ||
|
|
283a9d0507 | ||
|
|
c01571d11d | ||
|
|
757281ce34 | ||
|
|
b57a2c50a9 | ||
|
|
36385a74ba | ||
|
|
c048dcf02a | ||
|
|
9ede8ffe4d | ||
|
|
d16bed4ad7 | ||
|
|
68dae2d1fe | ||
|
|
d05c67ffaa | ||
|
|
5ca3358237 | ||
|
|
ffc81621d7 | ||
|
|
a489d21add | ||
|
|
bc004b3b27 | ||
|
|
52889e3504 | ||
|
|
6764f86980 | ||
|
|
02af138069 | ||
|
|
427c2d5d2a | ||
|
|
87d1047fa9 | ||
|
|
34b788cb88 | ||
|
|
291dc51849 | ||
|
|
1b7d604858 | ||
|
|
b51397fe19 | ||
|
|
68e1556378 | ||
|
|
23150fcfc3 | ||
|
|
1f14bf4bda | ||
|
|
b4677c4546 | ||
|
|
9f3bc1ead8 | ||
|
|
607c2b6c4a | ||
|
|
3820710c56 | ||
|
|
cce1fadc33 | ||
|
|
77971f9c96 | ||
|
|
624594bb5c | ||
|
|
eed7bb2e1a | ||
|
|
cc14963bc8 | ||
|
|
7218e71884 | ||
|
|
faf4557783 | ||
|
|
728cf15c45 | ||
|
|
48f6624737 | ||
|
|
5286ad1cd6 | ||
|
|
ee12e691be | ||
|
|
c2f98043df | ||
|
|
05b408d107 | ||
|
|
0d4b6f6344 | ||
|
|
07dc725857 | ||
|
|
d16194b794 | ||
|
|
d0f73344bf | ||
|
|
08dd4ed072 | ||
|
|
501a1c2f4d | ||
|
|
a0f157c8b6 | ||
|
|
2d424fc9a6 | ||
|
|
a40866e27f | ||
|
|
60ddc45b9b | ||
|
|
03b8bd5e22 | ||
|
|
de29528165 | ||
|
|
6b45ed7e78 | ||
|
|
59c7c49efa | ||
|
|
33d59c8b7d | ||
|
|
5f7ccd4e7c | ||
|
|
960f27f6ef | ||
|
|
aa57d89bea | ||
|
|
c5b1ad480f | ||
|
|
feadd022e7 | ||
|
|
4c0a5e8c30 | ||
|
|
b0d4c87d8e | ||
|
|
1a0f0a11b1 | ||
|
|
d21c060903 | ||
|
|
0230a4af01 | ||
|
|
2ed41ab164 | ||
|
|
c89941d435 | ||
|
|
55856be1de | ||
|
|
a6e29c5615 | ||
|
|
ecf9f26547 | ||
|
|
4dabfcba23 | ||
|
|
53c63ba68f | ||
|
|
2d4ed85e94 | ||
|
|
470c5076a3 | ||
|
|
762b51a5b4 | ||
|
|
13e925e29f | ||
|
|
e4e37d0cb4 | ||
|
|
3660cd26ae | ||
|
|
a31c995508 | ||
|
|
d0501ee0a6 | ||
|
|
3ddba81e24 | ||
|
|
c9d5ec26a2 | ||
|
|
441b91381f | ||
|
|
0db264dcac | ||
|
|
783f6283ca |
No files matched your search
@@ -1,20 +1,16 @@
|
||||
# 开发环境:本地只启动前端项目,依赖开发环境(后端、APP)
|
||||
NODE_ENV=development
|
||||
NODE_ENV=production
|
||||
|
||||
VITE_DEV=true
|
||||
|
||||
# 请求路径
|
||||
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
|
||||
# VITE_BASE_URL='http://dofast.demo.huizhizao.vip:20001'
|
||||
|
||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||
VITE_UPLOAD_TYPE=server
|
||||
# 上传路径
|
||||
VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload'
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASEPATH=/dev-api
|
||||
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
@@ -37,4 +33,4 @@ VITE_OUT_DIR=dist
|
||||
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
|
||||
|
||||
# 验证码的开关
|
||||
VITE_APP_CAPTCHA_ENABLE=false
|
||||
VITE_APP_CAPTCHA_ENABLE=true
|
||||
@@ -11,9 +11,6 @@ VITE_UPLOAD_TYPE=server
|
||||
# 上传路径
|
||||
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASEPATH=/dev-api
|
||||
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@ VITE_UPLOAD_TYPE=server
|
||||
# 上传路径
|
||||
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASEPATH=
|
||||
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@ VITE_UPLOAD_TYPE=server
|
||||
# 上传路径
|
||||
VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload'
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASEPATH=
|
||||
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@ VITE_UPLOAD_TYPE=server
|
||||
# 上传路径
|
||||
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASEPATH=
|
||||
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ dist
|
||||
dist-ssr
|
||||
*.local
|
||||
/dist*
|
||||
*-lock.*
|
||||
pnpm-debug
|
||||
auto-*.d.ts
|
||||
.idea
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
Vendored
-1
@@ -3,7 +3,6 @@
|
||||
"christian-kohler.path-intellisense",
|
||||
"vscode-icons-team.vscode-icons",
|
||||
"davidanson.vscode-markdownlint",
|
||||
"stylelint.vscode-stylelint",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"mrmlnc.vscode-less",
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 |
|
||||
| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 |
|
||||
|
||||

|
||||
|
||||
### 工作流程
|
||||
|
||||
| | 功能 | 描述 |
|
||||
@@ -129,6 +131,8 @@
|
||||
| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持回退操作 |
|
||||
| 🚀 | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 |
|
||||
|
||||

|
||||
|
||||
### 支付系统
|
||||
|
||||
| | 功能 | 描述 |
|
||||
@@ -142,27 +146,27 @@ ps:核心功能已经实现,正在对接微信小程序中...
|
||||
|
||||
### 基础设施
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|----------|----------------------------------------------|
|
||||
| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 |
|
||||
| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
|
||||
| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
|
||||
| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
|
||||
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
|
||||
| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
|
||||
| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
|
||||
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
|
||||
| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
|
||||
| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
|
||||
| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 |
|
||||
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
|
||||
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
|
||||
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
|
||||
| 🚀 | 分布式锁 | 基于 Redis 实现分布式锁,满足并发场景 |
|
||||
| 🚀 | 幂等组件 | 基于 Redis 实现幂等组件,解决重复请求问题 |
|
||||
| 🚀 | 服务保障 | 基于 Resilience4j 实现服务的稳定性,包括限流、熔断等功能 |
|
||||
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
|
||||
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
|
||||
| | 功能 | 描述 |
|
||||
|----|----------|----------------------------------------------|
|
||||
| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 |
|
||||
| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
|
||||
| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
|
||||
| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
|
||||
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
|
||||
| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
|
||||
| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
|
||||
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
|
||||
| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
|
||||
| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
|
||||
| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 |
|
||||
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
|
||||
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
|
||||
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
|
||||
| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 |
|
||||
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
|
||||
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
|
||||
|
||||

|
||||
|
||||
### 数据报表
|
||||
|
||||
|
||||
+10
-10
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "yudao-ui-admin-vue3",
|
||||
"version": "2.0.1-snapshot",
|
||||
"version": "2.1.0-snapshot",
|
||||
"description": "基于vue3、vite4、element-plus、typesScript",
|
||||
"author": "xingyu",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"i": "pnpm install",
|
||||
"dev": "vite --mode local-dev",
|
||||
"dev": "vite",
|
||||
"dev-server": "vite --mode dev",
|
||||
"ts:check": "vue-tsc --noEmit",
|
||||
"build:local-dev": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode local-dev",
|
||||
"build:local": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build",
|
||||
"build:dev": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode local-dev",
|
||||
"build:test": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode test",
|
||||
"build:stage": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode stage",
|
||||
@@ -35,7 +35,7 @@
|
||||
"@wangeditor/editor-for-vue": "^5.1.10",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.6.7",
|
||||
"axios": "^1.6.8",
|
||||
"benz-amr-recorder": "^1.1.5",
|
||||
"bpmn-js-token-simulation": "^0.10.0",
|
||||
"camunda-bpmn-moddle": "^7.0.1",
|
||||
@@ -46,7 +46,7 @@
|
||||
"driver.js": "^1.3.1",
|
||||
"echarts": "^5.5.0",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
"element-plus": "2.5.3",
|
||||
"element-plus": "2.6.1",
|
||||
"fast-xml-parser": "^4.3.2",
|
||||
"highlight.js": "^11.9.0",
|
||||
"jsencrypt": "^3.3.2",
|
||||
@@ -55,15 +55,15 @@
|
||||
"mitt": "^3.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.0",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"qrcode": "^1.5.3",
|
||||
"qs": "^6.11.2",
|
||||
"qs": "^6.12.0",
|
||||
"steady-xml": "^0.1.0",
|
||||
"url": "^0.11.3",
|
||||
"video.js": "^7.21.5",
|
||||
"vue": "3.4.20",
|
||||
"vue": "3.4.21",
|
||||
"vue-dompurify-html": "^4.1.4",
|
||||
"vue-i18n": "9.9.1",
|
||||
"vue-i18n": "9.10.2",
|
||||
"vue-router": "^4.3.0",
|
||||
"vue-types": "^5.1.1",
|
||||
"vuedraggable": "^4.1.0",
|
||||
@@ -102,6 +102,7 @@
|
||||
"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",
|
||||
@@ -136,7 +137,6 @@
|
||||
"url": "https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues"
|
||||
},
|
||||
"homepage": "https://gitee.com/yudaocode/yudao-ui-admin-vue3",
|
||||
"packageManager": "pnpm@8.6.0",
|
||||
"engines": {
|
||||
"node": ">= 16.0.0",
|
||||
"pnpm": ">=8.6.0"
|
||||
|
||||
Generated
+9614
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,43 @@
|
||||
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 })
|
||||
},
|
||||
|
||||
// 删除流程分类
|
||||
deleteCategory: async (id: number) => {
|
||||
return await request.delete({ url: `/bpm/category/delete?id=` + id })
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export const getProcessDefinitionBpmnXML = async (id: number) => {
|
||||
export const getProcessDefinition = async (id: number, key: string) => {
|
||||
return await request.get({
|
||||
url: '/bpm/process-definition/get-bpmn-xml?id=' + id
|
||||
url: '/bpm/process-definition/get',
|
||||
params: { id, key }
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ export const getFormPage = async (params) => {
|
||||
}
|
||||
|
||||
// 获得动态表单的精简列表
|
||||
export const getSimpleFormList = async () => {
|
||||
export const getFormSimpleList = async () => {
|
||||
return await request.get({
|
||||
url: '/bpm/form/list-all-simple'
|
||||
url: '/bpm/form/simple-list'
|
||||
})
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import request from '@/config/axios'
|
||||
|
||||
export type LeaveVO = {
|
||||
id: number
|
||||
result: number
|
||||
status: number
|
||||
type: number
|
||||
reason: string
|
||||
processInstanceId: string
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
@@ -20,51 +20,49 @@ export type ProcessInstanceVO = {
|
||||
endTime: string
|
||||
}
|
||||
|
||||
export type ProcessInstanceCCVO = {
|
||||
type: number,
|
||||
taskName: string,
|
||||
taskKey: string,
|
||||
processInstanceName: string,
|
||||
processInstanceKey: string,
|
||||
startUserId: string,
|
||||
options:string [],
|
||||
export type ProcessInstanceCopyVO = {
|
||||
type: number
|
||||
taskName: string
|
||||
taskKey: string
|
||||
processInstanceName: string
|
||||
processInstanceKey: string
|
||||
startUserId: string
|
||||
options: string[]
|
||||
reason: string
|
||||
}
|
||||
|
||||
export const getMyProcessInstancePage = async (params) => {
|
||||
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 cancelProcessInstance = async (id: number, reason: string) => {
|
||||
export const cancelProcessInstanceByStartUser = async (id: number, reason: string) => {
|
||||
const data = {
|
||||
id: id,
|
||||
reason: reason
|
||||
}
|
||||
return await request.delete({ url: '/bpm/process-instance/cancel', data: data })
|
||||
return await request.delete({ url: '/bpm/process-instance/cancel-by-start-user', data: data })
|
||||
}
|
||||
|
||||
export const getProcessInstance = async (id: number) => {
|
||||
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 })
|
||||
}
|
||||
|
||||
/**
|
||||
* 抄送
|
||||
* @param data 抄送数据
|
||||
* @returns 是否抄送成功
|
||||
*/
|
||||
export const createProcessInstanceCC = async (data) => {
|
||||
return await request.post({ url: '/bpm/process-instance/cc/create', data: data })
|
||||
export const getProcessInstanceCopyPage = async (params: any) => {
|
||||
return await request.get({ url: '/bpm/process-instance/copy/page', params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 抄送列表
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export const getProcessInstanceCCPage = async (params) => {
|
||||
return await request.get({ url: '/bpm/process-instance/cc/my-page', params })
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
+26
-41
@@ -4,78 +4,63 @@ export type TaskVO = {
|
||||
id: number
|
||||
}
|
||||
|
||||
export const getTodoTaskPage = async (params) => {
|
||||
export const getTaskTodoPage = async (params: any) => {
|
||||
return await request.get({ url: '/bpm/task/todo-page', params })
|
||||
}
|
||||
|
||||
export const getDoneTaskPage = async (params) => {
|
||||
export const getTaskDonePage = async (params: any) => {
|
||||
return await request.get({ url: '/bpm/task/done-page', params })
|
||||
}
|
||||
|
||||
export const completeTask = async (data) => {
|
||||
return await request.put({ url: '/bpm/task/complete', data })
|
||||
export const getTaskManagerPage = async (params: any) => {
|
||||
return await request.get({ url: '/bpm/task/manager-page', params })
|
||||
}
|
||||
|
||||
export const approveTask = async (data) => {
|
||||
export const approveTask = async (data: any) => {
|
||||
return await request.put({ url: '/bpm/task/approve', data })
|
||||
}
|
||||
|
||||
export const rejectTask = async (data) => {
|
||||
export const rejectTask = async (data: any) => {
|
||||
return await request.put({ url: '/bpm/task/reject', data })
|
||||
}
|
||||
export const backTask = async (data) => {
|
||||
return await request.put({ url: '/bpm/task/back', data })
|
||||
}
|
||||
|
||||
export const updateTaskAssignee = async (data) => {
|
||||
return await request.put({ url: '/bpm/task/update-assignee', data })
|
||||
}
|
||||
|
||||
export const getTaskListByProcessInstanceId = async (processInstanceId) => {
|
||||
export const getTaskListByProcessInstanceId = async (processInstanceId: string) => {
|
||||
return await request.get({
|
||||
url: '/bpm/task/list-by-process-instance-id?processInstanceId=' + processInstanceId
|
||||
})
|
||||
}
|
||||
|
||||
// 导出任务
|
||||
export const exportTask = async (params) => {
|
||||
return await request.download({ url: '/bpm/task/export', params })
|
||||
}
|
||||
|
||||
// 获取所有可回退的节点
|
||||
export const getReturnList = async (params) => {
|
||||
return await request.get({ url: '/bpm/task/return-list', params })
|
||||
export const getTaskListByReturn = async (id: string) => {
|
||||
return await request.get({ url: '/bpm/task/list-by-return', params: { id } })
|
||||
}
|
||||
|
||||
// 回退
|
||||
export const returnTask = async (data) => {
|
||||
export const returnTask = async (data: any) => {
|
||||
return await request.put({ url: '/bpm/task/return', data })
|
||||
}
|
||||
|
||||
/**
|
||||
* 委派
|
||||
*/
|
||||
export const delegateTask = async (data) => {
|
||||
// 委派
|
||||
export const delegateTask = async (data: any) => {
|
||||
return await request.put({ url: '/bpm/task/delegate', data })
|
||||
}
|
||||
|
||||
/**
|
||||
* 加签
|
||||
*/
|
||||
export const taskAddSign = async (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 getChildrenTaskList = async (id: string) => {
|
||||
return await request.get({ url: '/bpm/task/children-list?taskId=' + id })
|
||||
}
|
||||
|
||||
/**
|
||||
* 减签
|
||||
*/
|
||||
export const taskSubSign = async (data) => {
|
||||
// 减签
|
||||
export const signDeleteTask = async (data: any) => {
|
||||
return await request.delete({ url: '/bpm/task/delete-sign', data })
|
||||
}
|
||||
|
||||
// 获取减签任务列表
|
||||
export const getChildrenTaskList = async (id: string) => {
|
||||
return await request.get({ url: '/bpm/task/list-by-parent-task-id?parentTaskId=' + id })
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export type TaskAssignVO = {
|
||||
id: number
|
||||
modelId: string
|
||||
processDefinitionId: string
|
||||
taskDefinitionKey: string
|
||||
taskDefinitionName: string
|
||||
options: string[]
|
||||
type: number
|
||||
}
|
||||
|
||||
export const getTaskAssignRuleList = async (params) => {
|
||||
return await request.get({ url: '/bpm/task-assign-rule/list', params })
|
||||
}
|
||||
|
||||
export const createTaskAssignRule = async (data: TaskAssignVO) => {
|
||||
return await request.post({
|
||||
url: '/bpm/task-assign-rule/create',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export const updateTaskAssignRule = async (data: TaskAssignVO) => {
|
||||
return await request.put({
|
||||
url: '/bpm/task-assign-rule/update',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
@@ -4,7 +4,7 @@ export type UserGroupVO = {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
memberUserIds: number[]
|
||||
userIds: number[]
|
||||
status: number
|
||||
remark: string
|
||||
createTime: string
|
||||
@@ -42,6 +42,6 @@ export const getUserGroupPage = async (params) => {
|
||||
}
|
||||
|
||||
// 获取用户组精简信息列表
|
||||
export const getSimpleUserGroupList = async (): Promise<UserGroupVO[]> => {
|
||||
return await request.get({ url: '/bpm/user-group/list-all-simple' })
|
||||
export const getUserGroupSimpleList = async (): Promise<UserGroupVO[]> => {
|
||||
return await request.get({ url: '/bpm/user-group/simple-list' })
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { TransferReqVO } from '@/api/crm/customer'
|
||||
import { TransferReqVO } from '@/api/crm/permission'
|
||||
|
||||
export interface BusinessVO {
|
||||
id: number
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { TransferReqVO } from '@/api/crm/customer'
|
||||
import { TransferReqVO } from '@/api/crm/permission'
|
||||
|
||||
export interface ClueVO {
|
||||
id: number // 编号
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { TransferReqVO } from '@/api/crm/customer'
|
||||
import { TransferReqVO } from '@/api/crm/permission'
|
||||
|
||||
export interface ContactVO {
|
||||
id: number // 编号
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { TransferReqVO } from '@/api/crm/customer'
|
||||
import { TransferReqVO } from '@/api/crm/permission'
|
||||
|
||||
export interface ContractVO {
|
||||
id: number
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { TransferReqVO } from '@/api/crm/permission'
|
||||
|
||||
export interface CustomerVO {
|
||||
id: number // 编号
|
||||
@@ -102,12 +103,6 @@ export const getCustomerSimpleList = async () => {
|
||||
|
||||
// ======================= 业务操作 =======================
|
||||
|
||||
export interface TransferReqVO {
|
||||
id: number | undefined // 客户编号
|
||||
newOwnerUserId: number | undefined // 新负责人的用户编号
|
||||
oldOwnerPermissionLevel: number | undefined // 老负责人加入团队后的权限级别
|
||||
}
|
||||
|
||||
// 客户转移
|
||||
export const transferCustomer = async (data: TransferReqVO) => {
|
||||
return await request.put({ url: '/crm/customer/transfer', data })
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface PermissionVO {
|
||||
bizType: number // Crm 类型
|
||||
bizId: number // Crm 类型数据编号
|
||||
level: number // 权限级别
|
||||
toBizTypes?: number[] // 同时添加至
|
||||
deptName?: string // 部门名称
|
||||
nickname?: string // 用户昵称
|
||||
postNames?: string[] // 岗位名称数组
|
||||
@@ -13,6 +14,13 @@ export interface PermissionVO {
|
||||
ids?: number[]
|
||||
}
|
||||
|
||||
export interface TransferReqVO {
|
||||
id: number // 模块编号
|
||||
newOwnerUserId: number // 新负责人的用户编号
|
||||
oldOwnerPermissionLevel?: number // 老负责人加入团队后的权限级别
|
||||
toBizTypes?: number[] // 转移客户时,需要额外有【联系人】【商机】【合同】的 checkbox 选择
|
||||
}
|
||||
|
||||
/**
|
||||
* CRM 业务类型枚举
|
||||
*
|
||||
|
||||
@@ -3,18 +3,20 @@ import request from '@/config/axios'
|
||||
export interface ReceivableVO {
|
||||
id: number
|
||||
no: string
|
||||
planId: number
|
||||
customerId: number
|
||||
planId?: number
|
||||
customerId?: number
|
||||
customerName?: string
|
||||
contractId: number
|
||||
contractId?: number
|
||||
contract?: {
|
||||
id?: number
|
||||
name?: string
|
||||
no: string
|
||||
totalPrice: number
|
||||
}
|
||||
auditStatus: number
|
||||
processInstanceId: number
|
||||
returnTime: Date
|
||||
returnType: string
|
||||
returnType: number
|
||||
price: number
|
||||
ownerUserId: number
|
||||
ownerUserName?: string
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface ReceivablePlanVO {
|
||||
remindTime: Date
|
||||
customerId: number
|
||||
customerName?: string
|
||||
contractId: number
|
||||
contractId?: number
|
||||
contractNo?: string
|
||||
ownerUserId: number
|
||||
ownerUserName?: string
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,15 @@ export interface ApiAccessLogVO {
|
||||
applicationName: string
|
||||
requestMethod: string
|
||||
requestParams: string
|
||||
responseBody: string
|
||||
requestUrl: string
|
||||
userIp: string
|
||||
userAgent: string
|
||||
operateModule: string
|
||||
operateName: string
|
||||
operateType: number
|
||||
beginTime: Date
|
||||
endTIme: Date
|
||||
endTime: Date
|
||||
duration: number
|
||||
resultCode: number
|
||||
resultMsg: string
|
||||
|
||||
@@ -28,7 +28,6 @@ export type CodegenColumnVO = {
|
||||
columnComment: string
|
||||
nullable: number
|
||||
primaryKey: number
|
||||
autoIncrement: boolean
|
||||
ordinalPosition: number
|
||||
javaType: string
|
||||
javaField: string
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 导出Html
|
||||
export const exportHtml = () => {
|
||||
return request.download({ url: '/infra/db-doc/export-html' })
|
||||
}
|
||||
|
||||
// 导出Word
|
||||
export const exportWord = () => {
|
||||
return request.download({ url: '/infra/db-doc/export-word' })
|
||||
}
|
||||
|
||||
// 导出Markdown
|
||||
export const exportMarkdown = () => {
|
||||
return request.download({ url: '/infra/db-doc/export-markdown' })
|
||||
}
|
||||
@@ -1,49 +1,53 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 秒杀时段 VO
|
||||
export interface SeckillConfigVO {
|
||||
id: number
|
||||
name: string
|
||||
startTime: string
|
||||
endTime: string
|
||||
sliderPicUrls: string[]
|
||||
status: number
|
||||
id: number // 编号
|
||||
name: string // 秒杀时段名称
|
||||
startTime: string // 开始时间点
|
||||
endTime: string // 结束时间点
|
||||
sliderPicUrls: string[] // 秒杀轮播图
|
||||
status: number // 活动状态
|
||||
}
|
||||
|
||||
// 查询秒杀时段配置列表
|
||||
export const getSeckillConfigPage = async (params) => {
|
||||
return await request.get({ url: '/promotion/seckill-config/page', params })
|
||||
}
|
||||
// 秒杀时段 API
|
||||
export const SeckillConfigApi = {
|
||||
// 查询秒杀时段分页
|
||||
getSeckillConfigPage: async (params: any) => {
|
||||
return await request.get({ url: `/promotion/seckill-config/page`, params })
|
||||
},
|
||||
|
||||
// 查询秒杀时段配置详情
|
||||
export const getSeckillConfig = async (id: number) => {
|
||||
return await request.get({ url: '/promotion/seckill-config/get?id=' + id })
|
||||
}
|
||||
// 查询秒杀时段列表
|
||||
getSimpleSeckillConfigList: async () => {
|
||||
return await request.get({ url: `/promotion/seckill-config/simple-list` })
|
||||
},
|
||||
|
||||
// 获得所有开启状态的秒杀时段精简列表
|
||||
export const getSimpleSeckillConfigList = async () => {
|
||||
return await request.get({ url: '/promotion/seckill-config/list-all-simple' })
|
||||
}
|
||||
// 查询秒杀时段详情
|
||||
getSeckillConfig: async (id: number) => {
|
||||
return await request.get({ url: `/promotion/seckill-config/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增秒杀时段配置
|
||||
export const createSeckillConfig = async (data: SeckillConfigVO) => {
|
||||
return await request.post({ url: '/promotion/seckill-config/create', data })
|
||||
}
|
||||
// 新增秒杀时段
|
||||
createSeckillConfig: async (data: SeckillConfigVO) => {
|
||||
return await request.post({ url: `/promotion/seckill-config/create`, data })
|
||||
},
|
||||
|
||||
// 修改秒杀时段配置
|
||||
export const updateSeckillConfig = async (data: SeckillConfigVO) => {
|
||||
return await request.put({ url: '/promotion/seckill-config/update', data })
|
||||
}
|
||||
// 修改秒杀时段
|
||||
updateSeckillConfig: async (data: SeckillConfigVO) => {
|
||||
return await request.put({ url: `/promotion/seckill-config/update`, data })
|
||||
},
|
||||
|
||||
// 修改时段配置状态
|
||||
export const updateSeckillConfigStatus = (id: number, status: number) => {
|
||||
const data = {
|
||||
id,
|
||||
status
|
||||
// 删除秒杀时段
|
||||
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 })
|
||||
}
|
||||
return request.put({ url: '/promotion/seckill-config/update-status', data: data })
|
||||
}
|
||||
|
||||
// 删除秒杀时段配置
|
||||
export const deleteSeckillConfig = async (id: number) => {
|
||||
return await request.delete({ url: '/promotion/seckill-config/delete?id=' + id })
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { formatDate } from '@/utils/formatTime'
|
||||
|
||||
/** 会员分析 Request VO */
|
||||
export interface MemberAnalyseReqVO {
|
||||
times: [dayjs.ConfigType, dayjs.ConfigType]
|
||||
times: dayjs.ConfigType[]
|
||||
}
|
||||
|
||||
/** 会员分析 Response VO */
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface UReportDataVO {
|
||||
id: number
|
||||
name: string
|
||||
status: number
|
||||
content: string
|
||||
remark: string
|
||||
}
|
||||
|
||||
// 查询Ureport2报表分页
|
||||
export const getUReportDataPage = async (params) => {
|
||||
return await request.get({ url: `/report/ureport-data/page`, params })
|
||||
}
|
||||
|
||||
// 查询Ureport2报表详情
|
||||
export const getUReportData = async (id: number) => {
|
||||
return await request.get({ url: `/report/ureport-data/get?id=` + id })
|
||||
}
|
||||
|
||||
// 新增Ureport2报表
|
||||
export const createUReportData = async (data: UReportDataVO) => {
|
||||
return await request.post({ url: `/report/ureport-data/create`, data })
|
||||
}
|
||||
|
||||
// 修改Ureport2报表
|
||||
export const updateUReportData = async (data: UReportDataVO) => {
|
||||
return await request.put({ url: `/report/ureport-data/update`, data })
|
||||
}
|
||||
|
||||
// 删除Ureport2报表
|
||||
export const deleteUReportData = async (id: number) => {
|
||||
return await request.delete({ url: `/report/ureport-data/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 导出Ureport2报表 Excel
|
||||
export const exportUReportData = async (params) => {
|
||||
return await request.download({ url: `/report/ureport-data/export-excel`, params })
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface ErrorCodeVO {
|
||||
id: number | undefined
|
||||
type: number
|
||||
applicationName: string
|
||||
code: number | undefined
|
||||
message: string
|
||||
memo: string
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 查询错误码列表
|
||||
export const getErrorCodePage = (params: PageParam) => {
|
||||
return request.get({ url: '/system/error-code/page', params })
|
||||
}
|
||||
|
||||
// 查询错误码详情
|
||||
export const getErrorCode = (id: number) => {
|
||||
return request.get({ url: '/system/error-code/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增错误码
|
||||
export const createErrorCode = (data: ErrorCodeVO) => {
|
||||
return request.post({ url: '/system/error-code/create', data })
|
||||
}
|
||||
|
||||
// 修改错误码
|
||||
export const updateErrorCode = (data: ErrorCodeVO) => {
|
||||
return request.put({ url: '/system/error-code/update', data })
|
||||
}
|
||||
|
||||
// 删除错误码
|
||||
export const deleteErrorCode = (id: number) => {
|
||||
return request.delete({ url: '/system/error-code/delete?id=' + id })
|
||||
}
|
||||
// 导出错误码
|
||||
export const excelErrorCode = (params) => {
|
||||
return request.download({ url: '/system/error-code/export-excel', params })
|
||||
}
|
||||
@@ -8,6 +8,7 @@ export interface MailAccountVO {
|
||||
host: string
|
||||
port: number
|
||||
sslEnable: boolean
|
||||
starttlsEnable: boolean
|
||||
}
|
||||
|
||||
// 查询邮箱账号列表
|
||||
|
||||
@@ -2,30 +2,6 @@ import request from '@/config/axios'
|
||||
|
||||
export type OperateLogVO = {
|
||||
id: number
|
||||
userNickname: string
|
||||
traceId: string
|
||||
userId: number
|
||||
module: string
|
||||
name: string
|
||||
type: number
|
||||
content: string
|
||||
exts: Map<String, Object>
|
||||
requestMethod: string
|
||||
requestUrl: string
|
||||
userIp: string
|
||||
userAgent: string
|
||||
javaMethod: string
|
||||
javaMethodArgs: string
|
||||
startTime: Date
|
||||
duration: number
|
||||
resultCode: number
|
||||
resultMsg: string
|
||||
resultData: string
|
||||
}
|
||||
|
||||
export type OperateLogV2VO = {
|
||||
id: number
|
||||
userNickname: string
|
||||
traceId: string
|
||||
userType: number
|
||||
userId: number
|
||||
@@ -42,11 +18,6 @@ export type OperateLogV2VO = {
|
||||
creator: string
|
||||
creatorName: string
|
||||
createTime: Date
|
||||
// 数据扩展,渲染时使用
|
||||
title: string // 操作标题(如果为空则取 name 值)
|
||||
colSize: number // 变更记录行数
|
||||
contentStrList: string[]
|
||||
tagsContentList: string[]
|
||||
}
|
||||
|
||||
// 查询操作日志列表
|
||||
@@ -54,6 +25,6 @@ export const getOperateLogPage = (params: PageParam) => {
|
||||
return request.get({ url: '/system/operate-log/page', params })
|
||||
}
|
||||
// 导出操作日志
|
||||
export const exportOperateLog = (params) => {
|
||||
export const exportOperateLog = (params: any) => {
|
||||
return request.download({ url: '/system/operate-log/export', params })
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
import qs from 'qs'
|
||||
|
||||
export interface SensitiveWordVO {
|
||||
id: number
|
||||
name: string
|
||||
status: number
|
||||
description: string
|
||||
tags: string[]
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
export interface SensitiveWordTestReqVO {
|
||||
text: string
|
||||
tag: string[]
|
||||
}
|
||||
|
||||
// 查询敏感词列表
|
||||
export const getSensitiveWordPage = (params: PageParam) => {
|
||||
return request.get({ url: '/system/sensitive-word/page', params })
|
||||
}
|
||||
|
||||
// 查询敏感词详情
|
||||
export const getSensitiveWord = (id: number) => {
|
||||
return request.get({ url: '/system/sensitive-word/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增敏感词
|
||||
export const createSensitiveWord = (data: SensitiveWordVO) => {
|
||||
return request.post({ url: '/system/sensitive-word/create', data })
|
||||
}
|
||||
|
||||
// 修改敏感词
|
||||
export const updateSensitiveWord = (data: SensitiveWordVO) => {
|
||||
return request.put({ url: '/system/sensitive-word/update', data })
|
||||
}
|
||||
|
||||
// 删除敏感词
|
||||
export const deleteSensitiveWord = (id: number) => {
|
||||
return request.delete({ url: '/system/sensitive-word/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 导出敏感词
|
||||
export const exportSensitiveWord = (params) => {
|
||||
return request.download({ url: '/system/sensitive-word/export-excel', params })
|
||||
}
|
||||
|
||||
// 获取所有敏感词的标签数组
|
||||
export const getSensitiveWordTagList = () => {
|
||||
return request.get({ url: '/system/sensitive-word/get-tags' })
|
||||
}
|
||||
|
||||
// 获得文本所包含的不合法的敏感词数组
|
||||
export const validateText = (query: SensitiveWordTestReqVO) => {
|
||||
return request.get({
|
||||
url: '/system/sensitive-word/validate-text?' + qs.stringify(query, { arrayFormat: 'repeat' })
|
||||
})
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
@@ -503,9 +503,13 @@ const submit = () => {
|
||||
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">
|
||||
<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 * * * * ?" />
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import DictSelect from './src/DictSelect.vue'
|
||||
|
||||
export { DictSelect }
|
||||
@@ -0,0 +1,46 @@
|
||||
<!-- 数据字典 Select 选择器 -->
|
||||
<template>
|
||||
<el-select class="w-1/1" v-bind="attrs">
|
||||
<template v-if="valueType === 'int'">
|
||||
<el-option
|
||||
v-for="(dict, index) in getIntDictOptions(dictType)"
|
||||
:key="index"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="valueType === 'str'">
|
||||
<el-option
|
||||
v-for="(dict, index) in getStrDictOptions(dictType)"
|
||||
:key="index"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="valueType === 'bool'">
|
||||
<el-option
|
||||
v-for="(dict, index) in getBoolDictOptions(dictType)"
|
||||
:key="index"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getBoolDictOptions, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
|
||||
|
||||
// 接受父组件参数
|
||||
interface Props {
|
||||
dictType: string // 字典类型
|
||||
valueType: string // 字典值类型
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
dictType: '',
|
||||
valueType: 'str'
|
||||
})
|
||||
const attrs = useAttrs()
|
||||
defineOptions({ name: 'DictSelect' })
|
||||
</script>
|
||||
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div class="h-40px flex items-center justify-center">
|
||||
<MagicCubeEditor
|
||||
v-model="cellList"
|
||||
class="m-b-16px"
|
||||
:rows="1"
|
||||
:cols="cellCount"
|
||||
:cube-size="38"
|
||||
@hot-area-selected="handleHotAreaSelected"
|
||||
/>
|
||||
<img src="@/assets/imgs/diy/app-nav-bar-mp.png" alt="" class="h-30px w-76px" v-if="isMp" />
|
||||
</div>
|
||||
<template v-for="(cell, cellIndex) in cellList" :key="cellIndex">
|
||||
<template v-if="selectedHotAreaIndex === cellIndex">
|
||||
<el-form-item label="类型" :prop="`cell[${cellIndex}].type`">
|
||||
<el-radio-group v-model="cell.type">
|
||||
<el-radio label="text">文字</el-radio>
|
||||
<el-radio label="image">图片</el-radio>
|
||||
<el-radio label="search">搜索框</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 1. 文字 -->
|
||||
<template v-if="cell.type === 'text'">
|
||||
<el-form-item label="内容" :prop="`cell[${cellIndex}].text`">
|
||||
<el-input v-model="cell!.text" maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item label="颜色" :prop="`cell[${cellIndex}].text`">
|
||||
<ColorInput v-model="cell!.textColor" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<!-- 2. 图片 -->
|
||||
<template v-else-if="cell.type === 'image'">
|
||||
<el-form-item label="图片" :prop="`cell[${cellIndex}].imgUrl`">
|
||||
<UploadImg v-model="cell.imgUrl" :limit="1" height="56px" width="56px">
|
||||
<template #tip>建议尺寸 56*56</template>
|
||||
</UploadImg>
|
||||
</el-form-item>
|
||||
<el-form-item label="链接" :prop="`cell[${cellIndex}].url`">
|
||||
<AppLinkInput v-model="cell.url" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<!-- 3. 搜索框 -->
|
||||
<template v-else>
|
||||
<el-form-item label="提示文字" :prop="`cell[${cellIndex}].placeholder`">
|
||||
<el-input v-model="cell.placeholder" maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item label="圆角" :prop="`cell[${cellIndex}].borderRadius`">
|
||||
<el-slider
|
||||
v-model="cell.borderRadius"
|
||||
:max="100"
|
||||
:min="0"
|
||||
show-input
|
||||
input-size="small"
|
||||
:show-input-controls="false"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { NavigationBarCellProperty } from '../config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
// 导航栏属性面板
|
||||
defineOptions({ name: 'NavigationBarCellProperty' })
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: NavigationBarCellProperty[]
|
||||
isMp: boolean
|
||||
}>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData: cellList } = usePropertyForm(props.modelValue, emit)
|
||||
if (!cellList.value) cellList.value = []
|
||||
|
||||
// 单元格数量:小程序6个(右侧胶囊按钮占了2个),其它平台8个
|
||||
const cellCount = computed(() => (props.isMp ? 6 : 8))
|
||||
|
||||
// 选中的热区
|
||||
const selectedHotAreaIndex = ref(0)
|
||||
const handleHotAreaSelected = (cellValue: NavigationBarCellProperty, index: number) => {
|
||||
selectedHotAreaIndex.value = index
|
||||
if (!cellValue.type) {
|
||||
cellValue.type = 'text'
|
||||
cellValue.textColor = '#111111'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -2,22 +2,53 @@ import { DiyComponent } from '@/components/DiyEditor/util'
|
||||
|
||||
/** 顶部导航栏属性 */
|
||||
export interface NavigationBarProperty {
|
||||
// 页面标题
|
||||
title: string
|
||||
// 页面描述
|
||||
description: string
|
||||
// 顶部导航高度
|
||||
navBarHeight: number
|
||||
// 页面背景颜色
|
||||
backgroundColor: string
|
||||
// 页面背景图片
|
||||
backgroundImage: string
|
||||
// 背景类型
|
||||
bgType: 'color' | 'img'
|
||||
// 背景颜色
|
||||
bgColor: string
|
||||
// 图片链接
|
||||
bgImg: string
|
||||
// 样式类型:默认 | 沉浸式
|
||||
styleType: 'default' | 'immersion'
|
||||
styleType: 'normal' | 'inner'
|
||||
// 常驻显示
|
||||
alwaysShow: boolean
|
||||
// 是否显示返回按钮
|
||||
showGoBack: boolean
|
||||
// 小程序单元格列表
|
||||
mpCells: NavigationBarCellProperty[]
|
||||
// 其它平台单元格列表
|
||||
otherCells: NavigationBarCellProperty[]
|
||||
// 本地变量
|
||||
_local: {
|
||||
// 预览顶部导航(小程序)
|
||||
previewMp: boolean
|
||||
// 预览顶部导航(非小程序)
|
||||
previewOther: boolean
|
||||
}
|
||||
}
|
||||
|
||||
/** 顶部导航栏 - 单元格 属性 */
|
||||
export interface NavigationBarCellProperty {
|
||||
// 类型:文字 | 图片 | 搜索框
|
||||
type: 'text' | 'image' | 'search'
|
||||
// 宽度
|
||||
width: number
|
||||
// 高度
|
||||
height: number
|
||||
// 顶部位置
|
||||
top: number
|
||||
// 左侧位置
|
||||
left: number
|
||||
// 文字内容
|
||||
text: string
|
||||
// 文字颜色
|
||||
textColor: string
|
||||
// 图片地址
|
||||
imgUrl: string
|
||||
// 图片链接
|
||||
url: string
|
||||
// 搜索框:提示文字
|
||||
placeholder: string
|
||||
// 搜索框:边框圆角半径
|
||||
borderRadius: number
|
||||
}
|
||||
|
||||
// 定义组件
|
||||
@@ -26,13 +57,26 @@ export const component = {
|
||||
name: '顶部导航栏',
|
||||
icon: 'tabler:layout-navbar',
|
||||
property: {
|
||||
title: '页面标题',
|
||||
description: '',
|
||||
navBarHeight: 35,
|
||||
backgroundColor: '#fff',
|
||||
backgroundImage: '',
|
||||
styleType: 'default',
|
||||
bgType: 'color',
|
||||
bgColor: '#fff',
|
||||
bgImg: '',
|
||||
styleType: 'normal',
|
||||
alwaysShow: true,
|
||||
showGoBack: true
|
||||
mpCells: [
|
||||
{
|
||||
type: 'text',
|
||||
textColor: '#111111'
|
||||
}
|
||||
],
|
||||
otherCells: [
|
||||
{
|
||||
type: 'text',
|
||||
textColor: '#111111'
|
||||
}
|
||||
],
|
||||
_local: {
|
||||
previewMp: true,
|
||||
previewOther: false
|
||||
}
|
||||
}
|
||||
} as DiyComponent<NavigationBarProperty>
|
||||
@@ -1,45 +1,73 @@
|
||||
<template>
|
||||
<div
|
||||
class="navigation-bar"
|
||||
:style="{
|
||||
height: `${property.navBarHeight}px`,
|
||||
backgroundColor: property.backgroundColor,
|
||||
backgroundImage: `url(${property.backgroundImage})`
|
||||
}"
|
||||
>
|
||||
<!-- 左侧 -->
|
||||
<div class="left">
|
||||
<Icon icon="ep:arrow-left" v-show="property.showGoBack" />
|
||||
<div class="navigation-bar" :style="bgStyle">
|
||||
<div class="h-full w-full flex items-center">
|
||||
<div v-for="(cell, cellIndex) in cellList" :key="cellIndex" :style="getCellStyle(cell)">
|
||||
<span v-if="cell.type === 'text'">{{ cell.text }}</span>
|
||||
<img v-else-if="cell.type === 'image'" :src="cell.imgUrl" alt="" class="h-full w-full" />
|
||||
<SearchBar v-else :property="getSearchProp" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 中间 -->
|
||||
<div
|
||||
class="center"
|
||||
:style="{
|
||||
height: `${property.navBarHeight}px`,
|
||||
lineHeight: `${property.navBarHeight}px`
|
||||
}"
|
||||
>
|
||||
{{ property.title }}
|
||||
</div>
|
||||
<!-- 右侧 -->
|
||||
<div class="right"></div>
|
||||
<img
|
||||
v-if="property._local?.previewMp"
|
||||
src="@/assets/imgs/diy/app-nav-bar-mp.png"
|
||||
alt=""
|
||||
class="h-30px w-86px"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { NavigationBarProperty } from './config'
|
||||
import { NavigationBarCellProperty, NavigationBarProperty } from './config'
|
||||
import SearchBar from '@/components/DiyEditor/components/mobile/SearchBar/index.vue'
|
||||
import { StyleValue } from 'vue'
|
||||
import { SearchProperty } from '@/components/DiyEditor/components/mobile/SearchBar/config'
|
||||
|
||||
/** 页面顶部导航栏 */
|
||||
defineOptions({ name: 'NavigationBar' })
|
||||
|
||||
defineProps<{ property: NavigationBarProperty }>()
|
||||
const props = defineProps<{ property: NavigationBarProperty }>()
|
||||
|
||||
// 背景
|
||||
const bgStyle = computed(() => {
|
||||
const background =
|
||||
props.property.bgType === 'img' && props.property.bgImg
|
||||
? `url(${props.property.bgImg}) no-repeat top center / 100% 100%`
|
||||
: props.property.bgColor
|
||||
return { background }
|
||||
})
|
||||
// 单元格列表
|
||||
const cellList = computed(() =>
|
||||
props.property._local?.previewMp ? props.property.mpCells : props.property.otherCells
|
||||
)
|
||||
// 单元格宽度
|
||||
const cellWidth = computed(() => {
|
||||
return props.property._local?.previewMp ? (375 - 80 - 86) / 6 : (375 - 90) / 8
|
||||
})
|
||||
// 获得单元格样式
|
||||
const getCellStyle = (cell: NavigationBarCellProperty) => {
|
||||
return {
|
||||
width: cell.width * cellWidth.value + (cell.width - 1) * 10 + 'px',
|
||||
left: cell.left * cellWidth.value + (cell.left + 1) * 10 + 'px',
|
||||
position: 'absolute'
|
||||
} as StyleValue
|
||||
}
|
||||
// 获得搜索框属性
|
||||
const getSearchProp = (cell: NavigationBarCellProperty) => {
|
||||
return {
|
||||
height: 30,
|
||||
showScan: false,
|
||||
placeholder: cell.placeholder,
|
||||
borderRadius: cell.borderRadius
|
||||
} as SearchProperty
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.navigation-bar {
|
||||
display: flex;
|
||||
height: 35px;
|
||||
height: 50px;
|
||||
background: #fff;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 6px;
|
||||
|
||||
/* 左边 */
|
||||
.left {
|
||||
|
||||
@@ -1,53 +1,73 @@
|
||||
<template>
|
||||
<el-form label-width="80px" :model="formData" :rules="rules">
|
||||
<el-form-item label="页面标题" prop="title">
|
||||
<el-input v-model="formData!.title" placeholder="页面标题" maxlength="25" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item label="页面描述" prop="description">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="formData!.description"
|
||||
placeholder="用户通过微信分享给朋友时,会自动显示页面描述"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="样式" prop="styleType">
|
||||
<el-radio-group v-model="formData!.styleType">
|
||||
<el-radio label="default">默认</el-radio>
|
||||
<el-radio label="immersion">沉浸式</el-radio>
|
||||
<el-radio label="normal">标准</el-radio>
|
||||
<el-tooltip
|
||||
content="沉侵式头部仅支持微信小程序、APP,建议页面第一个组件为图片展示类组件"
|
||||
placement="top"
|
||||
>
|
||||
<el-radio label="inner">沉浸式</el-radio>
|
||||
</el-tooltip>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="常驻显示" prop="alwaysShow" v-if="formData.styleType === 'immersion'">
|
||||
<el-form-item label="常驻显示" prop="alwaysShow" v-if="formData.styleType === 'inner'">
|
||||
<el-radio-group v-model="formData!.alwaysShow">
|
||||
<el-radio :label="false">关闭</el-radio>
|
||||
<el-radio :label="true">开启</el-radio>
|
||||
<el-tooltip content="常驻显示关闭后,头部小组件将在页面滑动时淡入" placement="top">
|
||||
<el-radio :label="true">开启</el-radio>
|
||||
</el-tooltip>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="高度" prop="navBarHeight">
|
||||
<el-slider
|
||||
v-model="formData!.navBarHeight"
|
||||
:max="100"
|
||||
:min="35"
|
||||
show-input
|
||||
input-size="small"
|
||||
/>
|
||||
<el-form-item label="背景类型" prop="bgType">
|
||||
<el-radio-group v-model="formData.bgType">
|
||||
<el-radio label="color">纯色</el-radio>
|
||||
<el-radio label="img">图片</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="返回按钮" prop="showGoBack">
|
||||
<el-switch v-model="formData!.showGoBack" />
|
||||
<el-form-item label="背景颜色" prop="bgColor" v-if="formData.bgType === 'color'">
|
||||
<ColorInput v-model="formData.bgColor" />
|
||||
</el-form-item>
|
||||
<el-form-item label="背景颜色" prop="backgroundColor">
|
||||
<ColorInput v-model="formData!.backgroundColor" />
|
||||
</el-form-item>
|
||||
<el-form-item label="背景图片" prop="backgroundImage">
|
||||
<UploadImg v-model="formData!.backgroundImage" :limit="1">
|
||||
<template #tip>建议宽度 750px</template>
|
||||
</UploadImg>
|
||||
<el-form-item label="背景图片" prop="bgImg" v-else>
|
||||
<UploadImg v-model="formData.bgImg" :limit="1" width="56px" height="56px" />
|
||||
</el-form-item>
|
||||
<el-card class="property-group" shadow="never">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>内容(小程序)</span>
|
||||
<el-form-item prop="_local.previewMp" class="m-b-0!">
|
||||
<el-checkbox
|
||||
v-model="formData._local.previewMp"
|
||||
@change="formData._local.previewOther = !formData._local.previewMp"
|
||||
>预览</el-checkbox
|
||||
>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
<NavigationBarCellProperty v-model="formData.mpCells" is-mp />
|
||||
</el-card>
|
||||
<el-card class="property-group" shadow="never">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>内容(非小程序)</span>
|
||||
<el-form-item prop="_local.previewOther" class="m-b-0!">
|
||||
<el-checkbox
|
||||
v-model="formData._local.previewOther"
|
||||
@change="formData._local.previewMp = !formData._local.previewOther"
|
||||
>预览</el-checkbox
|
||||
>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
<NavigationBarCellProperty v-model="formData.otherCells" :is-mp="false" />
|
||||
</el-card>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { NavigationBarProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import NavigationBarCellProperty from '@/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue'
|
||||
// 导航栏属性面板
|
||||
defineOptions({ name: 'NavigationBarProperty' })
|
||||
// 表单校验
|
||||
@@ -58,6 +78,9 @@ const rules = {
|
||||
const props = defineProps<{ modelValue: NavigationBarProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
if (!formData.value._local) {
|
||||
formData.value._local = { previewMp: true, previewOther: false }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -0,0 +1,3 @@
|
||||
import { useFormCreateDesigner } from './src/useFormCreateDesigner'
|
||||
|
||||
export { useFormCreateDesigner }
|
||||
@@ -0,0 +1,15 @@
|
||||
import { useUploadFileRule } from './useUploadFileRule'
|
||||
import { useUploadImgRule } from './useUploadImgRule'
|
||||
import { useUploadImgsRule } from './useUploadImgsRule'
|
||||
import { useDictSelectRule } from './useDictSelectRule'
|
||||
import { useUserSelectRule } from './useUserSelectRule'
|
||||
import { useEditorRule } from './useEditorRule'
|
||||
|
||||
export {
|
||||
useUploadFileRule,
|
||||
useUploadImgRule,
|
||||
useUploadImgsRule,
|
||||
useDictSelectRule,
|
||||
useUserSelectRule,
|
||||
useEditorRule
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
const selectRule = [
|
||||
{ type: 'switch', field: 'multiple', title: '是否多选' },
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'disabled',
|
||||
title: '是否禁用'
|
||||
},
|
||||
{ type: 'switch', field: 'clearable', title: '是否可以清空选项' },
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'collapseTags',
|
||||
title: '多选时是否将选中值按文字的形式展示'
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'multipleLimit',
|
||||
title: '多选时用户最多可以选择的项目数,为 0 则不限制',
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'autocomplete',
|
||||
title: 'autocomplete 属性'
|
||||
},
|
||||
{ type: 'input', field: 'placeholder', title: '占位符' },
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'filterable',
|
||||
title: '是否可搜索'
|
||||
},
|
||||
{ type: 'switch', field: 'allowCreate', title: '是否允许用户创建新条目' },
|
||||
{
|
||||
type: 'input',
|
||||
field: 'noMatchText',
|
||||
title: '搜索条件无匹配时显示的文字'
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'remote',
|
||||
title: '其中的选项是否从服务器远程加载'
|
||||
},
|
||||
{
|
||||
type: 'Struct',
|
||||
field: 'remoteMethod',
|
||||
title: '自定义远程搜索方法'
|
||||
},
|
||||
{ type: 'input', field: 'noDataText', title: '选项为空时显示的文字' },
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'reserveKeyword',
|
||||
title: '多选且可搜索时,是否在选中一个选项后保留当前的搜索关键词'
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'defaultFirstOption',
|
||||
title: '在输入框按下回车,选择第一个匹配项'
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'popperAppendToBody',
|
||||
title: '是否将弹出框插入至 body 元素',
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'automaticDropdown',
|
||||
title: '对于不可搜索的 Select,是否在输入框获得焦点后自动弹出选项菜单'
|
||||
}
|
||||
]
|
||||
|
||||
export default selectRule
|
||||
@@ -0,0 +1,59 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import * as DictDataApi from '@/api/system/dict/dict.type'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
import selectRule from '@/components/FormCreate/src/config/selectRule'
|
||||
|
||||
export const useDictSelectRule = () => {
|
||||
const label = '字典选择器'
|
||||
const name = 'DictSelect'
|
||||
const dictOptions = ref<{ label: string; value: string }[]>([]) // 字典类型下拉数据
|
||||
onMounted(async () => {
|
||||
const data = await DictDataApi.getSimpleDictTypeList()
|
||||
if (!data || data.length === 0) {
|
||||
return
|
||||
}
|
||||
dictOptions.value =
|
||||
data?.map((item: DictDataApi.DictTypeVO) => ({
|
||||
label: item.name,
|
||||
value: item.type
|
||||
})) ?? []
|
||||
})
|
||||
return {
|
||||
icon: 'icon-select',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'select',
|
||||
field: 'dictType',
|
||||
title: '字典类型',
|
||||
value: '',
|
||||
options: dictOptions.value
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'valueType',
|
||||
title: '字典值类型',
|
||||
value: 'str',
|
||||
options: [
|
||||
{ label: '数字', value: 'int' },
|
||||
{ label: '字符串', value: 'str' },
|
||||
{ label: '布尔值', value: 'bool' }
|
||||
]
|
||||
},
|
||||
...selectRule
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
|
||||
export const useEditorRule = () => {
|
||||
const label = '富文本'
|
||||
const name = 'Editor'
|
||||
return {
|
||||
icon: 'icon-editor',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'input',
|
||||
field: 'height',
|
||||
title: '高度'
|
||||
},
|
||||
{ type: 'switch', field: 'readonly', title: '是否只读' }
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
|
||||
export const useUploadFileRule = () => {
|
||||
const label = '文件上传'
|
||||
const name = 'UploadFile'
|
||||
return {
|
||||
icon: 'icon-upload',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
title: '文件类型',
|
||||
value: ['doc', 'xls', 'ppt', 'txt', 'pdf'],
|
||||
options: [
|
||||
{ label: 'doc', value: 'doc' },
|
||||
{ label: 'xls', value: 'xls' },
|
||||
{ label: 'ppt', value: 'ppt' },
|
||||
{ label: 'txt', value: 'txt' },
|
||||
{ label: 'pdf', value: 'pdf' }
|
||||
],
|
||||
props: {
|
||||
multiple: true
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'autoUpload',
|
||||
title: '是否在选取文件后立即进行上传',
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
title: '拖拽上传',
|
||||
value: false
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'isShowTip',
|
||||
title: '是否显示提示',
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'limit',
|
||||
title: '数量限制',
|
||||
value: 5,
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'disabled',
|
||||
title: '是否禁用',
|
||||
value: false
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
|
||||
export const useUploadImgRule = () => {
|
||||
const label = '单图上传'
|
||||
const name = 'UploadImg'
|
||||
return {
|
||||
icon: 'icon-upload',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
title: '拖拽上传',
|
||||
value: false
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
title: '图片类型限制',
|
||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||
options: [
|
||||
{ label: 'image/apng', value: 'image/apng' },
|
||||
{ label: 'image/bmp', value: 'image/bmp' },
|
||||
{ label: 'image/gif', value: 'image/gif' },
|
||||
{ label: 'image/jpeg', value: 'image/jpeg' },
|
||||
{ label: 'image/pjpeg', value: 'image/pjpeg' },
|
||||
{ label: 'image/svg+xml', value: 'image/svg+xml' },
|
||||
{ label: 'image/tiff', value: 'image/tiff' },
|
||||
{ label: 'image/webp', value: 'image/webp' },
|
||||
{ label: 'image/x-icon', value: 'image/x-icon' }
|
||||
],
|
||||
props: {
|
||||
multiple: true
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'height',
|
||||
title: '组件高度',
|
||||
value: '150px'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'width',
|
||||
title: '组件宽度',
|
||||
value: '150px'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'borderradius',
|
||||
title: '组件边框圆角',
|
||||
value: '8px'
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'disabled',
|
||||
title: '是否显示删除按钮',
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'showBtnText',
|
||||
title: '是否显示按钮文字',
|
||||
value: true
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
|
||||
export const useUploadImgsRule = () => {
|
||||
const label = '多图上传'
|
||||
const name = 'UploadImgs'
|
||||
return {
|
||||
icon: 'icon-upload',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
title: '拖拽上传',
|
||||
value: false
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
title: '图片类型限制',
|
||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||
options: [
|
||||
{ label: 'image/apng', value: 'image/apng' },
|
||||
{ label: 'image/bmp', value: 'image/bmp' },
|
||||
{ label: 'image/gif', value: 'image/gif' },
|
||||
{ label: 'image/jpeg', value: 'image/jpeg' },
|
||||
{ label: 'image/pjpeg', value: 'image/pjpeg' },
|
||||
{ label: 'image/svg+xml', value: 'image/svg+xml' },
|
||||
{ label: 'image/tiff', value: 'image/tiff' },
|
||||
{ label: 'image/webp', value: 'image/webp' },
|
||||
{ label: 'image/x-icon', value: 'image/x-icon' }
|
||||
],
|
||||
props: {
|
||||
multiple: true
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'limit',
|
||||
title: '数量限制',
|
||||
value: 5,
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'height',
|
||||
title: '组件高度',
|
||||
value: '150px'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'width',
|
||||
title: '组件宽度',
|
||||
value: '150px'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'borderradius',
|
||||
title: '组件边框圆角',
|
||||
value: '8px'
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
import selectRule from '@/components/FormCreate/src/config/selectRule'
|
||||
|
||||
export const useUserSelectRule = () => {
|
||||
const label = '用户选择器'
|
||||
const name = 'UserSelect'
|
||||
return {
|
||||
icon: 'icon-select',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [makeRequiredRule(), ...selectRule])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
useDictSelectRule,
|
||||
useEditorRule,
|
||||
useUploadFileRule,
|
||||
useUploadImgRule,
|
||||
useUploadImgsRule,
|
||||
useUserSelectRule
|
||||
} from './config'
|
||||
import { Ref } from 'vue'
|
||||
|
||||
/**
|
||||
* 表单设计器增强 hook
|
||||
* 新增
|
||||
* - 文件上传
|
||||
* - 单图上传
|
||||
* - 多图上传
|
||||
* - 字典选择器
|
||||
* - 系统用户选择器
|
||||
* - 富文本
|
||||
*/
|
||||
export const useFormCreateDesigner = (designer: Ref) => {
|
||||
const editorRule = useEditorRule()
|
||||
const uploadFileRule = useUploadFileRule()
|
||||
const uploadImgRule = useUploadImgRule()
|
||||
const uploadImgsRule = useUploadImgsRule()
|
||||
const dictSelectRule = useDictSelectRule()
|
||||
const userSelectRule = useUserSelectRule()
|
||||
|
||||
onMounted(() => {
|
||||
// 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代
|
||||
designer.value?.removeMenuItem('upload')
|
||||
// 移除自带的富文本组件规则,使用 editorRule 替代
|
||||
designer.value?.removeMenuItem('fc-editor')
|
||||
const components = [
|
||||
editorRule,
|
||||
uploadFileRule,
|
||||
uploadImgRule,
|
||||
uploadImgsRule,
|
||||
dictSelectRule,
|
||||
userSelectRule
|
||||
]
|
||||
components.forEach((component) => {
|
||||
// 插入组件规则
|
||||
designer.value?.addComponent(component)
|
||||
// 插入拖拽按钮到 `main` 分类下
|
||||
designer.value?.appendMenuItem('main', {
|
||||
icon: component.icon,
|
||||
name: component.name,
|
||||
label: component.label
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// TODO puhui999: 借鉴一下 form-create-designer utils 方法 🤣 (导入不了只能先 copy 过来用下)
|
||||
export function makeRequiredRule() {
|
||||
return {
|
||||
type: 'Required',
|
||||
field: 'formCreate$required',
|
||||
title: '是否必填'
|
||||
}
|
||||
}
|
||||
|
||||
export const localeProps = (t, prefix, rules) => {
|
||||
return rules.map((rule) => {
|
||||
if (rule.field === 'formCreate$required') {
|
||||
rule.title = t('props.required') || rule.title
|
||||
} else if (rule.field && rule.field !== '_optionType') {
|
||||
rule.title = t('components.' + prefix + '.' + rule.field) || rule.title
|
||||
}
|
||||
return rule
|
||||
})
|
||||
}
|
||||
|
||||
export function upper(str) {
|
||||
return str.replace(str[0], str[0].toLocaleUpperCase())
|
||||
}
|
||||
|
||||
export function makeOptionsRule(t, to, userOptions) {
|
||||
console.log(userOptions[0])
|
||||
const options = [
|
||||
{ label: t('props.optionsType.struct'), value: 0 },
|
||||
{ label: t('props.optionsType.json'), value: 1 },
|
||||
{ label: '用户数据', value: 2 }
|
||||
]
|
||||
|
||||
const control = [
|
||||
{
|
||||
value: 0,
|
||||
rule: [
|
||||
{
|
||||
type: 'TableOptions',
|
||||
field: 'formCreate' + upper(to).replace('.', '>'),
|
||||
props: { defaultValue: [] }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
rule: [
|
||||
{
|
||||
type: 'Struct',
|
||||
field: 'formCreate' + upper(to).replace('.', '>'),
|
||||
props: { defaultValue: [] }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
rule: [
|
||||
{
|
||||
type: 'TableOptions',
|
||||
field: 'formCreate' + upper(to).replace('.', '>'),
|
||||
props: { modelValue: [] }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
options.splice(0, 0)
|
||||
control.push()
|
||||
|
||||
return {
|
||||
type: 'radio',
|
||||
title: t('props.options'),
|
||||
field: '_optionType',
|
||||
value: 0,
|
||||
options,
|
||||
props: {
|
||||
type: 'button'
|
||||
},
|
||||
control
|
||||
}
|
||||
}
|
||||
@@ -189,7 +189,7 @@ const emit = defineEmits(['update:modelValue', 'hotAreaSelected'])
|
||||
const emitUpdateModelValue = () => emit('update:modelValue', hotAreas)
|
||||
|
||||
// 热区选中
|
||||
const selectedHotAreaIndex = ref(-1)
|
||||
const selectedHotAreaIndex = ref(0)
|
||||
const handleHotAreaSelected = (hotArea: Rect, index: number) => {
|
||||
selectedHotAreaIndex.value = index
|
||||
emit('hotAreaSelected', hotArea, index)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { OperateLogV2VO } from '@/api/system/operatelog'
|
||||
import { OperateLogVO } from '@/api/system/operatelog'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import { DICT_TYPE, getDictLabel, getDictObj } from '@/utils/dict'
|
||||
import { ElTag } from 'element-plus'
|
||||
@@ -31,7 +31,7 @@ import { ElTag } from 'element-plus'
|
||||
defineOptions({ name: 'OperateLogV2' })
|
||||
|
||||
interface Props {
|
||||
logList: OperateLogV2VO[] // 操作日志列表
|
||||
logList: OperateLogVO[] // 操作日志列表
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
|
||||
@@ -53,7 +53,7 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:page', 'update:limit', 'pagination', 'pagination'])
|
||||
const emit = defineEmits(['update:page', 'update:limit', 'pagination'])
|
||||
const currentPage = computed({
|
||||
get() {
|
||||
return props.page
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
/* stylelint-disable order/properties-order */
|
||||
<template>
|
||||
<div class="add-node-btn-box">
|
||||
<div class="add-node-btn">
|
||||
<el-popover placement="right-start" v-model="visible" width="auto">
|
||||
<div class="add-node-popover-body">
|
||||
<a class="add-node-popover-item approver" @click="addType(1)">
|
||||
<div class="item-wrapper">
|
||||
<span class="iconfont"></span>
|
||||
</div>
|
||||
<p>审批人</p>
|
||||
</a>
|
||||
<a class="add-node-popover-item notifier" @click="addType(2)">
|
||||
<div class="item-wrapper">
|
||||
<span class="iconfont"></span>
|
||||
</div>
|
||||
<p>抄送人</p>
|
||||
</a>
|
||||
<a class="add-node-popover-item condition" @click="addType(4)">
|
||||
<div class="item-wrapper">
|
||||
<span class="iconfont"></span>
|
||||
</div>
|
||||
<p>条件分支</p>
|
||||
</a>
|
||||
</div>
|
||||
<template #reference>
|
||||
<button class="btn" type="button">
|
||||
<span class="iconfont"></span>
|
||||
</button>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
let props = defineProps({
|
||||
childNodeP: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
let emits = defineEmits(['update:childNodeP'])
|
||||
let visible = ref(false)
|
||||
const addType = (type) => {
|
||||
visible.value = false
|
||||
if (type != 4) {
|
||||
var data
|
||||
if (type == 1) {
|
||||
data = {
|
||||
nodeName: '审核人',
|
||||
error: true,
|
||||
type: 1,
|
||||
settype: 1,
|
||||
selectMode: 0,
|
||||
selectRange: 0,
|
||||
directorLevel: 1,
|
||||
examineMode: 1,
|
||||
noHanderAction: 1,
|
||||
examineEndDirectorLevel: 0,
|
||||
childNode: props.childNodeP,
|
||||
nodeUserList: []
|
||||
}
|
||||
} else if (type == 2) {
|
||||
data = {
|
||||
nodeName: '抄送人',
|
||||
type: 2,
|
||||
ccSelfSelectFlag: 1,
|
||||
childNode: props.childNodeP,
|
||||
nodeUserList: []
|
||||
}
|
||||
}
|
||||
emits('update:childNodeP', data)
|
||||
} else {
|
||||
emits('update:childNodeP', {
|
||||
nodeName: '路由',
|
||||
type: 4,
|
||||
childNode: null,
|
||||
conditionNodes: [
|
||||
{
|
||||
nodeName: '条件1',
|
||||
error: true,
|
||||
type: 3,
|
||||
priorityLevel: 1,
|
||||
conditionList: [],
|
||||
nodeUserList: [],
|
||||
childNode: props.childNodeP
|
||||
},
|
||||
{
|
||||
nodeName: '条件2',
|
||||
type: 3,
|
||||
priorityLevel: 2,
|
||||
conditionList: [],
|
||||
nodeUserList: [],
|
||||
childNode: null
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.add-node-btn-box {
|
||||
width: 240px;
|
||||
display: inline-flex;
|
||||
-ms-flex-negative: 0;
|
||||
flex-shrink: 0;
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
margin: auto;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background-color: #cacaca;
|
||||
}
|
||||
|
||||
.add-node-btn {
|
||||
user-select: none;
|
||||
width: 240px;
|
||||
padding: 20px 0 32px;
|
||||
display: flex;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
-webkit-box-flex: 1;
|
||||
flex-grow: 1;
|
||||
|
||||
.btn {
|
||||
outline: none;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: #3296fa;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
border: none;
|
||||
line-height: 30px;
|
||||
-webkit-transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
|
||||
.iconfont {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.3);
|
||||
box-shadow: 0 13px 27px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: none;
|
||||
background: #1e83e9;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-node-popover-body {
|
||||
display: flex;
|
||||
|
||||
.add-node-popover-item {
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
color: #191f25 !important;
|
||||
|
||||
.item-wrapper {
|
||||
user-select: none;
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin-bottom: 5px;
|
||||
background: #fff;
|
||||
border: 1px solid #e2e2e2;
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
|
||||
.iconfont {
|
||||
font-size: 35px;
|
||||
line-height: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
&.approver {
|
||||
.item-wrapper {
|
||||
color: #ff943e;
|
||||
}
|
||||
}
|
||||
|
||||
&.notifier {
|
||||
.item-wrapper {
|
||||
color: #3296fa;
|
||||
}
|
||||
}
|
||||
|
||||
&.condition {
|
||||
.item-wrapper {
|
||||
color: #15bc83;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.item-wrapper {
|
||||
background: #3296fa;
|
||||
box-shadow: 0 10px 20px 0 rgba(50, 150, 250, 0.4);
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
.item-wrapper {
|
||||
box-shadow: none;
|
||||
background: #eaeaea;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,297 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<!--
|
||||
* @Date: 2022-09-21 14:41:53
|
||||
* @LastEditors: StavinLi 495727881@qq.com
|
||||
* @LastEditTime: 2023-05-24 15:20:24
|
||||
* @FilePath: /Workflow-Vue3/src/components/nodeWrap.vue
|
||||
-->
|
||||
<template>
|
||||
<div class="node-wrap" v-if="nodeConfig.type < 3">
|
||||
<div class="node-wrap-box" :class="(nodeConfig.type == 0 ? 'start-node ' : '') +(isTried && nodeConfig.error ? 'active error' : '')">
|
||||
<div class="title" :style="`background: rgb(${bgColors[nodeConfig.type]});`">
|
||||
<span v-if="nodeConfig.type == 0">{{ nodeConfig.nodeName }}</span>
|
||||
<template v-else>
|
||||
<span class="iconfont">{{nodeConfig.type == 1?'':''}}</span>
|
||||
<input
|
||||
v-if="isInput"
|
||||
type="text"
|
||||
class="ant-input editable-title-input"
|
||||
@blur="blurEvent()"
|
||||
@focus="$event.currentTarget.select()"
|
||||
v-focus
|
||||
v-model="nodeConfig.nodeName"
|
||||
:placeholder="defaultText"
|
||||
/>
|
||||
<span v-else class="editable-title" @click="clickEvent()">{{ nodeConfig.nodeName }}</span>
|
||||
<i class="anticon anticon-close close" @click="delNode"></i>
|
||||
</template>
|
||||
</div>
|
||||
<div class="content" @click="setPerson">
|
||||
<div class="text">
|
||||
<span class="placeholder" v-if="!showText">请选择{{defaultText}}</span>
|
||||
{{showText}}
|
||||
</div>
|
||||
<i class="anticon anticon-right arrow"></i>
|
||||
</div>
|
||||
<div class="error_tip" v-if="isTried && nodeConfig.error">
|
||||
<i class="anticon anticon-exclamation-circle"></i>
|
||||
</div>
|
||||
</div>
|
||||
<addNode v-model:childNodeP="nodeConfig.childNode" />
|
||||
</div>
|
||||
<div class="branch-wrap" v-if="nodeConfig.type == 4">
|
||||
<div class="branch-box-wrap">
|
||||
<div class="branch-box">
|
||||
<button class="add-branch" @click="addTerm">添加条件</button>
|
||||
<div class="col-box" v-for="(item, index) in nodeConfig.conditionNodes" :key="index">
|
||||
<div class="condition-node">
|
||||
<div class="condition-node-box">
|
||||
<div class="auto-judge" :class="isTried && item.error ? 'error active' : ''">
|
||||
<div class="sort-left" v-if="index != 0" @click="arrTransfer(index, -1)"><</div>
|
||||
<div class="title-wrapper">
|
||||
<input
|
||||
v-if="isInputList[index]"
|
||||
type="text"
|
||||
class="ant-input editable-title-input"
|
||||
@blur="blurEvent(index)"
|
||||
@focus="$event.currentTarget.select()"
|
||||
v-model="item.nodeName"
|
||||
/>
|
||||
<span v-else class="editable-title" @click="clickEvent(index)">{{ item.nodeName }}</span>
|
||||
<span class="priority-title" @click="setPerson(item.priorityLevel)">优先级{{ item.priorityLevel }}</span>
|
||||
<i class="anticon anticon-close close" @click="delTerm(index)"></i>
|
||||
</div>
|
||||
<div class="sort-right" v-if="index != nodeConfig.conditionNodes.length - 1" @click="arrTransfer(index)">></div>
|
||||
<div class="content" @click="setPerson(item.priorityLevel)">{{ conditionStr(nodeConfig, index) }}</div>
|
||||
<div class="error_tip" v-if="isTried && item.error">
|
||||
<i class="anticon anticon-exclamation-circle"></i>
|
||||
</div>
|
||||
</div>
|
||||
<addNode v-model:childNodeP="item.childNode" />
|
||||
</div>
|
||||
</div>
|
||||
<nodeWrap v-if="item.childNode" v-model:nodeConfig="item.childNode" />
|
||||
<template v-if="index == 0">
|
||||
<div class="top-left-cover-line"></div>
|
||||
<div class="bottom-left-cover-line"></div>
|
||||
</template>
|
||||
<template v-if="index == nodeConfig.conditionNodes.length - 1">
|
||||
<div class="top-right-cover-line"></div>
|
||||
<div class="bottom-right-cover-line"></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<addNode v-model:childNodeP="nodeConfig.childNode" />
|
||||
</div>
|
||||
</div>
|
||||
<nodeWrap v-if="nodeConfig.childNode" v-model:nodeConfig="nodeConfig.childNode" />
|
||||
</template>
|
||||
<script setup>
|
||||
import addNode from './addNode.vue'
|
||||
import { onMounted, ref, watch, getCurrentInstance, computed } from 'vue'
|
||||
import {
|
||||
arrToStr,
|
||||
conditionStr,
|
||||
setApproverStr,
|
||||
copyerStr,
|
||||
bgColors,
|
||||
placeholderList
|
||||
} from './util'
|
||||
import { useWorkFlowStoreWithOut } from '@/store/modules/simpleWorkflow'
|
||||
let _uid = getCurrentInstance().uid
|
||||
|
||||
let props = defineProps({
|
||||
nodeConfig: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
flowPermission: {
|
||||
type: Object,
|
||||
// eslint-disable-next-line vue/require-valid-default-prop
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
let defaultText = computed(() => {
|
||||
return placeholderList[props.nodeConfig.type]
|
||||
})
|
||||
let showText = computed(() => {
|
||||
if (props.nodeConfig.type == 0) return arrToStr(props.flowPermission) || '所有人'
|
||||
if (props.nodeConfig.type == 1) return setApproverStr(props.nodeConfig)
|
||||
return copyerStr(props.nodeConfig)
|
||||
})
|
||||
|
||||
let isInputList = ref([])
|
||||
let isInput = ref(false)
|
||||
const resetConditionNodesErr = () => {
|
||||
for (var i = 0; i < props.nodeConfig.conditionNodes.length; i++) {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes[i].error =
|
||||
conditionStr(props.nodeConfig, i) == '请设置条件' &&
|
||||
i != props.nodeConfig.conditionNodes.length - 1
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
if (props.nodeConfig.type == 1) {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.error = !setApproverStr(props.nodeConfig)
|
||||
} else if (props.nodeConfig.type == 2) {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.error = !copyerStr(props.nodeConfig)
|
||||
} else if (props.nodeConfig.type == 4) {
|
||||
resetConditionNodesErr()
|
||||
}
|
||||
})
|
||||
let emits = defineEmits(['update:flowPermission', 'update:nodeConfig'])
|
||||
let store = useWorkFlowStoreWithOut()
|
||||
let {
|
||||
setPromoter,
|
||||
setApprover,
|
||||
setCopyer,
|
||||
setCondition,
|
||||
setFlowPermission,
|
||||
setApproverConfig,
|
||||
setCopyerConfig,
|
||||
setConditionsConfig
|
||||
} = store
|
||||
let isTried = computed(() => store.isTried)
|
||||
let flowPermission1 = computed(() => store.flowPermission1)
|
||||
let approverConfig1 = computed(() => store.approverConfig1)
|
||||
let copyerConfig1 = computed(() => store.copyerConfig1)
|
||||
let conditionsConfig1 = computed(() => store.conditionsConfig1)
|
||||
watch(flowPermission1, (flow) => {
|
||||
if (flow.flag && flow.id === _uid) {
|
||||
emits('update:flowPermission', flow.value)
|
||||
}
|
||||
})
|
||||
watch(approverConfig1, (approver) => {
|
||||
if (approver.flag && approver.id === _uid) {
|
||||
emits('update:nodeConfig', approver.value)
|
||||
}
|
||||
})
|
||||
watch(copyerConfig1, (copyer) => {
|
||||
if (copyer.flag && copyer.id === _uid) {
|
||||
emits('update:nodeConfig', copyer.value)
|
||||
}
|
||||
})
|
||||
watch(conditionsConfig1, (condition) => {
|
||||
if (condition.flag && condition.id === _uid) {
|
||||
emits('update:nodeConfig', condition.value)
|
||||
}
|
||||
})
|
||||
|
||||
const clickEvent = (index) => {
|
||||
if (index || index === 0) {
|
||||
isInputList.value[index] = true
|
||||
} else {
|
||||
isInput.value = true
|
||||
}
|
||||
}
|
||||
const blurEvent = (index) => {
|
||||
if (index || index === 0) {
|
||||
isInputList.value[index] = false
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes[index].nodeName =
|
||||
props.nodeConfig.conditionNodes[index].nodeName || '条件'
|
||||
} else {
|
||||
isInput.value = false
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.nodeName = props.nodeConfig.nodeName || defaultText
|
||||
}
|
||||
}
|
||||
const delNode = () => {
|
||||
emits('update:nodeConfig', props.nodeConfig.childNode)
|
||||
}
|
||||
const addTerm = () => {
|
||||
let len = props.nodeConfig.conditionNodes.length + 1
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes.push({
|
||||
nodeName: '条件' + len,
|
||||
type: 3,
|
||||
priorityLevel: len,
|
||||
conditionList: [],
|
||||
nodeUserList: [],
|
||||
childNode: null
|
||||
})
|
||||
resetConditionNodesErr()
|
||||
emits('update:nodeConfig', props.nodeConfig)
|
||||
}
|
||||
const delTerm = (index) => {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes.splice(index, 1)
|
||||
props.nodeConfig.conditionNodes.map((item, index) => {
|
||||
item.priorityLevel = index + 1
|
||||
item.nodeName = `条件${index + 1}`
|
||||
})
|
||||
resetConditionNodesErr()
|
||||
emits('update:nodeConfig', props.nodeConfig)
|
||||
if (props.nodeConfig.conditionNodes.length == 1) {
|
||||
if (props.nodeConfig.childNode) {
|
||||
if (props.nodeConfig.conditionNodes[0].childNode) {
|
||||
reData(props.nodeConfig.conditionNodes[0].childNode, props.nodeConfig.childNode)
|
||||
} else {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes[0].childNode = props.nodeConfig.childNode
|
||||
}
|
||||
}
|
||||
emits('update:nodeConfig', props.nodeConfig.conditionNodes[0].childNode)
|
||||
}
|
||||
}
|
||||
const reData = (data, addData) => {
|
||||
if (!data.childNode) {
|
||||
data.childNode = addData
|
||||
} else {
|
||||
reData(data.childNode, addData)
|
||||
}
|
||||
}
|
||||
const setPerson = (priorityLevel) => {
|
||||
var { type } = props.nodeConfig
|
||||
if (type == 0) {
|
||||
setPromoter(true)
|
||||
setFlowPermission({
|
||||
value: props.flowPermission,
|
||||
flag: false,
|
||||
id: _uid
|
||||
})
|
||||
} else if (type == 1) {
|
||||
setApprover(true)
|
||||
setApproverConfig({
|
||||
value: {
|
||||
...JSON.parse(JSON.stringify(props.nodeConfig)),
|
||||
...{ settype: props.nodeConfig.settype ? props.nodeConfig.settype : 1 }
|
||||
},
|
||||
flag: false,
|
||||
id: _uid
|
||||
})
|
||||
} else if (type == 2) {
|
||||
setCopyer(true)
|
||||
setCopyerConfig({
|
||||
value: JSON.parse(JSON.stringify(props.nodeConfig)),
|
||||
flag: false,
|
||||
id: _uid
|
||||
})
|
||||
} else {
|
||||
setCondition(true)
|
||||
setConditionsConfig({
|
||||
value: JSON.parse(JSON.stringify(props.nodeConfig)),
|
||||
priorityLevel,
|
||||
flag: false,
|
||||
id: _uid
|
||||
})
|
||||
}
|
||||
}
|
||||
const arrTransfer = (index, type = 1) => {
|
||||
//向左-1,向右1
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes[index] = props.nodeConfig.conditionNodes.splice(
|
||||
index + type,
|
||||
1,
|
||||
props.nodeConfig.conditionNodes[index]
|
||||
)[0]
|
||||
props.nodeConfig.conditionNodes.map((item, index) => {
|
||||
item.priorityLevel = index + 1
|
||||
})
|
||||
resetConditionNodesErr()
|
||||
emits('update:nodeConfig', props.nodeConfig)
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* todo
|
||||
*/
|
||||
export const arrToStr = (arr?: [{ name: string }]) => {
|
||||
if (arr) {
|
||||
return arr
|
||||
.map((item) => {
|
||||
return item.name
|
||||
})
|
||||
.toString()
|
||||
}
|
||||
}
|
||||
|
||||
export const setApproverStr = (nodeConfig: any) => {
|
||||
if (nodeConfig.settype == 1) {
|
||||
if (nodeConfig.nodeUserList.length == 1) {
|
||||
return nodeConfig.nodeUserList[0].name
|
||||
} else if (nodeConfig.nodeUserList.length > 1) {
|
||||
if (nodeConfig.examineMode == 1) {
|
||||
return arrToStr(nodeConfig.nodeUserList)
|
||||
} else if (nodeConfig.examineMode == 2) {
|
||||
return nodeConfig.nodeUserList.length + '人会签'
|
||||
}
|
||||
}
|
||||
} else if (nodeConfig.settype == 2) {
|
||||
const level =
|
||||
nodeConfig.directorLevel == 1 ? '直接主管' : '第' + nodeConfig.directorLevel + '级主管'
|
||||
if (nodeConfig.examineMode == 1) {
|
||||
return level
|
||||
} else if (nodeConfig.examineMode == 2) {
|
||||
return level + '会签'
|
||||
}
|
||||
} else if (nodeConfig.settype == 4) {
|
||||
if (nodeConfig.selectRange == 1) {
|
||||
return '发起人自选'
|
||||
} else {
|
||||
if (nodeConfig.nodeUserList.length > 0) {
|
||||
if (nodeConfig.selectRange == 2) {
|
||||
return '发起人自选'
|
||||
} else {
|
||||
return '发起人从' + nodeConfig.nodeUserList[0].name + '中自选'
|
||||
}
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
} else if (nodeConfig.settype == 5) {
|
||||
return '发起人自己'
|
||||
} else if (nodeConfig.settype == 7) {
|
||||
return '从直接主管到通讯录中级别最高的第' + nodeConfig.examineEndDirectorLevel + '个层级主管'
|
||||
}
|
||||
}
|
||||
|
||||
export const copyerStr = (nodeConfig: any) => {
|
||||
if (nodeConfig.nodeUserList.length != 0) {
|
||||
return arrToStr(nodeConfig.nodeUserList)
|
||||
} else {
|
||||
if (nodeConfig.ccSelfSelectFlag == 1) {
|
||||
return '发起人自选'
|
||||
}
|
||||
}
|
||||
}
|
||||
export const conditionStr = (nodeConfig, index) => {
|
||||
const { conditionList, nodeUserList } = nodeConfig.conditionNodes[index]
|
||||
if (conditionList.length == 0) {
|
||||
return index == nodeConfig.conditionNodes.length - 1 &&
|
||||
nodeConfig.conditionNodes[0].conditionList.length != 0
|
||||
? '其他条件进入此流程'
|
||||
: '请设置条件'
|
||||
} else {
|
||||
let str = ''
|
||||
for (let i = 0; i < conditionList.length; i++) {
|
||||
const {
|
||||
columnId,
|
||||
columnType,
|
||||
showType,
|
||||
showName,
|
||||
optType,
|
||||
zdy1,
|
||||
opt1,
|
||||
zdy2,
|
||||
opt2,
|
||||
fixedDownBoxValue
|
||||
} = conditionList[i]
|
||||
if (columnId == 0) {
|
||||
if (nodeUserList.length != 0) {
|
||||
str += '发起人属于:'
|
||||
str +=
|
||||
nodeUserList
|
||||
.map((item) => {
|
||||
return item.name
|
||||
})
|
||||
.join('或') + ' 并且 '
|
||||
}
|
||||
}
|
||||
if (columnType == 'String' && showType == '3') {
|
||||
if (zdy1) {
|
||||
str += showName + '属于:' + dealStr(zdy1, JSON.parse(fixedDownBoxValue)) + ' 并且 '
|
||||
}
|
||||
}
|
||||
if (columnType == 'Double') {
|
||||
if (optType != 6 && zdy1) {
|
||||
const optTypeStr = ['', '<', '>', '≤', '=', '≥'][optType]
|
||||
str += `${showName} ${optTypeStr} ${zdy1} 并且 `
|
||||
} else if (optType == 6 && zdy1 && zdy2) {
|
||||
str += `${zdy1} ${opt1} ${showName} ${opt2} ${zdy2} 并且 `
|
||||
}
|
||||
}
|
||||
}
|
||||
return str ? str.substring(0, str.length - 4) : '请设置条件'
|
||||
}
|
||||
}
|
||||
|
||||
export const dealStr = (str: string, obj) => {
|
||||
const arr = []
|
||||
const list = str.split(',')
|
||||
for (const elem in obj) {
|
||||
list.map((item) => {
|
||||
if (item == elem) {
|
||||
arr.push(obj[elem].value)
|
||||
}
|
||||
})
|
||||
}
|
||||
return arr.join('或')
|
||||
}
|
||||
|
||||
export const removeEle = (arr, elem, key = 'id') => {
|
||||
let includesIndex
|
||||
arr.map((item, index) => {
|
||||
if (item[key] == elem[key]) {
|
||||
includesIndex = index
|
||||
}
|
||||
})
|
||||
arr.splice(includesIndex, 1)
|
||||
}
|
||||
|
||||
export const bgColors = ['87, 106, 149', '255, 148, 62', '50, 150, 250']
|
||||
export const placeholderList = ['发起人', '审核人', '抄送人']
|
||||
export const setTypes = [
|
||||
{ value: 1, label: '指定成员' },
|
||||
{ value: 2, label: '主管' },
|
||||
{ value: 4, label: '发起人自选' },
|
||||
{ value: 5, label: '发起人自己' },
|
||||
{ value: 7, label: '连续多级主管' }
|
||||
]
|
||||
|
||||
export const selectModes = [
|
||||
{ value: 1, label: '选一个人' },
|
||||
{ value: 2, label: '选多个人' }
|
||||
]
|
||||
|
||||
export const selectRanges = [
|
||||
{ value: 1, label: '全公司' },
|
||||
{ value: 2, label: '指定成员' },
|
||||
{ value: 3, label: '指定角色' }
|
||||
]
|
||||
|
||||
export const optTypes = [
|
||||
{ value: '1', label: '小于' },
|
||||
{ value: '2', label: '大于' },
|
||||
{ value: '3', label: '小于等于' },
|
||||
{ value: '4', label: '等于' },
|
||||
{ value: '5', label: '大于等于' },
|
||||
{ value: '6', label: '介于两个数之间' }
|
||||
]
|
||||
File diff suppressed because it is too large.
Load diff
@@ -6,7 +6,9 @@
|
||||
:action="uploadUrl"
|
||||
:auto-upload="autoUpload"
|
||||
:before-upload="beforeUpload"
|
||||
:disabled="disabled"
|
||||
:drag="drag"
|
||||
:http-request="httpRequest"
|
||||
:limit="props.limit"
|
||||
:multiple="props.limit > 1"
|
||||
:on-error="excelUploadError"
|
||||
@@ -15,15 +17,14 @@
|
||||
:on-remove="handleRemove"
|
||||
:on-success="handleFileSuccess"
|
||||
:show-file-list="true"
|
||||
:http-request="httpRequest"
|
||||
class="upload-file-uploader"
|
||||
name="file"
|
||||
>
|
||||
<el-button type="primary">
|
||||
<el-button v-if="!disabled" type="primary">
|
||||
<Icon icon="ep:upload-filled" />
|
||||
选取文件
|
||||
</el-button>
|
||||
<template v-if="isShowTip" #tip>
|
||||
<template v-if="isShowTip && !disabled" #tip>
|
||||
<div style="font-size: 8px">
|
||||
大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
|
||||
</div>
|
||||
@@ -31,6 +32,25 @@
|
||||
格式为 <b style="color: #f56c6c">{{ fileType.join('/') }}</b> 的文件
|
||||
</div>
|
||||
</template>
|
||||
<template #file="row">
|
||||
<div class="flex items-center">
|
||||
<span>{{ row.file.name }}</span>
|
||||
<div class="ml-10px">
|
||||
<el-link
|
||||
:href="row.file.url"
|
||||
:underline="false"
|
||||
download
|
||||
target="_blank"
|
||||
type="primary"
|
||||
>
|
||||
下载
|
||||
</el-link>
|
||||
</div>
|
||||
<div class="ml-10px">
|
||||
<el-button link type="danger" @click="handleRemove(row.file)"> 删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
@@ -48,13 +68,13 @@ const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
|
||||
title: propTypes.string.def('文件上传'),
|
||||
fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']), // 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||
fileSize: propTypes.number.def(5), // 大小限制(MB)
|
||||
limit: propTypes.number.def(5), // 数量限制
|
||||
autoUpload: propTypes.bool.def(true), // 自动上传
|
||||
drag: propTypes.bool.def(false), // 拖拽上传
|
||||
isShowTip: propTypes.bool.def(true) // 是否显示提示
|
||||
isShowTip: propTypes.bool.def(true), // 是否显示提示
|
||||
disabled: propTypes.bool.def(false) // 是否禁用上传组件 ==> 非必传(默认为 false)
|
||||
})
|
||||
|
||||
// ========== 上传相关 ==========
|
||||
|
||||
@@ -6,17 +6,18 @@
|
||||
:action="uploadUrl"
|
||||
:before-upload="beforeUpload"
|
||||
:class="['upload', drag ? 'no-border' : '']"
|
||||
:disabled="disabled"
|
||||
:drag="drag"
|
||||
:http-request="httpRequest"
|
||||
:multiple="false"
|
||||
:on-error="uploadError"
|
||||
:on-success="uploadSuccess"
|
||||
:show-file-list="false"
|
||||
:http-request="httpRequest"
|
||||
>
|
||||
<template v-if="modelValue">
|
||||
<img :src="modelValue" class="upload-image" />
|
||||
<div class="upload-handle" @click.stop>
|
||||
<div class="handle-icon" @click="editImg" v-if="!disabled">
|
||||
<div v-if="!disabled" class="handle-icon" @click="editImg">
|
||||
<Icon icon="ep:edit" />
|
||||
<span v-if="showBtnText">{{ t('action.edit') }}</span>
|
||||
</div>
|
||||
@@ -77,10 +78,8 @@ const props = defineProps({
|
||||
height: propTypes.string.def('150px'), // 组件高度 ==> 非必传(默认为 150px)
|
||||
width: propTypes.string.def('150px'), // 组件宽度 ==> 非必传(默认为 150px)
|
||||
borderradius: propTypes.string.def('8px'), // 组件边框圆角 ==> 非必传(默认为 8px)
|
||||
// 是否显示删除按钮
|
||||
showDelete: propTypes.bool.def(true),
|
||||
// 是否显示按钮文字
|
||||
showBtnText: propTypes.bool.def(true)
|
||||
showDelete: propTypes.bool.def(true), // 是否显示删除按钮
|
||||
showBtnText: propTypes.bool.def(true) // 是否显示按钮文字
|
||||
})
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
:action="uploadUrl"
|
||||
:before-upload="beforeUpload"
|
||||
:class="['upload', drag ? 'no-border' : '']"
|
||||
:disabled="disabled"
|
||||
:drag="drag"
|
||||
:http-request="httpRequest"
|
||||
:limit="limit"
|
||||
:multiple="true"
|
||||
:on-error="uploadError"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="uploadSuccess"
|
||||
:http-request="httpRequest"
|
||||
list-type="picture-card"
|
||||
>
|
||||
<div class="upload-empty">
|
||||
|
||||
@@ -17,7 +17,11 @@ export const useUpload = () => {
|
||||
// 1.2 获取文件预签名地址
|
||||
const presignedInfo = await FileApi.getFilePresignedUrl(fileName)
|
||||
// 1.3 上传文件(不能使用 ElUpload 的 ajaxUpload 方法的原因:其使用的是 FormData 上传,Minio 不支持)
|
||||
return axios.put(presignedInfo.uploadUrl, options.file).then(() => {
|
||||
return axios.put(presignedInfo.uploadUrl, options.file, {
|
||||
headers: {
|
||||
'Content-Type': options.file.type,
|
||||
}
|
||||
}).then(() => {
|
||||
// 1.4. 记录文件信息到后端(异步)
|
||||
createFile(presignedInfo, fileName, options.file)
|
||||
// 通知成功,数据格式保持与后端上传的返回结果一致
|
||||
|
||||
@@ -436,7 +436,7 @@ const initBpmnModeler = () => {
|
||||
|
||||
// bpmnModeler.createDiagram()
|
||||
|
||||
console.log(bpmnModeler, 'bpmnModeler111111')
|
||||
// console.log(bpmnModeler, 'bpmnModeler111111')
|
||||
emit('init-finished', bpmnModeler)
|
||||
initModelListeners()
|
||||
}
|
||||
@@ -666,10 +666,10 @@ const previewProcessJson = () => {
|
||||
}
|
||||
/* ------------------------------------------------ 芋道源码 methods ------------------------------------------------------ */
|
||||
const processSave = async () => {
|
||||
console.log(bpmnModeler, 'bpmnModelerbpmnModelerbpmnModelerbpmnModeler')
|
||||
// console.log(bpmnModeler, 'bpmnModelerbpmnModelerbpmnModelerbpmnModeler')
|
||||
const { err, xml } = await bpmnModeler.saveXML()
|
||||
console.log(err, 'errerrerrerrerr')
|
||||
console.log(xml, 'xmlxmlxmlxmlxml')
|
||||
// console.log(err, 'errerrerrerrerr')
|
||||
// console.log(xml, 'xmlxmlxmlxmlxml')
|
||||
// 读取异常时抛出异常
|
||||
if (err) {
|
||||
// this.$modal.msgError('保存模型失败,请重试!')
|
||||
|
||||
@@ -115,19 +115,19 @@ const highlightDiagram = async () => {
|
||||
if (!task) {
|
||||
return
|
||||
}
|
||||
//进行中的任务已经高亮过了,则不高亮后面的任务了
|
||||
// 进行中的任务已经高亮过了,则不高亮后面的任务了
|
||||
if (findProcessTask) {
|
||||
removeTaskDefinitionKeyList.push(n.id)
|
||||
return
|
||||
}
|
||||
// 高亮任务
|
||||
canvas.addMarker(n.id, getResultCss(task.result))
|
||||
canvas.addMarker(n.id, getResultCss(task.status))
|
||||
//标记是否高亮了进行中任务
|
||||
if (task.result === 1) {
|
||||
if (task.status === 1) {
|
||||
findProcessTask = true
|
||||
}
|
||||
// 如果非通过,就不走后面的线条了
|
||||
if (task.result !== 2) {
|
||||
if (task.status !== 2) {
|
||||
return
|
||||
}
|
||||
// 处理 outgoing 出线
|
||||
@@ -194,6 +194,7 @@ const highlightDiagram = async () => {
|
||||
})
|
||||
} else if (n.$type === 'bpmn:StartEvent') {
|
||||
// 开始节点
|
||||
canvas.addMarker(n.id, 'highlight')
|
||||
n.outgoing?.forEach((nn) => {
|
||||
// outgoing 例如说【bpmn:SequenceFlow】连线
|
||||
// 获得连线是否有指向目标。如果有,则进行高亮
|
||||
@@ -205,10 +206,10 @@ const highlightDiagram = async () => {
|
||||
})
|
||||
} else if (n.$type === 'bpmn:EndEvent') {
|
||||
// 结束节点
|
||||
if (!processInstance.value || processInstance.value.result === 1) {
|
||||
if (!processInstance.value || processInstance.value.status === 1) {
|
||||
return
|
||||
}
|
||||
canvas.addMarker(n.id, getResultCss(processInstance.value.result))
|
||||
canvas.addMarker(n.id, getResultCss(processInstance.value.status))
|
||||
} else if (n.$type === 'bpmn:ServiceTask') {
|
||||
//服务任务
|
||||
if (activity.startTime > 0 && activity.endTime === 0) {
|
||||
@@ -223,39 +224,49 @@ const highlightDiagram = async () => {
|
||||
canvas.addMarker(out.id, getResultCss(2))
|
||||
})
|
||||
}
|
||||
} else if (n.$type === 'bpmn:SequenceFlow') {
|
||||
let targetActivity = activityList.find((m: any) => m.key === n.targetRef.id)
|
||||
if (targetActivity) {
|
||||
canvas.addMarker(n.id, getActivityHighlightCss(targetActivity))
|
||||
}
|
||||
}
|
||||
})
|
||||
if (!isEmpty(removeTaskDefinitionKeyList)) {
|
||||
taskList.value = taskList.value.filter(
|
||||
(item) => !removeTaskDefinitionKeyList.includes(item.definitionKey)
|
||||
(item) => !removeTaskDefinitionKeyList.includes(item.taskDefinitionKey)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const getActivityHighlightCss = (activity) => {
|
||||
return activity.endTime ? 'highlight' : 'highlight-todo'
|
||||
}
|
||||
const getResultCss = (result) => {
|
||||
if (result === 1) {
|
||||
|
||||
const getResultCss = (status) => {
|
||||
if (status === 1) {
|
||||
// 审批中
|
||||
return 'highlight-todo'
|
||||
} else if (result === 2) {
|
||||
} else if (status === 2) {
|
||||
// 已通过
|
||||
return 'highlight'
|
||||
} else if (result === 3) {
|
||||
} else if (status === 3) {
|
||||
// 不通过
|
||||
return 'highlight-reject'
|
||||
} else if (result === 4) {
|
||||
} else if (status === 4) {
|
||||
// 已取消
|
||||
return 'highlight-cancel'
|
||||
} else if (result === 5) {
|
||||
} else if (status === 5) {
|
||||
// 退回
|
||||
return 'highlight-return'
|
||||
} else if (result === 6) {
|
||||
} else if (status === 6) {
|
||||
// 委派
|
||||
return 'highlight-return'
|
||||
} else if (result === 7 || result === 8 || result === 9) {
|
||||
// 待后加签任务完成/待前加签任务完成/待前置任务完成
|
||||
return 'highlight-return'
|
||||
return 'highlight-todo'
|
||||
} else if (status === 7) {
|
||||
// 审批通过中
|
||||
return 'highlight-todo'
|
||||
} else if (status === 0) {
|
||||
// 待审批
|
||||
return 'highlight-todo'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
@@ -296,10 +307,10 @@ const elementHover = (element) => {
|
||||
!elementOverlayIds.value && (elementOverlayIds.value = {})
|
||||
!overlays.value && (overlays.value = bpmnModeler.get('overlays'))
|
||||
// 展示信息
|
||||
console.log(activityLists.value, 'activityLists.value')
|
||||
console.log(element.value, 'element.value')
|
||||
// console.log(activityLists.value, 'activityLists.value')
|
||||
// console.log(element.value, 'element.value')
|
||||
const activity = activityLists.value.find((m) => m.key === element.value.id)
|
||||
console.log(activity, 'activityactivityactivityactivity')
|
||||
// console.log(activity, 'activityactivityactivityactivity')
|
||||
if (!activity) {
|
||||
return
|
||||
}
|
||||
@@ -313,15 +324,14 @@ const elementHover = (element) => {
|
||||
<p>部门:${processInstance.value.startUser.deptName}</p>
|
||||
<p>创建时间:${formatDate(processInstance.value.createTime)}`
|
||||
} else if (element.value.type === 'bpmn:UserTask') {
|
||||
// debugger
|
||||
let task = taskList.value.find((m) => m.id === activity.taskId) // 找到活动对应的 taskId
|
||||
if (!task) {
|
||||
return
|
||||
}
|
||||
let optionData = getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)
|
||||
let optionData = getIntDictOptions(DICT_TYPE.BPM_TASK_STATUS)
|
||||
let dataResult = ''
|
||||
optionData.forEach((element) => {
|
||||
if (element.value == task.result) {
|
||||
if (element.value == task.status) {
|
||||
dataResult = element.label
|
||||
}
|
||||
})
|
||||
@@ -333,7 +343,7 @@ const elementHover = (element) => {
|
||||
// <p>部门:${task.assigneeUser.deptName}</p>
|
||||
// <p>结果:${getIntDictOptions(
|
||||
// DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
|
||||
// task.result
|
||||
// task.status
|
||||
// )}</p>
|
||||
// <p>创建时间:${formatDate(task.createTime)}</p>`
|
||||
if (task.endTime) {
|
||||
@@ -351,29 +361,30 @@ const elementHover = (element) => {
|
||||
}
|
||||
console.log(html)
|
||||
} else if (element.value.type === 'bpmn:EndEvent' && processInstance.value) {
|
||||
let optionData = getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)
|
||||
let optionData = getIntDictOptions(DICT_TYPE.BPM_TASK_STATUS)
|
||||
let dataResult = ''
|
||||
optionData.forEach((element) => {
|
||||
if (element.value == processInstance.value.result) {
|
||||
if (element.value == processInstance.value.status) {
|
||||
dataResult = element.label
|
||||
}
|
||||
})
|
||||
html = `<p>结果:${dataResult}</p>`
|
||||
// html = `<p>结果:${getIntDictOptions(
|
||||
// DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
|
||||
// processInstance.value.result
|
||||
// processInstance.value.status
|
||||
// )}</p>`
|
||||
if (processInstance.value.endTime) {
|
||||
html += `<p>结束时间:${formatDate(processInstance.value.endTime)}</p>`
|
||||
}
|
||||
}
|
||||
console.log(html, 'html111111111111111')
|
||||
// console.log(html, 'html111111111111111')
|
||||
elementOverlayIds.value[element.value.id] = toRaw(overlays.value)?.add(element.value, {
|
||||
position: { left: 0, bottom: 0 },
|
||||
html: `<div class="element-overlays">${html}</div>`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 流程图的元素被 out
|
||||
const elementOut = (element) => {
|
||||
toRaw(overlays.value).remove({ element })
|
||||
@@ -389,6 +400,7 @@ onMounted(() => {
|
||||
// 初始模型的监听器
|
||||
initModelListeners()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// this.$once('hook:beforeDestroy', () => {
|
||||
// })
|
||||
@@ -427,7 +439,7 @@ watch(
|
||||
)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="scss">
|
||||
/** 处理中 */
|
||||
.highlight-todo.djs-connection > .djs-visual > path {
|
||||
stroke: #1890ff !important;
|
||||
@@ -501,6 +513,10 @@ watch(
|
||||
stroke: green !important;
|
||||
}
|
||||
|
||||
.djs-element.highlight > .djs-visual > path {
|
||||
stroke: green !important;
|
||||
}
|
||||
|
||||
/** 不通过 */
|
||||
.highlight-reject.djs-shape .djs-visual > :nth-child(1) {
|
||||
fill: red !important;
|
||||
@@ -520,6 +536,7 @@ watch(
|
||||
|
||||
.highlight-reject.djs-connection > .djs-visual > path {
|
||||
stroke: red !important;
|
||||
marker-end: url(#sequenceflow-end-white-success) !important;
|
||||
}
|
||||
|
||||
.highlight-reject:not(.djs-connection) .djs-visual > :nth-child(1) {
|
||||
|
||||
+10
@@ -332,6 +332,16 @@
|
||||
"name": "multiinstance_condition",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateStrategy",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateParam",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+10
@@ -319,6 +319,16 @@
|
||||
"name": "priority",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateStrategy",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateParam",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+10
@@ -319,6 +319,16 @@
|
||||
"name": "priority",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateStrategy",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateParam",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -24,15 +24,10 @@
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="condition" v-if="formVisible" key="form">
|
||||
<template #title><Icon icon="ep:list" />表单</template>
|
||||
<!-- <element-form :id="elementId" :type="elementType" /> -->
|
||||
友情提示:使用
|
||||
<router-link :to="{ path: '/bpm/manager/form' }"
|
||||
><el-link type="danger">流程表单</el-link>
|
||||
</router-link>
|
||||
替代,提供更好的表单设计功能
|
||||
<element-form :id="elementId" :type="elementType" />
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="task" v-if="elementType.indexOf('Task') !== -1" key="task">
|
||||
<template #title><Icon icon="ep:checked" />任务</template>
|
||||
<template #title><Icon icon="ep:checked" />任务(审批人)</template>
|
||||
<element-task :id="elementId" :type="elementType" />
|
||||
</el-collapse-item>
|
||||
<el-collapse-item
|
||||
@@ -40,7 +35,7 @@
|
||||
v-if="elementType.indexOf('Task') !== -1"
|
||||
key="multiInstance"
|
||||
>
|
||||
<template #title><Icon icon="ep:help-filled" />多实例</template>
|
||||
<template #title><Icon icon="ep:help-filled" />多实例(会签配置)</template>
|
||||
<element-multi-instance :business-object="elementBusinessObject" :type="elementType" />
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="listeners" key="listeners">
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
<el-form label-width="90px" :model="needProps" :rules="rules">
|
||||
<div v-if="needProps.type == 'bpmn:Process'">
|
||||
<!-- 如果是 Process 信息的时候,使用自定义表单 -->
|
||||
<el-link
|
||||
href="https://doc.iocoder.cn/bpm/#_3-%E6%B5%81%E7%A8%8B%E5%9B%BE%E7%A4%BA%E4%BE%8B"
|
||||
type="danger"
|
||||
target="_blank"
|
||||
>
|
||||
如何实现实现会签、或签?
|
||||
</el-link>
|
||||
<el-form-item label="流程标识" prop="id">
|
||||
<el-input
|
||||
v-model="needProps.id"
|
||||
@@ -68,13 +61,13 @@ const resetBaseInfo = () => {
|
||||
console.log(bpmnElement.value, 'bpmnElement')
|
||||
|
||||
bpmnElement.value = bpmnInstances()?.bpmnElement
|
||||
console.log(bpmnElement.value, 'resetBaseInfo11111111111')
|
||||
// console.log(bpmnElement.value, 'resetBaseInfo11111111111')
|
||||
elementBaseInfo.value = bpmnElement.value.businessObject
|
||||
needProps.value['type'] = bpmnElement.value.businessObject.$type
|
||||
// elementBaseInfo.value['typess'] = bpmnElement.value.businessObject.$type
|
||||
|
||||
// elementBaseInfo.value = JSON.parse(JSON.stringify(bpmnElement.value.businessObject))
|
||||
console.log(elementBaseInfo.value, 'elementBaseInfo22222222222')
|
||||
// console.log(elementBaseInfo.value, 'elementBaseInfo22222222222')
|
||||
}
|
||||
const handleKeyUpdate = (value) => {
|
||||
// 校验 value 的值,只有 XML NCName 通过的情况下,才进行赋值。否则,会导致流程图报错,无法绘制的问题
|
||||
@@ -121,11 +114,11 @@ const updateBaseInfo = (key) => {
|
||||
// id: elementBaseInfo.value[key]
|
||||
// // di: { id: `${elementBaseInfo.value[key]}_di` }
|
||||
// }
|
||||
console.log(elementBaseInfo, 'elementBaseInfo11111111111')
|
||||
// console.log(elementBaseInfo, 'elementBaseInfo11111111111')
|
||||
needProps.value = { ...elementBaseInfo.value, ...needProps.value }
|
||||
|
||||
if (key === 'id') {
|
||||
console.log('jinru')
|
||||
// console.log('jinru')
|
||||
console.log(window, 'window')
|
||||
console.log(bpmnElement.value, 'bpmnElement')
|
||||
console.log(toRaw(bpmnElement.value), 'bpmnElement')
|
||||
@@ -138,20 +131,11 @@ const updateBaseInfo = (key) => {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), attrObj)
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
// 针对上传的 bpmn 流程图时,需要延迟 1 秒的时间,保证 key 和 name 的更新
|
||||
setTimeout(() => {
|
||||
console.log(props.model, 'props.model')
|
||||
handleKeyUpdate(props.model.key)
|
||||
handleNameUpdate(props.model.name)
|
||||
console.log(props, 'propsssssssssssssssssssss')
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.businessObject,
|
||||
(val) => {
|
||||
console.log(val, 'val11111111111111111111')
|
||||
// console.log(val, 'val11111111111111111111')
|
||||
if (val) {
|
||||
// nextTick(() => {
|
||||
resetBaseInfo()
|
||||
@@ -159,6 +143,18 @@ watch(
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.model?.key,
|
||||
(val) => {
|
||||
// 针对上传的 bpmn 流程图时,保证 key 和 name 的更新
|
||||
if (val) {
|
||||
handleKeyUpdate(props.model.key)
|
||||
handleNameUpdate(props.model.name)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// watch(
|
||||
// () => ({ ...props }),
|
||||
// (oldVal, newVal) => {
|
||||
|
||||
@@ -1,228 +1,233 @@
|
||||
<template>
|
||||
<div class="panel-tab__content">
|
||||
<el-form label-width="80px">
|
||||
<el-form-item label="表单标识">
|
||||
<el-input v-model="formKey" clearable @change="updateElementFormKey" />
|
||||
</el-form-item>
|
||||
<el-form-item label="业务标识">
|
||||
<el-select v-model="businessKey" @change="updateElementBusinessKey">
|
||||
<el-option v-for="i in fieldList" :key="i.id" :value="i.id" :label="i.label" />
|
||||
<el-option label="无" value="" />
|
||||
<el-form-item label="流程表单">
|
||||
<!-- <el-input v-model="formKey" clearable @change="updateElementFormKey" />-->
|
||||
<el-select v-model="formKey" clearable @change="updateElementFormKey">
|
||||
<el-option v-for="form in formList" :key="form.id" :label="form.name" :value="form.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="业务标识">-->
|
||||
<!-- <el-select v-model="businessKey" @change="updateElementBusinessKey">-->
|
||||
<!-- <el-option v-for="i in fieldList" :key="i.id" :value="i.id" :label="i.label" />-->
|
||||
<!-- <el-option label="无" value="" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
|
||||
<!--字段列表-->
|
||||
<div class="element-property list-property">
|
||||
<el-divider><Icon icon="ep:coin" /> 表单字段</el-divider>
|
||||
<el-table :data="fieldList" max-height="240" fit border>
|
||||
<el-table-column label="序号" type="index" width="50px" />
|
||||
<el-table-column label="字段名称" prop="label" min-width="80px" show-overflow-tooltip />
|
||||
<el-table-column
|
||||
label="字段类型"
|
||||
prop="type"
|
||||
min-width="80px"
|
||||
:formatter="(row) => fieldType[row.type] || row.type"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
label="默认值"
|
||||
prop="defaultValue"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="操作" width="90px">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="openFieldForm(scope, scope.$index)"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeField(scope, scope.$index)"
|
||||
>移除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="element-drawer__button">
|
||||
<XButton type="primary" proIcon="ep:plus" title="添加字段" @click="openFieldForm(null, -1)" />
|
||||
</div>
|
||||
<!-- <div class="element-property list-property">-->
|
||||
<!-- <el-divider><Icon icon="ep:coin" /> 表单字段</el-divider>-->
|
||||
<!-- <el-table :data="fieldList" max-height="240" fit border>-->
|
||||
<!-- <el-table-column label="序号" type="index" width="50px" />-->
|
||||
<!-- <el-table-column label="字段名称" prop="label" min-width="80px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- label="字段类型"-->
|
||||
<!-- prop="type"-->
|
||||
<!-- min-width="80px"-->
|
||||
<!-- :formatter="(row) => fieldType[row.type] || row.type"-->
|
||||
<!-- show-overflow-tooltip-->
|
||||
<!-- />-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- label="默认值"-->
|
||||
<!-- prop="defaultValue"-->
|
||||
<!-- min-width="80px"-->
|
||||
<!-- show-overflow-tooltip-->
|
||||
<!-- />-->
|
||||
<!-- <el-table-column label="操作" width="90px">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-button type="primary" link @click="openFieldForm(scope, scope.$index)"-->
|
||||
<!-- >编辑</el-button-->
|
||||
<!-- >-->
|
||||
<!-- <el-divider direction="vertical" />-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- style="color: #ff4d4f"-->
|
||||
<!-- @click="removeField(scope, scope.$index)"-->
|
||||
<!-- >移除</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </el-table>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="element-drawer__button">-->
|
||||
<!-- <XButton type="primary" proIcon="ep:plus" title="添加字段" @click="openFieldForm(null, -1)" />-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!--字段配置侧边栏-->
|
||||
<el-drawer
|
||||
v-model="fieldModelVisible"
|
||||
title="字段配置"
|
||||
:size="`${width}px`"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form :model="formFieldForm" label-width="90px">
|
||||
<el-form-item label="字段ID">
|
||||
<el-input v-model="formFieldForm.id" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型">
|
||||
<el-select
|
||||
v-model="formFieldForm.typeType"
|
||||
placeholder="请选择字段类型"
|
||||
clearable
|
||||
@change="changeFieldTypeType"
|
||||
>
|
||||
<el-option v-for="(value, key) of fieldType" :label="value" :value="key" :key="key" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型名称" v-if="formFieldForm.typeType === 'custom'">
|
||||
<el-input v-model="formFieldForm.type" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="formFieldForm.label" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="时间格式" v-if="formFieldForm.typeType === 'date'">
|
||||
<el-input v-model="formFieldForm.datePattern" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="默认值">
|
||||
<el-input v-model="formFieldForm.defaultValue" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- <el-drawer-->
|
||||
<!-- v-model="fieldModelVisible"-->
|
||||
<!-- title="字段配置"-->
|
||||
<!-- :size="`${width}px`"-->
|
||||
<!-- append-to-body-->
|
||||
<!-- destroy-on-close-->
|
||||
<!-- >-->
|
||||
<!-- <el-form :model="formFieldForm" label-width="90px">-->
|
||||
<!-- <el-form-item label="字段ID">-->
|
||||
<!-- <el-input v-model="formFieldForm.id" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="类型">-->
|
||||
<!-- <el-select-->
|
||||
<!-- v-model="formFieldForm.typeType"-->
|
||||
<!-- placeholder="请选择字段类型"-->
|
||||
<!-- clearable-->
|
||||
<!-- @change="changeFieldTypeType"-->
|
||||
<!-- >-->
|
||||
<!-- <el-option v-for="(value, key) of fieldType" :label="value" :value="key" :key="key" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="类型名称" v-if="formFieldForm.typeType === 'custom'">-->
|
||||
<!-- <el-input v-model="formFieldForm.type" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="名称">-->
|
||||
<!-- <el-input v-model="formFieldForm.label" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="时间格式" v-if="formFieldForm.typeType === 'date'">-->
|
||||
<!-- <el-input v-model="formFieldForm.datePattern" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="默认值">-->
|
||||
<!-- <el-input v-model="formFieldForm.defaultValue" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-form>-->
|
||||
|
||||
<!-- 枚举值设置 -->
|
||||
<template v-if="formFieldForm.type === 'enum'">
|
||||
<el-divider key="enum-divider" />
|
||||
<p class="listener-filed__title" key="enum-title">
|
||||
<span><Icon icon="ep:menu" />枚举值列表:</span>
|
||||
<el-button type="primary" @click="openFieldOptionForm(null, -1, 'enum')"
|
||||
>添加枚举值</el-button
|
||||
>
|
||||
</p>
|
||||
<el-table :data="fieldEnumList" key="enum-table" max-height="240" fit border>
|
||||
<el-table-column label="序号" width="50px" type="index" />
|
||||
<el-table-column label="枚举值编号" prop="id" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="枚举值名称" prop="name" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="90px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="openFieldOptionForm(scope, scope.$index, 'enum')"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeFieldOptionItem(scope, scope.$index, 'enum')"
|
||||
>移除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
<!-- <!– 枚举值设置 –>-->
|
||||
<!-- <template v-if="formFieldForm.type === 'enum'">-->
|
||||
<!-- <el-divider key="enum-divider" />-->
|
||||
<!-- <p class="listener-filed__title" key="enum-title">-->
|
||||
<!-- <span><Icon icon="ep:menu" />枚举值列表:</span>-->
|
||||
<!-- <el-button type="primary" @click="openFieldOptionForm(null, -1, 'enum')"-->
|
||||
<!-- >添加枚举值</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </p>-->
|
||||
<!-- <el-table :data="fieldEnumList" key="enum-table" max-height="240" fit border>-->
|
||||
<!-- <el-table-column label="序号" width="50px" type="index" />-->
|
||||
<!-- <el-table-column label="枚举值编号" prop="id" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="枚举值名称" prop="name" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="操作" width="90px">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- @click="openFieldOptionForm(scope, scope.$index, 'enum')"-->
|
||||
<!-- >编辑</el-button-->
|
||||
<!-- >-->
|
||||
<!-- <el-divider direction="vertical" />-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- style="color: #ff4d4f"-->
|
||||
<!-- @click="removeFieldOptionItem(scope, scope.$index, 'enum')"-->
|
||||
<!-- >移除</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </el-table>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<!-- 校验规则 -->
|
||||
<el-divider key="validation-divider" />
|
||||
<p class="listener-filed__title" key="validation-title">
|
||||
<span><Icon icon="ep:menu" />约束条件列表:</span>
|
||||
<el-button type="primary" @click="openFieldOptionForm(null, -1, 'constraint')"
|
||||
>添加约束</el-button
|
||||
>
|
||||
</p>
|
||||
<el-table :data="fieldConstraintsList" key="validation-table" max-height="240" fit border>
|
||||
<el-table-column label="序号" width="50px" type="index" />
|
||||
<el-table-column label="约束名称" prop="name" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="约束配置" prop="config" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="90px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="openFieldOptionForm(scope, scope.$index, 'constraint')"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeFieldOptionItem(scope, scope.$index, 'constraint')"
|
||||
>移除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- <!– 校验规则 –>-->
|
||||
<!-- <el-divider key="validation-divider" />-->
|
||||
<!-- <p class="listener-filed__title" key="validation-title">-->
|
||||
<!-- <span><Icon icon="ep:menu" />约束条件列表:</span>-->
|
||||
<!-- <el-button type="primary" @click="openFieldOptionForm(null, -1, 'constraint')"-->
|
||||
<!-- >添加约束</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </p>-->
|
||||
<!-- <el-table :data="fieldConstraintsList" key="validation-table" max-height="240" fit border>-->
|
||||
<!-- <el-table-column label="序号" width="50px" type="index" />-->
|
||||
<!-- <el-table-column label="约束名称" prop="name" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="约束配置" prop="config" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="操作" width="90px">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- @click="openFieldOptionForm(scope, scope.$index, 'constraint')"-->
|
||||
<!-- >编辑</el-button-->
|
||||
<!-- >-->
|
||||
<!-- <el-divider direction="vertical" />-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- style="color: #ff4d4f"-->
|
||||
<!-- @click="removeFieldOptionItem(scope, scope.$index, 'constraint')"-->
|
||||
<!-- >移除</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </el-table>-->
|
||||
|
||||
<!-- 表单属性 -->
|
||||
<el-divider key="property-divider" />
|
||||
<p class="listener-filed__title" key="property-title">
|
||||
<span><Icon icon="ep:menu" />字段属性列表:</span>
|
||||
<el-button type="primary" @click="openFieldOptionForm(null, -1, 'property')"
|
||||
>添加属性</el-button
|
||||
>
|
||||
</p>
|
||||
<el-table :data="fieldPropertiesList" key="property-table" max-height="240" fit border>
|
||||
<el-table-column label="序号" width="50px" type="index" />
|
||||
<el-table-column label="属性编号" prop="id" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="属性值" prop="value" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="90px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="openFieldOptionForm(scope, scope.$index, 'property')"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeFieldOptionItem(scope, scope.$index, 'property')"
|
||||
>移除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- <!– 表单属性 –>-->
|
||||
<!-- <el-divider key="property-divider" />-->
|
||||
<!-- <p class="listener-filed__title" key="property-title">-->
|
||||
<!-- <span><Icon icon="ep:menu" />字段属性列表:</span>-->
|
||||
<!-- <el-button type="primary" @click="openFieldOptionForm(null, -1, 'property')"-->
|
||||
<!-- >添加属性</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </p>-->
|
||||
<!-- <el-table :data="fieldPropertiesList" key="property-table" max-height="240" fit border>-->
|
||||
<!-- <el-table-column label="序号" width="50px" type="index" />-->
|
||||
<!-- <el-table-column label="属性编号" prop="id" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="属性值" prop="value" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="操作" width="90px">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- @click="openFieldOptionForm(scope, scope.$index, 'property')"-->
|
||||
<!-- >编辑</el-button-->
|
||||
<!-- >-->
|
||||
<!-- <el-divider direction="vertical" />-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- style="color: #ff4d4f"-->
|
||||
<!-- @click="removeFieldOptionItem(scope, scope.$index, 'property')"-->
|
||||
<!-- >移除</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </el-table>-->
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<div class="element-drawer__button">
|
||||
<el-button>取 消</el-button>
|
||||
<el-button type="primary" @click="saveField">保 存</el-button>
|
||||
</div>
|
||||
</el-drawer>
|
||||
<!-- <!– 底部按钮 –>-->
|
||||
<!-- <div class="element-drawer__button">-->
|
||||
<!-- <el-button>取 消</el-button>-->
|
||||
<!-- <el-button type="primary" @click="saveField">保 存</el-button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-drawer>-->
|
||||
|
||||
<el-dialog
|
||||
v-model="fieldOptionModelVisible"
|
||||
:title="optionModelTitle"
|
||||
width="600px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form :model="fieldOptionForm" label-width="96px">
|
||||
<el-form-item label="编号/ID" v-if="fieldOptionType !== 'constraint'" key="option-id">
|
||||
<el-input v-model="fieldOptionForm.id" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" v-if="fieldOptionType !== 'property'" key="option-name">
|
||||
<el-input v-model="fieldOptionForm.name" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="配置" v-if="fieldOptionType === 'constraint'" key="option-config">
|
||||
<el-input v-model="fieldOptionForm.config" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="值" v-if="fieldOptionType === 'property'" key="option-value">
|
||||
<el-input v-model="fieldOptionForm.value" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="fieldOptionModelVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="saveFieldOption">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- <el-dialog-->
|
||||
<!-- v-model="fieldOptionModelVisible"-->
|
||||
<!-- :title="optionModelTitle"-->
|
||||
<!-- width="600px"-->
|
||||
<!-- append-to-body-->
|
||||
<!-- destroy-on-close-->
|
||||
<!-- >-->
|
||||
<!-- <el-form :model="fieldOptionForm" label-width="96px">-->
|
||||
<!-- <el-form-item label="编号/ID" v-if="fieldOptionType !== 'constraint'" key="option-id">-->
|
||||
<!-- <el-input v-model="fieldOptionForm.id" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="名称" v-if="fieldOptionType !== 'property'" key="option-name">-->
|
||||
<!-- <el-input v-model="fieldOptionForm.name" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="配置" v-if="fieldOptionType === 'constraint'" key="option-config">-->
|
||||
<!-- <el-input v-model="fieldOptionForm.config" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="值" v-if="fieldOptionType === 'property'" key="option-value">-->
|
||||
<!-- <el-input v-model="fieldOptionForm.value" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-form>-->
|
||||
<!-- <template #footer>-->
|
||||
<!-- <el-button @click="fieldOptionModelVisible = false">取 消</el-button>-->
|
||||
<!-- <el-button type="primary" @click="saveFieldOption">确 定</el-button>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-dialog>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as FormApi from '@/api/bpm/form'
|
||||
|
||||
defineOptions({ name: 'ElementForm' })
|
||||
|
||||
const props = defineProps({
|
||||
@@ -263,6 +268,9 @@ const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||
const resetFormList = () => {
|
||||
bpmnELement.value = bpmnInstances().bpmnElement
|
||||
formKey.value = bpmnELement.value.businessObject.formKey
|
||||
if (formKey.value?.length > 0) {
|
||||
formKey.value = parseInt(formKey.value)
|
||||
}
|
||||
// 获取元素扩展属性 或者 创建扩展属性
|
||||
elExtensionElements.value =
|
||||
bpmnELement.value.businessObject.get('extensionElements') ||
|
||||
@@ -421,7 +429,7 @@ const saveField = () => {
|
||||
|
||||
// 移除某个 字段的 配置项
|
||||
const removeFieldOptionItem = (option, index, type) => {
|
||||
console.log(option, 'option')
|
||||
// console.log(option, 'option')
|
||||
if (type === 'property') {
|
||||
fieldPropertiesList.value.splice(index, 1)
|
||||
return
|
||||
@@ -451,6 +459,11 @@ const updateElementExtensions = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const formList = ref([]) // 流程表单的下拉框的数据
|
||||
onMounted(async () => {
|
||||
formList.value = await FormApi.getFormSimpleList()
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
(val) => {
|
||||
|
||||
@@ -26,8 +26,16 @@
|
||||
type="primary"
|
||||
preIcon="ep:plus"
|
||||
title="添加监听器"
|
||||
size="small"
|
||||
@click="openListenerForm(null)"
|
||||
/>
|
||||
<XButton
|
||||
type="success"
|
||||
preIcon="ep:select"
|
||||
title="选择监听器"
|
||||
size="small"
|
||||
@click="openProcessListenerDialog"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 监听器 编辑/创建 部分 -->
|
||||
@@ -240,11 +248,21 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<!-- 选择弹窗 -->
|
||||
<ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { createListenerObject, updateElementExtensions } from '../../utils'
|
||||
import { initListenerType, initListenerForm, listenerType, fieldType } from './utilSelf'
|
||||
import {
|
||||
initListenerType,
|
||||
initListenerForm,
|
||||
listenerType,
|
||||
fieldType,
|
||||
initListenerForm2
|
||||
} from './utilSelf'
|
||||
import ProcessListenerDialog from './ProcessListenerDialog.vue'
|
||||
|
||||
defineOptions({ name: 'ElementListeners' })
|
||||
|
||||
@@ -284,6 +302,7 @@ const resetListenersList = () => {
|
||||
}
|
||||
// 打开 监听器详情 侧边栏
|
||||
const openListenerForm = (listener, index?) => {
|
||||
// debugger
|
||||
if (listener) {
|
||||
listenerForm.value = initListenerForm(listener)
|
||||
editingListenerIndex.value = index
|
||||
@@ -321,6 +340,7 @@ const openListenerFieldForm = (field, index?) => {
|
||||
}
|
||||
// 保存监听器注入字段
|
||||
const saveListenerFiled = async () => {
|
||||
// debugger
|
||||
let validateStatus = await listenerFieldFormRef.value.validate()
|
||||
if (!validateStatus) return // 验证不通过直接返回
|
||||
if (editingListenerFieldIndex.value === -1) {
|
||||
@@ -337,6 +357,7 @@ const saveListenerFiled = async () => {
|
||||
}
|
||||
// 移除监听器字段
|
||||
const removeListenerField = (index) => {
|
||||
// debugger
|
||||
ElMessageBox.confirm('确认移除该字段吗?', '提示', {
|
||||
confirmButtonText: '确 认',
|
||||
cancelButtonText: '取 消'
|
||||
@@ -349,6 +370,7 @@ const removeListenerField = (index) => {
|
||||
}
|
||||
// 移除监听器
|
||||
const removeListener = (index) => {
|
||||
debugger
|
||||
ElMessageBox.confirm('确认移除该监听器吗?', '提示', {
|
||||
confirmButtonText: '确 认',
|
||||
cancelButtonText: '取 消'
|
||||
@@ -365,6 +387,7 @@ const removeListener = (index) => {
|
||||
}
|
||||
// 保存监听器配置
|
||||
const saveListenerConfig = async () => {
|
||||
// debugger
|
||||
let validateStatus = await listenerFormRef.value.validate()
|
||||
if (!validateStatus) return // 验证不通过直接返回
|
||||
const listenerObject = createListenerObject(listenerForm.value, false, prefix)
|
||||
@@ -389,6 +412,28 @@ const saveListenerConfig = async () => {
|
||||
listenerForm.value = {}
|
||||
}
|
||||
|
||||
// 打开监听器弹窗
|
||||
const processListenerDialogRef = ref()
|
||||
const openProcessListenerDialog = async () => {
|
||||
processListenerDialogRef.value.open('execution')
|
||||
}
|
||||
const selectProcessListener = (listener) => {
|
||||
const listenerForm = initListenerForm2(listener)
|
||||
const listenerObject = createListenerObject(listenerForm, false, prefix)
|
||||
bpmnElementListeners.value.push(listenerObject)
|
||||
elementListenersList.value.push(listenerForm)
|
||||
|
||||
// 保存其他配置
|
||||
otherExtensionList.value =
|
||||
bpmnElement.value.businessObject?.extensionElements?.values?.filter(
|
||||
(ex) => ex.$type !== `${prefix}:ExecutionListener`
|
||||
) ?? []
|
||||
updateElementExtensions(
|
||||
bpmnElement.value,
|
||||
otherExtensionList.value.concat(bpmnElementListeners.value)
|
||||
)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
(val) => {
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<!-- 执行器选择 -->
|
||||
<template>
|
||||
<Dialog title="请选择监听器" v-model="dialogVisible" width="1024px">
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="名字" align="center" prop="name" />
|
||||
<el-table-column label="类型" align="center" prop="type">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_PROCESS_LISTENER_TYPE" :value="scope.row.type" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="事件" align="center" prop="event" />
|
||||
<el-table-column label="值类型" align="center" prop="valueType">
|
||||
<template #default="scope">
|
||||
<dict-tag
|
||||
:type="DICT_TYPE.BPM_PROCESS_LISTENER_VALUE_TYPE"
|
||||
:value="scope.row.valueType"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="值" align="center" prop="value" />
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="select(scope.row)"> 选择 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ProcessListenerApi, ProcessListenerVO } from '@/api/bpm/processListener'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { CommonStatusEnum } from '@/utils/constants'
|
||||
|
||||
/** BPM 流程 表单 */
|
||||
defineOptions({ name: 'ProcessListenerDialog' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<ProcessListenerVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
type: undefined,
|
||||
status: CommonStatusEnum.ENABLE
|
||||
})
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string) => {
|
||||
dialogVisible.value = true
|
||||
loading.value = true
|
||||
try {
|
||||
queryParams.pageNo = 1
|
||||
queryParams.type = type
|
||||
const data = await ProcessListenerApi.getProcessListenerPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const select = async (row) => {
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('select', row)
|
||||
}
|
||||
</script>
|
||||
@@ -39,6 +39,13 @@
|
||||
title="添加监听器"
|
||||
@click="openListenerForm(null)"
|
||||
/>
|
||||
<XButton
|
||||
type="success"
|
||||
preIcon="ep:select"
|
||||
title="选择监听器"
|
||||
size="small"
|
||||
@click="openProcessListenerDialog"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 监听器 编辑/创建 部分 -->
|
||||
@@ -286,11 +293,22 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<!-- 选择弹窗 -->
|
||||
<ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { createListenerObject, updateElementExtensions } from '../../utils'
|
||||
import { initListenerForm, initListenerType, eventType, listenerType, fieldType } from './utilSelf'
|
||||
import {
|
||||
initListenerForm,
|
||||
initListenerType,
|
||||
eventType,
|
||||
listenerType,
|
||||
fieldType,
|
||||
initListenerForm2
|
||||
} from './utilSelf'
|
||||
import ProcessListenerDialog from '@/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue'
|
||||
|
||||
defineOptions({ name: 'UserTaskListeners' })
|
||||
|
||||
@@ -437,6 +455,28 @@ const removeListenerField = (field, index) => {
|
||||
.catch(() => console.info('操作取消'))
|
||||
}
|
||||
|
||||
// 打开监听器弹窗
|
||||
const processListenerDialogRef = ref()
|
||||
const openProcessListenerDialog = async () => {
|
||||
processListenerDialogRef.value.open('task')
|
||||
}
|
||||
const selectProcessListener = (listener) => {
|
||||
const listenerForm = initListenerForm2(listener)
|
||||
const listenerObject = createListenerObject(listenerForm, true, prefix)
|
||||
bpmnElementListeners.value.push(listenerObject)
|
||||
elementListenersList.value.push(listenerForm)
|
||||
|
||||
// 保存其他配置
|
||||
otherExtensionList.value =
|
||||
bpmnElement.value.businessObject?.extensionElements?.values?.filter(
|
||||
(ex) => ex.$type !== `${prefix}:TaskListener`
|
||||
) ?? []
|
||||
updateElementExtensions(
|
||||
bpmnElement.value,
|
||||
otherExtensionList.value.concat(bpmnElementListeners.value)
|
||||
)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
(val) => {
|
||||
|
||||
@@ -40,6 +40,33 @@ export function initListenerType(listener) {
|
||||
}
|
||||
}
|
||||
|
||||
/** 将 ProcessListenerDO 转换成 initListenerForm 想同的 Form 对象 */
|
||||
export function initListenerForm2(processListener) {
|
||||
if (processListener.valueType === 'class') {
|
||||
return {
|
||||
listenerType: 'classListener',
|
||||
class: processListener.value,
|
||||
event: processListener.event,
|
||||
fields: []
|
||||
}
|
||||
} else if (processListener.valueType === 'expression') {
|
||||
return {
|
||||
listenerType: 'expressionListener',
|
||||
expression: processListener.value,
|
||||
event: processListener.event,
|
||||
fields: []
|
||||
}
|
||||
} else if (processListener.valueType === 'delegateExpression') {
|
||||
return {
|
||||
listenerType: 'delegateExpressionListener',
|
||||
delegateExpression: processListener.value,
|
||||
event: processListener.event,
|
||||
fields: []
|
||||
}
|
||||
}
|
||||
throw new Error('未知的监听器类型')
|
||||
}
|
||||
|
||||
export const listenerType = {
|
||||
classListener: 'Java 类',
|
||||
expressionListener: '表达式',
|
||||
|
||||
+31
-5
@@ -1,11 +1,15 @@
|
||||
<template>
|
||||
<div class="panel-tab__content">
|
||||
<el-form label-width="90px">
|
||||
<el-form-item label="回路特性">
|
||||
<el-form-item label="快捷配置">
|
||||
<el-button size="small" @click="changeConfig('依次审批')">依次审批</el-button>
|
||||
<el-button size="small" @click="changeConfig('会签')">会签</el-button>
|
||||
<el-button size="small" @click="changeConfig('或签')">或签</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="会签类型">
|
||||
<el-select v-model="loopCharacteristics" @change="changeLoopCharacteristicsType">
|
||||
<el-option label="并行多重事件" value="ParallelMultiInstance" />
|
||||
<el-option label="时序多重事件" value="SequentialMultiInstance" />
|
||||
<el-option label="循环事件" value="StandardLoop" />
|
||||
<el-option label="无" value="Null" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -15,7 +19,7 @@
|
||||
loopCharacteristics === 'SequentialMultiInstance'
|
||||
"
|
||||
>
|
||||
<el-form-item label="循环基数" key="loopCardinality">
|
||||
<el-form-item label="循环数量" key="loopCardinality">
|
||||
<el-input
|
||||
v-model="loopInstanceForm.loopCardinality"
|
||||
clearable
|
||||
@@ -25,7 +29,8 @@
|
||||
<el-form-item label="集合" key="collection" v-show="false">
|
||||
<el-input v-model="loopInstanceForm.collection" clearable @change="updateLoopBase" />
|
||||
</el-form-item>
|
||||
<el-form-item label="元素变量" key="elementVariable">
|
||||
<!-- add by 芋艿:由于「元素变量」暂时用不到,所以这里 display 为 none -->
|
||||
<el-form-item label="元素变量" key="elementVariable" style="display: none">
|
||||
<el-input v-model="loopInstanceForm.elementVariable" clearable @change="updateLoopBase" />
|
||||
</el-form-item>
|
||||
<el-form-item label="完成条件" key="completionCondition">
|
||||
@@ -35,7 +40,8 @@
|
||||
@change="updateLoopCondition"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="异步状态" key="async">
|
||||
<!-- add by 芋艿:由于「异步状态」暂时用不到,所以这里 display 为 none -->
|
||||
<el-form-item label="异步状态" key="async" style="display: none">
|
||||
<el-checkbox
|
||||
v-model="loopInstanceForm.asyncBefore"
|
||||
label="异步前"
|
||||
@@ -124,6 +130,7 @@ const getElementLoop = (businessObject) => {
|
||||
businessObject.loopCharacteristics.extensionElements.values[0].body
|
||||
}
|
||||
}
|
||||
|
||||
const changeLoopCharacteristicsType = (type) => {
|
||||
// this.loopInstanceForm = { ...this.defaultLoopInstanceForm }; // 切换类型取消原表单配置
|
||||
// 取消多实例配置
|
||||
@@ -160,6 +167,7 @@ const changeLoopCharacteristicsType = (type) => {
|
||||
loopCharacteristics: toRaw(multiLoopInstance.value)
|
||||
})
|
||||
}
|
||||
|
||||
// 循环基数
|
||||
const updateLoopCardinality = (cardinality) => {
|
||||
let loopCardinality = null
|
||||
@@ -176,6 +184,7 @@ const updateLoopCardinality = (cardinality) => {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 完成条件
|
||||
const updateLoopCondition = (condition) => {
|
||||
let completionCondition = null
|
||||
@@ -192,6 +201,7 @@ const updateLoopCondition = (condition) => {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 重试周期
|
||||
const updateLoopTimeCycle = (timeCycle) => {
|
||||
const extensionElements = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
|
||||
@@ -209,6 +219,7 @@ const updateLoopTimeCycle = (timeCycle) => {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 直接更新的基础信息
|
||||
const updateLoopBase = () => {
|
||||
bpmnInstances().modeling.updateModdleProperties(
|
||||
@@ -220,6 +231,7 @@ const updateLoopBase = () => {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 各异步状态
|
||||
const updateLoopAsync = (key) => {
|
||||
const { asyncBefore, asyncAfter } = loopInstanceForm.value
|
||||
@@ -238,6 +250,20 @@ const updateLoopAsync = (key) => {
|
||||
)
|
||||
}
|
||||
|
||||
const changeConfig = (config) => {
|
||||
if (config === '依次审批') {
|
||||
changeLoopCharacteristicsType('SequentialMultiInstance')
|
||||
updateLoopCardinality('1')
|
||||
updateLoopCondition('${ nrOfCompletedInstances >= nrOfInstances }')
|
||||
} else if (config === '会签') {
|
||||
changeLoopCharacteristicsType('ParallelMultiInstance')
|
||||
updateLoopCondition('${ nrOfCompletedInstances >= nrOfInstances }')
|
||||
} else if (config === '或签') {
|
||||
changeLoopCharacteristicsType('ParallelMultiInstance')
|
||||
updateLoopCondition('${ nrOfCompletedInstances > 0 }')
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
multiLoopInstance.value = null
|
||||
bpmnElement.value = null
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div class="panel-tab__content">
|
||||
<el-form size="small" label-width="90px">
|
||||
<el-form-item label="异步延续">
|
||||
<!-- add by 芋艿:由于「异步延续」暂时用不到,所以这里 display 为 none -->
|
||||
<el-form-item label="异步延续" style="display: none">
|
||||
<el-checkbox
|
||||
v-model="taskConfigForm.asyncBefore"
|
||||
label="异步前"
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
<!-- 表达式选择 -->
|
||||
<template>
|
||||
<Dialog title="请选择表达式" v-model="dialogVisible" width="1024px">
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="名字" align="center" prop="name" />
|
||||
<el-table-column label="表达式" align="center" prop="expression" />
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="select(scope.row)"> 选择 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { CommonStatusEnum } from '@/utils/constants'
|
||||
import { ProcessExpressionApi, ProcessExpressionVO } from '@/api/bpm/processExpression'
|
||||
|
||||
/** BPM 流程 表单 */
|
||||
defineOptions({ name: 'ProcessExpressionDialog' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<ProcessExpressionVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
type: undefined,
|
||||
status: CommonStatusEnum.ENABLE
|
||||
})
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string) => {
|
||||
dialogVisible.value = true
|
||||
loading.value = true
|
||||
try {
|
||||
queryParams.pageNo = 1
|
||||
queryParams.type = type
|
||||
const data = await ProcessExpressionApi.getProcessExpressionPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const select = async (row) => {
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('select', row)
|
||||
}
|
||||
</script>
|
||||
+194
-60
@@ -1,85 +1,204 @@
|
||||
<template>
|
||||
<div style="margin-top: 16px">
|
||||
<!-- <el-form-item label="处理用户">-->
|
||||
<!-- <el-select v-model="userTaskForm.assignee" @change="updateElementTask('assignee')">-->
|
||||
<!-- <el-option v-for="ak in mockData" :key="'ass-' + ak" :label="`用户${ak}`" :value="`user${ak}`" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="候选用户">-->
|
||||
<!-- <el-select v-model="userTaskForm.candidateUsers" multiple collapse-tags @change="updateElementTask('candidateUsers')">-->
|
||||
<!-- <el-option v-for="uk in mockData" :key="'user-' + uk" :label="`用户${uk}`" :value="`user${uk}`" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="候选分组">-->
|
||||
<!-- <el-select v-model="userTaskForm.candidateGroups" multiple collapse-tags @change="updateElementTask('candidateGroups')">-->
|
||||
<!-- <el-option v-for="gk in mockData" :key="'ass-' + gk" :label="`分组${gk}`" :value="`group${gk}`" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item label="到期时间">
|
||||
<el-input v-model="userTaskForm.dueDate" clearable @change="updateElementTask('dueDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item label="跟踪时间">
|
||||
<el-input
|
||||
v-model="userTaskForm.followUpDate"
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="规则类型" prop="candidateStrategy">
|
||||
<el-select
|
||||
v-model="userTaskForm.candidateStrategy"
|
||||
clearable
|
||||
@change="updateElementTask('followUpDate')"
|
||||
style="width: 100%"
|
||||
@change="changeCandidateStrategy"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="userTaskForm.candidateStrategy == 10"
|
||||
label="指定角色"
|
||||
prop="candidateParam"
|
||||
>
|
||||
<el-select
|
||||
v-model="userTaskForm.candidateParam"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<el-option v-for="item in roleOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="userTaskForm.candidateStrategy == 20 || userTaskForm.candidateStrategy == 21"
|
||||
label="指定部门"
|
||||
prop="candidateParam"
|
||||
span="24"
|
||||
>
|
||||
<el-tree-select
|
||||
ref="treeRef"
|
||||
v-model="userTaskForm.candidateParam"
|
||||
:data="deptTreeOptions"
|
||||
:props="defaultProps"
|
||||
empty-text="加载中,请稍后"
|
||||
multiple
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
@change="updateElementTask"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="优先级">
|
||||
<el-input v-model="userTaskForm.priority" clearable @change="updateElementTask('priority')" />
|
||||
<el-form-item
|
||||
v-if="userTaskForm.candidateStrategy == 22"
|
||||
label="指定岗位"
|
||||
prop="candidateParam"
|
||||
span="24"
|
||||
>
|
||||
<el-select
|
||||
v-model="userTaskForm.candidateParam"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<el-option v-for="item in postOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
友情提示:任务的分配规则,使用
|
||||
<router-link target="_blank" :to="{ path: '/bpm/manager/model' }"
|
||||
><el-link type="danger">流程模型</el-link>
|
||||
</router-link>
|
||||
下的【分配规则】替代,提供指定角色、部门负责人、部门成员、岗位、工作组、自定义脚本等 7
|
||||
种维护的任务分配维度,更加灵活!
|
||||
</div>
|
||||
<el-form-item
|
||||
v-if="userTaskForm.candidateStrategy == 30"
|
||||
label="指定用户"
|
||||
prop="candidateParam"
|
||||
span="24"
|
||||
>
|
||||
<el-select
|
||||
v-model="userTaskForm.candidateParam"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item.id"
|
||||
:label="item.nickname"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="userTaskForm.candidateStrategy === 40"
|
||||
label="指定用户组"
|
||||
prop="candidateParam"
|
||||
>
|
||||
<el-select
|
||||
v-model="userTaskForm.candidateParam"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userGroupOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="userTaskForm.candidateStrategy === 60"
|
||||
label="流程表达式"
|
||||
prop="candidateParam"
|
||||
>
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="userTaskForm.candidateParam[0]"
|
||||
clearable
|
||||
style="width: 72%"
|
||||
@change="updateElementTask"
|
||||
/>
|
||||
<el-button class="ml-5px" size="small" type="success" @click="openProcessExpressionDialog"
|
||||
>选择表达式</el-button
|
||||
>
|
||||
<!-- 选择弹窗 -->
|
||||
<ProcessExpressionDialog ref="processExpressionDialogRef" @select="selectProcessExpression" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { defaultProps, handleTree } from '@/utils/tree'
|
||||
import * as RoleApi from '@/api/system/role'
|
||||
import * as DeptApi from '@/api/system/dept'
|
||||
import * as PostApi from '@/api/system/post'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import * as UserGroupApi from '@/api/bpm/userGroup'
|
||||
import ProcessExpressionDialog from './ProcessExpressionDialog.vue'
|
||||
|
||||
defineOptions({ name: 'UserTask' })
|
||||
const props = defineProps({
|
||||
id: String,
|
||||
type: String
|
||||
})
|
||||
const defaultTaskForm = ref({
|
||||
assignee: '',
|
||||
candidateUsers: [],
|
||||
candidateGroups: [],
|
||||
dueDate: '',
|
||||
followUpDate: '',
|
||||
priority: ''
|
||||
const userTaskForm = ref({
|
||||
candidateStrategy: undefined, // 分配规则
|
||||
candidateParam: [] // 分配选项
|
||||
})
|
||||
const userTaskForm = ref<any>({})
|
||||
// const mockData=ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
||||
const bpmnElement = ref()
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||
|
||||
const roleOptions = ref<RoleApi.RoleVO[]>([]) // 角色列表
|
||||
const deptTreeOptions = ref() // 部门树
|
||||
const postOptions = ref<PostApi.PostVO[]>([]) // 岗位列表
|
||||
const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||
const userGroupOptions = ref<UserGroupApi.UserGroupVO[]>([]) // 用户组列表
|
||||
|
||||
const resetTaskForm = () => {
|
||||
for (let key in defaultTaskForm.value) {
|
||||
let value
|
||||
if (key === 'candidateUsers' || key === 'candidateGroups') {
|
||||
value = bpmnElement.value?.businessObject[key]
|
||||
? bpmnElement.value.businessObject[key].split(',')
|
||||
: []
|
||||
const businessObject = bpmnElement.value.businessObject
|
||||
if (!businessObject) {
|
||||
return
|
||||
}
|
||||
if (businessObject.candidateStrategy != undefined) {
|
||||
userTaskForm.value.candidateStrategy = parseInt(businessObject.candidateStrategy) as any
|
||||
} else {
|
||||
userTaskForm.value.candidateStrategy = undefined
|
||||
}
|
||||
if (businessObject.candidateParam && businessObject.candidateParam.length > 0) {
|
||||
if (userTaskForm.value.candidateStrategy === 60) {
|
||||
// 特殊:流程表达式,只有一个 input 输入框
|
||||
userTaskForm.value.candidateParam = [businessObject.candidateParam]
|
||||
} else {
|
||||
value = bpmnElement.value?.businessObject[key] || defaultTaskForm.value[key]
|
||||
userTaskForm.value.candidateParam = businessObject.candidateParam
|
||||
.split(',')
|
||||
.map((item) => +item)
|
||||
}
|
||||
userTaskForm.value[key] = value
|
||||
} else {
|
||||
userTaskForm.value.candidateParam = []
|
||||
}
|
||||
}
|
||||
const updateElementTask = (key) => {
|
||||
const taskAttr = Object.create(null)
|
||||
if (key === 'candidateUsers' || key === 'candidateGroups') {
|
||||
taskAttr[key] =
|
||||
userTaskForm.value[key] && userTaskForm.value[key].length
|
||||
? userTaskForm.value[key].join()
|
||||
: null
|
||||
} else {
|
||||
taskAttr[key] = userTaskForm.value[key] || null
|
||||
}
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), taskAttr)
|
||||
|
||||
/** 更新 candidateStrategy 字段时,需要清空 candidateParam,并触发 bpmn 图更新 */
|
||||
const changeCandidateStrategy = () => {
|
||||
userTaskForm.value.candidateParam = []
|
||||
updateElementTask()
|
||||
}
|
||||
|
||||
/** 选中某个 options 时候,更新 bpmn 图 */
|
||||
const updateElementTask = () => {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
candidateStrategy: userTaskForm.value.candidateStrategy,
|
||||
candidateParam: userTaskForm.value.candidateParam.join(',')
|
||||
})
|
||||
}
|
||||
|
||||
// 打开监听器弹窗
|
||||
const processExpressionDialogRef = ref()
|
||||
const openProcessExpressionDialog = async () => {
|
||||
processExpressionDialogRef.value.open()
|
||||
}
|
||||
const selectProcessExpression = (expression) => {
|
||||
userTaskForm.value.candidateParam = [expression.expression]
|
||||
}
|
||||
|
||||
watch(
|
||||
@@ -92,6 +211,21 @@ watch(
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
// 获得角色列表
|
||||
roleOptions.value = await RoleApi.getSimpleRoleList()
|
||||
// 获得部门列表
|
||||
const deptOptions = await DeptApi.getSimpleDeptList()
|
||||
deptTreeOptions.value = handleTree(deptOptions, 'id')
|
||||
// 获得岗位列表
|
||||
postOptions.value = await PostApi.getSimplePostList()
|
||||
// 获得用户列表
|
||||
userOptions.value = await UserApi.getSimpleUserList()
|
||||
// 获得用户组列表
|
||||
userGroupOptions.value = await UserGroupApi.getUserGroupSimpleList()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
bpmnElement.value = null
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import { toRaw } from 'vue'
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||
// 创建监听器实例
|
||||
export function createListenerObject(options, isTask, prefix) {
|
||||
debugger
|
||||
const listenerObj = Object.create(null)
|
||||
listenerObj.event = options.event
|
||||
isTask && (listenerObj.id = options.id) // 任务监听器特有的 id 字段
|
||||
|
||||
@@ -195,7 +195,7 @@ export default defineComponent({
|
||||
</div>
|
||||
<Menu
|
||||
class={[
|
||||
'!absolute top-0',
|
||||
'!absolute top-0 z-11',
|
||||
{
|
||||
'!left-[var(--tab-menu-min-width)]': unref(collapse),
|
||||
'!left-[var(--tab-menu-max-width)]': !unref(collapse),
|
||||
|
||||
@@ -2,23 +2,24 @@ import * as echarts from 'echarts/core'
|
||||
|
||||
import {
|
||||
BarChart,
|
||||
FunnelChart,
|
||||
GaugeChart,
|
||||
LineChart,
|
||||
PieChart,
|
||||
MapChart,
|
||||
PictorialBarChart,
|
||||
RadarChart,
|
||||
GaugeChart
|
||||
PieChart,
|
||||
RadarChart
|
||||
} from 'echarts/charts'
|
||||
|
||||
import {
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
PolarComponent,
|
||||
AriaComponent,
|
||||
ParallelComponent,
|
||||
GridComponent,
|
||||
LegendComponent,
|
||||
ParallelComponent,
|
||||
PolarComponent,
|
||||
TitleComponent,
|
||||
ToolboxComponent,
|
||||
TooltipComponent,
|
||||
VisualMapComponent
|
||||
} from 'echarts/components'
|
||||
|
||||
@@ -41,7 +42,8 @@ echarts.use([
|
||||
CanvasRenderer,
|
||||
PictorialBarChart,
|
||||
RadarChart,
|
||||
GaugeChart
|
||||
GaugeChart,
|
||||
FunnelChart
|
||||
])
|
||||
|
||||
export default echarts
|
||||
@@ -1,22 +1,27 @@
|
||||
import type { App } from 'vue'
|
||||
// 👇使用 form-create 需额外全局引入 element plus 组件
|
||||
import {
|
||||
ElAlert,
|
||||
ElAside,
|
||||
ElPopconfirm,
|
||||
ElHeader,
|
||||
ElMain,
|
||||
ElContainer,
|
||||
ElDivider,
|
||||
ElTransfer,
|
||||
ElAlert,
|
||||
ElTabs,
|
||||
ElHeader,
|
||||
ElMain,
|
||||
ElPopconfirm,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElTabPane
|
||||
ElTabPane,
|
||||
ElTabs,
|
||||
ElTransfer
|
||||
} from 'element-plus'
|
||||
|
||||
import FcDesigner from '@form-create/designer'
|
||||
import formCreate from '@form-create/element-ui'
|
||||
import install from '@form-create/element-ui/auto-import'
|
||||
//======================= 自定义组件 =======================
|
||||
import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile'
|
||||
import { DictSelect } from '@/components/DictSelect'
|
||||
import UserSelect from '@/views/system/user/components/UserSelect.vue'
|
||||
import { Editor } from '@/components/Editor'
|
||||
|
||||
const components = [
|
||||
ElAside,
|
||||
@@ -30,7 +35,13 @@ const components = [
|
||||
ElTabs,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElTabPane
|
||||
ElTabPane,
|
||||
UploadImg,
|
||||
UploadImgs,
|
||||
UploadFile,
|
||||
DictSelect,
|
||||
UserSelect,
|
||||
Editor
|
||||
]
|
||||
|
||||
// 参考 http://www.form-create.com/v3/element-ui/auto-import.html 文档
|
||||
@@ -40,4 +51,5 @@ export const setupFormCreate = (app: App<Element>) => {
|
||||
})
|
||||
formCreate.use(install)
|
||||
app.use(formCreate)
|
||||
app.use(FcDesigner)
|
||||
}
|
||||
@@ -243,7 +243,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '/manager/form/edit',
|
||||
path: 'manager/form/edit',
|
||||
component: () => import('@/views/bpm/form/editor/index.vue'),
|
||||
name: 'BpmFormEditor',
|
||||
meta: {
|
||||
@@ -255,7 +255,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/manager/model/edit',
|
||||
path: 'manager/model/edit',
|
||||
component: () => import('@/views/bpm/model/editor/index.vue'),
|
||||
name: 'BpmModelEditor',
|
||||
meta: {
|
||||
@@ -267,7 +267,19 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/manager/definition',
|
||||
path: 'manager/simple/workflow/model/edit',
|
||||
component: () => import('@/views/bpm/simpleWorkflow/index.vue'),
|
||||
name: 'SimpleWorkflowDesignEditor',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '仿钉钉设计流程',
|
||||
activeMenu: '/bpm/manager/model'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'manager/definition',
|
||||
component: () => import('@/views/bpm/definition/index.vue'),
|
||||
name: 'BpmProcessDefinition',
|
||||
meta: {
|
||||
@@ -279,30 +291,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/manager/task-assign-rule',
|
||||
component: () => import('@/views/bpm/taskAssignRule/index.vue'),
|
||||
name: 'BpmTaskAssignRuleList',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '任务分配规则'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/process-instance/create',
|
||||
component: () => import('@/views/bpm/processInstance/create/index.vue'),
|
||||
name: 'BpmProcessInstanceCreate',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '发起流程',
|
||||
activeMenu: 'bpm/processInstance/create'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/process-instance/detail',
|
||||
path: 'process-instance/detail',
|
||||
component: () => import('@/views/bpm/processInstance/detail/index.vue'),
|
||||
name: 'BpmProcessInstanceDetail',
|
||||
meta: {
|
||||
@@ -310,11 +299,11 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '流程详情',
|
||||
activeMenu: 'bpm/processInstance/detail'
|
||||
activeMenu: '/bpm/task/my'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/bpm/oa/leave/create',
|
||||
path: 'oa/leave/create',
|
||||
component: () => import('@/views/bpm/oa/leave/create.vue'),
|
||||
name: 'OALeaveCreate',
|
||||
meta: {
|
||||
@@ -326,7 +315,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/bpm/oa/leave/detail',
|
||||
path: 'oa/leave/detail',
|
||||
component: () => import('@/views/bpm/oa/leave/detail.vue'),
|
||||
name: 'OALeaveDetail',
|
||||
meta: {
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { store } from '../index'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useWorkFlowStore = defineStore('simpleWorkflow', {
|
||||
state: () => ({
|
||||
tableId: '',
|
||||
isTried: false,
|
||||
promoterDrawer: false,
|
||||
flowPermission1: {},
|
||||
approverDrawer: false,
|
||||
approverConfig1: {},
|
||||
copyerDrawer: false,
|
||||
copyerConfig1: {},
|
||||
conditionDrawer: false,
|
||||
conditionsConfig1: {
|
||||
conditionNodes: []
|
||||
}
|
||||
}),
|
||||
actions: {
|
||||
setTableId(payload) {
|
||||
this.tableId = payload
|
||||
},
|
||||
setIsTried(payload) {
|
||||
this.isTried = payload
|
||||
},
|
||||
setPromoter(payload) {
|
||||
this.promoterDrawer = payload
|
||||
},
|
||||
setFlowPermission(payload) {
|
||||
this.flowPermission1 = payload
|
||||
},
|
||||
setApprover(payload) {
|
||||
this.approverDrawer = payload
|
||||
},
|
||||
setApproverConfig(payload) {
|
||||
this.approverConfig1 = payload
|
||||
},
|
||||
setCopyer(payload) {
|
||||
this.copyerDrawer = payload
|
||||
},
|
||||
setCopyerConfig(payload) {
|
||||
this.copyerConfig1 = payload
|
||||
},
|
||||
setCondition(payload) {
|
||||
this.conditionDrawer = payload
|
||||
},
|
||||
setConditionsConfig(payload) {
|
||||
this.conditionsConfig1 = payload
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const useWorkFlowStoreWithOut = () => {
|
||||
return useWorkFlowStore(store)
|
||||
}
|
||||
@@ -248,15 +248,15 @@ export const CouponTemplateTakeTypeEnum = {
|
||||
*/
|
||||
export const PromotionProductScopeEnum = {
|
||||
ALL: {
|
||||
scope: 10,
|
||||
scope: 1,
|
||||
name: '通用劵'
|
||||
},
|
||||
SPU: {
|
||||
scope: 20,
|
||||
scope: 2,
|
||||
name: '商品劵'
|
||||
},
|
||||
CATEGORY: {
|
||||
scope: 30,
|
||||
scope: 3,
|
||||
name: '品类劵'
|
||||
}
|
||||
}
|
||||
|
||||
+16
-14
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* 数据字典工具类
|
||||
*/
|
||||
import { useDictStoreWithOut } from '@/store/modules/dict'
|
||||
import { ElementPlusInfoType } from '@/types/elementPlus'
|
||||
import {useDictStoreWithOut} from '@/store/modules/dict'
|
||||
import {ElementPlusInfoType} from '@/types/elementPlus'
|
||||
|
||||
const dictStore = useDictStoreWithOut()
|
||||
|
||||
@@ -104,6 +104,7 @@ export enum DICT_TYPE {
|
||||
USER_TYPE = 'user_type',
|
||||
COMMON_STATUS = 'common_status',
|
||||
TERMINAL = 'terminal', // 终端
|
||||
DATE_INTERVAL = 'date_interval', // 数据间隔
|
||||
|
||||
// ========== SYSTEM 模块 ==========
|
||||
SYSTEM_USER_SEX = 'system_user_sex',
|
||||
@@ -111,7 +112,6 @@ export enum DICT_TYPE {
|
||||
SYSTEM_ROLE_TYPE = 'system_role_type',
|
||||
SYSTEM_DATA_SCOPE = 'system_data_scope',
|
||||
SYSTEM_NOTICE_TYPE = 'system_notice_type',
|
||||
SYSTEM_OPERATE_TYPE = 'system_operate_type',
|
||||
SYSTEM_LOGIN_TYPE = 'system_login_type',
|
||||
SYSTEM_LOGIN_RESULT = 'system_login_result',
|
||||
SYSTEM_SMS_CHANNEL_CODE = 'system_sms_channel_code',
|
||||
@@ -134,15 +134,16 @@ export enum DICT_TYPE {
|
||||
INFRA_CODEGEN_FRONT_TYPE = 'infra_codegen_front_type',
|
||||
INFRA_CODEGEN_SCENE = 'infra_codegen_scene',
|
||||
INFRA_FILE_STORAGE = 'infra_file_storage',
|
||||
INFRA_OPERATE_TYPE = 'infra_operate_type',
|
||||
|
||||
// ========== BPM 模块 ==========
|
||||
BPM_MODEL_CATEGORY = 'bpm_model_category',
|
||||
BPM_MODEL_FORM_TYPE = 'bpm_model_form_type',
|
||||
BPM_TASK_ASSIGN_RULE_TYPE = 'bpm_task_assign_rule_type',
|
||||
BPM_TASK_CANDIDATE_STRATEGY = 'bpm_task_candidate_strategy',
|
||||
BPM_PROCESS_INSTANCE_STATUS = 'bpm_process_instance_status',
|
||||
BPM_PROCESS_INSTANCE_RESULT = 'bpm_process_instance_result',
|
||||
BPM_TASK_ASSIGN_SCRIPT = 'bpm_task_assign_script',
|
||||
BPM_TASK_STATUS = 'bpm_task_status',
|
||||
BPM_OA_LEAVE_TYPE = 'bpm_oa_leave_type',
|
||||
BPM_PROCESS_LISTENER_TYPE = 'bpm_process_listener_type',
|
||||
BPM_PROCESS_LISTENER_VALUE_TYPE = 'bpm_process_listener_value_type',
|
||||
|
||||
// ========== PAY 模块 ==========
|
||||
PAY_CHANNEL_CODE = 'pay_channel_code', // 支付渠道编码类型
|
||||
@@ -157,7 +158,7 @@ export enum DICT_TYPE {
|
||||
MP_AUTO_REPLY_REQUEST_MATCH = 'mp_auto_reply_request_match', // 自动回复请求匹配类型
|
||||
MP_MESSAGE_TYPE = 'mp_message_type', // 消息类型
|
||||
|
||||
// ========== MALL - 会员模块 ==========
|
||||
// ========== Member 会员模块 ==========
|
||||
MEMBER_POINT_BIZ_TYPE = 'member_point_biz_type', // 积分的业务类型
|
||||
MEMBER_EXPERIENCE_BIZ_TYPE = 'member_experience_biz_type', // 会员经验业务类型
|
||||
|
||||
@@ -196,14 +197,15 @@ export enum DICT_TYPE {
|
||||
// ========== CRM - 客户管理模块 ==========
|
||||
CRM_AUDIT_STATUS = 'crm_audit_status', // CRM 审批状态
|
||||
CRM_BIZ_TYPE = 'crm_biz_type', // CRM 业务类型
|
||||
CRM_BUSINESS_END_STATUS_TYPE = 'crm_business_end_status_type', // CRM 商机结束状态类型
|
||||
CRM_RECEIVABLE_RETURN_TYPE = 'crm_receivable_return_type', // CRM 回款的还款方式
|
||||
CRM_CUSTOMER_INDUSTRY = 'crm_customer_industry',
|
||||
CRM_CUSTOMER_LEVEL = 'crm_customer_level',
|
||||
CRM_CUSTOMER_SOURCE = 'crm_customer_source',
|
||||
CRM_PRODUCT_STATUS = 'crm_product_status',
|
||||
CRM_CUSTOMER_INDUSTRY = 'crm_customer_industry', // CRM 客户所属行业
|
||||
CRM_CUSTOMER_LEVEL = 'crm_customer_level', // CRM 客户级别
|
||||
CRM_CUSTOMER_SOURCE = 'crm_customer_source', // CRM 客户来源
|
||||
CRM_PRODUCT_STATUS = 'crm_product_status', // CRM 商品状态
|
||||
CRM_PERMISSION_LEVEL = 'crm_permission_level', // CRM 数据权限的级别
|
||||
CRM_PRODUCT_UNIT = 'crm_product_unit', // 产品单位
|
||||
CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type', // 跟进方式
|
||||
CRM_PRODUCT_UNIT = 'crm_product_unit', // CRM 产品单位
|
||||
CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type', // CRM 跟进方式
|
||||
|
||||
// ========== ERP - 企业资源计划模块 ==========
|
||||
ERP_AUDIT_STATUS = 'erp_audit_status', // ERP 审批状态
|
||||
|
||||
@@ -28,7 +28,7 @@ export const decodeFields = (fields: string[]) => {
|
||||
return rule
|
||||
}
|
||||
|
||||
// 设置表单的 Conf 和 Fields
|
||||
// 设置表单的 Conf 和 Fields,适用 FcDesigner 场景
|
||||
export const setConfAndFields = (designerRef: object, conf: string, fields: string) => {
|
||||
// @ts-ignore
|
||||
designerRef.value.setOption(JSON.parse(conf))
|
||||
@@ -36,19 +36,22 @@ export const setConfAndFields = (designerRef: object, conf: string, fields: stri
|
||||
designerRef.value.setRule(decodeFields(fields))
|
||||
}
|
||||
|
||||
// 设置表单的 Conf 和 Fields
|
||||
// 设置表单的 Conf 和 Fields,适用 form-create 场景
|
||||
export const setConfAndFields2 = (
|
||||
detailPreview: object,
|
||||
conf: string,
|
||||
fields: string,
|
||||
fields: string[],
|
||||
value?: object
|
||||
) => {
|
||||
if (isRef(detailPreview)) {
|
||||
detailPreview = detailPreview.value
|
||||
}
|
||||
// @ts-ignore
|
||||
detailPreview.value.option = JSON.parse(conf)
|
||||
detailPreview.option = JSON.parse(conf)
|
||||
// @ts-ignore
|
||||
detailPreview.value.rule = decodeFields(fields)
|
||||
detailPreview.rule = decodeFields(fields)
|
||||
if (value) {
|
||||
// @ts-ignore
|
||||
detailPreview.value.value = value
|
||||
detailPreview.value = value
|
||||
}
|
||||
}
|
||||
Loaded 100 of 233 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user