Browse Source

Merge branch 'v8_master'

# Conflicts:
#	src/types/components.d.ts
lwx_v10
超级管理员 2 years ago
parent
commit
4981750f3d
  1. 25
      node_modules/.package-lock.json
  2. 27
      package-lock.json
  3. 2
      package.json
  4. 32
      src/api/DesignForm/requestapi.ts
  5. 128
      src/api/date/type.ts
  6. 1
      src/assets/icons/chaoSongWoDe.svg
  7. 1
      src/assets/icons/daiWoCuLi.svg
  8. 1
      src/assets/icons/fenZhu.svg
  9. 1
      src/assets/icons/liuChengBiaoDan.svg
  10. 1
      src/assets/icons/puTongBiaoDan.svg
  11. 1
      src/assets/icons/woChuangJianDe.svg
  12. 1
      src/assets/icons/woYiChuLi.svg
  13. 1
      src/assets/icons/ziJianApp.svg
  14. BIN
      src/assets/images/13.png
  15. BIN
      src/assets/images/3.png
  16. 13
      src/components/DesignForm/assembly/index.ts
  17. 618
      src/components/DesignForm/formControlAttr.vue
  18. 125
      src/components/IconSelect/appMenuSvgPage.vue
  19. 87
      src/components/IconSelect/svgPage.vue
  20. 2
      src/components/SvgIcon/index.vue
  21. 8
      src/router/index.ts
  22. 12
      src/types/components.d.ts
  23. 594
      src/views/sysworkflow/codepage/createpage.vue
  24. 106
      src/views/sysworkflow/codepage/editpage.vue
  25. 363
      src/views/sysworkflow/codepage/page.vue
  26. 213
      src/views/sysworkflow/codepage/page0318.vue
  27. 38
      src/views/sysworkflow/lowcodepage/appFormList.vue
  28. 165
      src/views/sysworkflow/lowcodepage/appPage/appMenuGroup.vue
  29. 155
      src/views/sysworkflow/lowcodepage/appPage/appMenus.vue
  30. 299
      src/views/sysworkflow/lowcodepage/appPage/index.vue
  31. 18
      src/views/sysworkflow/lowcodepage/index.vue
  32. 5
      src/views/sysworkflow/lowcodepage/workFlow.vue
  33. 79
      src/widget/associatedforms/associatedFormsFillRole.vue
  34. 107
      src/widget/associatedforms/associatedFormsTinyace.vue
  35. 108
      src/widget/associatedforms/associatedFormsTinyaceRange.vue

25
node_modules/.package-lock.json

@ -966,6 +966,15 @@
"resolved": "https://registry.npmmirror.com/@types/event-emitter/-/event-emitter-0.3.4.tgz",
"integrity": "sha512-q68CMfgGnlwrV6BFupIGNSitHbuFhGzA+uTBztFKAQuGCF/Xy0mi33jwEPQaHtnb89cLFlsc7AIxk/2gdtXrvw=="
},
"node_modules/@types/jquery": {
"version": "3.5.29",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.29.tgz",
"integrity": "sha512-oXQQC9X9MOPRrMhPHHOsXqeQDnWeCDT3PelUIg/Oy8FAbzSZtFHRjc7IpbfFVmpLtJ+UOoywpRsuO5Jxjybyeg==",
"dev": true,
"dependencies": {
"@types/sizzle": "*"
}
},
"node_modules/@types/json-schema": {
"version": "7.0.14",
"resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.14.tgz",
@ -1027,6 +1036,12 @@
"integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==",
"dev": true
},
"node_modules/@types/sizzle": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz",
"integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==",
"dev": true
},
"node_modules/@types/spark-md5": {
"version": "3.0.4",
"resolved": "https://registry.npmmirror.com/@types/spark-md5/-/spark-md5-3.0.4.tgz",
@ -5265,6 +5280,11 @@
"jiti": "bin/jiti.js"
}
},
"node_modules/jquery": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg=="
},
"node_modules/js-base64": {
"version": "2.6.4",
"resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz",
@ -9747,7 +9767,7 @@
},
"node_modules/unplugin-vue-components": {
"version": "0.24.1",
"resolved": "https://registry.npmmirror.com/unplugin-vue-components/-/unplugin-vue-components-0.24.1.tgz",
"resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.24.1.tgz",
"integrity": "sha512-T3A8HkZoIE1Cja95xNqolwza0yD5IVlgZZ1PVAGvVCx8xthmjsv38xWRCtHtwl+rvZyL9uif42SRkDGw9aCfMA==",
"dev": true,
"dependencies": {
@ -9765,6 +9785,9 @@
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@babel/parser": "^7.15.8",
"@nuxt/kit": "^3.2.2",

27
package-lock.json

@ -21,6 +21,7 @@
"echarts": "^5.4.3",
"element-plus": "^2.3.4",
"font-awesome": "^4.7.0",
"jquery": "^3.7.1",
"js-beautify": "^1.14.8",
"js-md5": "^0.7.3",
"mapv-three": "^1.0.18",
@ -46,6 +47,7 @@
"@commitlint/cli": "^17.6.3",
"@commitlint/config-conventional": "^17.6.3",
"@iconify-json/ep": "^1.1.10",
"@types/jquery": "^3.5.29",
"@types/md5": "^2.3.2",
"@types/nprogress": "^0.2.0",
"@types/path-browserify": "^1.0.0",
@ -1363,6 +1365,15 @@
"resolved": "https://registry.npmmirror.com/@types/event-emitter/-/event-emitter-0.3.4.tgz",
"integrity": "sha512-q68CMfgGnlwrV6BFupIGNSitHbuFhGzA+uTBztFKAQuGCF/Xy0mi33jwEPQaHtnb89cLFlsc7AIxk/2gdtXrvw=="
},
"node_modules/@types/jquery": {
"version": "3.5.29",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.29.tgz",
"integrity": "sha512-oXQQC9X9MOPRrMhPHHOsXqeQDnWeCDT3PelUIg/Oy8FAbzSZtFHRjc7IpbfFVmpLtJ+UOoywpRsuO5Jxjybyeg==",
"dev": true,
"dependencies": {
"@types/sizzle": "*"
}
},
"node_modules/@types/json-schema": {
"version": "7.0.14",
"resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.14.tgz",
@ -1424,6 +1435,12 @@
"integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==",
"dev": true
},
"node_modules/@types/sizzle": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz",
"integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==",
"dev": true
},
"node_modules/@types/spark-md5": {
"version": "3.0.4",
"resolved": "https://registry.npmmirror.com/@types/spark-md5/-/spark-md5-3.0.4.tgz",
@ -5675,6 +5692,11 @@
"jiti": "bin/jiti.js"
}
},
"node_modules/jquery": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg=="
},
"node_modules/js-base64": {
"version": "2.6.4",
"resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz",
@ -10157,7 +10179,7 @@
},
"node_modules/unplugin-vue-components": {
"version": "0.24.1",
"resolved": "https://registry.npmmirror.com/unplugin-vue-components/-/unplugin-vue-components-0.24.1.tgz",
"resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.24.1.tgz",
"integrity": "sha512-T3A8HkZoIE1Cja95xNqolwza0yD5IVlgZZ1PVAGvVCx8xthmjsv38xWRCtHtwl+rvZyL9uif42SRkDGw9aCfMA==",
"dev": true,
"dependencies": {
@ -10175,6 +10197,9 @@
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@babel/parser": "^7.15.8",
"@nuxt/kit": "^3.2.2",

2
package.json

@ -52,6 +52,7 @@
"echarts": "^5.4.3",
"element-plus": "^2.3.4",
"font-awesome": "^4.7.0",
"jquery": "^3.7.1",
"js-beautify": "^1.14.8",
"js-md5": "^0.7.3",
"mapv-three": "^1.0.18",
@ -77,6 +78,7 @@
"@commitlint/cli": "^17.6.3",
"@commitlint/config-conventional": "^17.6.3",
"@iconify-json/ep": "^1.1.10",
"@types/jquery": "^3.5.29",
"@types/md5": "^2.3.2",
"@types/nprogress": "^0.2.0",
"@types/path-browserify": "^1.0.0",

32
src/api/DesignForm/requestapi.ts

@ -343,3 +343,35 @@ export function gainFormPageListCont(data: any) {
data: data
});
}
//创建APP
export function createApp(data: any) {
return request({
url: '/systemapi/app/createApp',
method: 'post',
data: data
});
}
//获取应用编辑页面信息
export function gainAppEditPsge(data: any) {
return request({
url: '/systemapi/app/gainAppEditPsge',
method: 'post',
data: data
});
}
//获取除固定菜单以外的数据
export function ginOthenMenuTree(data: any) {
return request({
url: '/systemapi/app/ginOthenMenuTree',
method: 'post',
data: data
});
}
//新增菜单
export function saveAppMenu(data: any) {
return request({
url: '/systemapi/app/saveAppMenu',
method: 'post',
data: data
});
}

128
src/api/date/type.ts

@ -65,3 +65,131 @@ export interface dataBaseStruct {
id?: string;
redashDatasourceId?: number;
}
/**
@ 作者: 秦东
@ 时间: 2024-04-22 11:43:21
@ 功能: 自建应用菜单树结构
*/
export interface appMenuTreeInfo {
id:string; //节点唯一识别符
label:string; //节点名称
type:number; //节点类型 1:目录;2:菜单;3:必定存在
svg?:string; //图标
pcIsShow:number; //pc端显示与隐藏
wapIsShow:number; //移动端显示与隐藏
parent:string; // 父级
appkey:string; //app唯一识别符
isLock:number;
sort:number; //排序
children?:appMenuTreeInfo[]; //子级
}
/**
@ 作者: 秦东
@ 时间: 2024-04-23 16:03:48
@ 功能: appCont
*/
export interface appSetInfo {
appKey:string;
appName:string;
appSvg:string;
state:number;
uuid:string;
}
/**
@ 作者: 秦东
@ 时间: 2024-04-22 08:31:22
@ 功能: 实验拖拽树
*/
export let threeShiyanData = [
{
id:"1",
svg:"chaoSongWoDe",
label:"Hr管理",
type:1,
children:[
{
id:"2",
svg:"chaoSongWoDe",
label:"Hr看板",
type:2,
children:[]
},
{
id:"3",
svg:"chaoSongWoDe",
label:"员工档案",
type:2,
children:[]
},
{
id:"4",
svg:"chaoSongWoDe",
label:"绩效考核",
type:1,
children:[
{
id:"5",
svg:"chaoSongWoDe",
label:"统计分析",
type:1,
children:[
{
id:"6",
svg:"chaoSongWoDe",
label:"综合成绩",
type:2,
children:[]
},
{
id:"7",
svg:"chaoSongWoDe",
label:"指标分析",
type:2,
children:[]
}
]
},
{
id:"8",
svg:"chaoSongWoDe",
label:"考核方案",
type:1,
children:[
{
id:"9",
svg:"chaoSongWoDe",
label:"方案生成",
type:2,
children:[]
}
]
}
]
},
{
id:"10",
svg:"chaoSongWoDe",
label:"考勤管理",
type:2,
children:[]
},
]
},
{
id:"11",
svg:"chaoSongWoDe",
label:"应用管理",
type:1,
children:[
{
id:"",
svg:"chaoSongWoDe",
label:"应用中心",
type:2,
children:[]
},
]
}
];

1
src/assets/icons/chaoSongWoDe.svg

@ -0,0 +1 @@
<svg t="1713594202430" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12832" width="200" height="200"><path d="M536.539429 565.357714a102.144 102.144 0 0 1 16.036571-67.547428l4.205714-5.485715a356.205714 356.205714 0 0 0 95.652572-231.990857c-1.92-123.501714-77.074286-198.052571-182.857143-198.052571-106.624 0-180.571429 72.740571-180.571429 195.2a347.245714 347.245714 0 0 0 95.250286 234.422857l4.608 4.681143 2.377143 6.217143c25.362286 66.358857-6.930286 117.266286-44.946286 126.555428-98.742857 40.027429-168.777143 84.114286-209.718857 131.364572a126.171429 126.171429 0 0 0-30.665143 82.651428v39.350857a49.974857 49.974857 0 0 0 49.371429 50.541715h335.908571a300.544 300.544 0 0 0 47.670857 62.171428H155.190857A111.542857 111.542857 0 0 1 45.129143 882.651429v-39.350858a189.44 189.44 0 0 1 46.006857-123.977142c48.237714-55.625143 125.878857-104.612571 236.763429-149.193143 8.082286-2.029714 16.457143-14.409143 8.740571-39.094857a410.934857 410.934857 0 0 1-108.397714-273.627429C228.242286 100.004571 329.965714 0 469.613714 0c138.733714 0 241.206857 101.613714 243.638857 259.657143a418.468571 418.468571 0 0 1-83.657142 241.371428 295.515429 295.515429 0 0 0-92.909715 64.347429zM737.298286 1024a246.326857 246.326857 0 0 1-0.164572-492.525714h0.164572a246.326857 246.326857 0 0 1 0 492.525714z m0-51.858286a194.468571 194.468571 0 1 0-189.769143-194.413714A192.128 192.128 0 0 0 737.298286 972.068571z m-73.142857-209.645714c-30.72-59.465143-9.142857-81.92 49.371428-49.682286l105.325714 58.221715c58.002286 32.054857 51.620571 52.534857-13.513142 45.714285l-44.544-4.553143 4.516571 46.957715c6.473143 67.2-13.165714 73.563429-43.885714 14.006857l-57.179429-110.738286z" fill="currentColor" p-id="12833"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

1
src/assets/icons/daiWoCuLi.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1713593859030" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="817" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M443.890033 1023.9995H196.927154c-89.934956 0-162.542921-70.688965-162.542921-157.385923V157.385923C34.385233 70.509966 107.412198 0 196.928154 0H801.769859c89.934956 0 162.601921 70.748965 162.60192 157.385923v294.267856a33.455984 33.455984 0 0 1-66.851967 0V157.385923a94.431954 94.431954 0 0 0-95.929953-92.692955H196.928154a94.431954 94.431954 0 0 0-95.930953 92.692955v709.047654a94.431954 94.431954 0 0 0 95.929953 92.692955H443.710033a32.436984 32.436984 0 1 1 0 64.872968z" p-id="818"></path><path d="M249.090128 247.919879h447.336782q32.315984 0 32.315984 32.316984v0.06q0 32.316984-32.315984 32.316984H249.090128q-32.316984 0-32.316984-32.316984v-0.06q0-32.315984 32.316984-32.315984zM253.647126 495.841758h281.915862q32.316984 0 32.316985 32.315984v0.06q0 32.316984-32.316985 32.316984H253.647126q-32.316984 0-32.316984-32.316984v-0.06q0-32.315984 32.316984-32.315984zM869.461825 806.176606a22.063989 22.063989 0 0 1-22.003989 22.00499H759.859879a22.003989 22.003989 0 0 1-21.883989-22.00499v-87.595957a21.883989 21.883989 0 0 1 43.767978 0v65.951968h65.951968a21.883989 21.883989 0 0 1 22.004989 21.883989z" p-id="819"></path><path d="M773.769872 560.054727A215.843895 215.843895 0 1 0 989.615767 775.899621 215.843895 215.843895 0 0 0 773.769872 560.054727z m0 380.724814A164.879919 164.879919 0 1 1 938.652792 775.899621 164.879919 164.879919 0 0 1 773.769872 940.779541z" p-id="820"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

1
src/assets/icons/fenZhu.svg

@ -0,0 +1 @@
<svg t="1713757185363" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9936" width="200" height="200"><path d="M256 512 256 448l384 0 0 64L332.8 512 256 512zM320 832l64 0 0 64L320 896 281.6 896 256 896 39.488 896C14.72 896 0 899.008 0 874.24L0 423.68 0 384 0 320 0 259.84 0 134.4C0 108.288 15.872 64 42.048 64l353.28 0C421.44 64 448 108.288 448 134.4L448 192l461.888 0C934.592 192 960 235.136 960 259.84L960 384l-64 0-128 0L64 384l0 39.68L64 832l192 0L320 832zM64 320l832 0L896 256 442.688 256 384 256 384 215.04 384 128 64 128l0 131.84L64 320zM832 640 832 576l-64 0 0 320 64 0 0-64 192 0 0 192-192 0 0-64-128 0 0-64 0-128-64 0 0 128L448 896 448 576l192 0 0 128 64 0L704 576 704 512l64 0 64 0L832 448l192 0 0 192L832 640zM896 576l64 0L960 512l-64 0L896 576zM576 640 512 640l0 192 64 0L576 640zM896 960l64 0 0-64-64 0L896 960z" p-id="9937"></path></svg>

