Selaa lähdekoodia

Merge branch 'online' into feature/0516-courseware

lex 1 vuosi sitten
vanhempi
commit
35bde19706
100 muutettua tiedostoa jossa 4727 lisäystä ja 28 poistoa
  1. 0 1
      dist/assets/404.17f7490f.css
  2. 1 0
      dist/assets/404.2e2564f3.css
  3. 1 0
      dist/assets/404.41632ed2.js
  4. 0 1
      dist/assets/404.bb8006fa.js
  5. 1 1
      dist/assets/Cascader.a84e948d.js
  6. 1 1
      dist/assets/DeleteFilled.2a3b3066.js
  7. 1 1
      dist/assets/FormItemGridItem.930c3242.js
  8. 1 1
      dist/assets/PageHeader.e8f5b4e1.js
  9. 1 1
      dist/assets/TreeSelect.6e5c1d79.js
  10. 1 1
      dist/assets/api.39f82c79.js
  11. 0 0
      dist/assets/api.3d30ce7e.js
  12. 1 1
      dist/assets/api.4006f814.js
  13. 0 0
      dist/assets/api.6040327b.js
  14. 1 1
      dist/assets/api.62e040f2.js
  15. 1 1
      dist/assets/api.a1ab0d47.js
  16. 1 1
      dist/assets/api.b003d277.js
  17. 0 0
      dist/assets/api.d71d4abc.js
  18. 1 1
      dist/assets/api.e513d6d6.js
  19. 0 0
      dist/assets/constant.d4a76877.js
  20. 1 1
      dist/assets/dateUtil.163360e3.js
  21. 0 0
      dist/assets/dayjs.min.d91a859a.js
  22. 0 0
      dist/assets/detail.28813d04.js
  23. 0 0
      dist/assets/editAndUpdate.796e5b9d.js
  24. 0 0
      dist/assets/employee-tab.5c70792d.js
  25. 1 1
      dist/assets/filters.21e6bf24.js
  26. 0 0
      dist/assets/index.0450a810.js
  27. 1 1
      dist/assets/index.07713f87.js
  28. 0 0
      dist/assets/index.18179f0a.css
  29. 0 0
      dist/assets/index.182b913f.js
  30. 0 0
      dist/assets/index.1f2ecc91.js
  31. 0 0
      dist/assets/index.223858a6.js
  32. 0 0
      dist/assets/index.291ec3fd.js
  33. 0 0
      dist/assets/index.2f0cd39f.js
  34. 0 0
      dist/assets/index.2ffb0350.js
  35. 0 0
      dist/assets/index.3881fe62.css
  36. 0 0
      dist/assets/index.3ee668c4.js
  37. 0 0
      dist/assets/index.447dac53.js
  38. 0 0
      dist/assets/index.48bca030.js
  39. 1 1
      dist/assets/index.4bb1e398.js
  40. 0 0
      dist/assets/index.5136035f.js
  41. 0 0
      dist/assets/index.5e5a1871.js
  42. 1 1
      dist/assets/index.6797b13e.js
  43. 0 0
      dist/assets/index.6807fcf7.js
  44. 1 0
      dist/assets/index.686af97c.js
  45. 0 0
      dist/assets/index.68c8370b.js
  46. 0 0
      dist/assets/index.69246979.css
  47. 0 0
      dist/assets/index.6a14fb5d.js
  48. 0 0
      dist/assets/index.746842da.css
  49. 0 0
      dist/assets/index.7b72b78d.js
  50. 0 1
      dist/assets/index.7e338cc1.css
  51. 1 0
      dist/assets/index.88a710bb.css
  52. 0 0
      dist/assets/index.8bdcdb3c.js
  53. 0 0
      dist/assets/index.8c438324.js
  54. 0 0
      dist/assets/index.8d91b63e.js
  55. 1 1
      dist/assets/index.957f0ce3.js
  56. 0 1
      dist/assets/index.9a011606.js
  57. 0 0
      dist/assets/index.a6d739b8.js
  58. 0 0
      dist/assets/index.a7ddacb9.js
  59. 0 0
      dist/assets/index.b39f3ab2.js
  60. 1 1
      dist/assets/index.b9ebd51f.js
  61. 0 0
      dist/assets/index.c59e9042.js
  62. 1 1
      dist/assets/index.dfbbfc12.js
  63. 0 0
      dist/assets/index.e8a7e66d.js
  64. 0 0
      dist/assets/index.f6064889.js
  65. 0 0
      dist/assets/index.f82a40aa.js
  66. 0 0
      dist/assets/instrument-list.06c3f8bd.js
  67. 0 0
      dist/assets/interface-log.49934b63.js
  68. 0 0
      dist/assets/musicPreView.e8c7302e.js
  69. 1 0
      dist/assets/musicUtil.3b4f332b.js
  70. 0 0
      dist/assets/musicUtil.99bcdb58.js
  71. 1 1
      dist/assets/parentLayout.221bde7c.js
  72. 0 0
      dist/assets/plan-detail.bc32f46e.js
  73. 1 1
      dist/assets/searchArray.84e16e6c.js
  74. 0 0
      dist/assets/sms-config-app.dcaa639a.js
  75. 1 1
      dist/assets/tabsView.ffd592a9.js
  76. 1 1
      dist/assets/use-async.34739939.js
  77. 0 0
      dist/assets/vuedraggable.umd.8c648a7b.js
  78. 0 0
      dist/assets/wechat-config-template-edit.f0a72f76.js
  79. 0 0
      dist/assets/wechat-config-template-message.38869eab.js
  80. 0 0
      dist/assets/wechat-config-template.cfe7d82c.js
  81. 0 0
      dist/index.html
  82. 8 1
      src/router/constant.ts
  83. 53 0
      src/utils/constant.ts
  84. 433 0
      src/views/message/api.ts
  85. 348 0
      src/views/message/message-config/email/email-config.tsx
  86. 253 0
      src/views/message/message-config/email/modal/email-config-edit.tsx
  87. 61 0
      src/views/message/message-config/index.tsx
  88. 327 0
      src/views/message/message-config/push/modal/push-config-edit.tsx
  89. 387 0
      src/views/message/message-config/push/push-config.tsx
  90. 159 0
      src/views/message/message-config/sms/modal/sms-config-app-edit.tsx
  91. 222 0
      src/views/message/message-config/sms/modal/sms-config-edit.tsx
  92. 347 0
      src/views/message/message-config/sms/sms-config-app.tsx
  93. 327 0
      src/views/message/message-config/sms/sms-config.tsx
  94. 229 0
      src/views/message/message-config/wechat/modal/wechat-config-edit.tsx
  95. 218 0
      src/views/message/message-config/wechat/modal/wechat-config-template-edit.tsx
  96. 342 0
      src/views/message/message-config/wechat/wechat-config-template-message.tsx
  97. 350 0
      src/views/message/message-config/wechat/wechat-config-template.tsx
  98. 355 0
      src/views/message/message-config/wechat/wechat-config.tsx
  99. 198 0
      src/views/message/message-record/email-record.tsx
  100. 82 0
      src/views/message/message-record/index.tsx

+ 0 - 1
dist/assets/404.17f7490f.css

