Browse Source

定义发送企业微信消息

qin_v18
herenshan112 8 months ago
parent
commit
ffb446db60
  1. 4
      package.json
  2. 19
      src/api/displayboardapi/indexapi.ts
  3. 16
      src/api/displayboardapi/types.ts
  4. 561
      src/assets/public/iconfont.css
  5. BIN
      src/assets/public/iconfont.ttf
  6. BIN
      src/assets/public/iconfont.woff
  7. BIN
      src/assets/public/iconfont.woff2
  8. 561
      src/assets/public/iconfontCss/iconfont.css
  9. BIN
      src/assets/public/iconfontCss/iconfont.ttf
  10. BIN
      src/assets/public/iconfontCss/iconfont.woff
  11. BIN
      src/assets/public/iconfontCss/iconfont.woff2
  12. 562
      src/assets/public/print-lock.css
  13. 7
      src/components/DesignForm/aceDrawer.vue
  14. 147
      src/components/DesignForm/aceDrawerPage.vue
  15. 4
      src/components/DesignForm/public/expand/pickpost.vue
  16. 6
      src/components/DesignForm/public/expand/pickrole.vue
  17. 641
      src/components/DesignForm/public/expand/userDialog.vue
  18. 1
      src/components/DesignForm/public/form/formItem.vue
  19. 6
      src/main.ts
  20. 143
      src/store/ruler/index.ts
  21. 214
      src/views/process/canvas-bg/CanvasBg.vue
  22. 98
      src/views/process/canvas-bg/drawRuler.ts
  23. 75
      src/views/process/customProvider.js
  24. 200
      src/views/process/print/canvas-bg/CanvasBg.vue
  25. 148
      src/views/process/print/canvas-bg/CanvasSlider.vue
  26. 193
      src/views/process/print/canvas-bg/CanvasThumbnail.vue
  27. 41
      src/views/process/print/canvas-bg/data/keyCode.ts
  28. 98
      src/views/process/print/canvas-bg/drawRuler.ts
  29. 14
      src/views/process/state.vue
  30. 30
      src/views/process/state2.vue
  31. 39
      src/views/sysworkflow/lowcodepage/appPage/appPageForm/pageConfig.ts
  32. 662
      src/views/sysworkflow/lowcodepage/appPage/appPageForm/pageList.vue
  33. 136
      src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage.vue
  34. 13
      src/views/sysworkflow/lowcodepage/appPage/createAppFormPage.vue
  35. 3353
      src/views/sysworkflow/lowcodepage/pageList.vue

4
package.json

@ -79,9 +79,13 @@
"uuid": "^9.0.1",
"vue": "^3.3.1",
"vue-baidu-map-3x": "^1.0.35",
"vue-demi": "^0.14.10",
"vue-i18n": "9.2.2",
"vue-plugin-hiprint": "^0.0.59-beta4",
"vue-router": "^4.2.0",
"vue3-dnd": "^2.1.0",
"vue3-ruler-tool": "^0.0.1",
"vue3-sketch-ruler": "^2.2.9",
"vuedraggable": "^4.1.0",
"vuedraggable-es": "^4.1.1",
"websocket": "^1.0.35"

19
src/api/displayboardapi/indexapi.ts

@ -126,7 +126,7 @@ export const targetListForDepartment = (data?: targetCanShu):any => {
}
//获取审批节点或条件节点
export const gainNodeFactor = (data?: any) => {
export const gainNodeFactor = (data?: any) => {
return request({
url: '/systemapi/task_flow/gain_node_factor',
method: 'post',
@ -182,3 +182,20 @@ export const hotNews = (data: attributePage):any => {
data: data
})
}
//获取行政组织几人员相关控件信息
export const gainOrgOfPeopleNodeFactor = (data?: any) => {
return request({
url: '/systemapi/task_flow/gainOrgOfPeopleNodeFactor',
method: 'post',
data: data
})
}
//获取行政组织几人员关系
export const gainOegAndPeople = (data?: any) => {
return request({
url: '/systemapi/user/gainOegAndPeople',
method: 'post',
data: data
})
}

16
src/api/displayboardapi/types.ts

@ -150,3 +150,19 @@ export interface setupPage {
export interface attributePage extends setupPage{
type?:number
}
//发送范围结构体
export interface sendTableFields {
fields:string;
lable:string;
multipleChoice:boolean;
types:string;
}
//获取行政组织几人员关系结构体
export interface sendCustFields {
id: string;
number: string;
name: string;
icon:string;
isPick: boolean;
types: string;
}

561
src/assets/public/iconfont.css

@ -0,0 +1,561 @@
@font-face {
font-family: "iconfont"; /* Project id 3559670 */
src: url("iconfont.woff2?t=1667531544868") format("woff2"),
url("iconfont.woff?t=1667531544868") format("woff"),
url("iconfont.ttf?t=1667531544868") format("truetype");
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.sv-edit-data:before {
content: "\e655";
}
.sv-shimmer:before {
content: "\e6d6";
}
.sv-origin:before {
content: "\e6ac";
}
.sv-zIndex:before {
content: "\e603";
}
.sv-structure:before {
content: "\ec6f";
}
.sv-list:before {
content: "\e742";
}
.sv-grid:before {
content: "\e849";
}
.sv-flow:before {
content: "\e611";
}
.sv-switch:before {
content: "\e6f6";
}
.sv-theme:before {
content: "\e644";
}
.sv-element:before {
content: "\e615";
}
.sv-pdf:before {
content: "\e67a";
}
.sv-browser:before {
content: "\e726";
}
.sv-font-big:before {
content: "\eb04";
}
.sv-font-small:before {
content: "\eb05";
}
.sv-font-bold:before {
content: "\ec83";
}
.sv-font-tiny:before {
content: "\e6c1";
}
.sv-options:before {
content: "\e607";
}
.sv-close:before {
content: "\e646";
}
.sv-clone:before {
content: "\ec7a";
}
.sv-cut:before {
content: "\e643";
}
.sv-preview:before {
content: "\e61c";
}
.sv-zoom-in:before {
content: "\e60f";
}
.sv-zoom-out:before {
content: "\e610";
}
.sv-edit:before {
content: "\e6b9";
}
.sv-paste:before {
content: "\e6c0";
}
.sv-copy:before {
content: "\e6c2";
}
.sv-unlock:before {
content: "\e6e7";
}
.sv-lock:before {
content: "\e6e8";
}
.sv-zIndex-plus:before {
content: "\e715";
}
.sv-zIndex-minus:before {
content: "\e716";
}
.sv-zIndex-top:before {
content: "\e71f";
}
.sv-sigh:before {
content: "\e724";
}
.sv-ask:before {
content: "\e725";
}
.sv-dev-code:before {
content: "\e733";
}
.sv-bug:before {
content: "\e73f";
}
.sv-zIndex-bottom:before {
content: "\e71d";
}
.sv-new:before {
content: "\e64d";
}
.sv-clear:before {
content: "\e62d";
}
.sv-base:before {
content: "\e7d0";
}
.sv-export:before {
content: "\eabf";
}
.sv-import:before {
content: "\eac0";
}
.sv-add:before {
content: "\eaf3";
}
.sv-printer:before {
content: "\eabe";
}
.sv-save:before {
content: "\eabd";
}
.sv-more:before {
content: "\e625";
}
.sv-menu:before {
content: "\e628";
}
.sv-nav-right:before {
content: "\e629";
}
.sv-nav-up:before {
content: "\e62a";
}
.sv-nav-left:before {
content: "\e62b";
}
.sv-nav-down:before {
content: "\e62c";
}
.sv-setting:before {
content: "\e62e";
}
.sv-delete:before {
content: "\e630";
}
.sv-undo:before {
content: "\e631";
}
.sv-redo:before {
content: "\e632";
}
.sv-refresh:before {
content: "\e634";
}
.sv-history:before {
content: "\e635";
}
.sv-html:before {
content: "\e633";
}
.sv-longText:before {
content: "\e64c";
}
.sv-table:before {
content: "\ec15";
}
.sv-qrcode:before {
content: "\e642";
}
.sv-image:before {
content: "\e8ba";
}
.sv-barcode:before {
content: "\eb64";
}
.sv-text:before {
content: "\e60b";
}
.sv-vline:before {
content: "\e63a";
}
.sv-oval:before {
content: "\eb99";
}
.sv-rect:before {
content: "\e620";
}
.sv-hline:before {
content: "\e60a";
}
.sv-print-c:before {
content: "\e602";
}
.sv-print:before {
content: "\e601";
}
.sv-c:before {
content: "\e600";
}
.sv-vertical:before {
content: "\e706";
}
.sv-distributeHor:before {
content: "\e707";
}
.sv-right:before {
content: "\e708";
}
.sv-left:before {
content: "\e709";
}
.sv-distributeVer:before {
content: "\e70f";
}
.sv-bottom:before {
content: "\e710";
}
.sv-top:before {
content: "\e711";
}
.sv-horizontal:before {
content: "\e712";
}
.sv-rotate:before {
content: "\e66f";
}
.sv-butongbu:before {
content: "\e636";
}
.sv-synchronization:before {
content: "\e676";
}
/* 重写全局 hiprint 样式 */
.hiprint-headerLine,
.hiprint-footerLine {
border-color: purple !important;
}
.hiprint-headerLine:hover,
.hiprint-footerLine:hover {
border-top: 3px dashed purple !important;
}
.hiprint-headerLine:hover:before {
content: "页眉线";
left: calc(50% - 18px);
position: relative;
background: #ffff;
top: -14px;
color: purple;
font-size: 12px;
}
.hiprint-footerLine:hover:before {
content: "页脚线";
left: calc(50% - 18px);
position: relative;
color: purple;
background: #ffff;
top: -14px;
font-size: 12px;
}
/* 区域 */
.left {
background: white;
border-radius: 4px;
border: 1px solid #d9d9d9;
padding: 10px 0;
box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
overflow: auto;
}
.center {
margin: 0 10px;
background: white;
border-radius: 4px;
border: 1px solid #d9d9d9;
padding: 20px;
box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
overflow: auto;
}
.right {
background: white;
border-radius: 4px;
border: 1px solid #d9d9d9;
padding: 10px 0;
box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
overflow: auto;
}
/* 左侧拖拽元素样式 */
.title {
font-size: 16px;
font-weight: 500;
width: 100%;
margin: 10px 0 0 24px;
}
.item {
display: flex;
flex-direction: column;
align-items: center;
background: white;
padding: 4px 10px;
margin: 10px 8px 4px 8px;
width: 38%;
min-height: 60px;
border-radius: 4px;
box-shadow: 2px 2px 2px 2px rgba(171, 171, 171, 0.2);
}
.item .iconfont {
font-size: 1.5rem;
}
.item span {
font-size: 14px;
}
/* scrollbar */
::-webkit-scrollbar {
height: 4px;
width: 4px;
}
::-webkit-scrollbar-corner {
height: 4px;
width: 4px;
}
::-webkit-scrollbar-thumb {
background: purple;
border-radius: 2px;
background-image: -webkit-linear-gradient(
45deg,
rgba(255, 255, 255, 0.2) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.2) 50%,
rgba(255, 255, 255, 0.2) 75%,
transparent 75%,
transparent
);
}
::-webkit-scrollbar-thumb:hover {
background: purple;
}
/* flex */
.flex-row {
display: flex;
}
.flex-col {
display: flex;
flex-direction: column;
}
.flex-wrap {
flex-wrap: wrap;
}
.align-center {
align-items: center;
}
.justify-center {
justify-content: center;
}
.flex-1 {
flex: 1;
}
.flex-2 {
flex: 2;
}
.flex-3 {
flex: 3;
}
.flex-4 {
flex: 4;
}
.flex-5 {
flex: 5;
}
.ml-10 {
margin-left: 10px;
}
.mr-10 {
margin-right: 10px;
}
.mt-10 {
margin-top: 10px;
}
.mb-10 {
margin-bottom: 10px;
}
button:hover {
opacity: 1;
}
button i {
font-size: 16px !important;
}
.circle,
.circle-4 {
border-radius: 4px !important;
}
.circle-10 {
border-radius: 10px !important;
}
/* modal */
.modal {
padding: 0;
margin: 0;
}
.modal .mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
height: 100%;
background-color: #00000073;
}
.modal .wrap {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
overflow: auto;
background-color: #00000073;
outline: 0;
}
.modal .wrap .box {
position: relative;
margin: 10% auto;
width: 40%;
background: #fff;
border-radius: 4px;
z-index: 1001;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
}
.modal-box__header {
padding: 10px 14px;
border-bottom: 1px solid #e9e9e9;
}
.modal-box__footer {
text-align: end;
}
.modal-box__footer button {
min-width: 100px;
}
.modal-box__footer button:not(:last-child) {
margin-right: 10px;
}

BIN
src/assets/public/iconfont.ttf

Binary file not shown.

BIN
src/assets/public/iconfont.woff

Binary file not shown.

BIN
src/assets/public/iconfont.woff2

Binary file not shown.

561
src/assets/public/iconfontCss/iconfont.css

@ -0,0 +1,561 @@
@font-face {
font-family: "iconfont"; /* Project id 3559670 */
src: url("iconfont.woff2?t=1667531544868") format("woff2"),
url("iconfont.woff?t=1667531544868") format("woff"),
url("iconfont.ttf?t=1667531544868") format("truetype");
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.sv-edit-data:before {
content: "\e655";
}
.sv-shimmer:before {
content: "\e6d6";
}
.sv-origin:before {
content: "\e6ac";
}
.sv-zIndex:before {
content: "\e603";
}
.sv-structure:before {
content: "\ec6f";
}
.sv-list:before {
content: "\e742";
}
.sv-grid:before {
content: "\e849";
}
.sv-flow:before {
content: "\e611";
}
.sv-switch:before {
content: "\e6f6";
}
.sv-theme:before {
content: "\e644";
}
.sv-element:before {
content: "\e615";
}
.sv-pdf:before {
content: "\e67a";
}
.sv-browser:before {
content: "\e726";
}
.sv-font-big:before {
content: "\eb04";
}
.sv-font-small:before {
content: "\eb05";
}
.sv-font-bold:before {
content: "\ec83";
}
.sv-font-tiny:before {
content: "\e6c1";
}
.sv-options:before {
content: "\e607";
}
.sv-close:before {
content: "\e646";
}
.sv-clone:before {
content: "\ec7a";
}
.sv-cut:before {
content: "\e643";
}
.sv-preview:before {
content: "\e61c";
}
.sv-zoom-in:before {
content: "\e60f";
}
.sv-zoom-out:before {
content: "\e610";
}
.sv-edit:before {
content: "\e6b9";
}
.sv-paste:before {
content: "\e6c0";
}
.sv-copy:before {
content: "\e6c2";
}
.sv-unlock:before {
content: "\e6e7";
}
.sv-lock:before {
content: "\e6e8";
}
.sv-zIndex-plus:before {
content: "\e715";
}
.sv-zIndex-minus:before {
content: "\e716";
}
.sv-zIndex-top:before {
content: "\e71f";
}
.sv-sigh:before {
content: "\e724";
}
.sv-ask:before {
content: "\e725";
}
.sv-dev-code:before {
content: "\e733";
}
.sv-bug:before {
content: "\e73f";
}
.sv-zIndex-bottom:before {
content: "\e71d";
}
.sv-new:before {
content: "\e64d";
}
.sv-clear:before {
content: "\e62d";
}
.sv-base:before {
content: "\e7d0";
}
.sv-export:before {
content: "\eabf";
}
.sv-import:before {
content: "\eac0";
}
.sv-add:before {
content: "\eaf3";
}
.sv-printer:before {
content: "\eabe";
}
.sv-save:before {
content: "\eabd";
}
.sv-more:before {
content: "\e625";
}
.sv-menu:before {
content: "\e628";
}
.sv-nav-right:before {
content: "\e629";
}
.sv-nav-up:before {
content: "\e62a";
}
.sv-nav-left:before {
content: "\e62b";
}
.sv-nav-down:before {
content: "\e62c";
}
.sv-setting:before {
content: "\e62e";
}
.sv-delete:before {
content: "\e630";
}
.sv-undo:before {
content: "\e631";
}
.sv-redo:before {
content: "\e632";
}
.sv-refresh:before {
content: "\e634";
}
.sv-history:before {
content: "\e635";
}
.sv-html:before {
content: "\e633";
}
.sv-longText:before {
content: "\e64c";
}
.sv-table:before {
content: "\ec15";
}
.sv-qrcode:before {
content: "\e642";
}
.sv-image:before {
content: "\e8ba";
}
.sv-barcode:before {
content: "\eb64";
}
.sv-text:before {
content: "\e60b";
}
.sv-vline:before {
content: "\e63a";
}
.sv-oval:before {
content: "\eb99";
}
.sv-rect:before {
content: "\e620";
}
.sv-hline:before {
content: "\e60a";
}
.sv-print-c:before {
content: "\e602";
}
.sv-print:before {
content: "\e601";
}
.sv-c:before {
content: "\e600";
}
.sv-vertical:before {
content: "\e706";
}
.sv-distributeHor:before {
content: "\e707";
}
.sv-right:before {
content: "\e708";
}
.sv-left:before {
content: "\e709";
}
.sv-distributeVer:before {
content: "\e70f";
}
.sv-bottom:before {
content: "\e710";
}
.sv-top:before {
content: "\e711";
}
.sv-horizontal:before {
content: "\e712";
}
.sv-rotate:before {
content: "\e66f";
}
.sv-butongbu:before {
content: "\e636";
}
.sv-synchronization:before {
content: "\e676";
}
/* 重写全局 hiprint 样式 */
.hiprint-headerLine,
.hiprint-footerLine {
border-color: purple !important;
}
.hiprint-headerLine:hover,
.hiprint-footerLine:hover {
border-top: 3px dashed purple !important;
}
.hiprint-headerLine:hover:before {
content: "页眉线";
left: calc(50% - 18px);
position: relative;
background: #ffff;
top: -14px;
color: purple;
font-size: 12px;
}
.hiprint-footerLine:hover:before {
content: "页脚线";
left: calc(50% - 18px);
position: relative;
color: purple;
background: #ffff;
top: -14px;
font-size: 12px;
}
/* 区域 */
.left {
background: white;
border-radius: 4px;
border: 1px solid #d9d9d9;
padding: 10px 0;
box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
overflow: auto;
}
.center {
margin: 0 10px;
background: white;
border-radius: 4px;
border: 1px solid #d9d9d9;
padding: 20px;
box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
overflow: auto;
}
.right {
background: white;
border-radius: 4px;
border: 1px solid #d9d9d9;
padding: 10px 0;
box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
overflow: auto;
}
/* 左侧拖拽元素样式 */
.title {
font-size: 16px;
font-weight: 500;
width: 100%;
margin: 10px 0 0 24px;
}
.item {
display: flex;
flex-direction: column;
align-items: center;
background: white;
padding: 4px 10px;
margin: 10px 8px 4px 8px;
width: 38%;
min-height: 60px;
border-radius: 4px;
box-shadow: 2px 2px 2px 2px rgba(171, 171, 171, 0.2);
}
.item .iconfont {
font-size: 1.5rem;
}
.item span {
font-size: 14px;
}
/* scrollbar */
::-webkit-scrollbar {
height: 4px;
width: 4px;
}
::-webkit-scrollbar-corner {
height: 4px;
width: 4px;
}
::-webkit-scrollbar-thumb {
background: purple;
border-radius: 2px;
background-image: -webkit-linear-gradient(
45deg,
rgba(255, 255, 255, 0.2) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.2) 50%,
rgba(255, 255, 255, 0.2) 75%,
transparent 75%,
transparent
);
}
::-webkit-scrollbar-thumb:hover {
background: purple;
}
/* flex */
.flex-row {
display: flex;
}
.flex-col {
display: flex;
flex-direction: column;
}
.flex-wrap {
flex-wrap: wrap;
}
.align-center {
align-items: center;
}
.justify-center {
justify-content: center;
}
.flex-1 {
flex: 1;
}
.flex-2 {
flex: 2;
}
.flex-3 {
flex: 3;
}
.flex-4 {
flex: 4;
}
.flex-5 {
flex: 5;
}
.ml-10 {
margin-left: 10px;
}
.mr-10 {
margin-right: 10px;
}
.mt-10 {
margin-top: 10px;
}
.mb-10 {
margin-bottom: 10px;
}
button:hover {
opacity: 1;
}
button i {
font-size: 16px !important;
}
.circle,
.circle-4 {
border-radius: 4px !important;
}
.circle-10 {
border-radius: 10px !important;
}
/* modal */
.modal {
padding: 0;
margin: 0;
}
.modal .mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
height: 100%;
background-color: #00000073;
}
.modal .wrap {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
overflow: auto;
background-color: #00000073;
outline: 0;
}
.modal .wrap .box {
position: relative;
margin: 10% auto;
width: 40%;
background: #fff;
border-radius: 4px;
z-index: 1001;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
}
.modal-box__header {
padding: 10px 14px;
border-bottom: 1px solid #e9e9e9;
}
.modal-box__footer {
text-align: end;
}
.modal-box__footer button {
min-width: 100px;
}
.modal-box__footer button:not(:last-child) {
margin-right: 10px;
}

BIN
src/assets/public/iconfontCss/iconfont.ttf

Binary file not shown.

BIN
src/assets/public/iconfontCss/iconfont.woff

Binary file not shown.

BIN
src/assets/public/iconfontCss/iconfont.woff2

Binary file not shown.

562
src/assets/public/print-lock.css

@ -0,0 +1,562 @@
@font-face {
font-family: "iconfont"; /* Project id 3559670 */
src: url("iconfont.woff2?t=1667531544868") format("woff2"),
url("iconfont.woff?t=1667531544868") format("woff"),
url("iconfont.ttf?t=1667531544868") format("truetype");
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.sv-edit-data:before {
content: "\e655";
}
.sv-shimmer:before {
content: "\e6d6";
}
.sv-origin:before {
content: "\e6ac";
}
.sv-zIndex:before {
content: "\e603";
}
.sv-structure:before {
content: "\ec6f";
}
.sv-list:before {
content: "\e742";
}
.sv-grid:before {
content: "\e849";
}
.sv-flow:before {
content: "\e611";
}
.sv-switch:before {
content: "\e6f6";
}
.sv-theme:before {
content: "\e644";
}
.sv-element:before {
content: "\e615";
}
.sv-pdf:before {
content: "\e67a";
}
.sv-browser:before {
content: "\e726";
}
.sv-font-big:before {
content: "\eb04";
}
.sv-font-small:before {
content: "\eb05";
}
.sv-font-bold:before {
content: "\ec83";
}
.sv-font-tiny:before {
content: "\e6c1";
}
.sv-options:before {
content: "\e607";
}
.sv-close:before {
content: "\e646";
}
.sv-clone:before {
content: "\ec7a";
}
.sv-cut:before {
content: "\e643";
}
.sv-preview:before {
content: "\e61c";
}
.sv-zoom-in:before {
content: "\e60f";
}
.sv-zoom-out:before {
content: "\e610";
}
.sv-edit:before {
content: "\e6b9";
}
.sv-paste:before {
content: "\e6c0";
}
.sv-copy:before {
content: "\e6c2";
}
.sv-unlock:before {
content: "\e6e7";
}
.sv-lock:before {
content: "\e6e8";
}
.sv-zIndex-plus:before {
content: "\e715";
}
.sv-zIndex-minus:before {
content: "\e716";
}
.sv-zIndex-top:before {
content: "\e71f";
}
.sv-sigh:before {
content: "\e724";
}
.sv-ask:before {
content: "\e725";
}
.sv-dev-code:before {
content: "\e733";
}
.sv-bug:before {
content: "\e73f";
}
.sv-zIndex-bottom:before {
content: "\e71d";
}
.sv-new:before {
content: "\e64d";
}
.sv-clear:before {
content: "\e62d";
}
.sv-base:before {
content: "\e7d0";
}
.sv-export:before {
content: "\eabf";
}
.sv-import:before {
content: "\eac0";
}
.sv-add:before {
content: "\eaf3";
}
.sv-printer:before {
content: "\eabe";
}
.sv-save:before {
content: "\eabd";
}
.sv-more:before {
content: "\e625";
}
.sv-menu:before {
content: "\e628";
}
.sv-nav-right:before {
content: "\e629";
}
.sv-nav-up:before {
content: "\e62a";
}
.sv-nav-left:before {
content: "\e62b";
}
.sv-nav-down:before {
content: "\e62c";
}
.sv-setting:before {
content: "\e62e";
}
.sv-delete:before {
content: "\e630";
}
.sv-undo:before {
content: "\e631";
}
.sv-redo:before {
content: "\e632";
}
.sv-refresh:before {
content: "\e634";
}
.sv-history:before {
content: "\e635";
}
.sv-html:before {
content: "\e633";
}
.sv-longText:before {
content: "\e64c";
}
.sv-table:before {
content: "\ec15";
}
.sv-qrcode:before {
content: "\e642";
}
.sv-image:before {
content: "\e8ba";
}
.sv-barcode:before {
content: "\eb64";
}
.sv-text:before {
content: "\e60b";
}
.sv-vline:before {
content: "\e63a";
}
.sv-oval:before {
content: "\eb99";
}
.sv-rect:before {
content: "\e620";
}
.sv-hline:before {
content: "\e60a";
}
.sv-print-c:before {
content: "\e602";
}
.sv-print:before {
content: "\e601";
}
.sv-c:before {
content: "\e600";
}
.sv-vertical:before {
content: "\e706";
}
.sv-distributeHor:before {
content: "\e707";
}
.sv-right:before {
content: "\e708";
}
.sv-left:before {
content: "\e709";
}
.sv-distributeVer:before {
content: "\e70f";
}
.sv-bottom:before {
content: "\e710";
}
.sv-top:before {
content: "\e711";
}
.sv-horizontal:before {
content: "\e712";
}
.sv-rotate:before {
content: "\e66f";
}
.sv-butongbu:before {
content: "\e636";
}
.sv-synchronization:before {
content: "\e676";
}
/* 重写全局 hiprint 样式 */
.hiprint-headerLine,
.hiprint-footerLine {
border-color: purple !important;
}
.hiprint-headerLine:hover,
.hiprint-footerLine:hover {
border-top: 3px dashed purple !important;
}
.hiprint-headerLine:hover:before {
content: "页眉线";
left: calc(50% - 18px);
position: relative;
background: #ffff;
top: -14px;
color: purple;
font-size: 12px;
}
.hiprint-footerLine:hover:before {
content: "页脚线";
left: calc(50% - 18px);
position: relative;
color: purple;
background: #ffff;
top: -14px;
font-size: 12px;
}
/* 区域 */
.left {
background: white;
border-radius: 4px;
border: 1px solid #d9d9d9;
padding: 10px 0;
box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
overflow: auto;
}
.center {
margin: 0 10px;
background: white;
border-radius: 4px;
border: 1px solid #d9d9d9;
padding: 20px;
box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
overflow: auto;
}
.right {
background: white;
border-radius: 4px;
border: 1px solid #d9d9d9;
padding: 10px 0;
box-shadow: 2px 2px 2px 0px rgb(128 0 128 / 20%);
overflow: auto;
}
/* 左侧拖拽元素样式 */
.title {
font-size: 16px;
font-weight: 500;
width: 100%;
margin: 10px 0 0 24px;
}
.item {
display: flex;
flex-direction: column;
align-items: center;
background: white;
padding: 4px 10px;
margin: 10px 8px 4px 8px;
width: 38%;
min-height: 60px;
border-radius: 4px;
box-shadow: 2px 2px 2px 2px rgba(171, 171, 171, 0.2);
}
.item .iconfont {
font-size: 1.5rem;
}
.item span {
font-size: 14px;
}
/* scrollbar */
::-webkit-scrollbar {
height: 4px;
width: 4px;
}
::-webkit-scrollbar-corner {
height: 4px;
width: 4px;
}
::-webkit-scrollbar-thumb {
background: purple;
border-radius: 2px;
background-image: -webkit-linear-gradient(
45deg,
rgba(255, 255, 255, 0.2) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.2) 50%,
rgba(255, 255, 255, 0.2) 75%,
transparent 75%,
transparent
);
}
::-webkit-scrollbar-thumb:hover {
background: purple;
}
/* flex */
.flex-row {
display: flex;
}
.flex-col {
display: flex;
flex-direction: column;
}
.flex-wrap {
flex-wrap: wrap;
}
.align-center {
align-items: center;
}
.justify-center {
justify-content: center;
}
.flex-1 {
flex: 1;
}
.flex-2 {
flex: 2;
}
.flex-3 {
flex: 3;
}
.flex-4 {
flex: 4;
}
.flex-5 {
flex: 5;
}
.ml-10 {
margin-left: 10px;
}
.mr-10 {
margin-right: 10px;
}
.mt-10 {
margin-top: 10px;
}
.mb-10 {
margin-bottom: 10px;
}
button:hover {
opacity: 1;
}
button i {
font-size: 16px !important;
}
.circle,
.circle-4 {
border-radius: 4px !important;
}
.circle-10 {
border-radius: 10px !important;
}
/* modal */
.modal {
padding: 0;
margin: 0;
}
.modal .mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
height: 100%;
background-color: #00000073;
}
.modal .wrap {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
overflow: auto;
background-color: #00000073;
outline: 0;
}
.modal .wrap .box {
position: relative;
margin: 10% auto;
width: 40%;
background: #fff;
border-radius: 4px;
z-index: 1001;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
}
.modal-box__header {
padding: 10px 14px;
border-bottom: 1px solid #e9e9e9;
}
.modal-box__footer {
text-align: end;
}
.modal-box__footer button {
min-width: 100px;
}
.modal-box__footer button:not(:last-child) {
margin-right: 10px;
}