After

Width:  |  Height:  |  Size: 897 B

1
src/assets/icons/liuChengBiaoDan.svg

@ -0,0 +1 @@
<svg t="1713756956200" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7983" width="200" height="200"><path d="M451.168317 1024h-364.990099A25.346535 25.346535 0 0 1 60.831683 998.653465v-892.198019A25.346535 25.346535 0 0 1 86.178218 81.108911h114.870495a25.346535 25.346535 0 0 1 0 50.693069H111.524752v841.504951h339.643565a25.346535 25.346535 0 0 1 0 50.693069zM897.267327 537.346535a25.346535 25.346535 0 0 1-25.346535-25.346535V131.80198h-92.362772a25.346535 25.346535 0 0 1 0-50.693069H897.267327a25.346535 25.346535 0 0 1 25.346534 25.346535v405.544554a25.346535 25.346535 0 0 1-25.346534 25.346535z" p-id="7984"></path><path d="M775.60396 212.910891h-567.762376a25.346535 25.346535 0 0 1-25.346534-25.346535v-162.217821A25.346535 25.346535 0 0 1 207.841584 0h567.762376A25.346535 25.346535 0 0 1 800.950495 25.346535v162.217821a25.346535 25.346535 0 0 1-25.346535 25.346535zM233.188119 162.217822h517.069307V50.693069H233.188119zM735.049505 375.128713h-486.653465a25.346535 25.346535 0 0 1 0-50.693069h486.653465a25.346535 25.346535 0 0 1 0 50.693069zM410.613861 598.178218h-162.217821a25.346535 25.346535 0 0 1 0-50.693069h162.217821a25.346535 25.346535 0 0 1 0 50.693069zM329.50495 821.227723h-81.10891a25.346535 25.346535 0 0 1 0-50.69307h81.10891a25.346535 25.346535 0 0 1 0 50.69307zM775.60396 699.564356h-202.772277a65.90099 65.90099 0 0 1 0-131.80198h202.772277a65.90099 65.90099 0 0 1 0 131.80198z m-202.772277-81.10891a15.207921 15.207921 0 0 0 0 30.415841h202.772277a15.207921 15.207921 0 0 0 0-30.415841zM775.60396 861.782178h-202.772277a65.90099 65.90099 0 0 1 0-131.80198h202.772277a65.90099 65.90099 0 0 1 0 131.80198z m-202.772277-81.108911a15.207921 15.207921 0 0 0 0 30.415842h202.772277a15.207921 15.207921 0 0 0 0-30.415842zM775.60396 1024h-202.772277a65.90099 65.90099 0 0 1 0-131.80198h202.772277a65.90099 65.90099 0 0 1 0 131.80198z m-202.772277-81.108911a15.207921 15.207921 0 0 0 0 30.415842h202.772277a15.207921 15.207921 0 0 0 0-30.415842z" p-id="7985"></path><path d="M532.277228 821.227723C449.850297 821.227723 385.267327 774.488713 385.267327 714.772277S449.850297 608.316832 532.277228 608.316832a25.346535 25.346535 0 0 1 0 50.693069c-56.776238 0-96.316832 29.40198-96.316832 55.762376s39.540594 55.762376 96.316832 55.762376a25.346535 25.346535 0 0 1 0 50.69307zM816.158416 983.445545a25.346535 25.346535 0 0 1 0-50.69307c56.776238 0 96.316832-29.40198 96.316832-55.762376S872.934653 821.227723 816.158416 821.227723a25.346535 25.346535 0 0 1 0-50.69307C898.585347 770.534653 963.168317 817.273663 963.168317 876.990099S898.585347 983.445545 816.158416 983.445545z" p-id="7986"></path></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

1
src/assets/icons/puTongBiaoDan.svg

@ -0,0 +1 @@
<svg t="1713756831580" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6930" width="200" height="200"><path d="M288 512l256 0C561.92 512 576 497.92 576 480 576 462.08 561.92 448 544 448l-256 0C270.08 448 256 462.08 256 480 256 497.92 270.08 512 288 512zM768 64 192 64C121.6 64 64 121.6 64 192l0 576c0 70.4 57.6 128 128 128l576 0c70.4 0 128-57.6 128-128L896 192C896 121.6 838.4 64 768 64zM832 768c0 35.2-28.8 64-64 64L192 832c-35.2 0-64-28.8-64-64L128 192c0-35.2 28.8-64 64-64l576 0c35.2 0 64 28.8 64 64L832 768zM672 256l-384 0C270.08 256 256 270.08 256 288 256 305.92 270.08 320 288 320l384 0C689.92 320 704 305.92 704 288 704 270.08 689.92 256 672 256zM608 640l-320 0C270.08 640 256 654.08 256 672l0 0C256 689.92 270.08 704 288 704l320 0c17.92 0 32-14.08 32-32l0 0C640 654.08 625.92 640 608 640z" p-id="6931"></path></svg>

After

Width:  |  Height:  |  Size: 867 B

1
src/assets/icons/woChuangJianDe.svg

@ -0,0 +1 @@
<svg t="1713594317729" class="icon" viewBox="0 0 1099 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19212" width="200" height="200"><path d="M222.42623 268.590164H125.17141C107.03318 268.590164 92.327869 285.502951 92.327869 306.360656s14.705311 37.770492 32.843541 37.770492H222.42623v97.254819c0 18.13823 16.912787 32.843541 37.770491 32.843541s37.770492-14.705311 37.770492-32.843541V344.131148h97.25482C413.360262 344.131148 428.065574 327.218361 428.065574 306.360656S413.360262 268.590164 395.222033 268.590164H297.967213V171.335344c0-18.13823-16.912787-32.843541-37.770492-32.843541s-37.770492 14.705311-37.770491 32.843541V268.590164z m616.918032-59.442361c-21.571148-5.036066-44.048787-7.70518-67.147541-7.70518-162.245246 0-293.770492 131.525246-293.770491 293.770492 0 78.780852 31.01377 150.326557 81.500327 203.079344C454.446164 763.803279 381.456787 876.695082 370.688 1007.213115H83.934426c-46.356984 0-83.934426-37.577443-83.934426-83.934426V83.934426C0 37.577443 37.577443 0 83.934426 0h671.47541c46.356984 0 83.934426 37.577443 83.934426 83.934426v125.213377zM772.196721 713.442623c-120.529836 0-218.229508-97.699672-218.229508-218.229508s97.699672-218.229508 218.229508-218.229508 218.229508 97.699672 218.229509 218.229508-97.699672 218.229508-218.229509 218.229508z m-327.344262 307.426623C454.756721 890.686951 540.789508 781.79882 658.549508 738.622951a276.009967 276.009967 0 0 0 112.690361 23.887738c40.137443 0 78.277246-8.536131 112.698754-23.887738 117.751607 43.175869 203.792787 152.072393 213.697049 282.246295H444.852459z" fill="currentColor" p-id="19213"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

1
src/assets/icons/woYiChuLi.svg

@ -0,0 +1 @@
<svg t="1713593953149" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3009" width="200" height="200"><path d="M631.249893 1022.319395H248.948766a105.512773 105.512773 0 0 1-39.311546-7.306979 102.078493 102.078493 0 0 1-33.319823-21.190238 97.182817 97.182817 0 0 1-22.140146-31.931497A93.821607 93.821607 0 0 1 146.651063 924.33281V97.913515c0-25.939775 10.814329-50.929642 29.958613-69.270158C195.82703 10.22977 221.912944 0 248.948766 0h599.172256c27.035821 0 53.121735 10.30284 72.339089 28.716426 19.144284 18.340517 29.958613 43.330384 29.958613 69.270159v519.306979a30.90852 30.90852 0 0 1-4.530327 13.66405 32.516055 32.516055 0 0 1-10.375909 10.37591 32.954474 32.954474 0 0 1-31.2008 0 230.09676 230.09676 0 0 0-84.030255-16.221493 225.858713 225.858713 0 0 0-83.664907 16.294562c-26.451263 10.668189-50.491223 26.232054-70.658484 45.814757a207.810475 207.810475 0 0 0-46.764664 68.466391c-10.814329 25.501356-16.075353 52.829456-15.783074 80.376766 0 49.395176 18.852005 97.182817 52.902526 134.302269a31.200799 31.200799 0 0 1 5.041815 34.050521 32.296846 32.296846 0 0 1-12.202654 13.517911 34.3428 34.3428 0 0 1-17.902098 5.041815v-0.657628zM248.948766 64.301413a36.607963 36.607963 0 0 0-25.428286 9.718282 33.685172 33.685172 0 0 0-10.52205 24.113029V924.33281c0 9.133723 3.799629 17.829028 10.52205 24.332239a36.754103 36.754103 0 0 0 25.428286 10.083631h319.168831a262.758955 262.758955 0 0 1 29.008705-290.671614 284.387612 284.387612 0 0 1 128.456686-89.29128 296.590267 296.590267 0 0 1 158.34223-9.499073V97.913515a32.589125 32.589125 0 0 0-10.52205-24.11303A35.365777 35.365777 0 0 0 848.121022 64.301413H248.948766z" fill="currentColor" p-id="3010"></path><path d="M756.856857 906.649922a29.958613 29.958613 0 0 1-22.359355-9.572143l-63.936063-63.936064a31.346939 31.346939 0 0 1 22.359354-53.340944c8.403026 0 16.440702 3.36121 22.359355 9.206793l44.134152 44.134151 93.383188-93.383188a30.689311 30.689311 0 0 1 44.71871 0 31.346939 31.346939 0 0 1 0 44.134152l-118.299986 111.285286a31.346939 31.346939 0 0 1-22.359355 11.471957zM448.063936 527.125446H290.744684a31.931497 31.931497 0 1 1 0-63.936064h157.319252a31.931497 31.931497 0 1 1 0 63.936064z m296.663337-265.974026H290.744684a32.004567 32.004567 0 0 1 0-63.936064h453.982589a32.004567 32.004567 0 0 1 0 63.936064z m0 120.857428H290.744684a32.004567 32.004567 0 0 1 0-63.936064h453.982589a32.004567 32.004567 0 0 1 0 63.936064z" fill="currentColor" p-id="3011"></path></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

1
src/assets/icons/ziJianApp.svg

@ -0,0 +1 @@
<svg t="1713840731502" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11177" width="200" height="200"><path d="M1023.401462 126.021423v227.811239a125.680133 125.680133 0 0 1-125.59481 125.59481h-227.811239a125.680133 125.680133 0 0 1-125.59481-125.637471V126.021423A125.680133 125.680133 0 0 1 669.995413 0.426613h227.811239a125.680133 125.680133 0 0 1 125.59481 125.59481z m-543.931328 539.665201v227.811239a125.680133 125.680133 0 0 1-125.594811 125.552149h-227.811239a125.680133 125.680133 0 0 1-125.552149-125.594811v-227.811239a125.680133 125.680133 0 0 1 125.594811-125.552149h227.768577a125.680133 125.680133 0 0 1 125.594811 125.594811z m0-539.665201v227.811239a125.680133 125.680133 0 0 1-125.594811 125.59481h-227.811239A125.680133 125.680133 0 0 1 0.554597 353.790001V126.021423A126.021423 126.021423 0 0 1 126.106746 0.426613h227.768577a125.680133 125.680133 0 0 1 125.594811 125.59481z m225.336884 822.210863a29.222977 29.222977 0 0 0-34.171686 5.204676l-22.439833 23.122414c0 0.68258-1.066532 0.68258-1.706452 0.682581-1.066532 0-1.407822-0.34129-1.749112-0.682581l-42.490636-42.447974c-0.68258 0-0.68258-1.066532-0.68258-1.749113 0-1.023871 0.34129-1.365161 0.68258-1.706451l22.781124-22.823785a31.057412 31.057412 0 0 0 5.204676-34.171686l-2.772983-5.887257a189.842699 189.842699 0 0 1-8.276288-20.00814l-2.090403-6.228547a29.436284 29.436284 0 0 0-27.9858-20.050802h-2.389032a31.825315 31.825315 0 0 1-32.123944-32.081283c0-17.917738 14.163545-32.123944 32.123944-32.123945h2.389032a29.862896 29.862896 0 0 0 27.9858-20.050802l2.090403-6.185885c3.071612-6.911127 5.545966-14.163545 8.276288-20.050802l2.772983-5.844596a29.222977 29.222977 0 0 0-5.204676-34.171685l-22.781124-22.781124c-0.68258 0-0.68258-1.066532-0.68258-1.706452 0-1.066532 0.34129-1.407822 0.68258-1.749112l41.808055-42.490636c0-0.68258 1.023871-0.68258 1.706452-0.68258 1.023871 0 1.365161 0.34129 1.706451 0.68258l22.823785 22.781124c8.958869 7.934998 22.781124 10.366691 34.129025 5.204676l5.887256-2.772983a189.842699 189.842699 0 0 1 20.050802-8.276288l6.228547-2.090403a29.436284 29.436284 0 0 0 20.050802-27.9858v-2.389032c0-17.960399 14.120884-32.123944 32.081283-32.123944 17.917738 0 32.123944 14.163545 32.123945 32.123944v2.047742a29.862896 29.862896 0 0 0 20.34943 27.9858l6.228547 2.090403c6.911127 3.071612 13.822255 5.503305 20.050802 8.276288l5.844596 2.772983c11.390562 6.185886 25.554107 3.412902 34.171686-5.204676l22.781124-22.781124c0-0.68258 1.066532-0.68258 1.706451-0.68258 1.066532 0 1.407822 0.34129 1.749112 0.68258l42.490636 42.447974c0.68258 0 0.68258 1.066532 0.68258 1.749113 0 1.023871-0.34129 1.365161-0.68258 1.706451l-22.781124 22.823785a32.379912 32.379912 0 0 0-5.204676 34.171686l2.772983 5.887257c3.114273 6.527176 6.228547 13.779594 8.276288 20.00814l2.090403 6.228547a29.436284 29.436284 0 0 0 27.9858 20.050802h2.389032c17.960399 0 32.123944 14.120884 32.123944 32.081283 0 17.917738-14.163545 32.123944-32.123944 32.123945h-2.389032a29.862896 29.862896 0 0 0-27.9858 20.050802l-2.090403 6.185885c-3.071612 6.911127-5.545966 13.822255-8.276288 20.050802l-2.772983 5.844596a29.222977 29.222977 0 0 0 5.204676 34.171686l22.781124 22.781124c0.68258 0 0.68258 0.725242 0.68258 1.706451 0 1.066532-0.34129 1.407822-0.68258 1.749112l-42.490636 42.490636c0 0.34129-1.023871 0.68258-1.706451 0.68258-1.023871 0-1.365161-0.34129-1.706451-0.68258l-22.823785-22.781124a32.379912 32.379912 0 0 0-34.171686-5.204676l-5.887257 2.772983a189.842699 189.842699 0 0 1-20.050802 8.276288l-6.185886 2.090403a29.436284 29.436284 0 0 0-20.050801 27.9858v2.389032c0 17.960399-14.120884 32.123944-32.081284 32.123944a31.825315 31.825315 0 0 1-32.123944-32.123944v-2.389032a29.862896 29.862896 0 0 0-20.050802-27.9858l-6.185886-2.090403c-6.911127-3.071612-13.822255-5.545966-20.050801-8.276288l-5.844596-2.772983zM789.233693 718.415967c-34.768944 0-63.991921 28.839026-63.991921 63.991921s28.839026 63.991921 63.991921 63.991921 63.991921-28.839026 63.991921-63.991921c-0.810564-35.152895-28.455074-63.991921-63.991921-63.991921z" fill="currentColor" p-id="11178"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
src/assets/images/13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
src/assets/images/3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 55 KiB

