From b1bdaa3be6bc37ec2dea407eebf15a764172fdee Mon Sep 17 00:00:00 2001
From: zhouwx <1175765986@qq.com>
Date: 星期一, 14 七月 2025 09:55:23 +0800
Subject: [PATCH] 修改
---
public/scenarioExample.docx | 0
src/views/build/conpanyFunctionConsult/qualityManage/rangeManage/range/index.vue | 55
src/api/supplier/satisaied.js | 36
src/api/selfProblems/plan.js | 36
src/views/work/selfProblems/scenario/index.vue | 222 +++
src/api/supplier/supplierList.js | 36
src/views/work/selfProblems/plan/index.vue | 265 ++++
src/api/selfProblems/nameList.js | 36
src/api/selfProblems/tableList.js | 36
src/views/certificatePdf.vue | 11
src/api/selfProblems/scenario.js | 36
public/planExample.docx | 0
src/components/Tinymce/Tinymce.vue | 6
src/views/work/qualityInfo/supplierQuality/satisfied/components/editDialog.vue | 275 ++++
src/views/work/selfProblems/internalAudit/auditorManage/nameList/components/nameListDialog.vue | 198 +++
src/views/work/selfProblems/internalAudit/auditorManage/tableList/components/editDialog.vue | 253 ++++
src/views/work/selfProblems/plan/components/planDialog.vue | 561 +++++++++
src/views/work/selfProblems/scenario/components/scenarioDialog.vue | 364 +++++
src/views/work/qualityInfo/supplierQuality/supplierList/components/supplierDialog.vue | 219 +++
src/views/work/selfProblems/internalAudit/auditorManage/tableList/index.vue | 228 +++
src/views/work/qualityInfo/supplierQuality/satisfied/index.vue | 316 +++++
public/tinymce/plugins/formatpainter/plugin.min.js | 1
src/views/work/selfProblems/internalAudit/auditorManage/nameList/index.vue | 215 +++
src/views/work/qualityInfo/supplierQuality/supplierList/index.vue | 201 +++
24 files changed, 3,601 insertions(+), 5 deletions(-)
diff --git a/public/planExample.docx b/public/planExample.docx
new file mode 100644
index 0000000..8ee28f6
--- /dev/null
+++ b/public/planExample.docx
Binary files differ
diff --git a/public/scenarioExample.docx b/public/scenarioExample.docx
new file mode 100644
index 0000000..0e2f578
--- /dev/null
+++ b/public/scenarioExample.docx
Binary files differ
diff --git a/public/tinymce/plugins/formatpainter/plugin.min.js b/public/tinymce/plugins/formatpainter/plugin.min.js
new file mode 100644
index 0000000..055e9c7
--- /dev/null
+++ b/public/tinymce/plugins/formatpainter/plugin.min.js
@@ -0,0 +1 @@
+!function(l){"use strict";var e,r,n,t,o,i,m,a,d,u,c,s,v,f,p=function(e){var r=e,n=function(){return r};return{get:n,set:function(e){r=e},clone:function(){return p(n())}}},g=function(e){return parseInt(e,10)},h=function(e,r,n){return{major:e,minor:r,patch:n}},b=function(e){var r=/([0-9]+)\.([0-9]+)\.([0-9]+)(?:(\-.+)?)/.exec(e);return r?h(g(r[1]),g(r[2]),g(r[3])):h(0,0,0)},y=function(e,r){var n=e-r;return 0===n?0:0<n?1:-1},S=function(e,r){return!!e&&-1===function(e,r){var n=y(e.major,r.major);if(0!==n)return n;var t=y(e.minor,r.minor);if(0!==t)return t;var o=y(e.patch,r.patch);return 0!==o?o:0}(b([(n=e).majorVersion,n.minorVersion].join(".").split(".").slice(0,3).join(".")),b(r));var n},O=function(e){return function(){return e}},w=O(!1),N=O(!0),T=w,x=N,E=function(){return k},k=(t={fold:function(e,r){return e()},is:T,isSome:T,isNone:x,getOr:n=function(e){return e},getOrThunk:r=function(e){return e()},getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},getOrNull:function(){return null},getOrUndefined:function(){},or:n,orThunk:r,map:E,ap:E,each:function(){},bind:E,flatten:E,exists:T,forall:x,filter:E,equals:e=function(e){return e.isNone()},equals_:e,toArray:function(){return[]},toString:O("none()")},Object.freeze&&Object.freeze(t),t),A=function(n){var e=function(){return n},r=function(){return o},t=function(e){return e(n)},o={fold:function(e,r){return r(n)},is:function(e){return n===e},isSome:x,isNone:T,getOr:e,getOrThunk:e,getOrDie:e,getOrNull:e,getOrUndefined:e,or:r,orThunk:r,map:function(e){return A(e(n))},ap:function(e){return e.fold(E,function(e){return A(e(n))})},each:function(e){e(n)},bind:t,flatten:e,exists:t,forall:t,filter:function(e){return e(n)?o:k},equals:function(e){return e.is(n)},equals_:function(e,r){return e.fold(T,function(e){return r(n,e)})},toArray:function(){return[n]},toString:function(){return"some("+n+")"}};return o},_={some:A,none:E,from:function(e){return null==e?k:A(e)}},D=function(r){return function(e){return function(e){if(null===e)return"null";var r=typeof e;return"object"===r&&Array.prototype.isPrototypeOf(e)?"array":"object"===r&&String.prototype.isPrototypeOf(e)?"string":r}(e)===r}},C=D("string"),L=D("boolean"),R=D("function"),P=D("number"),F=void 0===(o=Array.prototype.indexOf)?function(e,r){return q(e,r)}:function(e,r){return o.call(e,r)},I=function(e,r){return-1<F(e,r)},j=function(e,r){return V(e,r).isSome()},M=function(e,r){for(var n=e.length,t=new Array(n),o=0;o<n;o++){var i=e[o];t[o]=r(i,o,e)}return t},B=function(e,r){for(var n=[],t=0,o=e.length;t<o;t++){var i=e[t];r(i,t,e)&&n.push(i)}return n},U=function(e,r){for(var n=0,t=e.length;n<t;n++){var o=e[n];if(r(o,n,e))return _.some(o)}return _.none()},V=function(e,r){for(var n=0,t=e.length;n<t;n++)if(r(e[n],n,e))return _.some(n);return _.none()},q=function(e,r){for(var n=0,t=e.length;n<t;++n)if(e[n]===r)return n;return-1},X=Array.prototype.push,z=function(e,r){return function(e){for(var r=[],n=0,t=e.length;n<t;++n){if(!Array.prototype.isPrototypeOf(e[n]))throw new Error("Arr.flatten item "+n+" was not an array, input: "+e);X.apply(r,e[n])}return r}(M(e,r))},H=(Array.prototype.slice,R(Array.from)&&Array.from,Object.keys),W=Object.hasOwnProperty,Y=function(e,r){for(var n=H(e),t=0,o=n.length;t<o;t++){var i=n[t];r(e[i],i,e)}},G=function(t,o){var i={};return Y(t,function(e,r){var n=o(e,r,t);i[n.k]=n.v}),i},$=function(e){return n=function(e){return e},t=[],Y(e,function(e,r){t.push(n(e,r))}),t;var n,t},K=function(e,r){return Z(e,r)?_.from(e[r]):_.none()},Z=function(e,r){return W.call(e,r)},J=(l.Node.ATTRIBUTE_NODE,l.Node.CDATA_SECTION_NODE,l.Node.COMMENT_NODE,l.Node.DOCUMENT_NODE,l.Node.DOCUMENT_TYPE_NODE,l.Node.DOCUMENT_FRAGMENT_NODE,l.Node.ELEMENT_NODE),Q=l.Node.TEXT_NODE,ee=(l.Node.PROCESSING_INSTRUCTION_NODE,l.Node.ENTITY_REFERENCE_NODE,l.Node.ENTITY_NODE,l.Node.NOTATION_NODE,i=Q,function(e){return e.dom().nodeType===i}),re=function(e,r,n){!function(e,r,n){if(!(C(n)||L(n)||P(n)))throw l.console.error("Invalid call to Attr.set. Key ",r,":: Value ",n,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(r,n+"")}(e.dom(),r,n)},ne=function(e,r){var n=e.dom().getAttribute(r);return null===n?void 0:n},te=function(e,r){e.dom().removeAttribute(r)},oe=function(e,r){var n=ne(e,r);return void 0===n||""===n?[]:n.split(" ")},ie=function(e){return void 0!==e.dom().classList},ae=function(e){return oe(e,"class")},ue=function(e,r){return o=r,i=oe(n=e,t="class").concat([o]),re(n,t,i.join(" ")),!0;var n,t,o,i},ce=function(e,r){return o=r,0<(i=B(oe(n=e,t="class"),function(e){return e!==o})).length?re(n,t,i.join(" ")):te(n,t),!1;var n,t,o,i},se=function(e,r){var n;ie(e)?e.dom().classList.remove(r):ce(e,r),0===(ie(n=e)?n.dom().classList:ae(n)).length&&te(n,"class")},fe=function(e){if(null==e)throw new Error("Node cannot be null or undefined");return{dom:O(e)}},le={fromHtml:function(e,r){var n=(r||l.document).createElement("div");if(n.innerHTML=e,!n.hasChildNodes()||1<n.childNodes.length)throw l.console.error("HTML does not have a single root node",e),new Error("HTML must have a single root node");return fe(n.childNodes[0])},fromTag:function(e,r){var n=(r||l.document).createElement(e);return fe(n)},fromText:function(e,r){var n=(r||l.document).createTextNode(e);return fe(n)},fromDom:fe,fromPoint:function(e,r,n){var t=e.dom();return _.from(t.elementFromPoint(r,n)).map(fe)}},me=function(e,r){e.fire("FormatPainterToggle",{state:r})};(a=m||(m={})).Retrival="Retrieval",a.Application="Application",(u=d||(d={})).ListSchema="ListSchema",u.SubstitutionSchema="SubstitionSchema",(s=c||(c={})).InsertUnorderedList="InsertUnorderedList",s.InsertOrderedList="InsertOrderedList",s.InsertDefinitionList="InsertDefinitionList",(f=v||(v={})).Table="Table",f.Unspecified="Unspecified";var de,ve,pe,ge=function(e){var r,n;r=le.fromDom(e.getBody()),n="tox-cursor-format-painter",ie(r)?r.dom().classList.add(n):ue(r,n)},he=function(e,r){var n;n=e,se(le.fromDom(n.getBody()),"tox-cursor-format-painter"),r.set(m.Retrival),me(e,!1)},be=function(e,r){r.get()===m.Application?he(e,r):function(r,n){ge(r),n.set(m.Application),me(r,!0),r.execCommand("mceRetrieveFormats");var e=function(){n.get()===m.Application&&(r.execCommand("mcePaintFormats"),he(r,n)),o()},t=function(e){27===e.keyCode&&(he(r,n),o())};r.on("click",e),r.on("keydown",t);var o=function(){r.off("click",e),r.off("keydown",t)}}(e,r)},ye=(void 0!==l.window?l.window:Function("return this;")(),function(){return Se(0,0)}),Se=function(e,r){return{major:e,minor:r}},Oe={nu:Se,detect:function(e,r){var n=String(r).toLowerCase();return 0===e.length?ye():function(e,r){var n=function(e,r){for(var n=0;n<e.length;n++){var t=e[n];if(t.test(r))return t}}(e,r);if(!n)return{major:0,minor:0};var t=function(e){return Number(r.replace(n,"$"+e))};return Se(t(1),t(2))}(e,n)},unknown:ye},we="Firefox",Ne=function(e,r){return function(){return r===e}},Te=function(e){var r=e.current;return{current:r,version:e.version,isEdge:Ne("Edge",r),isChrome:Ne("Chrome",r),isIE:Ne("IE",r),isOpera:Ne("Opera",r),isFirefox:Ne(we,r),isSafari:Ne("Safari",r)}},xe={unknown:function(){return Te({current:void 0,version:Oe.unknown()})},nu:Te,edge:O("Edge"),chrome:O("Chrome"),ie:O("IE"),opera:O("Opera"),firefox:O(we),safari:O("Safari")},Ee="Windows",ke="Android",Ae="Solaris",_e="FreeBSD",De=function(e,r){return function(){return r===e}},Ce=function(e){var r=e.current;return{current:r,version:e.version,isWindows:De(Ee,r),isiOS:De("iOS",r),isAndroid:De(ke,r),isOSX:De("OSX",r),isLinux:De("Linux",r),isSolaris:De(Ae,r),isFreeBSD:De(_e,r)}},Le={unknown:function(){return Ce({current:void 0,version:Oe.unknown()})},nu:Ce,windows:O(Ee),ios:O("iOS"),android:O(ke),linux:O("Linux"),osx:O("OSX"),solaris:O(Ae),freebsd:O(_e)},Re=function(e,r){var n=String(r).toLowerCase();return U(e,function(e){return e.search(n)})},Pe=function(e,n){return Re(e,n).map(function(e){var r=Oe.detect(e.versionRegexes,n);return{current:e.name,version:r}})},Fe=function(e,n){return Re(e,n).map(function(e){var r=Oe.detect(e.versionRegexes,n);return{current:e.name,version:r}})},Ie=function(e,r){return-1!==e.indexOf(r)},je=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,Me=function(r){return function(e){return Ie(e,r)}},Be=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:function(e){return Ie(e,"edge/")&&Ie(e,"chrome")&&Ie(e,"safari")&&Ie(e,"applewebkit")}},{name:"Chrome",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,je],search:function(e){return Ie(e,"chrome")&&!Ie(e,"chromeframe")}},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:function(e){return Ie(e,"msie")||Ie(e,"trident")}},{name:"Opera",versionRegexes:[je,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:Me("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:Me("firefox")},{name:"Safari",versionRegexes:[je,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:function(e){return(Ie(e,"safari")||Ie(e,"mobile/"))&&Ie(e,"applewebkit")}}],Ue=[{name:"Windows",search:Me("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:function(e){return Ie(e,"iphone")||Ie(e,"ipad")},versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:Me("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"OSX",search:Me("os x"),versionRegexes:[/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:Me("linux"),versionRegexes:[]},{name:"Solaris",search:Me("sunos"),versionRegexes:[]},{name:"FreeBSD",search:Me("freebsd"),versionRegexes:[]}],Ve={browsers:O(Be),oses:O(Ue)},qe=function(e){var r,n,t,o,i,a,u,c,s,f,l,m=Ve.browsers(),d=Ve.oses(),v=Pe(m,e).fold(xe.unknown,xe.nu),p=Fe(d,e).fold(Le.unknown,Le.nu);return{browser:v,os:p,deviceType:(n=v,t=e,o=(r=p).isiOS()&&!0===/ipad/i.test(t),i=r.isiOS()&&!o,a=r.isAndroid()&&3===r.version.major,u=r.isAndroid()&&4===r.version.major,c=o||a||u&&!0===/mobile/i.test(t),s=r.isiOS()||r.isAndroid(),f=s&&!c,l=n.isSafari()&&r.isiOS()&&!1===/safari/i.test(t),{isiPad:O(o),isiPhone:O(i),isTablet:O(c),isPhone:O(f),isTouch:O(s),isAndroid:r.isAndroid,isiOS:r.isiOS,isWebView:O(l)})}},Xe=(pe=!(de=function(){var e=l.navigator.userAgent;return qe(e)}),function(){for(var e=[],r=0;r<arguments.length;r++)e[r]=arguments[r];return pe||(pe=!0,ve=de.apply(null,e)),ve}),ze=J,He=(Xe().browser.isIE(),function(e,r){var n=e.dom();if(n.nodeType!==ze)return!1;if(void 0!==n.matches)return n.matches(r);if(void 0!==n.msMatchesSelector)return n.msMatchesSelector(r);if(void 0!==n.webkitMatchesSelector)return n.webkitMatchesSelector(r);if(void 0!==n.mozMatchesSelector)return n.mozMatchesSelector(r);throw new Error("Browser lacks native selectors")}),We=function(e,r,n){for(var t=e.dom(),o=R(n)?n:O(!1);t.parentNode;){t=t.parentNode;var i=le.fromDom(t);if(r(i))return _.some(i);if(o(i))break}return _.none()},Ye=function(e,r,n){var t,o,i,a,u;return t=We,a=n,u=o=e,(i=r)(u)?_.some(o):R(a)&&a(o)?_.none():t(o,i,a)},Ge={formatpainter_checklist:{selector:"ul",classes:"tox-checklist"},formatpainter_liststyletype:{selector:"ul,ol",styles:{listStyleType:"%value"}},formatpainter_borderstyle:{selector:"td,th",styles:{borderTopStyle:"%valueTop",borderRightStyle:"%valueRight",borderBottomStyle:"%valueBottom",borderLeftStyle:"%valueLeft"},remove_similar:!0},formatpainter_bordercolor:{selector:"td,th",styles:{borderTopColor:"%valueTop",borderRightColor:"%valueRight",borderBottomColor:"%valueBottom",borderLeftColor:"%valueLeft"},remove_similar:!0},formatpainter_backgroundcolor:{selector:"td,th",styles:{backgroundColor:"%value"},remove_similar:!0},formatpainter_removeformat:[{selector:"b,strong,em,i,font,u,strike,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins",remove:"all",split:!0,expand:!1,block_expand:!0,deep:!0},{selector:"span",attributes:["style","class"],remove:"empty",split:!0,expand:!1,deep:!0},{selector:"*:not(tr,td,th,table)",attributes:["style","class"],split:!1,expand:!1,deep:!0}]},$e=function(i,e){return K(e,"selector").exists(function(e){var r=i.getBody(),n=i.selection.getStart(),t=i.dom.getParents(n,O(!0),r),o=i.selection.getSelectedBlocks();return i.dom.is(t.concat(o),e)})},Ke=function(t,e){return j(t.formatter.get(e),function(e){return r=t,Z(n=e,"inline")&&!$e(r,n);var r,n})},Ze=function(t,e,r){return j(e.get(r),function(e){return r=t,Z(n=e,"block")||$e(r,n);var r,n})},Je=function(e){return 1<e.length&&"%"===e.charAt(0)},Qe=function(e,r){return j(e.formatter.get(r),function(e){return n=K(r=e,"styles").exists(function(e){return j($(e),Je)}),t=K(r,"attributes").exists(function(e){return j($(e),Je)}),n||t;var r,n,t})},er=function(e){return He(e,"OL,UL,DL")},rr=function(e){return He(e,"LI,DT,DD")},nr=function(e,r,n){var t,o=e.formatter,i=Ke(e,n.formatName),a=Ze(e,o,n.formatName),u=(t=n.formatName,I(["formatpainter_borderstyle","formatpainter_bordercolor","formatpainter_backgroundcolor"],t));(r.table&&u||r.inline&&i||r.block&&a&&!u)&&o.apply(n.formatName,n.substitutedVariables)},tr=function(e,r){return function(e,r){for(var n=[],t=0;t<e.length;t++){var o=e[t];if(!o.isSome())return _.none();n.push(o.getOrDie())}return _.some(r.apply(null,n))}([Ye(le.fromDom(e.getStart()),er,r),Ye(le.fromDom(e.getEnd()),er,r)],function(e,r){return n=r,e.dom()===n.dom();var n}).getOr(!1)},or=function(e){var r=e.selection,n=r.getRng(),t=le.fromDom(e.getBody()),o=B(e.selection.getSelectedBlocks().map(le.fromDom),rr),i=n.collapsed&&o.length,a=o.length&&!tr(r,t);return 1<o.length||i||a},ir=function(t,e){var r,n;r=t,n=e.context,r.formatter.remove("formatpainter_removeformat"),n===v.Table&&function(e,r){for(var n=0,t=e.length;n<t;n++)r(e[n],n,e)}(["formatpainter_borderstyle","formatpainter_bordercolor","formatpainter_backgroundcolor"],function(e){r.formatter.remove(e)}),or(r)&&r.execCommand("RemoveList");var o,i,a,u,c,s,f=(a=(o=t).selection.getStart(),u=o.selection.getRng().collapsed,c=0<o.dom.select("td[data-mce-selected]").length,s=!!o.dom.getParent(a,"TABLE"),{inline:!0,table:u&&s||c,block:u||(i=o.selection,1<i.getSelectedBlocks().length)||c});e.schemas.forEach(function(e){switch(e.kind){case d.ListSchema:r=t,n=e,f.block&&r.execCommand(n.command);break;case d.SubstitutionSchema:nr(t,f,e)}var r,n})},ar=function(e){return ie(e)?function(e){for(var r=e.dom().classList,n=new Array(r.length),t=0;t<r.length;t++)n[t]=r.item(t);return n}(e):ae(e)},ur=function(e,r){var n,t,o=e.dom(),i=l.window.getComputedStyle(o).getPropertyValue(r),a=""!==i||null!=(t=ee(n=e)?n.dom().parentNode:n.dom())&&t.ownerDocument.body.contains(t)?i:cr(o,r);return null===a?void 0:a},cr=function(e,r){return void 0!==e.style?e.style.getPropertyValue(r):""},sr=function(){return(sr=Object.assign||function(e){for(var r,n=1,t=arguments.length;n<t;n++)for(var o in r=arguments[n])Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o]);return e}).apply(this,arguments)},fr=function(o,e){return G(e,function(e,r){return{k:e.slice(1,e.length),v:(n=o,t=r,"class"===t?ar(n).filter(function(e){return!/^(mce-.*)/.test(e)}).join(" "):ne(n,t))};var n,t})},lr=function(e){return(r=e,n=function(e){return 1<(r=e).length&&"%"===r.charAt(0);var r},t={},o={},Y(r,function(e,r){(n(e,r)?t:o)[r]=e}),{t:t,f:o}).t;var r,n,t,o},mr=function(e,n){var r=K(e,"styles").map(function(e){return t=n,r=lr(e),G(r,function(e,r){return{k:e.slice(1,e.length),v:ur(t,(n=r,n.replace(/([A-Z])/g,function(e){return"-"+e[0].toLowerCase()})))};var n});var t,r}),t=K(e,"attributes").map(function(e){return fr(n,lr(e))}),o=sr({},r.getOr({}),t.getOr({}));return $(o).every(function(e){return""!==e})?_.some(o):_.none()},dr=function(e,r,n){return(t=e.get(r),0===t.length?_.none():_.some(t[0])).bind(function(e){return mr(e,n)}).map(function(e){return{kind:d.SubstitutionSchema,formatName:r,substitutedVariables:e}});var t},vr=function(n,t){return(e=n,r=e.getParam("formatpainter_blacklisted_formats","link,address,removeformat,formatpainter_removeformat","string").split(/[ ,]/),H(e.formatter.get()).filter(function(e){return!I(r,e)})).filter(function(e){var r=Qe(n,e);return n.formatter.matchNode(t.dom(),e,{},r)});var e,r},pr=function(e){return(r=e,U($(c),function(e){return r.queryCommandState(e)})).map(function(e){return{kind:d.ListSchema,command:e}});var r},gr=function(e){var r,n,t,o,i,a=e.dom,u=e.selection.getStart();return{schemas:pr(e).toArray().concat((t=e,o=u,i=t.dom.getParents(o,O(!0)),z(M(i,le.fromDom),function(r){return z(vr(t,r),function(e){return dr(t.formatter,e,r).toArray()})}))),context:(r=a,n=u,r.getParent(n,"TABLE")?v.Table:v.Unspecified)}},hr=function(e){if(S(tinymce,"4.9.0"))return l.window.console.error("The format painter plugin requires at least version 4.9.0 of TinyMCE."),{};var n,r,t,o,i,a,u,c,s=p(m.Retrival),f=p({schemas:[],context:v.Unspecified});return(n=e).on("PreInit",function(){Y(Ge,function(e,r){n.formatter.get(r)||n.formatter.register(r,e)})}),t=s,o=f,(r=e).addCommand("mceToggleFormatPainter",function(){be(r,t)}),r.addCommand("mcePaintFormats",function(){r.undoManager.transact(function(){ir(r,o.get())})}),r.addCommand("mceRetrieveFormats",function(){o.set(gr(r))}),(i=e).ui?(u=i).ui.registry.addToggleButton("formatpainter",{active:!1,icon:"format-painter",tooltip:"Format Painter",onAction:function(){return u.execCommand("mceToggleFormatPainter")},onSetup:function(r){var e=function(e){r.setActive(e.state)};return u.on("FormatPainterToggle",e),function(){return u.off("FormatPainterToggle",e)}}}):(a=i).addButton("formatpainter",{active:!1,icon:"format-painter",tooltip:"Format Painter",cmd:"mceToggleFormatPainter",onPostRender:function(r){a.on("FormatPainterToggle",function(e){r.control.active(e.state)})}}),(c=e).addShortcut("Meta+alt+C","",function(){c.execCommand("mceRetrieveFormats")}),c.addShortcut("Meta+alt+V","",function(){c.execCommand("mcePaintFormats")}),{}};return function(){tinymce.PluginManager.add("formatpainter",hr)}}(window)();
diff --git a/src/api/selfProblems/nameList.js b/src/api/selfProblems/nameList.js
new file mode 100644
index 0000000..c2b51fd
--- /dev/null
+++ b/src/api/selfProblems/nameList.js
@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+
+export function getPersonPage(params) {
+ return request({
+ url: '/internal/audit/person/list',
+ method: 'get',
+ params: params
+ })
+}
+
+
+export function addPerson(data) {
+ return request({
+ url: '/internal/audit/person/insert',
+ method: 'post',
+ data: data
+ })
+}
+
+export function editPerson(params) {
+ return request({
+ url: `/internal/audit/person/update`,
+ method: 'post',
+ data: params
+ })
+}
+
+export function delPerson(data) {
+ return request({
+ url: `/internal/audit/person/deleted?personId=${data}`,
+ method: 'get'
+ })
+}
+
+
diff --git a/src/api/selfProblems/plan.js b/src/api/selfProblems/plan.js
new file mode 100644
index 0000000..ad9c05b
--- /dev/null
+++ b/src/api/selfProblems/plan.js
@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+
+export function getPlanPage(params) {
+ return request({
+ url: '/internal/audit/carry/list',
+ method: 'get',
+ params: params
+ })
+}
+
+
+export function addPlan(data) {
+ return request({
+ url: '/internal/audit/carry/insert',
+ method: 'post',
+ data: data
+ })
+}
+
+export function editPlan(params) {
+ return request({
+ url: `/internal/audit/carry/update`,
+ method: 'post',
+ data: params
+ })
+}
+
+export function delPlan(data) {
+ return request({
+ url: `/internal/audit/carry/deleted?carryId=${data}`,
+ method: 'get'
+ })
+}
+
+
diff --git a/src/api/selfProblems/scenario.js b/src/api/selfProblems/scenario.js
new file mode 100644
index 0000000..f103ea6
--- /dev/null
+++ b/src/api/selfProblems/scenario.js
@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+
+export function getScenarioPage(params) {
+ return request({
+ url: '/internal/audit/plan/list',
+ method: 'get',
+ params: params
+ })
+}
+
+
+export function addScenario(data) {
+ return request({
+ url: '/internal/audit/plan/insert',
+ method: 'post',
+ data: data
+ })
+}
+
+export function editScenario(params) {
+ return request({
+ url: `/internal/audit/plan/update`,
+ method: 'post',
+ data: params
+ })
+}
+
+export function delScenario(data) {
+ return request({
+ url: `/internal/audit/plan/deleted?planId=${data}`,
+ method: 'get'
+ })
+}
+
+
diff --git a/src/api/selfProblems/tableList.js b/src/api/selfProblems/tableList.js
new file mode 100644
index 0000000..8eec89d
--- /dev/null
+++ b/src/api/selfProblems/tableList.js
@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+
+export function getEvaluatePage(params) {
+ return request({
+ url: '/internal/audit/evaluate/list',
+ method: 'get',
+ params: params
+ })
+}
+
+
+export function addEvaluate(data) {
+ return request({
+ url: '/internal/audit/evaluate/insert',
+ method: 'post',
+ data: data
+ })
+}
+
+export function editEvaluate(params) {
+ return request({
+ url: `/internal/audit/evaluate/update`,
+ method: 'post',
+ data: params
+ })
+}
+
+export function delEvaluate(data) {
+ return request({
+ url: `/internal/audit/evaluate/deleted?evaluateId=${data}`,
+ method: 'get'
+ })
+}
+
+
diff --git a/src/api/supplier/satisaied.js b/src/api/supplier/satisaied.js
new file mode 100644
index 0000000..c44c15b
--- /dev/null
+++ b/src/api/supplier/satisaied.js
@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+
+export function getSatisfiedPage(params) {
+ return request({
+ url: '/internal/audit/customer/list',
+ method: 'get',
+ params: params
+ })
+}
+
+
+export function addSatisfied(data) {
+ return request({
+ url: '/internal/audit/customer/insert',
+ method: 'post',
+ data: data
+ })
+}
+
+export function editSatisfied(params) {
+ return request({
+ url: `/internal/audit/customer/update`,
+ method: 'post',
+ data: params
+ })
+}
+
+export function delSatisfied(data) {
+ return request({
+ url: `/internal/audit/customer/deleted?customerId=${data}`,
+ method: 'get'
+ })
+}
+
+
diff --git a/src/api/supplier/supplierList.js b/src/api/supplier/supplierList.js
new file mode 100644
index 0000000..fe53c2d
--- /dev/null
+++ b/src/api/supplier/supplierList.js
@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+
+export function getSupplierPage(params) {
+ return request({
+ url: '/internal/audit/supplier/list',
+ method: 'get',
+ params: params
+ })
+}
+
+
+export function addSupplier(data) {
+ return request({
+ url: '/internal/audit/supplier/insert',
+ method: 'post',
+ data: data
+ })
+}
+
+export function editSupplier(params) {
+ return request({
+ url: `/internal/audit/supplier/update`,
+ method: 'post',
+ data: params
+ })
+}
+
+export function delSupplier(data) {
+ return request({
+ url: `/internal/audit/supplier/deleted?supplierId=${data}`,
+ method: 'get'
+ })
+}
+
+
diff --git a/src/components/Tinymce/Tinymce.vue b/src/components/Tinymce/Tinymce.vue
index 3a47e16..fef35bd 100644
--- a/src/components/Tinymce/Tinymce.vue
+++ b/src/components/Tinymce/Tinymce.vue
@@ -24,6 +24,7 @@
import "tinymce/plugins/wordcount";
import "tinymce/plugins/fullscreen";
import "../../../public/tinymce/plugins/upfile/index";
+import "../../../public/tinymce/plugins/formatpainter/plugin.min";
import {getToken} from "@/utils/auth";
// import "tinymce/plugins/upfile";
// import "tinymce/plugins/attachment";
@@ -47,11 +48,11 @@
},
plugins: {
type: [String, Array],
- default: " paragraphspacing upfile lists image table wordcount fullscreen "
+ default: "formatpainter paragraphspacing upfile lists image table wordcount fullscreen "
},
toolbar: {
type: [String, Array],
- default: " styleselect fontsizeselect paragraphspacing | upfile image bold italic | fontselect |alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | undo redo | lists insertfile table | removeformat fullscreen "
+ default: " styleselect fontsizeselect paragraphspacing formatpainter | upfile image bold italic | fontselect |alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | undo redo | lists insertfile table | removeformat fullscreen "
}
},
data() {
@@ -81,6 +82,7 @@
'黑体=SimHei, "Microsoft YaHei", "PingFang SC", sans-serif;' + // Windows黑体
'微软雅黑=Microsoft YaHei, sans-serif;' +
'仿宋=FangSong, "Fang", serif;',
+ fontsize_formats: "8pt 10pt 12pt 13pt 14pt 18pt 24pt 36pt",
// 字体样式应用到文本时使用 <span> 而非 <font>
inline_styles: true,
diff --git a/src/views/build/conpanyFunctionConsult/qualityManage/rangeManage/range/index.vue b/src/views/build/conpanyFunctionConsult/qualityManage/rangeManage/range/index.vue
index 2b4356f..e480e98 100644
--- a/src/views/build/conpanyFunctionConsult/qualityManage/rangeManage/range/index.vue
+++ b/src/views/build/conpanyFunctionConsult/qualityManage/rangeManage/range/index.vue
@@ -42,7 +42,17 @@
node-key="id"
:current-node-key="currentSelectedKey"
@node-click="handleNodeClick"
- ></el-tree>
+ >
+ <template #default="{ node,data }">
+ <el-tooltip
+ :content="data.mess"
+ placement="bottom"
+ :disabled="!isTextOverflow(data)"
+ >
+ <span class="tree-text">{{ data.mess }}</span>
+ </el-tooltip>
+ </template>
+ </el-tree>
</div>
<el-empty v-else description="暂无数据" />
</div>
@@ -236,6 +246,29 @@
}
loading.value = false;
}
+const textMeasureRef = ref(null);
+const getMeasureElement = () => {
+ if (!textMeasureRef.value) {
+ const el = document.createElement('span');
+ el.className = 'text-measure-element';
+ el.style.cssText = `
+ position: absolute;
+ visibility: hidden;
+ white-space: nowrap;
+ font-size: 14px; /* 匹配实际字体大小 */
+ `;
+ document.body.appendChild(el);
+ textMeasureRef.value = el;
+ }
+ return textMeasureRef.value;
+};
+// 判断文本是否溢出
+const isTextOverflow = (text) => {
+ const measureEl = getMeasureElement();
+ measureEl.textContent = text.mess;
+ return measureEl.scrollWidth > 300; // 180px 是节点容器实际宽度
+};
+
const handleTree = (val) => {
const traverse = (nodes, currentPath = '') => {
nodes.forEach((node, index) => {
@@ -597,6 +630,26 @@
:deep(.el-tree){
background: none;
}
+ :deep(.el-tooltip )
+ {
+ color: black;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ word-break: break-all;
+ white-space: nowrap;
+ }
+ .tree-text {
+ display: inline-block;
+ max-width: 300px; /* 根据实际容器宽度调整 */
+ white-space: nowrap; /* 强制不换行 */
+ overflow: hidden; /* 隐藏溢出 */
+ text-overflow: ellipsis; /* 显示省略号 */
+ }
+ /* 可选:移除el-tree默认的节点内边距 */
+ .el-tree-node__content {
+ padding-right: 5px;
+ }
+
.tree-container {
max-width: 600px;
margin-top: 20px;
diff --git a/src/views/certificatePdf.vue b/src/views/certificatePdf.vue
index 167f502..90b1df7 100644
--- a/src/views/certificatePdf.vue
+++ b/src/views/certificatePdf.vue
@@ -29,7 +29,14 @@
})
const {info} = toRefs(data)
onMounted(()=>{
- data.info = route.query
+ if(route.query.type == 'inter'){
+ data.info.name = route.query.paperName
+ data.info.stuName = route.query.personName
+ data.info.number = route.query.certifity
+ data.info.companyName = route.query.companyName
+ }else {
+ data.info = route.query
+ }
console.log(' data.info', data.info)
nextTick(()=>{
getPdf()
@@ -37,7 +44,7 @@
})
function getPdf() {
- let title = data.info.name + '证书'
+ let title = data.info.stuName + '_' + data.info.name + '合格证书'
htmlToPdf(title);
}
diff --git a/src/views/work/qualityInfo/supplierQuality/satisfied/components/editDialog.vue b/src/views/work/qualityInfo/supplierQuality/satisfied/components/editDialog.vue
new file mode 100644
index 0000000..6da8030
--- /dev/null
+++ b/src/views/work/qualityInfo/supplierQuality/satisfied/components/editDialog.vue
@@ -0,0 +1,275 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="state.title"
+ width="600px"
+ :before-close="handleClose"
+ :close-on-press-escape="false"
+ :close-on-click-modal="false"
+ >
+ <el-form :model="state.form" size="default" ref="superRef" :rules="state.formRules" label-width="150px" >
+ <el-form-item v-if="state.isAdmin" label="企业:" prop="companyId">
+ <el-select v-model="state.form.companyId" placeholder="请选择" clearable style="width: 100%">
+ <el-option
+ v-for="item in state.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="年份:" prop="year" >
+ <el-select
+ :disabled="state.title === '查看'"
+ v-model="state.form.year"
+ filterable
+ allow-create
+ default-first-option
+ :reserve-keyword="false"
+ placeholder="请选择年份"
+ @change="handleChangeNum"
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in state.yearList"
+ :key="item.value"
+ :label="item.label"
+ :value="item.label"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="文件名称:" prop="fileName">
+ <el-input v-model.trim="state.form.fileName" :disabled="state.title =='查看'" placeholder="文件名称"></el-input>
+ </el-form-item>
+ <el-form-item label="文件:" prop="filePath">
+ <el-upload accept=".doc,.docx" :action="state.uploadUrl" :headers="state.header" method="post" :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile)" :on-exceed="showTip" :limit='state.fileLimit' v-model:file-list="state.fileList" :before-upload="picSize" :on-remove="(file, uploadFiles)=>handleRemove(file, uploadFiles)" >
+ <el-button type="primary">点击上传</el-button>
+ <template #tip>
+ <div class="el-upload__tip">支持上传.doc、.docx格式文档,尺寸小于5M,最多可上传1张</div>
+ </template>
+ </el-upload>
+ </el-form-item>
+ </el-form>
+ <template #footer v-if="state.title !='查看'">
+ <span class="dialog-footer">
+ <el-button @click="handleClose" size="default">取 消</el-button>
+ <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue'
+import {ElMessage} from "element-plus";
+import {addUser, editUser, getUserById, resetPwd} from "@/api/onlineEducation/user"
+import {Base64} from "js-base64"
+import {getCompany} from "@/api/onlineEducation/company";
+import {addIndustryTemp, updateIndustryTemp, updateInfoPlatforms} from "@/api/staffManage/staff";
+import {getToken} from "@/utils/auth";
+import {delPic} from "@/api/onlineEducation/banner";
+import {getIndustry} from "@/api/system/industry";
+import {addSatisfied, editSatisfied} from "@/api/supplier/satisaied";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const superRef = ref()
+const checkFiles = (rule, value, callback) => {
+ if (state.fileList.length == 0) {
+ callback(new Error('请上传模板文件'))
+ } else {
+ callback()
+ }
+}
+const state = reactive({
+ title: '',
+ form: {
+ id: null,
+ year:'',
+ filePath: '',
+ fileName: '',
+ companyId: null,
+ },
+ formRules:{
+ companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+ year: [{ required: true, message: '请输入年份', trigger: 'blur' }],
+ fileName: [{ required: true, message: '请输入文件名称', trigger: 'blur' }],
+ filePath: [{ required: true, validator: checkFiles, trigger: 'blur' }],
+ },
+ isAdmin: false,
+ companyList: [],
+ industryList: [],
+ uploadUrl: import.meta.env.VITE_APP_BASE_API + '/system/common/uploadFile',
+ header: {
+ Authorization: getToken()
+ },
+ fileLimit: 1,
+ fileList: [],
+ yearList: [
+ {
+ value: 1,
+ label: '2025'
+ },
+ {
+ value: 2,
+ label: '2024'
+ },
+ {
+ value: 3,
+ label: '2023'
+ },
+ {
+ value: 4,
+ label: '2022'
+ },
+ {
+ value: 5,
+ label: '2021'
+ },
+ ],
+})
+onMounted(() => {
+
+});
+
+const openDialog = async (type, value,companyId, isAdmin, companyList) => {
+ state.isAdmin = isAdmin
+ if(isAdmin){
+ state.companyList = companyList
+ }
+ state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看'
+ state.form.companyId = companyId
+ if(state.title == '编辑'||state.title == '查看'){
+ Object.keys(state.form).forEach(key => {
+ if (key in value) {
+ state.form[key] = value[key]
+ }
+ })
+ if(value.filePath) {
+ const obj = {
+ url: value.filePath,
+ name: value.fileName
+ }
+ state.fileList = [obj]
+ }
+ }
+ dialogVisible.value = true
+}
+
+const onSubmit = async () => {
+ const valid = await superRef.value.validate();
+ if(valid){
+ if(state.title == '新增'){
+ const {id,...data} = state.form
+ const res = await addSatisfied(data)
+ if(res.code == 200){
+ ElMessage.success(res.message)
+ emit('getList')
+ handleClose()
+ dialogVisible.value = false;
+ }else{
+ ElMessage.warning(res.message)
+ }
+ }else{
+ const res = await editSatisfied(state.form)
+ if(res.code == 200){
+ ElMessage.success(res.message)
+ emit('getList')
+ handleClose()
+ dialogVisible.value = false;
+ }else{
+ ElMessage.warning(res.message)
+ }
+ }
+ }
+}
+
+const handleAvatarSuccess = (res, uploadFile) => {
+ if(res.code == 200){
+ state.form.fileName = res.data.originName
+ state.form.filePath = res.data.path
+ }else{
+ state.fileList = []
+ ElMessage({
+ type: 'warning',
+ message: '文件上传失败'
+ })
+ }
+}
+
+const showTip =()=>{
+ ElMessage({
+ type: 'warning',
+ message: '超出文件上传数量'
+ });
+}
+const picSize = async (rawFile) => {
+ if(rawFile.size / 1024 / 1024 > 5){
+ ElMessage({
+ type: 'warning',
+ message: '文件大小不能超过5M'
+ });
+ return false
+ }
+};
+const handleRemove = async (file, uploadFiles) => {
+ let path = state.form.filePath;
+ await delPic({path: path}).then(res => {
+ if(res.code == 200){
+ // ElMessage({
+ // type: 'success',
+ // message: '文件已删除'
+ // })
+ state.form.filePath = ''
+ state.form.fileName = ''
+ }else{
+ ElMessage({
+ type: 'warning',
+ message: res.message
+ })
+ }
+ }).catch(() => {
+ state.form.imgUrl = ''
+ });
+}
+
+const handleClose = () => {
+ state.form = {
+ id: null,
+ year:'',
+ filePath: '',
+ fileName: '',
+ companyId: null,
+ }
+ state.fileList = []
+ superRef.value.clearValidate();
+ superRef.value.resetFields()
+ dialogVisible.value = false;
+}
+const handleChangeNum = (value) => {
+ if (!/^\d+$/.test(value)) { // 验证是否为数字
+ ElMessage.warning('只能输入数字')
+ state.form.year = '' // 重置选择,避免非法值被添加到options中
+ } else if (!state.yearList.some(option => option.label === value)) { // 确保不是已存在的选项
+ state.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同)
+ }
+}
+defineExpose({
+ openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+ :deep(.el-form .el-form-item__label) {
+ font-size: 15px;
+ }
+ .file {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ }
+}
+</style>
diff --git a/src/views/work/qualityInfo/supplierQuality/satisfied/index.vue b/src/views/work/qualityInfo/supplierQuality/satisfied/index.vue
new file mode 100644
index 0000000..00ce096
--- /dev/null
+++ b/src/views/work/qualityInfo/supplierQuality/satisfied/index.vue
@@ -0,0 +1,316 @@
+<template>
+ <div class="app-container">
+ <div style="display: flex;justify-content: space-between">
+ <el-form :inline="true" style="display: flex;align-items: center;flex-wrap: wrap;" >
+ <el-form-item>
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="openDialog('add',{})"
+ >新增</el-button>
+ </el-form-item>
+ <el-form-item v-if="isAdmin" label="企业:" >
+ <el-select v-model="data.queryParams.companyId" placeholder="请选择" clearable>
+ <el-option
+ v-for="item in companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="年份:" style="margin-left: 20px">
+ <el-select
+ v-model="data.queryParams.year"
+ placeholder="请选择年份"
+ style="width: 240px"
+ filterable
+ allow-create
+ default-first-option
+ :reserve-keyword="false"
+ @change="handleChangeNum"
+ >
+ <el-option
+ v-for="item in data.yearList"
+ :key="item.value"
+ :label="item.label"
+ :value="item.label"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item >
+ <el-button type="primary" @click="getList">查询</el-button>
+ <el-button type="primary" plain @click="reset">重置</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ <!-- 表格数据 -->
+ <el-table v-loading="loading" :data="dataList" :border="true">
+ <el-table-column label="序号" type="index" align="center" width="80"/>
+ <el-table-column label="文件名称" prop="fileNameSimple" align="center">
+ </el-table-column>
+ <el-table-column label="文件" prop="templateName" align="center">
+ <template #default="scope">
+ <el-link style="" type="primary" @click="openFile(scope.row.filePath)">{{scope.row.fileName}}</el-link>
+ </template>
+ </el-table-column>
+ <el-table-column label="年度" prop="year" align="center" />
+ <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+ <template #default="scope">
+ <el-button link type="primary" @click="downloadFile(scope.row)">下载</el-button>
+ <el-button link type="primary" @click="openDialog('edit',scope.row)">编辑</el-button>
+ <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination
+ v-show="total > 0"
+ :total="total"
+ v-model:page="queryParams.pageNum"
+ v-model:limit="queryParams.pageSize"
+ @pagination="getList"
+ />
+
+ <edit-dialog ref="dialogRef" @getList=getList></edit-dialog>
+ </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, onMounted, onUnmounted, reactive, ref, toRefs} from "vue";
+import {ElMessage, ElMessageBox} from "element-plus";
+import {delCompany, getCompany} from "@/api/onlineEducation/company";
+import { Plus, Upload, Download} from '@element-plus/icons-vue';
+import {delUser, getUser} from "@/api/onlineEducation/user";
+import Cookies from "js-cookie";
+import editDialog from './components/editDialog.vue'
+import {
+ delIndustryTemp,
+ getIndustryTemp, uploadTemplate,
+} from "@/api/staffManage/staff";
+import useUserStore from "@/store/modules/user";
+import axios from "axios";
+import {getToken} from "@/utils/auth";
+import {getIndustry} from "@/api/system/industry";
+import {renderAsync} from "docx-preview";
+import {delSatisfied, getSatisfiedPage} from "@/api/supplier/satisaied";
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const dialogRef = ref();
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ year: ''
+ },
+ total: 0,
+ dataList: [],
+ companyList: [],
+ industryList: [],
+ isAdmin: false,
+ typeList: [],
+ exportDialog: false,
+ yearList: [
+ {
+ value: 1,
+ label: '2025'
+ },
+ {
+ value: 2,
+ label: '2024'
+ },
+ {
+ value: 3,
+ label: '2023'
+ },
+ {
+ value: 4,
+ label: '2022'
+ },
+ {
+ value: 5,
+ label: '2021'
+ },
+ ],
+
+});
+const state = reactive({
+ form: {
+ id: null,
+ filePath: '',
+ companyId: null
+ },
+ exportFileList: [],
+})
+
+const { queryParams, total, dataList,companyList,industryList, isAdmin } = toRefs(data);
+const userInfo = ref()
+onMounted(async ()=>{
+ if(userStore.roles.includes('admin')){
+ data.isAdmin = true
+ data.queryParams.companyId = null
+ await getCompanyList()
+ }else{
+ data.isAdmin = false
+ data.queryParams.companyId = userStore.companyId
+ }
+ await getList()
+})
+
+onUnmounted(()=>{
+
+})
+const openFile = async(path)=>{
+ const ext = path.split('.').pop().toLowerCase();
+ if (ext === 'doc') {
+ ElMessageBox.confirm('暂不支持线上预览.doc文件,是否下载查看?', '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }).then(() => {
+ window.open(`${import.meta.env.VITE_APP_BASE_API}/${path}`, '_blank');
+ }).catch(() => {
+ console.log('取消预览')
+ });
+ return
+ }
+ try {
+ // 1. 获取文件
+ const response = await fetch(import.meta.env.VITE_APP_BASE_API + '/' + path);
+ const arrayBuffer = await response.arrayBuffer();
+ // 2. 创建新窗口
+ const win = window.open('', '_blank')
+ win.document.write(`
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <title>预览</title>
+ <style>
+ body { margin: 20px; font-family: Arial; }
+ .docx-container { width: 100%; height: 100%; }
+ </style>
+ </head>
+ <body>
+ <div id="container" class="docx-container"></div>
+ </body>
+ </html>
+ `);
+ // 3. 渲染 DOCX
+ await renderAsync(arrayBuffer, win.document.getElementById('container'));
+
+ } catch (error) {
+ console.error('预览失败:', error);
+ alert(`预览失败: ${error.message}`);
+ }
+}
+const getList = async () => {
+ loading.value = true
+ const res = await getSatisfiedPage(data.queryParams)
+ if(res.code == 200){
+ data.dataList = res.data.list.map(item => {
+ return {
+ ...item,
+ fileNameSimple: item.fileName.split('.')[0]
+ }
+ })
+ data.total = res.data.total
+ }else{
+ ElMessage.warning(res.message)
+ }
+ loading.value = false
+}
+
+
+const getCompanyList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getCompany(queryParams)
+ if (res.code == 200) {
+ data.companyList = res.data.list?res.data.list:[]
+ // data.queryParams.companyId = data.companyList[0].id
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const downloadFile = (e)=>{
+ axios.get(import.meta.env.VITE_APP_BASE_API + '/' +e.filePath,{headers:{'Content-Type': 'application/json','Authorization': `${getToken()}`},responseType: 'blob'}).then(res=>{
+ if (res) {
+ const link = document.createElement('a')
+ let blob = new Blob([res.data],{type: res.data.type})
+ link.style.display = "none";
+ link.href = URL.createObjectURL(blob); // 创建URL
+ link.setAttribute("download", e.fileName);
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ } else {
+ ElMessage({
+ type: 'warning',
+ message: '文件读取失败'
+ });
+ }
+ })
+}
+
+const openDialog = (type, value) => {
+ dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList);
+}
+
+const exportData = () => {
+ data.exportDialog = true
+
+}
+
+
+/** 重置新增的表单以及其他数据 */
+const reset= async()=> {
+ if(data.isAdmin){
+ data.queryParams = {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ year: ''
+ }
+ await getCompanyList()
+ }else {
+ data.queryParams = {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: data.queryParams.companyId,
+ year: ''
+ }
+ }
+ await getList()
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delSatisfied( val.id)
+ if(res.code == 200){
+ ElMessage.success('数据删除成功')
+ await getList()
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+const handleChangeNum = (value) => {
+ if (!/^\d+$/.test(value)) { // 验证是否为数字
+ ElMessage.warning('只能输入数字')
+ data.queryParams.year = '' // 重置选择,避免非法值被添加到options中
+ } else if (!data.yearList.some(option => option.label === value)) { // 确保不是已存在的选项
+ data.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同)
+ }
+}
+
+
+</script>
diff --git a/src/views/work/qualityInfo/supplierQuality/supplierList/components/supplierDialog.vue b/src/views/work/qualityInfo/supplierQuality/supplierList/components/supplierDialog.vue
new file mode 100644
index 0000000..f74e352
--- /dev/null
+++ b/src/views/work/qualityInfo/supplierQuality/supplierList/components/supplierDialog.vue
@@ -0,0 +1,219 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="title"
+ width="550px"
+ :before-close="handleClose"
+ :close-on-press-escape="false"
+ :close-on-click-modal="false"
+ >
+ <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-width="150px" >
+ <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
+ <el-select v-model="state.form.companyId" filterable placeholder="请选择" clearable style="width: 100%" :disabled="title == '查看' || title == '编辑' || !state.isAdmin">
+ <el-option
+ v-for="item in state.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="供应商名称:" prop="supplierName" >
+ <el-input v-model="state.form.supplierName" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="供应商类型:" prop="supplierType" >
+ <el-input v-model="state.form.supplierType" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="联系人:" prop="user" >
+ <el-input v-model="state.form.user" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="联系电话:" prop="phone" >
+ <el-input v-model="state.form.phone" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="邮箱:" prop="emil" >
+ <el-input v-model="state.form.emil" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="主营产品:" prop="merito" >
+ <el-input v-model="state.form.merito" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="服务内容:" prop="content" >
+ <el-input v-model="state.form.content" :disabled="title === '查看'"/>
+ </el-form-item>
+ </el-form>
+ <template #footer v-if="title !== '查看'">
+ <span class="dialog-footer">
+ <el-button @click="handleClose" size="default">取 消</el-button>
+ <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+<script setup>
+import {onMounted, reactive, ref, toRefs} from 'vue'
+import Editor from "@/components/Editor/index.vue";
+import {ElMessage} from "element-plus";
+import {addNotice} from "@/api/backManage/notice";
+import {addDict, editDict, getDictDetail} from "@/api/backManage/evaluate";
+import {addCompany, checkName, distributeCompany, editCompany, getCompany} from "@/api/onlineEducation/company";
+import {validEmail, verifyPhone} from "@/utils/validate";
+import {addBasic, editBasic} from "@/api/companyInfo/basicInfo";
+import Cookies from "js-cookie";
+import {addSupplier, editSupplier} from "@/api/supplier/supplierList";
+
+const dialogVisible = ref(false);
+const title = ref("");
+const busRef = ref();
+const length = ref()
+const emit = defineEmits(["getList"]);
+const validatePhone = (rule, value, callback)=>{
+ if(value === ''){
+ callback(new Error('请输入手机号'))
+ }else{
+ if(!verifyPhone(value)){
+ callback(new Error('手机号格式有误'))
+ }else{
+ callback()
+ }
+ }
+}
+const validateEmail = (rule, value, callback)=>{
+ if(value === ''){
+ callback(new Error('请输入邮箱'))
+ }else{
+ if(!validEmail(value)){
+ callback(new Error('邮箱格式有误'))
+ }else{
+ callback()
+ }
+ }
+}
+const state = reactive({
+ form: {
+ id: '',
+ companyId: null,
+ supplierName: '',
+ supplierType: '',
+ user: '',
+ phone: '',
+ emil: '',
+ merito: '',
+ content: '',
+ },
+ formRules:{
+ companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+ supplierName: [{ required: true, message: '请输入供应商名称', trigger: 'blur' }],
+ supplierType:[{ required: true, message: '请输入供应商类型', trigger: 'blur' }],
+ user: [{ required: true, message: '请输入联系人', trigger: 'blur' }],
+ phone: [{ required: true, validator: validatePhone, trigger: 'blur' }],
+ emil: [{ required: true, validator: validateEmail, trigger: 'blur' }],
+ merito: [{ required: true, message: '请输入主营产品', trigger: 'blur' }],
+ content: [{ required: true, message: '请输入服务内容', trigger: 'blur' }],
+ },
+ isAdmin: false,
+ companyList: []
+})
+
+onMounted(() => {
+
+})
+const openDialog = async (type, value,companyList) => {
+
+
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ state.isAdmin = userInfo.userType === 0;
+ if(state.isAdmin){
+ state.companyList = companyList
+ }
+ title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
+ if(type === 'edit' || type === 'review') {
+ state.form = JSON.parse(JSON.stringify(value));
+ if(state.isAdmin){
+ state.form.companyId = value.companyId
+ state.form.companyName = value.companyName
+ }
+ }
+ dialogVisible.value = true;
+}
+
+const onSubmit = async () => {
+ const valid = await busRef.value.validate();
+ if(!state.isAdmin){
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ state.form.companyId = userInfo.companyId
+ }
+ if(valid){
+ if(title.value === '新增'){
+ const {id, ...data} = JSON.parse(JSON.stringify(state.form))
+ const res = await addSupplier(data)
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '新增成功'
+ });
+ }else{
+ ElMessage.warning(res.message)
+ }
+ emit("getList")
+ busRef.value.clearValidate();
+ reset();
+ dialogVisible.value = false;
+ }else if(title.value === '编辑'){
+ const {...data} = JSON.parse(JSON.stringify(state.form))
+ const res = await editSupplier(data)
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '编辑成功'
+ });
+ }else{
+ ElMessage.warning(res.message)
+ }
+ emit("getList")
+ busRef.value.clearValidate();
+ reset();
+ dialogVisible.value = false;
+ }
+ }
+}
+
+const handleClose = () => {
+ busRef.value.clearValidate();
+ reset();
+ dialogVisible.value = false;
+ emit("getList")
+
+}
+const reset = () => {
+ state.form = {
+ id: '',
+ companyId: null,
+ supplierName: '',
+ supplierType: '',
+ user: '',
+ phone: '',
+ emil: '',
+ merito: '',
+ content: '',
+ }
+ state.companyList = []
+}
+defineExpose({
+ openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+ :deep(.el-form .el-form-item__label) {
+ font-size: 15px;
+ }
+ .file {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ }
+}
+</style>
diff --git a/src/views/work/qualityInfo/supplierQuality/supplierList/index.vue b/src/views/work/qualityInfo/supplierQuality/supplierList/index.vue
new file mode 100644
index 0000000..f36fce3
--- /dev/null
+++ b/src/views/work/qualityInfo/supplierQuality/supplierList/index.vue
@@ -0,0 +1,201 @@
+<template>
+ <div class="app-container">
+ <div style="margin-bottom: 10px">
+ <el-form style="display: flex;flex-wrap: wrap;">
+ <el-form-item>
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="openDialog('add',{})"
+ >新增</el-button>
+ </el-form-item>
+ <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px">
+ <el-select v-model="data.queryParams.companyId" filterable placeholder="请选择" clearable>
+ <el-option
+ v-for="item in data.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="data.isAdmin">
+ <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button>
+ <el-button plain @click="reset">重置</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ <!-- 表格数据 -->
+ <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange">
+ <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
+ <el-table-column label="供应商名称" prop="supplierName" align="center" />
+ <el-table-column label="供应商类型" prop="supplierType" align="center" />
+ <el-table-column label="联系人" prop="user" align="center" />
+ <el-table-column label="联系电话" prop="phone" align="center" />
+ <el-table-column label="邮箱" prop="emil" align="center" />
+ <el-table-column label="主营产品" prop="merito" align="center" />
+ <el-table-column label="服务内容" prop="content" align="center" />
+ <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+ <template #default="scope">
+ <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button>
+ <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button>
+ <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <div class="pag-container">
+ <el-pagination
+ v-model:current-page="data.queryParams.pageNum"
+ v-model:page-size="data.queryParams.pageSize"
+ :page-sizes="[10,15,20,25]"
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="total"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ />
+ </div>
+ <supplierDialog ref="noticeRef" @getList = "getList"></supplierDialog>
+ </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
+import supplierDialog from "./components/supplierDialog.vue"
+import {ElMessage, ElMessageBox} from "element-plus";
+import {getCompany} from "@/api/onlineEducation/company";
+import Cookies from "js-cookie";
+import {generateWordDocument} from "@/utils/exportWord";
+import {delBasic, getBasic} from "@/api/companyInfo/basicInfo";
+import {delSupplier, getSupplierPage} from "@/api/supplier/supplierList";
+
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const noticeRef = ref();
+const loadingCompany = ref(false)
+const choosedData = ref([])
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ },
+ companyList: [],
+ isAdmin: false
+});
+const dataList = ref([]);
+const total = ref(0);
+
+const { queryParams } = toRefs(data);
+
+onMounted(() => {
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ console.log("userInfo",userInfo)
+ data.isAdmin = userInfo.userType === 0;
+ if(data.isAdmin){
+ data.queryParams.companyId = null
+ }else {
+ data.queryParams.companyId = userInfo.companyId
+ }
+ getList();
+ if(data.isAdmin){
+ getCompanyList()
+ }
+});
+const getList = async () => {
+ loading.value = true;
+ const res = await getSupplierPage(data.queryParams);
+ if(res.code === 200){
+ dataList.value = res.data.list
+ total.value = res.data.total
+ }else{
+ ElMessage.warning(res.message)
+ }
+ loading.value = false;
+}
+
+const searchClick = () => {
+ getList();
+}
+const openDialog = (type, value) => {
+ noticeRef.value.openDialog(type, value,data.companyList);
+}
+const selectValue = (val) => {
+ data.companyList.forEach(item => {
+ if(item.name === val){
+ data.queryParams.companyId = item.id
+ }
+ })
+}
+
+const getCompanyList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getCompany(queryParams)
+ if (res.code == 200) {
+ data.companyList = res.data.list?res.data.list:[]
+ // data.queryParams.companyId = data.companyList[0].id
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const handleSizeChange = (val) => {
+ data.queryParams.pageSize = val
+ getList()
+}
+const handleCurrentChange = (val) => {
+ data.queryParams.pageNum = val
+ getList()
+}
+
+/** 重置新增的表单以及其他数据 */
+function reset() {
+ data.queryParams = {
+ companyId: '',
+ pageNum: 1,
+ pageSize: 10,
+ }
+ choosedData.value = []
+ data.companyList = [];
+ getList();
+ getCompanyList()
+}
+
+
+const handleSelectionChange = (val) => {
+ choosedData.value = val
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delSupplier(val.id);
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '删除成功'
+ });
+ getList();
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
+<style lang="scss">
+.pag-container{
+ float: right;
+ margin-top: 10px;
+}
+</style>
diff --git a/src/views/work/selfProblems/internalAudit/auditorManage/nameList/components/nameListDialog.vue b/src/views/work/selfProblems/internalAudit/auditorManage/nameList/components/nameListDialog.vue
new file mode 100644
index 0000000..e43fcd2
--- /dev/null
+++ b/src/views/work/selfProblems/internalAudit/auditorManage/nameList/components/nameListDialog.vue
@@ -0,0 +1,198 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="state.title"
+ width="550px"
+ :before-close="handleClose"
+ :close-on-press-escape="false"
+ :close-on-click-modal="false"
+ >
+ <el-form :model="state.form" size="default" ref="superRef" :rules="state.formRules" label-width="150px" >
+ <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
+ <el-select
+ v-model="state.form.companyId"
+ filterable
+ clearable
+ style="width: 100%"
+ :disabled="state.title == '查看' || state.title == '编辑' || !state.isAdmin"
+ @change="selectValueCom"
+ >
+ <el-option
+ v-for="item in state.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="人员选择:" prop="personId">
+ <el-select
+ clearable
+ v-model="state.form.personId"
+ :disabled="state.title =='查看'"
+ filterable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="专长领域:" prop="speciality">
+ <el-input v-model.trim="state.form.speciality" :disabled="state.title =='查看'" placeholder="专长领域"></el-input>
+ </el-form-item>
+ </el-form>
+ <template #footer v-if="state.title !='查看'">
+ <span class="dialog-footer">
+ <el-button @click="handleClose" size="default">取 消</el-button>
+ <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue'
+import {ElMessage} from "element-plus";
+import {addUser, editUser, getUser, getUserById, resetPwd} from "@/api/onlineEducation/user"
+import {Base64} from "js-base64"
+import {getCompany} from "@/api/onlineEducation/company";
+import {updateInfoPlatforms, updateSysClause} from "@/api/staffManage/staff";
+import Cookies from "js-cookie";
+import {addPerson, editPerson} from "@/api/selfProblems/nameList";
+import {addScenario, editScenario} from "@/api/selfProblems/scenario";
+import {getStudent} from "@/api/onlineEducation/student";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const superRef = ref()
+const state = reactive({
+ title: '',
+ form: {
+ id: null,
+ personId: null,
+ companyId: null,
+ speciality: ''
+ },
+ isAdmin: false,
+ peopleList: [],
+ formRules:{
+ personId: [{ required: true, message: '请选择人员', trigger: 'blur' }],
+ companyId: [{ required: true, message: '请选择公司', trigger: 'blur' }],
+ speciality: [{ required: true, message: '请输入专长领域', trigger: 'blur' }],
+ }
+})
+onMounted(() => {
+
+});
+
+const openDialog = async (type, value,companyList) => {
+ state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看'
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ state.isAdmin = userInfo.userType === 0;
+ state.form.companyName = userInfo.companyName
+ state.form.companyId = userInfo.companyId
+ if(state.isAdmin){
+ state.companyList = companyList
+ state.form.companyId = value.companyId
+ state.form.companyName = value.companyName
+ }
+ if(state.title == '编辑'||state.title == '查看'){
+ Object.keys(state.form).forEach(key => {
+ if (key in value) {
+ state.form[key] = value[key]
+ }
+ })
+ }
+ await getPeopleList()
+ dialogVisible.value = true
+}
+
+const getPeopleList = async ()=> {
+ if(state.isAdmin && !state.form.companyId && (state.form.companyId == 0 || state.form.companyId == null)){
+ return
+ }
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 9999,
+ companyId: state.form.companyId
+ }
+ const res = await getStudent(queryParams)
+ if(res.code == 200){
+ state.peopleList = res.data.list?res.data.list:[]
+ }else{
+ ElMessage.warning(res.message)
+ }
+};
+const onSubmit = async () => {
+ const valid = await superRef.value.validate();
+ if(valid) {
+ if (state.title === '新增') {
+ const {id, ...data} = JSON.parse(JSON.stringify(state.form))
+ const res = await addPerson(data)
+ if (res.code === 200) {
+ ElMessage({
+ type: 'success',
+ message: '新增成功'
+ });
+ } else {
+ ElMessage.warning(res.message)
+ }
+ emit("getList")
+ handleClose()
+ } else if (state.title === '编辑') {
+ const {...data} = JSON.parse(JSON.stringify(state.form))
+ const res = await editPerson(data)
+ if (res.code === 200) {
+ ElMessage({
+ type: 'success',
+ message: '编辑成功'
+ });
+ } else {
+ ElMessage.warning(res.message)
+ }
+ emit("getList")
+ handleClose()
+ }
+ }
+}
+const selectValueCom = (val) => {
+ state.form.personId = null
+ getPeopleList()
+}
+
+const handleClose = () => {
+ state.form = {
+ id: null,
+ personId: null,
+ companyId: null,
+ speciality: ''
+ }
+ state.peopleList = []
+ superRef.value.clearValidate();
+ dialogVisible.value = false;
+
+}
+
+defineExpose({
+ openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+ :deep(.el-form .el-form-item__label) {
+ font-size: 15px;
+ }
+ .file {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ }
+}
+</style>
diff --git a/src/views/work/selfProblems/internalAudit/auditorManage/nameList/index.vue b/src/views/work/selfProblems/internalAudit/auditorManage/nameList/index.vue
new file mode 100644
index 0000000..39be324
--- /dev/null
+++ b/src/views/work/selfProblems/internalAudit/auditorManage/nameList/index.vue
@@ -0,0 +1,215 @@
+<template>
+ <div class="app-container">
+ <div style="margin-bottom: 10px">
+ <el-form style="display: flex;flex-wrap: wrap;">
+ <el-form-item>
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="openDialog('add',{})"
+ >新增</el-button>
+ </el-form-item>
+ <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px">
+ <el-select v-model="data.queryParams.companyId" filterable placeholder="请选择" clearable>
+ <el-option
+ v-for="item in data.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="data.isAdmin">
+ <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button>
+ <el-button plain @click="reset">重置</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ <!-- 表格数据 -->
+ <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange">
+ <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
+ <el-table-column label="姓名" prop="personName" align="center" />
+ <el-table-column label="所属部门" prop="deptName" align="center" />
+ <el-table-column label="职务" prop="duty" align="center" />
+ <el-table-column label="专长领域" prop="speciality" align="center" />
+ <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+ <template #default="scope">
+ <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button>
+ <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button>
+ <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <div class="pag-container">
+ <el-pagination
+ v-model:current-page="data.queryParams.pageNum"
+ v-model:page-size="data.queryParams.pageSize"
+ :page-sizes="[10,15,20,25]"
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="total"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ />
+ </div>
+ <nameDialog ref="noticeRef" @getList = "getList"></nameDialog>
+ </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
+import nameDialog from "./components/nameListDialog.vue"
+import {ElMessage, ElMessageBox} from "element-plus";
+import {getCompany} from "@/api/onlineEducation/company";
+import Cookies from "js-cookie";
+import {generateWordDocument} from "@/utils/exportWord";
+import {delBasic, getBasic} from "@/api/companyInfo/basicInfo";
+import {delPerson, getPersonPage} from "@/api/selfProblems/nameList";
+
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const noticeRef = ref();
+const loadingCompany = ref(false)
+const choosedData = ref([])
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ },
+ companyList: [],
+ isAdmin: false
+});
+const dataList = ref([]);
+const total = ref(0);
+
+const { queryParams } = toRefs(data);
+
+onMounted(() => {
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ console.log("userInfo",userInfo)
+ data.isAdmin = userInfo.userType === 0;
+ if(data.isAdmin){
+ data.queryParams.companyId = null
+ getCompanyList()
+ }else {
+ data.queryParams.companyId = userInfo.companyId
+ }
+ getList();
+});
+const getList = async () => {
+ loading.value = true;
+ const res = await getPersonPage(data.queryParams);
+ if(res.code === 200){
+ dataList.value = res.data.list
+ total.value = res.data.total
+ }else{
+ ElMessage.warning(res.message)
+ }
+ loading.value = false;
+}
+
+const searchClick = () => {
+ getList();
+}
+const openDialog = (type, value) => {
+ noticeRef.value.openDialog(type, value,data.companyList);
+}
+const selectValue = (val) => {
+ data.companyList.forEach(item => {
+ if(item.name === val){
+ data.queryParams.companyId = item.id
+ }
+ })
+}
+
+const getCompanyList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getCompany(queryParams)
+ if (res.code == 200) {
+ data.companyList = res.data.list?res.data.list:[]
+ // data.queryParams.companyId = data.companyList[0].id
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const handleSizeChange = (val) => {
+ data.queryParams.pageSize = val
+ getList()
+}
+const handleCurrentChange = (val) => {
+ data.queryParams.pageNum = val
+ getList()
+}
+
+/** 重置新增的表单以及其他数据 */
+function reset() {
+ data.queryParams = {
+ companyId: '',
+ pageNum: 1,
+ pageSize: 10,
+ }
+ choosedData.value = []
+ data.companyList = [];
+ getList();
+ getCompanyList()
+}
+const exportData = () => {
+ if(choosedData.value && choosedData.value.length === 0){
+ ElMessage.warning('请选择需要导出的数据')
+ }else {
+ startGeneration()
+ }
+}
+const templatePath = '/infoExample.docx'
+const startGeneration = async () => {
+ choosedData.value.forEach(item => {
+ try {
+ generateWordDocument(templatePath, item, item.companyName+'_基本情况.docx');
+ } catch (error){
+ ElMessage({
+ type: 'warning',
+ message: '导出失败'
+ });
+ }
+ })
+}
+
+const handleSelectionChange = (val) => {
+ choosedData.value = val
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delPerson(val.id);
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '删除成功'
+ });
+ getList();
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
+<style lang="scss">
+.pag-container{
+ float: right;
+ margin-top: 10px;
+}
+</style>
diff --git a/src/views/work/selfProblems/internalAudit/auditorManage/tableList/components/editDialog.vue b/src/views/work/selfProblems/internalAudit/auditorManage/tableList/components/editDialog.vue
new file mode 100644
index 0000000..4939c0e
--- /dev/null
+++ b/src/views/work/selfProblems/internalAudit/auditorManage/tableList/components/editDialog.vue
@@ -0,0 +1,253 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="state.title"
+ width="550px"
+ :before-close="handleClose"
+ :close-on-press-escape="false"
+ :close-on-click-modal="false"
+ >
+ <el-form :model="state.form" size="default" ref="superRef" :rules="state.formRules" label-width="150px" >
+ <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
+ <el-select
+ v-model="state.form.companyId"
+ filterable
+ clearable
+ style="width: 100%"
+ :disabled="state.title == '查看' || state.title == '编辑' || !state.isAdmin"
+ @change="selectValueCom"
+ >
+ <el-option
+ v-for="item in state.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="人员选择:" prop="personId">
+ <el-select
+ clearable
+ v-model="state.form.personId"
+ :disabled="state.title =='查看'"
+ filterable
+ style="width: 100%"
+ @change="changePerson"
+ >
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="内审员证书:" prop="certifity">
+ <el-select
+ clearable
+ v-model="state.form.certifity"
+ :disabled="state.title =='查看'"
+ filterable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in state.certList"
+ :key="item.number"
+ :label="item.certName"
+ :value="item.number"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="审核经历次数:" prop="amount">
+ <el-input v-model.trim="state.form.amount" :disabled="state.title =='查看'" placeholder="核经历次数"></el-input>
+ </el-form-item>
+ <el-form-item label="评定结论:" prop="conclusion">
+ <el-input v-model.trim="state.form.conclusion" :disabled="state.title =='查看'" type="textarea" :rows="2" placeholder="评定结论"></el-input>
+ </el-form-item>
+ </el-form>
+ <template #footer v-if="state.title !='查看'">
+ <span class="dialog-footer">
+ <el-button @click="handleClose" size="default">取 消</el-button>
+ <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue'
+import {ElMessage} from "element-plus";
+import {addUser, editUser, getUser, getUserById, resetPwd} from "@/api/onlineEducation/user"
+import {Base64} from "js-base64"
+import {getCompany} from "@/api/onlineEducation/company";
+import {updateInfoPlatforms, updateSysClause} from "@/api/staffManage/staff";
+import Cookies from "js-cookie";
+import {addScenario, editScenario} from "@/api/selfProblems/scenario";
+import {addEvaluate, editEvaluate} from "@/api/selfProblems/tableList";
+import {getStudent, getStuTrainRecord} from "@/api/onlineEducation/student";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const superRef = ref()
+const state = reactive({
+ title: '',
+ form: {
+ id: null,
+ personId: null,
+ companyId: null,
+ certifity: '',
+ amount: '',
+ conclusion: ''
+
+ },
+ isAdmin: false,
+ peopleList: [],
+ certList: [],
+ formRules:{
+ companyId: [{ required: true, message: '请选择公司', trigger: 'blur' }],
+ personId: [{ required: true, message: '请选择人员', trigger: 'blur' }],
+ }
+})
+onMounted(() => {
+
+});
+
+const openDialog = async (type, value,companyList) => {
+ state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看'
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ state.isAdmin = userInfo.userType === 0;
+ state.form.companyName = userInfo.companyName
+ state.form.companyId = userInfo.companyId
+ if(state.isAdmin){
+ state.companyList = companyList
+ state.form.companyId = value.companyId
+ state.form.companyName = value.companyName
+ }
+ if(state.title == '编辑'||state.title == '查看'){
+ Object.keys(state.form).forEach(key => {
+ if (key in value) {
+ state.form[key] = value[key]
+ }
+ })
+ }
+ await getPeopleList()
+ await getCertList()
+ dialogVisible.value = true
+}
+
+const getPeopleList = async ()=> {
+ if(state.isAdmin && !state.form.companyId && (state.form.companyId == 0 || state.form.companyId == null)){
+ return
+ }
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 9999,
+ companyId: state.form.companyId
+ }
+ const res = await getStudent(queryParams)
+ if(res.code == 200){
+ state.peopleList = res.data.list?res.data.list:[]
+ }else{
+ ElMessage.warning(res.message)
+ }
+};
+const getCertList = async ()=> {
+ if(state.isAdmin && !state.form.companyId && (state.form.companyId == 0 || state.form.companyId == null)){
+ return
+ }
+ const param = {
+ studentId: state.form.personId
+ }
+ const res = await getStuTrainRecord(param)
+ if(res.code == 200){
+ const data = res.data.filter(i => i.passed == 1)
+ state.certList = data.map(item => {
+ return{
+ ...item,
+ certName: item.name + '合格证书'
+ }
+ })
+
+ }else{
+ ElMessage.warning(res.message)
+ }
+};
+const onSubmit = async () => {
+ const valid = await superRef.value.validate();
+ if(valid){
+ if(state.title === '新增'){
+ const {id, ...data} = JSON.parse(JSON.stringify(state.form))
+ const res = await addEvaluate(data)
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '新增成功'
+ });
+ }else{
+ ElMessage.warning(res.message)
+ }
+ emit("getList")
+ handleClose()
+ }else if(state.title === '编辑'){
+ const {...data} = JSON.parse(JSON.stringify(state.form))
+ const res = await editEvaluate(data)
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '编辑成功'
+ });
+ }else{
+ ElMessage.warning(res.message)
+ }
+ emit("getList")
+ handleClose()
+ }
+
+ }
+}
+const selectValueCom = (val) => {
+ state.form.personId = null
+ state.form.certifity = ''
+ getPeopleList()
+}
+
+const handleClose = () => {
+ state.form = {
+ id: null,
+ personId: null,
+ companyId: null,
+ certifity: '',
+ amount: '',
+ conclusion: ''
+ }
+ state.certList = []
+ state.companyList = []
+ state.peopleList = []
+ superRef.value.clearValidate();
+ superRef.value.resetFields()
+ dialogVisible.value = false;
+}
+const changePerson = () =>{
+ state.form.certifity = ''
+ getCertList()
+}
+
+defineExpose({
+ openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+ :deep(.el-form .el-form-item__label) {
+ font-size: 15px;
+ }
+ .file {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ }
+}
+</style>
diff --git a/src/views/work/selfProblems/internalAudit/auditorManage/tableList/index.vue b/src/views/work/selfProblems/internalAudit/auditorManage/tableList/index.vue
new file mode 100644
index 0000000..f424f8e
--- /dev/null
+++ b/src/views/work/selfProblems/internalAudit/auditorManage/tableList/index.vue
@@ -0,0 +1,228 @@
+<template>
+ <div class="app-container">
+ <div style="margin-bottom: 10px">
+ <el-form style="display: flex;flex-wrap: wrap;">
+ <el-form-item>
+ <el-button
+ v-if="data.userType ==0 || data.userType == 1"
+ type="primary"
+ plain
+ icon="Plus"
+ @click="openDialog('add',{})"
+ >新增</el-button>
+ </el-form-item>
+ <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px">
+ <el-select v-model="data.queryParams.companyId" filterable placeholder="请选择" clearable>
+ <el-option
+ v-for="item in data.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="data.isAdmin">
+ <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button>
+ <el-button plain @click="reset">重置</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ <!-- 表格数据 -->
+ <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange">
+ <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
+ <el-table-column label="姓名" prop="personName" align="center" />
+ <el-table-column label="所属部门" prop="deptName" align="center" />
+ <el-table-column label="内审员证书" prop="certifity" align="center" >
+ <template #default="scope">
+ <el-button v-if="scope.row.certifity" type="primary" @click="downloadCert(scope.row)" link>证书</el-button>
+ </template>
+ </el-table-column>
+ <el-table-column label="审核经历次数" prop="amount" align="center" />
+ <el-table-column label="评定结论" prop="conclusion" align="center" />
+ <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+ <template #default="scope">
+ <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button>
+ <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button>
+ <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <div class="pag-container">
+ <el-pagination
+ v-model:current-page="data.queryParams.pageNum"
+ v-model:page-size="data.queryParams.pageSize"
+ :page-sizes="[10,15,20,25]"
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="total"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ />
+ </div>
+ <editDialog ref="noticeRef" @getList = "getList"></editDialog>
+ </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
+import editDialog from "./components/editDialog.vue"
+import {ElMessage, ElMessageBox} from "element-plus";
+import {getCompany} from "@/api/onlineEducation/company";
+import Cookies from "js-cookie";
+import {generateWordDocument} from "@/utils/exportWord";
+import {delBasic, getBasic} from "@/api/companyInfo/basicInfo";
+import {delEvaluate, getEvaluatePage} from "@/api/selfProblems/tableList";
+import Default from "@tinymce/tinymce-vue";
+import {useRouter} from "vue-router";
+const router = useRouter();
+
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const noticeRef = ref();
+const loadingCompany = ref(false)
+const choosedData = ref([])
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ },
+ companyList: [],
+ isAdmin: false,
+ userType: null
+});
+const dataList = ref([]);
+const total = ref(0);
+
+const { queryParams } = toRefs(data);
+
+onMounted(() => {
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ console.log("userInfo",userInfo)
+ data.isAdmin = userInfo.userType === 0;
+ data.userType = userInfo.userType
+ if(data.isAdmin){
+ data.queryParams.companyId = null
+ getCompanyList()
+ }else {
+ data.queryParams.companyId = userInfo.companyId
+ }
+ getList();
+});
+const getList = async () => {
+ loading.value = true;
+ const res = await getEvaluatePage(data.queryParams);
+ if(res.code === 200){
+ dataList.value = res.data.list
+ total.value = res.data.total
+ }else{
+ ElMessage.warning(res.message)
+ }
+ loading.value = false;
+
+}
+
+const searchClick = () => {
+ getList();
+}
+const openDialog = (type, value) => {
+ noticeRef.value.openDialog(type, value,data.companyList);
+}
+const getCompanyList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getCompany(queryParams)
+ if (res.code == 200) {
+ data.companyList = res.data.list?res.data.list:[]
+ // data.queryParams.companyId = data.companyList[0].id
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const handleSizeChange = (val) => {
+ data.queryParams.pageSize = val
+ getList()
+}
+const handleCurrentChange = (val) => {
+ data.queryParams.pageNum = val
+ getList()
+}
+
+/** 重置新增的表单以及其他数据 */
+function reset() {
+ data.queryParams = {
+ companyId: '',
+ pageNum: 1,
+ pageSize: 10,
+ }
+ choosedData.value = []
+ data.companyList = [];
+ getList();
+ getCompanyList()
+}
+const exportData = () => {
+ if(choosedData.value && choosedData.value.length === 0){
+ ElMessage.warning('请选择需要导出的数据')
+ }else {
+ startGeneration()
+ }
+}
+const templatePath = '/infoExample.docx'
+const startGeneration = async () => {
+ choosedData.value.forEach(item => {
+ try {
+ generateWordDocument(templatePath, item, item.companyName+'_基本情况.docx');
+ } catch (error){
+ ElMessage({
+ type: 'warning',
+ message: '导出失败'
+ });
+ }
+ })
+}
+const downloadCert = (info) => {
+ info.type = 'inter'
+ const routePath = '/certPdf'
+ const resolvedRoute = router.resolve(routePath)
+ const queryString = new URLSearchParams(info).toString()
+ const fullPath = `${resolvedRoute.href}?${queryString}`
+ window.open(fullPath, '_blank')
+
+}
+
+const handleSelectionChange = (val) => {
+ choosedData.value = val
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delEvaluate(val.id);
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '删除成功'
+ });
+ getList();
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
+<style lang="scss">
+.pag-container{
+ float: right;
+ margin-top: 10px;
+}
+</style>
diff --git a/src/views/work/selfProblems/plan/components/planDialog.vue b/src/views/work/selfProblems/plan/components/planDialog.vue
new file mode 100644
index 0000000..fcbcb34
--- /dev/null
+++ b/src/views/work/selfProblems/plan/components/planDialog.vue
@@ -0,0 +1,561 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="title"
+ width="50%"
+ :before-close="handleClose"
+ :close-on-press-escape="false"
+ :close-on-click-modal="false"
+ >
+ <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-width="100px" >
+ <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
+ <el-select
+ v-model="state.form.companyId"
+ filterable
+ clearable
+ style="width: 100%"
+ :disabled="title == '查看' || title == '编辑' || !state.isAdmin"
+ @change="selectValueCom"
+ >
+ <el-option
+ v-for="item in state.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="年份:" prop="year" >
+ <el-select
+ :disabled="title === '查看'"
+ v-model="state.form.year"
+ filterable
+ allow-create
+ default-first-option
+ :reserve-keyword="false"
+ @change="handleChangeNum"
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in state.yearList"
+ :key="item.value"
+ :label="item.label"
+ :value="item.label"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="审核目的:" prop="auditPurpose" >
+ <el-input v-model="state.form.auditPurpose" :rows="2" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="审核依据:" prop="reviewBasis" >
+ <el-input v-model="state.form.reviewBasis" :rows="2" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="审核范围:" prop="reviewScope" >
+ <el-input v-model="state.form.reviewScope" :rows="2" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="审核日期:" prop="reviewStart" >
+ <el-date-picker
+ :disabled="title === '查看'"
+ v-model="checkTime"
+ type="daterange"
+ range-separator="至"
+ start-placeholder="开始日期"
+ end-placeholder="结束日期"
+ format="YYYY-MM-DD"
+ />
+ </el-form-item>
+ <el-form-item label="审核组长/审核员:" prop="reviewPerson" >
+ <el-input v-model="state.form.reviewPerson" :rows="2" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="审核起止时间:" prop="firstStarttime" >
+ <div style="display: flex;flex-direction: column">
+ <el-date-picker
+ :disabled="title === '查看'"
+ v-model="checkStartTime"
+ type="datetimerange"
+ range-separator="至"
+ start-placeholder="首次会议开始时间"
+ end-placeholder="首次会议结束时间"
+ format="YYYY-MM-DD HH:mm:ss"
+ style="width: 100%"
+ />
+ <el-date-picker
+ :disabled="title === '查看'"
+ style="margin-top: 10px;width: 100%"
+ v-model="checkEndTime"
+ type="datetimerange"
+ range-separator="至"
+ start-placeholder="末次会议开始时间"
+ end-placeholder="末次会议结束时间"
+ format="YYYY-MM-DD HH:mm:ss"
+ />
+ </div>
+ </el-form-item>
+ <el-row :gutter="24">
+ <el-col :span="24">
+ <el-form-item >
+ <el-button
+ :disabled="title === '查看'"
+ type="primary"
+ @click="addTable"
+ >新增</el-button>
+ <el-table style="margin-top: 10px;margin-bottom: 20px" :data="state.form.deptList" :border="true">
+ <el-table-column label="日期" prop="date" align="center">
+ <template #default="{row,$index}">
+ <el-form-item :prop="'deptList.' + '[' + $index + ']' + '.date'" :rules="state.rules.date">
+ <el-input :disabled="title === '查看'" type="textarea" v-model="row.date" placeholder="请输入"></el-input>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column label="时间" prop="time" align="center">
+ <template #default="{row,$index}">
+ <el-form-item :prop="'deptList.' + '[' + $index + ']' + '.time'" :rules="state.rules.time">
+ <el-input :disabled="title === '查看'" type="textarea" v-model="row.time" placeholder="请输入"></el-input>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column label="受审核部门" prop="deptId" align="center">
+ <template #default="{row,$index}">
+ <el-form-item :prop="'deptList.' + '[' + $index + ']' + '.deptId'" :rules="state.rules.deptId">
+ <el-select
+ :disabled="title === '查看'"
+ v-model="row.deptId"
+ placeholder="请选择部门"
+ style="width: 240px"
+ @change="changeDept(row)"
+ >
+ <el-option
+ v-for="item in state.deptList"
+ :key="item.deptId"
+ :label="item.deptName"
+ :value="item.deptId"
+ />
+ </el-select>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column label="事项/要素" prop="dept" align="center">
+ <template #default="{row,$index}">
+ <span>{{row.termNum}}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="审核员" prop="dept" align="center">
+ <template #default="{row,$index}">
+ <el-form-item :prop="'deptList.' + '[' + $index + ']' + '.checkId'" :rules="state.rules.checkId">
+ <el-select clearable v-model="row.checkId" :disabled="title =='查看'" filterable style="width: 240px">
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column label="操作" align="center" width="120" v-if="title !== '查看'" >
+ <template #default="scope">
+ <el-button link type="danger" @click="delTable(scope.row)" >删除</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="24">
+ <el-col :span="24">
+ <el-form-item label="编制:" prop="compilationId" >
+ <el-select clearable v-model="state.form.compilationId" :disabled="title =='查看'" filterable style="width: 240px">
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="24">
+ <el-col :span="24">
+ <el-form-item label="校对:" prop="proofreadId" >
+ <el-select clearable v-model="state.form.proofreadId" :disabled="title =='查看'" filterable style="width: 240px">
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="24">
+ <el-col :span="24">
+ <el-form-item label="审核:" prop="checkId" >
+ <el-select clearable v-model="state.form.checkId" :disabled="title =='查看'" filterable style="width: 240px">
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="24">
+ <el-col :span="24">
+ <el-form-item label="批准:" prop="ratifyId" >
+ <el-select clearable v-model="state.form.ratifyId" :disabled="title =='查看'" filterable style="width: 240px">
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer v-if="title !== '查看'">
+ <span class="dialog-footer">
+ <el-button @click="handleClose" size="default">取 消</el-button>
+ <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+<script setup>
+import {nextTick, onMounted, reactive, ref, toRefs} from 'vue'
+import Editor from "@/components/Editor/index.vue";
+import {ElMessage} from "element-plus";
+import {addNotice} from "@/api/backManage/notice";
+import {addDict, editDict, getDictDetail} from "@/api/backManage/evaluate";
+import {addCompany, checkName, distributeCompany, editCompany, getCompany} from "@/api/onlineEducation/company";
+import {verifyPhone} from "@/utils/validate";
+import {addBasic, editBasic} from "@/api/companyInfo/basicInfo";
+import Cookies from "js-cookie";
+import {getUser} from "@/api/onlineEducation/user";
+import {getDept} from "@/api/qualityObjectives/object";
+import {addPlan, editPlan} from "@/api/selfProblems/plan";
+
+const dialogVisible = ref(false);
+const title = ref("");
+const busRef = ref();
+const length = ref()
+const checkTime = ref([])
+const checkStartTime = ref([])
+const checkEndTime = ref([])
+const emit = defineEmits(["getList"]);
+const validateFieldsReview = (rule, value, callback) =>{
+ if (checkTime.value && checkTime.value.length >0 ) {
+ callback();
+ } else {
+ callback(new Error('请选择时间'));
+ }
+}
+const validateFields = (rule, value, callback) =>{
+ if (checkStartTime.value && checkStartTime.value.length >0 && checkEndTime.value && checkEndTime.value.length >0 ) {
+ callback();
+ } else {
+ callback(new Error('请选择时间'));
+ }
+}
+const state = reactive({
+ form: {
+ id: '',
+ companyId: null,
+ year: "", //年份
+ auditPurpose: "", //审核目的
+ reviewBasis: "", //审核依据
+ reviewScope: "", //审核范围
+ reviewStart: "",
+ reviewEnd: "", //审核时间
+ reviewPerson: "", //审核组
+ firstStarttime: "", //首次审核开始时间
+ firstEndtime: "", //首次审核结束时间
+ lastStarttime: "", //末次审核开始时间
+ lastEndtime: "", //末次审核结束时间
+ compilationId: null, //编制人id
+ proofreadId: null, //校对人id
+ checkId: null, //审核人id
+ ratifyId: null, //批准人id
+ deptList: []
+ },
+ formRules:{
+ companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+ year: [{ required: true, message: '请输入年份', trigger: 'blur' }],
+ auditPurpose: [{ required: true, message: '请输入审核目的', trigger: 'blur' }], //审核目的
+ reviewBasis: [{ required: true, message: '请输入审核依据', trigger: 'blur' }],//审核依据
+ reviewScope:[{ required: true, message: '请输入审核范围', trigger: 'blur' }], //审核范围
+ reviewStart: [{ required: true,validator: validateFieldsReview, trigger: 'blur' }],//审核时间
+ reviewPerson:[{ required: true, message: '请输入审核组长/审核员', trigger: 'blur' }], //审核组
+ firstStarttime:[{ required: true, validator: validateFields,trigger: 'blur' }],
+ checkEndTime:[{ required: true, message: '请选择末次会议时间', trigger: 'blur' }],
+ compilationId: [{ required: true, message: '请选择编制人', trigger: 'blur' }], //编制人id
+ proofreadId: [{ required: true, message: '请选择校对人', trigger: 'blur' }], //校对人id
+ checkId: [{ required: true, message: '请选择审核人', trigger: 'blur' }], //审核人id
+ ratifyId: [{ required: true, message: '请选择批准人', trigger: 'blur' }], //批准人id
+ },
+ rules: {
+ date: [{required: true, message: "", trigger: "blur"}],
+ time: [{required: true, message: "", trigger: "blur"}],
+ deptId: [{required: true, message: "", trigger: "blur"}],
+ checkId: [{required: true, message: "", trigger: "blur"}],
+
+ },
+ isAdmin: false,
+ companyList: [],
+ yearList: [
+ {
+ value: 1,
+ label: '2025'
+ },
+ {
+ value: 2,
+ label: '2024'
+ },
+ {
+ value: 3,
+ label: '2023'
+ },
+ {
+ value: 4,
+ label: '2022'
+ },
+ {
+ value: 5,
+ label: '2021'
+ },
+ ],
+ peopleList: [],
+ deptList: [],
+})
+
+onMounted(() => {
+
+})
+const openDialog = async (type, value,companyList) => {
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ state.isAdmin = userInfo.userType === 0;
+ state.form.companyName = userInfo.companyName
+ state.form.companyId = userInfo.companyId
+ if(state.isAdmin){
+ state.companyList = companyList
+ state.form.companyId = value.companyId
+ state.form.companyName = value.companyName
+ }
+ await getDeptList()
+ title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
+ if(type === 'edit' || type === 'review') {
+ state.form = JSON.parse(JSON.stringify(value));
+ checkTime.value = [state.form.reviewStart,state.form.reviewEnd]
+ checkStartTime.value = [state.form.firstStarttime,state.form.firstEndtime]
+ checkEndTime.value = [state.form.lastStarttime,state.form.lastEndtime]
+ await nextTick(()=> {
+ state.form.deptList.forEach(item => {
+ state.deptList.forEach(i => {
+ if(i.deptId == item.deptId){
+ item.termNum = sortVersionNumbers(i.caluseVO1List?.map(x=>x.clauseNum)).join('、')
+ }
+ })
+ })
+ })
+ }
+ await getPeopleList()
+
+ dialogVisible.value = true;
+}
+const getPeopleList = async ()=> {
+ if(state.isAdmin && !state.form.companyId && (state.form.companyId == 0 || state.form.companyId == null)){
+ return
+ }
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 9999,
+ companyId: state.form.companyId
+ }
+ const res = await getUser(queryParams)
+ if(res.code == 200){
+ state.peopleList = res.data.list?res.data.list:[]
+ }else{
+ ElMessage.warning(res.message)
+ }
+};
+
+const onSubmit = async () => {
+ state.form.reviewStart = checkTime.value[0]
+ state.form.reviewEnd = checkTime.value[0]
+ state.form.firstStarttime = checkStartTime.value[0]
+ state.form.firstEndtime = checkStartTime.value[1]
+ state.form.lastStarttime = checkEndTime.value[0]
+ state.form.lastEndtime = checkEndTime.value[1]
+
+ const valid = await busRef.value.validate();
+ if(!state.isAdmin){
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ state.form.companyId = userInfo.companyId
+ }
+ if(state.form.deptList && state.form.deptList.length ==0){
+ ElMessage.warning('请添加受审部门信息')
+ return
+ }
+
+ console.log('111',state.form)
+ if(valid){
+ if(title.value === '新增'){
+ const {id, ...data} = JSON.parse(JSON.stringify(state.form))
+ const res = await addPlan(data)
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '新增成功'
+ });
+ }else{
+ ElMessage.warning(res.message)
+ }
+ emit("getList")
+ busRef.value.clearValidate();
+ reset();
+ dialogVisible.value = false;
+ }else if(title.value === '编辑'){
+ const {...data} = JSON.parse(JSON.stringify(state.form))
+ const res = await editPlan(data)
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '编辑成功'
+ });
+ }else{
+ ElMessage.warning(res.message)
+ }
+ emit("getList")
+ busRef.value.clearValidate();
+ reset();
+ dialogVisible.value = false;
+ }
+ }
+}
+const delTable = (val) => {
+ state.form.deptList = state.form.deptList.filter(item=> item.deptId != val.deptId)
+}
+const handleClose = () => {
+ busRef.value.clearValidate();
+ reset();
+ dialogVisible.value = false;
+ emit("getList")
+
+}
+const changeDept = (val) => {
+ let termNum = ''
+ state.deptList.forEach(item => {
+ if(item.deptId == val.deptId){
+ termNum = sortVersionNumbers(item.caluseVO1List?.map(i=>i.clauseNum)).join('、')
+ }
+ })
+ state.form.deptList.forEach(item => {
+ if(item.deptId == val.deptId){
+ item.termNum = termNum
+ }
+ })
+
+}
+const sortVersionNumbers = (versions) => {
+ return versions.sort((a, b) => {
+ const partsA = a.split('.').map(Number);
+ const partsB = b.split('.').map(Number);
+ const maxLength = Math.max(partsA.length, partsB.length)
+ for (let i = 0; i < maxLength; i++) {
+ const numA = partsA[i] || 0
+ const numB = partsB[i] || 0
+
+ if (numA !== numB) {
+ return numA - numB
+ }
+ }
+ return 0
+ });
+}
+const addTable = () => {
+ state.form.deptList.push({})
+}
+const handleChangeNum = (value) => {
+ if (!/^\d+$/.test(value)) { // 验证是否为数字
+ ElMessage.warning('只能输入数字')
+ state.form.year = '' // 重置选择,避免非法值被添加到options中
+ } else if (!state.yearList.some(option => option.label === value)) { // 确保不是已存在的选项
+ state.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同)
+ }
+}
+const getDeptList = async () => {
+ if(state.isAdmin && !state.form.companyId && (state.form.companyId == 0 || state.form.companyId == null)){
+ return
+ }
+ const param = {
+ pageNum: 1,
+ pageSize: 999,
+ companyId: state.form.companyId
+ }
+ const res = await getDept(param)
+ if(res.code === 200){
+ state.deptList = res.data
+ }
+}
+const selectValueCom = (val) => {
+ state.form.compilationId= null
+ state.form.proofreadId = null
+ state.form.checkId = null
+ state.form.ratifyId = null
+ getPeopleList()
+ getDeptList()
+}
+const reset = () => {
+ state.form = {
+ id: '',
+ companyId: null,
+ year: "", //年份
+ auditPurpose: "", //审核目的
+ reviewBasis: "", //审核依据
+ reviewScope: "", //审核范围
+ reviewStart: "",
+ reviewEnd: "", //审核时间
+ reviewPerson: "", //审核组
+ firstStarttime: "", //首次审核开始时间
+ firstEndtime: "", //首次审核结束时间
+ lastStarttime: "", //末次审核开始时间
+ lastEndtime: "", //末次审核结束时间
+ compilationId: null, //编制人id
+ proofreadId: null, //校对人id
+ checkId: null, //审核人id
+ ratifyId: null, //批准人id
+ deptList: []
+
+ }
+ state.companyList = []
+ state.peopleList = []
+ checkTime.value = []
+ checkStartTime.value = []
+ checkEndTime.value = []
+}
+defineExpose({
+ openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+ :deep(.el-form .el-form-item__label) {
+ font-size: 15px;
+ }
+ .file {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ }
+}
+</style>
diff --git a/src/views/work/selfProblems/plan/index.vue b/src/views/work/selfProblems/plan/index.vue
new file mode 100644
index 0000000..effd72a
--- /dev/null
+++ b/src/views/work/selfProblems/plan/index.vue
@@ -0,0 +1,265 @@
+<template>
+ <div class="app-container">
+ <div style="margin-bottom: 10px">
+ <el-form style="display: flex;flex-wrap: wrap;">
+ <el-form-item>
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="openDialog('add',{})"
+ >新增</el-button>
+ </el-form-item>
+ <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px">
+ <el-select v-model="data.queryParams.companyId" filterable placeholder="请选择" clearable>
+ <el-option
+ v-for="item in data.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="data.isAdmin">
+ <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button>
+ <el-button plain @click="reset">重置</el-button>
+ </el-form-item>
+ <el-form-item style="margin-left: 15px">
+ <el-button
+ type="primary"
+ @click="exportData"
+ >导出</el-button>
+ </el-form-item>
+
+ </el-form>
+ </div>
+ <!-- 表格数据 -->
+ <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" />
+ <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
+ <el-table-column v-if="data.isAdmin" label="公司名称" prop="companyName" align="center" />
+ <el-table-column label="计划名称" align="center">
+ <template #default="scope">
+ <span>{{scope.row.year}}年内审实施计划</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+ <template #default="scope">
+ <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button>
+ <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button>
+ <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <div class="pag-container">
+ <el-pagination
+ v-model:current-page="data.queryParams.pageNum"
+ v-model:page-size="data.queryParams.pageSize"
+ :page-sizes="[10,15,20,25]"
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="total"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ />
+ </div>
+ <planDialog ref="noticeRef" @getList = "getList"></planDialog>
+ </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs} from "vue";
+import planDialog from "./components/planDialog.vue"
+import {ElMessage, ElMessageBox} from "element-plus";
+import {getCompany} from "@/api/onlineEducation/company";
+import Cookies from "js-cookie";
+import {generateWordDocument} from "@/utils/exportWord";
+import {delBasic, getBasic} from "@/api/companyInfo/basicInfo";
+import {delPlan, getPlanPage} from "@/api/selfProblems/plan";
+import {getDept} from "@/api/qualityObjectives/object";
+
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const noticeRef = ref();
+const loadingCompany = ref(false)
+const choosedData = ref([])
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ },
+ companyList: [],
+ isAdmin: false,
+ deptList: []
+});
+const dataList = ref([]);
+const total = ref(0);
+
+const { queryParams } = toRefs(data);
+
+onMounted(() => {
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ console.log("userInfo",userInfo)
+ data.isAdmin = userInfo.userType === 0;
+ if(data.isAdmin){
+ data.queryParams.companyId = null
+ getCompanyList()
+ }else {
+ data.queryParams.companyId = userInfo.companyId
+ }
+ getList();
+ getDeptList()
+});
+const getList = async () => {
+ loading.value = true;
+ const res = await getPlanPage(data.queryParams);
+ if(res.code === 200){
+ dataList.value = res.data.list
+ total.value = res.data.total
+ }else{
+ ElMessage.warning(res.message)
+ }
+ loading.value = false;
+}
+
+const searchClick = () => {
+ getList();
+}
+const openDialog = (type, value) => {
+ noticeRef.value.openDialog(type, value,data.companyList);
+}
+const selectValue = (val) => {
+ data.companyList.forEach(item => {
+ if(item.name === val){
+ data.queryParams.companyId = item.id
+ }
+ })
+}
+
+const getCompanyList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getCompany(queryParams)
+ if (res.code == 200) {
+ data.companyList = res.data.list?res.data.list:[]
+ // data.queryParams.companyId = data.companyList[0].id
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const handleSizeChange = (val) => {
+ data.queryParams.pageSize = val
+ getList()
+}
+const handleCurrentChange = (val) => {
+ data.queryParams.pageNum = val
+ getList()
+}
+
+/** 重置新增的表单以及其他数据 */
+function reset() {
+ data.queryParams = {
+ companyId: '',
+ pageNum: 1,
+ pageSize: 10,
+ }
+ choosedData.value = []
+ data.companyList = [];
+ getList();
+ getCompanyList()
+}
+const exportData = () => {
+ if(choosedData.value && choosedData.value.length === 0){
+ ElMessage.warning('请选择需要导出的数据')
+ }else {
+ startGeneration()
+ }
+}
+const templatePath = '/planExample.docx'
+const startGeneration = async () => {
+ for (const item of choosedData.value) {
+ await nextTick(()=> {
+ item.deptList.forEach(de => {
+ data.deptList.forEach(d=> {
+ if(de.deptId == d.deptId){
+ de.term = sortVersionNumbers(d.caluseVO1List?.map(x=>x.clauseNum)).join('、')
+ }
+ })
+ })
+ })
+ console.log('x',item.deptList)
+ item.reviewStart = item.reviewStart.substring(0,10)
+ item.reviewEnd = item.reviewEnd.substring(0,10)
+ try {
+ generateWordDocument(templatePath, item, item.companyName+'_' +item.year +'内审实施计划.docx');
+ } catch (error){
+ ElMessage({
+ type: 'warning',
+ message: '导出失败'
+ });
+ }
+ }
+}
+const sortVersionNumbers = (versions) => {
+ return versions.sort((a, b) => {
+ const partsA = a.split('.').map(Number);
+ const partsB = b.split('.').map(Number);
+ const maxLength = Math.max(partsA.length, partsB.length)
+ for (let i = 0; i < maxLength; i++) {
+ const numA = partsA[i] || 0
+ const numB = partsB[i] || 0
+
+ if (numA !== numB) {
+ return numA - numB
+ }
+ }
+ return 0
+ });
+}
+const getDeptList= async () => {
+ const param = {
+ companyId: data.queryParams.companyId,
+ }
+ const res = await getDept(param)
+ if(res.code === 200){
+ data.deptList = res.data
+ }
+}
+
+const handleSelectionChange = (val) => {
+ choosedData.value = val
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delPlan(val.id);
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '删除成功'
+ });
+ getList();
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
+<style lang="scss">
+.pag-container{
+ float: right;
+ margin-top: 10px;
+}
+</style>
diff --git a/src/views/work/selfProblems/scenario/components/scenarioDialog.vue b/src/views/work/selfProblems/scenario/components/scenarioDialog.vue
new file mode 100644
index 0000000..8685cb8
--- /dev/null
+++ b/src/views/work/selfProblems/scenario/components/scenarioDialog.vue
@@ -0,0 +1,364 @@
+<template>
+ <div class="notice">
+ <el-dialog
+ v-model="dialogVisible"
+ :title="title"
+ width="50%"
+ :before-close="handleClose"
+ :close-on-press-escape="false"
+ :close-on-click-modal="false"
+ >
+ <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-position="top" label-width="150px" >
+ <el-form-item label="企业名称:" prop="companyId" v-if="state.isAdmin">
+ <el-select
+ v-model="state.form.companyId"
+ filterable
+ clearable
+ style="width: 100%"
+ :disabled="title == '查看' || title == '编辑' || !state.isAdmin"
+ @change="selectValueCom"
+ >
+ <el-option
+ v-for="item in state.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="年份:" prop="year" >
+ <el-select
+ :disabled="title === '查看'"
+ v-model="state.form.year"
+ filterable
+ allow-create
+ default-first-option
+ :reserve-keyword="false"
+ @change="handleChangeNum"
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in state.yearList"
+ :key="item.value"
+ :label="item.label"
+ :value="item.label"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="1.目的" prop="purpose" >
+ <el-input v-model="state.form.purpose" :rows="4" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="2.内审目的" prop="auditPurpose" >
+ <el-input v-model="state.form.auditPurpose" :rows="4" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="3.审核范围" prop="reviewScope" >
+ <el-input v-model="state.form.reviewScope" :rows="4" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="4.审核依据" prop="reviewBasis" >
+ <el-input v-model="state.form.reviewBasis" :rows="4" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="5.审核实施" prop="reviewCarry" >
+ <el-input v-model="state.form.reviewCarry" :rows="4" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="6.审核组构成" prop="reviewConstitute" >
+ <el-input v-model="state.form.reviewConstitute" :rows="4" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ <el-form-item label="7.要求" prop="reviewRequire" >
+ <el-input v-model="state.form.reviewRequire" :rows="4" type="textarea" :disabled="title === '查看'"/>
+ </el-form-item>
+ </el-form>
+ <el-form :model="state.form" size="default" ref="peoRef" :rules="state.peoRules" label-width="60px">
+ <el-row :gutter="24">
+ <el-col :span="24">
+ <el-form-item label="编制:" prop="compilationId" >
+ <el-select clearable v-model="state.form.compilationId" :disabled="title =='查看'" filterable style="width: 240px">
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="24">
+ <el-col :span="24">
+ <el-form-item label="校对:" prop="proofreadId" >
+ <el-select clearable v-model="state.form.proofreadId" :disabled="title =='查看'" filterable style="width: 240px">
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="24">
+ <el-col :span="24">
+ <el-form-item label="审核:" prop="checkId" >
+ <el-select clearable v-model="state.form.checkId" :disabled="title =='查看'" filterable style="width: 240px">
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="24">
+ <el-col :span="24">
+ <el-form-item label="批准:" prop="ratifyId" >
+ <el-select clearable v-model="state.form.ratifyId" :disabled="title =='查看'" filterable style="width: 240px">
+ <el-option
+ v-for="item in state.peopleList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer v-if="title !== '查看'">
+ <span class="dialog-footer">
+ <el-button @click="handleClose" size="default">取 消</el-button>
+ <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+<script setup>
+import {onMounted, reactive, ref, toRefs} from 'vue'
+import Editor from "@/components/Editor/index.vue";
+import {ElMessage} from "element-plus";
+import {addNotice} from "@/api/backManage/notice";
+import {addDict, editDict, getDictDetail} from "@/api/backManage/evaluate";
+import {addCompany, checkName, distributeCompany, editCompany, getCompany} from "@/api/onlineEducation/company";
+import {verifyPhone} from "@/utils/validate";
+import {addBasic, editBasic} from "@/api/companyInfo/basicInfo";
+import Cookies from "js-cookie";
+import {getUser} from "@/api/onlineEducation/user";
+import {addScenario, editScenario} from "@/api/selfProblems/scenario";
+
+const dialogVisible = ref(false);
+const title = ref("");
+const busRef = ref();
+const peoRef = ref()
+const length = ref()
+const emit = defineEmits(["getList"]);
+const state = reactive({
+ form: {
+ id: '',
+ companyId: null,
+ year: "",
+ purpose: "",
+ auditPurpose: "",
+ reviewBasis: "",
+ reviewScope: "",
+ reviewCarry: "",
+ reviewConstitute: "",
+ reviewRequire: "",
+ compilationId: null,
+ proofreadId: null,
+ checkId: null,
+ ratifyId: null
+ },
+ formRules:{
+ companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+ year: [{ required: true, message: '请选择年份', trigger: 'blur' }],
+ purpose:[{ required: true, message: '请输入目的', trigger: 'blur' }],
+ auditPurpose: [{ required: true, message: '请输入审核目的', trigger: 'blur' }],
+ reviewBasis: [{ required: true, message: '请输入审核依据', trigger: 'blur' }],
+ reviewScope: [{ required: true, message: '请输入审核范围', trigger: 'blur' }],
+ reviewCarry: [{ required: true, message: '请输入审核实施', trigger: 'blur' }],
+ reviewConstitute: [{ required: true, message: '请输入审核组构成', trigger: 'blur' }],
+ reviewRequire: [{ required: true, message: '请输入要求', trigger: 'blur' }],
+
+ },
+ peoRules: {
+ compilationId: [{ required: true, message: '请选择编制人', trigger: 'blur' }],
+ proofreadId: [{ required: true, message: '请选择校对人', trigger: 'blur' }],
+ checkId: [{ required: true, message: '请选择审核人', trigger: 'blur' }],
+ ratifyId: [{ required: true, message: '请选择批准人', trigger: 'blur' }],
+ },
+ isAdmin: false,
+ companyList: [],
+ yearList: [
+ {
+ value: 1,
+ label: '2025'
+ },
+ {
+ value: 2,
+ label: '2024'
+ },
+ {
+ value: 3,
+ label: '2023'
+ },
+ {
+ value: 4,
+ label: '2022'
+ },
+ {
+ value: 5,
+ label: '2021'
+ },
+ ],
+ peopleList: [],
+})
+
+onMounted(() => {
+
+})
+const openDialog = async (type, value,companyList) => {
+
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ state.isAdmin = userInfo.userType === 0;
+ state.form.companyName = userInfo.companyName
+ state.form.companyId = userInfo.companyId
+ if(state.isAdmin){
+ state.companyList = companyList
+ state.form.companyId = value.companyId
+ state.form.companyName = value.companyName
+ }
+ title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
+ if(type === 'edit' || type === 'review') {
+ state.form = JSON.parse(JSON.stringify(value));
+ if(state.isAdmin){
+ state.form.companyId = value.companyId
+ state.form.companyName = value.companyName
+ }
+ }
+ await getPeopleList()
+ dialogVisible.value = true;
+}
+const getPeopleList = async ()=> {
+ if(state.isAdmin && !state.form.companyId && (state.form.companyId == 0 || state.form.companyId == null)){
+ return
+ }
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 9999,
+ companyId: state.form.companyId
+ }
+ const res = await getUser(queryParams)
+ if(res.code == 200){
+ state.peopleList = res.data.list?res.data.list:[]
+ }else{
+ ElMessage.warning(res.message)
+ }
+};
+
+const onSubmit = async () => {
+ const valid = await busRef.value.validate();
+ const validPro = await peoRef.value.validate();
+ if(!state.isAdmin){
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ state.form.companyId = userInfo.companyId
+ }
+ if(valid && validPro){
+ if(title.value === '新增'){
+ const {id, ...data} = JSON.parse(JSON.stringify(state.form))
+ const res = await addScenario(data)
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '新增成功'
+ });
+ }else{
+ ElMessage.warning(res.message)
+ }
+ emit("getList")
+ busRef.value.clearValidate();
+ peoRef.value.clearValidate();
+ reset();
+ dialogVisible.value = false;
+ }else if(title.value === '编辑'){
+ const {...data} = JSON.parse(JSON.stringify(state.form))
+ const res = await editScenario(data)
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '编辑成功'
+ });
+ }else{
+ ElMessage.warning(res.message)
+ }
+ emit("getList")
+ busRef.value.clearValidate();
+ peoRef.value.clearValidate();
+ reset();
+ dialogVisible.value = false;
+ }
+ }
+}
+
+const handleClose = () => {
+ busRef.value.clearValidate();
+ peoRef.value.clearValidate();
+ reset();
+ dialogVisible.value = false;
+ emit("getList")
+
+}
+const handleChangeNum = (value) => {
+ if (!/^\d+$/.test(value)) { // 验证是否为数字
+ ElMessage.warning('只能输入数字')
+ state.form.year = '' // 重置选择,避免非法值被添加到options中
+ } else if (!state.yearList.some(option => option.label === value)) { // 确保不是已存在的选项
+ state.yearList.push({ value, label: value }); // 添加新选项(这里简单地将值和标签设为相同)
+ }
+}
+const selectValueCom = (val) => {
+ state.form.compilationId = null
+ state.form.proofreadId = null
+ state.form.checkId = null
+ state.form.ratifyId = null
+ getPeopleList()
+}
+const reset = () => {
+ state.form = {
+ id: '',
+ companyId: null,
+ year: "",
+ purpose: "",
+ auditPurpose: "",
+ reviewBasis: "",
+ reviewScope: "",
+ reviewCarry: "",
+ reviewConstitute: "",
+ reviewRequire: "",
+ compilationId: null,
+ proofreadId: null,
+ checkId: null,
+ ratifyId: null
+ }
+ state.companyList = []
+ state.peopleList = []
+}
+defineExpose({
+ openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+ :deep(.el-form .el-form-item__label) {
+ font-size: 15px;
+ }
+ .file {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ }
+}
+</style>
diff --git a/src/views/work/selfProblems/scenario/index.vue b/src/views/work/selfProblems/scenario/index.vue
new file mode 100644
index 0000000..6a4dfe2
--- /dev/null
+++ b/src/views/work/selfProblems/scenario/index.vue
@@ -0,0 +1,222 @@
+<template>
+ <div class="app-container">
+ <div style="margin-bottom: 10px">
+ <el-form style="display: flex;flex-wrap: wrap;">
+ <el-form-item>
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="openDialog('add',{})"
+ >新增</el-button>
+ </el-form-item>
+ <el-form-item label="企业名称:" v-if="data.isAdmin" style="margin-left: 20px">
+ <el-select v-model="data.queryParams.companyId" filterable placeholder="请选择" clearable>
+ <el-option
+ v-for="item in data.companyList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="data.isAdmin">
+ <el-button type="primary" style="margin-left: 30px" @click="searchClick">查询</el-button>
+ <el-button plain @click="reset">重置</el-button>
+ </el-form-item>
+
+
+ <el-form-item style="margin-left: 15px">
+ <el-button
+ type="primary"
+ @click="exportData"
+ >导出</el-button>
+ </el-form-item>
+
+ </el-form>
+ </div>
+ <!-- 表格数据 -->
+ <el-table v-loading="loading" :data="dataList" :border="true" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" />
+ <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
+ <el-table-column v-if="data.isAdmin" label="企业名称" prop="companyName" align="center">
+ </el-table-column>
+ <el-table-column label="方案名称" align="center">
+ <template #default="scope">
+ <span>{{scope.row.year}}年度内部审核策划方案</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="操作" align="center" class-name="small-padding fixed-width" >
+ <template #default="scope">
+ <el-button link type="primary" @click="openDialog('review',scope.row)" >查看</el-button>
+ <el-button link type="primary" @click="openDialog('edit',scope.row)" >编辑</el-button>
+ <el-button link type="danger" @click="handleDelete(scope.row)" >删除</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <div class="pag-container">
+ <el-pagination
+ v-model:current-page="data.queryParams.pageNum"
+ v-model:page-size="data.queryParams.pageSize"
+ :page-sizes="[10,15,20,25]"
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="total"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ />
+ </div>
+ <scenarioDialog ref="noticeRef" @getList = "getList"></scenarioDialog>
+ </div>
+</template>
+
+<script setup>
+import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
+import scenarioDialog from "./components/scenarioDialog.vue"
+import {ElMessage, ElMessageBox} from "element-plus";
+import {getCompany} from "@/api/onlineEducation/company";
+import Cookies from "js-cookie";
+import {generateWordDocument} from "@/utils/exportWord";
+import {delBasic, getBasic} from "@/api/companyInfo/basicInfo";
+import {delScenario, getScenarioPage} from "@/api/selfProblems/scenario";
+
+const { proxy } = getCurrentInstance();
+const loading = ref(false);
+const noticeRef = ref();
+const loadingCompany = ref(false)
+const choosedData = ref([])
+const data = reactive({
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ companyId: null,
+ },
+ companyList: [],
+ isAdmin: false
+});
+const dataList = ref([]);
+const total = ref(0);
+
+const { queryParams } = toRefs(data);
+
+onMounted(() => {
+ const userInfo = JSON.parse(Cookies.get('userInfo'))
+ console.log("userInfo",userInfo)
+ data.isAdmin = userInfo.userType === 0;
+ if(data.isAdmin){
+ data.queryParams.companyId = null
+ getCompanyList()
+ }else {
+ data.queryParams.companyId = userInfo.companyId
+ }
+ getList();
+});
+const getList = async () => {
+ loading.value = true;
+ const res = await getScenarioPage(data.queryParams);
+ if(res.code === 200){
+ dataList.value = res.data.list
+ total.value = res.data.total
+ }else{
+ ElMessage.warning(res.message)
+ }
+ loading.value = false;
+
+}
+
+const searchClick = () => {
+ getList();
+}
+const openDialog = (type, value) => {
+ noticeRef.value.openDialog(type, value,data.companyList);
+}
+
+const getCompanyList = async ()=>{
+ const queryParams = {
+ pageNum: 1,
+ pageSize: 999
+ }
+ const res = await getCompany(queryParams)
+ if (res.code == 200) {
+ data.companyList = res.data.list?res.data.list:[]
+ } else {
+ ElMessage.warning(res.message)
+ }
+}
+
+const handleSizeChange = (val) => {
+ data.queryParams.pageSize = val
+ getList()
+}
+const handleCurrentChange = (val) => {
+ data.queryParams.pageNum = val
+ getList()
+}
+
+/** 重置新增的表单以及其他数据 */
+function reset() {
+ data.queryParams = {
+ companyId: '',
+ pageNum: 1,
+ pageSize: 10,
+ }
+ choosedData.value = []
+ data.companyList = [];
+ getList();
+ getCompanyList()
+}
+const exportData = () => {
+ if(choosedData.value && choosedData.value.length === 0){
+ ElMessage.warning('请选择需要导出的数据')
+ }else {
+ startGeneration()
+ }
+}
+const templatePath = '/scenarioExample.docx'
+const startGeneration = async () => {
+ choosedData.value.forEach(item => {
+ try {
+ item.title = item.year+'年度内部审核策划方案'
+ generateWordDocument(templatePath, item, item.companyName+ '_' + item.title +'.docx');
+ } catch (error){
+ ElMessage({
+ type: 'warning',
+ message: '导出失败'
+ });
+ }
+ })
+}
+
+const handleSelectionChange = (val) => {
+ choosedData.value = val
+}
+const handleDelete = (val) => {
+ ElMessageBox.confirm(
+ '确定删除此条数据?',
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ })
+ .then( async() => {
+ const res = await delScenario(val.id);
+ if(res.code === 200){
+ ElMessage({
+ type: 'success',
+ message: '删除成功'
+ });
+ getList();
+ }else{
+ ElMessage.warning(res.message)
+ }
+ })
+}
+
+</script>
+<style lang="scss">
+.pag-container{
+ float: right;
+ margin-top: 10px;
+}
+</style>
--
Gitblit v1.9.2