7
src/components/DesignForm/aceDrawer.vue

@ -19,7 +19,6 @@ const props = withDefaults(
id?: string;
// eslint-disable-next-line vue/require-default-prop
codeType?: string;
data?: object;
}>(),
{
id: "editJson",
@ -85,7 +84,7 @@ const jiShuDiGui = (val: []) => {
watch(
() => visible,
(val: booble) => {
jiShuDiGui(props.data.content);
jiShuDiGui(props.data?.content);
},
{ deep: true }
);
@ -113,7 +112,9 @@ const drawerBeforeClose = () => {
emits("beforeClose");
treeSelectAry.value = [];
};
onMounted(() => {});
onMounted(() => {
console.log("预览视图--------------------------------》", props.data);
});
onUnmounted(() => {
if (Object.keys(editor.value).length !== 0) {
editor.value.destroy();

147
src/components/DesignForm/aceDrawerPage.vue

@ -3,90 +3,89 @@
@ 时间: 2023-07-19 08:39:34
@ 备注: 抽屉
-->
<script lang='ts' setup>
import { ref, nextTick, watch, onMounted, onUnmounted } from 'vue'
import { aceEdit } from '@/api/DesignForm/utils'
<script lang="ts" setup>
import { ref, nextTick, watch, onMounted, onUnmounted } from "vue";
import { aceEdit } from "@/api/DesignForm/utils";
const props = withDefaults(
defineProps<{
data?:object
modelValue: boolean
// eslint-disable-next-line vue/require-default-prop
title?: string
direction?: 'rtl' | 'ltr'
content: string
id?: string
// eslint-disable-next-line vue/require-default-prop
codeType?: string
}>(),
{
id: 'editJson',
content: '',
direction: 'ltr'
}
)
const emits = defineEmits<{
(e: 'beforeClose'): void
(e: 'confirm', content: string): void
(e: 'update:modelValue', val: boolean): void
}>()
const editor = ref<any>({})
const visible = ref(false)
defineProps<{
data?: object;
modelValue: boolean;
// eslint-disable-next-line vue/require-default-prop
title?: string;
direction?: "rtl" | "ltr";
content: string;
id?: string;
// eslint-disable-next-line vue/require-default-prop
codeType?: string;
}>(),
{
id: "editJson",
content: "",
direction: "ltr",
}
);
const emits = defineEmits<{
(e: "beforeClose"): void;
(e: "confirm", content: string): void;
(e: "update:modelValue", val: boolean): void;
}>();
const editor = ref<any>({});
const visible = ref(false);
watch(
() => props.modelValue,
(val: boolean) => {
visible.value = val
if (val) {
initEditor()
}
() => props.modelValue,
(val: boolean) => {
visible.value = val;
if (val) {
initEditor();
}
)
}
);
const initEditor = () => {
nextTick(() => {
editor.value = aceEdit(props.content, props.id, props.codeType)
})
}
nextTick(() => {
editor.value = aceEdit(props.content, props.id, props.codeType);
});
};
const dialogConfirm = () => {
const editVal = editor.value.getValue()
emits('confirm', editVal)
}
const editVal = editor.value.getValue();
emits("confirm", editVal);
};
const drawerBeforeClose = () => {
emits('update:modelValue', false)
emits('beforeClose')
}
onMounted(() => {})
emits("update:modelValue", false);
emits("beforeClose");
};
onMounted(() => {});
onUnmounted(() => {
if (Object.keys(editor.value).length !== 0) {
editor.value.destroy()
editor.value.container.remove()
}
})
if (Object.keys(editor.value).length !== 0) {
editor.value.destroy();
editor.value.container.remove();
}
});
</script>
<template>
<el-drawer
v-model="visible"
size="60%"
:title="title"
:direction="direction as any"
class="ace-dialog"
:append-to-body="true"
:before-close="drawerBeforeClose"
>
<template #header>
<div v-html="title"></div>
</template>
<div>{{props.data}}</div>
<div v-if="visible" :id="id"></div>
<div class="dialog-footer">
<el-button type="primary" size="small" @click="dialogConfirm">
确定
</el-button>
</div>
</el-drawer>
<el-drawer
v-model="visible"
size="60%"
:title="title"
:direction="direction as any"
class="ace-dialog"
:append-to-body="true"
:before-close="drawerBeforeClose"
>
<template #header>
<div v-html="title"></div>
</template>
<div>{{ props.data }}</div>
<div v-if="visible" :id="id"></div>
<div class="dialog-footer">
<el-button type="primary" size="small" @click="dialogConfirm"> 确定 </el-button>
</div>
</el-drawer>
</template>
<style lang='scss' scoped>
#editJson, #editJsonCopy {
width: 100%;
height: calc(100vh - 90px);
<style lang="scss" scoped>
#editJson,
#editJsonCopy {
width: 100%;
height: calc(100vh - 90px);
}
</style>

4
src/components/DesignForm/public/expand/pickpost.vue