@@ -1 +0,0 @@
-.page-container[data-v-d1dd2068]{border-radius:4px;padding:50px 0;height:100vh;background:#f0f2f5}.page-container .center-box[data-v-d1dd2068]{display:flex;flex-direction:column;align-items:center}.page-container .center-box .text-center[data-v-d1dd2068]{display:flex;flex-direction:row;align-items:flex-end}.page-container .center-box .text-center h2[data-v-d1dd2068]{color:#666;padding:20px 0;font-weight:600;color:#434e59;line-height:108px;font-size:77px}.page-container .center-box .text-center p[data-v-d1dd2068]{height:23px;font-size:17px;font-weight:400;color:#00000073;line-height:23px;margin-bottom:13px}.page-container .center-box .text-center .subBtn[data-v-d1dd2068]{margin-bottom:44px}.page-container img[data-v-d1dd2068]{width:585px}

+ 1 - 0
dist/assets/404.2e2564f3.css

@@ -0,0 +1 @@
+.page-container[data-v-5fc2dfea]{border-radius:4px;padding:50px 0;height:100vh;background:#f0f2f5}.page-container .center-box[data-v-5fc2dfea]{display:flex;flex-direction:column;align-items:center}.page-container .center-box .text-center[data-v-5fc2dfea]{display:flex;flex-direction:row;align-items:flex-end}.page-container .center-box .text-center h2[data-v-5fc2dfea]{color:#666;padding:20px 0;font-weight:600;color:#434e59;line-height:108px;font-size:77px}.page-container .center-box .text-center p[data-v-5fc2dfea]{height:23px;font-size:17px;font-weight:400;color:#00000073;line-height:23px;margin-bottom:13px}.page-container .center-box .text-center .subBtn[data-v-5fc2dfea]{margin-bottom:44px}.page-container img[data-v-5fc2dfea]{width:585px}

+ 1 - 0
dist/assets/404.41632ed2.js

@@ -0,0 +1 @@
+import{d as u,c as r,e as p,f as d,g as e,i,w as l,p as f,y as m,z as h,o as b,k as x,t as B}from"./index.1f2ecc91.js";import{u as g}from"./tabsView.ffd592a9.js";import"./searchs.b637f0d6.js";const v=""+new URL("404.db5b619b.png",import.meta.url).href,s=t=>(m("data-v-5fc2dfea"),t=t(),h(),t),w={class:"page-container"},y={class:"center-box"},C={class:"text-center"},E=s(()=>e("img",{src:v,alt:""},null,-1)),S={class:"sub-wrap"},V=s(()=>e("h2",{class:"text-base text-gray-500"},"404",-1)),k=s(()=>e("p",null,"\u62B1\u6B49\uFF0C\u4F60\u8BBF\u95EE\u7684\u9875\u9762\u4E0D\u5B58\u5728",-1)),F=u({__name:"404",setup(t){const o=g(),c=r(),a=p();function _(){o.closeCurrentTab(a),c.push("/")}return(I,N)=>{const n=f;return b(),d("div",w,[e("div",y,[e("div",C,[E,e("div",S,[V,k,i(n,{class:"subBtn",type:"info",onClick:_},{default:l(()=>[x("\u56DE\u5230\u9996\u9875")]),_:1})])])])])}}});const z=B(F,[["__scopeId","data-v-5fc2dfea"]]);export{z as default};

+ 0 - 1
dist/assets/404.bb8006fa.js

@@ -1 +0,0 @@
-import{d as u,c as d,e as r,f as p,g as t,i,w as l,p as m,y as h,z as b,o as f,k as x,t as B}from"./index.789dd106.js";import{u as g}from"./tabsView.ce4b9104.js";import"./searchs.b637f0d6.js";const v=""+new URL("404.db5b619b.png",import.meta.url).href,s=e=>(h("data-v-d1dd2068"),e=e(),b(),e),w={class:"page-container"},y={class:"center-box"},C={class:"text-center"},E=s(()=>t("img",{src:v,alt:""},null,-1)),S={class:"sub-wrap"},V=s(()=>t("h2",{class:"text-base text-gray-500"},"404",-1)),k=s(()=>t("p",null,"\u62B1\u6B49\uFF0C\u4F60\u8BBF\u95EE\u7684\u9875\u9762\u4E0D\u5B58\u5728",-1)),F=u({__name:"404",setup(e){const o=g(),c=d(),_=r();function n(){o.closeCurrentTab(_),c.push("/")}return(I,N)=>{const a=m;return f(),p("div",w,[t("div",y,[t("div",C,[E,t("div",S,[V,k,i(a,{class:"subBtn",type:"info",onClick:n},{default:l(()=>[x("\u56DE\u5230\u9996\u9875")]),_:1})])])])])}}});const z=B(F,[["__scopeId","data-v-d1dd2068"]]);export{z as default};

+ 1 - 1
dist/assets/Cascader.85b68ac2.js → dist/assets/Cascader.a84e948d.js

@@ -1,4 +1,4 @@
-import{cj as B,ck as pt,d as re,cl as bt,aQ as E,r as R,C as yt,bi as d,a2 as xe,cm as wt,D as Se,F as h,cn as ce,co as kt,cp as $e,cq as Rt,cr as Ct,m as xt,cs as Pe,ct as St,cu as Mt,cv as he,cw as Tt,H as qe,cx as We,cy as Qe,cz as Nt,cA as Ft,N as Pt,cB as Ot,cC as Ge,cD as Kt,cE as fe,cF as je,cG as ke,cH as Q,cI as _t,cJ as Je,cK as Lt,cL as De,cM as It,cN as Ce,aE as Bt,M as Ee,O as At,cO as Vt,cP as zt,cQ as $t,cR as jt,cS as Dt,cT as Ue,cU as Et,cV as Ut,cW as Ht,cX as qt,cY as Wt,cZ as ee,U as Qt}from"./index.789dd106.js";const Gt=B("base-menu-mask",`
+import{cj as B,ck as pt,d as re,cl as bt,aQ as E,r as R,C as yt,bi as d,a2 as xe,cm as wt,D as Se,F as h,cn as ce,co as kt,cp as $e,cq as Rt,cr as Ct,m as xt,cs as Pe,ct as St,cu as Mt,cv as he,cw as Tt,H as qe,cx as We,cy as Qe,cz as Nt,cA as Ft,N as Pt,cB as Ot,cC as Ge,cD as Kt,cE as fe,cF as je,cG as ke,cH as Q,cI as _t,cJ as Je,cK as Lt,cL as De,cM as It,cN as Ce,aE as Bt,M as Ee,O as At,cO as Vt,cP as zt,cQ as $t,cR as jt,cS as Dt,cT as Ue,cU as Et,cV as Ut,cW as Ht,cX as qt,cY as Wt,cZ as ee,U as Qt}from"./index.1f2ecc91.js";const Gt=B("base-menu-mask",`
  position: absolute;
  left: 0;
  right: 0;

+ 1 - 1
dist/assets/DeleteFilled.12f6975e.js → dist/assets/DeleteFilled.2a3b3066.js

@@ -1 +1 @@
-import{d as e,f as t,g as o,o as c}from"./index.789dd106.js";const n={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 1024 1024"},l=o("path",{d:"M864 256H736v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zm-200 0H360v-72h304v72z",fill:"currentColor"},null,-1),s=[l],h=e({name:"DeleteFilled",render:function(i,a){return c(),t("svg",n,s)}});export{h as D};
+import{d as e,f as t,g as o,o as c}from"./index.1f2ecc91.js";const n={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 1024 1024"},l=o("path",{d:"M864 256H736v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zm-200 0H360v-72h304v72z",fill:"currentColor"},null,-1),s=[l],h=e({name:"DeleteFilled",render:function(i,a){return c(),t("svg",n,s)}});export{h as D};

+ 1 - 1
dist/assets/FormItemGridItem.266fd41a.js → dist/assets/FormItemGridItem.930c3242.js

@@ -1 +1 @@
-import{d as a,r as n,bi as r,dc as o,dd as i,l as m,de as d,ad as p,df as f,dg as l}from"./index.789dd106.js";const I=Object.assign(Object.assign({},f),l),g=a({__GRID_ITEM__:!0,name:"FormItemGridItem",alias:["FormItemGi"],props:I,setup(){const e=n(null);return{formItemInstRef:e,validate:(...t)=>{const{value:s}=e;if(s)return s.validate(...t)},restoreValidation:()=>{const{value:t}=e;t&&t.restoreValidation()}}},render(){return r(p,o(this.$.vnode.props||{},d),{default:()=>{const e=o(this.$props,i);return r(m,Object.assign({ref:"formItemInstRef"},e),this.$slots)}})}});export{g as N};
+import{d as a,r as n,bi as r,dc as o,dd as i,l as m,de as d,ad as p,df as f,dg as l}from"./index.1f2ecc91.js";const I=Object.assign(Object.assign({},f),l),g=a({__GRID_ITEM__:!0,name:"FormItemGridItem",alias:["FormItemGi"],props:I,setup(){const e=n(null);return{formItemInstRef:e,validate:(...t)=>{const{value:s}=e;if(s)return s.validate(...t)},restoreValidation:()=>{const{value:t}=e;t&&t.restoreValidation()}}},render(){return r(p,o(this.$.vnode.props||{},d),{default:()=>{const e=o(this.$props,i);return r(m,Object.assign({ref:"formItemInstRef"},e),this.$slots)}})}});export{g as N};

+ 1 - 1
dist/assets/PageHeader.0c76ed3e.js → dist/assets/PageHeader.e8f5b4e1.js

@@ -1,4 +1,4 @@
-import{d as S,bi as e,cE as l,cj as z,cG as i,cI as _,cJ as y,dt as $,du as H,F as P,cP as R,cp as B}from"./index.789dd106.js";const E=S({name:"ArrowBack",render(){return e("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},e("path",{d:"M0 0h24v24H0V0z",fill:"none"}),e("path",{d:"M19 11H7.83l4.88-4.88c.39-.39.39-1.03 0-1.42-.39-.39-1.02-.39-1.41 0l-6.59 6.59c-.39.39-.39 1.02 0 1.41l6.59 6.59c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L7.83 13H19c.55 0 1-.45 1-1s-.45-1-1-1z"}))}}),T=l([z("page-header-header",`
+import{d as S,bi as e,cE as l,cj as z,cG as i,cI as _,cJ as y,dt as $,du as H,F as P,cP as R,cp as B}from"./index.1f2ecc91.js";const E=S({name:"ArrowBack",render(){return e("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},e("path",{d:"M0 0h24v24H0V0z",fill:"none"}),e("path",{d:"M19 11H7.83l4.88-4.88c.39-.39.39-1.03 0-1.42-.39-.39-1.02-.39-1.41 0l-6.59 6.59c-.39.39-.39 1.02 0 1.41l6.59 6.59c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L7.83 13H19c.55 0 1-.45 1-1s-.45-1-1-1z"}))}}),T=l([z("page-header-header",`
  margin-bottom: 20px;
  `),z("page-header",`
  display: flex;

+ 1 - 1
dist/assets/TreeSelect.037ea33e.js → dist/assets/TreeSelect.6e5c1d79.js

@@ -1,4 +1,4 @@
-import{c_ as je,G as ze,c$ as De,d0 as $e,d1 as We,cE as He,cj as U,cG as ne,cF as Ge,d as Qe,r as v,cI as Je,cK as Xe,cM as Ze,aQ as _,cL as V,F as c,O as qe,d2 as Ye,cw as et,d3 as tt,cJ as oe,cP as nt,cN as j,cO as at,bi as u,cQ as lt,cR as ot,cS as rt,cT as it,a2 as dt,H as st,cx as ct,d4 as ut,cy as ht,cz as ft,cA as gt,d5 as mt,cC as vt,d6 as yt,cZ as p,cW as bt,cX as pt,cs as St,N as wt}from"./index.789dd106.js";const xt=t=>{const{popoverColor:h,boxShadow2:i,borderRadius:s,heightMedium:d,dividerColor:y,textColor2:C}=t;return{menuPadding:"4px",menuColor:h,menuBoxShadow:i,menuBorderRadius:s,menuHeight:`calc(${d} * 7.6)`,actionDividerColor:y,actionTextColor:C,actionPadding:"8px 12px"}},kt=je({name:"TreeSelect",common:ze,peers:{Tree:De,Empty:$e,InternalSelection:We},self:xt}),Tt=kt;function ae(t,h){const{rawNode:i}=t;return Object.assign(Object.assign({},i),{label:i[h],value:t.key})}function le(t,h,i,s){const{rawNode:d}=t;return Object.assign(Object.assign({},d),{value:t.key,label:h.map(y=>y.rawNode[s]).join(i)})}const Kt=He([U("tree-select",`
+import{c_ as je,G as ze,c$ as De,d0 as $e,d1 as We,cE as He,cj as U,cG as ne,cF as Ge,d as Qe,r as v,cI as Je,cK as Xe,cM as Ze,aQ as _,cL as V,F as c,O as qe,d2 as Ye,cw as et,d3 as tt,cJ as oe,cP as nt,cN as j,cO as at,bi as u,cQ as lt,cR as ot,cS as rt,cT as it,a2 as dt,H as st,cx as ct,d4 as ut,cy as ht,cz as ft,cA as gt,d5 as mt,cC as vt,d6 as yt,cZ as p,cW as bt,cX as pt,cs as St,N as wt}from"./index.1f2ecc91.js";const xt=t=>{const{popoverColor:h,boxShadow2:i,borderRadius:s,heightMedium:d,dividerColor:y,textColor2:C}=t;return{menuPadding:"4px",menuColor:h,menuBoxShadow:i,menuBorderRadius:s,menuHeight:`calc(${d} * 7.6)`,actionDividerColor:y,actionTextColor:C,actionPadding:"8px 12px"}},kt=je({name:"TreeSelect",common:ze,peers:{Tree:De,Empty:$e,InternalSelection:We},self:xt}),Tt=kt;function ae(t,h){const{rawNode:i}=t;return Object.assign(Object.assign({},i),{label:i[h],value:t.key})}function le(t,h,i,s){const{rawNode:d}=t;return Object.assign(Object.assign({},d),{value:t.key,label:h.map(y=>y.rawNode[s]).join(i)})}const Kt=He([U("tree-select",`
  z-index: auto;
  outline: none;
  width: 100%;

+ 1 - 1
dist/assets/api.3d694ea1.js → dist/assets/api.39f82c79.js

@@ -1 +1 @@
-import{ab as a}from"./index.789dd106.js";const t=s=>a({url:"/cbs-app/sysApplication/page",method:"post",data:s});export{t as s};
+import{ab as a}from"./index.1f2ecc91.js";const t=s=>a({url:"/cbs-app/sysApplication/page",method:"post",data:s});export{t as s};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/api.3d30ce7e.js


+ 1 - 1
dist/assets/api.03a83426.js → dist/assets/api.4006f814.js

@@ -1 +1 @@
-var m=Object.defineProperty,i=Object.defineProperties;var c=Object.getOwnPropertyDescriptors;var o=Object.getOwnPropertySymbols;var u=Object.prototype.hasOwnProperty,d=Object.prototype.propertyIsEnumerable;var s=(a,e,t)=>e in a?m(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,p=(a,e)=>{for(var t in e||(e={}))u.call(e,t)&&s(a,t,e[t]);if(o)for(var t of o(e))d.call(e,t)&&s(a,t,e[t]);return a},l=(a,e)=>i(a,c(e));import{ab as r,dn as n}from"./index.789dd106.js";const b=a=>r({url:"/cbs-app/material/page",method:"post",data:a}),y=a=>new Promise(e=>{r({url:"/cbs-app/materialCategory/page",method:"post",data:l(p({},a),{rows:1e3})}).then(t=>{t!=null&&t.data&&(t.data.rows=n(t.data.rows,"subMaterialCategoryList"),e(t))}).catch(()=>{e({})})}),C=a=>r({url:"/cbs-app/material/save",method:"post",data:a}),v=a=>r({url:"/cbs-app/material/remove?id="+a,method:"post"}),f=a=>r({url:`/cbs-app/material/detail/${a}`,method:"get"}),M=a=>r({url:"/cbs-app/material/update",method:"post",data:a}),w=a=>r({url:"/cbs-app/materialCategory/page",method:"post",data:a}),D=a=>r({url:"/cbs-app/materialCategory/save",method:"post",data:a}),L=a=>r({url:"/cbs-app/materialCategory/remove?id="+a,method:"post"}),P=a=>r({url:"/cbs-app/materialCategory/update",method:"post",data:a});export{D as a,w as b,L as c,C as d,y as e,f,b as g,v as h,P as m,M as u};
+var m=Object.defineProperty,i=Object.defineProperties;var c=Object.getOwnPropertyDescriptors;var o=Object.getOwnPropertySymbols;var u=Object.prototype.hasOwnProperty,d=Object.prototype.propertyIsEnumerable;var s=(a,e,t)=>e in a?m(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t,p=(a,e)=>{for(var t in e||(e={}))u.call(e,t)&&s(a,t,e[t]);if(o)for(var t of o(e))d.call(e,t)&&s(a,t,e[t]);return a},l=(a,e)=>i(a,c(e));import{ab as r,dn as n}from"./index.1f2ecc91.js";const b=a=>r({url:"/cbs-app/material/page",method:"post",data:a}),y=a=>new Promise(e=>{r({url:"/cbs-app/materialCategory/page",method:"post",data:l(p({},a),{rows:1e3})}).then(t=>{t!=null&&t.data&&(t.data.rows=n(t.data.rows,"subMaterialCategoryList"),e(t))}).catch(()=>{e({})})}),C=a=>r({url:"/cbs-app/material/save",method:"post",data:a}),v=a=>r({url:"/cbs-app/material/remove?id="+a,method:"post"}),f=a=>r({url:`/cbs-app/material/detail/${a}`,method:"get"}),M=a=>r({url:"/cbs-app/material/update",method:"post",data:a}),w=a=>r({url:"/cbs-app/materialCategory/page",method:"post",data:a}),D=a=>r({url:"/cbs-app/materialCategory/save",method:"post",data:a}),L=a=>r({url:"/cbs-app/materialCategory/remove?id="+a,method:"post"}),P=a=>r({url:"/cbs-app/materialCategory/update",method:"post",data:a});export{D as a,w as b,L as c,C as d,y as e,f,b as g,v as h,P as m,M as u};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/api.6040327b.js


+ 1 - 1
dist/assets/api.abb70d8c.js → dist/assets/api.62e040f2.js

@@ -1 +1 @@
-import{ab as s}from"./index.789dd106.js";const a=t=>s({url:"/cbs-app/sysMenuButton/page",method:"post",data:t}),u=t=>s({url:"/cbs-app/sysMenuButton/save",method:"post",data:t}),o=t=>s({url:"/cbs-app/sysMenuButton/update",method:"post",data:t}),n=t=>s({url:"/cbs-app/sysMenuButton/remove",method:"post",data:t,requestType:"form"}),p=t=>s({url:"/cbs-app/musicTag/page",method:"post",data:t}),r=t=>s({url:"/cbs-app/musicSheet/page",method:"post",data:t});export{o as a,a as b,n as c,p as d,r as m,u as s};
+import{ab as s}from"./index.1f2ecc91.js";const a=t=>s({url:"/cbs-app/sysMenuButton/page",method:"post",data:t}),u=t=>s({url:"/cbs-app/sysMenuButton/save",method:"post",data:t}),o=t=>s({url:"/cbs-app/sysMenuButton/update",method:"post",data:t}),n=t=>s({url:"/cbs-app/sysMenuButton/remove",method:"post",data:t,requestType:"form"}),p=t=>s({url:"/cbs-app/musicTag/page",method:"post",data:t}),r=t=>s({url:"/cbs-app/musicSheet/page",method:"post",data:t});export{o as a,a as b,n as c,p as d,r as m,u as s};

+ 1 - 1
dist/assets/api.1acf39e1.js → dist/assets/api.a1ab0d47.js

@@ -1 +1 @@
-import{ab as e}from"./index.789dd106.js";const r=s=>e({url:"/cbs-app/sysUserLoginLog/page",method:"post",data:s}),t=s=>e({url:"/cbs-app/sysUserLogin/page",method:"post",data:s}),o=s=>e({url:"/cbs-app/sysUserDevice/page",method:"post",data:s}),p=s=>e({url:"/cbs-app/sysUserAuditLog/page",method:"post",data:s});export{t as a,o as b,p as c,r as s};
+import{ab as e}from"./index.1f2ecc91.js";const r=s=>e({url:"/cbs-app/sysUserLoginLog/page",method:"post",data:s}),t=s=>e({url:"/cbs-app/sysUserLogin/page",method:"post",data:s}),o=s=>e({url:"/cbs-app/sysUserDevice/page",method:"post",data:s}),p=s=>e({url:"/cbs-app/sysUserAuditLog/page",method:"post",data:s});export{t as a,o as b,p as c,r as s};

+ 1 - 1
dist/assets/api.ac6a3c33.js → dist/assets/api.b003d277.js

@@ -1 +1 @@
-import{ab as t}from"./index.789dd106.js";const a=e=>t({url:"/cbs-app/knowledgePoint/page",method:"post",data:e}),n=e=>t({url:"/cbs-app/knowledgePoint/save",method:"post",data:e}),l=e=>t({url:"/cbs-app/knowledgePoint/remove?id="+e,method:"post"}),r=e=>t({url:"/cbs-app/knowledgePoint/update",method:"post",data:e}),s=e=>t({url:"/cbs-app/knowledgePointMaterialRelation/page",method:"post",data:e}),i=e=>t({url:"/cbs-app/knowledgePointMaterialRelation/update",method:"post",data:e}),p=e=>t({url:"/cbs-app/knowledgePointMaterialRelation/remove",method:"post",data:e}),d=e=>t({url:"/cbs-app/knowledgePointMaterialRelation/materialPage",method:"post",data:e}),g=e=>t({url:"/cbs-app/knowledgePointMaterialRelation/save",method:"post",data:e}),c=e=>t({url:`/cbs-app/knowledgePoint/status?id=${e}`,method:"post"});export{n as a,c as b,l as c,g as d,d as e,a as f,s as g,p as h,i,r as k};
+import{ab as t}from"./index.1f2ecc91.js";const a=e=>t({url:"/cbs-app/knowledgePoint/page",method:"post",data:e}),n=e=>t({url:"/cbs-app/knowledgePoint/save",method:"post",data:e}),l=e=>t({url:"/cbs-app/knowledgePoint/remove?id="+e,method:"post"}),r=e=>t({url:"/cbs-app/knowledgePoint/update",method:"post",data:e}),s=e=>t({url:"/cbs-app/knowledgePointMaterialRelation/page",method:"post",data:e}),i=e=>t({url:"/cbs-app/knowledgePointMaterialRelation/update",method:"post",data:e}),p=e=>t({url:"/cbs-app/knowledgePointMaterialRelation/remove",method:"post",data:e}),d=e=>t({url:"/cbs-app/knowledgePointMaterialRelation/materialPage",method:"post",data:e}),g=e=>t({url:"/cbs-app/knowledgePointMaterialRelation/save",method:"post",data:e}),c=e=>t({url:`/cbs-app/knowledgePoint/status?id=${e}`,method:"post"});export{n as a,c as b,l as c,g as d,d as e,a as f,s as g,p as h,i,r as k};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/api.d71d4abc.js


+ 1 - 1
dist/assets/api.32da9f90.js → dist/assets/api.e513d6d6.js

@@ -1 +1 @@
-import{ab as e}from"./index.789dd106.js";const a=t=>e({url:"/cbs-app/musicalInstrument/page",method:"post",data:t}),u=t=>e({url:"/cbs-app/musicalInstrument/queryNotRelated",method:"post",data:t}),r=t=>e({url:"/cbs-app/musicalInstrument/save",method:"post",data:t}),c=t=>e({url:"/cbs-app/musicalInstrument/update",method:"post",data:t}),p=t=>e({url:"/cbs-app/musicalInstrument/enable?id="+t.id,method:"post",data:t}),o=t=>e({url:"/cbs-app/subjectCategory/page",method:"post",data:t}),n=t=>e({url:"/cbs-app/subjectCategory/save",method:"post",data:t}),m=t=>e({url:"/cbs-app/subjectCategory/update",method:"post",data:t}),b=t=>e({url:"/cbs-app/subject/page",method:"post",data:t}),l=t=>e({url:"/cbs-app/subject/save",method:"post",data:t}),d=t=>e({url:"/cbs-app/subject/update",method:"post",data:t}),i=t=>e({url:"/cbs-app/subject/enable",method:"post",requestType:"form",data:t});export{d as a,o as b,a as c,b as d,i as e,n as f,m as g,r as h,c as i,p as j,u as m,l as s};
+import{ab as e}from"./index.1f2ecc91.js";const a=t=>e({url:"/cbs-app/musicalInstrument/page",method:"post",data:t}),u=t=>e({url:"/cbs-app/musicalInstrument/queryNotRelated",method:"post",data:t}),r=t=>e({url:"/cbs-app/musicalInstrument/save",method:"post",data:t}),c=t=>e({url:"/cbs-app/musicalInstrument/update",method:"post",data:t}),p=t=>e({url:"/cbs-app/musicalInstrument/enable?id="+t.id,method:"post",data:t}),o=t=>e({url:"/cbs-app/subjectCategory/page",method:"post",data:t}),n=t=>e({url:"/cbs-app/subjectCategory/save",method:"post",data:t}),m=t=>e({url:"/cbs-app/subjectCategory/update",method:"post",data:t}),b=t=>e({url:"/cbs-app/subject/page",method:"post",data:t}),l=t=>e({url:"/cbs-app/subject/save",method:"post",data:t}),d=t=>e({url:"/cbs-app/subject/update",method:"post",data:t}),i=t=>e({url:"/cbs-app/subject/enable",method:"post",requestType:"form",data:t});export{d as a,o as b,a as c,b as d,i as e,n as f,m as g,r as h,c as i,p as j,u as m,l as s};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/constant.d4a76877.js


+ 1 - 1
dist/assets/dateUtil.862a46f3.js → dist/assets/dateUtil.163360e3.js

@@ -1 +1 @@
-import{d as a}from"./dayjs.min.61ba4767.js";const l=(r,d=[],Y="YYYY-MM-DD")=>r&&r.length?Y=="YYYY-MM-DD"?{[d[0]||"start"]:a(r[0]).isValid()?a(r[0]).format(Y)+" 00:00:00":"",[d[1]||"end"]:a(r[1]).isValid()?a(r[1]).format(Y)+" 23:59:59":""}:{[d[0]||"start"]:a(r[0]).isValid()?a(r[0]).format(Y):"",[d[1]||"end"]:a(r[1]).isValid()?a(r[1]).format(Y):""}:{},f=(r,d=[],Y="YYYY-MM-DD")=>r&&r.length?{[d[0]||"start"]:a(r[0]).isValid()?a(r[0]).format(Y):"",[d[1]||"end"]:a(r[1]).isValid()?a(r[1]).format(Y):""}:{};export{f,l as g};
+import{d as a}from"./dayjs.min.d91a859a.js";const l=(r,d=[],Y="YYYY-MM-DD")=>r&&r.length?Y=="YYYY-MM-DD"?{[d[0]||"start"]:a(r[0]).isValid()?a(r[0]).format(Y)+" 00:00:00":"",[d[1]||"end"]:a(r[1]).isValid()?a(r[1]).format(Y)+" 23:59:59":""}:{[d[0]||"start"]:a(r[0]).isValid()?a(r[0]).format(Y):"",[d[1]||"end"]:a(r[1]).isValid()?a(r[1]).format(Y):""}:{},f=(r,d=[],Y="YYYY-MM-DD")=>r&&r.length?{[d[0]||"start"]:a(r[0]).isValid()?a(r[0]).format(Y):"",[d[1]||"end"]:a(r[1]).isValid()?a(r[1]).format(Y):""}:{};export{f,l as g};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/dayjs.min.d91a859a.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/detail.28813d04.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/editAndUpdate.796e5b9d.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/employee-tab.5c70792d.js


+ 1 - 1
dist/assets/filters.de6e9e5f.js → dist/assets/filters.21e6bf24.js

@@ -1 +1 @@
-import{p as t,e,c as s,o as n,a as o}from"./constant.ded25e36.js";const l=(r,i)=>{if(r&&i){let u=i.get(r);if(u)return u}return r},f=r=>r&&t&&t[r]?t[r]:r,c=r=>r&&e&&e[r]?e[r]:r,p=r=>r&&s&&s[r]?s[r]:r,m=r=>{if(r&&n&&n[r])return n[r]},T=r=>r&&o&&o[r]?o[r]:r;export{c as a,f as b,m as c,T as d,p as f,l as g};
+import{p as t,e,c as s,o as n,a as o}from"./constant.d4a76877.js";const l=(r,i)=>{if(r&&i){let u=i.get(r);if(u)return u}return r},f=r=>r&&t&&t[r]?t[r]:r,c=r=>r&&e&&e[r]?e[r]:r,p=r=>r&&s&&s[r]?s[r]:r,m=r=>{if(r&&n&&n[r])return n[r]},T=r=>r&&o&&o[r]?o[r]:r;export{c as a,f as b,m as c,T as d,p as f,l as g};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.0450a810.js


+ 1 - 1
dist/assets/index.70371ae0.js → dist/assets/index.07713f87.js

@@ -1 +1 @@
-import{S as l}from"./searchs.b637f0d6.js";import{d as y,e as h,a as m,r as z,B as v,bx as w,M as s,F as K,i as P,ci as b}from"./index.789dd106.js";const x=y({name:"table-container",props:{page:{type:Number,default:1,required:!0},pageSize:{type:Number,default:10},pageTotal:{type:Number,default:0},saveKey:{type:String,default:""},sync:{type:Boolean,default:!1},checkedRowKeysRef:{type:Object},pageSizes:{type:Array,default:()=>[10,20,30,40]},pageSlot:{type:Number,default:9}},emits:["update:page","update:pageSize","list"],setup(e,{slots:T,attrs:k,emit:t}){const o=h(),u=m({pageInformation:null}),g=z(0);g.value=Math.ceil(e.pageTotal/e.pageSize);const d=a=>{t("update:page",a),t("list"),i()},r=a=>{t("update:pageSize",a),t("list"),i()};v(()=>{if(e.sync){const a=new l(e.saveKey||o.path),n=a.get(e.saveKey||o.path);if(u.pageInformation=n,n&&n.page){for(const p in n.page)if(n.page.hasOwnProperty(p)&&["page","pageSize"].includes(p)){const f=n.page[p],S=`update:${p}`;t(S,f)}}e.saveKey&&a.update(o.path,void 0,"bind")}window.addEventListener("watchStorage",c)}),w(()=>{window.removeEventListener("watchStorage",c)}),s(()=>e.pageSize,()=>{g.value=Math.ceil(e.pageTotal/e.pageSize),i()}),s(()=>e.page,()=>{i()}),s(()=>e.pageTotal,()=>{g.value=Math.ceil(e.pageTotal/e.pageSize),i()}),K({get(){return e.page},set(a){t("update:page",a)}});const i=()=>{e.sync&&new l(e.saveKey||o.path).update({page:e.page,pageCount:g.value,pageSize:e.pageSize,saveKey:e.saveKey},void 0,"page")},c=()=>{let a=u.pageInformation&&u.pageInformation.page?u.pageInformation.page:null;a&&a.page&&a.page};return()=>P(b,{style:{marginTop:"12px",justifyContent:"flex-end"},page:e.page,"onUpdate:page":a=>e.page=a,displayOrder:["quick-jumper","pages","size-picker"],pageCount:g.value,showQuickJumper:!0,showSizePicker:!0,pageSize:e.pageSize,prefix:()=>`\u5171 ${e.pageTotal} \u6761`,pageSizes:e.pageSizes,onUpdatePage:d,onUpdatePageSize:r,pageSlot:e.pageSlot},null)}});export{x as P};
+import{S as l}from"./searchs.b637f0d6.js";import{d as y,e as h,a as m,r as z,B as v,bx as w,M as s,F as K,i as P,ci as b}from"./index.1f2ecc91.js";const x=y({name:"table-container",props:{page:{type:Number,default:1,required:!0},pageSize:{type:Number,default:10},pageTotal:{type:Number,default:0},saveKey:{type:String,default:""},sync:{type:Boolean,default:!1},checkedRowKeysRef:{type:Object},pageSizes:{type:Array,default:()=>[10,20,30,40]},pageSlot:{type:Number,default:9}},emits:["update:page","update:pageSize","list"],setup(e,{slots:T,attrs:k,emit:t}){const o=h(),u=m({pageInformation:null}),g=z(0);g.value=Math.ceil(e.pageTotal/e.pageSize);const d=a=>{t("update:page",a),t("list"),i()},r=a=>{t("update:pageSize",a),t("list"),i()};v(()=>{if(e.sync){const a=new l(e.saveKey||o.path),n=a.get(e.saveKey||o.path);if(u.pageInformation=n,n&&n.page){for(const p in n.page)if(n.page.hasOwnProperty(p)&&["page","pageSize"].includes(p)){const f=n.page[p],S=`update:${p}`;t(S,f)}}e.saveKey&&a.update(o.path,void 0,"bind")}window.addEventListener("watchStorage",c)}),w(()=>{window.removeEventListener("watchStorage",c)}),s(()=>e.pageSize,()=>{g.value=Math.ceil(e.pageTotal/e.pageSize),i()}),s(()=>e.page,()=>{i()}),s(()=>e.pageTotal,()=>{g.value=Math.ceil(e.pageTotal/e.pageSize),i()}),K({get(){return e.page},set(a){t("update:page",a)}});const i=()=>{e.sync&&new l(e.saveKey||o.path).update({page:e.page,pageCount:g.value,pageSize:e.pageSize,saveKey:e.saveKey},void 0,"page")},c=()=>{let a=u.pageInformation&&u.pageInformation.page?u.pageInformation.page:null;a&&a.page&&a.page};return()=>P(b,{style:{marginTop:"12px",justifyContent:"flex-end"},page:e.page,"onUpdate:page":a=>e.page=a,displayOrder:["quick-jumper","pages","size-picker"],pageCount:g.value,showQuickJumper:!0,showSizePicker:!0,pageSize:e.pageSize,prefix:()=>`\u5171 ${e.pageTotal} \u6761`,pageSizes:e.pageSizes,onUpdatePage:d,onUpdatePageSize:r,pageSlot:e.pageSlot},null)}});export{x as P};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.18179f0a.css


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.182b913f.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.1f2ecc91.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.223858a6.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.291ec3fd.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.2f0cd39f.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.2ffb0350.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.3881fe62.css


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.3ee668c4.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.447dac53.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.48bca030.js


+ 1 - 1
dist/assets/index.b24e8dc3.js → dist/assets/index.4bb1e398.js

@@ -1 +1 @@
-import{d as g,r as K,e as w,a as F,M as m,B as _,i,q as M,bp as P}from"./index.789dd106.js";import{S}from"./searchs.b637f0d6.js";const I="_saveForm_1s8vz_1",E={saveForm:I},D=g({name:"save-form",props:{model:{type:Object,default:{}},saveKey:{type:String,default:""}},emits:["setModel","submit","reset"],setup(o,{slots:d,attrs:c,emit:n,expose:l}){const u=K(),r=w(),t=F({searchs:null,saveKey:o.saveKey,model:{}}),f=()=>{const e=o.model,s={};for(const a in e)s[a]=null;return s};m(()=>o.saveKey,e=>{t.saveKey=e}),m(()=>o.model,e=>{t.model=e},{deep:!0});const p=()=>{const e=new S(t.saveKey||r.path);t.searchs=e;const s=e.get(t.saveKey||r.path);for(const a in s.form)if(s.form.hasOwnProperty(a)){const b=s.form[a];t.model[a]=b}n("setModel",t.model),t.saveKey&&t.searchs.update(r.path,void 0,"bind")};_(()=>{p()});const h=e=>{e&&(e.stopPropagation(),e.stopImmediatePropagation(),e.preventDefault()),t.saveKey&&t.searchs.update(r.path,void 0,"bind"),t.searchs.update(t.model,void 0,"form"),n("submit",e)},v=e=>{e&&(e.stopPropagation(),e.stopImmediatePropagation(),e.preventDefault());let s=new Event("watchStorage");window.dispatchEvent(s),y(),n("submit",e)},y=()=>{n("setModel",f()),t.searchs.update({},void 0,"form"),t.searchs.update({},void 0,"page")};return l({submit:h,reset:v}),()=>i("div",{class:["section-container section-save-form",E.saveForm]},[i(M,P({model:t.model,ref:u,inline:!0,"label-placement":"left","label-width":"auto"},c),{default:()=>[d.default&&d.default()]})])}});export{D as S};
+import{d as g,r as K,e as w,a as F,M as m,B as _,i,q as M,bp as P}from"./index.1f2ecc91.js";import{S}from"./searchs.b637f0d6.js";const I="_saveForm_1s8vz_1",E={saveForm:I},D=g({name:"save-form",props:{model:{type:Object,default:{}},saveKey:{type:String,default:""}},emits:["setModel","submit","reset"],setup(o,{slots:d,attrs:c,emit:n,expose:l}){const u=K(),r=w(),t=F({searchs:null,saveKey:o.saveKey,model:{}}),f=()=>{const e=o.model,s={};for(const a in e)s[a]=null;return s};m(()=>o.saveKey,e=>{t.saveKey=e}),m(()=>o.model,e=>{t.model=e},{deep:!0});const p=()=>{const e=new S(t.saveKey||r.path);t.searchs=e;const s=e.get(t.saveKey||r.path);for(const a in s.form)if(s.form.hasOwnProperty(a)){const b=s.form[a];t.model[a]=b}n("setModel",t.model),t.saveKey&&t.searchs.update(r.path,void 0,"bind")};_(()=>{p()});const h=e=>{e&&(e.stopPropagation(),e.stopImmediatePropagation(),e.preventDefault()),t.saveKey&&t.searchs.update(r.path,void 0,"bind"),t.searchs.update(t.model,void 0,"form"),n("submit",e)},v=e=>{e&&(e.stopPropagation(),e.stopImmediatePropagation(),e.preventDefault());let s=new Event("watchStorage");window.dispatchEvent(s),y(),n("submit",e)},y=()=>{n("setModel",f()),t.searchs.update({},void 0,"form"),t.searchs.update({},void 0,"page")};return l({submit:h,reset:v}),()=>i("div",{class:["section-container section-save-form",E.saveForm]},[i(M,P({model:t.model,ref:u,inline:!0,"label-placement":"left","label-width":"auto"},c),{default:()=>[d.default&&d.default()]})])}});export{D as S};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.5136035f.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.5e5a1871.js


+ 1 - 1
dist/assets/index.9c53d834.js → dist/assets/index.6797b13e.js

@@ -1 +1 @@
-import{d as s,e as n,c as u,x as c,i as p,N as i}from"./index.789dd106.js";const l=s({name:"Redirect",setup(){const t=n(),o=u();return c(()=>{const{params:r,query:a}=t,{path:e}=r;o.replace({path:"/"+(Array.isArray(e)?e.join("/"):e),query:a})}),()=>p(i,null,null)}});export{l as default};
+import{d as s,e as n,c as u,x as c,i as p,N as i}from"./index.1f2ecc91.js";const l=s({name:"Redirect",setup(){const t=n(),o=u();return c(()=>{const{params:r,query:a}=t,{path:e}=r;o.replace({path:"/"+(Array.isArray(e)?e.join("/"):e),query:a})}),()=>p(i,null,null)}});export{l as default};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.6807fcf7.js


+ 1 - 0
dist/assets/index.686af97c.js

@@ -0,0 +1 @@
+import{d as m,e as p,r as t,h as s,B as v,Y as h,w as x,U as g,dk as k,o as b,g as u,t as w}from"./index.1f2ecc91.js";const B={class:"frame"},R=["src"],y=m({__name:"index",setup(S){var f,i;const o=p(),a=t(!1),c=t(null),r=t("");(f=s(o.meta))!=null&&f.frameSrc&&(r.value=(i=s(o.meta))==null?void 0:i.frameSrc);function _(){a.value=!1}function l(){g(()=>{const e=s(c);if(!e)return;const n=e;n.attachEvent?n.attachEvent("onload",()=>{_()}):e.onload=()=>{_()}})}return v(()=>{a.value=!0,l()}),(e,n)=>{const d=k;return b(),h(d,{show:a.value},{default:x(()=>[u("div",B,[u("iframe",{src:r.value,class:"frame-iframe",ref_key:"frameRef",ref:c},null,8,R)])]),_:1},8,["show"])}}});const E=w(y,[["__scopeId","data-v-86b4e8ba"]]);export{E as default};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.68c8370b.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.69246979.css


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.6a14fb5d.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.746842da.css


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.7b72b78d.js


+ 0 - 1
dist/assets/index.7e338cc1.css

@@ -1 +0,0 @@
-.frame[data-v-508d955d]{width:100%;height:100vh}.frame-iframe[data-v-508d955d]{width:100%;height:100%;overflow:hidden;border:0;box-sizing:border-box}

+ 1 - 0
dist/assets/index.88a710bb.css

@@ -0,0 +1 @@
+.frame[data-v-86b4e8ba]{width:100%;height:100vh}.frame-iframe[data-v-86b4e8ba]{width:100%;height:100%;overflow:hidden;border:0;box-sizing:border-box}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.8bdcdb3c.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.8c438324.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.8d91b63e.js


+ 1 - 1
dist/assets/index.a0bcdc8a.js → dist/assets/index.957f0ce3.js

@@ -1 +1 @@
-import{d as o,L as s,F as i,i as d,ds as f}from"./index.789dd106.js";import{u as l}from"./tabsView.ce4b9104.js";const g=o({name:"TheLink",props:{to:{type:Object,default:{}},target:{type:String,default:"_self"},authLink:{type:String,default:""}},setup(t,{slots:e}){const a=s();l().closeCurrentTab({path:t.to.path});const u=i(()=>{const n=a.getAuths.some(r=>r===t.authLink);return!!(t.authLink&&!n)});return()=>u.value?e.default&&e.default():d(f,{to:t.to,target:t.target},{default:()=>[e.default&&e.default()]})}});export{g as T};
+import{d as o,L as s,F as i,i as d,ds as f}from"./index.1f2ecc91.js";import{u as l}from"./tabsView.ffd592a9.js";const g=o({name:"TheLink",props:{to:{type:Object,default:{}},target:{type:String,default:"_self"},authLink:{type:String,default:""}},setup(t,{slots:e}){const a=s();l().closeCurrentTab({path:t.to.path});const u=i(()=>{const n=a.getAuths.some(r=>r===t.authLink);return!!(t.authLink&&!n)});return()=>u.value?e.default&&e.default():d(f,{to:t.to,target:t.target},{default:()=>[e.default&&e.default()]})}});export{g as T};

+ 0 - 1
dist/assets/index.9a011606.js

@@ -1 +0,0 @@
-import{d as m,e as p,r as t,h as s,B as v,Y as h,w as x,U as g,dk as k,o as w,g as d,t as B}from"./index.789dd106.js";const R={class:"frame"},y=["src"],S=m({__name:"index",setup(C){var f,i;const o=p(),a=t(!1),c=t(null),r=t("");(f=s(o.meta))!=null&&f.frameSrc&&(r.value=(i=s(o.meta))==null?void 0:i.frameSrc);function _(){a.value=!1}function u(){g(()=>{const e=s(c);if(!e)return;const n=e;n.attachEvent?n.attachEvent("onload",()=>{_()}):e.onload=()=>{_()}})}return v(()=>{a.value=!0,u()}),(e,n)=>{const l=k;return w(),h(l,{show:a.value},{default:x(()=>[d("div",R,[d("iframe",{src:r.value,class:"frame-iframe",ref_key:"frameRef",ref:c},null,8,y)])]),_:1},8,["show"])}}});const I=B(S,[["__scopeId","data-v-508d955d"]]);export{I as default};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.a6d739b8.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.a7ddacb9.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.b39f3ab2.js


+ 1 - 1
dist/assets/index.e0017534.js → dist/assets/index.b9ebd51f.js

@@ -1 +1 @@
-import{d as n,i as e,ao as o,aj as a}from"./index.789dd106.js";const i="_showContentWidth_1uy1t_1",r={showContentWidth:i},d=n({name:"the-tooltip",props:{maxWidth:{type:Number,default:300},showContentWidth:{type:Number,default:120},tipsContent:{type:String,default:""},content:{type:String,default:""},placement:{type:String,default:"top"},showArrow:{type:Boolean,default:!0},trigger:{type:String,default:"hover"}},setup(t){return()=>e(a,null,[e(o,{style:{maxWidth:t.maxWidth+"px"},trigger:t.trigger,placement:t.placement,showArrow:t.showArrow},{trigger:()=>e("p",{style:{maxWidth:t.showContentWidth+"px"},class:r.showContentWidth},[t.content]),default:()=>t.tipsContent||t.content})])}});export{d as T};
+import{d as n,i as e,ao as o,aj as a}from"./index.1f2ecc91.js";const i="_showContentWidth_1uy1t_1",r={showContentWidth:i},d=n({name:"the-tooltip",props:{maxWidth:{type:Number,default:300},showContentWidth:{type:Number,default:120},tipsContent:{type:String,default:""},content:{type:String,default:""},placement:{type:String,default:"top"},showArrow:{type:Boolean,default:!0},trigger:{type:String,default:"hover"}},setup(t){return()=>e(a,null,[e(o,{style:{maxWidth:t.maxWidth+"px"},trigger:t.trigger,placement:t.placement,showArrow:t.showArrow},{trigger:()=>e("p",{style:{maxWidth:t.showContentWidth+"px"},class:r.showContentWidth},[t.content]),default:()=>t.tipsContent||t.content})])}});export{d as T};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.c59e9042.js


+ 1 - 1
dist/assets/index.06e28872.js → dist/assets/index.dfbbfc12.js

@@ -1,4 +1,4 @@
-var Tt=Object.defineProperty,xt=Object.defineProperties;var bt=Object.getOwnPropertyDescriptors;var yt=Object.getOwnPropertySymbols;var At=Object.prototype.hasOwnProperty,Rt=Object.prototype.propertyIsEnumerable;var mt=(o,t,e)=>t in o?Tt(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e,Ct=(o,t)=>{for(var e in t||(t={}))At.call(t,e)&&mt(o,e,t[e]);if(yt)for(var e of yt(t))Rt.call(t,e)&&mt(o,e,t[e]);return o},St=(o,t)=>xt(o,bt(t));var nt=(o,t,e)=>new Promise((n,l)=>{var r=w=>{try{S(e.next(w))}catch(x){l(x)}},u=w=>{try{S(e.throw(w))}catch(x){l(x)}},S=w=>w.done?n(w.value):Promise.resolve(w.value).then(r,u);S((e=e.apply(o,t)).next())});import{d as defineComponent,a as reactive,r as ref,i as createVNode,ac as NGrid,ad as NGi,a9 as NSpace,p as __unplugin_components_3,k as createTextVNode,U as nextTick,cc as commonjsGlobal,cb as getDefaultExportFromCjs,ab as service,u as useMessage,M as watch,cd as NUpload,aa as NModal}from"./index.789dd106.js";/*!
+var Tt=Object.defineProperty,xt=Object.defineProperties;var bt=Object.getOwnPropertyDescriptors;var yt=Object.getOwnPropertySymbols;var At=Object.prototype.hasOwnProperty,Rt=Object.prototype.propertyIsEnumerable;var mt=(o,t,e)=>t in o?Tt(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e,Ct=(o,t)=>{for(var e in t||(t={}))At.call(t,e)&&mt(o,e,t[e]);if(yt)for(var e of yt(t))Rt.call(t,e)&&mt(o,e,t[e]);return o},St=(o,t)=>xt(o,bt(t));var nt=(o,t,e)=>new Promise((n,l)=>{var r=w=>{try{S(e.next(w))}catch(x){l(x)}},u=w=>{try{S(e.throw(w))}catch(x){l(x)}},S=w=>w.done?n(w.value):Promise.resolve(w.value).then(r,u);S((e=e.apply(o,t)).next())});import{d as defineComponent,a as reactive,r as ref,i as createVNode,ac as NGrid,ad as NGi,a9 as NSpace,p as __unplugin_components_3,k as createTextVNode,U as nextTick,cc as commonjsGlobal,cb as getDefaultExportFromCjs,ab as service,u as useMessage,M as watch,cd as NUpload,aa as NModal}from"./index.1f2ecc91.js";/*!
  * Cropper.js v1.5.13
  * https://fengyuanchen.github.io/cropperjs
  *

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.e8a7e66d.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.f6064889.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/index.f82a40aa.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/instrument-list.06c3f8bd.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/interface-log.49934b63.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/musicPreView.e8c7302e.js


+ 1 - 0
dist/assets/musicUtil.3b4f332b.js

@@ -0,0 +1 @@
+import{a as p}from"./objectUtil.ec24ceed.js";import{c as f}from"./constant.d4a76877.js";const g=(a,t)=>{if(t=="PLATFORM")return"--";let n="";if(a){const e=a.applicationName;if(t=="ORG"){const o=a.organizationRole?"-"+a.organizationRole:"";n+=e+o}else if(t=="PERSON"){a!=null&&a.userName&&(n=a.userName);let o=p(a.clientType,new Map(Object.entries(f)));o=o?"-"+o:"",n+=" ("+e+o+")"}}return n},m=(a,t)=>{const n=t.toString();let e=document.querySelector("#copy-input");e||(e=document.createElement("input"),e.id="copy-input",e.readOnly=!0,e.style.position="fixed",e.style.left="-1000px",e.style.zIndex="-1000",document.body.appendChild(e)),e.value=n,o(e,0,n.length),document.execCommand("copy")&&(document.execCommand("copy"),a.success("\u590D\u5236\u6210\u529F")),e.blur();function o(r,l,i){if(r.createTextRange){const c=r.createTextRange();c.collapse(!0),c.moveStart("character",l),c.moveEnd("character",i-l),c.select()}else r.setSelectionRange(l,i),r.focus()}};export{m as c,g};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/musicUtil.99bcdb58.js


+ 1 - 1
dist/assets/parentLayout.7bef9bc2.js → dist/assets/parentLayout.221bde7c.js

@@ -1 +1 @@
-import{t as o,Y as t,W as r,o as n}from"./index.789dd106.js";const c={};function s(a,_){const e=r("router-view");return n(),t(e)}const f=o(c,[["render",s]]);export{f as default};
+import{t as o,Y as t,W as r,o as n}from"./index.1f2ecc91.js";const c={};function s(a,_){const e=r("router-view");return n(),t(e)}const f=o(c,[["render",s]]);export{f as default};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/plan-detail.bc32f46e.js


+ 1 - 1
dist/assets/searchArray.c8aafeb3.js → dist/assets/searchArray.84e16e6c.js

@@ -1 +1 @@
-import{p as o,e as r,s as u,b as n,d as c,c as p,f as y,m as i,g as m,h as l,i as S,o as T,j as d,k as h,l as A,a as g,n as f,q as w,r as E,t as b,u as k,v,w as x,x as q,y as z,z as C,A as F}from"./constant.ded25e36.js";function a(s){let t=[];for(let e in s)t.push({label:s[e],value:e});return t}const K=a(o),N=a(r);a(u);a(n);a(c);a(p);a(y);a(i);a(m);a(l);a(S);const V=a(T);a(d);const j=a(h),B=a(A),D=a(g);a(f);a(w);a(E);a(b);a(k);a(v);a(x);a(q);a(z);a(C);a(F);export{j as a,B as b,D as c,N as e,V as o,K as p};
+import{p as o,e as r,s as u,b as n,d as c,c as p,f as y,m as i,g as m,h as l,i as S,o as T,j as d,k as h,l as A,a as g,n as f,q as w,r as E,t as b,u as k,v,w as x,x as q,y as z,z as C,A as F}from"./constant.d4a76877.js";function a(s){let t=[];for(let e in s)t.push({label:s[e],value:e});return t}const K=a(o),N=a(r);a(u);a(n);a(c);a(p);a(y);a(i);a(m);a(l);a(S);const V=a(T);a(d);const j=a(h),B=a(A),D=a(g);a(f);a(w);a(E);a(b);a(k);a(v);a(x);a(q);a(z);a(C);a(F);export{j as a,B as b,D as c,N as e,V as o,K as p};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/sms-config-app.dcaa639a.js


+ 1 - 1
dist/assets/tabsView.ce4b9104.js → dist/assets/tabsView.ffd592a9.js

@@ -1 +1 @@
-import{v as n}from"./index.789dd106.js";import{S as r}from"./searchs.b637f0d6.js";const b=["Redirect","login"],f=new r("");function o(t){return t.filter(a=>{var s,i;return(i=(s=a==null?void 0:a.meta)==null?void 0:s.affix)!=null?i:!1})}const p=n({id:"app-tabs-view",state:()=>({tabsList:[]}),getters:{},actions:{initTabs(t){this.tabsList=t},addTabs(t){return b.includes(t.name)?!1:(this.tabsList.some(s=>s.path==t.path)||this.tabsList.push(t),!0)},closeLeftTabs(t){const a=this.tabsList.findIndex(s=>s.path==t.path);this.tabsList=this.tabsList.filter((s,i)=>{var e,h;return i>=a||((h=(e=s==null?void 0:s.meta)==null?void 0:e.affix)!=null?h:!1)})},closeRightTabs(t){const a=this.tabsList.findIndex(s=>s.path==t.path);this.tabsList=this.tabsList.filter((s,i)=>{var e,h;return i<=a||((h=(e=s==null?void 0:s.meta)==null?void 0:e.affix)!=null?h:!1)})},closeOtherTabs(t){this.tabsList=this.tabsList.filter(a=>{var s,i;return a.path==t.path||((i=(s=a==null?void 0:a.meta)==null?void 0:s.affix)!=null?i:!1)}),f.removeByOtherRouter(t.path)},closeCurrentTab(t){if(t){f.removeByRouter(t.path);const a=this.tabsList.findIndex(s=>s.path==t.path);a!=-1&&this.tabsList.splice(a,1)}},closeAllTabs(){f.removeAll(),this.tabsList=o(this.tabsList)}}});export{p as u};
+import{v as n}from"./index.1f2ecc91.js";import{S as r}from"./searchs.b637f0d6.js";const b=["Redirect","login"],f=new r("");function o(t){return t.filter(a=>{var s,i;return(i=(s=a==null?void 0:a.meta)==null?void 0:s.affix)!=null?i:!1})}const p=n({id:"app-tabs-view",state:()=>({tabsList:[]}),getters:{},actions:{initTabs(t){this.tabsList=t},addTabs(t){return b.includes(t.name)?!1:(this.tabsList.some(s=>s.path==t.path)||this.tabsList.push(t),!0)},closeLeftTabs(t){const a=this.tabsList.findIndex(s=>s.path==t.path);this.tabsList=this.tabsList.filter((s,i)=>{var e,h;return i>=a||((h=(e=s==null?void 0:s.meta)==null?void 0:e.affix)!=null?h:!1)})},closeRightTabs(t){const a=this.tabsList.findIndex(s=>s.path==t.path);this.tabsList=this.tabsList.filter((s,i)=>{var e,h;return i<=a||((h=(e=s==null?void 0:s.meta)==null?void 0:e.affix)!=null?h:!1)})},closeOtherTabs(t){this.tabsList=this.tabsList.filter(a=>{var s,i;return a.path==t.path||((i=(s=a==null?void 0:a.meta)==null?void 0:s.affix)!=null?i:!1)}),f.removeByOtherRouter(t.path)},closeCurrentTab(t){if(t){f.removeByRouter(t.path);const a=this.tabsList.findIndex(s=>s.path==t.path);a!=-1&&this.tabsList.splice(a,1)}},closeAllTabs(){f.removeAll(),this.tabsList=o(this.tabsList)}}});export{p as u};

+ 1 - 1
dist/assets/use-async.64e4c0e6.js → dist/assets/use-async.34739939.js

@@ -1 +1 @@
-import{e as n,B as r}from"./index.789dd106.js";import{S as o}from"./searchs.b637f0d6.js";const g=e=>{const s=n(),t=new o(s.path).get(s.path);r(()=>{e(t)})},i=(e,s="current",a)=>{const t=new o(a.path);t.update({[s]:e},void 0,"form");const c=t.get(a.path);console.log(c,"setTabsCaches")};export{g,i as s};
+import{e as n,B as r}from"./index.1f2ecc91.js";import{S as o}from"./searchs.b637f0d6.js";const g=e=>{const s=n(),t=new o(s.path).get(s.path);r(()=>{e(t)})},i=(e,s="current",a)=>{const t=new o(a.path);t.update({[s]:e},void 0,"form");const c=t.get(a.path);console.log(c,"setTabsCaches")};export{g,i as s};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/vuedraggable.umd.8c648a7b.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/wechat-config-template-edit.f0a72f76.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/wechat-config-template-message.38869eab.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/assets/wechat-config-template.cfe7d82c.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/index.html


+ 8 - 1
src/router/constant.ts

@@ -27,5 +27,12 @@ export const asyncRoutes = {
   unitExamination: () => import('@/views/teaching-manage/unit-test/index'),
   unitTestCreate: () => import('@/views/teaching-manage/unit-test/unit-test-index/editAndUpdate'),
   musicSheet: () => import('@/views/music-library/music-sheet/index'), // 曲谱管理
-  projectMusicSheetManager: () => import('@/views/music-library/project-music-sheet/index') // 曲谱管理
+  projectMusicSheetManager: () => import('@/views/music-library/project-music-sheet/index') ,// 曲谱管理
+  messageTemplate: () => import('@/views/message/message-template/index') ,// 消息模板
+  messageRecord: () => import('@/views/message/message-record/index') ,// 消息记录
+  messageConfig: () => import('@/views/message/message-config/index') ,// 消息配置
+  messageConfigApp: () => import('@/views/message/message-config/sms/sms-config-app') ,// 消息配置应用
+  wxTemplateConfig: () => import('@views/message/message-config/wechat/wechat-config-template') ,// 推送消息配置模板
+  wxTemplateMessage: () => import('@views/message/message-config/wechat/wechat-config-template-message') ,// 推送消息配置模板内容
+  sysExceptionLog: () => import('@views/system-manage/expection-log/index') ,// 异常上报
 }

+ 53 - 0
src/utils/constant.ts

@@ -278,4 +278,57 @@ export const musicSheetAvailableType = {
 export const musicSheetAudioType = {
   HOMEMODE: '自制伴奏',
   COMMON: '普通伴奏',
+} as any
+
+export const messageSenderMode = {
+  SMS: '短信',
+  PUSH: '推送',
+  WECHAT: '公众号',
+  EMAIL: '邮件',
+} as any
+
+export const messageSenderFunctionModule = {
+  DEFAULT: '默认',
+  SYSTEM: '系统',
+  TRAINING: '作业',
+  COURSE: '课程',
+  PAY: '缴费通知',
+  LEAVE: '请假通知',
+  VIPAPPLY: 'VIP课通知',
+  STUDENT: '学员通知',
+  MUSICGROUP: '退团通知',
+  MUSIC: '建团通知',
+  WORK: '作业通知',
+  OA: 'OA通知',
+  TEACHER: '老师通知',
+} as any
+
+export const messageSendStatus= {
+  FAILED: '发送失败',
+  WAIT: '待发送',
+  SENDING: '发送中',
+  SUCCESSED: '发送完成',
+} as any
+
+export const deviceType= {
+  ANDROID: '安卓',
+  IOS: '苹果',
+} as any
+
+/**
+ * 应用类型
+ */
+export const appType= {
+  ANDROID: '安卓',
+  IOS: '苹果',
+  HARMONY: '鸿蒙',
+  WEB: '浏览器',
+} as any
+
+/**
+ * 异常类型
+ */
+export const exceptionType= {
+  ERROR: '错误',
+  RECORD: '记录',
 } as any

+ 433 - 0
src/views/message/api.ts

@@ -0,0 +1,433 @@
+import request from "@/utils/request";
+
+/**
+ * @description: 消息模板
+ */
+export const sysMessageConfigPage = (params: object) => {
+  return request({
+    url: '/cbs-app/sysMessageConfig/page',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 消息模板修改
+ */
+export const sysMessageConfigUpdate= (params: object) => {
+  return request({
+    url: '/cbs-app/sysMessageConfig/update',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 消息模板新增
+ */
+export const sysMessageConfigSave = (params: object) => {
+  return request({
+    url: '/cbs-app/sysMessageConfig/save',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 消息模板启用/停用
+ */
+export const sysMessageConfigStatus = (params: object) => {
+  return request({
+    url: '/cbs-app/sysMessageConfig/status',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 短信配置分页
+ */
+export const smsConfigPage = (params: object) => {
+  return request({
+    url: '/cbs-app/smsConfig/page',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 添加短信配置
+ */
+export const smsConfigSave = (params: object) => {
+  return request({
+    url: '/cbs-app/smsConfig/save',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 修改短信配置
+ */
+export const smsConfigUpdate = (params: object) => {
+  return request({
+    url: '/cbs-app/smsConfig/update',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 短信配置启用/停用
+ */
+export const smsConfigStatus = (params: object) => {
+  return request({
+    url: '/cbs-app/smsConfig/status',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 短信配置删除
+ */
+export const smsConfigRemove = (id: object) => {
+  return request({
+    url: '/cbs-app/smsConfig/remove?id=' + id,
+    method: 'post',
+  } as any)
+}
+
+/**
+ * @description: 短信配置详情
+ */
+export const smsConfigDetail = (id: object) => {
+  return request({
+    url: '/cbs-app/smsConfig/detail/' + id,
+    method: 'get',
+  } as any)
+}
+
+/**
+ * @description: 短信应用配置表分页
+ */
+export const smsAppConfigPage = (params: object) => {
+  return request({
+    url: '/cbs-app/smsAppConfig/page',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 添加短信应用配置
+ */
+export const smsAppConfigSave = (params: object) => {
+  return request({
+    url: '/cbs-app/smsAppConfig/save',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 修改短信配置
+ */
+export const smsAppConfigUpdate = (params: object) => {
+  return request({
+    url: '/cbs-app/smsAppConfig/update',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 短信应用配置表删除
+ */
+export const smsAppConfigRemove = (id: object) => {
+  return request({
+    url: '/cbs-app/smsAppConfig/remove?id=' + id,
+    method: 'post',
+  } as any)
+}
+
+/**
+ * @description: 短信应用配置表修改状态
+ */
+export const smsAppConfigStatus = (params: object) => {
+  return request({
+    url: '/cbs-app/smsAppConfig/status',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: app推送配置表分页
+ */
+export const appSendConfigPage = (params: object) => {
+  return request({
+    url: '/cbs-app/appSendConfig/page',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: app推送配置表启用/停用
+ */
+export const appSendConfigStatus = (params: object) => {
+  return request({
+    url: '/cbs-app/appSendConfig/status',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: app推送配置表删除
+ */
+export const appSendConfigRemove = (id: object) => {
+  return request({
+    url: '/cbs-app/appSendConfig/remove?id=' + id,
+    method: 'post',
+  } as any)
+}
+
+/**
+ * @description: 添加短信配置
+ */
+export const appSendConfigSave = (params: object) => {
+  return request({
+    url: '/cbs-app/appSendConfig/save',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 修改短信配置
+ */
+export const appSendConfigUpdate = (params: object) => {
+  return request({
+    url: '/cbs-app/appSendConfig/update',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+
+/**
+ * @description: 消息记录
+ */
+export const sysMessagePage = (params: object) => {
+  return request({
+    url: '/cbs-app/sysMessage/page',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 微信配置信息分页
+ */
+export const wxConfigInfoPage = (params: object) => {
+  return request({
+    url: '/cbs-app/wxConfigInfo/page',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 微信配置信息新增
+ */
+export const wxConfigInfoSave = (params: object) => {
+  return request({
+    url: '/cbs-app/wxConfigInfo/save',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 微信配置信息修改
+ */
+export const wxConfigInfoUpdate = (params: object) => {
+  return request({
+    url: '/cbs-app/wxConfigInfo/update',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+
+/**
+ * @description: 微信配置信息删除
+ */
+export const wxConfigInfoRemove = (id: object) => {
+  return request({
+    url: '/cbs-app/wxConfigInfo/remove?id=' + id,
+    method: 'post',
+  } as any)
+}
+
+/**
+ * @description: 微信配置信息删除启用/停用
+ */
+export const wxConfigInfoStatus = (params: object) => {
+  return request({
+    url: '/cbs-app/wxConfigInfo/status',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 微信配置信息详情
+ */
+export const wxConfigInfoDetail = (id: object) => {
+  return request({
+    url: '/cbs-app/wxConfigInfo/detail/' + id,
+    method: 'get',
+  } as any)
+}
+
+/**
+ * @description: 微信模板配置新增
+ */
+export const wxTemplateConfigSave = (params: object) => {
+  return request({
+    url: '/cbs-app/wxTemplateConfig/save',
+    method: 'post',
+    data: params
+  } as any)
+}
+/**
+ * @description: 微信模板配置修改
+ */
+export const wxTemplateConfigUpdate = (params: object) => {
+  return request({
+    url: '/cbs-app/wxTemplateConfig/update',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 微信模板配置分页
+ */
+export const wxTemplateConfigPage = (params: object) => {
+  return request({
+    url: '/cbs-app/wxTemplateConfig/page',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+
+/**
+ * @description: 微信模板配置启用/停用
+ */
+export const wxTemplateConfigStatus = (params: object) => {
+  return request({
+    url: '/cbs-app/wxTemplateConfig/status',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 微信模板配置删除
+ */
+export const wxTemplateConfigRemove = (id: object) => {
+  return request({
+    url: '/cbs-app/wxTemplateConfig/remove?id=' + id,
+    method: 'post',
+  } as any)
+}
+
+/**
+ * @description: 微信模板配置详情
+ */
+export const wxTemplateConfigDetail = (id: object) => {
+  return request({
+    url: '/cbs-app/wxTemplateConfig/detail/' + id,
+    method: 'get',
+  } as any)
+}
+
+/**
+ * @description: 微信模板消息内容分页
+ */
+export const wxTemplateMessagePage = (params: object) => {
+  return request({
+    url: '/cbs-app/wxTemplateMessage/page',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 微信模板消息内容详情
+ */
+export const wxTemplateMessageDetail = (id: object) => {
+  return request({
+    url: '/cbs-app/wxTemplateMessage/detail/' + id,
+    method: 'get',
+  } as any)
+}
+
+/**
+ * @description: 邮件配置表分页
+ */
+export const emailConfigPage = (params: object) => {
+  return request({
+    url: '/cbs-app/emailConfig/page',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 邮件配置表删除
+ */
+export const emailConfigRemove = (id: object) => {
+  return request({
+    url: '/cbs-app/emailConfig/remove?id=' + id,
+    method: 'post',
+  } as any)
+}
+
+/**
+ * @description: 邮件配置表启用/停用
+ */
+export const emailConfigStatus = (params: object) => {
+  return request({
+    url: '/cbs-app/emailConfig/status',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 邮件配置表新增
+ */
+export const emailConfigSave = (params: object) => {
+  return request({
+    url: '/cbs-app/emailConfig/save',
+    method: 'post',
+    data: params
+  } as any)
+}
+
+/**
+ * @description: 邮件配置表修改
+ */
+export const emailConfigUpdate = (params: object) => {
+  return request({
+    url: '/cbs-app/emailConfig/update',
+    method: 'post',
+    data: params
+  } as any)
+}

+ 348 - 0
src/views/message/message-config/email/email-config.tsx

@@ -0,0 +1,348 @@
+import {
+  NButton,
+  NDataTable,
+  NFormItem,
+  NInput,
+  NModal,
+  NSelect,
+  NSpace,
+  NTag,
+  useDialog,
+  useMessage
+} from 'naive-ui'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { useTabsViewStore } from '@/store/modules/tabsView'
+import SaveForm from '@components/save-form'
+import Pagination from '@components/pagination'
+import deepClone from '@/utils/deep.clone'
+import EmailConfigEdit from '@views/message/message-config/email/modal/email-config-edit'
+import { getMapValueByKey } from '@/utils/objectUtil'
+import { appKey } from '@/utils/constant'
+import { sysApplicationPage } from '@views/menu-manage/api'
+import { emailConfigPage, emailConfigRemove, emailConfigStatus } from '@views/message/api'
+
+export default defineComponent({
+  name: 'email-config',
+  setup(props, ctx) {
+    const route = useRoute()
+    const router = useRouter()
+    const dialog = useDialog()
+    const message = useMessage()
+    const state = reactive({
+      loading: false,
+      appId: null as any,
+      pagination: {
+        page: 1,
+        rows: 10,
+        pageTotal: 0
+      },
+      searchForm: {
+        keyword: null, //关键字
+        status: null, // 状态
+        appKey: null // 接入应用
+      },
+      name: null as any,
+      dataList: [],
+      showEdit: false,
+      editMode: 'add',
+      editRowData: {} as any,
+      appData: [] as any
+    })
+    const tabsViewStore = useTabsViewStore()
+    const gotoBack = () => {
+      tabsViewStore.closeCurrentTab(route)
+      router.push({
+        path: '/message/messageConfig'
+      })
+    }
+
+    onMounted(async () => {
+      // 应用
+      {
+        state.appData = []
+        const { data } = await sysApplicationPage({ page: 1, rows: 999 })
+        if (data && data.rows) {
+          data.rows.forEach((item: any) => {
+            state.appData.push({ label: item.appName, value: item.appKey })
+          })
+        }
+      }
+
+      getList()
+    })
+
+    const saveForm = ref()
+    const onSearch = () => {
+      saveForm.value?.submit()
+    }
+    const onBtnReset = () => {
+      saveForm.value?.reset()
+    }
+
+    const onSubmit = () => {
+      state.pagination.page = 1
+      getList()
+    }
+
+    const getList = async () => {
+      try {
+        state.loading = true
+        const { data } = await emailConfigPage({
+          ...state.pagination,
+          ...state.searchForm
+        })
+        state.pagination.pageTotal = Number(data.total)
+        state.dataList = data.rows || []
+      } catch {}
+      state.loading = false
+    }
+
+    const onChangeStatus = (row: any) => {
+      const statusStr = row.status ? '停用' : '启用'
+      dialog.warning({
+        title: '提示',
+        content: `是否${statusStr}?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await emailConfigStatus({
+              id: row.id,
+              status: !row.status
+            })
+            getList()
+            message.success(`${statusStr}成功`)
+          } catch {}
+        }
+      })
+    }
+
+    const onRmove = (row: any): void => {
+      dialog.warning({
+        title: '提示',
+        content: `删除"${row.name}",是否继续?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await emailConfigRemove(row.id)
+            getList()
+            message.success('删除成功')
+          } catch {}
+        }
+      })
+    }
+
+    const columns = (): any => {
+      return [
+        {
+          title: '编号',
+          key: 'id'
+        },
+        {
+          title: '平台名称',
+          key: 'name'
+        },
+        {
+          title: '接入应用',
+          key: 'appKey',
+          render(row: any) {
+            return <div>{getMapValueByKey(row.appKey, new Map(Object.entries(appKey)))}</div>
+          }
+        },
+        {
+          title: '域名',
+          key: 'hostUrl'
+        },
+        {
+          title: '端口',
+          key: 'smtpPort'
+        },
+        {
+          title: '用户名',
+          key: 'account'
+        },
+        {
+          title: '密码',
+          key: 'password'
+        },
+        {
+          title: '发送方',
+          key: 'from'
+        },
+        {
+          title: '发送名称',
+          key: 'fromName'
+        },
+        {
+          title: '状态',
+          key: 'status',
+          render(row: any) {
+            return (
+              <NTag type={row.status ? 'primary' : 'default'}>{row.status ? '启用' : '停用'}</NTag>
+            )
+          }
+        },
+        {
+          title: '操作',
+          key: 'operation',
+          fixed: 'right',
+          render(row: any) {
+            return (
+              <NSpace>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="emailConfig/status1790935300606857218"
+                  onClick={() => {
+                    onChangeStatus(row)
+                  }}
+                >
+                  {row.status ? '停用' : '启用'}
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="emailConfig/update1790935437341167617"
+                  onClick={() => {
+                    state.showEdit = true
+                    state.editRowData = deepClone(row)
+                    state.editMode = 'edit'
+                  }}
+                >
+                  修改
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="emailConfig/remove1790935226178932738"
+                  disabled={!!row.status}
+                  onClick={() => {
+                    onRmove(row)
+                  }}
+                >
+                  删除
+                </NButton>
+              </NSpace>
+            )
+          }
+        }
+      ]
+    }
+
+    return () => (
+      <div class="system-menu-container">
+        <div class={['section-container']}>
+          <div class="system-menu-container">
+            <SaveForm
+              ref={saveForm}
+              model={state.searchForm}
+              onSubmit={onSubmit}
+              saveKey="email-config"
+              onSetModel={(val: any) => (state.searchForm = val)}
+            >
+              <NFormItem label="关键字" path="keyword">
+                <NInput
+                  placeholder="编号/平台名称"
+                  v-model:value={state.searchForm.keyword}
+                  clearable
+                />
+              </NFormItem>
+              <NFormItem label="接入应用" path="appKey">
+                <NSelect
+                  placeholder="请选择接入应用"
+                  v-model:value={state.searchForm.appKey}
+                  options={state.appData}
+                  clearable
+                />
+              </NFormItem>
+              <NFormItem label="状态" path="status">
+                <NSelect
+                  v-model:value={state.searchForm.status}
+                  clearable
+                  options={
+                    [
+                      {
+                        label: '启用',
+                        value: 1
+                      },
+                      {
+                        label: '停用',
+                        value: 0
+                      }
+                    ] as any
+                  }
+                  placeholder="全部状态"
+                />
+              </NFormItem>
+              <NFormItem>
+                <NSpace>
+                  <NButton type="primary" onClick={onSearch}>
+                    搜索
+                  </NButton>
+                  <NButton type="default" onClick={onBtnReset}>
+                    重置
+                  </NButton>
+                </NSpace>
+              </NFormItem>
+            </SaveForm>
+
+            <NSpace style={{ paddingBottom: '12px' }}>
+              <NButton
+                type="primary"
+                v-auth="emailConfig/save1790935373034098690"
+                onClick={() => {
+                  state.showEdit = true
+                  state.editMode = 'add'
+                }}
+              >
+                新增邮件配置
+              </NButton>
+            </NSpace>
+
+            <div class={['section-container']}>
+              <NDataTable
+                loading={state.loading}
+                columns={columns()}
+                data={state.dataList}
+                rowKey={(row: any) => row.id}
+                scrollX={'1400'}
+              ></NDataTable>
+
+              <Pagination
+                v-model:page={state.pagination.page}
+                v-model:pageSize={state.pagination.rows}
+                v-model:pageTotal={state.pagination.pageTotal}
+                onList={getList}
+                sync
+                saveKey="email-config"
+              ></Pagination>
+            </div>
+            <NModal
+              blockScroll={true}
+              v-model:show={state.showEdit}
+              preset="dialog"
+              showIcon={false}
+              title={(state.editMode == 'add' ? '新增' : '编辑') + '邮件配置'}
+              style={{ width: '700px' }}
+            >
+              <EmailConfigEdit
+                editMode={state.editMode}
+                rowData={state.editRowData}
+                onClose={() => (state.showEdit = false)}
+                onGetList={() => {
+                  state.pagination.page = 1
+                  getList()
+                }}
+              />
+            </NModal>
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 253 - 0
src/views/message/message-config/email/modal/email-config-edit.tsx

@@ -0,0 +1,253 @@
+import {defineComponent, onMounted, reactive, ref} from "vue";
+import {NButton, NForm, NFormItemGi, NGrid, NInput, NSelect, NSpace, useMessage} from "naive-ui";
+import {sysApplicationPage} from "@views/menu-manage/api";
+import {emailConfigSave, emailConfigUpdate} from "@views/message/api";
+
+export default defineComponent({
+  mpName: 'email-config-edit',
+  props: {
+    editMode: {
+      type: String,
+      required: true
+    },
+    rowData: {
+      type: Object,
+      required: false
+    },
+  },
+  emits: ['close', 'getList'],
+  setup(props, {slots, attrs, emit}) {
+    const message = useMessage()
+    const btnLoading = ref(false)
+    const forms = reactive({
+      name: null, //平台名称
+      sender: null, //三方服务厂商
+      smtpPort: null, //端口
+      account: null, //账号
+      password: null, //密码
+      from: null, //密码
+      fromName: null, //发送方名称
+      appKey: null, //应用端
+      hostUrl: null, //域名
+    })
+    const formsRef = ref()
+
+    const state = reactive({
+      rowData: null as any,
+      appData: [] as any,
+    })
+
+    onMounted(async () => {
+      state.rowData = props.rowData
+      if (props.editMode == 'edit' && props.rowData) {
+        forms.name = state.rowData.name
+        forms.sender = state.rowData.sender
+        forms.smtpPort = state.rowData.smtpPort
+        forms.account = state.rowData.account
+        forms.password = state.rowData.password
+        forms.from = state.rowData.from
+        forms.fromName = state.rowData.fromName
+        forms.appKey = state.rowData.appKey
+        forms.hostUrl = state.rowData.hostUrl
+      }
+      // 应用
+      {
+        state.appData = []
+        const {data} = await sysApplicationPage({page: 1, rows: 999})
+        if (data && data.rows) {
+          data.rows.forEach((item: any) => {
+            state.appData.push({label: item.appName, value: item.appKey})
+          })
+        }
+      }
+
+
+    })
+
+    const onSubmit = async () => {
+      formsRef.value.validate(async (error: any) => {
+        if (error) return false
+        btnLoading.value = true
+        try {
+          let res;
+          if (props.editMode == 'add') {
+            res = await emailConfigSave(
+                {
+                  ...forms,
+                }
+            ) as any;
+          } else {
+            res = await emailConfigUpdate(
+                {
+                  ...forms,
+                  id: state.rowData.id
+                }
+            ) as any;
+          }
+          if (res && res.code === 200) {
+            emit('close')
+            emit('getList')
+          }
+        } catch (error) {
+        }
+        btnLoading.value = false
+      })
+    }
+
+    return () => {
+      return (
+          <div style="background: #fff; padding-top: 12px">
+            <NForm
+                ref={formsRef}
+                labelPlacement="top"
+                model={forms}
+                label-placement="left"
+                label-width="100"
+            >
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="平台名称"
+                    path="name"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入平台名称'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.name}
+                      placeholder="请输入平台名称"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="域名"
+                    path="hostUrl"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入域名'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.hostUrl}
+                      placeholder="请输入域名"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="端口"
+                    path="smtpPort"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入端口'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.smtpPort}
+                      placeholder="请输入端口"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="用户名"
+                    path="account"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入用户名'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.account}
+                      placeholder="请输入用户名"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="密码"
+                    path="password"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入密码'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.password}
+                      placeholder="请输入密码"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="发送方"
+                    path="from"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入发送方'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.from}
+                      placeholder="请输入发送方"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="发送方名称"
+                    path="fromName"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入发送方名称'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.fromName}
+                      placeholder="请输入发送方名称"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="接入应用"
+                    path="appKey"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择接入应用'
+                      }
+                    ]}
+                >
+                  <NSelect
+                      v-model:value={forms.appKey}
+                      placeholder="请选择接入应用"
+                      options={state.appData}
+                      clearable
+                  />
+                </NFormItemGi>
+              </NGrid>
+            </NForm>
+
+            <NSpace justify="end">
+              <NButton onClick={() => emit('close')}>取消</NButton>
+              <NButton type="primary" onClick={onSubmit}
+                       loading={btnLoading.value}
+                       disabled={btnLoading.value}
+              >
+                保存
+              </NButton>
+            </NSpace>
+          </div>
+      )
+    }
+  }
+})

+ 61 - 0
src/views/message/message-config/index.tsx

@@ -0,0 +1,61 @@
+import { NTabPane, NTabs } from 'naive-ui'
+import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue'
+import { useRoute } from 'vue-router'
+import { getTabsCache, setTabsCaches } from '@/hooks/use-async'
+import SmsConfig from '@views/message/message-config/sms/sms-config'
+import PushConfig from '@views/message/message-config/push/push-config'
+import WechatConfig from '@views/message/message-config/wechat/wechat-config'
+import EmailConfig from '@views/message/message-config/email/email-config'
+
+export default defineComponent({
+  name: 'message-config-index',
+  setup() {
+    const state = reactive({
+      tabName: 'SMS' as 'SMS' | 'PUSH' | 'EMAIL' | 'WECHAT'
+    })
+    const tabsInstRef = ref()
+    getTabsCache((val: any) => {
+      if (val.form.tabName) {
+        state.tabName = val.form.tabName
+        nextTick(() => tabsInstRef.value?.syncBarPosition())
+      }
+    })
+    const route = useRoute()
+    const setTabs = (val: any) => {
+      setTabsCaches(val, 'tabName', route)
+    }
+
+    onMounted(async () => {
+      nextTick(() => tabsInstRef.value?.syncBarPosition())
+    })
+
+    return () => {
+      return (
+        <div class="system-menu-container">
+          <div class={['section-container']} style="padding-top: 0">
+            <NTabs
+              ref={tabsInstRef}
+              type="line"
+              size="large"
+              v-model:value={state.tabName}
+              onUpdate:value={(val: any) => setTabs(val)}
+            >
+              <NTabPane name="SMS" tab="短信" v-auth="smsConfig/page1790929887618469889">
+                <SmsConfig />
+              </NTabPane>
+              <NTabPane name="PUSH" tab="推送" v-auth="appSendConfig/page1790933531566870529">
+                <PushConfig />
+              </NTabPane>
+              <NTabPane name="WECHAT" tab="公众号" v-auth="wxConfigInfo/page1790934372273164290">
+                <WechatConfig />
+              </NTabPane>
+              <NTabPane name="EMAIL" tab="邮件" v-auth="emailConfig/page1790935157727891457">
+                <EmailConfig />
+              </NTabPane>
+            </NTabs>
+          </div>
+        </div>
+      )
+    }
+  }
+})

+ 327 - 0
src/views/message/message-config/push/modal/push-config-edit.tsx

@@ -0,0 +1,327 @@
+import {defineComponent, onMounted, reactive, ref} from "vue";
+import {NButton, NForm, NFormItemGi, NGrid, NInput, NInputNumber, NSelect, NSpace, useMessage} from "naive-ui";
+import {getSelectDataFromObj} from "@/utils/objectUtil";
+import {clientType, deviceType} from "@/utils/constant";
+import {appSendConfigSave, appSendConfigUpdate} from "@views/message/api";
+
+export default defineComponent({
+  name: 'push-config-edit',
+  props: {
+    editMode: {
+      type: String,
+      required: true
+    },
+    rowData: {
+      type: Object,
+      required: false
+    },
+    appData: {
+      type: [] as any,
+      required: true
+    },
+  },
+  emits: ['close', 'getList'],
+  setup(props, {slots, attrs, emit}) {
+    const message = useMessage()
+    const btnLoading = ref(false)
+    const forms = reactive({
+      name: null, // 平台名称
+      sender: null, // 平台标识
+      appKey: null, // 应用端
+      accessUrl: null, // 接入地址
+      clientId: null, // 客户端
+      apnsProduction: null as any, // 推送环境
+      account: null, // 接入账号
+      password: null, // 接入密码
+      timeToLive: null as any, // 离线保存时长
+      extendData: null, // 扩展参数
+      deviceType: null, // 设备类型
+    })
+    const formsRef = ref()
+
+    const state = reactive({
+      rowData: null as any,
+      musicSheetCategories: [] as any,
+      appData: [] as any,
+    })
+
+    onMounted(async () => {
+      state.rowData = props.rowData
+      if (props.editMode == 'edit' && props.rowData) {
+        forms.name = state.rowData.name
+        forms.sender = state.rowData.sender
+        forms.appKey = state.rowData.appKey
+        forms.clientId = state.rowData.clientId
+        forms.apnsProduction = state.rowData.apnsProduction
+        forms.account = state.rowData.account
+        forms.password = state.rowData.password
+        forms.timeToLive = Number.parseFloat(state.rowData.timeToLive)/3600
+        forms.accessUrl = state.rowData.accessUrl
+        forms.extendData = state.rowData.extendData
+        forms.deviceType = state.rowData.deviceType
+      }
+      // 客户端
+
+
+      // state.appData = []
+      // const {data} = await sysApplicationPage({page: 1, rows: 999})
+      // if (data && data.rows) {
+      //   data.rows.forEach((item: any) => {
+      //     state.appData.push({label: item.appName, value: item.id + ''})
+      //   })
+      // }
+    })
+
+    const onSubmit = async () => {
+      formsRef.value.validate(async (error: any) => {
+        if (error) return false
+        btnLoading.value = true
+        try {
+          let res;
+          if (props.editMode == 'add') {
+            res = await appSendConfigSave(
+                {
+                  ...forms,
+                  timeToLive: Number.parseFloat(forms.timeToLive) * 3600
+                }
+            ) as any;
+          } else {
+            res = await appSendConfigUpdate(
+                {
+                  ...forms,
+                  id: state.rowData.id,
+                  timeToLive: Number.parseFloat(forms.timeToLive) * 3600
+                }
+            ) as any;
+          }
+          if (res && res.code === 200) {
+            emit('close')
+            emit('getList')
+          }
+        } catch (error) {
+        }
+        btnLoading.value = false
+      })
+    }
+
+    return () => {
+      return (
+          <div style="background: #fff; padding-top: 12px">
+            <NForm
+                ref={formsRef}
+                labelPlacement="top"
+                model={forms}
+                label-placement="left"
+                label-width="100"
+            >
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="平台名称"
+                    path="name"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入平台名称'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.name}
+                      placeholder="请输入平台名称"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="平台标识"
+                    path="sender"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入平台标识'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.sender}
+                      placeholder="请输入平台标识"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="接入应用"
+                    path="appKey"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入接入应用'
+                      }
+                    ]}
+                >
+                  <NSelect
+                      v-model:value={forms.appKey}
+                      placeholder="请输入接入应用"
+                      options={props.appData}
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="客户端"
+                    path="clientId"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择客户端'
+                      }
+                    ]}
+                >
+                  <NSelect
+                      v-model:value={forms.clientId}
+                      options={getSelectDataFromObj(clientType)}
+                      placeholder="请选择客户端"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="接入地址"
+                    path="accessUrl"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入接入地址'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.accessUrl}
+                      placeholder="请输入接入地址"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="推送环境"
+                    path="apnsProduction"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入推送环境',
+                        type: 'boolean'
+                      }
+                    ]}
+                >
+                  <NSelect
+                      v-model:value={forms.apnsProduction}
+                      placeholder="请输入推送环境"
+                      options={[
+                        {
+                          label: '线上',
+                          value: true
+                        }, {
+                          label: '开发',
+                          value: false
+                        }
+
+                      ] as any}
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="接入key"
+                    path="account"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入接入key'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.account}
+                      placeholder="请输入接入key"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="接入密钥"
+                    path="password"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入接入密钥'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.password}
+                      placeholder="请输入接入密码"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="离线保留时长(小时)"
+                    path="timeToLive"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入离线保留时长(小时)'
+                      }
+                    ]}
+                >
+                  <NInputNumber
+                      v-model:value={forms.timeToLive}
+                      placeholder="请输入离线保留时长(小时)"
+                      min={0}
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="设备类型"
+                    path="deviceType"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请选择设备类型'
+                      }
+                    ]}
+                >
+                  <NSelect
+                      placeholder="请选择设备类型"
+                      value={forms.deviceType}
+                      options={getSelectDataFromObj(deviceType)}
+                      clearable
+                  />
+                </NFormItemGi>
+              </NGrid>
+              <NGrid cols={1}>
+                <NFormItemGi
+                    label="拓展参数"
+                    path="extendData"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请输入拓展参数'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.extendData}
+                      placeholder="请输入拓展参数"
+                      autosize={{minRows: 3}}
+                      type={'textarea'}
+                  />
+                </NFormItemGi>
+              </NGrid>
+            </NForm>
+
+            <NSpace justify="end">
+              <NButton onClick={() => emit('close')}>取消</NButton>
+              <NButton type="primary" onClick={onSubmit}
+                       loading={btnLoading.value}
+                       disabled={btnLoading.value}
+              >
+                保存
+              </NButton>
+            </NSpace>
+          </div>
+      )
+    }
+  }
+})

+ 387 - 0
src/views/message/message-config/push/push-config.tsx

@@ -0,0 +1,387 @@
+import {
+  NButton,
+  NDataTable,
+  NFormItem,
+  NInput,
+  NModal,
+  NSelect,
+  NSpace,
+  NTag,
+  useDialog,
+  useMessage
+} from 'naive-ui'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { useTabsViewStore } from '@/store/modules/tabsView'
+import SaveForm from '@components/save-form'
+import Pagination from '@components/pagination'
+import PushConfigEdit from '@views/message/message-config/push/modal/push-config-edit'
+import TheTooltip from '@components/TheTooltip'
+import { getMapValueByKey, getSelectDataFromObj } from '@/utils/objectUtil'
+import { appKey, clientType, deviceType } from '@/utils/constant'
+import deepClone from '@/utils/deep.clone'
+import { sysApplicationPage } from '@views/menu-manage/api'
+import { appSendConfigPage, appSendConfigRemove, appSendConfigStatus } from '@views/message/api'
+
+export default defineComponent({
+  name: 'push-config',
+  setup(props, ctx) {
+    const route = useRoute()
+    const router = useRouter()
+    const dialog = useDialog()
+    const message = useMessage()
+    const state = reactive({
+      loading: false,
+      appId: null as any,
+      pagination: {
+        page: 1,
+        rows: 10,
+        pageTotal: 0
+      },
+      searchForm: {
+        keyword: null, //关键字
+        status: null, // 状态
+        appKey: null, // 应用
+        clientId: null // 客户端
+      },
+      name: null as any,
+      smsConfigId: null as any,
+      dataList: [],
+      showEdit: false,
+      editMode: 'add',
+      editRowData: {} as any,
+      appData: [] as any
+    })
+    const tabsViewStore = useTabsViewStore()
+    const gotoBack = () => {
+      tabsViewStore.closeCurrentTab(route)
+      router.push({
+        path: '/message/messageConfig'
+      })
+    }
+
+    onMounted(async () => {
+      state.appData = []
+      const { data } = await sysApplicationPage({ page: 1, rows: 999 })
+      if (data && data.rows) {
+        data.rows.forEach((item: any) => {
+          state.appData.push({ label: item.appName, value: item.appKey })
+        })
+      }
+      getList()
+    })
+
+    const saveForm = ref()
+    const onSearch = () => {
+      saveForm.value?.submit()
+    }
+    const onBtnReset = () => {
+      saveForm.value?.reset()
+    }
+
+    const onSubmit = () => {
+      state.pagination.page = 1
+      getList()
+    }
+
+    const getList = async () => {
+      state.loading = true
+      try {
+        const { data } = await appSendConfigPage({
+          ...state.pagination,
+          ...state.searchForm
+        })
+        state.pagination.pageTotal = Number(data.total)
+        state.dataList = data.rows || []
+      } catch {}
+      state.loading = false
+    }
+
+    const onChangeStatus = (row: any) => {
+      const statusStr = row.status ? '停用' : '启用'
+      dialog.warning({
+        title: '提示',
+        content: `是否${statusStr}?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await appSendConfigStatus({
+              id: row.id,
+              status: !row.status
+            })
+            getList()
+            message.success(`${statusStr}成功`)
+          } catch {}
+        }
+      })
+    }
+
+    const onRmove = (row: any): void => {
+      dialog.warning({
+        title: '提示',
+        content: `删除"${row.name}",是否继续?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await appSendConfigRemove(row.id)
+            getList()
+            message.success('删除成功')
+          } catch {}
+        }
+      })
+    }
+
+    const columns = (): any => {
+      return [
+        {
+          title: '编号',
+          key: 'id'
+        },
+        {
+          title: '平台名称',
+          key: 'name'
+        },
+        {
+          title: '平台标识',
+          key: 'sender'
+        },
+        {
+          title: '应用',
+          key: 'appKey',
+          render(row: any) {
+            return <div>{getMapValueByKey(row.appKey, new Map(Object.entries(appKey)))}</div>
+          }
+        },
+        {
+          title: '客户端',
+          key: 'clientId',
+          render(row: any) {
+            return <div>{getMapValueByKey(row.clientId, new Map(Object.entries(clientType)))}</div>
+          }
+        },
+        {
+          title: '设备类型',
+          key: 'deviceType',
+          render(row: any) {
+            return (
+              <div>{getMapValueByKey(row.deviceType, new Map(Object.entries(deviceType)))}</div>
+            )
+          }
+        },
+        {
+          title: '接入地址',
+          key: 'accessUrl'
+        },
+        {
+          title: '离线保留时长(小时)',
+          key: 'timeToLive',
+          render(row: any) {
+            return row.timeToLive / 3600
+          }
+        },
+        {
+          title: '推送环境',
+          key: 'apnsProduction',
+          render(row: any) {
+            return row.apnsProduction ? '线上' : '开发'
+          }
+        },
+        {
+          title: '接入key',
+          key: 'account'
+        },
+        {
+          title: '接入秘匙',
+          key: 'password'
+        },
+        {
+          title: '拓展参数',
+          key: 'extendData',
+          render(row: any) {
+            return <TheTooltip content={row.extendData} />
+          }
+        },
+        {
+          title: '状态',
+          key: 'status',
+          render(row: any) {
+            return (
+              <NTag type={row.status ? 'primary' : 'default'}>{row.status ? '启用' : '停用'}</NTag>
+            )
+          }
+        },
+        {
+          title: '操作',
+          key: 'operation',
+          fixed: 'right',
+          minWidth: '180px',
+          render(row: any) {
+            return (
+              <NSpace>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="appSendConfig/status1790933632397938690"
+                  onClick={() => {
+                    onChangeStatus(row)
+                  }}
+                >
+                  {row.status ? '停用' : '启用'}
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="appSendConfig/update1790933865680932866"
+                  onClick={() => {
+                    state.showEdit = true
+                    state.editRowData = deepClone(row)
+                    state.editMode = 'edit'
+                  }}
+                >
+                  修改
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="appSendConfig/remove1790933707882827777"
+                  disabled={!!row.status}
+                  onClick={() => {
+                    onRmove(row)
+                  }}
+                >
+                  删除
+                </NButton>
+              </NSpace>
+            )
+          }
+        }
+      ]
+    }
+
+    return () => (
+      <div class="system-menu-container">
+        <div class={['section-container']}>
+          <div class="system-menu-container">
+            <SaveForm
+              ref={saveForm}
+              model={state.searchForm}
+              onSubmit={onSubmit}
+              saveKey="push-config-app"
+              onSetModel={(val: any) => (state.searchForm = val)}
+            >
+              <NFormItem label="关键字" path="keyword">
+                <NInput
+                  placeholder="应用编号/名称"
+                  v-model:value={state.searchForm.keyword}
+                  clearable
+                />
+              </NFormItem>
+              <NFormItem label="应用" path="appKey">
+                <NSelect
+                  placeholder="请选择应用"
+                  v-model:value={state.searchForm.appKey}
+                  options={state.appData}
+                  clearable
+                />
+              </NFormItem>
+              <NFormItem label="客户端" path="clientId">
+                <NSelect
+                  placeholder="请选择客户端"
+                  v-model:value={state.searchForm.clientId}
+                  options={getSelectDataFromObj(clientType)}
+                  clearable
+                />
+              </NFormItem>
+              <NFormItem label="状态" path="status">
+                <NSelect
+                  v-model:value={state.searchForm.status}
+                  clearable
+                  options={
+                    [
+                      {
+                        label: '启用',
+                        value: 1
+                      },
+                      {
+                        label: '停用',
+                        value: 0
+                      }
+                    ] as any
+                  }
+                  placeholder="全部状态"
+                />
+              </NFormItem>
+              <NFormItem>
+                <NSpace>
+                  <NButton type="primary" onClick={onSearch}>
+                    搜索
+                  </NButton>
+                  <NButton type="default" onClick={onBtnReset}>
+                    重置
+                  </NButton>
+                </NSpace>
+              </NFormItem>
+            </SaveForm>
+
+            <NSpace style={{ paddingBottom: '12px' }}>
+              <NButton
+                type="primary"
+                v-auth="appSendConfig/save1790933794033831937"
+                onClick={() => {
+                  state.showEdit = true
+                  state.editMode = 'add'
+                }}
+              >
+                新增推送平台
+              </NButton>
+            </NSpace>
+
+            <div class={['section-container']}>
+              <NDataTable
+                loading={state.loading}
+                columns={columns()}
+                data={state.dataList}
+                rowKey={(row: any) => row.id}
+                scrollX={'1400'}
+              ></NDataTable>
+
+              <Pagination
+                v-model:page={state.pagination.page}
+                v-model:pageSize={state.pagination.rows}
+                v-model:pageTotal={state.pagination.pageTotal}
+                onList={getList}
+                sync
+                saveKey="push-config-app"
+              ></Pagination>
+            </div>
+            <NModal
+              blockScroll={true}
+              v-model:show={state.showEdit}
+              preset="dialog"
+              showIcon={false}
+              title={(state.editMode == 'add' ? '新增' : '编辑') + '推送平台'}
+              // style={{width: 'auto'}}
+              style={{ width: '700px' }}
+            >
+              <PushConfigEdit
+                editMode={state.editMode}
+                rowData={state.editRowData}
+                appData={state.appData}
+                onClose={() => (state.showEdit = false)}
+                onGetList={() => {
+                  state.pagination.page = 1
+                  getList()
+                }}
+              />
+            </NModal>
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 159 - 0
src/views/message/message-config/sms/modal/sms-config-app-edit.tsx

@@ -0,0 +1,159 @@
+import {defineComponent, onMounted, reactive, ref} from "vue";
+import {NButton, NForm, NFormItemGi, NGrid, NInput, NSelect, NSpace} from "naive-ui";
+import {smsAppConfigSave, smsAppConfigUpdate} from "@views/message/api";
+
+export default defineComponent({
+  name: 'sms-config-app-edit',
+  props: {
+    editMode: {
+      type: String,
+      required: true
+    },
+    smsConfigId: {
+      type: Number,
+      required: true
+    },
+    rowData: {
+      type: Object,
+      required: false
+    },
+    appData: {
+      type: Array as any,
+      required: true
+    }
+  },
+  emits: ['close', 'getList'],
+  setup(props, {slots, attrs, emit}) {
+    const btnLoading = ref(false)
+    const forms = reactive({
+      appKey: null as any,
+      sign: null,
+      extendData: null,
+    })
+    const formsRef = ref()
+
+    const state = reactive({
+      rowData: null as any,
+      musicSheetCategories: [] as any,
+    })
+
+    onMounted(async () => {
+      state.rowData = props.rowData
+      if (props.editMode == 'edit' && props.rowData) {
+        forms.appKey = state.rowData.appKey
+        forms.sign = state.rowData.sign
+        forms.extendData = state.rowData.extendData
+      }
+    })
+
+    const onSubmit = async () => {
+      formsRef.value.validate(async (error: any) => {
+        if (error) return false
+        btnLoading.value = true
+        try {
+          let res;
+          if (props.editMode == 'add') {
+            res = await smsAppConfigSave(
+                {
+                  ...forms,
+                  sysConfigId: props.smsConfigId
+                }
+            ) as any;
+          } else {
+            res = await smsAppConfigUpdate(
+                {
+                  ...forms,
+                  id: state.rowData.id
+                }
+            ) as any;
+          }
+          if (res && res.code === 200) {
+            emit('close')
+            emit('getList')
+          }
+        } catch (error) {
+        }
+        btnLoading.value = false
+      })
+    }
+
+    return () => {
+      return (
+          <div style="background: #fff; padding-top: 12px">
+            <NForm
+                ref={formsRef}
+                labelPlacement="top"
+                model={forms}
+                label-placement="left"
+                label-width="100"
+            >
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="应用"
+                    path="appKey"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入平台名称'
+                      }
+                    ]}
+                >
+                  <NSelect
+                      placeholder="请选择平台"
+                      v-model:value={forms.appKey}
+                      options={props.appData}
+                      filterable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="签名"
+                    path="sign"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入签名'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.sign}
+                      placeholder="请输入签名"
+                      clearable
+                  />
+                </NFormItemGi>
+              </NGrid>
+              <NGrid cols={1}>
+                <NFormItemGi
+                    label="拓展参数"
+                    path="extendData"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请输入拓展参数'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.extendData}
+                      placeholder="请输入拓展参数"
+                      autosize={{minRows: 3}}
+                      type={'textarea'}
+                  />
+                </NFormItemGi>
+              </NGrid>
+            </NForm>
+
+            <NSpace justify="end">
+              <NButton onClick={() => emit('close')}>取消</NButton>
+              <NButton type="primary" onClick={onSubmit}
+                       loading={btnLoading.value}
+                       disabled={btnLoading.value}
+              >
+                保存
+              </NButton>
+            </NSpace>
+          </div>
+      )
+    }
+  }
+})

+ 222 - 0
src/views/message/message-config/sms/modal/sms-config-edit.tsx

@@ -0,0 +1,222 @@
+import {defineComponent, onMounted, reactive, ref} from "vue";
+import {NButton, NForm, NFormItemGi, NGrid, NInput, NSpace, useMessage} from "naive-ui";
+import {smsConfigSave, smsConfigUpdate} from "@views/message/api";
+
+export default defineComponent({
+  name: 'sms-config-edit',
+  props: {
+    editMode: {
+      type: String,
+      required: true
+    },
+    rowData: {
+      type: Object,
+      required: false
+    },
+  },
+  emits: ['close', 'getList'],
+  setup(props, {slots, attrs, emit}) {
+    const message = useMessage()
+    const btnLoading = ref(false)
+    const forms = reactive({
+      name: null,
+      sender: null,
+      accessUrl: null,
+      account: null,
+      password: null,
+      extendData: null,
+      appId: null,
+    })
+    const formsRef = ref()
+
+    const state = reactive({
+      rowData: null as any,
+      musicSheetCategories: [] as any,
+    })
+
+    onMounted(async () => {
+      state.rowData = props.rowData
+      if (props.editMode == 'edit' && props.rowData) {
+        forms.name = state.rowData.name
+        forms.sender = state.rowData.sender
+        forms.accessUrl = state.rowData.accessUrl
+        forms.account = state.rowData.account
+        forms.password = state.rowData.password
+        forms.extendData = state.rowData.extendData
+        forms.appId = state.rowData.appId
+      }
+    })
+
+    const onSubmit = async () => {
+      formsRef.value.validate(async (error: any) => {
+        if (error) return false
+        btnLoading.value = true
+        try {
+          let res;
+          if (props.editMode == 'add') {
+            res = await smsConfigSave(
+                {
+                  ...forms,
+                }
+            ) as any;
+          } else {
+            res = await smsConfigUpdate(
+                {
+                  ...forms,
+                  id: state.rowData.id
+                }
+            ) as any;
+          }
+          if (res && res.code === 200) {
+            emit('close')
+            emit('getList')
+          }
+        } catch (error) {
+        }
+        btnLoading.value = false
+      })
+    }
+
+    return () => {
+      return (
+          <div style="background: #fff; padding-top: 12px">
+            <NForm
+                ref={formsRef}
+                labelPlacement="top"
+                model={forms}
+                label-placement="left"
+                label-width="100"
+            >
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="平台名称"
+                    path="name"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入平台名称'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.name}
+                      placeholder="请输入平台名称"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="平台标识"
+                    path="sender"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入平台标识'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.sender}
+                      placeholder="请输入平台标识"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="接入地址"
+                    path="accessUrl"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入接入地址'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.accessUrl}
+                      placeholder="请输入接入地址"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="应用ID"
+                    path="appId"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请输入应用ID'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.appId}
+                      placeholder="请输入应用ID"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="接入账号"
+                    path="account"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入接入账号'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.account}
+                      placeholder="请输入接入账号"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="接入密码"
+                    path="password"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入接入密码'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.password}
+                      placeholder="请输入接入密码"
+                      clearable
+                  />
+                </NFormItemGi>
+              </NGrid>
+              <NGrid cols={1}>
+                <NFormItemGi
+                    label="拓展参数"
+                    path="extendData"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请输入拓展参数'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.extendData}
+                      placeholder="请输入拓展参数"
+                      autosize={{minRows: 3}}
+                      type={'textarea'}
+                  />
+                </NFormItemGi>
+              </NGrid>
+            </NForm>
+
+            <NSpace justify="end">
+              <NButton onClick={() => emit('close')}>取消</NButton>
+              <NButton type="primary" onClick={onSubmit}
+                       loading={btnLoading.value}
+                       disabled={btnLoading.value}
+              >
+                保存
+              </NButton>
+            </NSpace>
+          </div>
+      )
+    }
+  }
+})

+ 347 - 0
src/views/message/message-config/sms/sms-config-app.tsx

@@ -0,0 +1,347 @@
+import {
+  NButton,
+  NDataTable,
+  NFormItem,
+  NInput,
+  NModal,
+  NPageHeader,
+  NSelect,
+  NSpace,
+  NTag,
+  useDialog,
+  useMessage
+} from 'naive-ui'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { useTabsViewStore } from '@/store/modules/tabsView'
+import SaveForm from '@components/save-form'
+import Pagination from '@components/pagination'
+import deepClone from '@/utils/deep.clone'
+import SmsConfigAppEdit from '@views/message/message-config/sms/modal/sms-config-app-edit'
+import { sysApplicationPage } from '@views/menu-manage/api'
+import TheTooltip from '@components/TheTooltip'
+import {
+  smsAppConfigPage,
+  smsAppConfigRemove,
+  smsAppConfigStatus,
+  smsConfigDetail
+} from '@views/message/api'
+
+export default defineComponent({
+  name: 'sms-config-app',
+  setup(props, ctx) {
+    const dialog = useDialog()
+    const route = useRoute()
+    const message = useMessage()
+    const router = useRouter()
+    const state = reactive({
+      loading: false,
+      appId: null as any,
+      pagination: {
+        page: 1,
+        rows: 10,
+        pageTotal: 0
+      },
+      searchForm: {
+        keyword: null, //关键字
+        status: null // 状态
+      },
+      name: null as any,
+      smsConfigId: null as any,
+      dataList: [],
+      showEdit: false,
+      editMode: 'add',
+      editRowData: {} as any,
+      appData: [] as any,
+      appMap: new Map()
+    })
+    const tabsViewStore = useTabsViewStore()
+    const gotoBack = () => {
+      tabsViewStore.closeCurrentTab(route)
+      router.push({
+        path: '/message/messageConfig'
+      })
+    }
+
+    onMounted(async () => {
+      if (!route.query) {
+        return
+      }
+      state.smsConfigId = route.query.id
+      {
+        const { data } = await smsConfigDetail(state.smsConfigId)
+        if (data) {
+          state.name = data.name
+        }
+      }
+
+      // 应用
+      {
+        state.appData = []
+        const { data } = await sysApplicationPage({ page: 1, rows: 999 })
+        if (data && data.rows) {
+          data.rows.forEach((item: any) => {
+            state.appData.push({ label: item.appName, value: item.appKey })
+            state.appMap.set(item.appKey, item.appName)
+          })
+        }
+      }
+      getList()
+    })
+
+    const saveForm = ref()
+    const onSearch = () => {
+      saveForm.value?.submit()
+    }
+    const onBtnReset = () => {
+      saveForm.value?.reset()
+    }
+
+    const onSubmit = () => {
+      state.pagination.page = 1
+      getList()
+    }
+
+    const getList = async () => {
+      if (!state.smsConfigId) {
+        return
+      }
+      try {
+        state.loading = true
+        const { data } = await smsAppConfigPage({
+          ...state.pagination,
+          ...state.searchForm,
+          sysConfigId: state.smsConfigId
+        })
+        state.pagination.pageTotal = Number(data.total)
+        state.dataList = data.rows || []
+      } catch {}
+      state.loading = false
+    }
+
+    const onChangeStatus = (row: any) => {
+      const statusStr = row.status ? '停用' : '启用'
+      dialog.warning({
+        title: '提示',
+        content: `是否${statusStr}?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await smsAppConfigStatus({
+              id: row.id,
+              status: !row.status
+            })
+            getList()
+            message.success(`${statusStr}成功`)
+          } catch {}
+        }
+      })
+    }
+
+    const onRmove = (row: any): void => {
+      dialog.warning({
+        title: '提示',
+        content: `删除"${row.name}",是否继续?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await smsAppConfigRemove(row.id)
+            getList()
+            message.success('删除成功')
+          } catch {}
+        }
+      })
+    }
+
+    const columns = (): any => {
+      return [
+        {
+          title: '编号',
+          key: 'id'
+        },
+        {
+          title: '应用',
+          key: 'appKey',
+          render(row: any) {
+            return state.appMap.get(row.appKey)
+          }
+        },
+        {
+          title: '签名',
+          key: 'sign'
+        },
+        {
+          title: '拓展参数',
+          key: 'extendData',
+          render: (row: any) => {
+            return <TheTooltip content={row.extendData} />
+          }
+        },
+        {
+          title: '状态',
+          key: 'status',
+          render(row: any) {
+            return (
+              <NTag type={row.status ? 'primary' : 'default'}>{row.status ? '启用' : '停用'}</NTag>
+            )
+          }
+        },
+        {
+          title: '操作',
+          key: 'operation',
+          fixed: 'right',
+          render(row: any) {
+            return (
+              <NSpace>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="smsAppConfig/status1790942026752135170"
+                  onClick={() => {
+                    onChangeStatus(row)
+                  }}
+                >
+                  {row.status ? '停用' : '启用'}
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="smsAppConfig/update1790942447902199809"
+                  onClick={() => {
+                    state.showEdit = true
+                    state.editRowData = deepClone(row)
+                    state.editMode = 'edit'
+                  }}
+                >
+                  修改
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="smsAppConfig/remove1790942087347245058"
+                  disabled={!!row.status}
+                  onClick={() => {
+                    onRmove(row)
+                  }}
+                >
+                  删除
+                </NButton>
+              </NSpace>
+            )
+          }
+        }
+      ]
+    }
+
+    return () => (
+      <div class="system-menu-container">
+        <NPageHeader on-back={() => gotoBack()} title={state.name}></NPageHeader>
+        <div class={['section-container']}>
+          <div class="system-menu-container">
+            <SaveForm
+              ref={saveForm}
+              model={state.searchForm}
+              onSubmit={onSubmit}
+              saveKey="sms-config-app"
+              onSetModel={(val: any) => (state.searchForm = val)}
+            >
+              <NFormItem label="关键字" path="keyword">
+                <NInput
+                  placeholder="应用编号/名称"
+                  v-model:value={state.searchForm.keyword}
+                  clearable
+                />
+              </NFormItem>
+              <NFormItem label="状态" path="status">
+                <NSelect
+                  v-model:value={state.searchForm.status}
+                  clearable
+                  options={
+                    [
+                      {
+                        label: '启用',
+                        value: 1
+                      },
+                      {
+                        label: '停用',
+                        value: 0
+                      }
+                    ] as any
+                  }
+                  placeholder="全部状态"
+                />
+              </NFormItem>
+              <NFormItem>
+                <NSpace>
+                  <NButton type="primary" onClick={onSearch}>
+                    搜索
+                  </NButton>
+                  <NButton type="default" onClick={onBtnReset}>
+                    重置
+                  </NButton>
+                </NSpace>
+              </NFormItem>
+            </SaveForm>
+
+            <NSpace style={{ paddingBottom: '12px' }}>
+              <NButton
+                type="primary"
+                v-auth="smsAppConfig/save1790942383565770753"
+                onClick={() => {
+                  state.showEdit = true
+                  state.editMode = 'add'
+                }}
+              >
+                新增应用
+              </NButton>
+            </NSpace>
+
+            <div class={['section-container']}>
+              <NDataTable
+                loading={state.loading}
+                columns={columns()}
+                data={state.dataList}
+                rowKey={(row: any) => row.id}
+                scrollX={'1400'}
+              ></NDataTable>
+
+              <Pagination
+                v-model:page={state.pagination.page}
+                v-model:pageSize={state.pagination.rows}
+                v-model:pageTotal={state.pagination.pageTotal}
+                onList={getList}
+                sync
+                saveKey="sms-config-app"
+              ></Pagination>
+            </div>
+            <NModal
+              blockScroll={true}
+              v-model:show={state.showEdit}
+              preset="dialog"
+              showIcon={false}
+              title={(state.editMode == 'add' ? '新增' : '编辑') + '应用'}
+              style={{ width: '700px' }}
+            >
+              <SmsConfigAppEdit
+                editMode={state.editMode}
+                rowData={state.editRowData}
+                appData={state.appData}
+                smsConfigId={state.smsConfigId}
+                onClose={() => (state.showEdit = false)}
+                onGetList={() => {
+                  state.pagination.page = 1
+                  getList()
+                }}
+              />
+            </NModal>
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 327 - 0
src/views/message/message-config/sms/sms-config.tsx

@@ -0,0 +1,327 @@
+import { defineComponent, onMounted, reactive, ref } from 'vue'
+import SaveForm from '@components/save-form'
+import {
+  DataTableRowKey,
+  NButton,
+  NDataTable,
+  NFormItem,
+  NInput,
+  NModal,
+  NSelect,
+  NSpace,
+  NTag,
+  useDialog,
+  useMessage
+} from 'naive-ui'
+import Pagination from '@components/pagination'
+import SmsConfigEdit from '@views/message/message-config/sms/modal/sms-config-edit'
+import deepClone from '@/utils/deep.clone'
+import { useRouter } from 'vue-router'
+import TheTooltip from '@components/TheTooltip'
+import { smsConfigPage, smsConfigRemove, smsConfigStatus } from '@views/message/api'
+
+export default defineComponent({
+  name: 'sms-config',
+
+  setup(props) {
+    const router = useRouter()
+    const dialog = useDialog()
+    const message = useMessage()
+    const state = reactive({
+      loading: false,
+      appId: null as any,
+      pagination: {
+        page: 1,
+        rows: 10,
+        pageTotal: 0
+      },
+      searchForm: {
+        keyword: null, //关键字
+        status: null // 状态
+      },
+      dataList: [],
+      showEdit: false,
+      editMode: 'add',
+      editRowData: {} as any
+    })
+
+    onMounted(async () => {
+      getList()
+    })
+
+    const saveForm = ref()
+
+    const onSearch = () => {
+      saveForm.value?.submit()
+    }
+    const onBtnReset = () => {
+      saveForm.value?.reset()
+    }
+
+    const onSubmit = () => {
+      state.pagination.page = 1
+      getList()
+    }
+
+    const checkedRowKeysRef = ref<DataTableRowKey[]>([])
+    const handleCheck = (rowKeys: DataTableRowKey[]) => {
+      checkedRowKeysRef.value = rowKeys
+    }
+
+    const getList = async () => {
+      try {
+        state.loading = true
+        const { data } = await smsConfigPage({
+          ...state.pagination,
+          ...state.searchForm
+        })
+        state.pagination.pageTotal = Number(data.total)
+        state.dataList = data.rows || []
+        // state.dataList = []
+      } catch {}
+      state.loading = false
+    }
+
+    const onChangeStatus = (row: any) => {
+      const statusStr = row.status ? '停用' : '启用'
+      dialog.warning({
+        title: '提示',
+        content: `是否${statusStr}?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await smsConfigStatus({
+              id: row.id,
+              status: !row.status
+            })
+            getList()
+            message.success(`${statusStr}成功`)
+          } catch {}
+        }
+      })
+    }
+
+    const onRmove = (row: any): void => {
+      dialog.warning({
+        title: '提示',
+        content: `删除"${row.name}",是否继续?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await smsConfigRemove(row.id)
+            getList()
+            message.success('删除成功')
+          } catch {}
+        }
+      })
+    }
+
+    const columns = (): any => {
+      return [
+        {
+          title: '编号',
+          key: 'id'
+        },
+        {
+          title: '平台名称',
+          key: 'name'
+        },
+        {
+          title: '平台标识',
+          key: 'sender'
+        },
+        {
+          title: '接入地址',
+          key: 'accessUrl'
+        },
+        {
+          title: '应用ID',
+          key: 'appId'
+        },
+        {
+          title: '接入账号',
+          key: 'account'
+        },
+        {
+          title: '接入密码',
+          key: 'password'
+        },
+        {
+          title: '拓展参数',
+          key: 'extendData',
+          render: (row: any) => {
+            return <TheTooltip content={row.extendData} />
+          }
+        },
+        {
+          title: '状态',
+          key: 'status',
+          render(row: any) {
+            return (
+              <NTag type={row.status ? 'primary' : 'default'}>{row.status ? '启用' : '停用'}</NTag>
+            )
+          }
+        },
+        {
+          title: '操作',
+          key: 'operation',
+          fixed: 'right',
+          render(row: any) {
+            return (
+              <NSpace>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="message/messageConfigApp1788130264099217409"
+                  onClick={() => {
+                    router.push({
+                      path: '/message/messageConfigApp',
+                      query: {
+                        id: row.id
+                      }
+                    })
+                  }}
+                >
+                  应用详情
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  v-auth="smsConfig/status1790932263540690945"
+                  text
+                  onClick={() => onChangeStatus(row)}
+                >
+                  {row.status ? '停用' : '启用'}
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="smsConfig/update1790932998848319490"
+                  onClick={() => {
+                    state.showEdit = true
+                    state.editRowData = deepClone(row)
+                    state.editMode = 'edit'
+                  }}
+                >
+                  修改
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="smsConfig/remove1790932360940818433"
+                  disabled={!!row.status}
+                  onClick={() => onRmove(row)}
+                >
+                  删除
+                </NButton>
+              </NSpace>
+            )
+          }
+        }
+      ]
+    }
+
+    return () => {
+      return (
+        <div class="system-menu-container">
+          <SaveForm
+            ref={saveForm}
+            model={state.searchForm}
+            onSubmit={onSubmit}
+            saveKey="sms-config"
+            onSetModel={(val: any) => (state.searchForm = val)}
+          >
+            <NFormItem label="关键字" path="keyword">
+              <NInput placeholder="编号/名称" v-model:value={state.searchForm.keyword} clearable />
+            </NFormItem>
+            <NFormItem label="状态" path="status">
+              <NSelect
+                v-model:value={state.searchForm.status}
+                clearable
+                options={
+                  [
+                    {
+                      label: '启用',
+                      value: 1
+                    },
+                    {
+                      label: '停用',
+                      value: 0
+                    }
+                  ] as any
+                }
+                placeholder="全部状态"
+              />
+            </NFormItem>
+            <NFormItem>
+              <NSpace>
+                <NButton type="primary" onClick={onSearch}>
+                  搜索
+                </NButton>
+                <NButton type="default" onClick={onBtnReset}>
+                  重置
+                </NButton>
+              </NSpace>
+            </NFormItem>
+          </SaveForm>
+
+          <NSpace style={{ paddingBottom: '12px' }}>
+            <NButton
+              type="primary"
+              v-auth="smsConfig/save1790932891084066817"
+              onClick={() => {
+                state.showEdit = true
+                state.editMode = 'add'
+              }}
+            >
+              新增短信平台
+            </NButton>
+          </NSpace>
+
+          <div class={['section-container']}>
+            <NDataTable
+              loading={state.loading}
+              columns={columns()}
+              data={state.dataList}
+              rowKey={(row: any) => row.id}
+              scrollX={'1400'}
+            ></NDataTable>
+
+            <Pagination
+              v-model:page={state.pagination.page}
+              v-model:pageSize={state.pagination.rows}
+              v-model:pageTotal={state.pagination.pageTotal}
+              onList={getList}
+              sync
+              saveKey="sms-config"
+            ></Pagination>
+          </div>
+          <NModal
+            blockScroll={true}
+            v-model:show={state.showEdit}
+            preset="dialog"
+            showIcon={false}
+            title={(state.editMode == 'add' ? '新增' : '编辑') + '短信平台'}
+            // style={{width: 'auto'}}
+            style={{ width: '700px' }}
+          >
+            <SmsConfigEdit
+              editMode={state.editMode}
+              rowData={state.editRowData}
+              onClose={() => (state.showEdit = false)}
+              onGetList={() => {
+                state.pagination.page = 1
+                getList()
+              }}
+            />
+          </NModal>
+        </div>
+      )
+    }
+  }
+})

+ 229 - 0
src/views/message/message-config/wechat/modal/wechat-config-edit.tsx

@@ -0,0 +1,229 @@
+import {defineComponent, onMounted, reactive, ref} from "vue";
+import {NButton, NForm, NFormItemGi, NGrid, NInput, NSelect, NSpace, useMessage} from "naive-ui";
+import {wxConfigInfoSave, wxConfigInfoUpdate} from "@views/message/api";
+
+export default defineComponent({
+  mpName: 'wechat-config-edit',
+  props: {
+    editMode: {
+      type: String,
+      required: true
+    },
+    rowData: {
+      type: Object,
+      required: false
+    },
+    appData: {
+      type: Array as any,
+      required: true
+    }
+  },
+  emits: ['close', 'getList'],
+  setup(props, {slots, attrs, emit}) {
+
+
+    const message = useMessage()
+    const btnLoading = ref(false)
+    const forms = reactive({
+      mpName: null, //公众号名称
+      appid: null, //公众号ID
+      secret: null, //接入密钥
+      token: null, //消息密钥
+      aeskey: null, //加密模式密钥
+      appKey: null, //应用
+      content: null, //关注公众号提示信息
+    })
+    const formsRef = ref()
+
+    const state = reactive({
+      rowData: null as any,
+    })
+
+    onMounted(async () => {
+      state.rowData = props.rowData
+      if (props.editMode == 'edit' && props.rowData) {
+        forms.mpName = state.rowData.mpName
+        forms.appid = state.rowData.appid
+        forms.secret = state.rowData.secret
+        forms.token = state.rowData.token
+        forms.aeskey = state.rowData.aeskey
+        forms.appKey = state.rowData.appKey
+        forms.content = state.rowData.content
+      }
+    })
+
+    const onSubmit = async () => {
+      formsRef.value.validate(async (error: any) => {
+        if (error) return false
+        btnLoading.value = true
+        try {
+          let res;
+          if (props.editMode == 'add') {
+            res = await wxConfigInfoSave(
+                {
+                  ...forms,
+                }
+            ) as any;
+          } else {
+            res = await wxConfigInfoUpdate(
+                {
+                  ...forms,
+                  id: state.rowData.id
+                }
+            ) as any;
+          }
+          if (res && res.code === 200) {
+            emit('close')
+            emit('getList')
+          }
+        } catch (error) {
+        }
+        btnLoading.value = false
+      })
+    }
+
+    return () => {
+      return (
+          <div style="background: #fff; padding-top: 12px">
+            <NForm
+                ref={formsRef}
+                labelPlacement="top"
+                model={forms}
+                label-placement="left"
+                label-width="100"
+            >
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="公众号名称"
+                    path="mpName"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入公众号名称'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.mpName}
+                      placeholder="请输入公众号名称"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="公众号ID"
+                    path="appid"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入公众号ID'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.appid}
+                      placeholder="请输入公众号ID"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="接入密钥"
+                    path="secret"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入接入密钥'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.secret}
+                      placeholder="请输入接入密钥"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="消息密钥"
+                    path="token"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入消息密钥'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.token}
+                      placeholder="请输入消息密钥"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="加密模式密钥"
+                    path="aeskey"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入加密模式密钥'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.aeskey}
+                      placeholder="请输入加密模式密钥"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="应用"
+                    path="appKey"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择应用'
+                      }
+                    ]}
+                >
+                  <NSelect
+                      placeholder="请选择应用"
+                      v-model:value={forms.appKey}
+                      options={props.appData}
+                      clearable
+                  />
+                </NFormItemGi>
+              </NGrid>
+              <NGrid cols={1}>
+                <NFormItemGi
+                    label="关注公众号提示信息"
+                    path="content"
+                    rule={[
+                      {
+                        required: true,
+                        message: '关注公众号提示信息'
+                      }
+                    ]}
+                >
+                  <NInput
+                      type={'textarea'}
+                      v-model:value={forms.content}
+                      placeholder="关注公众号提示信息"
+                      autosize={{minRows:3}}
+                      clearable
+                  />
+                </NFormItemGi>
+              </NGrid>
+            </NForm>
+
+            <NSpace justify="end">
+              <NButton onClick={() => emit('close')}>取消</NButton>
+              <NButton type="primary" onClick={onSubmit}
+                       loading={btnLoading.value}
+                       disabled={btnLoading.value}
+              >
+                保存
+              </NButton>
+            </NSpace>
+          </div>
+      )
+    }
+  }
+})

+ 218 - 0
src/views/message/message-config/wechat/modal/wechat-config-template-edit.tsx

@@ -0,0 +1,218 @@
+import {defineComponent, onMounted, reactive, ref} from "vue";
+import {NButton, NForm, NFormItemGi, NGrid, NInput, NSpace, useMessage} from "naive-ui";
+import {wxTemplateConfigSave, wxTemplateConfigUpdate} from "@views/message/api";
+
+export default defineComponent({
+  mpName: 'wechat-config-template-edit',
+  props: {
+    appid: {
+      type: String,
+      required: false
+    },
+    editMode: {
+      type: String,
+      required: true
+    },
+    rowData: {
+      type: Object,
+      required: false
+    },
+  },
+  emits: ['close', 'getList'],
+  setup(props, {slots, attrs, emit}) {
+    const message = useMessage()
+    const btnLoading = ref(false)
+    const forms = reactive({
+      wxTemplateId: null, //微信模板id
+      command: null, //指令
+      url: null, //模板消息地址
+      description: null, //描述
+      content: {
+        content: null,
+        title: null,
+      } as any
+    })
+    const formsRef = ref()
+
+    const state = reactive({
+      rowData: null as any,
+    })
+
+    onMounted(async () => {
+      if (!props.appid) {
+        return
+      }
+      state.rowData = props.rowData
+      if (props.editMode == 'edit' && props.rowData) {
+        forms.command = state.rowData.command
+        forms.wxTemplateId = state.rowData.wxTemplateId
+        forms.url = state.rowData.url
+        forms.description = state.rowData.description
+        if (state.rowData.content) {
+          forms.content.content = state.rowData.content.content
+          forms.content.title = state.rowData.content.title
+        }
+      }
+    })
+
+    const onSubmit = async () => {
+      formsRef.value.validate(async (error: any) => {
+        if (error) return false
+        btnLoading.value = true
+        try {
+          let res;
+          if (props.editMode == 'add') {
+            res = await wxTemplateConfigSave(
+                {
+                  ...forms,
+                  appid: props.appid
+                }
+            ) as any;
+          } else {
+            res = await wxTemplateConfigUpdate(
+                {
+                  ...forms,
+                  id: state.rowData.id,
+                  appid: props.appid
+                }
+            ) as any;
+          }
+          if (res && res.code === 200) {
+            emit('close')
+            emit('getList')
+          }
+        } catch (error) {
+        }
+        btnLoading.value = false
+      })
+    }
+
+    return () => {
+      return (
+          <div style="background: #fff; padding-top: 12px">
+            <NForm
+                ref={formsRef}
+                labelPlacement="top"
+                model={forms}
+                label-placement="left"
+                label-width="100"
+            >
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="标题"
+                    path="content.title"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入标题'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.content.title}
+                      placeholder="请输入标题"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="指令"
+                    path="command"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入指令'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.command}
+                      placeholder="请输入指令"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="模板ID"
+                    path="wxTemplateId"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入模板ID'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.wxTemplateId}
+                      placeholder="请输入模板ID"
+                      clearable
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="模板地址"
+                    path="appid"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请输入模板地址'
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.url}
+                      placeholder="请输入模板地址"
+                      clearable
+                  />
+                </NFormItemGi>
+
+              </NGrid>
+              <NGrid cols={1}>
+                <NFormItemGi
+                    label="内容"
+                    path="content.content"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入内容'
+                      }
+                    ]}
+                >
+                  <NInput
+                      type={'textarea'}
+                      v-model:value={forms.content.content}
+                      placeholder="请输入内容"
+                      autosize={{minRows:3}}
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="描述"
+                    path="description"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请输入描述'
+                      }
+                    ]}
+                >
+                  <NInput
+                      type={'textarea'}
+                      v-model:value={forms.description}
+                      placeholder="请输入描述"
+                      autosize={{minRows:3}}
+                  />
+                </NFormItemGi>
+              </NGrid>
+            </NForm>
+
+            <NSpace justify="end">
+              <NButton onClick={() => emit('close')}>取消</NButton>
+              <NButton type="primary" onClick={onSubmit}
+                       loading={btnLoading.value}
+                       disabled={btnLoading.value}
+              >
+                保存
+              </NButton>
+            </NSpace>
+          </div>
+      )
+    }
+  }
+})

+ 342 - 0
src/views/message/message-config/wechat/wechat-config-template-message.tsx

@@ -0,0 +1,342 @@
+import {
+  NButton,
+  NDataTable,
+  NFormItem,
+  NInput,
+  NModal,
+  NPageHeader,
+  NSelect,
+  NSpace,
+  NTag,
+  useDialog,
+  useMessage
+} from 'naive-ui'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { useTabsViewStore } from '@/store/modules/tabsView'
+import SaveForm from '@components/save-form'
+import Pagination from '@components/pagination'
+import deepClone from '@/utils/deep.clone'
+import WechatConfigTemplateEdit from '@views/message/message-config/wechat/modal/wechat-config-template-edit'
+import {
+  wxTemplateConfigDetail,
+  wxTemplateConfigRemove,
+  wxTemplateConfigStatus,
+  wxTemplateMessagePage
+} from '@views/message/api'
+
+export default defineComponent({
+  name: 'wechat-config-template',
+  setup(props, ctx) {
+    const route = useRoute()
+    const router = useRouter()
+    const dialog = useDialog()
+    const message = useMessage()
+    const state = reactive({
+      loading: false,
+      pagination: {
+        page: 1,
+        rows: 10,
+        pageTotal: 0
+      },
+      searchForm: {
+        keyword: null, //关键字
+        status: null // 状态
+      },
+      dataList: [],
+      showEdit: false,
+      editMode: 'add',
+      editRowData: {} as any,
+      appid: null as any,
+      wxTemplateConfigId: null as any
+    })
+    const tabsViewStore = useTabsViewStore()
+    const gotoBack = () => {
+      tabsViewStore.closeCurrentTab(route)
+      router.push({
+        path: '/message/wxTemplateConfig',
+        query: state.appid
+      })
+    }
+
+    onMounted(async () => {
+      state.wxTemplateConfigId = route.query
+      if (!state.wxTemplateConfigId) {
+        return
+      }
+      {
+        const { data } = await wxTemplateConfigDetail(state.wxTemplateConfigId)
+        if (data) {
+          state.appid = data.appid
+        } else {
+          return
+        }
+      }
+      getList()
+    })
+
+    const saveForm = ref()
+    const onSearch = () => {
+      saveForm.value?.submit()
+    }
+    const onBtnReset = () => {
+      saveForm.value?.reset()
+    }
+
+    const onSubmit = () => {
+      state.pagination.page = 1
+      getList()
+    }
+
+    const getList = async () => {
+      if (!state.appid) {
+        return
+      }
+      try {
+        state.loading = true
+        const { data } = await wxTemplateMessagePage({
+          ...state.pagination,
+          ...state.searchForm,
+          appid: state.appid
+        })
+        state.pagination.pageTotal = Number(data.total)
+        state.dataList = data.rows || []
+      } catch {}
+      state.loading = false
+    }
+
+    const onChangeStatus = (row: any) => {
+      const statusStr = row.status ? '停用' : '启用'
+      dialog.warning({
+        title: '提示',
+        content: `是否${statusStr}?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await wxTemplateConfigStatus({
+              id: row.id,
+              status: !row.status
+            })
+            getList()
+            message.success(`${statusStr}成功`)
+          } catch {}
+        }
+      })
+    }
+
+    const onRmove = (row: any): void => {
+      dialog.warning({
+        title: '提示',
+        content: `删除"${row.name}",是否继续?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await wxTemplateConfigRemove(row.id)
+            getList()
+            message.success('删除成功')
+          } catch {}
+        }
+      })
+    }
+
+    const columns = (): any => {
+      return [
+        {
+          title: '编号',
+          key: 'id'
+        },
+        {
+          title: '应用标志',
+          key: 'command'
+        },
+        {
+          title: '指令',
+          key: 'wxTemplateId'
+        },
+        {
+          title: '标题',
+          key: 'url'
+        },
+        {
+          title: '内容',
+          key: 'description'
+        },
+        {
+          title: '版本',
+          key: 'description'
+        },
+        {
+          title: '类型WECHAT',
+          key: 'description'
+        },
+        {
+          title: 'APP',
+          key: 'description'
+        },
+        {
+          title: '描述',
+          key: 'description'
+        },
+        {
+          title: '状态',
+          key: 'status',
+          render(row: any) {
+            return (
+              <NTag type={row.status ? 'primary' : 'default'}>{row.status ? '启用' : '停用'}</NTag>
+            )
+          }
+        },
+        {
+          title: '操作',
+          key: 'operation',
+          fixed: 'right',
+          render(row: any) {
+            return (
+              <NSpace>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  onClick={() => {
+                    onChangeStatus(row)
+                  }}
+                >
+                  {row.status ? '停用' : '启用'}
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  onClick={() => {
+                    state.showEdit = true
+                    state.editRowData = deepClone(row)
+                    state.editMode = 'edit'
+                  }}
+                >
+                  修改
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  disabled={!!row.status}
+                  onClick={() => {
+                    onRmove(row)
+                  }}
+                >
+                  删除
+                </NButton>
+              </NSpace>
+            )
+          }
+        }
+      ]
+    }
+
+    return () => (
+      <div class="system-menu-container">
+        <NPageHeader on-back={() => gotoBack()} title={state.wxTemplateConfigId}></NPageHeader>
+        <div class={['section-container']}>
+          <div class="system-menu-container">
+            <SaveForm
+              ref={saveForm}
+              model={state.searchForm}
+              onSubmit={onSubmit}
+              saveKey="wechat-config-template"
+              onSetModel={(val: any) => (state.searchForm = val)}
+            >
+              <NFormItem label="关键字" path="keyword">
+                <NInput
+                  placeholder="平台编号/名称"
+                  v-model:value={state.searchForm.keyword}
+                  clearable
+                />
+              </NFormItem>
+              <NFormItem label="状态" path="status">
+                <NSelect
+                  v-model:value={state.searchForm.status}
+                  clearable
+                  options={
+                    [
+                      {
+                        label: '启用',
+                        value: 1
+                      },
+                      {
+                        label: '停用',
+                        value: 0
+                      }
+                    ] as any
+                  }
+                  placeholder="全部状态"
+                />
+              </NFormItem>
+              <NFormItem>
+                <NSpace>
+                  <NButton type="primary" onClick={onSearch}>
+                    搜索
+                  </NButton>
+                  <NButton type="default" onClick={onBtnReset}>
+                    重置
+                  </NButton>
+                </NSpace>
+              </NFormItem>
+            </SaveForm>
+
+            <NSpace style={{ paddingBottom: '12px' }}>
+              <NButton
+                type="primary"
+                onClick={() => {
+                  state.showEdit = true
+                  state.editMode = 'add'
+                }}
+              >
+                新增消息内容
+              </NButton>
+            </NSpace>
+
+            <div class={['section-container']}>
+              <NDataTable
+                loading={state.loading}
+                columns={columns()}
+                data={state.dataList}
+                rowKey={(row: any) => row.id}
+                scrollX={'1400'}
+              ></NDataTable>
+
+              <Pagination
+                v-model:page={state.pagination.page}
+                v-model:pageSize={state.pagination.rows}
+                v-model:pageTotal={state.pagination.pageTotal}
+                onList={getList}
+                sync
+                saveKey="wechat-config-template"
+              ></Pagination>
+            </div>
+            <NModal
+              blockScroll={true}
+              v-model:show={state.showEdit}
+              preset="dialog"
+              showIcon={false}
+              title={(state.editMode == 'add' ? '新增' : '编辑') + '模板'}
+              style={{ width: 'auto' }}
+            >
+              <WechatConfigTemplateEdit
+                editMode={state.editMode}
+                rowData={state.editRowData}
+                style={{ width: '450' }}
+                onClose={() => (state.showEdit = false)}
+                onGetList={() => {
+                  state.pagination.page = 1
+                  getList()
+                }}
+              />
+            </NModal>
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 350 - 0
src/views/message/message-config/wechat/wechat-config-template.tsx

@@ -0,0 +1,350 @@
+import {
+  NButton,
+  NDataTable,
+  NFormItem,
+  NInput,
+  NModal,
+  NPageHeader,
+  NSelect,
+  NSpace,
+  NTag,
+  useDialog,
+  useMessage
+} from 'naive-ui'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { useTabsViewStore } from '@/store/modules/tabsView'
+import SaveForm from '@components/save-form'
+import Pagination from '@components/pagination'
+import deepClone from '@/utils/deep.clone'
+import WechatConfigTemplateEdit from '@views/message/message-config/wechat/modal/wechat-config-template-edit'
+import TheTooltip from '@components/TheTooltip'
+import {
+  wxConfigInfoDetail,
+  wxTemplateConfigPage,
+  wxTemplateConfigRemove,
+  wxTemplateConfigStatus
+} from '@views/message/api'
+
+export default defineComponent({
+  name: 'wechat-config-template',
+  setup(props, ctx) {
+    const route = useRoute()
+    const router = useRouter()
+    const dialog = useDialog()
+    const message = useMessage()
+    const state = reactive({
+      loading: false,
+      pagination: {
+        page: 1,
+        rows: 10,
+        pageTotal: 0
+      },
+      searchForm: {
+        keyword: null, //关键字
+        status: null // 状态
+      },
+      mpName: null as any,
+      dataList: [],
+      showEdit: false,
+      editMode: 'add',
+      editRowData: {} as any,
+      wxConfigAppId: null as any,
+      appid: null as any
+    })
+    const tabsViewStore = useTabsViewStore()
+    const gotoBack = () => {
+      tabsViewStore.closeCurrentTab(route)
+      router.push({
+        path: '/message/messageConfig'
+      })
+    }
+
+    onMounted(async () => {
+      if (!route.query) {
+        return
+      }
+      state.wxConfigAppId = route.query.id
+      {
+        const { data } = await wxConfigInfoDetail(state.wxConfigAppId)
+        if (data) {
+          state.appid = data.appid
+          state.mpName = data.mpName
+          state.wxConfigAppId = data.appid
+        } else {
+          return
+        }
+      }
+
+      getList()
+    })
+
+    const saveForm = ref()
+    const onSearch = () => {
+      saveForm.value?.submit()
+    }
+    const onBtnReset = () => {
+      saveForm.value?.reset()
+    }
+
+    const onSubmit = () => {
+      state.pagination.page = 1
+      getList()
+    }
+
+    const getList = async () => {
+      if (!state.wxConfigAppId) {
+        return
+      }
+      try {
+        state.loading = true
+        const { data } = await wxTemplateConfigPage({
+          ...state.pagination,
+          ...state.searchForm,
+          appid: state.wxConfigAppId
+        })
+        state.pagination.pageTotal = Number(data.total)
+        state.dataList = data.rows || []
+      } catch {}
+      state.loading = false
+    }
+
+    const onChangeStatus = (row: any) => {
+      const statusStr = row.status ? '停用' : '启用'
+      dialog.warning({
+        title: '提示',
+        content: `是否${statusStr}?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await wxTemplateConfigStatus({
+              id: row.id,
+              status: !row.status
+            })
+            getList()
+            message.success(`${statusStr}成功`)
+          } catch {}
+        }
+      })
+    }
+
+    const onRmove = (row: any): void => {
+      dialog.warning({
+        title: '提示',
+        content: `删除"${row.name}",是否继续?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await wxTemplateConfigRemove(row.id)
+            getList()
+            message.success('删除成功')
+          } catch {}
+        }
+      })
+    }
+
+    const columns = (): any => {
+      return [
+        {
+          title: '编号',
+          key: 'id'
+        },
+        {
+          title: '指令',
+          key: 'command'
+        },
+        {
+          title: '模板ID',
+          key: 'wxTemplateId'
+        },
+        {
+          title: '模板地址',
+          key: 'url'
+        },
+        {
+          title: '标题',
+          key: 'content.title'
+        },
+        {
+          title: '内容',
+          key: 'content.content',
+          render(row: any) {
+            return <TheTooltip content={row.content.content} />
+          }
+        },
+        {
+          title: '状态',
+          key: 'status',
+          render(row: any) {
+            return (
+              <NTag type={row.status ? 'primary' : 'default'}>{row.status ? '启用' : '停用'}</NTag>
+            )
+          }
+        },
+        {
+          title: '操作',
+          key: 'operation',
+          fixed: 'right',
+          render(row: any) {
+            return (
+              <NSpace>
+                {/*<NButton*/}
+                {/*    type="primary"*/}
+                {/*    size="small"*/}
+                {/*    text*/}
+                {/*    onClick={() => {*/}
+                {/*      router.push({*/}
+                {/*        path: '/message/wxTemplateMessage',*/}
+                {/*        query: row.id*/}
+                {/*      })*/}
+                {/*    }}*/}
+                {/*>*/}
+                {/*  消息内容配置*/}
+                {/*</NButton>*/}
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="wxTemplateConfig/status1790945458334535681"
+                  onClick={() => {
+                    onChangeStatus(row)
+                  }}
+                >
+                  {row.status ? '停用' : '启用'}
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="wxTemplateConfig/update1790945691365871618"
+                  onClick={() => {
+                    state.showEdit = true
+                    state.editRowData = deepClone(row)
+                    state.editMode = 'edit'
+                  }}
+                >
+                  修改
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="wxTemplateConfig/remove1790945187923562498"
+                  disabled={!!row.status}
+                  onClick={() => {
+                    onRmove(row)
+                  }}
+                >
+                  删除
+                </NButton>
+              </NSpace>
+            )
+          }
+        }
+      ]
+    }
+
+    return () => (
+      <div class="system-menu-container">
+        <NPageHeader on-back={() => gotoBack()} title={state.mpName}></NPageHeader>
+        <div class={['section-container']}>
+          <div class="system-menu-container">
+            <SaveForm
+              ref={saveForm}
+              model={state.searchForm}
+              onSubmit={onSubmit}
+              saveKey="wechat-config-template"
+              onSetModel={(val: any) => (state.searchForm = val)}
+            >
+              <NFormItem label="关键字" path="keyword">
+                <NInput placeholder="编号" v-model:value={state.searchForm.keyword} clearable />
+              </NFormItem>
+              <NFormItem label="状态" path="status">
+                <NSelect
+                  v-model:value={state.searchForm.status}
+                  clearable
+                  options={
+                    [
+                      {
+                        label: '启用',
+                        value: 1
+                      },
+                      {
+                        label: '停用',
+                        value: 0
+                      }
+                    ] as any
+                  }
+                  placeholder="全部状态"
+                />
+              </NFormItem>
+              <NFormItem>
+                <NSpace>
+                  <NButton type="primary" onClick={onSearch}>
+                    搜索
+                  </NButton>
+                  <NButton type="default" onClick={onBtnReset}>
+                    重置
+                  </NButton>
+                </NSpace>
+              </NFormItem>
+            </SaveForm>
+
+            <NSpace style={{ paddingBottom: '12px' }}>
+              <NButton
+                type="primary"
+                v-auth="wxTemplateConfig/save1790945603360985090"
+                onClick={() => {
+                  state.showEdit = true
+                  state.editMode = 'add'
+                }}
+              >
+                新增模板
+              </NButton>
+            </NSpace>
+
+            <div class={['section-container']}>
+              <NDataTable
+                loading={state.loading}
+                columns={columns()}
+                data={state.dataList}
+                rowKey={(row: any) => row.id}
+                scrollX={'1400'}
+              ></NDataTable>
+
+              <Pagination
+                v-model:page={state.pagination.page}
+                v-model:pageSize={state.pagination.rows}
+                v-model:pageTotal={state.pagination.pageTotal}
+                onList={getList}
+                sync
+                saveKey="wechat-config-template"
+              ></Pagination>
+            </div>
+            <NModal
+              blockScroll={true}
+              v-model:show={state.showEdit}
+              preset="dialog"
+              showIcon={false}
+              title={(state.editMode == 'add' ? '新增' : '编辑') + '模板'}
+              style={{ width: '700px' }}
+            >
+              <WechatConfigTemplateEdit
+                appid={state.appid}
+                editMode={state.editMode}
+                rowData={state.editRowData}
+                onClose={() => (state.showEdit = false)}
+                onGetList={() => {
+                  state.pagination.page = 1
+                  getList()
+                }}
+              />
+            </NModal>
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 355 - 0
src/views/message/message-config/wechat/wechat-config.tsx

@@ -0,0 +1,355 @@
+import {
+  NButton,
+  NDataTable,
+  NFormItem,
+  NInput,
+  NModal,
+  NSelect,
+  NSpace,
+  NTag,
+  useDialog,
+  useMessage
+} from 'naive-ui'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { useTabsViewStore } from '@/store/modules/tabsView'
+import SaveForm from '@components/save-form'
+import Pagination from '@components/pagination'
+import deepClone from '@/utils/deep.clone'
+import WechatConfigEdit from '@views/message/message-config/wechat/modal/wechat-config-edit'
+import { sysApplicationPage } from '@views/menu-manage/api'
+import { getMapValueByKey } from '@/utils/objectUtil'
+import { appKey } from '@/utils/constant'
+import { wxConfigInfoPage, wxConfigInfoRemove, wxConfigInfoStatus } from '@views/message/api'
+
+export default defineComponent({
+  name: 'wechat-config',
+  setup(props, ctx) {
+    const route = useRoute()
+    const router = useRouter()
+    const dialog = useDialog()
+    const message = useMessage()
+    const state = reactive({
+      loading: false,
+      appId: null as any,
+      pagination: {
+        page: 1,
+        rows: 10,
+        pageTotal: 0
+      },
+      searchForm: {
+        keyword: null, //关键字
+        appKey: null, //应用
+        status: null // 状态
+      },
+      name: null as any,
+      dataList: [],
+      showEdit: false,
+      editMode: 'add',
+      editRowData: {} as any,
+      appData: [] as any
+    })
+    const tabsViewStore = useTabsViewStore()
+    const gotoBack = () => {
+      tabsViewStore.closeCurrentTab(route)
+      router.push({
+        path: '/message/messageConfig'
+      })
+    }
+
+    onMounted(async () => {
+      state.appData = []
+      const { data } = await sysApplicationPage({ page: 1, rows: 999 })
+      if (data && data.rows) {
+        data.rows.forEach((item: any) => {
+          state.appData.push({ label: item.appName, value: item.appKey })
+        })
+      }
+
+      getList()
+    })
+
+    const saveForm = ref()
+    const onSearch = () => {
+      saveForm.value?.submit()
+    }
+    const onBtnReset = () => {
+      saveForm.value?.reset()
+    }
+
+    const onSubmit = () => {
+      state.pagination.page = 1
+      getList()
+    }
+
+    const getList = async () => {
+      try {
+        state.loading = true
+        const { data } = await wxConfigInfoPage({
+          ...state.pagination,
+          ...state.searchForm
+        })
+        state.pagination.pageTotal = Number(data.total)
+        state.dataList = data.rows || []
+      } catch {}
+      state.loading = false
+    }
+
+    const onChangeStatus = (row: any) => {
+      const statusStr = row.status ? '停用' : '启用'
+      dialog.warning({
+        title: '提示',
+        content: `是否${statusStr}?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await wxConfigInfoStatus({
+              id: row.id,
+              status: !row.status
+            })
+            getList()
+            message.success(`${statusStr}成功`)
+          } catch {}
+        }
+      })
+    }
+
+    const onRmove = (row: any): void => {
+      dialog.warning({
+        title: '提示',
+        content: `删除"${row.name}",是否继续?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await wxConfigInfoRemove(row.id)
+            getList()
+            message.success('删除成功')
+          } catch {}
+        }
+      })
+    }
+
+    const columns = (): any => {
+      return [
+        {
+          title: '编号',
+          key: 'id'
+        },
+        {
+          title: '应用',
+          key: 'appKey',
+          render(row: any) {
+            return <div>{getMapValueByKey(row.appKey, new Map(Object.entries(appKey)))}</div>
+          }
+        },
+        {
+          title: '公众号名称',
+          key: 'mpName'
+        },
+        {
+          title: '公众号ID',
+          key: 'appid'
+        },
+        {
+          title: '接入密钥',
+          key: 'secret'
+        },
+        {
+          title: '消息密钥',
+          key: 'token'
+        },
+        {
+          title: '加密模式密钥',
+          key: 'aeskey'
+        },
+        {
+          title: '状态',
+          key: 'status',
+          render(row: any) {
+            return (
+              <NTag type={row.status ? 'primary' : 'default'}>{row.status ? '启用' : '停用'}</NTag>
+            )
+          }
+        },
+        {
+          title: '操作',
+          key: 'operation',
+          fixed: 'right',
+          render(row: any) {
+            return (
+              <NSpace>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="message/wxTemplateConfig1788457824507092993"
+                  onClick={() => {
+                    router.push({
+                      path: '/message/wxTemplateConfig',
+                      query: {
+                        id: row.id
+                      }
+                    })
+                  }}
+                >
+                  查看模板
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="wxConfigInfo/status1790934722325581825"
+                  onClick={() => {
+                    onChangeStatus(row)
+                  }}
+                >
+                  {row.status ? '停用' : '启用'}
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="wxConfigInfo/update1790934555132235777"
+                  onClick={() => {
+                    state.showEdit = true
+                    state.editRowData = deepClone(row)
+                    state.editMode = 'edit'
+                  }}
+                >
+                  修改
+                </NButton>
+                <NButton
+                  type="primary"
+                  size="small"
+                  text
+                  v-auth="wxConfigInfo/remove1790934636120051714"
+                  disabled={!!row.status}
+                  onClick={() => {
+                    onRmove(row)
+                  }}
+                >
+                  删除
+                </NButton>
+              </NSpace>
+            )
+          }
+        }
+      ]
+    }
+
+    return () => (
+      <div class="system-menu-container">
+        <div class={['section-container']}>
+          <div class="system-menu-container">
+            <SaveForm
+              ref={saveForm}
+              model={state.searchForm}
+              onSubmit={onSubmit}
+              saveKey="wechat-config"
+              onSetModel={(val: any) => (state.searchForm = val)}
+            >
+              <NFormItem label="关键字" path="keyword">
+                <NInput
+                  placeholder="应用编号/名称"
+                  v-model:value={state.searchForm.keyword}
+                  clearable
+                />
+              </NFormItem>
+              <NFormItem label="应用" path="appKey">
+                <NSelect
+                  placeholder="请选择应用"
+                  v-model:value={state.searchForm.appKey}
+                  options={state.appData}
+                  clearable
+                />
+              </NFormItem>
+              <NFormItem label="状态" path="status">
+                <NSelect
+                  v-model:value={state.searchForm.status}
+                  clearable
+                  options={
+                    [
+                      {
+                        label: '启用',
+                        value: 1
+                      },
+                      {
+                        label: '停用',
+                        value: 0
+                      }
+                    ] as any
+                  }
+                  placeholder="全部状态"
+                />
+              </NFormItem>
+              <NFormItem>
+                <NSpace>
+                  <NButton type="primary" onClick={onSearch}>
+                    搜索
+                  </NButton>
+                  <NButton type="default" onClick={onBtnReset}>
+                    重置
+                  </NButton>
+                </NSpace>
+              </NFormItem>
+            </SaveForm>
+
+            <NSpace style={{ paddingBottom: '12px' }}>
+              <NButton
+                type="primary"
+                v-auth="wxConfigInfo/save1790934473301364738"
+                onClick={() => {
+                  state.showEdit = true
+                  state.editMode = 'add'
+                }}
+              >
+                新增公众号配置
+              </NButton>
+            </NSpace>
+
+            <div class={['section-container']}>
+              <NDataTable
+                loading={state.loading}
+                columns={columns()}
+                data={state.dataList}
+                rowKey={(row: any) => row.id}
+                scrollX={'1400'}
+              ></NDataTable>
+
+              <Pagination
+                v-model:page={state.pagination.page}
+                v-model:pageSize={state.pagination.rows}
+                v-model:pageTotal={state.pagination.pageTotal}
+                onList={getList}
+                sync
+                saveKey="wechat-config"
+              ></Pagination>
+            </div>
+            <NModal
+              blockScroll={true}
+              v-model:show={state.showEdit}
+              preset="dialog"
+              showIcon={false}
+              title={(state.editMode == 'add' ? '新增' : '编辑') + '短信平台'}
+              // style={{width: 'auto'}}
+              style={{ width: '700px' }}
+            >
+              <WechatConfigEdit
+                editMode={state.editMode}
+                rowData={state.editRowData}
+                appData={state.appData}
+                onClose={() => (state.showEdit = false)}
+                onGetList={() => {
+                  state.pagination.page = 1
+                  getList()
+                }}
+              />
+            </NModal>
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 198 - 0
src/views/message/message-record/email-record.tsx

@@ -0,0 +1,198 @@
+import {defineComponent, onMounted, reactive, ref} from 'vue'
+import SaveForm from '@components/save-form'
+import {DataTableRowKey, NButton, NDataTable, NFormItem, NInput, NSelect, NSpace, useDialog, useMessage} from 'naive-ui'
+import Pagination from '@components/pagination'
+import {getSelectDataFromObj} from '@/utils/objectUtil'
+import {clientType, messageSenderFunctionModule} from '@/utils/constant'
+import {sysMessagePage} from "@views/message/api";
+import TheTooltip from "@components/TheTooltip";
+
+export default defineComponent({
+  name: 'email-record',
+  props: {
+    appKey: {
+      type: String,
+      required: true
+    }
+  },
+
+  setup(props) {
+    const dialog = useDialog()
+    const message = useMessage()
+    const state = reactive({
+      loading: false,
+      appId: null as any,
+      pagination: {
+        page: 1,
+        rows: 10,
+        pageTotal: 0
+      },
+      searchForm: {
+        title: null, //消息名称
+        clientId: null, //客户端
+        model: null, // 功能模块
+        status: null // 状态
+      },
+      dataList: []
+    })
+
+    onMounted(async () => {
+      getList()
+    })
+
+
+    const saveForm = ref()
+
+    const onSearch = () => {
+      saveForm.value?.submit()
+    }
+    const onBtnReset = () => {
+      saveForm.value?.reset()
+    }
+
+    const onSubmit = () => {
+      state.pagination.page = 1
+      getList()
+    }
+
+    const checkedRowKeysRef = ref<DataTableRowKey[]>([])
+    const handleCheck = (rowKeys: DataTableRowKey[]) => {
+      checkedRowKeysRef.value = rowKeys
+    }
+
+    const getList = async () => {
+      try {
+        state.loading = true
+        const {data} = await sysMessagePage({
+          ...state.pagination,
+          ...state.searchForm,
+          appKey: props.appKey,
+          sendMode:'EMAIL',
+        })
+        state.pagination.pageTotal = Number(data.total)
+        state.dataList = data.rows || []
+      } catch {
+      }
+      state.loading = false
+    }
+
+    const columns = (): any => {
+      return [
+        {
+          title: '标题',
+          key: 'title'
+        },
+        {
+          title: '发送时间',
+          key: 'sendTime'
+        },
+        {
+          title: '发送平台',
+          key: 'senderName'
+        },
+        {
+          title: '收件人地址',
+          key: 'receiver'
+        },
+        {
+          title: '正文',
+          key: 'content',
+          render: (row: any) => {
+            return <TheTooltip showContentWidth={300} content={row.content}/>
+          }
+        },
+        {
+          title: '触发条件',
+          key: 'triggerCondition'
+        },
+      ]
+    }
+
+    return () => {
+      return (
+          <div class="system-menu-container">
+            <SaveForm
+                ref={saveForm}
+                model={state.searchForm}
+                onSubmit={onSubmit}
+                saveKey="email-record"
+                onSetModel={(val: any) => (state.searchForm = val)}
+            >
+              <NFormItem label="标题" path="title">
+                <NInput
+                    placeholder="请输入标题"
+                    v-model:value={state.searchForm.title}
+                    clearable
+                />
+              </NFormItem>
+              <NFormItem label="发送对象" path="clientId">
+                <NSelect
+                    placeholder="全部发送对象"
+                    v-model:value={state.searchForm.clientId}
+                    options={getSelectDataFromObj(clientType)}
+                    clearable
+                />
+              </NFormItem>
+              <NFormItem label="功能模块" path="model">
+                <NSelect
+                    filterable
+                    placeholder="全部功能模块"
+                    v-model:value={state.searchForm.model}
+                    options={getSelectDataFromObj(messageSenderFunctionModule)}
+                    clearable
+                ></NSelect>
+              </NFormItem>
+              <NFormItem label="状态" path="status">
+                <NSelect
+                    v-model:value={state.searchForm.status}
+                    placeholder="请选择状态"
+                    options={
+                      [
+                        {
+                          label: '启用',
+                          value: true
+                        },
+                        {
+                          label: '停用',
+                          value: false
+                        }
+                      ] as any
+                    }
+                    clearable
+                />
+              </NFormItem>
+              <NFormItem>
+                <NSpace>
+                  <NButton type="primary" onClick={onSearch}>
+                    搜索
+                  </NButton>
+                  <NButton type="default" onClick={onBtnReset}>
+                    重置
+                  </NButton>
+                </NSpace>
+              </NFormItem>
+            </SaveForm>
+
+            <div class={['section-container']}>
+              <NDataTable
+                  loading={state.loading}
+                  columns={columns()}
+                  data={state.dataList}
+                  rowKey={(row: any) => row.id}
+                  scrollX={'1400'}
+              ></NDataTable>
+
+              <Pagination
+                  v-model:page={state.pagination.page}
+                  v-model:pageSize={state.pagination.rows}
+                  v-model:pageTotal={state.pagination.pageTotal}
+                  onList={getList}
+                  sync
+                  saveKey="email-record"
+              ></Pagination>
+            </div>
+          </div>
+      )
+    }
+  }
+})

+ 82 - 0
src/views/message/message-record/index.tsx

@@ -0,0 +1,82 @@
+import { NTabPane, NTabs } from 'naive-ui'
+import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue'
+import { useRoute } from 'vue-router'
+import { getTabsCache, setTabsCaches } from '@/hooks/use-async'
+import { appKey } from '@/utils/constant'
+import { sysApplicationPage } from '@views/menu-manage/api'
+import SmsRecord from '@views/message/message-record/sms-record'
+import PushRecord from '@views/message/message-record/push-record'
+import WechatRecord from '@views/message/message-record/wechat-record'
+import EmailRecord from '@views/message/message-record/email-record'
+
+export default defineComponent({
+  name: 'message-template-index',
+  setup() {
+    const state = reactive({
+      tabName: 'KT' as 'KT' | 'GYT' | 'KLX' | 'GYM' | 'CBS',
+      appKeyList: [] as any,
+      appNameList: [] as any,
+      messageSendMode: 'SMS' as 'SMS' | 'PUSH' | 'EMAIL' | 'WECHAT'
+    })
+    const tabsInstRef = ref()
+    getTabsCache((val: any) => {
+      if (val.form.tabName) {
+        state.tabName = val.form.tabName
+        nextTick(() => tabsInstRef.value?.syncBarPosition())
+      }
+    })
+    const route = useRoute()
+    const setTabs = (val: any) => {
+      setTabsCaches(val, 'tabName', route)
+    }
+
+    onMounted(async () => {
+      // 获取应用APP信息
+      // const appKeys = Object.keys(appKey)
+      const { data } = await sysApplicationPage({ page: 1, rows: 99, parentId: 0 })
+      const tempList = data.rows || []
+      tempList.forEach((next: any) => {
+        // if (appKeys.includes(next.appKey)) {
+        state.appKeyList.push(next.appKey)
+        state.appNameList.push(next.appName)
+        // }
+      })
+      nextTick(() => tabsInstRef.value?.syncBarPosition())
+    })
+
+    return () => {
+      return (
+        <div class="system-menu-container">
+          <div class={['section-container']} style="padding-top: 0">
+            <NTabs
+              ref={tabsInstRef}
+              type="line"
+              size="large"
+              v-model:value={state.tabName}
+              onUpdate:value={(val: any) => setTabs(val)}
+            >
+              {state.appKeyList.map((app: any, index: number) => (
+                <NTabPane name={app} tab={state.appNameList[index]}>
+                  <NTabs type="card" size="small" v-model:value={state.messageSendMode}>
+                    <NTabPane name={'SMS'} tab={'短信'}>
+                      <SmsRecord appKey={app} />
+                    </NTabPane>
+                    <NTabPane name={'PUSH'} tab={'推送'}>
+                      <PushRecord appKey={app} />
+                    </NTabPane>
+                    <NTabPane name={'WECHAT'} tab={'公众号'}>
+                      <WechatRecord appKey={app} />
+                    </NTabPane>
+                    <NTabPane name={'EMAIL'} tab={'邮件'}>
+                      <EmailRecord appKey={app} />
+                    </NTabPane>
+                  </NTabs>
+                </NTabPane>
+              ))}
+            </NTabs>
+          </div>
+        </div>
+      )
+    }
+  }
+})

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä