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