@ -4,11 +4,9 @@
@ 备注: 岗位选择
-->
<script lang="ts" setup>
import { basis_org_postList } from "@/api/hr/org/index";
import { basis_org_postList,getgovcont, getpositioncont,getOrgTreeList } from "@/api/hr/org/index";
import { orgInfo } from "@/api/hr/org/type";
import { getOrgTreeList } from "@/api/hr/org/index";
import { getgovcont, getpositioncont } from "@/api/hr/org/index";
const props = withDefaults(
defineProps<{

6
src/components/DesignForm/public/expand/pickrole.vue

@ -18,7 +18,11 @@ const emits = defineEmits<{
}>();
const value = computed({
get: () => {
return props.modelValue * 1;
if (props.modelValue == "") {
return props.modelValue;
} else {
return props.modelValue * 1;
}
},
set: (newVal: any) => {
emits("update:modelValue", newVal);

641
src/components/DesignForm/public/expand/userDialog.vue

@ -3,361 +3,380 @@
@ 时间: 2023-08-21 14:41:41
@ 备注: 选择用户
-->
<script lang='ts' setup>
import { ref, onMounted, reactive, nextTick } from 'vue'
import { getRequest } from '@/api/DesignForm'
import formatResult from '@/utils/DesignForm/formatResult'
import { getOrgFormTree,getOrgFormUserList,searchUserCustomerFormList } from '@/api/hr/org/index'
import { orgform,criteriaForPeopleList } from '@/api/hr/org/type'
import UserRole from '@/assets/icons/user.svg'
<script lang="ts" setup>
import { ref, onMounted, reactive, nextTick } from "vue";
import { getRequest } from "@/api/DesignForm";
import formatResult from "@/utils/DesignForm/formatResult";
import {
getOrgFormTree,
getOrgFormUserList,
searchUserCustomerFormList,
} from "@/api/hr/org/index";
import { orgform, criteriaForPeopleList } from "@/api/hr/org/type";
import UserRole from "@/assets/icons/user.svg";
const props = withDefaults(
defineProps<{
modelValue?: string
}>(),
{}
)
defineProps<{
modelValue?: string;
}>(),
{}
);
const emits = defineEmits<{
(e: 'update:modelValue', value: string): void
}>()
const visible = ref(false)
(e: "update:modelValue", value: string): void;
}>();
const visible = ref(false);
//
const treeEl = ref()
const treeData = ref<orgform[]>([])
const department = ref(309)
const treeEl = ref();
const treeData = ref<orgform[]>([]);
const department = ref(309);
const handleNodeClick = (data: any) => {
department.value = data.id
getUserList()
}
department.value = data.id;
getUserList();
};
const getTreeData = () => {
// getRequest('deptList', {}).then((res: any) => {
// treeData.value = formatResult(res.data, 'transformDataToChild')
// })
getOrgFormTree({id:309})
.then(({ data }) => {
// console.log(data)
treeData.value = data.list
}).finally(()=>{})
}
// getRequest('deptList', {}).then((res: any) => {
// treeData.value = formatResult(res.data, 'transformDataToChild')
// })
getOrgFormTree({ id: 309 })
.then(({ data }) => {
// console.log(data)
treeData.value = data.list;
})
.finally(() => {});
};
//
const userName = ref()
const userName = ref();
const tableData = ref<criteriaForPeopleList[]>();
const page = reactive({
total: 0,
current: 1,
pageSize: 10
})
total: 0,
current: 1,
pageSize: 10,
});
const searchClick = () => {
getUserList()
}
getUserList();
};
const resetClick = () => {
userName.value = ''
department.value = ''
treeEl.value.setCurrentKey(null)
getUserList()
}
userName.value = "";
department.value = "";
treeEl.value.setCurrentKey(null);
getUserList();
};
const getUserList = () => {
const params = {
pageInfo: {
pageIndex: page.current,
pageSize: page.pageSize
},
name: userName.value,
department: department.value
}
// getRequest('userList', params).then((res: any) => {
// tableData.value = res.data.list
// })
// getOrgFormUserList
getOrgFormUserList(params)
.then(({ data })=>{
tableData.value = data.list
page.total = data.total
})
.finally(()=>{})
}
const params = {
pageInfo: {
pageIndex: page.current,
pageSize: page.pageSize,
},
name: userName.value,
department: department.value,
};
// getRequest('userList', params).then((res: any) => {
// tableData.value = res.data.list
// })
// getOrgFormUserList
getOrgFormUserList(params)
.then(({ data }) => {
tableData.value = data.list;
page.total = data.total;
})
.finally(() => {});
};
const currentChange = (current: number) => {
page.current = current
getUserList()
}
page.current = current;
getUserList();
};
// 
// const checkData = ref<any>([]);
const checkDataList = reactive<criteriaForPeopleList[]>([]);
const tableRowClick = (row: any) => {
if(checkDataList.length > 0){
let isIn = true
checkDataList.forEach(item =>{
if(item.id == row.id){
isIn = false
}
})
if(isIn){
checkDataList.push(row)
}
}else{
checkDataList.push(row)
}
// console.log("checkDataList",checkDataList,row)
}
if (checkDataList.length > 0) {
let isIn = true;
checkDataList.forEach((item) => {
if (item.id == row.id) {
isIn = false;
}
});
if (isIn) {
checkDataList.push(row);
}
} else {
checkDataList.push(row);
}
// console.log("checkDataList",checkDataList,row)
};
const delRowClick = (row: criteriaForPeopleList) => {
// console.log("checkDataList",row)
// checkData.value.forEach((item: any, index: number) => {
// if (item === row) {
// checkData.value.splice(index, 1)
// }
// })
if(checkDataList &&checkDataList.length > 0) {
checkDataList.forEach((item:criteriaForPeopleList,index:number) => {
if(item.id == row.id){
checkDataList.splice(index,1)
}
})
}
// console.log("checkDataList",row)
// checkData.value.forEach((item: any, index: number) => {
// if (item === row) {
// checkData.value.splice(index, 1)
// }
// })
if (checkDataList && checkDataList.length > 0) {
checkDataList.forEach((item: criteriaForPeopleList, index: number) => {
if (item.id == row.id) {
checkDataList.splice(index, 1);
}
});
}
// let checkDataAry = checkDataList
// if(checkDataAry.length > 0) {
// checkDataList.splice(0,checkDataList.length)
// console.log("checkDataList----1------>",checkDataAry,checkDataList)
// checkDataAry.forEach(item => {
// if(item.id != row.id){
// console.log("checkDataList---------->",item)
// checkDataList.push(item)
// }
// })
// }
}
// let checkDataAry = checkDataList
// if(checkDataAry.length > 0) {
// checkDataList.splice(0,checkDataList.length)
// console.log("checkDataList----1------>",checkDataAry,checkDataList)
// checkDataAry.forEach(item => {
// if(item.id != row.id){
// console.log("checkDataList---------->",item)
// checkDataList.push(item)
// }
// })
// }
};
const delAllClick = () => {
// checkData.value = []
checkDataList.splice(0,checkDataList.length)
}
// checkData.value = []
checkDataList.splice(0, checkDataList.length);
};
//
const open = () => {
visible.value = true
// console.log("open--->",props.modelValue)
if (props.modelValue) {
searchUserCustomerFormList({name:props.modelValue})
.then(({data})=>{
// console.log("",data)
// checkDataList = data
checkDataList.splice(0,checkDataList.length)
if(data.length > 0){
data.forEach((item:any) => {
checkDataList.push(item)
})
}
})
// checkData.value = props.modelValue.split(',')
// let jsonCont:criteriaForPeopleList[] = JSON.parse(props.modelValue)
// if(jsonCont.length > 0) {
// checkDataList.splice(0,checkDataList.length)
// jsonCont.forEach(item=>{
// checkDataList.push(item)
// })
// }
} else {
checkDataList.splice(0,checkDataList.length)
}
}
visible.value = true;
// console.log("open--->",props.modelValue)
if (props.modelValue) {
searchUserCustomerFormList({ name: props.modelValue }).then(({ data }) => {
// console.log("",data)
// checkDataList = data
checkDataList.splice(0, checkDataList.length);
if (data.length > 0) {
data.forEach((item: any) => {
checkDataList.push(item);
});
}
});
// checkData.value = props.modelValue.split(',')
// let jsonCont:criteriaForPeopleList[] = JSON.parse(props.modelValue)
// if(jsonCont.length > 0) {
// checkDataList.splice(0,checkDataList.length)
// jsonCont.forEach(item=>{
// checkDataList.push(item)
// })
// }
} else {
checkDataList.splice(0, checkDataList.length);
}
};
//
const confirmClick = () => {
// emits('update:modelValue', checkData.value.join(','))
let jsonStr = JSON.stringify(checkDataList)
emits('update:modelValue', jsonStr)
visible.value = false
}
defineExpose({ open })
// emits('update:modelValue', checkData.value.join(','))
let jsonStr = JSON.stringify(checkDataList);
emits("update:modelValue", jsonStr);
visible.value = false;
};
defineExpose({ open });
onMounted(() => {
nextTick(() => {
// loading
getTreeData()
getUserList()
})
})
nextTick(() => {
// loading
getTreeData();
getUserList();
});
});
const defaultProps ={
children: 'children',
label: 'name',
}
const defaultProps = {
children: "children",
label: "name",
};
</script>
<template>
<el-dialog
title="用户选择"
v-model="visible"
:append-to-body="true"
:props="defaultProps "
width="80%"
top="2vh"
draggable
>
<el-row :gutter="20">
<el-col :span="6" style="padding:0">
<div class="sidebar_tree">
<el-tree
ref="treeEl"
:data="treeData"
node-key="id"
@node-click="handleNodeClick"
:props="defaultProps "
highlight-current
/>
</div>
</el-col>
<el-col :span="12">
<div class="search">
<el-input placeholder="请输入用户名" v-model="userName" />
<el-button type="primary" @click="searchClick">查询</el-button>
<el-button @click="resetClick">重置</el-button>
</div>
<div class="list">
<el-table :data="tableData" style="width: 100%; height:710px">
<el-table-column prop="userName" label="照片" width="100px" align="center">
<template #default="scope">
<el-avatar v-if="scope.row.icon != ''" shape="square" :size="30" :src="scope.row.icon" />
<el-avatar v-else shape="square" :size="30" :src="UserRole" />
</template>
</el-table-column>
<el-table-column prop="name" label="姓名" width="120px" align="left">
<template #default="scope">
{{ scope.row.name }}({{ scope.row.number }})
</template>
</el-table-column>
<el-table-column prop="tel" label="联系方式" width="120px" align="left" />
<el-table-column prop="nickName" label="归属行政组织" align="left">
<template #default="{ row }">
{{ row.companyname }}<span v-if="row.maindeparmentname!=''"> / {{ row.maindeparmentname }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="60px">
<template #default="{ row }">
<el-button circle size="small" @click="tableRowClick(row)"><el-icon><ArrowRight /></el-icon></el-button>
</template>
</el-table-column>
</el-table>
<div class="page">
<el-pagination
background
layout="prev, pager, next, jumper"
small
hide-on-single-page
:current-page="page.current"
:total="page.total"
:page-size="page.pageSize"
@current-change="currentChange"
/>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="has_select">
<div class="total">
<div>已选择{{ checkDataList.length }}</div>
<el-button type="danger" @click="delAllClick" size="small">全部移除</el-button>
</div>
<el-table :data="checkDataList" style="height:710px">
<el-table-column prop="userName" label="照片" width="60px" align="center">
<template #default="scope">
<el-avatar v-if="scope.row.icon != ''" shape="square" :size="30" :src="scope.row.icon" />
<el-avatar v-else shape="square" :size="30" :src="UserRole" />
</template>
</el-table-column>
<el-table-column prop="name" label="姓名" align="left">
<template #default="scope">
{{ scope.row.name }}({{ scope.row.number }})
</template>
</el-table-column>
<el-table-column label="操作" width="60px">
<template #default="{ row }">
<el-button size="small" type="danger" @click="delRowClick(row)">移除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-col>
</el-row>
<template #footer>
<div>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="confirmClick"> 确定 </el-button>
</div>
</template>
<el-dialog
title="用户选择"
v-model="visible"
:append-to-body="true"
:props="defaultProps"
width="80%"
top="2vh"
draggable
>
<el-row :gutter="20">
<el-col :span="6" style="padding: 0">
<div class="sidebar_tree">
<el-tree
ref="treeEl"
:data="treeData"
node-key="id"
@node-click="handleNodeClick"
:props="defaultProps"
highlight-current
/>
</div>
</el-col>
<el-col :span="12">
<div class="search">
<el-input placeholder="请输入用户名" v-model="userName" />
<el-button type="primary" @click="searchClick">查询</el-button>
<el-button @click="resetClick">重置</el-button>
</div>
<div class="list">
<el-table :data="tableData" style="width: 100%; height: 710px">
<el-table-column prop="userName" label="照片" width="100px" align="center">
<template #default="scope">
<el-avatar
v-if="scope.row.icon != ''"
shape="square"
:size="30"
:src="scope.row.icon"
/>
<el-avatar v-else shape="square" :size="30" :src="UserRole" />
</template>
</el-table-column>
<el-table-column prop="name" label="姓名" width="120px" align="left">
<template #default="scope">
{{ scope.row.name }}({{ scope.row.number }})
</template>
</el-table-column>
<el-table-column prop="tel" label="联系方式" width="120px" align="left" />
<el-table-column prop="nickName" label="归属行政组织" align="left">
<template #default="{ row }">
{{ row.companyname
}}<span v-if="row.maindeparmentname != ''">
/ {{ row.maindeparmentname }}</span
>
</template>
</el-table-column>
<el-table-column label="操作" width="60px">
<template #default="{ row }">
<el-button circle size="small" @click="tableRowClick(row)"
><el-icon><ArrowRight /></el-icon
></el-button>
</template>
</el-table-column>
</el-table>
<div class="page">
<el-pagination
background
layout="prev, pager, next, jumper"
small
hide-on-single-page
:current-page="page.current"
:total="page.total"
:page-size="page.pageSize"
@current-change="currentChange"
/>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="has_select">
<div class="total">
<div>已选择{{ checkDataList.length }}</div>
<el-button type="danger" @click="delAllClick" size="small"
>全部移除</el-button
>
</div>
<el-table :data="checkDataList" style="height: 710px">
<el-table-column prop="userName" label="照片" width="60px" align="center">
<template #default="scope">
<el-avatar
v-if="scope.row.icon != ''"
shape="square"
:size="30"
:src="scope.row.icon"
/>
<el-avatar v-else shape="square" :size="30" :src="UserRole" />
</template>
</el-table-column>
<el-table-column prop="name" label="姓名" align="left">
<template #default="scope">
{{ scope.row.name }}({{ scope.row.number }})
</template>
</el-table-column>
<el-table-column label="操作" width="60px">
<template #default="{ row }">
<el-button size="small" type="danger" @click="delRowClick(row)"
>移除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</el-col>
</el-row>
<template #footer>
<div>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="confirmClick"> 确定 </el-button>
</div>
</template>
</el-dialog>
</template>
<style lang='scss' scoped>
<style lang="scss" scoped>
.sidebar_tree {
width: 100%;
border: 1px solid #ebeef5;
border-radius: 3px;
padding: 10px 0;
margin-right: 10px;
height: 750px;
overflow-y: auto;
width: 100%;
border: 1px solid #ebeef5;
border-radius: 3px;
padding: 10px 0;
margin-right: 10px;
height: 750px;
overflow-y: auto;
}
.has_select {
width: 100%;
width: 100%;
.total {
display: flex;
justify-content: space-between;
align-items: center;
height: 32px;
margin-bottom: 10px;
}
.total {
display: flex;
justify-content: space-between;
align-items: center;
height: 32px;
margin-bottom: 10px;
}
}
.search {
display: flex;
margin-bottom: 10px;
.el-input {
margin-right: 10px;
}
display: flex;
margin-bottom: 10px;
.el-input {
margin-right: 10px;
}
}
.page {
padding-top: 20px;
display: flex;
justify-content:space-between;
padding-top: 20px;
display: flex;
justify-content: space-between;
}
.expand-user-dialog {
display: flex;
align-items: flex-start;
.sidebar-tree {
width: 180px;
border: 1px solid #ebeef5;
border-radius: 3px;
padding: 10px 0;
margin-right: 10px;
max-height: 500px;
overflow-y: auto;
}
.table-list {
}
.search {
display: flex;
align-items: flex-start;
.sidebar-tree {
width: 180px;
border: 1px solid #ebeef5;
border-radius: 3px;
padding: 10px 0;
margin-right: 10px;
max-height: 500px;
overflow-y: auto;
}
.table-list {
margin-bottom: 10px;
.el-input {
margin-right: 10px;
}
.search {
display: flex;
margin-bottom: 10px;
.el-input {
margin-right: 10px;
}
}
.page {
padding-top: 20px;
display: flex;
justify-content: flex-end;
}
.has-select {
width: 200px;
margin-left: 20px;
.total {
display: flex;
justify-content: space-between;
align-items: center;
height: 32px;
margin-bottom: 10px;
}
}
.page {
padding-top: 20px;
display: flex;
justify-content: flex-end;
}
.has-select {
width: 200px;
margin-left: 20px;
.total {
display: flex;
justify-content: space-between;
align-items: center;
height: 32px;
margin-bottom: 10px;
}
}
}
</style>

1
src/components/DesignForm/public/form/formItem.vue

@ -1003,7 +1003,6 @@ const diGuiJilian = (val: any, options: any[]) => {
};
</script>
<template>
{{ data.type }}
<BaiduMap
v-if="judgeIsShow(data.name) && data.type === 'baidumap' && type != 4"
:data="data"

6
src/main.ts

@ -28,6 +28,10 @@ import ComWidget from '@/widget/index'
import AKDesign from '@/views/sysworkflow/codepage/index'
import * as pinia from './store/index'
import SketchRule from 'vue3-sketch-ruler'
import 'vue3-sketch-ruler/lib/style.css'
const app = createApp(App);
@ -39,7 +43,7 @@ import * as ElementPlusIconsVue from '@element-plus/icons-vue'
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.component('SketchRule', SketchRule)
app.directive('focus', {
mounted(el) {
el.focus();

143
src/store/ruler/index.ts

@ -0,0 +1,143 @@
import { defineStore } from "pinia";
import { store } from "@/store";
export const printPageConfigStore = defineStore("printPageConfigStore", () => {
const isMoveCanvas = ref(false);
const isThumbnail = ref(true);
const viewWidth = ref<number>(1000);
const viewHeight = ref<number>(800);
const scale = ref<number>(100); //缩放
const scrollTop = ref<number>(0);
const scrollLeft = ref<number>(0);
const screenWidth = ref<number>(1920);
const screenHeight = ref<number>(1080);
//bg
const backgroundColor = ref<string>('#FFFFFF');
const backgroundImage = ref<string>('');
const scaleSub = () => {
return scale.value
}
const percent = () => {
return scale.value * 0.01
}
const thumbnailSize = () => {
if(scale.value > 100){
return 10 / scale.value
}else{
return 0.1;
}
}
const viewWidthSub = () => {
return viewWidth.value;
}
const viewHeightSub = () => {
return viewHeight.value;
}
const scrollTopSub = () => {
return scrollTop.value;
}
const scrollLeftSub = () => {
return scrollLeft.value;
}
const screenWidthSub = () => {
return screenWidth.value;
}
const screenHeightSub = () => {
return screenHeight.value;
}
const showWidth = () => {
return screenWidthSub() * (scaleSub() < 100 ? 1 : percent()) + 400;
}
const showHeight = () => {
return screenHeightSub() * (scaleSub() < 100 ? 1 : percent()) + 400;
}
const isMoveCanvasSub = () => {
return isMoveCanvas.value;
}
const canvasConfig = () =>{
return {
thumbnailWidth: Math.ceil(screenWidthSub() * thumbnailSize() * percent()),
thumbnailHeight: Math.ceil(screenHeightSub() * thumbnailSize ()* percent()),
thumbnailWrapWidth: Math.ceil(showWidth()* thumbnailSize()),
thumbnailWrapHeight: Math.ceil(showHeight() * thumbnailSize())
}
}
const setViewBox = (data:{ width: number; height: number }) => {
viewWidth.value = data.width;
viewHeight.value = data.height;
}
const setScroll = ({ left, top }: { left: number; top: number }) => {
const distance = 60;
if (left < 0) {
left = 0;
} else if (left > showWidth() - viewWidthSub() - distance) {
left = showWidth() - viewWidthSub() - distance;
}
if (top < 0) {
top = 0;
} else if (top > showHeight() - viewHeightSub() - distance) {
top = showHeight() - viewHeightSub() - distance;
}
scrollLeft.value = Math.round(left);
scrollTop.value = Math.round(top);
}
const setMoveCanvas = (data: boolean) => {
isMoveCanvas.value = data
}
const setScale = (data: number) => {
scale.value = data;
}
const setThumbnail = (data: boolean) => {
isThumbnail.value = data;
}
return {
isMoveCanvas,
isThumbnail,
viewWidth,
viewHeight,
scale, //缩放
scrollTop,
scrollLeft,
screenWidth,
screenHeight,
//bg
backgroundColor,
backgroundImage,
scaleSub,
percent,
thumbnailSize,
viewWidthSub,
viewHeightSub,
scrollTopSub,
scrollLeftSub,
screenWidthSub,
screenHeightSub,
showWidth,
showHeight,
isMoveCanvasSub,
canvasConfig,
setViewBox,
setScroll,
setMoveCanvas,
setScale,
setThumbnail
};
});
export function useUserStoreHook() {
return printPageConfigStore(store);
}

214
src/views/process/canvas-bg/CanvasBg.vue

@ -0,0 +1,214 @@
<!--
@ 作者: 秦东
@ 时间: 2025-03-24 11:00:01
@ 备注: 画板背景
-->
<script lang="ts" setup>
import { drawRuler } from "./drawRuler.ts";
import { printPageConfigStore } from "@/store/ruler/index";
const editorStore = printPageConfigStore();
const topRulerRef = ref(null); //
const leftRulerRef = ref(null); //
const scrollLeft = ref(editorStore.scrollLeftSub() - 24);
const scrollTop = ref(editorStore.scrollLeftSub() - 24);
const isMoveCanvas = ref(editorStore.isMoveCanvasSub());
let moveInfo = {
startX: 0,
startY: 0,
};
const bgStyle = reactive({
width: editorStore.showWidth() + "px",
height: editorStore.showHeight() + "px",
});
const canvasStyle = reactive({
left: -scrollLeft.value + "px",
top: -scrollTop.value + "px",
width: editorStore.screenWidth + "px",
height: editorStore.screenHeight + "px",
transform: `scale(${editorStore.scale * 0.01})`,
});
const topStyle = reactive({
left: -scrollLeft.value + "px",
});
const leftStyle = reactive({
top: -scrollTop.value + "px",
});
let isRuler = false;
const refreshRuler = () => {
if (!isRuler) {
isRuler = true;
nextTick(() => {
drawRuler(
"top",
topRulerRef.value,
editorStore.scale,
editorStore.showWidth(),
24,
60
);
drawRuler(
"left",
leftRulerRef.value,
editorStore.scale,
editorStore.showHeight(),
24,
60
);
isRuler = false;
});
}
};
//
watch(
() => editorStore.screenWidth,
() => {
refreshRuler();
},
{
deep: true,
}
);
watch(
() => editorStore.screenHeight,
() => {
refreshRuler();
},
{
deep: true,
}
);
watch(
() => editorStore.scale,
(val: number) => {
console.log("标尺刻度值---111--》", val);
canvasStyle.scale = val * 0.01;
refreshRuler();
},
{
deep: true,
}
);
const onKeyAction = (e: KeyboardEvent) => {
if (e.keyCode == keyCode.space) {
editorStore.setMoveCanvas(!editorStore.isMoveCanvas);
}
};
const onWheelAction = (e: WheelEvent) => {
// console.log(editorStore.scale);
if (e.wheelDelta > 0) {
editorStore.setScale(editorStore.scale + 1);
} else {
editorStore.setScale(editorStore.scale - 1);
}
};
onMounted(() => {
// window.addEventListener("keydown", onKeyAction);
window.addEventListener("wheel", onWheelAction);
refreshRuler();
});
onBeforeUnmount(() => {
// window.removeEventListener("keydown", onKeyAction);
window.removeEventListener("wheel", onWheelAction);
});
const onMoveCanvasDown = (e: MouseEvent) => {
e.stopPropagation();
console.log("鼠标", editorStore.scale);
moveInfo = {
startX: e.clientX,
startY: e.clientY,
};
};
const onMoveCanvasUp = (e: MouseEvent) => {
e.stopPropagation();
let left = scrollLeft.value - (e.clientX - moveInfo.startX);
let top = scrollTop.value - (e.clientY - moveInfo.startY);
// console.log('move', left, top);
editorStore.setScroll({ left, top });
};
</script>
<template>
<div class="dashboard-canvas" id="dashboard">
<div class="canvas-bg" :style="bgStyle">
<div
:style="canvasStyle"
class="canvas-panel-wrap"
@mousedown="onMoveCanvasDown"
@mouseup="onMoveCanvasUp"
>
{{ canvasStyle }}
<slot></slot>
</div>
<canvas ref="topRulerRef" class="canvas-ruler top" :style="topStyle"></canvas>
<canvas ref="leftRulerRef" class="canvas-ruler left" :style="leftStyle"></canvas>
<i class="canvas-ruler-cross fa fa-eye"></i>
<div
class="canvas-move"
v-show="isMoveCanvas"
@mousedown="onMoveCanvasDown"
@mouseup="onMoveCanvasUp"
>
1212312312
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.dashboard-canvas {
top: 0px;
height: calc(100vh - 200px);
overflow: hidden;
position: relative;
left: 0px;
width: 100%;
}
.canvas-ruler-cross {
display: inline-block;
width: 24px;
height: 24px;
position: absolute;
background-color: var(--ruler-bg);
display: flex;
align-items: center;
justify-content: center;
}
.canvas-panel-wrap {
position: absolute;
box-shadow: var(--canvas-shadow) 0 0 30px 0;
transform-origin: left top;
margin-left: 20px;
margin-top: 20px;
background-color: #e4e4ed;
}
.canvas-move {
position: absolute;
height: 100%;
width: 100%;
background-color: var(--move-bg);
cursor: move;
}
.canvas-ruler {
position: absolute;
transform-origin: left top;
// cursor: ew-resize;
background-color: var(--ruler-bg);
&.left {
top: 24px;
left: 0px;
}
&.top {
top: 0px;
left: 24px;
}
}
</style>

98
src/views/process/canvas-bg/drawRuler.ts

@ -0,0 +1,98 @@
/**
* Canvas
* @param direction
* @param canvas canvas DOM
* @param scale [20-200]
* @param width
* @param height
* @param startLen
*/
export function drawRuler(
direction: string,
canvas: HTMLCanvasElement,
scale: number = 100,
width: number,
height: number = 24,
startLen: number = 60
) {
const padding = 2;
const ctx: CanvasRenderingContext2D = canvas.getContext('2d');
const percent = scale * 0.01;
let unit = Math.ceil(10 / percent);
if (unit < 8) {
unit = 8;
}
//计算出要绘制多少个刻度
const scaleCount = Math.ceil(width + startLen / unit);
if (direction == 'top') {
canvas.width = width + startLen;
canvas.height = height;
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
//绘制起点
ctx.strokeStyle = 'rgb(161, 174, 179)';
ctx.font = '10px Arial';
ctx.lineWidth = 0.5;
ctx.moveTo(startLen, 0);
ctx.lineTo(startLen, height);
ctx.fillText('0', startLen + padding, 13);
for (let i = 1; i <= scaleCount; i++) {
//计算每个刻度的位置
const step = startLen + Math.round(i * unit * percent);
//10的倍数刻度大长度
if (i % 10 === 0) {
ctx.moveTo(step, 0);
ctx.lineTo(step, height);
//标注刻度值
const scaleText = i * unit + '';
ctx.fillText(scaleText, step + padding, 13);
} else if (i % 5 === 0) {//5的倍数刻度中长度
ctx.moveTo(step, 15);
ctx.lineTo(step, height);
//标注刻度值
const scaleText = i * unit + '';
ctx.fillText(scaleText, step + padding, 13);
} else {//其他刻度小长度
ctx.moveTo(step, height - 2);
ctx.lineTo(step, height);
}
}
ctx.stroke();
} else {
canvas.width = height;
canvas.height = width + startLen;
ctx.clearRect(0, 0, height, width + startLen);
ctx.beginPath();
//绘制起点
ctx.strokeStyle = 'rgb(161, 174, 179)';
ctx.font = '10px Arial';
ctx.lineWidth = 0.5;
ctx.moveTo(0, startLen);
ctx.lineTo(height, startLen);
ctx.fillText('0', padding, startLen - padding);
//计算出要绘制多少个刻度
for (let i = 1; i <= scaleCount; i++) {
const step = startLen + Math.round(i * unit * percent);
if (i % 10 === 0) {
ctx.moveTo(0, step);
ctx.lineTo(height, step);
//标注刻度值
const scaleText = unit * i + '';
ctx.fillText(scaleText, padding, step - padding);
} else if (i % 5 === 0) {
ctx.moveTo(15, step);
ctx.lineTo(height, step);
//标注刻度值
const scaleText = unit * i + '';
ctx.fillText(scaleText, padding, step - padding);
} else {
ctx.moveTo(height - 2, step);
ctx.lineTo(height, step);
}
}
ctx.stroke();
}
}

75
src/views/process/customProvider.js

@ -0,0 +1,75 @@
import { hiprint } from "vue-plugin-hiprint";
export const iCustomProvider = function (options) {
console.log(options.moduleList.value);
var addElementTypes = function (context) {
context.removePrintElementTypes("providerModule1");
context.addPrintElementTypes("providerModule1", [
new hiprint.PrintElementTypeGroup("追溯业务", [
// options.config,
...options.moduleList.value.map(item => ({
tid: item.defaultModule,
title: item.title,
data: item.title,
type: item.type,
options: {
field: item.field,
height: 14,
testData: "默认",
fontSize: 12,
fontWeight: '500',
textAlign: 'center',
textContentVerticalAlign: 'middle',
...(item.textType ? { textType: item.textType } : {}),
},
})),
{
tid: "providerModule1.text",
title: "文本",
data: "文本",
type: "text",
options: {
field: "customText",
testData: "文本",
height: 14,
fontSize: 12,
fontWeight: "500",
textAlign: "left",
textContentVerticalAlign: "middle",
},
},
{
tid: "providerModule1.barcode",
title: "条形码",
data: "XS888888888",
type: "text",
options: {
field: "barcode",
testData: "XS888888888",
height: 32,
fontSize: 12,
lineHeight: 18,
textAlign: "left",
textType: "barcode",
},
},
{
tid: "providerModule1.qrcode",
title: "二维码",
data: "XS888888888",
type: "qrcode",
options: {
field: "qrcode",
testData: "XS888888888",
height: 32,
fontSize: 12,
lineHeight: 18,
textType: "qrcode",
},
},
]),
]);
};
return {
addElementTypes: addElementTypes,
};
};

200
src/views/process/print/canvas-bg/CanvasBg.vue

@ -0,0 +1,200 @@
<template>
<div class="canvas-bg" :style="bgStyle">
<div :style="canvasStyle" class="canvas-panel-wrap">
{{ canvasStyle }} <slot></slot>
</div>
<canvas ref="topRulerRef" class="canvas-ruler top" :style="topStyle"></canvas>
<canvas ref="leftRulerRef" class="canvas-ruler left" :style="leftStyle"></canvas>
<i class="canvas-ruler-cross"></i>
<div
class="canvas-move"
v-show="isMoveCanvas"
@mousedown="onMoveCanvasDown"
@mouseup="onMoveCanvasUp"
></div>
</div>
</template>
<script lang="ts">
import {
defineComponent,
ref,
onMounted,
computed,
watch,
nextTick,
onBeforeUnmount,
} from "vue";
import { drawRuler } from "./drawRuler.ts";
import { useUserRulerStore } from "@/store/ruler/index";
import { keyCode } from "./data/keyCode";
export default defineComponent({
name: "CanvasBg",
setup() {
const editorStore = useUserRulerStore();
const topRulerRef = ref();
const leftRulerRef = ref();
const isMoveCanvas = computed(() => editorStore.isMoveCanvas);
watch(
() => editorStore.screenWidth,
() => {
refreshRuler();
}
);
watch(
() => editorStore.screenHeight,
() => {
refreshRuler();
}
);
watch(
() => editorStore.scale,
() => {
refreshRuler();
}
);
let isRuler = false;
const refreshRuler = () => {
if (!isRuler) {
isRuler = true;
nextTick(() => {
drawRuler(
"top",
topRulerRef.value,
editorStore.scale,
editorStore.showWidth,
24,
60
);
drawRuler(
"left",
leftRulerRef.value,
editorStore.scale,
editorStore.showWidth,
24,
60
);
isRuler = false;
});
}
};
const scrollLeft = computed(() => {
return editorStore.scrollLeft - 24;
});
const scrollTop = computed(() => {
return editorStore.scrollTop - 24;
});
const onKeyAction = (e: KeyboardEvent) => {
if (e.keyCode == keyCode.space) {
editorStore.setMoveCanvas(!editorStore.isMoveCanvas);
}
};
const onWheelAction = (e: WheelEvent) => {
if (isMoveCanvas.value) {
if (e.wheelDelta > 0) {
editorStore.setScale(editorStore.scale + 1);
} else {
editorStore.setScale(editorStore.scale - 1);
}
}
};
onMounted(() => {
window.addEventListener("keydown", onKeyAction);
window.addEventListener("wheel", onWheelAction);
refreshRuler();
});
onBeforeUnmount(() => {
window.removeEventListener("keydown", onKeyAction);
window.removeEventListener("wheel", onWheelAction);
});
let moveInfo = {
startX: 0,
startY: 0,
};
return {
topRulerRef,
leftRulerRef,
topStyle: computed(() => ({
left: -scrollLeft.value + "px",
})),
leftStyle: computed(() => ({ top: -scrollTop.value + "px" })),
isMoveCanvas,
bgStyle: computed(() => ({
width: editorStore.showWidth + "px",
height: editorStore.showHeight + "px",
})),
canvasStyle: computed(() => ({
left: -scrollLeft.value + "px",
top: -scrollTop.value + "px",
width: editorStore.screenWidth + "px",
height: editorStore.screenHeight + "px",
transform: `scale(${editorStore.scale * 0.01})`,
})),
scrollLeft,
scrollTop,
onMoveCanvasDown: (e: MouseEvent) => {
e.stopPropagation();
moveInfo = {
startX: e.clientX,
startY: e.clientY,
};
},
onMoveCanvasUp: (e: MouseEvent) => {
e.stopPropagation();
let left = scrollLeft.value - (e.clientX - moveInfo.startX);
let top = scrollTop.value - (e.clientY - moveInfo.startY);
// console.log('move', left, top);
editorStore.setScroll({ left, top });
},
};
},
});
</script>
<style lang="scss" scoped>
.canvas-ruler-cross {
display: inline-block;
width: 24px;
height: 24px;
position: absolute;
background-color: var(--ruler-bg);
}
.canvas-panel-wrap {
position: absolute;
box-shadow: var(--canvas-shadow) 0 0 30px 0;
transform-origin: left top;
margin-left: 60px;
margin-top: 60px;
}
.canvas-move {
position: absolute;
height: 100%;
width: 100%;
background-color: var(--move-bg);
cursor: move;
}
.canvas-ruler {
position: absolute;
transform-origin: left top;
// cursor: ew-resize;
background-color: var(--ruler-bg);
&.left {
top: 24px;
left: 0px;
}
&.top {
top: 0px;
left: 24px;
}
}
</style>

148
src/views/process/print/canvas-bg/CanvasSlider.vue

@ -0,0 +1,148 @@
<template>
<div class="canvas-slider">
<el-tooltip placement="top" effect="light">
<template #content>
<div class="operation-tip-item">
<div>按下空格键可移动画布</div>
<div>按下空格键滚动鼠标滑轮可放缩画布</div>
</div>
</template>
<i class="el-icon-thumb" />
</el-tooltip>
<el-input-number v-model="scalePercent" :min="20" :max="200" size="small"></el-input-number>
<el-slider
size="small"
v-model="scalePercent"
:min="20"
:max="200"
:step="5"
style="width: 100px; margin: 0 12px"
></el-slider>
<el-tooltip placement="top">
<template #content> 实际大小 </template>
<i class="el-icon-full-screen" @click="onRealCanvas" />
</el-tooltip>
<el-tooltip placement="top">
<template #content> 适应屏幕大小 </template>
<i class="el-icon-aim" @click="onFitCanvas" />
</el-tooltip>
<i
class="el-icon-monitor"
:style="{ color: showThumbnail ? 'dodgerblue' : 'rgba(0,0,0,0.5)' }"
@click="onMagic"
></i>
</div>
</template>
<script lang="ts">
import { useEditorStore } from '@/stores/editor';
import { defineComponent, ref, computed, onMounted, onBeforeUnmount } from 'vue';
//
export default defineComponent({
name: 'CanvasSlider',
setup() {
const store = useEditorStore();
const scalePercent = computed({
get: () => store.scale,
set: (value) => {
store.setScale(value);
}
});
const showThumbnail = computed({
get: () => store.$state.isThumbnail,
set: (value) => {
store.setThumbnail(value);
}
});
const onFitCanvas = () => {
store.setScale(
parseInt(
//@ts-ignore
((document.getElementById('dashboard').offsetHeight - 84) / store.screenHeight) * 100
)
);
};
const onRealCanvas = () => {
store.setScale(100);
};
const onMagic = () => {
showThumbnail.value = !showThumbnail.value;
};
return {
showThumbnail,
scalePercent,
//method
onMagic,
onFitCanvas,
onRealCanvas
};
}
});
</script>
<style lang="scss" scoped>
.operation-tip-item > div {
color: var(--el-color-primary);
background: rgba(26, 103, 255, 0.1);
padding: 5px 10px;
}
.operation-tip-item > div:not(:last-child) {
margin-bottom: 8px;
}
i {
font-size: 16px;
color: var(--slider-icon);
cursor: pointer;
&:not(:last-child) {
margin-right: 10px;
}
}
:deep(.el-input-number__decrease) {
border: none;
background: none;
}
:deep(.el-input-number__increase) {
border: none;
background: none;
}
:deep(.el-input__wrapper) {
border: none;
border-radius: 0;
background: none;
box-shadow: none;
}
.el-input-number--small {
width: 84px;
}
$line: solid 1px var(--canvas-slider-border);
.canvas-slider {
display: flex;
position: fixed;
bottom: 10px;
right: 310px;
background-color: var(--slider-bg);
height: 32px;
justify-content: flex-end;
align-items: center;
border: $line;
z-index: 9;
border-radius: 2px;
padding: 0 16px;
}
</style>

193
src/views/process/print/canvas-bg/CanvasThumbnail.vue

@ -0,0 +1,193 @@
<template>
<canvas
class="canvas-thumbnail"
:width="canvasConfig.thumbnailWrapWidth"
:height="canvasConfig.thumbnailWrapHeight"
ref="thumbnailRef"
v-show="showThumbnail"
@mousedown="onMoveStart"
@mousemove="onMove"
@mouseup="onMoveEnd"
@mouseleave="onMoveEnd"
>
</canvas>
</template>
<script lang="ts">
import { useEditorStore } from '@/stores/editor';
import {
defineComponent,
ref,
computed,
reactive,
watch,
onMounted,
nextTick,
onBeforeUnmount
} from 'vue';
export default defineComponent({
name: 'CanvasThumbnail',
setup(props, context) {
const editorStore = useEditorStore();
const thumbnailRef = ref();
const canvasConfig = computed(() => editorStore.canvasConfig);
let isLock = false;
const viewBox = computed({
get: () => ({ viewWidth: editorStore.viewWidth, viewHeight: editorStore.viewHeight }),
set: (v) => {
editorStore.setViewBox(v);
}
});
const unscale = computed(() => {
if (editorStore.scale > 100) {
return 1 / editorStore.thumbnailSize;
} else {
return 10;
}
});
const getViewBox = () => {
nextTick(() => {
let dashboardDom = document.getElementById('dashboard');
if (!dashboardDom) {
return;
}
viewBox.value.viewWidth = dashboardDom.offsetWidth;
viewBox.value.viewHeight = dashboardDom.offsetHeight;
drawThumbnail();
});
};
const drawThumbnail = () => {
if (!isLock) {
isLock = true;
nextTick(() => {
let startLen = 6;
const ctx = thumbnailRef.value.getContext('2d');
ctx.clearRect(
0,
0,
canvasConfig.value.thumbnailWrapWidth,
canvasConfig.value.thumbnailWrapHeight
);
ctx.beginPath();
ctx.fillStyle = 'rgba(26, 103, 255, 0.5)';
ctx.rect(
startLen,
startLen,
canvasConfig.value.thumbnailWidth,
canvasConfig.value.thumbnailHeight
);
ctx.fill();
ctx.beginPath();
ctx.strokeStyle = '#1a67ff';
ctx.rect(
Math.round(editorStore.scrollLeft * editorStore.thumbnailSize),
Math.round(editorStore.scrollTop * editorStore.thumbnailSize),
viewBox.value.viewWidth * editorStore.thumbnailSize,
viewBox.value.viewHeight * editorStore.thumbnailSize
);
ctx.stroke();
isLock = false;
});
}
};
watch(
() => editorStore.scale,
() => {
drawThumbnail();
}
);
watch(
() => editorStore.screenWidth,
() => {
drawThumbnail();
}
);
watch(
() => editorStore.screenHeight,
() => {
drawThumbnail();
}
);
watch(
() => editorStore.scrollLeft,
() => {
drawThumbnail();
}
);
watch(
() => editorStore.scrollTop,
() => {
drawThumbnail();
}
);
watch(
() => editorStore.screenHeight,
() => {
drawThumbnail();
}
);
watch(
() => editorStore.viewHeight,
() => {
drawThumbnail();
}
);
watch(
() => editorStore.viewWidth,
() => {
drawThumbnail();
}
);
onMounted(() => {
window.addEventListener('resize', getViewBox);
getViewBox();
});
onBeforeUnmount(() => {
window.removeEventListener('resize', getViewBox);
});
let moveInfo = {
startX: 0,
startY: 0,
isMove: false
};
return {
canvasConfig,
thumbnailRef,
showThumbnail: computed(() => editorStore.isThumbnail),
onMoveStart: (e: MouseEvent) => {
moveInfo.isMove = true;
moveInfo.startX = e.clientX;
moveInfo.startY = e.clientY;
},
onMove: (e: MouseEvent) => {
if (moveInfo.isMove) {
let left = editorStore.scrollLeft + (e.clientX - moveInfo.startX) * unscale.value;
let top = editorStore.scrollTop + (e.clientY - moveInfo.startY) * unscale.value;
// console.log('thumbnail', left, top);
editorStore.setScroll({ left, top });
moveInfo.startX = e.clientX;
moveInfo.startY = e.clientY;
}
},
onMoveEnd: () => {
moveInfo.isMove = false;
}
};
}
});
</script>
<style lang="scss" scoped>
.canvas-thumbnail {
background-color: var(--thumbnail-wrap-bg);
position: fixed;
right: 310px;
bottom: 48px;
z-index: 9;
cursor: move;
}
</style>

41
src/views/process/print/canvas-bg/data/keyCode.ts

@ -0,0 +1,41 @@
export const keyCode = {
space: 32,
backspace: 8,
shift: 16,
ctr: 17,
option: 18,
command: 91,
alt: 18,
ctrl: 17,
equal: 187,
minus: 189,
q: 81,
w: 87,
c: 67,
d: 68,
z: 90,
y: 89,
g: 71,
l: 76,
h: 72,
u: 85,
o: 79,
r: 82,
t: 84,
b: 66,
s: 83,
p: 80,
left: 37,
top: 38,
right: 39,
bottom: 40
};
// export function getCodeKey(code) {
// for (let k in keyCode) {
// if (keyCode[k] == code) {
// return k;
// }
// }
// return '';
// }

98
src/views/process/print/canvas-bg/drawRuler.ts

@ -0,0 +1,98 @@
/**
* Canvas
* @param direction
* @param canvas canvas DOM
* @param scale [20-200]
* @param width
* @param height
* @param startLen
*/
export function drawRuler(
direction: string,
canvas: HTMLCanvasElement,
scale: number = 100,
width: number,
height: number = 24,
startLen: number = 60
) {
const padding = 2;
const ctx: CanvasRenderingContext2D = canvas.getContext('2d');
const percent = scale * 0.01;
let unit = Math.ceil(10 / percent);
if (unit < 8) {
unit = 8;
}
//计算出要绘制多少个刻度
const scaleCount = Math.ceil(width + startLen / unit);
if (direction == 'top') {
canvas.width = width + startLen;
canvas.height = height;
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
//绘制起点
ctx.strokeStyle = 'rgb(161, 174, 179)';
ctx.font = '10px Arial';
ctx.lineWidth = 0.5;
ctx.moveTo(startLen, 0);
ctx.lineTo(startLen, height);
ctx.fillText('0', startLen + padding, 13);
for (let i = 1; i <= scaleCount; i++) {
//计算每个刻度的位置
const step = startLen + Math.round(i * unit * percent);
//10的倍数刻度大长度
if (i % 10 === 0) {
ctx.moveTo(step, 0);
ctx.lineTo(step, height);
//标注刻度值
const scaleText = i * unit + '';
ctx.fillText(scaleText, step + padding, 13);
} else if (i % 5 === 0) {//5的倍数刻度中长度
ctx.moveTo(step, 15);
ctx.lineTo(step, height);
//标注刻度值
const scaleText = i * unit + '';
ctx.fillText(scaleText, step + padding, 13);
} else {//其他刻度小长度
ctx.moveTo(step, height - 2);
ctx.lineTo(step, height);
}
}
ctx.stroke();
} else {
canvas.width = height;
canvas.height = width + startLen;
ctx.clearRect(0, 0, height, width + startLen);
ctx.beginPath();
//绘制起点
ctx.strokeStyle = 'rgb(161, 174, 179)';
ctx.font = '10px Arial';
ctx.lineWidth = 0.5;
ctx.moveTo(0, startLen);
ctx.lineTo(height, startLen);
ctx.fillText('0', padding, startLen - padding);
//计算出要绘制多少个刻度
for (let i = 1; i <= scaleCount; i++) {
const step = startLen + Math.round(i * unit * percent);
if (i % 10 === 0) {
ctx.moveTo(0, step);
ctx.lineTo(height, step);
//标注刻度值
const scaleText = unit * i + '';
ctx.fillText(scaleText, padding, step - padding);
} else if (i % 5 === 0) {
ctx.moveTo(15, step);
ctx.lineTo(height, step);
//标注刻度值
const scaleText = unit * i + '';
ctx.fillText(scaleText, padding, step - padding);
} else {
ctx.moveTo(height - 2, step);
ctx.lineTo(height, step);
}
}
ctx.stroke();
}
}

14
src/views/process/state.vue

@ -0,0 +1,14 @@
<!--
@ 作者: 秦东
@ 时间: 2025-03-24 09:42:31
@ 备注:
-->
<script lang="ts" setup>
import CanvasBg from "@/views/process/canvas-bg/CanvasBg.vue";
</script>
<template>
<div>
<CanvasBg />
</div>
</template>
<style lang="scss" scoped></style>

30
src/views/process/state2.vue

@ -0,0 +1,30 @@
<!--
@ 作者: 秦东
@ 时间: 2025-03-22 11:05:01
@ 备注:
-->
<script lang="ts" setup>
import { Vue3RulerTool } from "vue3-ruler-tool";
import "vue3-ruler-tool/dist/style.css";
const presetLine = ref([
{ type: "h", site: 20 },
{ type: "v", site: 10 },
]);
const visible = ref(true);
const input = (list: any) => {
presetLine.value = list;
};
</script>
<template>
<vue3-ruler-tool
:value="presetLine"
:step-length="50"
:parent="true"
:is-scale-revise="true"
:visible.sync="visible"
@input="input"
>
<div>我是内容</div>
</vue3-ruler-tool>
</template>
<style lang="scss" scoped></style>

39
src/views/sysworkflow/lowcodepage/appPage/appPageForm/pageConfig.ts

@ -0,0 +1,39 @@
export default {
paperOrientationList:[
{
value:1,
label:"纵向"
},
{
value:2,
label:"横向"
},
],
// 纸张类型
paperTypes: {
'A3': {
width: 420,
height: 296.6
},
'A4': {
width: 210,
height: 296.6
},
'A5': {
width: 210,
height: 147.6
},
'B3': {
width: 500,
height: 352.6
},
'B4': {
width: 250,
height: 352.6
},
'B5': {
width: 250,
height: 175.6
}
},
}

662
src/views/sysworkflow/lowcodepage/appPage/appPageForm/pageList.vue

@ -5,7 +5,8 @@
-->
<script lang="ts" setup>
import { ElTable } from "element-plus";
import { Hide, View } from "@element-plus/icons-vue";
import { Hide, View, Calendar, Search } from "@element-plus/icons-vue";
import {
attrButton,
tableButton,
@ -33,6 +34,11 @@ import { formTableField, formTabelStruct } from "@/api/DesignForm/type";
import tempOtherUnit from "@/components/DesignForm/pageList/types";
import { ElMessage } from "element-plus";
import { sendTableFields, sendCustFields } from "@/api/displayboardapi/types";
import {
gainOrgOfPeopleNodeFactor,
gainOegAndPeople,
} from "@/api/displayboardapi/indexapi";
import Sortable from "sortablejs";
//
@ -220,6 +226,15 @@ const state = reactive({
},
},
},
sendMsg: {
open: false, //
type: "textcard", //
title: [], //
content: [], //
icon: "", //
sendRange: 2, //
sendRangeList: [], //
},
});
/**
@ 作者: 秦东
@ -368,6 +383,14 @@ const getListInfo = () => {
console.log("获取列表内容---->", stateData);
state.tableData = stateData.tableData;
state.searchData = stateData.searchData;
if (stateData.sendMsg) {
state.sendMsg = stateData.sendMsg;
if (state.sendMsg.sendRange != 0) {
oldPickSendRange.value = state.sendMsg.sendRange;
}
}
if (state.searchData == null) {
state.searchData = new Array();
}
@ -866,6 +889,7 @@ const dialogOpen = (obj: any, params: any = {}) => {
drawer.visible = true;
Object.assign(drawer, { direction: "ltr" }, params);
let editData = objToStringify(obj, true);
console.log("数据格式处理------------------------>", params);
switch (params.type) {
case "dict":
editData = json2string(obj, true);
@ -1087,8 +1111,473 @@ const addListField = (
// }
// console.log("state.tableData.columns", state.tableData);
};
/**
@ 作者: 秦东
@ 时间: 2025-03-25 15:27:52
@ 功能: 选择发送范围
*/
const tableFieldsList = ref<sendTableFields[]>();
const oldPickSendRange = ref<number>(2);
const pickTableIsOpen = ref(false); //
const sendTableLoading = ref(false);
const pickCustomizeIsOpen = ref(false); //
const sendCustLoading = ref(false);
const pickSendRange = (val: number) => {
console.log("pickSendRange", val);
switch (val) {
case 5: //
getOrgPeople();
pickTableIsOpen.value = true;
break;
case 6: //
gainPeopleAndOrg();
pickCustomizeIsOpen.value = true;
break;
default:
oldPickSendRange.value = val;
}
};
const tableFields = reactive({
list: [],
});
/**
@ 作者: 秦东
@ 时间: 2025-03-26 09:03:12
@ 功能: 获取要发送得行政组织字段
*/
const getOrgPeople = () => {
gainOrgOfPeopleNodeFactor({ id: state.formId })
.then((data) => {
tableFieldsList.value = data.data;
console.log("选表格中指定发送范围数据", data);
if (state.sendMsg.sendRangeList.length > 0) {
tableFields.list = [];
state.sendMsg.sendRangeList.forEach((item: sendTableFields) => {
if (item.types != "people" && item.types != "masterOrg") {
tableFields.list.push(item.id);
}
});
}
})
.finally(() => {
sendTableLoading.value = false;
});
};
/**
@ 作者: 秦东
@ 时间: 2025-03-25 15:55:48
@ 功能: 关闭表格发送范围
*/
const handleTableClose = () => {
pickTableIsOpen.value = false;
state.sendMsg.sendRangeList = [];
sendTableLoading.value = false;
state.sendMsg.sendRange = oldPickSendRange.value;
};
/**
@ 作者: 秦东
@ 时间: 2025-03-25 16:00:08
@ 功能: 选表格中指定发送范围数据
*/
const pickTableSendRange = () => {
// sendTableLoading.value = true;
console.log("选表格中指定发送范围数据", tableFields.list);
if (
tableFields.list &&
tableFields.list.length > 0 &&
tableFieldsList.value.length > 0
) {
state.sendMsg.sendRangeList = [];
tableFields.list.forEach((item: string) => {
tableFieldsList.value.forEach((vit: sendTableFields) => {
if (vit.id == item) {
state.sendMsg.sendRangeList.push(vit);
}
});
});
if (state.sendMsg.sendRangeList.length > 0) {
sendTableLoading.value = false;
pickTableIsOpen.value = false;
oldPickSendRange.value = state.sendMsg.sendRange;
} else {
handleTableClose();
}
} else {
handleTableClose();
}
console.log("选表----------->", state);
};
/**
@ 作者: 秦东
@ 时间: 2025-03-26 11:08:42
@ 功能: 关闭自定义发送范围
*/
const handleCustClose = () => {
pickCustomizeIsOpen.value = false;
state.sendMsg.sendRange = oldPickSendRange.value;
delAllPick();
};
/**
@ 作者: 秦东
@ 时间: 2025-03-27 08:42:51
@ 功能: 获取自定义人员与行政组织穿梭框
*/
const orgManLoading = ref(false);
const orgManList = ref<sendCustFields[]>([]);
const orgAndPeopleBrea = ref<sendCustFields[]>([]);
const PickOrgManList = ref<sendCustFields[]>([]);
const gainPeopleAndOrg = (orgId?: string) => {
orgManLoading.value = true;
gainOegAndPeople({ id: orgId })
.then((data) => {
console.log("获取自定义人员与行政组织穿梭框----------->", data);
orgAndPeopleBrea.value = data.data.breadcrumb;
orgManList.value = data.data.orgManList;
nextTick(() => {
if (PickOrgManList.value.length <= 0) {
PickOrgManList.value = [];
console.log(
"获取自定义人员与行政组织穿梭框----------->",
state.sendMsg.sendRangeList
);
state.sendMsg.sendRangeList.forEach((item: sendTableFields) => {
console.log("获取自定义人员与行政组织穿梭框----------->", item.types);
if (item.types == "people" || item.types == "masterOrg") {
orgManList.value.forEach((itemOrg: sendCustFields) => {
if (item.id == itemOrg.id && item.types == itemOrg.types) {
itemOrg.isPick = true;
// PickOrgManList.value.push(itemOrg);
}
});
PickOrgManList.value.push(item);
}
});
} else {
if (PickOrgManList.value.length > 0) {
PickOrgManList.value.forEach((item: sendCustFields) => {
orgManList.value.forEach((itemOrg: sendCustFields) => {
if (
item.id == itemOrg.id &&
item.number == itemOrg.number &&
item.types == itemOrg.types
) {
itemOrg.isPick = true;
}
});
});
}
}
console.log(
"获取自定义人员与行政组织穿梭框---------11111->",
PickOrgManList.value
);
});
})
.finally(() => {
orgManLoading.value = false;
});
};
/**
@ 作者: 秦东
@ 时间: 2025-03-26 11:37:21
@ 功能: 提交自定义数据
*/
const pickCustSendRange = () => {
sendCustLoading.value = true;
if (PickOrgManList.value && PickOrgManList.value.length > 0) {
state.sendMsg.sendRangeList = [];
PickOrgManList.value.forEach((item: string) => {
state.sendMsg.sendRangeList.push(item);
// if (item.types == "masterOrg") {
// state.sendMsg.sendRangeList.push({
// lable: item.name,
// fields: item.id,
// types: item.types,
// multipleChoice: true,
// });
// } else {
// state.sendMsg.sendRangeList.push({
// lable: item.name,
// fields: item.id,
// types: item.types,
// multipleChoice: false,
// });
// }
});
if (state.sendMsg.sendRangeList.length > 0) {
sendCustLoading.value = false;
oldPickSendRange.value = state.sendMsg.sendRange;
handleCustClose();
} else {
handleCustClose();
}
} else {
handleCustClose();
}
};
/**
@ 作者: 秦东
@ 时间: 2025-03-27 09:15:59
@ 功能: 选择人员或行政组织
*/
const pickOrgOrMan = (info: sendCustFields) => {
if (info.isPick) {
//
info.isPick = false;
if (PickOrgManList.value.length > 0) {
PickOrgManList.value.forEach((item: sendCustFields, index: number) => {
if (
item.id == info.id &&
item.number == info.number &&
item.types == info.types
) {
PickOrgManList.value.splice(index, 1);
}
});
}
} else {
//
info.isPick = true;
if (PickOrgManList.value.length > 0) {
let isWrite = true;
PickOrgManList.value.forEach((item: sendCustFields) => {
if (
item.id == info.id &&
item.number == info.number &&
item.types == info.types
) {
isWrite = false;
}
});
if (isWrite) {
PickOrgManList.value.push(info);
}
} else {
PickOrgManList.value.push(info);
}
}
};
/**
@ 作者: 秦东
@ 时间: 2025-03-27 09:54:56
@ 功能: 删除已选择的信息
*/
const delPick = (info: sendCustFields) => {
if (PickOrgManList.value.length > 0) {
PickOrgManList.value.forEach((item: sendCustFields, index: number) => {
if (item.id == info.id && item.number == info.number && item.types == info.types) {
PickOrgManList.value.splice(index, 1);
}
});
}
if (orgManList.value.length > 0) {
orgManList.value.forEach((itemOrg: sendCustFields) => {
if (
info.id == itemOrg.id &&
info.number == itemOrg.number &&
info.types == itemOrg.types
) {
itemOrg.isPick = false;
}
});
}
};
/**
@ 作者: 秦东
@ 时间: 2025-03-27 10:09:23
@ 功能: 删除所有选择
*/
const delAllPick = () => {
if (PickOrgManList.value.length > 0) {
PickOrgManList.value.splice(0, PickOrgManList.value.length);
}
if (orgManList.value.length > 0) {
orgManList.value.forEach((itemOrg: sendCustFields) => {
itemOrg.isPick = false;
});
}
// if (peopleList.value.length > 0) {
// peopleList.value.forEach((itemMan: sendCustFields) => {
// itemMan.isPick = false;
// });
// }
};
</script>
<template>
<!--自定义发送范围-->
<el-dialog
v-model="pickCustomizeIsOpen"
title="自定义发送范围"
width="600"
:before-close="handleCustClose"
draggable
>
<div class="custBox">
<el-row>
<el-col :span="12" class="rightLine">
<div class="leftSearch">
<el-input
v-model="input2"
style="width: 100%"
placeholder="搜查成员"
:prefix-icon="Search"
/>
</div>
<div class="leftButBox fenpi">
<div style="padding: 5px 0">
<el-button type="primary" text size="small" @click="gainPeopleAndOrg()"
>全部</el-button
>
</div>
<el-scrollbar wrap-style="padding: 5px 0">
<div class="scrollbar-flex-content">
<el-button
v-for="item in orgAndPeopleBrea"
type="primary"
text
size="small"
@click="gainPeopleAndOrg(item.id)"
>{{ item.name }}</el-button
>
</div>
</el-scrollbar>
</div>
<el-scrollbar height="400px" v-loading="orgManLoading">
<div v-for="item in orgManList">
<div
v-if="item.types == 'masterOrg'"
:class="
item.isPick ? 'scrollbar-demo-item active' : 'scrollbar-demo-item'
"
>
<div class="usBox" @click="pickOrgOrMan(item)">
<span class="iconSpan fa fa-folder-o"></span>
<el-text>{{ item.name }}</el-text>
</div>
<div @click="gainPeopleAndOrg(item.id)" style="cursor: pointer">下级</div>
</div>
<div
v-else
:class="
item.isPick ? 'scrollbar-demo-item active' : 'scrollbar-demo-item'
"
>
<div class="usBox" @click="pickOrgOrMan(item)">
<el-image
v-if="item.icon != ''"
style="width: 30px; height: 30px"
:src="item.icon"
fit="fit"
/>
<span v-else class="iconSpan fa fa-user-o"></span>
<div class="usInfo">
<el-text>{{ item.name }}</el-text
><el-text type="info">No{{ item.number }}</el-text>
</div>
</div>
<div></div>
</div>
</div>
</el-scrollbar>
</el-col>
<el-col :span="12">
<div class="leftSearch pickTitle">
<el-text class="mx-1">已选择{{ PickOrgManList.length }}</el-text>
<el-text
class="mx-1"
type="danger"
style="cursor: pointer"
@click="delAllPick"
>清空</el-text
>
</div>
<el-scrollbar height="435px">
<div v-for="item in PickOrgManList">
<div v-if="item.types == 'masterOrg'" class="scrollbar-demo-item active">
<div class="usBoxac">
<span class="iconSpan fa fa-folder-o"></span>
<el-text>{{ item.name }}</el-text>
</div>
<div>
<i class="fa fa-close" @click="delPick(item)"></i>
</div>
</div>
<div v-else class="scrollbar-demo-item active">
<div class="usBoxac">
<el-image
v-if="item.icon != ''"
style="width: 30px; height: 30px"
:src="item.icon"
fit="fit"
/>
<span v-else class="iconSpan fa fa-user-o"></span>
<div class="usInfo">
<el-text>{{ item.name }}</el-text
><el-text type="info">No{{ item.number }}</el-text>
</div>
</div>
<div><i class="fa fa-close" @click="delPick(item)"></i></div>
</div>
</div>
</el-scrollbar>
</el-col>
</el-row>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleCustClose">取消选择</el-button>
<el-button type="primary" @click="pickCustSendRange" v-loading="sendCustLoading">
确定选择
</el-button>
</div>
</template>
</el-dialog>
<!--表格中的数据-->
<el-dialog
v-model="pickTableIsOpen"
title="从现有表单中选择发送范围字段"
width="500"
:before-close="handleTableClose"
draggable
>
<el-form :model="tableFields" label-width="auto">
<el-form-item label="表格字段">
<el-select
v-model="tableFields.list"
placeholder="请选择表格字段"
clearable
multiple
>
<el-option
v-for="item in tableFieldsList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleTableClose">取消选择</el-button>
<el-button
type="primary"
@click="pickTableSendRange"
v-loading="sendTableLoading"
>
确定选择
</el-button>
</div>
</template>
</el-dialog>
<el-main class="mainBox">
<div class="header">
<div class="field"></div>
@ -1353,6 +1842,7 @@ const addListField = (
:title="drawer.title"
:direction="drawer.direction"
:content="drawer.content"
:data="drawer"
:code-type="drawer.codeType"
@before-close="drawerBeforeClose"
@confirm="dialogConfirm"
@ -1377,7 +1867,7 @@ const addListField = (
:search-data="state.searchData"
:config="state.config"
:form-id="props.appPageKey"
:viewPage="stateList.view"
:viewPage="state.view"
v-if="state.previewVisible"
/>
</el-drawer>
@ -1496,6 +1986,98 @@ const addListField = (
</div>
</el-tab-pane>
<el-tab-pane label="列表设置" :name="2">
<el-divider content-position="left">企业微信消息推送</el-divider>
<div class="demo_collapse">
<el-form
label-position="top"
label-width="auto"
:model="state.sendMsg"
style="max-width: 600px"
>
<el-form-item label="是否开启推送信息">
<el-switch
v-model="state.sendMsg.open"
class="ml-2"
inline-prompt
active-text="是"
inactive-text="否"
style="--el-switch-on-color: #409eff; --el-switch-off-color: #ff4949"
/>
</el-form-item>
<el-form-item v-if="state.sendMsg.open" label="消息类型">
<el-radio-group v-model="state.sendMsg.type" size="small">
<el-radio-button value="textcard">文本卡片</el-radio-button>
<el-radio-button v-if="!isCardTrue" value="news"
>图文消息</el-radio-button
>
<el-radio-button value="text">文本消息</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="state.sendMsg.open && state.sendMsg.type != 'text'"
label="发送消息标题字段"
>
<el-select
v-model="state.sendMsg.title"
multiple
placeholder="请选择消息标题字段"
clearable
>
<el-option
v-for="item in allKeyWords"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item v-if="state.sendMsg.open" label="发送消息主体字段" clearable>
<el-select
v-model="state.sendMsg.content"
multiple
placeholder="请选择消息主体字段"
>
<el-option
v-for="item in allKeyWords"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="state.sendMsg.open && !isCardTrue && state.sendMsg.type == 'news'"
label="图片字段"
>
<el-select
v-model="state.sendMsg.icon"
placeholder="请选择图片字段"
clearable
>
<el-option
v-for="item in cardKeyWords"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item v-if="state.sendMsg.open" label="发送范围">
<el-radio-group
v-model="state.sendMsg.sendRange"
size="small"
@change="pickSendRange"
>
<el-radio-button :value="1">全集团</el-radio-button>
<el-radio-button :value="2">本公司</el-radio-button>
<el-radio-button :value="3">本部门</el-radio-button>
<el-radio-button :value="4">本行政组织</el-radio-button>
<el-radio-button :value="5">表格中指定</el-radio-button>
<el-radio-button :value="6">自定义</el-radio-button>
</el-radio-group>
</el-form-item>
</el-form>
</div>
<el-divider content-position="left">开启视图</el-divider>
<div class="demo_collapse">
<el-collapse v-value="activeName" @change="handleChange">
@ -2284,4 +2866,80 @@ const addListField = (
color: #337ecc;
}
}
.custBox {
border: 1px solid #c4c4c4;
height: 470px;
overflow: hidden;
.rightLine {
height: 470px;
border-right: 1px solid #c4c4c4;
}
.leftSearch {
border-bottom: 1px solid #c4c4c4;
padding: 2px 5px;
}
.pickTitle {
display: flex;
align-items: center;
justify-content: space-between;
height: 37px;
}
.leftButBox {
border-bottom: 1px solid #c4c4c4;
padding: 0px 5px;
}
.fenpi {
display: flex;
}
}
.scrollbar-flex-content {
display: flex;
width: fit-content;
}
.scrollbar-demo-item {
display: flex;
align-items: center;
justify-content: space-between;
height: 40px;
margin: 5px;
text-align: left;
border-radius: 4px;
background: rgb(221.7, 222.6, 224.4);
color: #303133;
padding: 0 5px;
.usBox {
display: flex;
align-items: center;
cursor: pointer;
span {
overflow: hidden; /* 隐藏溢出内容 :ml-search[overflow] */
}
.iconSpan {
font-size: 25px;
margin-right: 10px;
}
}
.usBoxac {
display: flex;
align-items: center;
span {
overflow: hidden; /* 隐藏溢出内容 :ml-search[overflow] */
}
.iconSpan {
font-size: 25px;
margin-right: 10px;
}
}
.usInfo {
margin-left: 4px;
}
}
.scrollbar-demo-item.active {
background: var(--el-color-primary-light-9);
color: var(--el-color-primary);
i {
color: #f56c6c;
cursor: pointer;
}
}
</style>

136
src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage.vue

@ -0,0 +1,136 @@
<!--
@ 作者: 秦东
@ 时间: 2025-03-24 15:32:40
@ 备注: 打印模版设计
-->
<script lang="ts" setup>
import PageConfig from "@/views/sysworkflow/lowcodepage/appPage/appPageForm/pageConfig";
import { printPageConfigStore } from "@/store/ruler/index";
import CanvasBg from "@/views/process/canvas-bg/CanvasBg.vue";
const props = defineProps({
appCont: {
type: Object,
default() {
return {};
},
},
formKey: {
type: String,
default: "",
},
groupKey: {
type: String,
default: "",
},
menuId: {
type: String,
default: "",
},
appPageKey: {
type: String,
default: "",
},
formVersion: {
type: String,
default: "",
},
state: {
type: Object,
default() {
return {};
},
},
});
const paperOrientation = ref<number>(1);
const pageSize = ref<number>(2);
</script>
<template>
<div class="common-layout">
<el-container>
<el-aside class="asideBox">
<div class="titleBox">打印数据源</div>
</el-aside>
<el-container class="contBox">
<el-header>
<div class="titleBox">
<el-row :gutter="5" class="rowBox">
<el-col :span="4">
<el-select
v-model="paperOrientation"
placeholder="请选择纸张方向"
size="small"
>
<el-option
v-for="item in PageConfig.paperOrientationList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-col>
<el-col :span="12">
<el-radio-group v-model="pageSize" size="small">
<el-radio-button label="A3" value="A3" />
<el-radio-button label="A4" value="A4" />
<el-radio-button label="A5" value="A5" />
<el-radio-button label="B3" value="B3" />
<el-radio-button label="B4" value="B4" />
<el-radio-button label="B5" value="B5" />
<el-radio-button label="自定义" value="zdy" />
</el-radio-group>
</el-col>
<el-col :span="6">
<el-button-group class="ml-4" size="small">
<el-button type="primary">预览</el-button>
<el-button type="danger">清空</el-button>
<el-button type="primary">保存</el-button>
</el-button-group>
</el-col>
</el-row>
</div>
</el-header>
<el-main>
<CanvasBg />
</el-main>
</el-container>
<el-aside class="asideBox">
<div class="titleBox">模块设置</div>
</el-aside>
</el-container>
</div>
</template>
<style lang="scss" scoped>
.common-layout {
width: 100%;
height: calc(100vh - 40px);
:deep .el-header {
padding: 0px;
}
:deep .el-main {
padding: 0px;
}
.asideBox {
width: 220px;
height: calc(100vh - 40px);
}
.contBox {
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
}
.titleBox {
width: 100%;
height: 40px;
border-bottom: 1px solid #ccc;
display: flex;
align-items: center;
}
.rowBox {
width: 100%;
text-align: center;
}
}
</style>

13
src/views/sysworkflow/lowcodepage/appPage/createAppFormPage.vue

@ -12,6 +12,8 @@ import { getProductionMarkForm } from "@/api/DesignForm/requestapi";
import PageForm from "@/views/sysworkflow/lowcodepage/appPage/appPageForm/pageForm.vue";
import PageFlow from "@/views/sysworkflow/lowcodepage/appPage/appPageForm/pageFlow.vue";
import PageList from "@/views/sysworkflow/lowcodepage/appPage/appPageForm/pageList.vue";
import PrintSetupPage from "@/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage.vue";
const props = defineProps({
appCont: {
type: Object,
@ -218,6 +220,7 @@ onBeforeMount(() => {
<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 class="headRight">
@ -259,6 +262,16 @@ onBeforeMount(() => {
v-model:app-page-key="appPageKey"
v-model:form-version="formVersion"
/>
<PrintSetupPage
v-if="tabsActive == 4"
v-model:state="state"
:form-Key="props.formKey"
:app-cont="props.appCont"
:menu-id="menuId"
:group-key="props.groupKey"
v-model:app-page-key="appPageKey"
v-model:form-version="formVersion"
/>
</el-container>
</el-container>
</div>

3353
src/views/sysworkflow/lowcodepage/pageList.vue

File diff suppressed because it is too large
Loading…
Cancel
Save