diff --git a/.env.dev b/.env.dev
index 2008a002..dc7d2502 100644
--- a/.env.dev
+++ b/.env.dev
@@ -32,3 +32,6 @@ VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
# 验证码的开关
VITE_APP_CAPTCHA_ENABLE=true
+
+# GoView域名
+VITE_GOVIEW_URL='http://127.0.0.1:3000'
\ No newline at end of file
diff --git a/.env.local b/.env.local
index ad084700..35765584 100644
--- a/.env.local
+++ b/.env.local
@@ -29,3 +29,6 @@ VITE_MALL_H5_DOMAIN='http://localhost:3000'
# 验证码的开关
VITE_APP_CAPTCHA_ENABLE=false
+
+# GoView域名
+VITE_GOVIEW_URL='http://127.0.0.1:3000'
\ No newline at end of file
diff --git a/.env.prod b/.env.prod
index 8b78c415..ca7cb8e4 100644
--- a/.env.prod
+++ b/.env.prod
@@ -29,3 +29,6 @@ VITE_OUT_DIR=dist-prod
# 商城H5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
+
+# GoView域名
+VITE_GOVIEW_URL='http://127.0.0.1:3000'
\ No newline at end of file
diff --git a/.env.stage b/.env.stage
index 3d005c7b..084337c6 100644
--- a/.env.stage
+++ b/.env.stage
@@ -29,3 +29,6 @@ VITE_OUT_DIR=dist-stage
# 商城H5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
+
+# GoView域名
+VITE_GOVIEW_URL='http://127.0.0.1:3000'
\ No newline at end of file
diff --git a/.env.test b/.env.test
index 80f4c660..2252e146 100644
--- a/.env.test
+++ b/.env.test
@@ -29,3 +29,6 @@ VITE_OUT_DIR=dist-test
# 商城H5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
+
+# GoView域名
+VITE_GOVIEW_URL='http://127.0.0.1:3000'
\ No newline at end of file
diff --git a/package.json b/package.json
index d2d8b31d..89477d4c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "yudao-ui-admin-vue3",
- "version": "2.3.0-snapshot",
+ "version": "2.4.0-snapshot",
"description": "基于vue3、vite4、element-plus、typesScript",
"author": "xingyu",
"private": false,
@@ -38,7 +38,7 @@
"animate.css": "^4.1.1",
"axios": "^1.6.8",
"benz-amr-recorder": "^1.1.5",
- "bpmn-js-token-simulation": "^0.10.0",
+ "bpmn-js-token-simulation": "^0.36.0",
"camunda-bpmn-moddle": "^7.0.1",
"cropperjs": "^1.6.1",
"crypto-js": "^4.2.0",
@@ -47,7 +47,7 @@
"driver.js": "^1.3.1",
"echarts": "^5.5.0",
"echarts-wordcloud": "^2.1.0",
- "element-plus": "2.8.4",
+ "element-plus": "2.9.1",
"fast-xml-parser": "^4.3.2",
"highlight.js": "^11.9.0",
"jsencrypt": "^3.3.2",
@@ -73,6 +73,7 @@
"vue-i18n": "9.10.2",
"vue-router": "4.4.5",
"vue-types": "^5.1.1",
+ "vue3-signature": "^0.2.4",
"vuedraggable": "^4.1.0",
"web-storage-cache": "^1.1.1",
"xml-js": "^1.6.11"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 226b5c23..ec016eb1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -45,8 +45,8 @@ dependencies:
specifier: ^1.1.5
version: 1.1.5
bpmn-js-token-simulation:
- specifier: ^0.10.0
- version: 0.10.0
+ specifier: ^0.36.0
+ version: 0.36.0
camunda-bpmn-moddle:
specifier: ^7.0.1
version: 7.0.1
@@ -72,8 +72,8 @@ dependencies:
specifier: ^2.1.0
version: 2.1.0(echarts@5.5.1)
element-plus:
- specifier: 2.8.4
- version: 2.8.4(vue@3.5.12)
+ specifier: 2.9.1
+ version: 2.9.1(vue@3.5.12)
fast-xml-parser:
specifier: ^4.3.2
version: 4.5.0
@@ -149,6 +149,9 @@ dependencies:
vue-types:
specifier: ^5.1.1
version: 5.1.3(vue@3.5.12)
+ vue3-signature:
+ specifier: ^0.2.4
+ version: 0.2.4(vue@3.5.12)
vuedraggable:
specifier: ^4.1.0
version: 4.1.0(vue@3.5.12)
@@ -2122,7 +2125,7 @@ packages:
'@form-create/element-ui': 3.2.14(vue@3.5.12)
'@form-create/utils': 3.2.14
codemirror: 6.65.7
- element-plus: 2.8.4(vue@3.5.12)
+ element-plus: 2.9.1(vue@3.5.12)
vue: 3.5.12(typescript@5.3.3)
vuedraggable: 4.1.0(vue@3.5.12)
transitivePeerDependencies:
@@ -4581,12 +4584,14 @@ packages:
min-dom: 4.2.1
dev: true
- /bpmn-js-token-simulation@0.10.0:
- resolution: {integrity: sha512-QuZQ/KVXKt9Vl+XENyOBoTW2Aw+uKjuBlKdCJL6El7AyM7DkJ5bZkSYURshId1SkBDdYg2mJ1flSmsrhGuSfwg==, tarball: https://registry.npmmirror.com/bpmn-js-token-simulation/-/bpmn-js-token-simulation-0.10.0.tgz}
+ /bpmn-js-token-simulation@0.36.0:
+ resolution: {integrity: sha512-vz+RHlbZCev/6dzk6FhJRz8M0aZ1GL7Xrza0ecWqeg4tHbgPozgyOm3tXTz75XdtOwRVVBzmCjcciXQX7A55wQ==, tarball: https://registry.npmmirror.com/bpmn-js-token-simulation/-/bpmn-js-token-simulation-0.36.0.tgz}
+ engines: {node: '>= 16'}
dependencies:
- min-dash: 3.8.1
- min-dom: 0.2.0
- svg.js: 2.7.1
+ inherits-browser: 0.1.0
+ min-dash: 4.2.2
+ min-dom: 4.2.1
+ randomcolor: 0.6.2
dev: false
/bpmn-js@17.11.1:
@@ -4927,51 +4932,13 @@ packages:
dot-prop: 5.3.0
dev: true
- /component-classes@1.2.6:
- resolution: {integrity: sha512-hPFGULxdwugu1QWW3SvVOCUHLzO34+a2J6Wqy0c5ASQkfi9/8nZcBB0ZohaEbXOQlCflMAEMmEWk7u7BVs4koA==, tarball: https://registry.npmmirror.com/component-classes/-/component-classes-1.2.6.tgz}
- dependencies:
- component-indexof: 0.0.3
- dev: false
-
- /component-closest@0.1.4:
- resolution: {integrity: sha512-NF9hMj6JKGM5sb6wP/dg7GdJOttaIH9PcTsUNdWcrvu7Kw/5R5swQAFpgaYEHlARrNMyn4Wf7O1PlRej+pt76Q==, tarball: https://registry.npmmirror.com/component-closest/-/component-closest-0.1.4.tgz}
- dependencies:
- component-matches-selector: 0.1.7
- dev: false
-
- /component-delegate@0.2.4:
- resolution: {integrity: sha512-OlpcB/6Fi+kXQPh/TfXnSvvmrU04ghz7vcJh/jgLF0Ni+I+E3WGlKJQbBGDa5X+kVUG8WxOgjP+8iWbz902fPg==, tarball: https://registry.npmmirror.com/component-delegate/-/component-delegate-0.2.4.tgz}
- dependencies:
- component-closest: 0.1.4
- component-event: 0.1.4
- dev: false
-
/component-emitter@1.3.1:
resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==, tarball: https://registry.npmmirror.com/component-emitter/-/component-emitter-1.3.1.tgz}
dev: true
- /component-event@0.1.4:
- resolution: {integrity: sha512-GMwOG8MnUHP1l8DZx1ztFO0SJTFnIzZnBDkXAj8RM2ntV2A6ALlDxgbMY1Fvxlg6WPQ+5IM/a6vg4PEYbjg/Rw==, tarball: https://registry.npmmirror.com/component-event/-/component-event-0.1.4.tgz}
- dev: false
-
/component-event@0.2.1:
resolution: {integrity: sha512-wGA++isMqiDq1jPYeyv2as/Bt/u+3iLW0rEa+8NQ82jAv3TgqMiCM+B2SaBdn2DfLilLjjq736YcezihRYhfxw==, tarball: https://registry.npmmirror.com/component-event/-/component-event-0.2.1.tgz}
- /component-indexof@0.0.3:
- resolution: {integrity: sha512-puDQKvx/64HZXb4hBwIcvQLaLgux8o1CbWl39s41hrIIZDl1lJiD5jc22gj3RBeGK0ovxALDYpIbyjqDUUl0rw==, tarball: https://registry.npmmirror.com/component-indexof/-/component-indexof-0.0.3.tgz}
- dev: false
-
- /component-matches-selector@0.1.7:
- resolution: {integrity: sha512-Yb2+pVBvrqkQVpPaDBF0DYXRreBveXJNrpJs9FnFu8PF6/5IIcz5oDZqiH9nB5hbD2/TmFVN5ZCxBzqu7yFFYQ==, tarball: https://registry.npmmirror.com/component-matches-selector/-/component-matches-selector-0.1.7.tgz}
- dependencies:
- component-query: 0.0.3
- global-object: 1.0.0
- dev: false
-
- /component-query@0.0.3:
- resolution: {integrity: sha512-VgebQseT1hz1Ps7vVp2uaSg+N/gsI5ts3AZUSnN6GMA2M82JH7o+qYifWhmVE/e8w/H48SJuA3nA9uX8zRe95Q==, tarball: https://registry.npmmirror.com/component-query/-/component-query-0.0.3.tgz}
- dev: false
-
/compute-scroll-into-view@1.0.20:
resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==, tarball: https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz}
dev: false
@@ -5521,6 +5488,10 @@ packages:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, tarball: https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz}
dev: true
+ /default-passive-events@2.0.0:
+ resolution: {integrity: sha512-eMtt76GpDVngZQ3ocgvRcNCklUMwID1PaNbCNxfpDXuiOXttSh0HzBbda1HU9SIUsDc02vb7g9+3I5tlqe/qMQ==, tarball: https://registry.npmmirror.com/default-passive-events/-/default-passive-events-2.0.0.tgz}
+ dev: false
+
/define-data-property@1.1.4:
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==, tarball: https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz}
engines: {node: '>= 0.4'}
@@ -5795,8 +5766,8 @@ packages:
resolution: {integrity: sha512-nz88NNBsD7kQSAGGJyp8hS6xSPtWwqNogA0mjtc2nUYeEf3nURK9qpV18TuBdDmEDgVWotS8Wkzf+V52dSQ/LQ==, tarball: https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.67.tgz}
dev: true
- /element-plus@2.8.4(vue@3.5.12):
- resolution: {integrity: sha512-ZlVAdUOoJliv4kW3ntWnnSHMT+u/Os7mXJjk2xzOlqNeHaI2/ozlF+R58ZCEak8ZnDi6+5A2viWEYRsq64IuiA==, tarball: https://registry.npmmirror.com/element-plus/-/element-plus-2.8.4.tgz}
+ /element-plus@2.9.1(vue@3.5.12):
+ resolution: {integrity: sha512-9Agqf/jt4Ugk7EZ6C5LME71sgkvauPCsnvJN12Xid2XVobjufxMGpRE4L7pS4luJMOmFAH3J0NgYEGZT5r+NDg==, tarball: https://registry.npmmirror.com/element-plus/-/element-plus-2.9.1.tgz}
peerDependencies:
vue: ^3.2.0
dependencies:
@@ -6674,10 +6645,6 @@ packages:
global-prefix: 3.0.0
dev: true
- /global-object@1.0.0:
- resolution: {integrity: sha512-mSPSkY6UsHv6hgW0V2dfWBWTS8TnPnLx3ECVNoWp6rBI2Bg66VYoqGoTFlH/l7XhAZ/l+StYlntXlt87BEeCcg==, tarball: https://registry.npmmirror.com/global-object/-/global-object-1.0.0.tgz}
- dev: false
-
/global-prefix@3.0.0:
resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==, tarball: https://registry.npmmirror.com/global-prefix/-/global-prefix-3.0.0.tgz}
engines: {node: '>=6'}
@@ -7899,10 +7866,6 @@ packages:
engines: {node: '>=18'}
dev: true
- /min-dash@3.8.1:
- resolution: {integrity: sha512-evumdlmIlg9mbRVPbC4F5FuRhNmcMS5pvuBUbqb1G9v09Ro0ImPEgz5n3khir83lFok1inKqVDjnKEg3GpDxQg==, tarball: https://registry.npmmirror.com/min-dash/-/min-dash-3.8.1.tgz}
- dev: false
-
/min-dash@4.2.2:
resolution: {integrity: sha512-qbhSYUxk6mBaF096B3JOQSumXbKWHenmT97cSpdNzgkWwGjhjhE/KZODCoDNhI2I4C9Cb6R/Q13S4BYkUSXoXQ==, tarball: https://registry.npmmirror.com/min-dash/-/min-dash-4.2.2.tgz}
@@ -7912,18 +7875,6 @@ packages:
dom-walk: 0.1.2
dev: false
- /min-dom@0.2.0:
- resolution: {integrity: sha512-VmxugbnAcVZGqvepjhOA4d4apmrpX8mMaRS+/jo0dI5Yorzrr4Ru9zc9KVALlY/+XakVCb8iQ+PYXljihQcsNw==, tarball: https://registry.npmmirror.com/min-dom/-/min-dom-0.2.0.tgz}
- dependencies:
- component-classes: 1.2.6
- component-closest: 0.1.4
- component-delegate: 0.2.4
- component-event: 0.1.4
- component-matches-selector: 0.1.7
- component-query: 0.0.3
- domify: 1.4.2
- dev: false
-
/min-dom@4.2.1:
resolution: {integrity: sha512-TMoL8SEEIhUWYgkj7XMSgxmwSyGI+4fP2KFFGnN3FbHfbGHVdsLYSz8LoIsgPhz4dWRmLvxWWSMgzZMJW5sZuA==, tarball: https://registry.npmmirror.com/min-dom/-/min-dom-4.2.1.tgz}
dependencies:
@@ -8714,6 +8665,10 @@ packages:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, tarball: https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz}
dev: true
+ /randomcolor@0.6.2:
+ resolution: {integrity: sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A==, tarball: https://registry.npmmirror.com/randomcolor/-/randomcolor-0.6.2.tgz}
+ dev: false
+
/rd@2.0.1:
resolution: {integrity: sha512-/XdKU4UazUZTXFmI0dpABt8jSXPWcEyaGdk340KdHnsEOdkTctlX23aAK7ChQDn39YGNlAJr1M5uvaKt4QnpNw==, tarball: https://registry.npmmirror.com/rd/-/rd-2.0.1.tgz}
dependencies:
@@ -9128,6 +9083,10 @@ packages:
engines: {node: '>=14'}
dev: true
+ /signature_pad@3.0.0-beta.4:
+ resolution: {integrity: sha512-cOf2NhVuTiuNqe2X/ycEmizvCDXk0DoemhsEpnkcGnA4kS5iJYTCqZ9As7tFBbsch45Q1EdX61833+6sjJ8rrw==, tarball: https://registry.npmmirror.com/signature_pad/-/signature_pad-3.0.0-beta.4.tgz}
+ dev: false
+
/sirv@2.0.4:
resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==, tarball: https://registry.npmmirror.com/sirv/-/sirv-2.0.4.tgz}
engines: {node: '>= 10'}
@@ -9561,10 +9520,6 @@ packages:
resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==, tarball: https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz}
dev: true
- /svg.js@2.7.1:
- resolution: {integrity: sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==, tarball: https://registry.npmmirror.com/svg.js/-/svg.js-2.7.1.tgz}
- dev: false
-
/svgo@2.8.0:
resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==, tarball: https://registry.npmmirror.com/svgo/-/svgo-2.8.0.tgz}
engines: {node: '>=10.13.0'}
@@ -10324,6 +10279,16 @@ packages:
vue: 3.5.12(typescript@5.3.3)
dev: false
+ /vue3-signature@0.2.4(vue@3.5.12):
+ resolution: {integrity: sha512-XFwwFVK9OG3F085pKIq2SlNVqx32WdFH+TXbGEWc5FfEKpx8oMmZuAwZZ50K/pH2FgmJSE8IRwU9DDhrLpd6iA==, tarball: https://registry.npmmirror.com/vue3-signature/-/vue3-signature-0.2.4.tgz}
+ peerDependencies:
+ vue: ^3.2.0
+ dependencies:
+ default-passive-events: 2.0.0
+ signature_pad: 3.0.0-beta.4
+ vue: 3.5.12(typescript@5.3.3)
+ dev: false
+
/vue@3.5.12(typescript@5.3.3):
resolution: {integrity: sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==, tarball: https://registry.npmmirror.com/vue/-/vue-3.5.12.tgz}
peerDependencies:
diff --git a/src/api/bpm/model/index.ts b/src/api/bpm/model/index.ts
index 0c499dba..63b6af6a 100644
--- a/src/api/bpm/model/index.ts
+++ b/src/api/bpm/model/index.ts
@@ -72,3 +72,7 @@ export const deleteModel = async (id: number) => {
export const deployModel = async (id: number) => {
return await request.post({ url: '/bpm/model/deploy?id=' + id })
}
+
+export const cleanModel = async (id: number) => {
+ return await request.delete({ url: '/bpm/model/clean?id=' + id })
+}
diff --git a/src/api/bpm/processInstance/index.ts b/src/api/bpm/processInstance/index.ts
index f97270f9..9a99a91e 100644
--- a/src/api/bpm/processInstance/index.ts
+++ b/src/api/bpm/processInstance/index.ts
@@ -36,6 +36,7 @@ export type ApprovalTaskInfo = {
assigneeUser: User
status: number
reason: string
+ signPicUrl: string
}
// 审批节点信息
@@ -89,7 +90,7 @@ export const getProcessInstanceCopyPage = async (params: any) => {
// 获取审批详情
export const getApprovalDetail = async (params: any) => {
- return await request.get({ url: 'bpm/process-instance/get-approval-detail' , params })
+ return await request.get({ url: 'bpm/process-instance/get-approval-detail', params })
}
// 获取表单字段权限
diff --git a/src/api/login/index.ts b/src/api/login/index.ts
index dec14fb3..8c69d9bc 100644
--- a/src/api/login/index.ts
+++ b/src/api/login/index.ts
@@ -22,11 +22,6 @@ export const register = (data: RegisterVO) => {
return request.post({ url: '/system/auth/register', data })
}
-// 刷新访问令牌
-export const refreshToken = () => {
- return request.post({ url: '/system/auth/refresh-token?refreshToken=' + getRefreshToken() })
-}
-
// 使用租户名,获得租户编号
export const getTenantIdByName = (name: string) => {
return request.get({ url: '/system/tenant/get-id-by-name?name=' + name })
@@ -76,11 +71,17 @@ export const socialAuthRedirect = (type: number, redirectUri: string) => {
})
}
// 获取验证图片以及 token
-export const getCode = (data) => {
+export const getCode = (data: any) => {
+ debugger
return request.postOriginal({ url: 'system/captcha/get', data })
}
// 滑动或者点选验证
-export const reqCheck = (data) => {
+export const reqCheck = (data: any) => {
return request.postOriginal({ url: 'system/captcha/check', data })
}
+
+// 通过短信重置密码
+export const smsResetPassword = (data: any) => {
+ return request.post({ url: '/system/auth/sms-reset-password', data })
+}
diff --git a/src/api/mall/trade/brokerage/user/index.ts b/src/api/mall/trade/brokerage/user/index.ts
index 1fed3bfa..8ed69771 100644
--- a/src/api/mall/trade/brokerage/user/index.ts
+++ b/src/api/mall/trade/brokerage/user/index.ts
@@ -13,6 +13,11 @@ export interface BrokerageUserVO {
avatar: string
}
+// 创建分销用户
+export const createBrokerageUser = (data: any) => {
+ return request.post({ url: '/trade/brokerage-user/create', data })
+}
+
// 查询分销用户列表
export const getBrokerageUserPage = async (params: any) => {
return await request.get({ url: `/trade/brokerage-user/page`, params })
diff --git a/src/assets/svgs/bpm/delay.svg b/src/assets/svgs/bpm/delay.svg
new file mode 100644
index 00000000..cbc31df6
--- /dev/null
+++ b/src/assets/svgs/bpm/delay.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue b/src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue
index 2c3bd541..f6176d23 100644
--- a/src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue
+++ b/src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue
@@ -2,17 +2,17 @@
-

+
-
+
文字
图片
@@ -21,37 +21,40 @@
-
+
-
+
+
+
+
-
+
建议尺寸 56*56
-
+
-
+
-
+
@@ -59,7 +62,7 @@
-
-
+
diff --git a/src/components/DiyEditor/components/mobile/TitleBar/config.ts b/src/components/DiyEditor/components/mobile/TitleBar/config.ts
index d9f0672c..0c104c95 100644
--- a/src/components/DiyEditor/components/mobile/TitleBar/config.ts
+++ b/src/components/DiyEditor/components/mobile/TitleBar/config.ts
@@ -1,9 +1,7 @@
-import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
+import {ComponentStyle, DiyComponent} from '@/components/DiyEditor/util'
/** 标题栏属性 */
export interface TitleBarProperty {
- // 背景图
- bgImgUrl: string
// 偏移
marginLeft: number
// 显示位置
diff --git a/src/components/DiyEditor/components/mobile/TitleBar/index.vue b/src/components/DiyEditor/components/mobile/TitleBar/index.vue
index b75d224e..7b907293 100644
--- a/src/components/DiyEditor/components/mobile/TitleBar/index.vue
+++ b/src/components/DiyEditor/components/mobile/TitleBar/index.vue
@@ -1,21 +1,30 @@
-
-
-
+
+
+
{{ property.title }}
{{ property.description }}
{{ property.more.text }}
-
+
-
-
+
diff --git a/src/components/DiyEditor/index.vue b/src/components/DiyEditor/index.vue
index 700d32bd..643cc50a 100644
--- a/src/components/DiyEditor/index.vue
+++ b/src/components/DiyEditor/index.vue
@@ -12,17 +12,17 @@
@@ -31,21 +31,21 @@
-
+
-

+
@@ -55,43 +55,43 @@
@click="handleComponentSelected(component, index)"
>
handleMoveComponent(index, direction)"
+ :can-move-up="index > 0"
+ :component="element"
+ @click="handleComponentSelected(element, index)"
@copy="handleCopyComponent(index)"
@delete="handleDeleteComponent(index)"
- @click="handleComponentSelected(element, index)"
+ @move="(direction) => handleMoveComponent(index, direction)"
/>
@@ -99,9 +99,9 @@
@@ -109,9 +109,9 @@
@@ -120,10 +120,10 @@
@@ -134,11 +134,11 @@
-
+
@@ -152,8 +152,8 @@
view-class="p-[var(--el-card-padding)] p-b-[calc(var(--el-card-padding)+var(--el-card-padding))] property"
>
@@ -166,8 +166,8 @@
+
+ 是否需要签名
+
+
+
@@ -435,6 +440,9 @@
+
+
+
@@ -484,6 +492,7 @@ import {
import { defaultProps } from '@/utils/tree'
import { cloneDeep } from 'lodash-es'
import { convertTimeUnit, getApproveTypeText } from '../utils'
+import UserTaskListener from './components/UserTaskListener.vue'
defineOptions({
name: 'UserTaskNodeConfig'
})
@@ -609,6 +618,8 @@ const {
cTimeoutMaxRemindCount
} = useTimeoutHandler()
+const userTaskListenerRef = ref()
+
// 保存配置
const saveConfig = async () => {
activeTabName.value = 'user'
@@ -624,7 +635,8 @@ const saveConfig = async () => {
}
if (!formRef) return false
- const valid = await formRef.value.validate()
+ if (!userTaskListenerRef) return false
+ const valid = (await formRef.value.validate()) && (await userTaskListenerRef.value.validate())
if (!valid) return false
const showText = getShowText()
if (!showText) return false
@@ -663,6 +675,29 @@ const saveConfig = async () => {
currentNode.value.fieldsPermission = fieldsPermissionConfig.value
// 设置按钮权限
currentNode.value.buttonsSetting = buttonsSetting.value
+ // 创建任务监听器
+ currentNode.value.taskCreateListener = {
+ enable: configForm.value.taskCreateListenerEnable ?? false,
+ path: configForm.value.taskCreateListenerPath,
+ header: configForm.value.taskCreateListenerHeader,
+ body: configForm.value.taskCreateListenerBody
+ }
+ // 指派任务监听器
+ currentNode.value.taskAssignListener = {
+ enable: configForm.value.taskAssignListenerEnable ?? false,
+ path: configForm.value.taskAssignListenerPath,
+ header: configForm.value.taskAssignListenerHeader,
+ body: configForm.value.taskAssignListenerBody
+ }
+ // 完成任务监听器
+ currentNode.value.taskCompleteListener = {
+ enable: configForm.value.taskCompleteListenerEnable ?? false,
+ path: configForm.value.taskCompleteListenerPath,
+ header: configForm.value.taskCompleteListenerHeader,
+ body: configForm.value.taskCompleteListenerBody
+ }
+ // 签名
+ currentNode.value.signEnable = configForm.value.signEnable
currentNode.value.showText = showText
settingVisible.value = false
@@ -714,6 +749,24 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
buttonsSetting.value = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING
// 4. 表单字段权限配置
getNodeConfigFormFields(node.fieldsPermission)
+ // 5. 监听器
+ // 5.1 创建任务
+ configForm.value.taskCreateListenerEnable = node.taskCreateListener!.enable
+ configForm.value.taskCreateListenerPath = node.taskCreateListener!.path
+ configForm.value.taskCreateListenerHeader = node.taskCreateListener?.header ?? []
+ configForm.value.taskCreateListenerBody = node.taskCreateListener?.body ?? []
+ // 5.2 指派任务
+ configForm.value.taskAssignListenerEnable = node.taskAssignListener!.enable
+ configForm.value.taskAssignListenerPath = node.taskAssignListener!.path
+ configForm.value.taskAssignListenerHeader = node.taskAssignListener?.header ?? []
+ configForm.value.taskAssignListenerBody = node.taskAssignListener?.body ?? []
+ // 5.3 完成任务
+ configForm.value.taskCompleteListenerEnable = node.taskCompleteListener!.enable
+ configForm.value.taskCompleteListenerPath = node.taskCompleteListener!.path
+ configForm.value.taskCompleteListenerHeader = node.taskCompleteListener?.header ?? []
+ configForm.value.taskCompleteListenerBody = node.taskCompleteListener?.body ?? []
+ // 6. 签名
+ configForm.value.signEnable = node?.signEnable ?? false
}
defineExpose({ openDrawer, showUserTaskNodeConfig }) // 暴露方法给父组件
diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue
new file mode 100644
index 00000000..85f6e4a0
--- /dev/null
+++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue
@@ -0,0 +1,263 @@
+
+
+
+
+
+ {{ dict.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/components/UserTaskListener.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/components/UserTaskListener.vue
new file mode 100644
index 00000000..6ab587c7
--- /dev/null
+++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/components/UserTaskListener.vue
@@ -0,0 +1,261 @@
+
+
+
+
+ {{ listener.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 添加一行
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 添加一行
+
+
+
+
+
+
+
+
diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue
new file mode 100644
index 00000000..94f9c413
--- /dev/null
+++ b/src/components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+ {{ currentNode.name }}
+
+
+
+
+ {{ currentNode.showText }}
+
+
+ {{ NODE_DEFAULT_TEXT.get(NodeType.DELAY_TIMER_NODE) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue
index 63aa24e4..0af03106 100644
--- a/src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue
+++ b/src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue
@@ -77,7 +77,7 @@ const props = defineProps({
const currentNode = useWatchNode(props)
// 是否只读
const readonly = inject('readonly')
-const processInstance = inject[>('processInstance')
+const processInstance = inject][>('processInstance', ref({}))
// 审批信息的弹窗显示,用于只读模式
const dialogVisible = ref(false) // 弹窗可见性
const processInstanceInfos = ref([]) // 流程的审批信息
diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/RouterNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/RouterNode.vue
new file mode 100644
index 00000000..452a8bbb
--- /dev/null
+++ b/src/components/SimpleProcessDesignerV2/src/nodes/RouterNode.vue
@@ -0,0 +1,98 @@
+
+ ]
+
+
+
+
+
+
+
+
+
+ {{ currentNode.name }}
+
+
+
+
+ {{ currentNode.showText }}
+
+
+ {{ NODE_DEFAULT_TEXT.get(NodeType.ROUTER_BRANCH_NODE) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue
index 89a57d04..4abe38f0 100644
--- a/src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue
+++ b/src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue
@@ -13,7 +13,7 @@
>
('readonly') // 是否只读
-const tasks = inject[>('tasks')
+const tasks = inject][>('tasks', ref([]))
// 定义事件,更新父组件。
const emits = defineEmits<{
'update:modelValue': [node: SimpleFlowNode | undefined]
diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue
index 761a6743..47ef540c 100644
--- a/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue
+++ b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue
@@ -131,7 +131,7 @@ const emits = defineEmits<{
// 是否只读
const readonly = inject('readonly')
-const tasks = inject][>('tasks')
+const tasks = inject][>('tasks', ref([]))
// 监控节点变化
const currentNode = useWatchNode(props)
// 节点名称编辑
diff --git a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue
index 9d2fa5ba..83d40fbf 100644
--- a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue
+++ b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue
@@ -308,28 +308,6 @@ const props = defineProps({
}
})
-// 监听value变化,重新加载流程图
-watch(
- () => props.value,
- (newValue) => {
- if (newValue && bpmnModeler) {
- createNewDiagram(newValue)
- }
- },
- { immediate: true }
-)
-
-// 监听processId和processName变化
-watch(
- [() => props.processId, () => props.processName],
- ([newId, newName]) => {
- if (newId && newName && !props.value) {
- createNewDiagram(null)
- }
- },
- { immediate: true }
-)
-
provide('configGlobal', props)
let bpmnModeler: any = null
const defaultZoom = ref(1)
@@ -480,6 +458,7 @@ const initModelListeners = () => {
emit('commandStack-changed', event)
emit('input', xml)
emit('change', xml)
+ emit('save', xml)
} catch (e: any) {
console.error(`[Process Designer Warn]: ${e.message || e}`)
}
@@ -568,6 +547,7 @@ const importLocalFile = () => {
reader.onload = function () {
let xmlStr = this.result
createNewDiagram(xmlStr)
+ emit('save', xmlStr)
}
}
/* ------------------------------------------------ refs methods ------------------------------------------------------ */
diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json
index 7fe1fa79..9f3ae16c 100644
--- a/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json
+++ b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json
@@ -1438,6 +1438,31 @@
"isBody": true
}
]
+ },
+ {
+ "name": "SignEnable",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Boolean",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "SkipExpression",
+ "extends": ["bpmn:UserTask"],
+ "properties": [
+ {
+ "name": "skipExpression",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
}
],
"emumerations": []
diff --git a/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue b/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue
index e53ad994..ff08dd33 100644
--- a/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue
+++ b/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue
@@ -1,5 +1,5 @@
- ]
+
diff --git a/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue b/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue
index 70ad4f8b..3172338d 100644
--- a/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue
+++ b/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue
@@ -152,6 +152,9 @@ watch(
handleKeyUpdate(props.model.key)
handleNameUpdate(props.model.name)
}
+ },
+ {
+ immediate: true
}
)
diff --git a/src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue b/src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue
index ba385145..206c3889 100644
--- a/src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue
+++ b/src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue
@@ -5,6 +5,7 @@
4. 操作按钮
5. 字段权限
6. 审批类型
+ 7. 是否需要签名
-->
@@ -161,6 +162,11 @@
+
+
是否需要签名
+
+
+
@@ -218,6 +224,9 @@ const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFie
// 审批类型
const approveType = ref({ value: ApproveType.USER })
+// 是否需要签名
+const signEnable = ref({ value: false })
+
const elExtensionElements = ref()
const otherExtensions = ref()
const bpmnElement = ref()
@@ -325,6 +334,11 @@ const resetCustomConfigList = () => {
ex.$type !== `${prefix}:ApproveType`
) ?? []
+ // 是否需要签名
+ signEnable.value =
+ elExtensionElements.value.values?.filter((ex) => ex.$type === `${prefix}:SignEnable`)?.[0] ||
+ bpmnInstances().moddle.create(`${prefix}:SignEnable`, { value: false })
+
// 更新元素扩展属性,避免后续报错
updateElementExtensions()
}
@@ -373,7 +387,8 @@ const updateElementExtensions = () => {
assignEmptyUserIdsEl.value,
approveType.value,
...buttonsSettingEl.value,
- ...fieldsPermissionEl.value
+ ...fieldsPermissionEl.value,
+ signEnable.value
]
})
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
diff --git a/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue b/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue
index e563bfd6..81088ccc 100644
--- a/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue
+++ b/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue
@@ -192,6 +192,16 @@
+
+
+
+
@@ -220,7 +230,8 @@ const props = defineProps({
const prefix = inject('prefix')
const userTaskForm = ref({
candidateStrategy: undefined, // 分配规则
- candidateParam: [] // 分配选项
+ candidateParam: [], // 分配选项
+ skipExpression: '' // 跳过表达式
})
const bpmnElement = ref()
const bpmnInstances = () => (window as any)?.bpmnInstances
@@ -311,6 +322,13 @@ const resetTaskForm = () => {
(ex) => ex.$type !== `${prefix}:CandidateStrategy` && ex.$type !== `${prefix}:CandidateParam`
) ?? []
+ // 跳过表达式
+ if (businessObject.skipExpression != undefined) {
+ userTaskForm.value.skipExpression = businessObject.skipExpression
+ } else {
+ userTaskForm.value.skipExpression = ''
+ }
+
// 改用通过extensionElements来存储数据
return
if (businessObject.candidateStrategy != undefined) {
@@ -390,6 +408,18 @@ const updateElementTask = () => {
})
}
+const updateSkipExpression = () => {
+ if (userTaskForm.value.skipExpression && userTaskForm.value.skipExpression !== '') {
+ bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+ skipExpression: userTaskForm.value.skipExpression
+ })
+ } else {
+ bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+ skipExpression: null
+ })
+ }
+}
+
// 打开监听器弹窗
const processExpressionDialogRef = ref()
const openProcessExpressionDialog = async () => {
diff --git a/src/components/bpmnProcessDesigner/package/theme/process-designer.scss b/src/components/bpmnProcessDesigner/package/theme/process-designer.scss
index b1ff0af3..bca0258c 100644
--- a/src/components/bpmnProcessDesigner/package/theme/process-designer.scss
+++ b/src/components/bpmnProcessDesigner/package/theme/process-designer.scss
@@ -1,6 +1,4 @@
@use 'bpmn-js-token-simulation/assets/css/bpmn-js-token-simulation.css';
-@use 'bpmn-js-token-simulation/assets/css/font-awesome.min.css';
-@use 'bpmn-js-token-simulation/assets/css/normalize.css';
// 边框被 token-simulation 样式覆盖了
.djs-palette {
@@ -97,12 +95,12 @@
box-sizing: border-box;
}
}
- svg {
- width: 100%;
- height: 100%;
- min-height: 100%;
- overflow: hidden;
- }
+ // svg {
+ // width: 100%;
+ // height: 100%;
+ // min-height: 100%;
+ // overflow: hidden;
+ // }
}
}
diff --git a/src/directives/permission/hasPermi.ts b/src/directives/permission/hasPermi.ts
index 931f44b3..02e2fbc7 100644
--- a/src/directives/permission/hasPermi.ts
+++ b/src/directives/permission/hasPermi.ts
@@ -5,18 +5,10 @@ const { t } = useI18n() // 国际化
export function hasPermi(app: App) {
app.directive('hasPermi', (el, binding) => {
- const { wsCache } = useCache()
const { value } = binding
- const all_permission = '*:*:*'
- const userInfo = wsCache.get(CACHE_KEY.USER)
- const permissions = userInfo?.permissions || []
if (value && value instanceof Array && value.length > 0) {
- const permissionFlag = value
-
- const hasPermissions = permissions.some((permission: string) => {
- return all_permission === permission || permissionFlag.includes(permission)
- })
+ const hasPermissions = hasPermission(value)
if (!hasPermissions) {
el.parentNode && el.parentNode.removeChild(el)
@@ -26,3 +18,14 @@ export function hasPermi(app: App) {
}
})
}
+
+export const hasPermission = (permission: string[]) => {
+ const { wsCache } = useCache()
+ const all_permission = '*:*:*'
+ const userInfo = wsCache.get(CACHE_KEY.USER)
+ const permissions = userInfo?.permissions || []
+
+ return permissions.some((p: string) => {
+ return all_permission === p || permission.includes(p)
+ })
+}
\ No newline at end of file
diff --git a/src/layout/components/Footer/src/Footer.vue b/src/layout/components/Footer/src/Footer.vue
index 62302fca..98ce7e56 100644
--- a/src/layout/components/Footer/src/Footer.vue
+++ b/src/layout/components/Footer/src/Footer.vue
@@ -12,6 +12,9 @@ const prefixCls = getPrefixCls('footer')
const appStore = useAppStore()
const title = computed(() => appStore.getTitle)
+
+// 添加当前年份计算属性
+const currentYear = computed(() => new Date().getFullYear())
@@ -19,6 +22,6 @@ const title = computed(() => appStore.getTitle)
:class="prefixCls"
class="h-[var(--app-footer-height)] bg-[var(--app-content-bg-color)] text-center leading-[var(--app-footer-height)] text-[var(--el-text-color-placeholder)] dark:bg-[var(--el-bg-color)] overflow-hidden"
>
- Copyright ©2022-{{ title }}
+ Copyright ©{{ currentYear }} {{ title }}
diff --git a/src/layout/components/TagsView/src/TagsView.vue b/src/layout/components/TagsView/src/TagsView.vue
index dcbb90fd..af492ba2 100644
--- a/src/layout/components/TagsView/src/TagsView.vue
+++ b/src/layout/components/TagsView/src/TagsView.vue
@@ -12,6 +12,10 @@ import { useDesign } from '@/hooks/web/useDesign'
import { useTemplateRefsList } from '@vueuse/core'
import { ElScrollbar } from 'element-plus'
import { useScrollTo } from '@/hooks/event/useScrollTo'
+import { useTagsView } from '@/hooks/web/useTagsView'
+import { cloneDeep } from 'lodash-es'
+
+defineOptions({ name: 'TagsView' })
const { getPrefixCls } = useDesign()
@@ -19,7 +23,9 @@ const prefixCls = getPrefixCls('tags-view')
const { t } = useI18n()
-const { currentRoute, push, replace } = useRouter()
+const { currentRoute, push } = useRouter()
+
+const { closeAll, closeLeft, closeRight, closeOther, closeCurrent, refreshPage } = useTagsView()
const permissionStore = usePermissionStore()
@@ -31,6 +37,10 @@ const visitedViews = computed(() => tagsViewStore.getVisitedViews)
const affixTagArr = ref([])
+const selectedTag = computed(() => tagsViewStore.getSelectedTag)
+
+const setSelectTag = tagsViewStore.setSelectedTag
+
const appStore = useAppStore()
const tagsViewImmerse = computed(() => appStore.getTagsViewImmerse)
@@ -45,66 +55,30 @@ const initTags = () => {
for (const tag of unref(affixTagArr)) {
// Must have tag name
if (tag.name) {
- tagsViewStore.addVisitedView(tag)
+ tagsViewStore.addVisitedView(cloneDeep(tag))
}
}
}
-const selectedTag = ref()
-
// 新增tag
const addTags = () => {
const { name } = unref(currentRoute)
if (name) {
- selectedTag.value = unref(currentRoute)
+ setSelectTag(unref(currentRoute))
tagsViewStore.addView(unref(currentRoute))
}
- return false
}
// 关闭选中的tag
const closeSelectedTag = (view: RouteLocationNormalizedLoaded) => {
- if (view?.meta?.affix) return
- tagsViewStore.delView(view)
- if (isActive(view)) {
- toLastView()
- }
-}
-
-// 关闭全部
-const closeAllTags = () => {
- tagsViewStore.delAllViews()
- toLastView()
-}
-
-// 关闭其它
-const closeOthersTags = () => {
- tagsViewStore.delOthersViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
-}
-
-// 重新加载
-const refreshSelectedTag = async (view?: RouteLocationNormalizedLoaded) => {
- if (!view) return
- tagsViewStore.delCachedView()
- const { path, query } = view
- await nextTick()
- replace({
- path: '/redirect' + path,
- query: query
+ closeCurrent(view, () => {
+ if (isActive(view)) {
+ toLastView()
+ }
})
}
-// 关闭左侧
-const closeLeftTags = () => {
- tagsViewStore.delLeftViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
-}
-
-// 关闭右侧
-const closeRightTags = () => {
- tagsViewStore.delRightViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
-}
-
-// 跳转到最后一个
+// 去最后一个
const toLastView = () => {
const visitedViews = tagsViewStore.getVisitedViews
const latestView = visitedViews.slice(-1)[0]
@@ -118,11 +92,38 @@ const toLastView = () => {
addTags()
return
}
- // TODO: You can set another route
- push('/')
+ // You can set another route
+ push(permissionStore.getAddRouters[0].path)
}
}
+// 关闭全部
+const closeAllTags = () => {
+ closeAll(() => {
+ toLastView()
+ })
+}
+
+// 关闭其它
+const closeOthersTags = () => {
+ closeOther()
+}
+
+// 重新加载
+const refreshSelectedTag = async (view?: RouteLocationNormalizedLoaded) => {
+ refreshPage(view)
+}
+
+// 关闭左侧
+const closeLeftTags = () => {
+ closeLeft()
+}
+
+// 关闭右侧
+const closeRightTags = () => {
+ closeRight()
+}
+
// 滚动到选中的tag
const moveToCurrentTag = async () => {
await nextTick()
@@ -209,13 +210,14 @@ const isActive = (route: RouteLocationNormalizedLoaded): boolean => {
// 所有右键菜单组件的元素
const itemRefs = useTemplateRefsList>()
-// 右键菜单装填改变的时候
+// 右键菜单状态改变的时候
const visibleChange = (visible: boolean, tagItem: RouteLocationNormalizedLoaded) => {
if (visible) {
for (const v of unref(itemRefs)) {
const elDropdownMenuRef = v.elDropdownMenuRef
if (tagItem.fullPath !== v.tagItem.fullPath) {
elDropdownMenuRef?.handleClose()
+ setSelectTag(tagItem)
}
}
}
@@ -243,7 +245,17 @@ const move = (to: number) => {
start()
}
-onMounted(() => {
+const canShowIcon = (item: RouteLocationNormalizedLoaded) => {
+ if (
+ (item?.matched?.[1]?.meta?.icon && unref(tagsViewIcon)) ||
+ (item?.meta?.affix && unref(tagsViewIcon) && item?.meta?.icon)
+ ) {
+ return true
+ }
+ return false
+}
+
+onBeforeMount(() => {
initTags()
addTags()
})
diff --git a/src/layout/components/useRenderLayout.tsx b/src/layout/components/useRenderLayout.tsx
index 5cae84dc..a631aa06 100644
--- a/src/layout/components/useRenderLayout.tsx
+++ b/src/layout/components/useRenderLayout.tsx
@@ -197,7 +197,7 @@ export const useRenderLayout = () => {
`${prefixCls}-content-scrollbar`,
{
'!h-[calc(100%-var(--tags-view-height))] mt-[calc(var(--tags-view-height))]':
- fixedHeader.value
+ fixedHeader.value && tagsView.value
}
]}
>
diff --git a/src/locales/en.ts b/src/locales/en.ts
index 6562c9b7..505cfd80 100644
--- a/src/locales/en.ts
+++ b/src/locales/en.ts
@@ -140,7 +140,10 @@ export default {
btnQRCode: 'QR code sign in',
qrcode: 'Scan the QR code to log in',
btnRegister: 'Sign up',
- SmsSendMsg: 'code has been sent'
+ SmsSendMsg: 'code has been sent',
+ resetPassword: "Reset Password",
+ resetPasswordSuccess: "Reset Password Success",
+ invalidTenantName:"Invalid Tenant Name"
},
captcha: {
verification: 'Please complete security verification',
diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts
index b9deb3f2..130d5652 100644
--- a/src/locales/zh-CN.ts
+++ b/src/locales/zh-CN.ts
@@ -141,7 +141,10 @@ export default {
btnQRCode: '二维码登录',
qrcode: '扫描二维码登录',
btnRegister: '注册',
- SmsSendMsg: '验证码已发送'
+ SmsSendMsg: '验证码已发送',
+ resetPassword: "重置密码",
+ resetPasswordSuccess: "重置密码成功",
+ invalidTenantName: "无效的租户名称"
},
captcha: {
verification: '请完成安全验证',
diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts
index 806f954d..4b177ae8 100644
--- a/src/router/modules/remaining.ts
+++ b/src/router/modules/remaining.ts
@@ -344,7 +344,8 @@ const remainingRouter: AppRouteRecordRaw[] = [
}
},
{
- path: 'manager/model/update/:id',
+ // TODO @zws:1)建议,在加一个路由。然后标题是“复制流程”,这样体验会好点;2)复制出来的数据,在名字前面,加“副本 ”,和钉钉保持一致!
+ path: 'manager/model/:type/:id',
component: () => import('@/views/bpm/model/form/index.vue'),
name: 'BpmModelUpdate',
meta: {
diff --git a/src/store/modules/tagsView.ts b/src/store/modules/tagsView.ts
index 4368efe0..2b2d817f 100644
--- a/src/store/modules/tagsView.ts
+++ b/src/store/modules/tagsView.ts
@@ -4,16 +4,19 @@ import { getRawRoute } from '@/utils/routerHelper'
import { defineStore } from 'pinia'
import { store } from '../index'
import { findIndex } from '@/utils'
+import { useUserStoreWithOut } from './user'
export interface TagsViewState {
visitedViews: RouteLocationNormalizedLoaded[]
cachedViews: Set
+ selectedTag?: RouteLocationNormalizedLoaded
}
export const useTagsViewStore = defineStore('tagsView', {
state: (): TagsViewState => ({
visitedViews: [],
- cachedViews: new Set()
+ cachedViews: new Set(),
+ selectedTag: undefined
}),
getters: {
getVisitedViews(): RouteLocationNormalizedLoaded[] {
@@ -21,6 +24,9 @@ export const useTagsViewStore = defineStore('tagsView', {
},
getCachedViews(): string[] {
return Array.from(this.cachedViews)
+ },
+ getSelectedTag(): RouteLocationNormalizedLoaded | undefined {
+ return this.selectedTag
}
},
actions: {
@@ -98,8 +104,12 @@ export const useTagsViewStore = defineStore('tagsView', {
},
// 删除所有tag
delAllVisitedViews() {
+ const userStore = useUserStoreWithOut()
+
// const affixTags = this.visitedViews.filter((tag) => tag.meta.affix)
- this.visitedViews = []
+ this.visitedViews = userStore.getUser
+ ? this.visitedViews.filter((tag) => tag?.meta?.affix)
+ : []
},
// 删除其他
delOthersViews(view: RouteLocationNormalizedLoaded) {
@@ -145,6 +155,18 @@ export const useTagsViewStore = defineStore('tagsView', {
break
}
}
+ },
+ // 设置当前选中的 tag
+ setSelectedTag(tag: RouteLocationNormalizedLoaded) {
+ this.selectedTag = tag
+ },
+ setTitle(title: string, path?: string) {
+ for (const v of this.visitedViews) {
+ if (v.path === (path ?? this.selectedTag?.path)) {
+ v.meta.title = title
+ break
+ }
+ }
}
},
persist: false
diff --git a/src/utils/download.ts b/src/utils/download.ts
index 5bbfb9fe..32fc624b 100644
--- a/src/utils/download.ts
+++ b/src/utils/download.ts
@@ -33,6 +33,10 @@ const download = {
markdown: (data: Blob, fileName: string) => {
download0(data, fileName, 'text/markdown')
},
+ // 下载 Json 方法
+ json: (data: Blob, fileName: string) => {
+ download0(data, fileName, 'application/json')
+ },
// 下载图片(允许跨域)
image: ({
url,
@@ -65,6 +69,31 @@ const download = {
a.download = 'image.png'
a.click()
}
+ },
+ base64ToFile: (base64: any, fileName: string) => {
+ // 将base64按照 , 进行分割 将前缀 与后续内容分隔开
+ const data = base64.split(',')
+ // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等)
+ const type = data[0].match(/:(.*?);/)[1]
+ // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp)
+ const suffix = type.split('/')[1]
+ // 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出
+ const bstr = window.atob(data[1])
+ // 获取解码结果字符串的长度
+ let n = bstr.length
+ // 根据解码结果字符串的长度创建一个等长的整形数字数组
+ // 但在创建时 所有元素初始值都为 0
+ const u8arr = new Uint8Array(n)
+ // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
+ while (n--) {
+ // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元
+ u8arr[n] = bstr.charCodeAt(n)
+ }
+
+ // 将File文件对象返回给方法的调用者
+ return new File([u8arr], `${fileName}.${suffix}`, {
+ type: type
+ })
}
}
diff --git a/src/utils/routerHelper.ts b/src/utils/routerHelper.ts
index b65f93a0..f9f95c43 100644
--- a/src/utils/routerHelper.ts
+++ b/src/utils/routerHelper.ts
@@ -73,7 +73,7 @@ export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecord
noCache: !route.keepAlive,
alwaysShow:
route.children &&
- route.children.length === 1 &&
+ route.children.length > 0 &&
(route.alwaysShow !== undefined ? route.alwaysShow : true)
} as any
// 特殊逻辑:如果后端配置的 MenuDO.component 包含 ?,则表示需要传递参数
@@ -100,7 +100,6 @@ export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecord
//处理顶级非目录路由
if (!route.children && route.parentId == 0 && route.component) {
data.component = Layout
- data.meta = {}
data.name = toCamelCase(route.path, true) + 'Parent'
data.redirect = ''
meta.alwaysShow = true
diff --git a/src/utils/tree.ts b/src/utils/tree.ts
index 91059ef9..e5db503f 100644
--- a/src/utils/tree.ts
+++ b/src/utils/tree.ts
@@ -376,6 +376,9 @@ export const treeToString = (tree: any[], nodeId) => {
let str = ''
function performAThoroughValidation(arr) {
+ if (typeof arr === 'undefined' || !Array.isArray(arr) || arr.length === 0) {
+ return false
+ }
for (const item of arr) {
if (item.id === nodeId) {
str += ` / ${item.name}`
diff --git a/src/views/Login/Login.vue b/src/views/Login/Login.vue
index ff6f068a..b2ff3809 100644
--- a/src/views/Login/Login.vue
+++ b/src/views/Login/Login.vue
@@ -59,6 +59,8 @@
+
+
@@ -73,7 +75,7 @@ import { useAppStore } from '@/store/modules/app'
import { ThemeSwitch } from '@/layout/components/ThemeSwitch'
import { LocaleDropdown } from '@/layout/components/LocaleDropdown'
-import { LoginForm, MobileForm, QrCodeForm, RegisterForm, SSOLoginVue } from './components'
+import { LoginForm, MobileForm, QrCodeForm, RegisterForm, SSOLoginVue, ForgetPasswordForm } from './components'
defineOptions({ name: 'Login' })
diff --git a/src/views/Login/SocialLogin.vue b/src/views/Login/SocialLogin.vue
index 37c50da1..e0caace8 100644
--- a/src/views/Login/SocialLogin.vue
+++ b/src/views/Login/SocialLogin.vue
@@ -133,6 +133,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('login.getSmsCode') }}
+
+
+ {{ mobileCodeTimer }}秒后可重新获取
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/Login/components/LoginForm.vue b/src/views/Login/components/LoginForm.vue
index 0bdf55c5..193f4781 100644
--- a/src/views/Login/components/LoginForm.vue
+++ b/src/views/Login/components/LoginForm.vue
@@ -59,7 +59,13 @@
- {{ t('login.forgetPassword') }}
+
+ {{ t('login.forgetPassword') }}
+
@@ -76,6 +82,7 @@
{
}
const loading = ref() // ElLoading.service 返回的实例
// 登录
-const handleLogin = async (params) => {
+const handleLogin = async (params: any) => {
loginLoading.value = true
try {
await getTenantId()
@@ -273,7 +280,7 @@ const handleLogin = async (params) => {
if (redirect.value.indexOf('sso') !== -1) {
window.location.href = window.location.href.replace('/login?redirect=', '')
} else {
- push({ path: redirect.value || permissionStore.addRouters[0].path })
+ await push({ path: redirect.value || permissionStore.addRouters[0].path })
}
} finally {
loginLoading.value = false
@@ -313,8 +320,7 @@ const doSocialLogin = async (type: number) => {
encodeURIComponent(`type=${type}&redirect=${redirect.value || '/'}`)
// 进行跳转
- const res = await LoginApi.socialAuthRedirect(type, encodeURIComponent(redirectUri))
- window.location.href = res
+ window.location.href = await LoginApi.socialAuthRedirect(type, encodeURIComponent(redirectUri))
}
}
watch(
diff --git a/src/views/Login/components/RegisterForm.vue b/src/views/Login/components/RegisterForm.vue
index 334887da..73f276ca 100644
--- a/src/views/Login/components/RegisterForm.vue
+++ b/src/views/Login/components/RegisterForm.vue
@@ -85,6 +85,7 @@
+
@@ -90,7 +91,7 @@
-
+
全部可见
@@ -110,7 +111,7 @@
-
+
- 设计
+ 复制
{{ scope.row.processDefinition.suspensionState === 1 ? '停用' : '启用' }}
+
+ 清理
+
-
-
-
-
-
diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue
index 37eff739..50386487 100644
--- a/src/views/bpm/model/editor/index.vue
+++ b/src/views/bpm/model/editor/index.vue
@@ -12,10 +12,12 @@
:additionalModel="controlForm.additionalModel"
:model="model"
@save="save"
+ :process-id="modelKey"
+ :process-name="modelName"
/>
()
@@ -51,10 +53,13 @@ const formType = ref(20)
provide('formFields', formFields)
provide('formType', formType)
-const xmlString = ref('') // BPMN XML
+// 注入流程数据
+const xmlString = inject('processData') as Ref
+// 注入模型数据
+const modelData = inject('modelData') as Ref
+
const modeler = shallowRef() // BPMN Modeler
const processDesigner = ref()
-const isModelerReady = ref(false)
const controlForm = ref({
simulation: true,
labelEditing: false,
@@ -65,154 +70,26 @@ const controlForm = ref({
})
const model = ref() // 流程模型的信息
-// 初始化 bpmnInstances
-const initBpmnInstances = () => {
- if (!modeler.value) return false
- try {
- const instances = {
- modeler: modeler.value,
- modeling: modeler.value.get('modeling'),
- moddle: modeler.value.get('moddle'),
- eventBus: modeler.value.get('eventBus'),
- bpmnFactory: modeler.value.get('bpmnFactory'),
- elementFactory: modeler.value.get('elementFactory'),
- elementRegistry: modeler.value.get('elementRegistry'),
- replace: modeler.value.get('replace'),
- selection: modeler.value.get('selection')
- }
-
- // 检查所有实例是否都存在
- return Object.values(instances).every((instance) => instance)
- } catch (error) {
- console.error('初始化 bpmnInstances 失败:', error)
- return false
- }
-}
-
/** 初始化 modeler */
-const initModeler = async (item) => {
- try {
- modeler.value = item
- // 等待 modeler 初始化完成
- await nextTick()
-
- // 确保 modeler 的所有实例都已经准备好
- if (initBpmnInstances()) {
- isModelerReady.value = true
- emit('init-finished')
-
- // 初始化完成后,设置初始值
- if (props.modelId) {
- // 编辑模式
- const data = await ModelApi.getModel(props.modelId)
- model.value = {
- ...data,
- bpmnXml: undefined // 清空 bpmnXml 属性
- }
- xmlString.value = data.bpmnXml || getDefaultBpmnXml(data.key, data.name)
- } else if (props.modelKey && props.modelName) {
- // 新建模式
- xmlString.value = props.value || getDefaultBpmnXml(props.modelKey, props.modelName)
- model.value = {
- key: props.modelKey,
- name: props.modelName
- } as ModelApi.ModelVO
- }
-
- // 导入XML并刷新视图
- await nextTick()
- try {
- await modeler.value.importXML(xmlString.value)
- if (processDesigner.value?.refresh) {
- processDesigner.value.refresh()
- }
- } catch (error) {
- console.error('导入XML失败:', error)
- }
- } else {
- console.error('modeler 实例未完全初始化')
- }
- } catch (error) {
- console.error('初始化 modeler 失败:', error)
- }
-}
-
-/** 获取默认的BPMN XML */
-const getDefaultBpmnXml = (key: string, name: string) => {
- return `
-
-
-
-
-
-`
+const initModeler = async (item: any) => {
+ //先初始化模型数据
+ model.value = modelData.value
+ modeler.value = item
}
/** 添加/修改模型 */
const save = async (bpmnXml: string) => {
try {
xmlString.value = bpmnXml
- if (props.modelId) {
- // 编辑模式
- const data = {
- ...model.value,
- bpmnXml: bpmnXml
- } as unknown as ModelApi.ModelVO
- await ModelApi.updateModelBpmn(data)
- emit('success')
- } else {
- // 新建模式,直接返回XML
- emit('success', bpmnXml)
- }
+ emit('success', bpmnXml)
} catch (error) {
console.error('保存失败:', error)
message.error('保存失败')
}
}
-// 监听 key、name 和 value 的变化
-watch(
- [() => props.modelKey, () => props.modelName, () => props.value],
- async ([newKey, newName, newValue]) => {
- if (!props.modelId && isModelerReady.value) {
- let shouldRefresh = false
-
- if (newKey && newName) {
- const newXml = newValue || getDefaultBpmnXml(newKey, newName)
- if (newXml !== xmlString.value) {
- xmlString.value = newXml
- shouldRefresh = true
- }
- model.value = {
- ...model.value,
- key: newKey,
- name: newName
- } as ModelApi.ModelVO
- } else if (newValue && newValue !== xmlString.value) {
- xmlString.value = newValue
- shouldRefresh = true
- }
-
- if (shouldRefresh) {
- // 确保更新后重新渲染
- await nextTick()
- if (processDesigner.value?.refresh) {
- try {
- await modeler.value?.importXML(xmlString.value)
- processDesigner.value.refresh()
- } catch (error) {
- console.error('导入XML失败:', error)
- }
- }
- }
- }
- },
- { deep: true }
-)
-
// 在组件卸载时清理
onBeforeUnmount(() => {
- isModelerReady.value = false
modeler.value = null
// 清理全局实例
const w = window as any
@@ -220,55 +97,6 @@ onBeforeUnmount(() => {
w.bpmnInstances = null
}
})
-
-/** 获取 XML 字符串 */
-const saveXML = async () => {
- if (!modeler.value) {
- return { xml: xmlString.value }
- }
- try {
- const result = await modeler.value.saveXML({ format: true })
- xmlString.value = result.xml
- return result
- } catch (error) {
- console.error('获取XML失败:', error)
- return { xml: xmlString.value }
- }
-}
-
-/** 获取SVG字符串 */
-const saveSVG = async () => {
- if (!modeler.value) {
- return { svg: undefined }
- }
- try {
- return await modeler.value.saveSVG()
- } catch (error) {
- console.error('获取SVG失败:', error)
- return { svg: undefined }
- }
-}
-
-/** 刷新视图 */
-const refresh = async () => {
- if (processDesigner.value?.refresh && modeler.value) {
- try {
- await modeler.value.importXML(xmlString.value)
- processDesigner.value.refresh()
- } catch (error) {
- console.error('刷新视图失败:', error)
- }
- }
-}
-
-// 暴露必要的属性和方法给父组件
-defineExpose({
- modeler,
- isModelerReady,
- saveXML,
- saveSVG,
- refresh
-})
diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue b/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue
index 56b466a9..fcd5ec89 100644
--- a/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue
+++ b/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue
@@ -25,7 +25,7 @@
-
+
{{ activity.name }}
@@ -113,7 +113,7 @@
-
+
+ 签名:
+
+
diff --git a/src/views/bpm/processInstance/detail/SignDialog.vue b/src/views/bpm/processInstance/detail/SignDialog.vue
new file mode 100644
index 00000000..744a3556
--- /dev/null
+++ b/src/views/bpm/processInstance/detail/SignDialog.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+ 清除
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/bpm/simple/SimpleModelDesign.vue b/src/views/bpm/simple/SimpleModelDesign.vue
index eed00997..09e5a688 100644
--- a/src/views/bpm/simple/SimpleModelDesign.vue
+++ b/src/views/bpm/simple/SimpleModelDesign.vue
@@ -4,9 +4,7 @@
:model-id="modelId"
:model-key="modelKey"
:model-name="modelName"
- :value="currentValue"
@success="handleSuccess"
- @init-finished="handleInit"
:start-user-ids="startUserIds"
ref="designerRef"
/>
@@ -19,137 +17,22 @@ defineOptions({
name: 'SimpleModelDesign'
})
-const props = defineProps<{
+defineProps<{
modelId?: string
modelKey?: string
modelName?: string
- value?: string
startUserIds?: number[]
}>()
-const emit = defineEmits(['success', 'init-finished'])
+const emit = defineEmits(['success'])
const designerRef = ref()
-const isInitialized = ref(false)
-const currentValue = ref('')
-
-// 初始化或更新当前值
-const initOrUpdateValue = async () => {
- console.log('initOrUpdateValue', props.value)
- if (props.value) {
- currentValue.value = props.value
- // 如果设计器已经初始化,立即加载数据
- if (isInitialized.value && designerRef.value) {
- try {
- await designerRef.value.loadProcessData(props.value)
- await nextTick()
- if (designerRef.value.refresh) {
- await designerRef.value.refresh()
- }
- } catch (error) {
- console.error('加载流程数据失败:', error)
- }
- }
- }
-}
-
-// 监听属性变化
-watch(
- [() => props.modelKey, () => props.modelName, () => props.value],
- async ([newKey, newName, newValue], [oldKey, oldName, oldValue]) => {
- if (designerRef.value && isInitialized.value) {
- try {
- if (newKey && newName && (newKey !== oldKey || newName !== oldName)) {
- await designerRef.value.updateModel(newKey, newName)
- }
- if (newValue && newValue !== oldValue) {
- currentValue.value = newValue
- await designerRef.value.loadProcessData(newValue)
- await nextTick()
- if (designerRef.value.refresh) {
- await designerRef.value.refresh()
- }
- }
- } catch (error) {
- console.error('更新流程数据失败:', error)
- }
- }
- },
- { deep: true, immediate: true }
-)
-
-// 初始化完成回调
-const handleInit = async () => {
- try {
- isInitialized.value = true
- emit('init-finished')
-
- // 等待下一个tick,确保设计器已经准备好
- await nextTick()
-
- // 初始化完成后,设置初始值
- if (props.modelKey && props.modelName) {
- await designerRef.value.updateModel(props.modelKey, props.modelName)
- }
- if (props.value) {
- currentValue.value = props.value
- await designerRef.value.loadProcessData(props.value)
- // 再次刷新确保数据正确加载
- await nextTick()
- if (designerRef.value.refresh) {
- await designerRef.value.refresh()
- }
- }
- } catch (error) {
- console.error('初始化流程数据失败:', error)
- }
-}
// 修改成功回调
const handleSuccess = (data?: any) => {
- console.warn('handleSuccess', data)
- if (data && data !== currentValue.value) {
- currentValue.value = data
+ console.info('handleSuccess', data)
+ if (data) {
emit('success', data)
}
}
-
-/** 获取当前流程数据 */
-const getCurrentFlowData = async () => {
- try {
- if (designerRef.value) {
- const data = await designerRef.value.getCurrentFlowData()
- if (data) {
- currentValue.value = data
- }
- return data
- }
- return currentValue.value || undefined
- } catch (error) {
- console.error('获取流程数据失败:', error)
- return currentValue.value || undefined
- }
-}
-
-// 组件创建时初始化数据
-onMounted(() => {
- initOrUpdateValue()
-})
-
-// 组件卸载前保存数据
-onBeforeUnmount(async () => {
- try {
- const data = await getCurrentFlowData()
- if (data) {
- emit('success', data)
- }
- } catch (error) {
- console.error('保存数据失败:', error)
- }
-})
-
-defineExpose({
- getCurrentFlowData,
- refresh: () => designerRef.value?.refresh?.()
-})
diff --git a/src/views/crm/business/BusinessForm.vue b/src/views/crm/business/BusinessForm.vue
index 6b03047b..4af1abe0 100644
--- a/src/views/crm/business/BusinessForm.vue
+++ b/src/views/crm/business/BusinessForm.vue
@@ -101,7 +101,7 @@
@@ -123,7 +123,7 @@
disabled
v-model="formData.totalPrice"
placeholder="请输入商机金额"
- :formatter="erpPriceTableColumnFormatter"
+ :formatter="erpPriceInputFormatter"
/>
@@ -142,7 +142,7 @@ import * as CustomerApi from '@/api/crm/customer'
import * as UserApi from '@/api/system/user'
import { useUserStore } from '@/store/modules/user'
import BusinessProductForm from './components/BusinessProductForm.vue'
-import { erpPriceMultiply, erpPriceTableColumnFormatter } from '@/utils'
+import { erpPriceMultiply, erpPriceInputFormatter } from '@/utils'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
diff --git a/src/views/crm/contract/ContractForm.vue b/src/views/crm/contract/ContractForm.vue
index 9c5b2c6a..db2eec9b 100644
--- a/src/views/crm/contract/ContractForm.vue
+++ b/src/views/crm/contract/ContractForm.vue
@@ -159,7 +159,7 @@
@@ -181,7 +181,7 @@
disabled
v-model="formData.totalPrice"
placeholder="请输入商机金额"
- :formatter="erpPriceTableColumnFormattere"
+ :formatter="erpPriceInputFormatter"
/>
@@ -199,7 +199,7 @@ import * as ContractApi from '@/api/crm/contract'
import * as UserApi from '@/api/system/user'
import * as ContactApi from '@/api/crm/contact'
import * as BusinessApi from '@/api/crm/business'
-import { erpPriceMultiply, erpPriceTableColumnFormatter } from '@/utils'
+import { erpPriceMultiply, erpPriceInputFormatter } from '@/utils'
import { useUserStore } from '@/store/modules/user'
import ContractProductForm from '@/views/crm/contract/components/ContractProductForm.vue'
diff --git a/src/views/infra/build/index.vue b/src/views/infra/build/index.vue
index ed1091e7..260b8b7a 100644
--- a/src/views/infra/build/index.vue
+++ b/src/views/infra/build/index.vue
@@ -135,7 +135,8 @@ const makeTemplate = () => {
/** 复制 **/
const copy = async (text: string) => {
- const { copy, copied, isSupported } = useClipboard({ source: text })
+ const textToCopy = JSON.stringify(text, null, 2)
+ const { copy, copied, isSupported } = useClipboard({ source: textToCopy })
if (!isSupported) {
message.error(t('common.copyError'))
} else {
@@ -149,17 +150,18 @@ const copy = async (text: string) => {
/**
* 代码高亮
*/
-const highlightedCode = (code) => {
+const highlightedCode = (code: string) => {
// 处理语言和代码
let language = 'json'
if (formType.value === 2) {
language = 'xml'
}
+ // debugger
if (!isString(code)) {
- code = JSON.stringify(code)
+ code = JSON.stringify(code, null, 2)
}
// 高亮
- const result = hljs.highlight(language, code, true)
+ const result = hljs.highlight(code, { language: language, ignoreIllegals: true })
return result.value || ' '
}
diff --git a/src/views/infra/file/index.vue b/src/views/infra/file/index.vue
index 3fcda6e8..e67ad51b 100644
--- a/src/views/infra/file/index.vue
+++ b/src/views/infra/file/index.vue
@@ -95,6 +95,9 @@
/>
+
+ 复制链接
+
{
formRef.value.open()
}
+/** 复制到剪贴板方法 */
+const copyToClipboard = (text: string) => {
+ navigator.clipboard.writeText(text).then(() => {
+ message.success('复制成功')
+ })
+}
+
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
diff --git a/src/views/mall/promotion/bargain/activity/index.vue b/src/views/mall/promotion/bargain/activity/index.vue
index 40449fea..2e4f1bf5 100644
--- a/src/views/mall/promotion/bargain/activity/index.vue
+++ b/src/views/mall/promotion/bargain/activity/index.vue
@@ -151,7 +151,6 @@ import * as BargainActivityApi from '@/api/mall/promotion/bargain/bargainActivit
import BargainActivityForm from './BargainActivityForm.vue'
import { formatDate } from '@/utils/formatTime'
import { fenToYuanFormat } from '@/utils/formatter'
-import { closeBargainActivity } from '@/api/mall/promotion/bargain/bargainActivity'
defineOptions({ name: 'PromotionBargainActivity' })
diff --git a/src/views/mall/promotion/diy/template/decorate.vue b/src/views/mall/promotion/diy/template/decorate.vue
index 82edbe5f..c7231c8a 100644
--- a/src/views/mall/promotion/diy/template/decorate.vue
+++ b/src/views/mall/promotion/diy/template/decorate.vue
@@ -2,18 +2,18 @@
@@ -26,13 +26,14 @@
-
diff --git a/src/views/mall/trade/brokerage/user/UpdateBindUserForm.vue b/src/views/mall/trade/brokerage/user/BrokerageUserUpdateForm.vue
similarity index 97%
rename from src/views/mall/trade/brokerage/user/UpdateBindUserForm.vue
rename to src/views/mall/trade/brokerage/user/BrokerageUserUpdateForm.vue
index 77ffac78..941b715b 100644
--- a/src/views/mall/trade/brokerage/user/UpdateBindUserForm.vue
+++ b/src/views/mall/trade/brokerage/user/BrokerageUserUpdateForm.vue
@@ -43,8 +43,8 @@
import * as BrokerageUserApi from '@/api/mall/trade/brokerage/user'
import { formatDate } from '@/utils/formatTime'
-/** 修改上级推广人表单 */
-defineOptions({ name: 'UpdateBindUserForm' })
+/** 修改分销用户 */
+defineOptions({ name: 'BrokerageUserUpdateForm' })
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
diff --git a/src/views/mall/trade/brokerage/user/index.vue b/src/views/mall/trade/brokerage/user/index.vue
index 22daf1b2..bbb17fba 100644
--- a/src/views/mall/trade/brokerage/user/index.vue
+++ b/src/views/mall/trade/brokerage/user/index.vue
@@ -4,19 +4,19 @@
@@ -26,111 +26,126 @@
clearable
placeholder="请选择推广资格"
>
-
-
+
+
- 搜索
- 重置
+
+
+ 搜索
+
+
+
+ 重置
+
+
+
+ 新增
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
-
+
-
+
handleCommand(command, scope.row)"
v-hasPermi="[
'trade:brokerage-user:user-query',
'trade:brokerage-user:order-query',
'trade:brokerage-user:update-bind-user',
'trade:brokerage-user:clear-bind-user'
]"
+ @command="(command) => handleCommand(command, scope.row)"
>
@@ -139,28 +154,28 @@
推广人
推广订单
修改上级推广人
清除上级推广人
@@ -172,28 +187,31 @@
-
+
-
+
-
+
+
+
-
diff --git a/src/views/system/area/index.vue b/src/views/system/area/index.vue
index 72cbcad2..339ecefb 100644
--- a/src/views/system/area/index.vue
+++ b/src/views/system/area/index.vue
@@ -16,6 +16,7 @@