13
src/components/DesignForm/assembly/index.ts

@ -599,6 +599,19 @@ const selectOption: any = [
iconFont: 'fa-wpforms',
control: {
modelValue: '',
hideConditionHtml:'',
hideConditionHtmlCopy:'',
formid: '',
dataRangeConditionHtml:'',
dataRangeConditionHtmlCopy:'',
saveFlag: false,
fillRoles: [
{
leftValue:'',
rightValue:'',
id:'',
}
],
},
config: {}
}

618
src/components/DesignForm/formControlAttr.vue

@ -626,6 +626,30 @@
vIf: state.isSearch,
vShow: ['associatedForms']
},
{
label: '关联表单',
value: config.associatedForms,
path: 'config.associatedForms',
type: 'associatedForms_form',
vIf: state.isSearch,
vShow: ['associatedForms']
},
{
label: '数据范围',
value: config.associatedForms,
path: 'config.associatedForms',
type: 'associatedForms_dataRange',
vIf: state.isSearch,
vShow: ['associatedForms']
},
{
label: '数据填充规则',
value: config.associatedForms,
path: 'config.associatedForms',
type: 'associatedForms_FillRoles',
vIf: state.isSearch,
vShow: ['associatedForms']
},
{
label: '轮播图设置',
value: config.carousel,
@ -1543,6 +1567,8 @@
element.imgId = onlyNumber;
}
});
}else if(controlData.value.type==='associatedForms'){
controlData.value.control.fillRoles[0].id = uuidv4().replaceAll('-','').toString();
}
})
//
@ -1654,6 +1680,7 @@ interface Tree {
[key: string]: any
}
const addRootNode = () => {
let onlyNumber = uuidv4().replaceAll('-','').toString();
controlData.value.control.fixedOptions.push({
@ -1741,20 +1768,26 @@ const transferDataSourceOptions = [
//liwenxuan20240403 associatedForms start
import AssociatedFormsTinyace from '@/widget/associatedforms/associatedFormsTinyace.vue'
import AssociatedFormsTinyaceRange from '@/widget/associatedforms/associatedFormsTinyaceRange.vue'
import AssociatedFormsFillRole from '@/widget/associatedforms/associatedFormsFillRole.vue'
const associatedFormsHideDialogFlag = ref(false)
const defaultProps = {
const treeDefaultProps = {
children: 'children',
label: 'label',
}
//AssociatedFormsTinyace
let aft = ref();
const aftRange = ref();
function getAssociatedFormsCurrentFieldTree() {
return request({
url: '/javasys/lowCode/AssociatedForms/getFieldTree',
method: 'post',
data: {
cfid:'1'
//cfid:'13'
cfid:props.customerformid
},
});
}
@ -1765,20 +1798,91 @@ function getAssociatedFormsOrgAndManTree() {
method: 'post',
});
}
const associatedFormsCurrentFormFieldTree = ref<Tree[]>()
function getCustomerFormList() {
return request({
url: '/javasys/lowCode/AssociatedForms/getCustomerFormList',
method: 'post',
});
}
function getAssociatedFormsRoleTree() {
return request({
url: '/javasys/lowCode/AssociatedForms/getRoleList',
method: 'post',
});
}
function getAsfasfFieldTree() {
return request({
url: '/javasys/lowCode/AssociatedForms/getFieldTree',
method: 'post',
data: {
//cfid:'13'
cfid:controlData.value.control.formid
},
});
}
const asfasfFieldTree = ref<Tree[]>()
function formidChanged(){
if(controlData.value.control.formid===''){
}else{
getAsfasfFieldTree().then(({ data }) => {
if(data.id==="cfid为空"){
//alert("cfid")
}else{
let resData = ref(data.children)
//let rootid_ = data.value.label
asfasfFieldTree.value = [{
id: 'rootid_'+data.label,
label: '关联的表单-'+data.label,
children: [...resData.value],
treeAttrs: data.treeAttrs,
}]
}
});
}
}
const associatedFormsCurrentFormFieldTree = ref<Tree[]>()
getAssociatedFormsCurrentFieldTree().then(({ data }) => {
if(data.id==="cfid为空"){
//alert("cfid")
}else{
let resData = ref(data.children)
//let rootid_ = data.value.label
associatedFormsCurrentFormFieldTree.value = [{
id: 'rootid_'+data.label,
label: '当前表单',
children: [...resData.value],
treeAttrs: data.treeAttrs,
}]
}
});
const customerFormTree = ref<Tree[]>()
getCustomerFormList().then(({ data }) => {
let resData = ref(data.children)
customerFormTree.value = [{
id: data.id,
//value: data.value,
//label: data.label,
label: '请选择表单',
children: [...resData.value]
}]
});
const orgAndManTree = ref<Tree[]>()
getAssociatedFormsOrgAndManTree().then(({ data }) => {
getAssociatedFormsOrgAndManTree().then(({ data }) => {
let resData = ref(data.children)
orgAndManTree.value = [{
id: data.id,
@ -1788,6 +1892,18 @@ const orgAndManTree = ref<Tree[]>()
}]
});
const roleTree = ref<Tree[]>()
getAssociatedFormsRoleTree().then(({ data }) => {
let resData = ref(data.children)
//console.log("roleTree=============="+resData.value);
roleTree.value = [{
id: data.id,
//label: data.label,
label: '角色',
children: [...resData.value]
}]
});
// field
const fieldTreeSearchFlag = ref(false)
function handleFieldTreeExpand(){
@ -1799,29 +1915,245 @@ function handleFieldTreeCollapse(){
fieldTreeSearchFlag.value = false;
}
function handleFieldTreeNodeclick(){
}
function handleFieldTreeContextmenu(MouseEvent:any, object:any, Node:any, element:any){
//console.log(MouseEvent)
console.log(object)
//console.log(Node)
//console.log(element)
aft.value.addIcon_field(object)
}
function handleFieldTreeContextmenuRange(MouseEvent:any, object:any, Node:any, element:any){
aftRange.value.addIcon_field(object)
}
//org
const orgTreeSearchFlag = ref(false)
function handleOrgTreeExpand(){
orgTreeSearchFlag.value = true;
}
function handleOrgTreeCollapse(){
orgTreeSearchFlag.value = false;
}
function handleOrgTreeContextmenu(MouseEvent:any, object:any, Node:any, element:any){
aft.value.addIcon_org(object)
}
function handleOrgTreeContextmenuRange(MouseEvent:any, object:any, Node:any, element:any){
aftRange.value.addIcon_org(object)
}
//role
const roleTreeSearchFlag = ref(false)
function handleRoleTreeExpand(){
roleTreeSearchFlag.value = true;
}
function handleRoleTreeCollapse(){
roleTreeSearchFlag.value = false;
}
function handleRoleTreeContextmenu(MouseEvent:any, object:any, Node:any, element:any){
aft.value.addIcon(object)
}
function handleRoleTreeContextmenuRange(MouseEvent:any, object:any, Node:any, element:any){
aftRange.value.addIcon(object)
}
import { ElTree } from 'element-plus'
const fieldTreeFilterText = ref('')
const orgTreeFilterText = ref('')
const roleTreeFilterText = ref('')
const fieldTreeRef = ref<InstanceType<typeof ElTree>>()
const orgTreeRef = ref<InstanceType<typeof ElTree>>()
const roleTreeRef = ref<InstanceType<typeof ElTree>>()
watch(fieldTreeFilterText, (val) => {
fieldTreeRef.value!.filter(val)
})
watch(orgTreeFilterText, (val) => {
orgTreeRef.value!.filter(val)
})
watch(roleTreeFilterText, (val) => {
roleTreeRef.value!.filter(val)
})
const filterNode = (value: string, associatedFormsCurrentFormFieldTree: Tree) => {
if (!value) return true
return associatedFormsCurrentFormFieldTree.label.includes(value)
}
//flag
const associatedFormsHideDialogFlag = ref(false)
const associatedFormsDataRangeDialogFlag = ref(false)
//
function associatedFormsHideDialoghandle(){
associatedFormsHideDialogFlag.value = true
controlData.value.control.hideConditionHtmlCopy = controlData.value.control.hideConditionHtml
nextTick(() => {
aft.value.focusEditor()
})
}
function associatedFormsDataRangeDialoghandle(){
getAsfasfFieldTree().then(({ data }) => {
if(data.id==="cfid为空"){
//alert("cfid")
}else{
let resData = ref(data.children)
//let rootid_ = data.value.label
asfasfFieldTree.value = [{
id: 'rootid_'+data.label,
label: '关联的表单-'+data.label,
children: [...resData.value],
treeAttrs: data.treeAttrs,
}]
}
});
associatedFormsDataRangeDialogFlag.value = true
controlData.value.control.dataRangeConditionHtmlCopy = controlData.value.control.dataRangeConditionHtml
nextTick(() => {
aftRange.value.focusEditor()
})
}
//text
function aftTextChanged(str:string){
controlData.value.control.hideConditionHtml = str
}
function aftTextChangedRange(str:string){
controlData.value.control.dataRangeConditionHtml = str
}
//asf
function asfhTextCancel(){
determine.value = false
associatedFormsHideDialogFlag.value = false
controlData.value.control.hideConditionHtml = controlData.value.control.hideConditionHtmlCopy
//copy
aft.value.handelCancel(controlData.value.control.hideConditionHtmlCopy)
}
function asfhTextCancelRange(){
determineRange.value = false
associatedFormsDataRangeDialogFlag.value = false
controlData.value.control.dataRangeConditionHtml = controlData.value.control.dataRangeConditionHtmlCopy
//copy
aftRange.value.handelCancel(controlData.value.control.dataRangeConditionHtmlCopy)
}
//true
let determine = ref(true)
let determineRange = ref(true)
//associatedFormsHideDialogFlag true init tinymce
watch(associatedFormsHideDialogFlag, (val) => {
if(val===true&&determine.value===false){
setTimeout(() => {
aft.value.tinymceReInit()
}, 200);
}
})
watch(associatedFormsDataRangeDialogFlag, (val) => {
if(val===true&&determineRange.value===false){
setTimeout(() => {
aftRange.value.tinymceReInit()
}, 200);
}
})
//
function handleDetermine(){
associatedFormsHideDialogFlag.value = false
determine.value = true
controlData.value.control.hideConditionHtmlCopy = controlData.value.control.hideConditionHtml
}
function handleDetermineRange(){
associatedFormsDataRangeDialogFlag.value = false
determineRange.value = true
controlData.value.control.dataRangeConditionHtmlCopy = controlData.value.control.dataRangeConditionHtml
}
//
const associatedFormsFillRolesDialogFlag = ref(false)
//
function associatedFormsDataFillRolesDialoghandle(){
if(controlData.value.control.formid===''){
alert("请先选择要关联的表单")
}else{
associatedFormsFillRolesDialogFlag.value = true
}
}
function asfhTextCancelFillRoles(){
associatedFormsFillRolesDialogFlag.value = false
}
//
function handleDetermineFillRoles(){
associatedFormsFillRolesDialogFlag.value = false
}
watch(()=>store.activeKey, () => {
if(controlData.value.type==='associatedForms'){
setTimeout(() => {
formidChanged()
}, 800);
}
})
function addFillRole(){
let onlyNumber = uuidv4().replaceAll('-','').toString(); //
controlData.value.control.fillRoles.push({
leftValue:'',
rightValue:'',
id:onlyNumber,
})
}
function delRole(id:String){
const delRoleData:any = controlData.value.control.fillRoles
for (var i = 0; i < delRoleData.length; i++) {
if(delRoleData[i].id===id){
delRoleData.splice(i, 1);
i--; //
}
}
}
//liwenxuan20240403 associatedForms end
const optionsCss = [
@ -1907,6 +2239,9 @@ const gainFormGroupList = () =>{
})
}
onMounted(() => {
gainFormGroupList()
})
@ -2277,10 +2612,39 @@ const loadNextPage = () => {
</el-row>
<el-row v-else-if="item.type === 'associatedForms_hide'">
<el-button type="primary" append-to-body="true" modal="true" @click="associatedFormsHideDialogFlag = true" >设置隐藏条件</el-button>
<el-button v-if="controlData.control.hideConditionHtml===''" style="padding-top: 5px;" type="primary" link append-to-body="true" modal="true" @click="associatedFormsHideDialoghandle" >设置隐藏条件</el-button>
<div style="width:100%; cursor: pointer;" @click="associatedFormsHideDialoghandle" v-html="controlData.control.hideConditionHtml"></div>
</el-row>
<el-row v-else-if="item.type === 'associatedForms_form'">
<div style="margin-top: 25px;margin-left: -60px;">
<el-tree-select
v-model="controlData.control.formid"
style="width: 260px;"
:data="customerFormTree[0].children"
check-strictly
:render-after-expand="false"
filterable
@change="formidChanged"
/>
</div>
<!-- <div v-html="controlData.control.formid"></div> -->
</el-row>
<el-row v-else-if="item.type === 'associatedForms_dataRange'">
<el-button v-if="controlData.control.dataRangeConditionHtml===''" style="padding-top: 5px;" type="primary" link append-to-body="true" modal="true" @click="associatedFormsDataRangeDialoghandle" >设置数据范围</el-button>
<div style="width:100%; cursor: pointer;" @click="associatedFormsDataRangeDialoghandle" v-html="controlData.control.dataRangeConditionHtml"></div>
</el-row>
<el-row v-else-if="item.type === 'associatedForms_FillRoles'">
<el-button style="padding-top: 5px;" type="primary" link append-to-body="true" modal="true" @click="associatedFormsDataFillRolesDialoghandle" >设置数据填充规则</el-button>
</el-row>
<el-input
v-else
:type="item.inputStyle"
@ -2983,64 +3347,268 @@ const loadNextPage = () => {
<!-- 关联表单设置弹窗 liwenxuan 20240402 start -->
<el-dialog v-model="associatedFormsHideDialogFlag" title="隐藏条件" top="150px" style="margin-top:70px ;min-height: 500px" width="50%">
<el-dialog v-model="associatedFormsHideDialogFlag" title="隐藏条件" top="150px" :close-on-click-modal="false" :show-close="false" style="margin-top:70px ;min-height: 500px" width="50%" >
<template v-if="controlData.type=='associatedForms'">
<div class="common-layout">
<el-container>
<el-aside width="300px" style="height:400px;border: 1px solid gainsboro;margin-right: 5px;">
<el-aside width="300px" style="height:420px;border: 1px solid gainsboro;margin-right: 5px;">
<el-input
v-show="fieldTreeSearchFlag"
v-model="fieldTreeFilterText"
style="width:98%;margin: 3px;"
placeholder="搜索字段"
class="filter-tree"
/>
<el-tree
ref="fieldTreeRef"
node-key="id"
empty-text="请先保存当前表单,若需要展示本次编辑表单添加的字段,也需先保存"
:data="associatedFormsCurrentFormFieldTree"
:props="defaultProps"
:props="treeDefaultProps"
:filter-node-method="filterNode"
style="max-width: 600px; border: 1px solid gainsboro; margin: 3px;"
@node-expand="handleFieldTreeExpand"
@node-collapse="handleFieldTreeCollapse"
@node-click="handleFieldTreeNodeclick"
@node-contextmenu="handleFieldTreeContextmenu"
/>
<el-input
v-show="orgTreeSearchFlag"
v-model="orgTreeFilterText"
style="width:98%;margin: 3px;"
placeholder="搜索字段"
class="filter-tree"
/>
<el-tree
ref="orgTreeRef"
style="max-width: 600px; border: 1px solid gainsboro; margin: 3px;"
:data="orgAndManTree"
:props="defaultProps"
:props="treeDefaultProps"
:filter-node-method="filterNode"
@node-expand="handleOrgTreeExpand"
@node-collapse="handleOrgTreeCollapse"
@node-contextmenu="handleOrgTreeContextmenu"
/>
<el-input
v-show="roleTreeSearchFlag"
v-model="roleTreeFilterText"
style="width:98%;margin: 3px;"
placeholder="搜索字段"
class="filter-tree"
/>
<el-tree
ref="roleTreeRef"
style="max-width: 600px; border: 1px solid gainsboro; margin: 3px;"
:data="roleTree"
:props="treeDefaultProps"
:filter-node-method="filterNode"
@node-expand="handleRoleTreeExpand"
@node-collapse="handleRoleTreeCollapse"
@node-contextmenu="handleRoleTreeContextmenu"
/>
</el-aside>
<el-main style="border: 1px solid gainsboro; padding: 3px;" class="associatedFormsHideDialogMain">
<div style="border: 1px solid gainsboro; height: 7%; border-bottom: 0px; padding-top: 3px; padding-left: 5px; background-color: #E6F3FE;">当满足以下条件时此控件隐藏</div>
<div id="associatedFormsHideEditArea" style="border: 1px solid gainsboro; height: 63%; border-bottom: 0px;"></div>
<div style="border: 1px solid gainsboro; height: 30%;"></div>
<div id="associatedFormsHideEditArea" style="border: 1px solid gainsboro; height: 63%; border-bottom: 0px;">
<AssociatedFormsTinyace ref="aft" :aft-text="controlData.control.hideConditionHtml" :aft-text-copy = "controlData.control.hideConditionHtmlCopy" @text-change = "aftTextChanged"></AssociatedFormsTinyace>
<!-- <div style="border: 1px solid #4189EF;width:90px;height:26px;border-radius: 3px;padding:2px;text-align: center;cursor:pointer;float: right;margin-top: -32px;margin-right: 5px;z-index:99999999;position: relative;">
<span style="color: #4189EF;font:6px;margin-right: 5px;">fx</span>插入函数
</div> -->
</div>
<div style="border: 1px solid gainsboro; height: 30%; padding-top: 20px;">
<ul>
<li>请从左侧面板<span style="color: red">右击</span>选择字段或选项</li>
<li>支持<span style="color: red">英文</span>模式下运算符<!-- +-*/><== --></li>
<li>参考场景</li>
<span style="margin-left: 14px;">年龄控件输入的值大于10时需要隐藏当前控件则可将隐藏条件设置为年龄>10</span>
</ul>
</div>
</el-main>
</el-container>
</div>
</template>
<template #footer>
<div class="dialog-footer">
<!-- <el-button @click="associatedFormsHideDialogFlag = false">取消</el-button> -->
<el-button type="primary" @click="associatedFormsHideDialogFlag = false">
<el-button @click="asfhTextCancel">取消</el-button>
<el-button type="primary" @click="handleDetermine">
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- 数据范围编辑弹窗 -->
<el-dialog v-model="associatedFormsDataRangeDialogFlag" title="数据范围" top="150px" :close-on-click-modal="false" :show-close="false" style="margin-top:70px ;min-height: 500px" width="50%" >
<template v-if="controlData.type=='associatedForms'">
<div class="common-layout">
<el-container>
<el-aside width="300px" style="height:420px;border: 1px solid gainsboro;margin-right: 5px;">
<el-tree
ref="fieldTreeRef"
node-key="id"
:data="asfasfFieldTree"
:props="treeDefaultProps"
:filter-node-method="filterNode"
style="max-width: 600px; border: 1px solid gainsboro; margin: 3px;"
@node-expand="handleFieldTreeExpand"
@node-collapse="handleFieldTreeCollapse"
@node-contextmenu="handleFieldTreeContextmenuRange"
/>
<el-input
v-show="fieldTreeSearchFlag"
v-model="fieldTreeFilterText"
style="width:98%;margin: 3px;"
placeholder="搜索字段"
class="filter-tree"
/>
<el-tree
ref="fieldTreeRef"
node-key="id"
empty-text="请先保存当前表单,若需要展示本次编辑表单添加的字段,也需先保存"
:data="associatedFormsCurrentFormFieldTree"
:props="treeDefaultProps"
:filter-node-method="filterNode"
style="max-width: 600px; border: 1px solid gainsboro; margin: 3px;"
@node-expand="handleFieldTreeExpand"
@node-collapse="handleFieldTreeCollapse"
@node-contextmenu="handleFieldTreeContextmenuRange"
/>
<el-input
v-show="orgTreeSearchFlag"
v-model="orgTreeFilterText"
style="width:98%;margin: 3px;"
placeholder="搜索字段"
class="filter-tree"
/>
<el-tree
ref="orgTreeRef"
style="max-width: 600px; border: 1px solid gainsboro; margin: 3px;"
:data="orgAndManTree"
:props="treeDefaultProps"
:filter-node-method="filterNode"
@node-expand="handleOrgTreeExpand"
@node-collapse="handleOrgTreeCollapse"
@node-contextmenu="handleOrgTreeContextmenuRange"
/>
<el-input
v-show="roleTreeSearchFlag"
v-model="roleTreeFilterText"
style="width:98%;margin: 3px;"
placeholder="搜索字段"
class="filter-tree"
/>
<el-tree
ref="roleTreeRef"
style="max-width: 600px; border: 1px solid gainsboro; margin: 3px;"
:data="roleTree"
:props="treeDefaultProps"
:filter-node-method="filterNode"
@node-expand="handleRoleTreeExpand"
@node-collapse="handleRoleTreeCollapse"
@node-contextmenu="handleRoleTreeContextmenuRange"
/>
</el-aside>
<el-main style="border: 1px solid gainsboro; padding: 3px;" class="associatedFormsHideDialogMain">
<div style="border: 1px solid gainsboro; height: 7%; border-bottom: 0px; padding-top: 3px; padding-left: 5px; background-color: #E6F3FE;">仅可选择符合以下条件的数据</div>
<div id="associatedFormsHideEditArea" style="border: 1px solid gainsboro; height: 63%; border-bottom: 0px;">
<AssociatedFormsTinyaceRange ref="aftRange" :aft-text="controlData.control.dataRangeConditionHtml" :aft-text-copy = "controlData.control.dataRangeConditionHtmlCopy" @text-change = "aftTextChangedRange"></AssociatedFormsTinyaceRange>
<!-- <div style="border: 1px solid #4189EF;width:90px;height:26px;border-radius: 3px;padding:2px;text-align: center;cursor:pointer;float: right;margin-top: -32px;margin-right: 5px;z-index:99999999;position: relative;">
<span style="color: #4189EF;font:6px;margin-right: 5px;">fx</span>插入函数
</div> -->
</div>
<div style="border: 1px solid gainsboro; height: 30%; padding-top: 20px;">
<ul>
<li>请从左侧面板<span style="color: red">右击</span>选择字段或选项</li>
<li>支持<span style="color: red">英文</span>模式下运算符<!-- +-*/><== --></li>
<li>参考场景</li>
<span style="margin-left: 14px;">仅可选择关联表单中年龄大于10的数据则可将数据范围设置为年龄>10</span>
</ul>
</div>
</el-main>
</el-container>
</div>
</template>
<template #footer>
<div class="dialog-footer">
<el-button @click="asfhTextCancelRange">取消</el-button>
<el-button type="primary" @click="handleDetermineRange">
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- 数据填充规则弹窗 -->
<el-dialog v-model="associatedFormsFillRolesDialogFlag" title="数据填充规则" top="150px" :close-on-click-modal="false" :show-close="false" style="margin-top:70px ;min-height: 500px" width="40%" >
<template v-if="controlData.type=='associatedForms'">
<el-divider style="margin-top: 0px;" />
<div style="margin-top: -10px;"><span style="color: grey;">当选择具体数据后将按如下规则给当前表单字段填充数据 </span></div>
<el-button style="font-size: large;margin-top: 3px;" type="primary" link append-to-body="true" modal="true" @click="addFillRole"> 添加规则</el-button>
<el-divider />
<div style="height:300px;border:1px solid white;overflow-y:auto">
<template v-for="(item, index) in controlData.control.fillRoles" :key="controlData.control.fillRoles[index].id">
<AssociatedFormsFillRole v-model:left-value="controlData.control.fillRoles[index].leftValue" v-model:right-value="controlData.control.fillRoles[index].rightValue" :left-tree-source = "asfasfFieldTree[0].children" :right-tree-source = "associatedFormsCurrentFormFieldTree[0].children" :current-key="controlData.control.fillRoles[index].id" @del-Role = "delRole" ></AssociatedFormsFillRole>
</template>
</div>
</template>
<template #footer>
<div class="dialog-footer">
<!-- <el-button @click="asfhTextCancelFillRoles">取消</el-button> -->
<el-button type="primary" @click="handleDetermineFillRoles">
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- 关联表单设置弹窗 liwenxuan 20240402 end -->
</template>
<style lang='scss' scoped>
li::before {
content: "";
display: inline-block;
width: 4px;
height: 4px;
border-radius: 50%;
background-color: gray;
margin-right: 5px;
margin-left: 5px;
margin-bottom: 3.5px;
}
.sidebar-tools .el-tabs__content{
padding: 0;

125
src/components/IconSelect/appMenuSvgPage.vue

@ -0,0 +1,125 @@
<!--
@ 作者: 秦东
@ 时间: 2024-04-22 14:39:07
@ 备注: 选择图标弹窗
-->
<script lang='ts' setup>
import SvgIcon from "@/components/SvgIcon/index.vue";
import SvgPage from "@/components/IconSelect/svgPage.vue";
const props = defineProps({
isShow:{
type: Boolean,
default: false,
},
svgName:{
type:String,
require: false,
default:""
},
iconList:{
type:Object,
default(){
return {}
}
}
});
const visible = ref(false); //
const iconSelectorRef = ref();
const iconSelectorDialogRef = ref();
const emits = defineEmits(["update:isShow","update:svgName"]);
const filterIconNames = ref<string[]>([]);
//
onClickOutside(iconSelectorRef, () => (visible.value = false), {
ignore: [iconSelectorDialogRef],
});
watch(() => props.isShow, (val:boolean) =>{
if(val){
filterIconNames.value = props.iconList
}
})
/**
@ 作者: 秦东
@ 时间: 2024-04-22 16:43:49
@ 功能: 关闭
*/
const handleClose = () => {
emits("update:isShow",false)
}
/**
@ 作者: 秦东
@ 时间: 2024-04-22 16:54:03
@ 功能: 确定
*/
const handleSelect = (svgName:string) => {
emits("update:svgName",svgName)
handleClose()
}
</script>
<template>
<el-dialog
v-model="props.isShow"
title="选择图标"
width="500"
:before-close="handleClose"
>
<el-input
v-model="filterValue"
class="p-2"
placeholder="搜索图标"
clearable
@input="handleFilter"
/>
<el-divider border-style="dashed" style="margin:0px;" />
<el-scrollbar height="250px">
<ul class="icon_list">
<li
v-for="(iconName, index) in filterIconNames"
:key="index"
class="icon-item"
@click="handleSelect(iconName)"
>
<el-tooltip :content="iconName" placement="bottom" effect="light">
<svg-icon color="var(--el-text-color-regular)" :icon-class="iconName" />
</el-tooltip>
</li>
</ul>
</el-scrollbar>
</el-dialog>
</template>
<style lang='scss' scoped>
.icon_list {
display: flex;
flex-wrap: wrap;
padding-left: 0px;
margin-top: 10px;
.icon-item {
display: flex;
flex-direction: column;
align-items: center;
justify-items: center;
width: 10%;
padding: 5px;
margin: 0 5px 5px 0;
cursor: pointer;
border: 1px solid #ccc;
padding: 5px 10px;
&:hover {
color: var(--el-color-primary);
border-color: var(--el-color-primary);
transition: all 0.2s;
transform: scaleX(1.1);
}
}
}
.svgBox{
:deep(.el-popper){
padding:0px;
}
}
</style>

87
src/components/IconSelect/svgPage.vue

@ -0,0 +1,87 @@
<!--
@ 作者: 秦东
@ 时间: 2024-04-22 16:05:27
@ 备注: 图标选择列表
-->
<script lang='ts' setup>
const allIconNames: string[] = []; //
const filterValue = ref(""); //
const filterIconNames = ref<string[]>([]); //
/**
@ 作者: 秦东
@ 时间: 2024-04-22 16:05:52
@ 功能: 加载svg
*/
const loadIcons =() => {
const icons = import.meta.glob("../../assets/icons/*.svg");
for (const icon in icons) {
const iconName = icon.split("assets/icons/")[1].split(".svg")[0];
allIconNames.push(iconName);
}
filterIconNames.value = allIconNames;
// console.log("icon --->",allIconNames);
}
onMounted(()=>{
loadIcons();
})
</script>
<template>
<div class="svgBox">
<el-input
v-model="filterValue"
class="p-2"
placeholder="搜索图标"
clearable
@input="handleFilter"
/>
<el-divider border-style="dashed" style="margin:0px;" />
<el-scrollbar height="150px">
<ul class="icon_list">
<li
v-for="(iconName, index) in filterIconNames"
:key="index"
class="icon-item"
@click="handleSelect(iconName)"
>
<el-tooltip :content="iconName" placement="bottom" effect="light">
<svg-icon color="var(--el-text-color-regular)" :icon-class="iconName" />
</el-tooltip>
</li>
</ul>
</el-scrollbar>
</div>
</template>
<style lang='scss' scoped>
.icon_list {
display: flex;
flex-wrap: wrap;
padding-left: 10px;
margin-top: 10px;
.icon-item {
display: flex;
flex-direction: column;
align-items: center;
justify-items: center;
width: 10%;
padding: 5px;
margin: 0 5px 5px 0;
cursor: pointer;
border: 1px solid #ccc;
padding: 5px 10px;
&:hover {
color: var(--el-color-primary);
border-color: var(--el-color-primary);
transition: all 0.2s;
transform: scaleX(1.1);
}
}
}
.svgBox{
:deep(.el-popper){
padding:0px;
}
}
</style>

2
src/components/SvgIcon/index.vue

@ -21,7 +21,7 @@ const props = defineProps({
},
color: {
type: String,
default: "",
default: "currentColor",
},
size: {
type: String,

8
src/router/index.ts

@ -1,5 +1,5 @@
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
import CreatePage from "@/views/sysworkflow/codepage/createpage.vue";
export const Layout = () => import("@/layout/index.vue");
// 静态路由
@ -13,6 +13,11 @@ export const constantRoutes: RouteRecordRaw[] = [
path: "/redirect/:path(.*)",
component: () => import("@/views/redirect/index.vue"),
},
{
path:"/create",
name: "create",
component: () => import('@/views/sysworkflow/codepage/createpage.vue'),
}
],
},
@ -52,6 +57,7 @@ export const constantRoutes: RouteRecordRaw[] = [
],
},
// 外部链接
/*{
path: '/external-link',

12
src/types/components.d.ts

@ -11,6 +11,7 @@ declare module '@vue/runtime-core' {
export interface GlobalComponents {
AceDrawer: typeof import('./../components/DesignForm/aceDrawer.vue')['default']
AddNode: typeof import('./../components/workflow/addNode.vue')['default']
AppMenuSvgPage: typeof import('./../components/IconSelect/appMenuSvgPage.vue')['default']
ApproverDrawer: typeof import('./../components/workflow/drwer/approverDrawer.vue')['default']
BianXian: typeof import('./../components/DesignForm/designLayout/bianXian.vue')['default']
Breadcrumb: typeof import('./../components/Breadcrumb/index.vue')['default']
@ -110,7 +111,17 @@ declare module '@vue/runtime-core' {
IconSelect: typeof import('./../components/IconSelect/index.vue')['default']
IEpCaretBottom: typeof import('~icons/ep/caret-bottom')['default']
IEpClose: typeof import('~icons/ep/close')['default']
<<<<<<< HEAD
IEpSetting: typeof import('~icons/ep/setting')['default']
=======
IEpDelete: typeof import('~icons/ep/delete')['default']
IEpEdit: typeof import('~icons/ep/edit')['default']
IEpPlus: typeof import('~icons/ep/plus')['default']
IEpRefresh: typeof import('~icons/ep/refresh')['default']
IEpSearch: typeof import('~icons/ep/search')['default']
IEpSetting: typeof import('~icons/ep/setting')['default']
IEpView: typeof import('~icons/ep/view')['default']
>>>>>>> v8_master
LangSelect: typeof import('./../components/LangSelect/index.vue')['default']
LayoutPage: typeof import('./../components/DesignForm/layoutPage/index.vue')['default']
List: typeof import('./../components/DesignForm/public/form/components/list.vue')['default']
@ -135,6 +146,7 @@ declare module '@vue/runtime-core' {
SingleUpload: typeof import('./../components/Upload/SingleUpload.vue')['default']
SizeSelect: typeof import('./../components/SizeSelect/index.vue')['default']
SvgIcon: typeof import('./../components/SvgIcon/index.vue')['default']
SvgPage: typeof import('./../components/IconSelect/svgPage.vue')['default']
TableListPage: typeof import('./../components/DesignForm/tableListPage/index.vue')['default']
Template: typeof import('./../components/DesignForm/template.vue')['default']
TextPage: typeof import('./../components/DesignForm/designLayout/textPage.vue')['default']

594
src/views/sysworkflow/codepage/createpage.vue

@ -0,0 +1,594 @@
<!--
@ 作者: 袁纪菲
@ 时间: 2024.4.16
@ 备注: 新建应用
-->
<script lang="ts" setup>
import { ref , onMounted } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
interface Menu {
id: number;
name: string;
type: string; //
parentId?: number | undefined; //ID
children?: Menu[]; //
expanded?: boolean;// true
order?: number; // order
}
// menu
function transformMenu(menuItems: Menu[], parentId?: number): Menu[] {
const transformedItems: Menu[] = [];
let order = 0; //
for (const item of menuItems) {
const newItem: Menu = { ...item, parentId, order: order++ }; //
if (item.type === 'group') {
const childItems = menuItems.filter((m) => m.parentId === item.id);
newItem.children = transformMenu(childItems, item.id);
}
transformedItems.push(newItem);
}
return transformedItems;
}
//
const initialMenu = [
{ id: 1, name: '分组A', type: 'group' , expanded: true },
{ id: 2, name: '表单1', type: 'form', parentId: 1 },
{ id: 3, name: '分组B', type: 'group', parentId: 1 , expanded: true },
{ id: 4, name: '表单2', type: 'form', parentId: 3 },
];
const menu = ref<Menu[]>(transformMenu(initialMenu)); // transformMenu menu
const appName = ref('');
const createFormVisible = ref(false);
const createGroupVisible = ref(false);
const moveToVisible = ref(false);
const renameVisible = ref(false);
const newFormName = ref('');
const newGroupName = ref('');
const renameValue = ref('');
//
let renameItem: Menu | null = null;
let originalName: string = '';
const selectedParentId = ref<number | undefined>(undefined);
// ID
const selectedGroupId = ref<number | null>(null);
//ID
const currentParentForNewForm = ref<number | undefined>(undefined);
const currentParentForNewGroup = ref<number | undefined>(undefined);
//
onMounted(() => {
appName.value = localStorage.getItem('appName') || '未命名应用';
});
//
const saveAppName = () => {
localStorage.setItem('appName', appName.value);
}
//
const openCreateFormDialog = () =>{
createFormVisible.value = true;
}
//
const saveNewForm = () =>{
if (!newFormName.value.trim()) {
ElMessage.error('表单名称不能为空');
return;
}
const newForm: Menu = {
id: menu.value.length + 1, // 使ID
name: newFormName.value,
type: 'form',
parentId: currentParentForNewForm.value, // ID
};
// children
if (currentParentForNewForm.value !== undefined) {
const parent = menu.value.find((item) => item.id === currentParentForNewForm.value);
if (parent && parent.children) {
parent.children.push(newForm);
}
} else {
// menu
menu.value.push(newForm);
}
ElMessage.success('新建成功');
createFormVisible.value = false;
newFormName.value = '';
}
//
const openCreateGroupDialog = () =>{
createGroupVisible.value = true;
}
//
const saveNewGroup = () =>{
if (!newGroupName.value.trim()) {
ElMessage.error('分组名称不能为空');
return;
}
const newGroup: Menu = {
id: menu.value.length + 1, // 使ID
name: newGroupName.value,
type: 'group',
parentId: currentParentForNewGroup.value, // ID
};
// children
if (currentParentForNewGroup.value !== undefined) {
const parent = menu.value.find((item) => item.id === currentParentForNewGroup.value);
if (parent && parent.children) {
parent.children.push(newGroup);
}
} else {
// menu
menu.value.push(newGroup);
}
createGroupVisible.value = false;
newGroupName.value = '';
}
//
const openCreateChildFormDialog = (parent: Menu) => {
// 便使
createFormVisible.value = true;
// ID
currentParentForNewForm.value = parent.id;
};
//
const openCreateChildGroupDialog = (parent: Menu) => {
// 便使
createGroupVisible.value = true;
// ID
currentParentForNewGroup.value = parent.id;
};
//
const confirmDelete = (item: Menu) => {
const isParentGroup = item.children && item.children.length > 0 && item.type === 'group' && item.parentId === selectedParentId.value; //
if (isParentGroup) {
//
ElMessageBox.confirm(
`确定要删除分组 "${item.name}" 及其所有子分组和表单吗?`,
'警告',
{
confirmButtonText: '确定删除',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
deleteMenuRecursively(item); //
}).catch(() => {}); //
} else {
//
ElMessageBox.confirm(
`确定要删除 ${item.type === 'group' ? '分组' : '表单'} "${item.name}" 吗?`,
'警告',
{
confirmButtonText: '确定删除',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
removeSingleItem(item); //
}).catch(() => {}); //
}
};
//
const deleteMenuRecursively = (parent: Menu) => {
//
for (const child of parent.children ?? []) {
if (child.children) {
deleteMenuRecursively(child); //
}
const childIndex = menu.value.findIndex((i) => i.id === child.id);
if (childIndex !== -1) {
menu.value.splice(childIndex, 1); //
}
}
const parentIndex = menu.value.findIndex((i) => i.id === parent.id);
if (parentIndex !== -1) {
menu.value.splice(parentIndex, 1); //
}
};
//
const removeSingleItem = (item: Menu) => {
const itemIndex = menu.value.findIndex((i) => i.id === item.id);
if (itemIndex !== -1) {
menu.value.splice(itemIndex, 1); //
}
// children
if (item.parentId !== undefined) {
const parent = menu.value.find((i) => i.id === item.parentId);
if (parent && parent.children) {
const childIndex = parent.children.findIndex((c) => c.id === item.id);
if (childIndex !== -1) {
parent.children.splice(childIndex, 1);
}
}
}
};
//
const showRenameDialog = (item: Menu) => {
renameItem = item;
originalName = item.name;
renameVisible.value = true;
// itemname
};
//
const handleRenameClose = () => {
renameItem = null;
originalName = '';
renameVisible.value = false;
};
//
const handleRenameCancel = () => {
handleRenameClose();
renameValue.value = originalName;
};
//
const handleRenameSave = () => {
if (!renameValue.value.trim()) {
ElMessage.error('名称不能为空');
return;
}
if (renameItem) {
renameItem.name = renameValue.value;
ElMessage.success('重命名成功');
}
handleRenameClose();
};
//
const showMoveToDialog = (item: Menu) => {
selectedGroupId.value = item.id;
moveToVisible.value = true;
};
//
const handleMoveToClose = () => {
selectedGroupId.value = null;
moveToVisible.value = false;
};
//
const handleMoveToCancel = () => {
handleMoveToClose();
};
//
const handleMoveToSave = () => {
if (!selectedParentId.value) {
ElMessage.error('请选择目标分组');
return;
}
const movingItemIndex = menu.value.findIndex((item) => item.id === selectedGroupId.value);
if (movingItemIndex === -1) {
ElMessage.error('移动失败,找不到待移动的项');
return;
}
const movingItem = menu.value[movingItemIndex];
const targetGroup = menu.value.find((item) => item.id === selectedParentId.value);
if (!targetGroup || targetGroup.type !== 'group') {
ElMessage.error('移动失败,找不到目标分组');
return;
}
// parentId
const movedItem = menu.value.splice(movingItemIndex, 1)[0];
movedItem.parentId = targetGroup.id;
// children
if (!targetGroup.children) {
targetGroup.children = [];
}
const insertIndex = targetGroup.children.findIndex((child) => child.id > movedItem.id);
targetGroup.children.splice(insertIndex >= 0 ? insertIndex : targetGroup.children.length, 0, movedItem);
ElMessage.success('移动成功');
handleMoveToClose();
};
// toggleExpand expanded
const toggleExpand = (group: Menu) => {
group.expanded = !group.expanded;
};
</script>
<template>
<div class="common-layout">
<!-- 顶部导航栏 -->
<el-header>
<div>
<el-input
v-model="appName"
class="header-input"
clearable
placeholder="未命名应用"
@clear="saveAppName"
@blur="saveAppName"
></el-input>
</div>
<div class="header-btn">
<el-button type="primary" >编辑表单</el-button>
</div>
</el-header>
<!-- 主体布局容器 -->
<el-container>
<!-- 左侧侧边栏 -->
<el-aside>
<div class="sidebar-upper">
<!-- 搜索框 -->
<el-input placeholder="搜索" class="search-input" />
<!-- 新增按钮 -->
<el-dropdown trigger="click">
<el-button type="primary" plain class="add-btn">
<el-icon><Plus /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="() => openCreateFormDialog()"><el-icon><DocumentAdd /></el-icon></el-dropdown-item>
<el-dropdown-item @click="() => openCreateGroupDialog()"><el-icon><FolderAdd /></el-icon></el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<!-- 侧边栏下半部区域 -->
<div class="sidebar-lower">
<ul class="sidebar-menu">
<template v-for="(item) in menu">
<template v-if="item.type === 'group'">
<!-- 分组 -->
<li :key="item.id">
<div class="menu-item" :class="{ 'is-collapsed': !item.expanded }" @click="toggleExpand(item)">
<span><el-icon><Folder /></el-icon>{{ item.name }}</span>
<el-dropdown trigger="click" placement="bottom-end">
<el-icon><MoreFilled /></el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="openCreateChildFormDialog(item)"><el-icon><DocumentAdd /></el-icon></el-dropdown-item>
<el-dropdown-item @click="openCreateChildGroupDialog(item)"><el-icon><FolderAdd /></el-icon></el-dropdown-item>
<el-dropdown-item @click="confirmDelete(item)"><el-icon><Delete /></el-icon></el-dropdown-item>
<el-dropdown-item @click="showRenameDialog(item)"><el-icon><EditPen /></el-icon></el-dropdown-item>
<el-dropdown-item @click="showMoveToDialog(item)"><el-icon><FolderRemove /></el-icon></el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<!-- 分组展开后显示子表单/子分组 -->
<transition name="expand-collapse">
<ul v-if="item.children && item.expanded">
<li v-for="child in item.children" :key="child.id">
<!-- 对子表单和子分组再次进行类型判断递归渲染 -->
<template v-if="child.type === 'group'">
<!-- 子分组模板 -->
<div class="menu-item-child">
<span @click="toggleExpand(child)"><el-icon><Folder /></el-icon>{{ child.name }}</span>
<el-dropdown trigger="click" placement="bottom-end">
<el-icon><MoreFilled /></el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="openCreateChildFormDialog(item)"><el-icon><DocumentAdd /></el-icon></el-dropdown-item>
<el-dropdown-item @click="openCreateChildGroupDialog(item)"><el-icon><FolderAdd /></el-icon></el-dropdown-item>
<el-dropdown-item @click="confirmDelete(item)"><el-icon><Delete /></el-icon></el-dropdown-item>
<el-dropdown-item @click="showRenameDialog(item)"><el-icon><EditPen /></el-icon></el-dropdown-item>
<el-dropdown-item @click="showMoveToDialog(item)"><el-icon><FolderRemove /></el-icon></el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
<template v-else-if="child.type === 'form'">
<!-- 子表单模板 -->
<div class="menu-item-child">
<span><el-icon><Document /></el-icon>{{ child.name }}</span>
<el-dropdown trigger="click" placement="bottom-end">
<el-icon><MoreFilled /></el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="confirmDelete(item)"><el-icon><Delete /></el-icon></el-dropdown-item>
<el-dropdown-item @click="showRenameDialog(item)"><el-icon><EditPen /></el-icon></el-dropdown-item>
<el-dropdown-item @click="showMoveToDialog(item)"><el-icon><FolderRemove /></el-icon></el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
</li>
</ul>
</transition>
</li>
</template>
<!-- 表单 -->
<template v-else-if="item.type === 'form'">
<!-- 表单模板 -->
<li :key="item.id" class="menu-item">
<span><el-icon><Document /></el-icon>{{ item.name }}</span>
<el-dropdown trigger="click" placement="bottom-end">
<el-icon><MoreFilled /></el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="confirmDelete(item)"><el-icon><Delete /></el-icon></el-dropdown-item>
<el-dropdown-item @click="showRenameDialog(item)"><el-icon><EditPen /></el-icon></el-dropdown-item>
<el-dropdown-item @click="showMoveToDialog(item)"><el-icon><FolderRemove /></el-icon></el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</li>
</template>
</template>
</ul>
</div>
</el-aside>
<!-- 主要内容区域 -->
<el-main>
表单预览
</el-main>
</el-container>
</div>
<!-- 新建表单对话框 -->
<el-dialog v-model="createFormVisible" title="新建表单" >
<el-form label-width="80px">
<el-form-item label="表单名称">
<el-input v-model="newFormName" />
</el-form-item>
</el-form>
<div class="dialog-footer">
<el-button @click="createFormVisible = false">取消</el-button>
<el-button type="primary" @click="saveNewForm">保存</el-button>
</div>
</el-dialog>
<!-- 新建分组对话框 -->
<el-dialog v-model="createGroupVisible" title="新建分组">
<el-form label-width="80px">
<el-form-item label="分组名称">
<el-input v-model="newGroupName" />
</el-form-item>
</el-form>
<div class="dialog-footer">
<el-button @click="createGroupVisible = false">取消</el-button>
<el-button type="primary" @click="saveNewGroup">保存</el-button>
</div>
</el-dialog>
<!-- 修改名称对话框 -->
<el-dialog v-model="renameVisible" title="修改名称" @close="handleRenameClose">
<el-form label-width="80px">
<el-form-item label="名称">
<el-input v-model="renameValue" />
</el-form-item>
</el-form>
<div class="dialog-footer">
<el-button @click="handleRenameCancel">取消</el-button>
<el-button type="primary" @click="handleRenameSave">保存</el-button>
</div>
</el-dialog>
<!-- 移动分组对话框 -->
<el-dialog
v-model="moveToVisible"
title="移动分组"
@close="handleMoveToClose">
<el-select
v-model="selectedParentId"
placeholder="选择目标分组"
>
<el-option
v-for="(group, index) in menu.filter((m) => m.type === 'group' && m.id !== selectedGroupId)"
:key="index"
:label="group.name"
:value="group.id"
/>
</el-select>
<div class="dialog-footer">
<el-button @click="handleMoveToCancel">取消</el-button>
<el-button type="primary" @click="handleMoveToSave">保存</el-button>
</div>
</el-dialog>
</template>
<style scoped>
.common-layout {
height: 100vh;
overflow: hidden;
}
.el-header {
height: 50px;
display: flex;
justify-content: space-between;
}
/* 应用名称 */
.header-input {
width: 100px;
margin-top: 10px;
}
/* 编辑表单按钮 */
.header-btn{
margin-top: 10px;
}
/* 侧边栏整体 */
.el-aside {
background-color: #f5f7fa;
width: 250px;
min-height: 100vh;
display: flex;
flex-direction: column;
position: relative;
}
/* 侧边栏上部区域 */
.sidebar-upper {
display: flex;
padding: 20px;
border-bottom: 1px solid #ebeef5;
}
/* 搜索框 */
.search-input{
width: 200px;
margin-right: 10px;
}
/* 新建按钮 */
.add-btn{
cursor: pointer;
height: 30px;
width: 30px;
margin-top: 2px;
}
/* 侧边栏下半部分菜单样式 */
.sidebar-lower {
overflow-y: auto;
padding: 5px 0;
}
.sidebar-menu {
list-style: none;
margin: 0;
padding: 0;
}
/* 父分组/表单 */
.menu-item {
display: flex;
justify-content: space-between;
padding: 8px 16px;
font-size: 14px;
line-height: 1.5;
color: #222222;
cursor: pointer;
transition: background-color 0.2s ease;
}
.menu-item:hover,
.menu-item:focus {
background-color: #cacbcc;
}
/* 子分组/表单 */
.menu-item-child{
display: flex;
justify-content: space-between;
padding: 8px 16px 8px 35px;
font-size: 14px;
line-height: 1.5;
color: #222222;
cursor: pointer;
transition: background-color 0.2s ease;
}
.menu-item-child:hover,
.menu-item-child:focus {
background-color: #cacbcc;
}
/* 定义展开/折叠动画的通用样式 */
.expand-collapse-enter-active,
.expand-collapse-leave-active {
transition: max-height 0.3s ease, opacity 0.3s ease;
overflow: hidden;
}
/* 定义展开动画 */
.expand-collapse-enter-from {
max-height: 0;
opacity: 0;
}
/* 定义折叠动画 */
.expand-collapse-leave-to {
max-height: 0;
opacity: 0;
}
/* 下拉菜单样式 */
.el-dropdown-menu {
padding: 0;
min-width: 100px;
}
/* 表单预览 */
.el-main {
flex: 1;
padding: 20px;
background-color: #ffffff;
}
/* 对话框样式 */
.dialog-footer {
text-align:right;
margin-top: 20px;
}
</style>

106
src/views/sysworkflow/codepage/editpage.vue

@ -0,0 +1,106 @@
<!--
@ 作者: 袁纪菲
@ 时间: 2024.4.16
@ 备注: 编辑应用
-->
<script lang="ts" setup>
import { reactive, ref , computed } from 'vue'
import { ElMessage} from 'element-plus';
const props = defineProps({
// eslint-disable-next-line vue/prop-name-casing
Visible:Boolean
});
const emits = defineEmits(["update:Visible", "data"]);
//
const formLabelWidth = ref('140px')
const form = reactive({
data: {
id: '',
name: '',
icon: '',
},
visible: computed({
get(){
return props.Visible
},
set(val) {
emits('update:Visible', val)
}
})
})
//
const previewImageUrl = ref<string>(''); //
//
const beforeUpload = (file: any) => {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJPG) {
ElMessage.error('只能上传 JPG 或 PNG 格式的图片');
return false;
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
ElMessage.error('图片大小不能超过 2MB');
return false;
}
// URL
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (e: ProgressEvent<FileReader>) => {
if (e.target?.result) {
previewImageUrl.value = e.target.result as string;
form.data.icon = e.target.result as string;// null
} else {
//
previewImageUrl.value = '';
ElMessage.error('无法预览图片,请重新上传');
}
};
return isJPG && isLt2M;
};
//
const submitForm = () => {
emits('data', form.data); //
emits('update:Visible', false); //
};
</script>
<template>
<div class="edit-container">
<el-dialog
:model-value="props.Visible"
title="编辑应用"
width="500">
<el-form :model="form">
<el-form-item label="应用名称" :label-width="formLabelWidth">
<el-input v-model="form.data.name" placeholder="请输入应用名称" autocomplete="off" />
</el-form-item>
<el-form-item label="应用图标" :label-width=formLabelWidth>
<el-upload
class="picture-uploader"
action=""
:auto-upload="false"
:before-upload="beforeUpload"
list-type="picture-card">
<i class="el-icon-plus"></i>
</el-upload>
<!-- 预览区域 -->
<div v-if="form.data.icon" class="preview-image">
<img :src="form.data.icon" alt="预览图片" />
</div>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="emits('update:Visible', false)">取消</el-button>
<el-button type="primary" @click="submitForm">
保存
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<style scoped>
</style>

363
src/views/sysworkflow/codepage/page.vue

@ -1,213 +1,252 @@
<!--
@ 作者: 袁纪菲
@ 时间: 2024.3.18
@ 备注: 应用管理父组件
@ 时间: 2024.4.16
@ 备注: 应用管理
-->
<script lang = "ts" setup>
import cardedit from './cardedit.vue';
import cardadd from './cardadd.vue';
import {ref,onMounted,onUnmounted,watch} from 'vue';
import {Delete,Edit,View,MoreFilled} from '@element-plus/icons-vue'
<script lang="ts" setup>
import editpage from './editpage.vue';
import { ref , onMounted } from 'vue';
import { useRouter } from 'vue-router';
//
const props = defineProps({
visible:Boolean
});
const drawerRefadd = ref(false);
const drawerRefedit = ref(false)
//
interface cardDatass {
//
const router = useRouter();
const goToCreatePage = () => {
try {
router.push({ name: 'create' });
} catch (error) {
console.error("导航到创建页面时发生错误:", error);
}
};
const dialogRefedit = ref(false);
interface cardDatas {
id: number;
name: string;
imageUrl: '',
}
const cardData = ref<cardDatass[]>([]);
const emits = defineEmits(["update:visible", "data"]);
//
const opencardadd = () => {
drawerRefadd.value = true;
cardadd.value.onSubmit = handleAddCard;
};
//
const handleAddCard = (newCard: cardDatass) => {
cardData.value.push(newCard);
};
//
const opencardedit = (index: number) => {
drawerRefedit.value = true;
// cardedit
cardedit.value.cardData = cardData.value[index];
cardedit.value.onSubmit = handleEditCard;
};
//
const handleEditCard = (newCard: cardDatass) => {
cardData.value.splice(0,1,newCard);
};
//
const deleteCard = (index: number) => {
cardData.value.splice(index, 1);
emits('data', cardData.value);
};
// 'data'
watch(() => props.visible, () => {
},
{ immediate: true }
);
//
const handleNewCard = (newCard: cardDatass) => {
cardData.value.push(newCard);
};
icon: string;
}
//
const cardData = ref<cardDatas[]>([]);
const emits = defineEmits(["update:Visible", "data"]);
onMounted(() => {
for(let i = 0;i<9;i++){
if (!cardData.value.length) {
for (let i = 0; i < 9; i++) {
cardData.value.push({
id: i,
name: '卡片' + i,
imageUrl: ''
name: '标题' + i,
icon: 'https://img.zcool.cn/community/01f3fb5a66a75ea80120a123a9f582.jpg@2o.jpg'
});
}
}
});
//
const showEditPage = (index: number) => {
dialogRefedit.value = true;
editpage.value.cardData = cardData.value[index];
editpage.value.onSubmit = handleEdit;
};
//
const handleEdit = (newCard: cardDatas) => {
cardData.value.splice(0, 1, newCard);
};
//
const deleteCard = (index: number) => {
cardData.value.splice(index, 1);
};
</script>
<template>
<cardadd v-model:visible="drawerRefadd" :keyval="props.visible" @data="handleNewCard"/>
<cardedit v-model:visible="drawerRefedit" :keyval="props.visible" @data="handleNewCard"/>
<el-row :gutter="10">
<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
<div class="grid-content ep-bg-purple" >
<el-card class="cardlarge">
<template #header>
<div class="cardhead-large">
<el-row class="block-col-2">
<el-col style="text-align: right;">
<el-dropdown>
<span class="el-dropdown-link">
<el-icon><MoreFilled /></el-icon>
</span>
<editpage v-model:Visible="dialogRefedit" @data="handleEdit" />
<div class="common-layout">
<el-container>
<el-container>
<el-main class="layout-content">
<el-header class="content-header">
<el-button class="create-btn" @click="goToCreatePage">
<el-icon><Plus /></el-icon>
新建应用
</el-button>
</el-header>
<el-main>
<el-scrollbar class="scrollbar">
<div class="xiangying">
<el-col v-for="(card) in cardData" :key="card.id">
<el-card class="cardpattern" shadow="hover" >
<div class="button">
<img :src="card.icon" class="picture" />
<span>自定义卡片</span>
<el-icon class="star">
<Star />
</el-icon>
<el-dropdown class="xiala" trigger="click">
<el-icon>
<MoreFilled />
</el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="opencardadd" >添加</el-dropdown-item>
<el-dropdown-item >编辑</el-dropdown-item>
<el-dropdown-item >删除</el-dropdown-item>
<el-dropdown-item @click = "() => showEditPage">编辑应用</el-dropdown-item>
<el-dropdown-item @click = "() => deleteCard">删除</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
<el-col style="text-align: left;">
<span>标题一</span>
</el-col>
</el-row>
</div>
</template>
<div class="grid-content ep-bg-purple" >
<el-row :gutter="10" >
<el-col v-for="(card, index) in cardData" :key="card.id" :xs="8" :sm="12" :md="8" :lg="8" :xl="8">
<el-card class="cardpattern">
<img
title="示例图片"
class="picture"
/>
<div class="cardhead">
<span>{{ card.name }}</span>
</div>
<div class="bottom">
<el-button size="small" circle class="button" :icon="View"></el-button>
<el-button size="small" circle class="button" :icon="Edit" @click="() => opencardedit(index)"></el-button>
<el-button size="small" circle class="button" :icon="Delete" @click="() => deleteCard(index)"></el-button>
</div>
</el-card>
</el-col>
</el-row>
</div>
</el-card>
</div>
</el-col>
</el-row>
<!-- 分页 -->
<div class="example-pagination-block">
<div class="example-demonstration"></div>
<el-pagination layout="prev, pager, next" :total="50" />
</el-scrollbar>
</el-main>
</el-main>
</el-container>
</el-container>
</div>
</template>
<style scoped>
/* 小卡片 */
.cardpattern{
padding-bottom: 0px;
margin-bottom: 10px;
min-width: 100px;
.common-layout {
width: 100%;
height: 100%;
.el-container {
height: 100%;
/* 不折叠的时候宽度是200px,折叠的时候宽度自适应 */
}
}
svg {
width: 1.5em;
margin-right: 5px;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
}
/* 小卡片标题 */
.cardhead{
padding: 10px;
font-size: 15px;
.el-aside {
width: auto;
}
/* 大卡片 */
.cardlarge{
max-width: 480px;
.el-menu-vertical-demo {
border-right: none;
margin-top: 0;
height: 100%;
background-color: #586177;
color: #fff;
}
/* 大卡片标题 */
.cardhead-large{
font-size: 20px;
.el-menu-item {
color: #ffffff;
}
/* 按钮整体 */
.bottom {
margin-top: 20px;
line-height: 10px;
/* 侧边栏标题 */
.side-header {
height: 64px;
padding: 0;
display: flex;
justify-content: space-evenly;
align-items: center;
justify-content: center;
}
/* 单个按钮 */
.button {
padding: 0px;
min-height: auto;
margin-bottom: 1px;
/* 右侧上方标题 */
.up-header {
display: flex;
align-items : center;
justify-content:left;
background-color: #fff;
padding: 0;
}
/* 图片 */
.picture {
height: 100%;
min-height: 50px;
max-height: 100px;
display: block;
width: 100%;
min-width: 50px;
/* 缩放侧边栏按钮 */
.trigger {
font-size: 18px;
line-height: 64px;
padding: 0 24px;
cursor: pointer;
}
.el-col {
border-radius: 4px;
.el-main {
overflow-y: auto;
padding-right: 0; /* 取消内外边距以免影响滚动区域 */
}
.grid-content {
border-radius: 4px;
min-height: 36px;
/* 内容框 */
.layout-content{
padding: 15px;
background: #f5f5f5;
min-height: 280px;
}
.app_box{
margin: 15px 0 0 0px;
/* 新建按钮框 */
.content-header {
display: flex;
justify-content: space-between;
text-align: right;
font-size: 12px;
height: 40px;
}
/* 新建按钮 */
.create-btn {
margin-right: 10px;
background-color: #1090ff;
color: #ffffff;
}
/* 卡片整体所在区域 */
.scrollbar{
height: 700px;
overflow-y: auto; /* 自动显示垂直滚动条 */
margin-right: 10px;
box-sizing: border-box; /* 保证高度计算包含内边距和边框 */
.block-col-2 .demonstration {
display: block;
color: var(--el-text-color-secondary);
font-size: 14px;
margin-bottom: 20px;
/* 当内容不够一屏时,禁用滚动条 */
&::-webkit-scrollbar {
width: 0;
height: 0;
}
}
/* 内容部分卡片响应式 */
.xiangying {
display: grid;
grid-auto-rows: minmax(160px, auto); /* 或者指定最大高度 */
grid-gap: 1px;
grid-template-columns: repeat(auto-fit, 230px);
overflow-y: auto; /* 添加此行以允许卡片区域内部内容滚动 */
}
/* 卡片 */
.cardpattern {
padding: 0px;
margin-bottom: 10px;
width: 220px;
height: 150px;
transition: all 0.3s ease;
}
.block-col-2 .el-dropdown-link {
/* 卡片标题 */
.cardhead {
margin-top: 50px;
font-size: 18px;
color: #000000;
font-weight: 500;
text-align: left;
font-family: PingFangSC-Regular;
line-height: 20px;
}
/* 收藏按钮与下拉框区域 */
.button {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 3px;
}
/* 收藏按钮 */
.star {
font-size: 20px;
margin-right: -5px;
}
/* 分页 */
.example-pagination-block + .example-pagination-block {
margin-top: 10px;
/* 占位元素 */
.placeholder {
height:14px;
/* 设置为图标按钮组的高度 */
width:100%;
/* 设置为图标按钮组的宽度 */
visibility: hidden;
/* 或者 opacity: 0; 保证不会影响布局但不可见 */
pointer-events: none;
/* 防止此元素捕获鼠标事件 */
}
.example-pagination-block .example-demonstration {
margin-bottom: 16px;
/* 图片 */
.picture {
width: 3cap;
margin: 1px;
}
</style>

213
src/views/sysworkflow/codepage/page0318.vue

@ -0,0 +1,213 @@
<!--
@ 作者: 袁纪菲
@ 时间: 2024.3.18
@ 备注: 应用管理父组件
-->
<script lang = "ts" setup>
import cardedit from './cardedit.vue';
import cardadd from './cardadd.vue';
import {ref,onMounted,onUnmounted,watch} from 'vue';
import {Delete,Edit,View,MoreFilled} from '@element-plus/icons-vue'
//
const props = defineProps({
visible:Boolean
});
const drawerRefadd = ref(false);
const drawerRefedit = ref(false)
//
interface cardDatass {
id: number;
name: string;
imageUrl: '',
}
const cardData = ref<cardDatass[]>([]);
const emits = defineEmits(["update:visible", "data"]);
//
const opencardadd = () => {
drawerRefadd.value = true;
cardadd.value.onSubmit = handleAddCard;
};
//
const handleAddCard = (newCard: cardDatass) => {
cardData.value.push(newCard);
};
//
const opencardedit = (index: number) => {
drawerRefedit.value = true;
// cardedit
cardedit.value.cardData = cardData.value[index];
cardedit.value.onSubmit = handleEditCard;
};
//
const handleEditCard = (newCard: cardDatass) => {
cardData.value.splice(0,1,newCard);
};
//
const deleteCard = (index: number) => {
cardData.value.splice(index, 1);
emits('data', cardData.value);
};
// 'data'
watch(() => props.visible, () => {
},
{ immediate: true }
);
//
const handleNewCard = (newCard: cardDatass) => {
cardData.value.push(newCard);
};
onMounted(() => {
for(let i = 0;i<9;i++){
cardData.value.push({
id: i,
name: '卡片' + i,
imageUrl: ''
});
}
});
</script>
<template>
<cardadd v-model:visible="drawerRefadd" :keyval="props.visible" @data="handleNewCard"/>
<cardedit v-model:visible="drawerRefedit" :keyval="props.visible" @data="handleNewCard"/>
<el-row :gutter="10">
<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
<div class="grid-content ep-bg-purple" >
<el-card class="cardlarge">
<template #header>
<div class="cardhead-large">
<el-row class="block-col-2">
<el-col style="text-align: right;">
<el-dropdown>
<span class="el-dropdown-link">
<el-icon><MoreFilled /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="opencardadd" >添加</el-dropdown-item>
<el-dropdown-item >编辑</el-dropdown-item>
<el-dropdown-item >删除</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
<el-col style="text-align: left;">
<span>标题一</span>
</el-col>
</el-row>
</div>
</template>
<div class="grid-content ep-bg-purple" >
<el-row :gutter="10" >
<el-col v-for="(card, index) in cardData" :key="card.id" :xs="8" :sm="12" :md="8" :lg="8" :xl="8">
<el-card class="cardpattern">
<img
v-if="card.imageUrl"
src="card.imageUrl"
title="示例图片"
class="picture"
/>
<div class="cardhead">
<span>{{ card.name }}</span>
</div>
<div class="bottom">
<el-button size="small" circle class="button" :icon="View"></el-button>
<el-button size="small" circle class="button" :icon="Edit" @click="() => opencardedit(index)"></el-button>
<el-button size="small" circle class="button" :icon="Delete" @click="() => deleteCard(index)"></el-button>
</div>
</el-card>
</el-col>
</el-row>
</div>
</el-card>
</div>
</el-col>
</el-row>
<!-- 分页 -->
<div class="example-pagination-block">
<div class="example-demonstration"></div>
<el-pagination layout="prev, pager, next" :total="50" />
</div>
</template>
<style scoped>
/* 小卡片 */
.cardpattern{
padding-bottom: 0px;
margin-bottom: 10px;
min-width: 100px;
}
/* 小卡片标题 */
.cardhead{
padding: 10px;
font-size: 15px;
}
/* 大卡片 */
.cardlarge{
max-width: 480px;
}
/* 大卡片标题 */
.cardhead-large{
font-size: 20px;
}
/* 按钮整体 */
.bottom {
margin-top: 20px;
line-height: 10px;
display: flex;
justify-content: space-evenly;
align-items: center;
}
/* 单个按钮 */
.button {
padding: 0px;
min-height: auto;
margin-bottom: 1px;
}
/* 图片 */
.picture {
height: 100%;
min-height: 50px;
max-height: 100px;
display: block;
width: 100%;
min-width: 50px;
}
.el-col {
border-radius: 4px;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.app_box{
margin: 15px 0 0 0px;
}
.block-col-2 .demonstration {
display: block;
color: var(--el-text-color-secondary);
font-size: 14px;
margin-bottom: 20px;
}
.block-col-2 .el-dropdown-link {
display: flex;
align-items: center;
}
/* 分页 */
.example-pagination-block + .example-pagination-block {
margin-top: 10px;
}
.example-pagination-block .example-demonstration {
margin-bottom: 16px;
}
</style>

38
src/views/sysworkflow/lowcodepage/appFormList.vue

@ -12,6 +12,7 @@ import { json2string,objToStringify,string2json,stringToObj } from '@/utils/Desi
import LowCodeFormPage from "@/views/sysworkflow/lowcodepage/lowCodeFormPage.vue"
import TaskCustomerForm from '@/views/taskplatform/taskmanagement/taskcustomerformnew.vue'
import TableFlow from '@/views/sysworkflow/lowcodepage/pageFlow/tableFlow.vue'
import DesignAPPpage from "@/views/sysworkflow/lowcodepage/appPage/index.vue" //
const props = defineProps({
groupId:{
@ -132,6 +133,17 @@ const refreshPage = (pageType:string) =>{
onMounted(()=>{
getFormAppList()
})
/**
@ 作者: 秦东
@ 时间: 2024-04-24 08:21:32
@ 功能: 关闭应用刷新页面
*/
const closeAppPage = () =>{
console.log("关闭应用刷新页面")
getFormAppList()
}
/**
@ 作者: 秦东
@ 时间: 2024-04-01 14:32:18
@ -201,6 +213,18 @@ const state = reactive({
dict: {},
refreshTable: true
})
const appPageShow = ref(false)
const appKey = ref<string>("")
/**
@ 作者: 秦东
@ 时间: 2024-04-23 15:30:17
@ 功能: 编辑app内容
*/
const editAppCont = (val:string) => {
appKey.value = val.toString();
appPageShow.value = true;
}
</script>
<template>
<div>
@ -224,7 +248,18 @@ const state = reactive({
<div class="cardhead">
<el-text class="w-150px mb-2" truncated :title="item.name" @click.top="startUsing(item.versionId,item.name)">{{item.name}}</el-text>
</div>
<el-row>
<el-row v-if="item.classify==3">
<el-col :span="8" class="but_centent">
<el-button size="small" circle class="button" :icon="View" @click="lookFormList(item)"></el-button>
</el-col>
<el-col :span="8" class="but_centent">
<el-button size="small" circle class="button" :icon="Edit" @click="editAppCont(item.signCodeStr)"></el-button>
</el-col>
<el-col :span="8" class="but_centent">
<el-button size="small" circle class="button" :icon="Delete" @click="delFormApp(item.idStr)"></el-button>
</el-col>
</el-row>
<el-row v-else>
<el-col :span="8" class="but_centent">
<el-button size="small" circle class="button" :icon="View" @click="lookFormList(item)"></el-button>
</el-col>
@ -246,6 +281,7 @@ const state = reactive({
<LowCodeFormPage v-if="addFormIsShow" :drawer-with="props.drawerWith" v-model:form-key="formId" @refreshPage="refreshPage" />
<DesignAPPpage v-model:is-show="appPageShow" v-model:form-key="appKey" :drawer-with="props.drawerWith" @refreshPage="closeAppPage" />
<el-drawer
v-model="lookPageIsShow"

165
src/views/sysworkflow/lowcodepage/appPage/appMenuGroup.vue

@ -0,0 +1,165 @@
<!--
@ 作者: 秦东
@ 时间: 2024-04-23 16:56:36
@ 备注: 菜单分组
-->
<script lang='ts' setup>
import { appMenuTreeInfo } from "@/api/date/type"
import { ginOthenMenuTree,saveAppMenu } from '@/api/DesignForm/requestapi'
const props = defineProps({
appCont:{
type:Object,
default(){
return {}
}
},
menuParentKey:{
type:String,
default:""
},
isShow:{
type: Boolean,
default: false,
},
menuType:{
type:Number,
default:1
}
});
const emits = defineEmits(["update:isShow","updateMenu"]);
watch(()=>props.isShow,(val:boolean)=>{
if(val){
console.log("props.appCont",props.appCont)
console.log("props.menuParentKey",props.menuParentKey)
getOldMenuTree()
}
})
const loading = ref(false)
const saveMenuGroup = ref(ElForm);
const menuOldTree = ref<appMenuTreeInfo[]>([])
const menuGroupInfo = reactive({
name:"",
group:""
})
const ssd = ref()
/**
@ 作者: 秦东
@ 时间: 2024-04-24 08:50:40
@ 功能: 关闭
*/
const handleClose = () => {
loading.value = false;
emits("updateMenu")
emits("update:isShow",false)
resetForm()
}
/**
@ 作者: 秦东
@ 时间: 2024-04-24 09:09:24
@ 功能: 获取已有菜单树
*/
const getOldMenuTree = () => {
ginOthenMenuTree({id:props.appCont.uuid})
.then((data) =>{
console.log("获取已有菜单树",data)
if(data.code == 0){
menuOldTree.value = data.data
}
});
}
/**
@ 作者: 秦东
@ 时间: 2024-04-24 09:29:59
@ 功能: 表单验证规则
*/
const rules = reactive({
name: [{ required: true, message: "请输入分组名称", trigger: "blur" }],
});
/**
@ 作者: 秦东
@ 时间: 2024-04-24 09:33:56
@ 功能: 重置表单
*/
const resetForm = () => {
saveMenuGroup.value.resetFields();
saveMenuGroup.value.clearValidate();
menuGroupInfo.name = undefined;
menuGroupInfo.group = "";
}
/**
@ 作者: 秦东
@ 时间: 2024-04-24 09:35:12
@ 功能: 写入菜单分组
*/
const saveMenuData = () => {
console.log("写入菜单分组",menuGroupInfo)
loading.value = true;
saveMenuGroup.value.validate((valid: any) => {
if (valid) {
let groupId = menuGroupInfo.group
if(menuGroupInfo.group == "") {
groupId = props.appCont.uuid
}
let sendCont = {
name:menuGroupInfo.name,
appkey:props.appCont.uuid,
type:props.menuType,
group:groupId
}
console.log("写入菜单分组",sendCont)
saveAppMenu(sendCont)
.then((data) =>{
handleClose()
})
.finally(() =>{
loading.value = false;
})
}else{
loading.value = false;
}
})
}
</script>
<template>
<el-dialog
v-model="props.isShow"
title="新建分组"
width="500"
:before-close="handleClose"
>
<el-form
ref="saveMenuGroup"
:model="menuGroupInfo"
:rules="rules"
label-width="120px"
>
<el-form-item label="分组名称" prop="name">
<el-input v-model="menuGroupInfo.name" clearable placeholder="请输入分组名称" />
</el-form-item>
<el-form-item label="选择上级分组">
<el-tree-select
v-model="menuGroupInfo.group"
:data="menuOldTree"
check-strictly
:render-after-expand="false"
show-checkbox
node-key="id"
value-key="id"
check-on-click-node
clearable
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" v-loading="loading" :disabled="loading" @click="saveMenuData">确定</el-button>
</div>
</template>
</el-dialog>
</template>
<style lang='scss' scoped>
</style>

155
src/views/sysworkflow/lowcodepage/appPage/appMenus.vue

@ -0,0 +1,155 @@
<!--
@ 作者: 秦东
@ 时间: 2024-04-22 08:56:40
@ 备注:
-->
<script lang='ts' setup>
import type {
AllowDropType,
NodeDropType,
} from 'element-plus/es/components/tree/src/tree.type'
import SvgIcon from "@/components/SvgIcon/index.vue";
import { threeShiyanData } from "@/api/date/type"
import AppMenuSvgPage from "@/components/IconSelect/appMenuSvgPage.vue";
const props = defineProps({
formKey:{
type:String,
default:""
},
menusTree:{
type:Object,
default(){
return {}
}
}
});
const svgIsShow = ref(false)
/**
@ 作者: 秦东
@ 时间: 2024-04-22 10:06:20
@ 功能: 树移动完毕后执行的操作
*/
const handleDrop = (
draggingNode: Node,
dropNode: Node,
dropType: NodeDropType,
ev: DragEvents
) => {
console.log('draggingNode:', draggingNode)
console.log('dropNode:', dropNode)
console.log('dropType:', dropType)
console.log('ev:', ev)
}
const treeList = ref<any[]>([])
/**
@ 作者: 秦东
@ 时间: 2024-04-22 15:53:35
@ 功能: 加载SVG图标
*/
const allIconNames:string[] = [];
const loadIcons = () => {
const icons = import.meta.glob("../../../../assets/icons/*.svg");
for (const icon in icons) {
const iconName = icon.split("assets/icons/")[1].split(".svg")[0];
allIconNames.push(iconName);
}
// console.log("icons",icons)
// console.log("allIconNames",allIconNames)
}
onMounted(()=>{
treeList.value = threeShiyanData
loadIcons();
})
/**
@ 作者: 秦东
@ 时间: 2024-04-22 16:52:03
@ 功能: 设置表单图标
*/
const svgName = ref("")
const svgId= ref("")
const setAppMenusSvg = (val:any) =>{
svgName.value = val.svg
svgId.value = val.id
svgIsShow.value = true;
}
watch(()=>svgName.value,(val:string)=>{
console.log("监听----svgName--->",val)
console.log("监听----threeShiyanData--->",threeShiyanData)
diguiData(treeList.value)
})
/**
@ 作者: 秦东
@ 时间: 2024-04-23 09:44:14
@ 功能: 递归判断是哪个节点换了图标
*/
const diguiData = (val:any) =>{
if(Array.isArray(val)){
try {
val.forEach((item:any) => {
if(item.id == svgId.value){
item.svg = svgName.value
throw item;
}
if(item.children&&Array.isArray(item.children)){
diguiData(item.children)
}
});
} catch (e) {
console.log('跳出循环:', threeShiyanData);
}
}
}
</script>
<template>
<el-tree
:data="props.menusTree"
draggable
default-expand-all
node-key="id"
:expand-on-click-node="false"
@node-drop="handleDrop"
>
<template #default="{ node, data }">
<div class="appMenuTitle">
<el-space wrap>
<svg-icon prefix="icon" :icon-class="data.svg" @click="setAppMenusSvg(data)" />
<el-text>{{node.label}}</el-text>
</el-space>
<el-dropdown>
<svg-icon class="svgBox" prefix="icon" icon-class="set" />
<template #dropdown>
<el-dropdown-item>修改名称</el-dropdown-item>
<el-dropdown-item>复制</el-dropdown-item>
<el-dropdown-item>移动到</el-dropdown-item>
<el-dropdown-item divided>新建子分组</el-dropdown-item>
<el-dropdown-item>新建普通表单</el-dropdown-item>
<el-dropdown-item>新建流程表单</el-dropdown-item>
<el-dropdown-item divided>隐藏PC端</el-dropdown-item>
<el-dropdown-item>隐藏移动端</el-dropdown-item>
<el-dropdown-item divided><el-text class="mx-1" type="danger">删除</el-text></el-dropdown-item>
</template>
</el-dropdown>
</div>
</template>
</el-tree>
<AppMenuSvgPage v-model:is-show="svgIsShow" v-model:svg-name="svgName" :icon-list="allIconNames" />
</template>
<style lang='scss' scoped>
.appMenuTitle{
width: 100%;
padding-right: 5px;
display: flex;
align-items: center;
justify-content: space-between;
.svgBox{
display: none;
}
}
.appMenuTitle:hover .svgBox{
display: block;
}
</style>

299
src/views/sysworkflow/lowcodepage/appPage/index.vue

@ -4,6 +4,14 @@
@ 备注: 设置自建应用
-->
<script lang='ts' setup>
import { appMenuTreeInfo,appSetInfo } from "@/api/date/type"
import { gainAppEditPsge } from '@/api/DesignForm/requestapi'
import { Search } from '@element-plus/icons-vue'
import SvgIcon from "@/components/SvgIcon/index.vue";
import AppMenus from "@/views/sysworkflow/lowcodepage/appPage/appMenus.vue"
import AppMenuGroup from "@/views/sysworkflow/lowcodepage/appPage/appMenuGroup.vue"
const props = defineProps({
drawerWith:{
type:Number,
@ -12,19 +20,230 @@ const props = defineProps({
formKey:{
type:String,
default:""
},
isShow:{
type: Boolean,
default: false,
}
});
const drawerOpenOrClose = ref(true)
const emits = defineEmits(["update:isShow","update:svgName","refreshPage"]);
const squareUrl = 'https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png'
const drawerOpenOrClose = ref(false)
const tabsActive = ref("1")
const menusTree = ref<appMenuTreeInfo[]>([])
const appCont = reactive<appSetInfo>({
appKey:"1",
appName:"未知应用",
appSvg:"",
state:1,
uuid:"1"
})
const menuParentKey = ref<string>("")
const menuGroupShow = ref(false) //
/**
@ 作者: 秦东
@ 时间: 2024-04-19 15:47:12
@ 功能: 选择选项
*/
const handleClick = () =>{}
/**
@ 作者: 秦东
@ 时间: 2024-04-23 09:56:19
@ 功能: 关闭
*/
const closeAppDraw = () =>{
emits("update:isShow",false)
emits("refreshPage")
}
onMounted(() =>{
// gainAppContent()
})
watch(()=>props.isShow,(val:boolean)=>{
if(val){
gainAppContent()
}
})
/**
@ 作者: 秦东
@ 时间: 2024-04-23 15:23:31
@ 功能: 获取app信息
*/
const gainAppContent = () =>{
let sendInfo = {
id:props.formKey.toString()
}
gainAppEditPsge(sendInfo)
.then((data)=>{
console.log("获取app信息---》",data)
menusTree.value = data.data.menuTree
appCont.appKey = data.data.appKey;
appCont.appName = data.data.appName;
appCont.appSvg = data.data.appSvg;
appCont.state = data.data.state;
appCont.uuid = data.data.uuid;
})
}
/**
@ 作者: 秦东
@ 时间: 2024-04-23 16:57:39
@ 功能: 添加菜单分组
*/
const addMenu = (key?:string) => {
if(key){
menuParentKey.value = key;
}else{
menuParentKey.value = "";
}
menuGroupShow.value = true;
}
</script>
<template>
<div class="drawerClass">
<el-drawer v-model="drawerOpenOrClose" title="设置/编辑自定义表单" :with-header="false" :close-on-click-modal="false" :close-on-press-escape="false" :destroy-on-close="true" :size="props.drawerWith">
<AppMenuGroup v-model:is-show="menuGroupShow" :menu-parent-key="menuParentKey" :app-cont="appCont" @updateMenu="gainAppContent" />
<el-drawer v-model="props.isShow" title="设置/编辑自定义表单" :with-header="false" :close-on-click-modal="false" :close-on-press-escape="false" :destroy-on-close="true" :size="props.drawerWith">
<div class="common-layout">
<el-container>
<el-header>Header</el-header>
<el-header class="headerBox">
<div>
<el-space wrap>
<el-avatar shape="square" :size="25" :src="appCont.appSvg" />
<el-text>{{ appCont.appName }}</el-text>
<el-tag v-if="appCont.state==1" type="success">已启用</el-tag>
<el-tag v-else type="danger">已禁用</el-tag>
</el-space>
</div>
<div>
<el-tabs v-model="tabsActive" @tab-click="handleClick" :stretch="true" class="tabsMain">
<el-tab-pane label="① 页面管理" :name="1">
</el-tab-pane>
<el-tab-pane label="② 集成&自动化" :name="2">
</el-tab-pane>
<el-tab-pane label="③ 应用设置" :name="3">
</el-tab-pane>
<el-tab-pane label="④ 应用发布" :name="4">
</el-tab-pane>
</el-tabs>
</div>
<div>
<el-button plain size="small">访问</el-button>
<el-button type="danger" size="small" @click="closeAppDraw">关闭</el-button>
</div>
</el-header>
<el-container>
<el-aside width="200px">Aside</el-aside>
<el-main>Main</el-main>
<el-aside class="asideBox">
<el-row>
<el-col :span="24" class="asideBoxSearch">
<el-input
v-model="input2"
style="width: 180px"
placeholder="搜索"
:suffix-icon="Search"
/>
<el-dropdown>
<el-button type="primary" class="fa fa-plus" />
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item >
<el-row>
<el-col :span="24">
<el-space wrap>
<svg-icon style="color: #79bbff;" prefix="icon" icon-class="puTongBiaoDan" />
新建普通表单
</el-space>
</el-col>
<el-col :span="24" style="padding-left:20px; font-size:12px;">
数据收集事件记录
</el-col>
</el-row>
</el-dropdown-item>
<el-dropdown-item >
<el-row>
<el-col :span="24">
<el-space wrap>
<svg-icon style="color: #eebe77;" prefix="icon" icon-class="liuChengBiaoDan" />
新建流程表单
</el-space>
</el-col>
<el-col :span="24" style="padding-left:20px; font-size:12px;">
任务协同业务审批
</el-col>
</el-row>
</el-dropdown-item>
<el-dropdown-item divided @click="addMenu">
<el-row>
<el-col :span="24">
<el-space wrap>
<svg-icon style="color: #337ecc;" prefix="icon" icon-class="fenZhu" />
新建分组
</el-space>
</el-col>
<el-col :span="24" style="padding-left:20px; font-size:12px;">
应用项目管理
</el-col>
</el-row>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
</el-row>
<el-scrollbar class="scroBox">
<!-- <el-menu
default-active="1"
@open="handleOpen"
@close="handleClose"
>
<el-menu-item index="1" class="menuBox">
<div class="textCenter">
<el-space wrap>
<svg-icon prefix="icon" icon-class="daiWoCuLi" />
待我处理
</el-space>
</div>
<div>2</div>
</el-menu-item>
<el-menu-item index="2" class="menuBox">
<div class="textCenter">
<el-space wrap>
<svg-icon prefix="icon" icon-class="woYiChuLi" />
我已处理
</el-space>
</div>
<div>2</div>
</el-menu-item>
<el-menu-item index="3" class="menuBox">
<div class="textCenter">
<el-space wrap>
<svg-icon prefix="icon" icon-class="chaoSongWoDe" />
抄送我的
</el-space>
</div>
<div>2</div>
</el-menu-item>
<el-menu-item index="4" class="menuBox">
<div class="textCenter">
<el-space wrap>
<svg-icon prefix="icon" icon-class="woChuangJianDe" />
我创建的
</el-space>
</div>
<div>2</div>
</el-menu-item>
</el-menu> -->
<AppMenus :form-Key="formKey" :menus-tree="menusTree" />
</el-scrollbar>
</el-aside>
<el-main class="mainBox">
<el-scrollbar class="scroBox">
<svg-icon icon-class="0213-lmp" />
</el-scrollbar>
</el-main>
</el-container>
</el-container>
</div>
@ -33,5 +252,75 @@ const drawerOpenOrClose = ref(true)
</div>
</template>
<style lang='scss' scoped>
.common-layout{
.el-header{
padding-left:10px;
padding-right:10px;
}
.headerBox{
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #F1F2F3;
:deep(.el-tabs__nav-wrap::after) {
position: static !important;
}
:deep(.el-tabs__header){
margin:0 0 1px 0;
}
}
.asideBox{
width:250px;
border-right: 1px solid #F1F2F3;
height: calc(100vh - 40px);
.asideBoxSearch{
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 10px;
}
.scroBox{
height: calc(100vh - 95px);
.el-menu{
border-right: 0px;
}
li{
padding-left:10px;
padding-right:10px;
}
.menuBox{
display: flex;
align-items: center;
justify-content: space-between;
.textCenter{
display: flex;
align-items: center;
}
}
.el-menu-item{
height:40px;
}
.el-menu-item.is-active {
color: var(--el-menu-active-color);
background-color: #e4e4e4e4;
}
.el-menu-item:hover{
background-color: #f1f1f1f1!important;
}
}
}
.el-main {
padding: 10px;
}
.mainBox{
background-color: #F1F2F3;
.scroBox{
height: calc(100vh - 60px);
}
}
}
</style>

18
src/views/sysworkflow/lowcodepage/index.vue

@ -5,7 +5,7 @@
-->
<script lang='ts' setup>
import { SearchForm,customerFormCont,customerFormConfig } from "@/api/DesignForm/type";
import { customerFormGroupList,editFormGroupState } from '@/api/DesignForm/requestapi'
import { customerFormGroupList,editFormGroupState,createApp,gainAppEditPsge } from '@/api/DesignForm/requestapi'
/**
@ -48,8 +48,22 @@ const handleCommand = (command: string,groupId: string) => {
drawerWith.value = contbody.value?.clientWidth
addFormIsShow.value = true;
}else if(command == "addFormApp"){
drawerWith.value = contbody.value?.clientWidth
let sendInfo = {
id:groupId.toString()
}
createApp(sendInfo)
.then((data)=>{
formKey.value = data.data.uuid
nextTick(() =>{
appPageShow.value = true
});
})
.finally(() => {
})
}else{
addFormGroupIsShow.value = true
drawerGroupWith.value = 400
@ -195,7 +209,7 @@ const getRongQiAttr = () => {
<el-pagination layout="prev, pager, next" v-model:current-page="page" :page-size="pageSize" :total="pageTotal" />
</div>
<DesignAPPpage v-if="appPageShow" :drawer-with="drawerWith" v-model:form-key="formKey" @refreshPage="refreshPage" />
<DesignAPPpage v-model:is-show="appPageShow" :drawer-with="drawerWith" v-model:form-key="formKey" @refreshPage="refreshPage" />
<LowCodeFormPage v-if="addFormIsShow" :drawer-with="drawerWith" v-model:form-key="formKey" :form-group-key="formGroupKey" @refreshPage="refreshPage" />
<LowCodeFormGroupPage v-if="addFormGroupIsShow" :drawer-with="drawerGroupWith" :group-key="groupKey" @refreshPage="refreshPage" />

5
src/views/sysworkflow/lowcodepage/workFlow.vue

@ -543,6 +543,7 @@ onMounted(()=>{
<template #icon>
流程可实现需要多人流转的业务场景<br>绘制流程图设定数据流转方式即可搭建线上工作流<br><br>
<el-image
class="imgBox"
:src="FlowImgSrc"
/>
</template>
@ -566,6 +567,10 @@ onMounted(()=>{
display: flex;
align-items: center;
justify-content: center;
.imgBox{
height: calc(100vh - 400px);
// height: 10%;
}
}
/* 去掉tabs标签栏下的下划线 */
::v-deep .el-tabs__nav-wrap::after {

79
src/widget/associatedforms/associatedFormsFillRole.vue

@ -0,0 +1,79 @@
<template>
<div style="margin-bottom: 15px; height: 40px; line-height: 40px;">
<el-tree-select
v-model="leftValue1" style="width: 290px;" :data="leftTreeSource"
check-strictly :render-after-expand="false" filterable @change="leftChanged" />
<span style="margin-left: 8px;margin-right: 8px;">的值填充到</span>
<el-tree-select
v-model="rightValue1" style="width: 290px;" :data="rightTreeSource"
check-strictly :render-after-expand="false" filterable @change="rightChanged" />
<Delete style="width: 22px; height: 22px; margin-right: 35px;cursor: pointer; color: #50A6FF;margin-top: 10px; display: block; float:right" @click="delRole" />
</div>
</template>
<script setup lang="ts">
const props = defineProps({
leftTreeSource: {
type: Object,
default() {
return {}
}
},
rightTreeSource: {
type: Object,
default() {
return {}
}
},
leftValue: {
type: String,
default() {
return {}
}
},
rightValue: {
type: String,
default() {
return {}
}
},
currentKey: {
type: String,
default() {
return {}
}
},
})
const leftValue1 = ref()
const rightValue1 = ref()
leftValue1.value = props.leftValue
rightValue1.value = props.rightValue
let emit = defineEmits(["update:leftValue", "update:rightValue","delRole"]);
function leftChanged(){
emit('update:leftValue',leftValue1)
}
function rightChanged(){
emit('update:rightValue',rightValue1)
}
function delRole(){
//alert(props.currentKey)
emit('delRole',props.currentKey)
}
</script>
<style></style>

107
src/widget/associatedforms/associatedFormsTinyace.vue

@ -0,0 +1,107 @@
<script lang='ts' setup>
import { ref, onMounted } from "vue";
import tinymce from "tinymce/tinymce";
import "tinymce/models/dom"; // tinymce 6.0.0
import "tinymce/themes/silver/theme";
import Editor from "@tinymce/tinymce-vue"; //
import { v4 as uuidv4 } from "uuid";
let onlyNumber = uuidv4().replaceAll('-','').toString(); //
/**
* 初始富文本组件
*/
const tinymceInit = {
selector: "#"+onlyNumber,
language_url: "/tinymce/langs/zh-Hans.js", // public
language: "zh-Hans", // zh-Hans.js
skin_url: "/tinymce/skins/ui/oxide", //
height: 260, //
statusbar:false,
toolbar:false,
branding: false, //Powered by TinyMCE
menubar: false, //
forced_root_block:'',
newline_behavior:"",
content_css: "/tinymce/skins/content/default/content.css", //csscsscss
auto_focus : true,
}
const props = defineProps({
aftText:{
type: String,
default(){
return {}
}
},
aftTextCopy:{
type: String,
default(){
return {}
}
},
})
let $emit = defineEmits(["textChange"]);
const tinymceHtml = ref("")
tinymceHtml.value = props.aftText
onMounted(() => {
tinymce.init({}); //
});
watch(()=>tinymceHtml.value, (val:any) => {
$emit('textChange',val);
},
{ deep: true }
)
const addIcon = (currentObject:any) =>{
tinymce.activeEditor?.execCommand('mceInsertContent', false, `<span style="margin:3px;background-color: #4189EF;border-radius: 5px; padding:3px" contenteditable="false" data-keyid= "${currentObject.id}" >${currentObject.label}</span>`);
}
const addIcon_field = (currentObject:any) =>{
tinymce.activeEditor?.execCommand('mceInsertContent', false, `<span style="margin:3px;background-color: #4189EF;border-radius: 5px; padding:3px" contenteditable="false" data-keyid= "${currentObject.id}" >${currentObject.treeAttrs.show}</span>`);
}
const addIcon_org = (currentObject:any) =>{
let id = "orgOrPerson:"+currentObject.id
tinymce.activeEditor?.execCommand('mceInsertContent', false, `<span style="margin:3px;background-color: #4189EF;border-radius: 5px; padding:3px" contenteditable="false" data-keyid= "${id}" >${currentObject.label}</span>`);
}
//
const handelCancel = (associatedFormsHideDialogTextCopy:any) =>{
tinymceHtml.value = associatedFormsHideDialogTextCopy
}
const tinymceReInit = ()=>{
let str:string = props.aftTextCopy
}
const focusEditor = ()=>{
tinymce.EditorManager.get(onlyNumber)?.focus(true)
}
defineExpose({
tinymceHtml,
addIcon,
addIcon_org,
addIcon_field,
handelCancel,
tinymceReInit,
focusEditor,
})
</script>
<template >
<div >
<editor :id="onlyNumber" v-model="tinymceHtml" :init="tinymceInit"></editor>
</div>
</template>
<style lang='scss' scoped>
</style>

108
src/widget/associatedforms/associatedFormsTinyaceRange.vue

@ -0,0 +1,108 @@
<script lang='ts' setup>
import { ref, onMounted } from "vue";
import tinymce from "tinymce/tinymce";
import "tinymce/models/dom"; // tinymce 6.0.0
import "tinymce/themes/silver/theme";
import Editor from "@tinymce/tinymce-vue"; //
import { v4 as uuidv4 } from "uuid";
let onlyNumber = uuidv4().replaceAll('-','').toString(); //
/**
* 初始富文本组件
*/
const tinymceInit = {
selector: "#"+onlyNumber,
language_url: "/tinymce/langs/zh-Hans.js", // public
language: "zh-Hans", // zh-Hans.js
skin_url: "/tinymce/skins/ui/oxide", //
height: 260, //
statusbar:false,
toolbar:false,
branding: false, //Powered by TinyMCE
menubar: false, //
forced_root_block:'',
newline_behavior:"",
content_css: "/tinymce/skins/content/default/content.css", //csscsscss
auto_focus : true,
}
const props = defineProps({
aftText:{
type: String,
default(){
return {}
}
},
aftTextCopy:{
type: String,
default(){
return {}
}
},
})
let $emit = defineEmits(["textChange"]);
const tinymceHtml = ref("")
tinymceHtml.value = props.aftText
onMounted(() => {
tinymce.init({}); //
});
watch(()=>tinymceHtml.value, (val:any) => {
$emit('textChange',val);
},
{ deep: true }
)
const addIcon = (currentObject:any) =>{
tinymce.activeEditor?.execCommand('mceInsertContent', false, `<span style="margin:3px;background-color: #4189EF;border-radius: 5px; padding:3px" contenteditable="false" data-keyid= "${currentObject.id}" >${currentObject.label}</span>`);
}
const addIcon_field = (currentObject:any) =>{
tinymce.activeEditor?.execCommand('mceInsertContent', false, `<span style="margin:3px;background-color: #4189EF;border-radius: 5px; padding:3px" contenteditable="false" data-keyid= "${currentObject.id}" >${currentObject.treeAttrs.show}</span>`);
}
const addIcon_org = (currentObject:any) =>{
let id = "orgOrPerson:"+currentObject.id
tinymce.activeEditor?.execCommand('mceInsertContent', false, `<span style="margin:3px;background-color: #4189EF;border-radius: 5px; padding:3px" contenteditable="false" data-keyid= "${id}" >${currentObject.label}</span>`);
}
//
const handelCancel = (associatedFormsHideDialogTextCopy:any) =>{
tinymceHtml.value = associatedFormsHideDialogTextCopy
}
const tinymceReInit = ()=>{
let str:string = props.aftTextCopy
}
const focusEditor = ()=>{
tinymce.EditorManager.get(onlyNumber)?.focus(true)
}
defineExpose({
tinymceHtml,
addIcon,
addIcon_org,
addIcon_field,
handelCancel,
tinymceReInit,
focusEditor,
})
</script>
<template >
<div >
<editor :id="onlyNumber" v-model="tinymceHtml" :init="tinymceInit"></editor>
</div>
</template>
<style lang='scss' scoped>
</style>
Loading…
Cancel
Save