1&&(Ro.forEach(function(e){r.addAnimationState({target:e,rect:Uo?Di(e):i}),Hi(e),e.fromRect=i,t.removeAnimationState(e)}),Uo=!1,ha(!this.options.removeCloneOnHide,n))},dragOverCompleted:function(e){var t=e.sortable,n=e.isOwner,r=e.insertion,i=e.activeSortable,a=e.parentEl,o=e.putSortable,s=this.options;if(r){if(n&&i._hideClone(),Ho=!1,s.animation&&Ro.length>1&&(Uo||!n&&!i.options.sort&&!o)){var c=Di(Go,!1,!0,!0);Ro.forEach(function(e){e!==Go&&(Vi(e,c),a.appendChild(e))}),Uo=!0}if(!n)if(Uo||_a(),Ro.length>1){var l=qo;i._showClone(t),i.options.animation&&!qo&&l&&zo.forEach(function(e){i.addAnimationState({target:e,rect:Ko}),e.fromRect=Ko,e.thisAnimationDuration=null})}else i._showClone(t)}},dragOverAnimationCapture:function(e){var t=e.dragRect,n=e.isOwner,r=e.activeSortable;if(Ro.forEach(function(e){e.thisAnimationDuration=null}),r.options.animation&&!n&&r.multiDrag.isMultiDrag){Ko=si({},t);var i=wi(Go,!0);Ko.top-=i.f,Ko.left-=i.e}},dragOverAnimationComplete:function(){Uo&&(Uo=!1,_a())},drop:function(e){var t=e.originalEvent,n=e.rootEl,r=e.parentEl,i=e.sortable,a=e.dispatchSortableEvent,o=e.oldIndex,s=e.putSortable,c=s||this.sortable;if(t){var l=this.options,u=r.children;if(!Wo)if(l.multiDragKey&&!this.multiDragKeyDown&&this._deselectMultiDrag(),Si(Go,l.selectedClass,!~Ro.indexOf(Go)),~Ro.indexOf(Go))Ro.splice(Ro.indexOf(Go),1),Bo=null,Ki({sortable:i,rootEl:n,name:`deselect`,targetEl:Go,originalEvt:t});else{if(Ro.push(Go),Ki({sortable:i,rootEl:n,name:`select`,targetEl:Go,originalEvt:t}),t.shiftKey&&Bo&&i.el.contains(Bo)){var d=ji(Bo),f=ji(Go);if(~d&&~f&&d!==f){var p,m;for(f>d?(m=d,p=f):(m=f,p=d+1);m1){var h=Di(Go),g=ji(Go,`:not(.`+this.options.selectedClass+`)`);if(!Ho&&l.animation&&(Go.thisAnimationDuration=null),c.captureAnimationState(),!Ho&&(l.animation&&(Go.fromRect=h,Ro.forEach(function(e){if(e.thisAnimationDuration=null,e!==Go){var t=Uo?Di(e):h;e.fromRect=t,c.addAnimationState({target:e,rect:t})}})),_a(),Ro.forEach(function(e){u[g]?r.insertBefore(e,u[g]):r.appendChild(e),g++}),o===ji(Go))){var _=!1;Ro.forEach(function(e){if(e.sortableIndex!==ji(e)){_=!0;return}}),_&&a(`update`)}Ro.forEach(function(e){Hi(e)}),c.animateAll()}Vo=c}(n===r||s&&s.lastPutMode!==`clone`)&&zo.forEach(function(e){e.parentNode&&e.parentNode.removeChild(e)})}},nullingGlobal:function(){this.isMultiDrag=Wo=!1,zo.length=0},destroyGlobal:function(){this._deselectMultiDrag(),vi(document,`pointerup`,this._deselectMultiDrag),vi(document,`mouseup`,this._deselectMultiDrag),vi(document,`touchend`,this._deselectMultiDrag),vi(document,`keydown`,this._checkKeyDown),vi(document,`keyup`,this._checkKeyUp)},_deselectMultiDrag:function(e){if(!(Wo!==void 0&&Wo)&&Vo===this.sortable&&!(e&&xi(e.target,this.options.draggable,this.sortable.el,!1))&&!(e&&e.button!==0))for(;Ro.length;){var t=Ro[0];Si(t,this.options.selectedClass,!1),Ro.shift(),Ki({sortable:this.sortable,rootEl:this.sortable.el,name:`deselect`,targetEl:t,originalEvt:e})}},_checkKeyDown:function(e){e.key===this.options.multiDragKey&&(this.multiDragKeyDown=!0)},_checkKeyUp:function(e){e.key===this.options.multiDragKey&&(this.multiDragKeyDown=!1)}},si(e,{pluginName:`multiDrag`,utils:{select:function(e){var t=e.parentNode[Oa];!t||!t.options.multiDrag||~Ro.indexOf(e)||(Vo&&Vo!==t&&(Vo.multiDrag._deselectMultiDrag(),Vo=t),Si(e,t.options.selectedClass,!0),Ro.push(e))},deselect:function(e){var t=e.parentNode[Oa],n=Ro.indexOf(e);!t||!t.options.multiDrag||!~n||(Si(e,t.options.selectedClass,!1),Ro.splice(n,1))}},eventProperties:function(){var e=this,t=[],n=[];return Ro.forEach(function(r){t.push({multiDragElement:r,index:r.sortableIndex});var i=Uo&&r!==Go?-1:Uo?ji(r,`:not(.`+e.options.selectedClass+`)`):ji(r);n.push({multiDragElement:r,index:i})}),{items:ui(Ro),clones:[].concat(zo),oldIndicies:t,newIndicies:n}},optionListeners:{multiDragKey:function(e){return e=e.toLowerCase(),e===`ctrl`?e=`Control`:e.length>1&&(e=e.charAt(0).toUpperCase()+e.substr(1)),e}}})}function ha(e,t){Ro.forEach(function(n,r){var i=t.children[n.sortableIndex+(e?Number(r):0)];i?t.insertBefore(n,i):t.appendChild(n)})}function ga(e,t){zo.forEach(function(n,r){var i=t.children[n.sortableIndex+(e?Number(r):0)];i?t.insertBefore(n,i):t.appendChild(n)})}function _a(){Ro.forEach(function(e){e!==Go&&e.parentNode&&e.parentNode.removeChild(e)})}var va,ya,ba,xa,Sa,Ca,wa,Ta,Ea,Da,Oa,ka,Aa,ja,Ma,Na,Pa,Fa,Ia,La,Ra,za,Ba,Va,Ha,Ua,Wa,Ga,Ka,qa,Ja,Ya,Xa,Za,Qa,$a,eo,to,no,ro,io,ao,oo,so,co,lo,uo,fo,po,mo,ho,go,_o,vo,yo,bo,xo,So,Co,wo,To,Eo,Do,Oo,ko,Ao,jo,Mo,No,Po,Fo,Io,Lo,Ro,zo,Bo,Vo,Ho,Uo,Wo,Go,Ko,qo,Jo=n((()=>{va=`1.14.0`,ya=gi(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),ba=gi(/Edge/i),xa=gi(/firefox/i),Sa=gi(/safari/i)&&!gi(/chrome/i)&&!gi(/android/i),Ca=gi(/iP(ad|od|hone)/i),wa=gi(/chrome/i)&&gi(/android/i),Ta={capture:!1,passive:!1},Ea=/\s+/g,Oa=`Sortable`+new Date().getTime(),ka=[],Aa={initializeByDefault:!0},ja={mount:function(e){for(var t in Aa)Aa.hasOwnProperty(t)&&!(t in e)&&(e[t]=Aa[t]);ka.forEach(function(t){if(t.pluginName===e.pluginName)throw`Sortable: Cannot mount plugin ${e.pluginName} more than once`}),ka.push(e)},pluginEvent:function(e,t,n){var r=this;this.eventCanceled=!1,n.cancel=function(){r.eventCanceled=!0};var i=e+`Global`;ka.forEach(function(r){t[r.pluginName]&&(t[r.pluginName][i]&&t[r.pluginName][i](ii({sortable:t},n)),t.options[r.pluginName]&&t[r.pluginName][e]&&t[r.pluginName][e](ii({sortable:t},n)))})},initializePlugins:function(e,t,n,r){for(var i in ka.forEach(function(r){var i=r.pluginName;if(!(!e.options[i]&&!r.initializeByDefault)){var a=new r(e,t,e.options);a.sortable=e,a.options=e.options,e[i]=a,si(n,a.defaults)}}),e.options)if(e.options.hasOwnProperty(i)){var a=this.modifyOption(e,i,e.options[i]);a!==void 0&&(e.options[i]=a)}},getEventProperties:function(e,t){var n={};return ka.forEach(function(r){typeof r.eventProperties==`function`&&si(n,r.eventProperties.call(t[r.pluginName],e))}),n},modifyOption:function(e,t,n){var r;return ka.forEach(function(i){e[i.pluginName]&&i.optionListeners&&typeof i.optionListeners[t]==`function`&&(r=i.optionListeners[t].call(e[i.pluginName],n))}),r}},Ma=[`evt`],Na=function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},r=n.evt,i=li(n,Ma);ja.pluginEvent.bind(Ji)(e,t,ii({dragEl:Pa,parentEl:Fa,ghostEl:Ia,rootEl:La,nextEl:Ra,lastDownEl:za,cloneEl:Ba,cloneHidden:Va,dragStarted:ro,putSortable:qa,activeSortable:Ji.active,originalEvent:r,oldIndex:Ha,oldDraggableIndex:Wa,newIndex:Ua,newDraggableIndex:Ga,hideGhostForTarget:Co,unhideGhostForTarget:wo,cloneNowHidden:function(){Va=!0},cloneNowShown:function(){Va=!1},dispatchSortableEvent:function(e){qi({sortable:t,name:e,originalEvent:r})}},i))},Ja=!1,Ya=!1,Xa=[],oo=!1,so=!1,uo=[],fo=!1,po=[],mo=typeof document<`u`,ho=Ca,go=ba||ya?`cssFloat`:`float`,_o=mo&&!wa&&!Ca&&`draggable`in document.createElement(`div`),vo=function(){if(mo){if(ya)return!1;var e=document.createElement(`x`);return e.style.cssText=`pointer-events:auto`,e.style.pointerEvents===`auto`}}(),yo=function(e,t){var n=Ci(e),r=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=ki(e,0,t),a=ki(e,1,t),o=i&&Ci(i),s=a&&Ci(a),c=o&&parseInt(o.marginLeft)+parseInt(o.marginRight)+Di(i).width,l=s&&parseInt(s.marginLeft)+parseInt(s.marginRight)+Di(a).width;if(n.display===`flex`)return n.flexDirection===`column`||n.flexDirection===`column-reverse`?`vertical`:`horizontal`;if(n.display===`grid`)return n.gridTemplateColumns.split(` `).length<=1?`vertical`:`horizontal`;if(i&&o.float&&o.float!==`none`){var u=o.float===`left`?`left`:`right`;return a&&(s.clear===`both`||s.clear===u)?`vertical`:`horizontal`}return i&&(o.display===`block`||o.display===`flex`||o.display===`table`||o.display===`grid`||c>=r&&n[go]===`none`||a&&n[go]===`none`&&c+l>r)?`vertical`:`horizontal`},bo=function(e,t,n){var r=n?e.left:e.top,i=n?e.right:e.bottom,a=n?e.width:e.height,o=n?t.left:t.top,s=n?t.right:t.bottom,c=n?t.width:t.height;return r===o||i===s||r+a/2===o+c/2},xo=function(e,t){var n;return Xa.some(function(r){var i=r[Oa].options.emptyInsertThreshold;if(!(!i||Ai(r))){var a=Di(r),o=e>=a.left-i&&e<=a.right+i,s=t>=a.top-i&&t<=a.bottom+i;if(o&&s)return n=r}}),n},So=function(e){function t(e,n){return function(r,i,a,o){var s=r.options.group.name&&i.options.group.name&&r.options.group.name===i.options.group.name;if(e==null&&(n||s))return!0;if(e==null||e===!1)return!1;if(n&&e===`clone`)return e;if(typeof e==`function`)return t(e(r,i,a,o),n)(r,i,a,o);var c=(n?r:i).options.group.name;return e===!0||typeof e==`string`&&e===c||e.join&&e.indexOf(c)>-1}}var n={},r=e.group;(!r||ai(r)!=`object`)&&(r={name:r}),n.name=r.name,n.checkPull=t(r.pull,!0),n.checkPut=t(r.put),n.revertClone=r.revertClone,e.group=n},Co=function(){!vo&&Ia&&Ci(Ia,`display`,`none`)},wo=function(){!vo&&Ia&&Ci(Ia,`display`,``)},mo&&document.addEventListener(`click`,function(e){if(Ya)return e.preventDefault(),e.stopPropagation&&e.stopPropagation(),e.stopImmediatePropagation&&e.stopImmediatePropagation(),Ya=!1,!1},!0),To=function(e){if(Pa){e=e.touches?e.touches[0]:e;var t=xo(e.clientX,e.clientY);if(t){var n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]=e[r]);n.target=n.rootEl=t,n.preventDefault=void 0,n.stopPropagation=void 0,t[Oa]._onDragOver(n)}}},Eo=function(e){Pa&&Pa.parentNode[Oa]._isOutsideThisEl(e.target)},Ji.prototype={constructor:Ji,_isOutsideThisEl:function(e){!this.el.contains(e)&&e!==this.el&&(io=null)},_getDirection:function(e,t){return typeof this.options.direction==`function`?this.options.direction.call(this,e,t,Pa):this.options.direction},_onTapStart:function(e){if(e.cancelable){var t=this,n=this.el,r=this.options,i=r.preventOnFilter,a=e.type,o=e.touches&&e.touches[0]||e.pointerType&&e.pointerType===`touch`&&e,s=(o||e).target,c=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||s,l=r.filter;if(ia(n),!Pa&&!(/mousedown|pointerdown/.test(a)&&e.button!==0||r.disabled)&&!c.isContentEditable&&!(!this.nativeDraggable&&Sa&&s&&s.tagName.toUpperCase()===`SELECT`)&&(s=xi(s,r.draggable,n,!1),!(s&&s.animated)&&za!==s)){if(Ha=ji(s),Wa=ji(s,r.draggable),typeof l==`function`){if(l.call(this,e,s,this)){qi({sortable:t,rootEl:c,name:`filter`,targetEl:s,toEl:n,fromEl:n}),Na(`filter`,t,{evt:e}),i&&e.cancelable&&e.preventDefault();return}}else if(l&&(l=l.split(`,`).some(function(r){if(r=xi(c,r.trim(),n,!1),r)return qi({sortable:t,rootEl:r,name:`filter`,targetEl:s,fromEl:n,toEl:n}),Na(`filter`,t,{evt:e}),!0}),l)){i&&e.cancelable&&e.preventDefault();return}r.handle&&!xi(c,r.handle,n,!1)||this._prepareDragStart(e,o,s)}}},_prepareDragStart:function(e,t,n){var r=this,i=r.el,a=r.options,o=i.ownerDocument,s;if(n&&!Pa&&n.parentNode===i){var c=Di(n);if(La=i,Pa=n,Fa=Pa.parentNode,Ra=Pa.nextSibling,za=n,Ka=a.group,Ji.dragged=Pa,Za={target:Pa,clientX:(t||e).clientX,clientY:(t||e).clientY},to=Za.clientX-c.left,no=Za.clientY-c.top,this._lastX=(t||e).clientX,this._lastY=(t||e).clientY,Pa.style[`will-change`]=`all`,s=function(){if(Na(`delayEnded`,r,{evt:e}),Ji.eventCanceled){r._onDrop();return}r._disableDelayedDragEvents(),!xa&&r.nativeDraggable&&(Pa.draggable=!0),r._triggerDragStart(e,t),qi({sortable:r,name:`choose`,originalEvent:e}),Si(Pa,a.chosenClass,!0)},a.ignore.split(`,`).forEach(function(e){Ti(Pa,e.trim(),Zi)}),_i(o,`dragover`,To),_i(o,`mousemove`,To),_i(o,`touchmove`,To),_i(o,`mouseup`,r._onDrop),_i(o,`touchend`,r._onDrop),_i(o,`touchcancel`,r._onDrop),xa&&this.nativeDraggable&&(this.options.touchStartThreshold=4,Pa.draggable=!0),Na(`delayStart`,this,{evt:e}),a.delay&&(!a.delayOnTouchOnly||t)&&(!this.nativeDraggable||!(ba||ya))){if(Ji.eventCanceled){this._onDrop();return}_i(o,`mouseup`,r._disableDelayedDrag),_i(o,`touchend`,r._disableDelayedDrag),_i(o,`touchcancel`,r._disableDelayedDrag),_i(o,`mousemove`,r._delayedDragTouchMoveHandler),_i(o,`touchmove`,r._delayedDragTouchMoveHandler),a.supportPointer&&_i(o,`pointermove`,r._delayedDragTouchMoveHandler),r._dragStartTimer=setTimeout(s,a.delay)}else s()}},_delayedDragTouchMoveHandler:function(e){var t=e.touches?e.touches[0]:e;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){Pa&&Zi(Pa),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var e=this.el.ownerDocument;vi(e,`mouseup`,this._disableDelayedDrag),vi(e,`touchend`,this._disableDelayedDrag),vi(e,`touchcancel`,this._disableDelayedDrag),vi(e,`mousemove`,this._delayedDragTouchMoveHandler),vi(e,`touchmove`,this._delayedDragTouchMoveHandler),vi(e,`pointermove`,this._delayedDragTouchMoveHandler)},_triggerDragStart:function(e,t){t||=e.pointerType==`touch`&&e,!this.nativeDraggable||t?this.options.supportPointer?_i(document,`pointermove`,this._onTouchMove):t?_i(document,`touchmove`,this._onTouchMove):_i(document,`mousemove`,this._onTouchMove):(_i(Pa,`dragend`,this),_i(La,`dragstart`,this._onDragStart));try{document.selection?aa(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch{}},_dragStarted:function(e,t){if(Ja=!1,La&&Pa){Na(`dragStarted`,this,{evt:t}),this.nativeDraggable&&_i(document,`dragover`,Eo);var n=this.options;!e&&Si(Pa,n.dragClass,!1),Si(Pa,n.ghostClass,!0),Ji.active=this,e&&this._appendGhost(),qi({sortable:this,name:`start`,originalEvent:t})}else this._nulling()},_emulateDragOver:function(){if(Qa){this._lastX=Qa.clientX,this._lastY=Qa.clientY,Co();for(var e=document.elementFromPoint(Qa.clientX,Qa.clientY),t=e;e&&e.shadowRoot&&(e=e.shadowRoot.elementFromPoint(Qa.clientX,Qa.clientY),e!==t);)t=e;if(Pa.parentNode[Oa]._isOutsideThisEl(e),t)do{if(t[Oa]){var n=void 0;if(n=t[Oa]._onDragOver({clientX:Qa.clientX,clientY:Qa.clientY,target:e,rootEl:t}),n&&!this.options.dragoverBubble)break}e=t}while(t=t.parentNode);wo()}},_onTouchMove:function(e){if(Za){var t=this.options,n=t.fallbackTolerance,r=t.fallbackOffset,i=e.touches?e.touches[0]:e,a=Ia&&wi(Ia,!0),o=Ia&&a&&a.a,s=Ia&&a&&a.d,c=ho&&lo&&Mi(lo),l=(i.clientX-Za.clientX+r.x)/(o||1)+(c?c[0]-uo[0]:0)/(o||1),u=(i.clientY-Za.clientY+r.y)/(s||1)+(c?c[1]-uo[1]:0)/(s||1);if(!Ji.active&&!Ja){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))=0&&(qi({sortable:this,name:`update`,toEl:Fa,originalEvent:e}),qi({sortable:this,name:`sort`,toEl:Fa,originalEvent:e})):(Ua>=0&&(qi({rootEl:Fa,name:`add`,toEl:Fa,fromEl:La,originalEvent:e}),qi({sortable:this,name:`remove`,toEl:Fa,originalEvent:e}),qi({rootEl:Fa,name:`sort`,toEl:Fa,fromEl:La,originalEvent:e}),qi({sortable:this,name:`sort`,toEl:Fa,originalEvent:e})),qa&&qa.save()),Ji.active&&((Ua==null||Ua===-1)&&(Ua=Ha,Ga=Wa),qi({sortable:this,name:`end`,toEl:Fa,originalEvent:e}),this.save()))),this._nulling()},_nulling:function(){Na(`nulling`,this),La=Pa=Fa=Ia=Ra=Ba=za=Va=Za=Qa=ro=Ua=Ga=Ha=Wa=io=ao=qa=Ka=Ji.dragged=Ji.ghost=Ji.clone=Ji.active=null,po.forEach(function(e){e.checked=!0}),po.length=$a=eo=0},handleEvent:function(e){switch(e.type){case`drop`:case`dragend`:this._onDrop(e);break;case`dragenter`:case`dragover`:Pa&&(this._onDragOver(e),Yi(e));break;case`selectstart`:e.preventDefault();break}},toArray:function(){for(var e=[],t,n=this.el.children,r=0,i=n.length,a=this.options;r{(function(r,i){typeof t==`object`&&typeof n==`object`?n.exports=i(he(),(Jo(),e(ni))):typeof define==`function`&&define.amd?define([,`sortablejs`],i):typeof t==`object`?t.vuedraggable=i(he(),(Jo(),e(ni))):r.vuedraggable=i(r.Vue,r.Sortable)})(typeof self<`u`?self:t,function(e,t){return(function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){typeof Symbol<`u`&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:`Module`}),Object.defineProperty(e,`__esModule`,{value:!0})},n.t=function(e,t){if(t&1&&(e=n(e)),t&8||t&4&&typeof e==`object`&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,`default`,{enumerable:!0,value:e}),t&2&&typeof e!=`string`)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,`a`,t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=``,n(n.s=`fb15`)})({"00ee":(function(e,t,n){var r=n(`b622`)(`toStringTag`),i={};i[r]=`z`,e.exports=String(i)===`[object z]`}),"0366":(function(e,t,n){var r=n(`1c0b`);e.exports=function(e,t,n){if(r(e),t===void 0)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,i){return e.call(t,n,r,i)}}return function(){return e.apply(t,arguments)}}}),"057f":(function(e,t,n){var r=n(`fc6a`),i=n(`241c`).f,a={}.toString,o=typeof window==`object`&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],s=function(e){try{return i(e)}catch{return o.slice()}};e.exports.f=function(e){return o&&a.call(e)==`[object Window]`?s(e):i(r(e))}}),"06cf":(function(e,t,n){var r=n(`83ab`),i=n(`d1e7`),a=n(`5c6c`),o=n(`fc6a`),s=n(`c04e`),c=n(`5135`),l=n(`0cfb`),u=Object.getOwnPropertyDescriptor;t.f=r?u:function(e,t){if(e=o(e),t=s(t,!0),l)try{return u(e,t)}catch{}if(c(e,t))return a(!i.f.call(e,t),e[t])}}),"0cfb":(function(e,t,n){var r=n(`83ab`),i=n(`d039`),a=n(`cc12`);e.exports=!r&&!i(function(){return Object.defineProperty(a(`div`),`a`,{get:function(){return 7}}).a!=7})}),"13d5":(function(e,t,n){var r=n(`23e7`),i=n(`d58f`).left,a=n(`a640`),o=n(`ae40`),s=a(`reduce`),c=o(`reduce`,{1:0});r({target:`Array`,proto:!0,forced:!s||!c},{reduce:function(e){return i(this,e,arguments.length,arguments.length>1?arguments[1]:void 0)}})}),"14c3":(function(e,t,n){var r=n(`c6b6`),i=n(`9263`);e.exports=function(e,t){var n=e.exec;if(typeof n==`function`){var a=n.call(e,t);if(typeof a!=`object`)throw TypeError(`RegExp exec method returned something other than an Object or null`);return a}if(r(e)!==`RegExp`)throw TypeError(`RegExp#exec called on incompatible receiver`);return i.call(e,t)}}),"159b":(function(e,t,n){var r=n(`da84`),i=n(`fdbc`),a=n(`17c2`),o=n(`9112`);for(var s in i){var c=r[s],l=c&&c.prototype;if(l&&l.forEach!==a)try{o(l,`forEach`,a)}catch{l.forEach=a}}}),"17c2":(function(e,t,n){var r=n(`b727`).forEach,i=n(`a640`),a=n(`ae40`),o=i(`forEach`),s=a(`forEach`);e.exports=!o||!s?function(e){return r(this,e,arguments.length>1?arguments[1]:void 0)}:[].forEach}),"1be4":(function(e,t,n){e.exports=n(`d066`)(`document`,`documentElement`)}),"1c0b":(function(e,t){e.exports=function(e){if(typeof e!=`function`)throw TypeError(String(e)+` is not a function`);return e}}),"1c7e":(function(e,t,n){var r=n(`b622`)(`iterator`),i=!1;try{var a=0,o={next:function(){return{done:!!a++}},return:function(){i=!0}};o[r]=function(){return this},Array.from(o,function(){throw 2})}catch{}e.exports=function(e,t){if(!t&&!i)return!1;var n=!1;try{var a={};a[r]=function(){return{next:function(){return{done:n=!0}}}},e(a)}catch{}return n}}),"1d80":(function(e,t){e.exports=function(e){if(e==null)throw TypeError(`Can't call method on `+e);return e}}),"1dde":(function(e,t,n){var r=n(`d039`),i=n(`b622`),a=n(`2d00`),o=i(`species`);e.exports=function(e){return a>=51||!r(function(){var t=[],n=t.constructor={};return n[o]=function(){return{foo:1}},t[e](Boolean).foo!==1})}}),"23cb":(function(e,t,n){var r=n(`a691`),i=Math.max,a=Math.min;e.exports=function(e,t){var n=r(e);return n<0?i(n+t,0):a(n,t)}}),"23e7":(function(e,t,n){var r=n(`da84`),i=n(`06cf`).f,a=n(`9112`),o=n(`6eeb`),s=n(`ce4e`),c=n(`e893`),l=n(`94ca`);e.exports=function(e,t){var n=e.target,u=e.global,d=e.stat,f,p=u?r:d?r[n]||s(n,{}):(r[n]||{}).prototype,m,h,g,_;if(p)for(m in t){if(g=t[m],e.noTargetGet?(_=i(p,m),h=_&&_.value):h=p[m],f=l(u?m:n+(d?`.`:`#`)+m,e.forced),!f&&h!==void 0){if(typeof g==typeof h)continue;c(g,h)}(e.sham||h&&h.sham)&&a(g,`sham`,!0),o(p,m,g,e)}}}),"241c":(function(e,t,n){var r=n(`ca84`),i=n(`7839`).concat(`length`,`prototype`);t.f=Object.getOwnPropertyNames||function(e){return r(e,i)}}),"25f0":(function(e,t,n){var r=n(`6eeb`),i=n(`825a`),a=n(`d039`),o=n(`ad6d`),s=`toString`,c=RegExp.prototype,l=c[s],u=a(function(){return l.call({source:`a`,flags:`b`})!=`/a/b`}),d=l.name!=s;(u||d)&&r(RegExp.prototype,s,function(){var e=i(this),t=String(e.source),n=e.flags,r=String(n===void 0&&e instanceof RegExp&&!(`flags`in c)?o.call(e):n);return`/`+t+`/`+r},{unsafe:!0})}),"2ca0":(function(e,t,n){var r=n(`23e7`),i=n(`06cf`).f,a=n(`50c4`),o=n(`5a34`),s=n(`1d80`),c=n(`ab13`),l=n(`c430`),u=``.startsWith,d=Math.min,f=c(`startsWith`);r({target:`String`,proto:!0,forced:!(!l&&!f&&function(){var e=i(String.prototype,`startsWith`);return e&&!e.writable}())&&!f},{startsWith:function(e){var t=String(s(this));o(e);var n=a(d(arguments.length>1?arguments[1]:void 0,t.length)),r=String(e);return u?u.call(t,r,n):t.slice(n,n+r.length)===r}})}),"2d00":(function(e,t,n){var r=n(`da84`),i=n(`342f`),a=r.process,o=a&&a.versions,s=o&&o.v8,c,l;s?(c=s.split(`.`),l=c[0]+c[1]):i&&(c=i.match(/Edge\/(\d+)/),(!c||c[1]>=74)&&(c=i.match(/Chrome\/(\d+)/),c&&(l=c[1]))),e.exports=l&&+l}),"342f":(function(e,t,n){e.exports=n(`d066`)(`navigator`,`userAgent`)||``}),"35a1":(function(e,t,n){var r=n(`f5df`),i=n(`3f8c`),a=n(`b622`)(`iterator`);e.exports=function(e){if(e!=null)return e[a]||e[`@@iterator`]||i[r(e)]}}),"37e8":(function(e,t,n){var r=n(`83ab`),i=n(`9bf2`),a=n(`825a`),o=n(`df75`);e.exports=r?Object.defineProperties:function(e,t){a(e);for(var n=o(t),r=n.length,s=0,c;r>s;)i.f(e,c=n[s++],t[c]);return e}}),"3bbe":(function(e,t,n){var r=n(`861d`);e.exports=function(e){if(!r(e)&&e!==null)throw TypeError(`Can't set `+String(e)+` as a prototype`);return e}}),"3ca3":(function(e,t,n){var r=n(`6547`).charAt,i=n(`69f3`),a=n(`7dd0`),o=`String Iterator`,s=i.set,c=i.getterFor(o);a(String,`String`,function(e){s(this,{type:o,string:String(e),index:0})},function(){var e=c(this),t=e.string,n=e.index,i;return n>=t.length?{value:void 0,done:!0}:(i=r(t,n),e.index+=i.length,{value:i,done:!1})})}),"3f8c":(function(e,t){e.exports={}}),4160:(function(e,t,n){var r=n(`23e7`),i=n(`17c2`);r({target:`Array`,proto:!0,forced:[].forEach!=i},{forEach:i})}),"428f":(function(e,t,n){e.exports=n(`da84`)}),"44ad":(function(e,t,n){var r=n(`d039`),i=n(`c6b6`),a=``.split;e.exports=r(function(){return!Object(`z`).propertyIsEnumerable(0)})?function(e){return i(e)==`String`?a.call(e,``):Object(e)}:Object}),"44d2":(function(e,t,n){var r=n(`b622`),i=n(`7c73`),a=n(`9bf2`),o=r(`unscopables`),s=Array.prototype;s[o]??a.f(s,o,{configurable:!0,value:i(null)}),e.exports=function(e){s[o][e]=!0}}),"44e7":(function(e,t,n){var r=n(`861d`),i=n(`c6b6`),a=n(`b622`)(`match`);e.exports=function(e){var t;return r(e)&&((t=e[a])===void 0?i(e)==`RegExp`:!!t)}}),4930:(function(e,t,n){var r=n(`d039`);e.exports=!!Object.getOwnPropertySymbols&&!r(function(){return!String(Symbol())})}),"4d64":(function(e,t,n){var r=n(`fc6a`),i=n(`50c4`),a=n(`23cb`),o=function(e){return function(t,n,o){var s=r(t),c=i(s.length),l=a(o,c),u;if(e&&n!=n){for(;c>l;)if(u=s[l++],u!=u)return!0}else for(;c>l;l++)if((e||l in s)&&s[l]===n)return e||l||0;return!e&&-1}};e.exports={includes:o(!0),indexOf:o(!1)}}),"4de4":(function(e,t,n){var r=n(`23e7`),i=n(`b727`).filter,a=n(`1dde`),o=n(`ae40`),s=a(`filter`),c=o(`filter`);r({target:`Array`,proto:!0,forced:!s||!c},{filter:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}})}),"4df4":(function(e,t,n){var r=n(`0366`),i=n(`7b0b`),a=n(`9bdd`),o=n(`e95a`),s=n(`50c4`),c=n(`8418`),l=n(`35a1`);e.exports=function(e){var t=i(e),n=typeof this==`function`?this:Array,u=arguments.length,d=u>1?arguments[1]:void 0,f=d!==void 0,p=l(t),m=0,h,g,_,v,y,b;if(f&&(d=r(d,u>2?arguments[2]:void 0,2)),p!=null&&!(n==Array&&o(p)))for(v=p.call(t),y=v.next,g=new n;!(_=y.call(v)).done;m++)b=f?a(v,d,[_.value,m],!0):_.value,c(g,m,b);else for(h=s(t.length),g=new n(h);h>m;m++)b=f?d(t[m],m):t[m],c(g,m,b);return g.length=m,g}}),"4fad":(function(e,t,n){var r=n(`23e7`),i=n(`6f53`).entries;r({target:`Object`,stat:!0},{entries:function(e){return i(e)}})}),"50c4":(function(e,t,n){var r=n(`a691`),i=Math.min;e.exports=function(e){return e>0?i(r(e),9007199254740991):0}}),5135:(function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}}),5319:(function(e,t,n){var r=n(`d784`),i=n(`825a`),a=n(`7b0b`),o=n(`50c4`),s=n(`a691`),c=n(`1d80`),l=n(`8aa5`),u=n(`14c3`),d=Math.max,f=Math.min,p=Math.floor,m=/\$([$&'`]|\d\d?|<[^>]*>)/g,h=/\$([$&'`]|\d\d?)/g,g=function(e){return e===void 0?e:String(e)};r(`replace`,2,function(e,t,n,r){var _=r.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,v=r.REPLACE_KEEPS_$0,y=_?`$`:`$0`;return[function(n,r){var i=c(this),a=n?.[e];return a===void 0?t.call(String(i),n,r):a.call(n,i,r)},function(e,r){if(!_&&v||typeof r==`string`&&r.indexOf(y)===-1){var a=n(t,e,this,r);if(a.done)return a.value}var c=i(e),p=String(this),m=typeof r==`function`;m||(r=String(r));var h=c.global;if(h){var x=c.unicode;c.lastIndex=0}for(var S=[];;){var C=u(c,p);if(C===null||(S.push(C),!h))break;String(C[0])===``&&(c.lastIndex=l(p,o(c.lastIndex),x))}for(var w=``,T=0,E=0;E=T&&(w+=p.slice(T,O)+N,T=O+D.length)}return w+p.slice(T)}];function b(e,n,r,i,o,s){var c=r+e.length,l=i.length,u=h;return o!==void 0&&(o=a(o),u=m),t.call(s,u,function(t,a){var s;switch(a.charAt(0)){case`$`:return`$`;case`&`:return e;case"`":return n.slice(0,r);case`'`:return n.slice(c);case`<`:s=o[a.slice(1,-1)];break;default:var u=+a;if(u===0)return t;if(u>l){var d=p(u/10);return d===0?t:d<=l?i[d-1]===void 0?a.charAt(1):i[d-1]+a.charAt(1):t}s=i[u-1]}return s===void 0?``:s})}})}),5692:(function(e,t,n){var r=n(`c430`),i=n(`c6cd`);(e.exports=function(e,t){return i[e]||(i[e]=t===void 0?{}:t)})(`versions`,[]).push({version:`3.6.5`,mode:r?`pure`:`global`,copyright:`© 2020 Denis Pushkarev (zloirock.ru)`})}),"56ef":(function(e,t,n){var r=n(`d066`),i=n(`241c`),a=n(`7418`),o=n(`825a`);e.exports=r(`Reflect`,`ownKeys`)||function(e){var t=i.f(o(e)),n=a.f;return n?t.concat(n(e)):t}}),"5a34":(function(e,t,n){var r=n(`44e7`);e.exports=function(e){if(r(e))throw TypeError(`The method doesn't accept regular expressions`);return e}}),"5c6c":(function(e,t){e.exports=function(e,t){return{enumerable:!(e&1),configurable:!(e&2),writable:!(e&4),value:t}}}),"5db7":(function(e,t,n){var r=n(`23e7`),i=n(`a2bf`),a=n(`7b0b`),o=n(`50c4`),s=n(`1c0b`),c=n(`65f0`);r({target:`Array`,proto:!0},{flatMap:function(e){var t=a(this),n=o(t.length),r;return s(e),r=c(t,0),r.length=i(r,t,t,n,0,1,e,arguments.length>1?arguments[1]:void 0),r}})}),6547:(function(e,t,n){var r=n(`a691`),i=n(`1d80`),a=function(e){return function(t,n){var a=String(i(t)),o=r(n),s=a.length,c,l;return o<0||o>=s?e?``:void 0:(c=a.charCodeAt(o),c<55296||c>56319||o+1===s||(l=a.charCodeAt(o+1))<56320||l>57343?e?a.charAt(o):c:e?a.slice(o,o+2):(c-55296<<10)+(l-56320)+65536)}};e.exports={codeAt:a(!1),charAt:a(!0)}}),"65f0":(function(e,t,n){var r=n(`861d`),i=n(`e8b5`),a=n(`b622`)(`species`);e.exports=function(e,t){var n;return i(e)&&(n=e.constructor,typeof n==`function`&&(n===Array||i(n.prototype))?n=void 0:r(n)&&(n=n[a],n===null&&(n=void 0))),new(n===void 0?Array:n)(t===0?0:t)}}),"69f3":(function(e,t,n){var r=n(`7f9a`),i=n(`da84`),a=n(`861d`),o=n(`9112`),s=n(`5135`),c=n(`f772`),l=n(`d012`),u=i.WeakMap,d,f,p,m=function(e){return p(e)?f(e):d(e,{})},h=function(e){return function(t){var n;if(!a(t)||(n=f(t)).type!==e)throw TypeError(`Incompatible receiver, `+e+` required`);return n}};if(r){var g=new u,_=g.get,v=g.has,y=g.set;d=function(e,t){return y.call(g,e,t),t},f=function(e){return _.call(g,e)||{}},p=function(e){return v.call(g,e)}}else{var b=c(`state`);l[b]=!0,d=function(e,t){return o(e,b,t),t},f=function(e){return s(e,b)?e[b]:{}},p=function(e){return s(e,b)}}e.exports={set:d,get:f,has:p,enforce:m,getterFor:h}}),"6eeb":(function(e,t,n){var r=n(`da84`),i=n(`9112`),a=n(`5135`),o=n(`ce4e`),s=n(`8925`),c=n(`69f3`),l=c.get,u=c.enforce,d=String(String).split(`String`);(e.exports=function(e,t,n,s){var c=s?!!s.unsafe:!1,l=s?!!s.enumerable:!1,f=s?!!s.noTargetGet:!1;if(typeof n==`function`&&(typeof t==`string`&&!a(n,`name`)&&i(n,`name`,t),u(n).source=d.join(typeof t==`string`?t:``)),e===r){l?e[t]=n:o(t,n);return}else c?!f&&e[t]&&(l=!0):delete e[t];l?e[t]=n:i(e,t,n)})(Function.prototype,`toString`,function(){return typeof this==`function`&&l(this).source||s(this)})}),"6f53":(function(e,t,n){var r=n(`83ab`),i=n(`df75`),a=n(`fc6a`),o=n(`d1e7`).f,s=function(e){return function(t){for(var n=a(t),s=i(n),c=s.length,l=0,u=[],d;c>l;)d=s[l++],(!r||o.call(n,d))&&u.push(e?[d,n[d]]:n[d]);return u}};e.exports={entries:s(!0),values:s(!1)}}),"73d9":(function(e,t,n){n(`44d2`)(`flatMap`)}),7418:(function(e,t){t.f=Object.getOwnPropertySymbols}),"746f":(function(e,t,n){var r=n(`428f`),i=n(`5135`),a=n(`e538`),o=n(`9bf2`).f;e.exports=function(e){var t=r.Symbol||={};i(t,e)||o(t,e,{value:a.f(e)})}}),7839:(function(e,t){e.exports=[`constructor`,`hasOwnProperty`,`isPrototypeOf`,`propertyIsEnumerable`,`toLocaleString`,`toString`,`valueOf`]}),"7b0b":(function(e,t,n){var r=n(`1d80`);e.exports=function(e){return Object(r(e))}}),"7c73":(function(e,t,n){var r=n(`825a`),i=n(`37e8`),a=n(`7839`),o=n(`d012`),s=n(`1be4`),c=n(`cc12`),l=n(`f772`),u=`>`,d=`<`,f=`prototype`,p=`script`,m=l(`IE_PROTO`),h=function(){},g=function(e){return d+p+u+e+d+`/`+p+u},_=function(e){e.write(g(``)),e.close();var t=e.parentWindow.Object;return e=null,t},v=function(){var e=c(`iframe`),t=`java`+p+`:`,n;return e.style.display=`none`,s.appendChild(e),e.src=String(t),n=e.contentWindow.document,n.open(),n.write(g(`document.F=Object`)),n.close(),n.F},y,b=function(){try{y=document.domain&&new ActiveXObject(`htmlfile`)}catch{}b=y?_(y):v();for(var e=a.length;e--;)delete b[f][a[e]];return b()};o[m]=!0,e.exports=Object.create||function(e,t){var n;return e===null?n=b():(h[f]=r(e),n=new h,h[f]=null,n[m]=e),t===void 0?n:i(n,t)}}),"7dd0":(function(e,t,n){var r=n(`23e7`),i=n(`9ed3`),a=n(`e163`),o=n(`d2bb`),s=n(`d44e`),c=n(`9112`),l=n(`6eeb`),u=n(`b622`),d=n(`c430`),f=n(`3f8c`),p=n(`ae93`),m=p.IteratorPrototype,h=p.BUGGY_SAFARI_ITERATORS,g=u(`iterator`),_=`keys`,v=`values`,y=`entries`,b=function(){return this};e.exports=function(e,t,n,u,p,x,S){i(n,t,u);var C=function(e){if(e===p&&O)return O;if(!h&&e in E)return E[e];switch(e){case _:return function(){return new n(this,e)};case v:return function(){return new n(this,e)};case y:return function(){return new n(this,e)}}return function(){return new n(this)}},w=t+` Iterator`,T=!1,E=e.prototype,D=E[g]||E[`@@iterator`]||p&&E[p],O=!h&&D||C(p),k=t==`Array`&&E.entries||D,A,j,M;if(k&&(A=a(k.call(new e)),m!==Object.prototype&&A.next&&(!d&&a(A)!==m&&(o?o(A,m):typeof A[g]!=`function`&&c(A,g,b)),s(A,w,!0,!0),d&&(f[w]=b))),p==v&&D&&D.name!==v&&(T=!0,O=function(){return D.call(this)}),(!d||S)&&E[g]!==O&&c(E,g,O),f[t]=O,p)if(j={values:C(v),keys:x?O:C(_),entries:C(y)},S)for(M in j)(h||T||!(M in E))&&l(E,M,j[M]);else r({target:t,proto:!0,forced:h||T},j);return j}}),"7f9a":(function(e,t,n){var r=n(`da84`),i=n(`8925`),a=r.WeakMap;e.exports=typeof a==`function`&&/native code/.test(i(a))}),"825a":(function(e,t,n){var r=n(`861d`);e.exports=function(e){if(!r(e))throw TypeError(String(e)+` is not an object`);return e}}),"83ab":(function(e,t,n){e.exports=!n(`d039`)(function(){return Object.defineProperty({},1,{get:function(){return 7}})[1]!=7})}),8418:(function(e,t,n){var r=n(`c04e`),i=n(`9bf2`),a=n(`5c6c`);e.exports=function(e,t,n){var o=r(t);o in e?i.f(e,o,a(0,n)):e[o]=n}}),"861d":(function(e,t){e.exports=function(e){return typeof e==`object`?e!==null:typeof e==`function`}}),8875:(function(e,t,n){var r,i,a;(function(n,o){i=[],r=o,a=typeof r==`function`?r.apply(t,i):r,a!==void 0&&(e.exports=a)})(typeof self<`u`?self:this,function(){function e(){var t=Object.getOwnPropertyDescriptor(document,`currentScript`);if(!t&&`currentScript`in document&&document.currentScript||t&&t.get!==e&&document.currentScript)return document.currentScript;try{throw Error()}catch(e){var n=/.*at [^(]*\((.*):(.+):(.+)\)$/gi.exec(e.stack)||/@([^@]*):(\d+):(\d+)\s*$/gi.exec(e.stack),r=n&&n[1]||!1,i=n&&n[2]||!1,a=document.location.href.replace(document.location.hash,``),o,s,c,l=document.getElementsByTagName(`script`);r===a&&(o=document.documentElement.outerHTML,s=RegExp(`(?:[^\\n]+?\\n){0,`+(i-2)+`}[^<]*
+ 联众咨询
diff --git a/package-lock.json b/package-lock.json
index ccd4869..bb39207 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,18 +21,20 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"decimal.js": "^10.6.0",
+ "docxtemplater": "^3.68.5",
"exceljs": "^4.4.0",
+ "file-saver": "^2.0.5",
"localforage": "^1.10.0",
"lucide-vue-next": "^0.563.0",
"motion-v": "^2.0.0",
"pinia": "^3.0.4",
"pinia-plugin-persistedstate": "^4.7.1",
+ "pizzip": "^3.2.0",
"reka-ui": "^2.8.0",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.18",
"vue": "^3.5.25",
"vue-i18n": "^11.3.0",
- "vue-router": "^4.6.4",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
@@ -657,6 +659,15 @@
"vue": "^3.5.0"
}
},
+ "node_modules/@xmldom/xmldom": {
+ "version": "0.9.10",
+ "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz",
+ "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.6"
+ }
+ },
"node_modules/ag-charts-community": {
"version": "13.1.0",
"license": "MIT",
@@ -1013,6 +1024,18 @@
"node": ">=8"
}
},
+ "node_modules/docxtemplater": {
+ "version": "3.68.5",
+ "resolved": "https://registry.npmjs.org/docxtemplater/-/docxtemplater-3.68.5.tgz",
+ "integrity": "sha512-2xcHvTXjMA0jdX6PRh1BUTLrcRQ86Re/QJKWCUCX/vv5RKzntjNNkpR/O4AUoJY1TdoqxA+d04L4xgoAUNf/kw==",
+ "license": "MIT",
+ "dependencies": {
+ "@xmldom/xmldom": "^0.9.8"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/duplexer2": {
"version": "0.1.4",
"license": "BSD-3-Clause",
@@ -1117,6 +1140,12 @@
}
}
},
+ "node_modules/file-saver": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
+ "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==",
+ "license": "MIT"
+ },
"node_modules/framer-motion": {
"version": "12.34.3",
"license": "MIT",
@@ -1638,6 +1667,21 @@
}
}
},
+ "node_modules/pizzip": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/pizzip/-/pizzip-3.2.0.tgz",
+ "integrity": "sha512-X4NPNICxCfIK8VYhF6wbksn81vTiziyLbvKuORVAmolvnUzl1A1xmz9DAWKxPRq9lZg84pJOOAMq3OE61bD8IQ==",
+ "license": "(MIT OR GPL-3.0)",
+ "dependencies": {
+ "pako": "^2.1.0"
+ }
+ },
+ "node_modules/pizzip/node_modules/pako": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
+ "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
+ "license": "(MIT AND Zlib)"
+ },
"node_modules/postcss": {
"version": "8.5.6",
"funding": [
@@ -2128,27 +2172,6 @@
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
"license": "MIT"
},
- "node_modules/vue-router": {
- "version": "4.6.4",
- "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz",
- "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
- "license": "MIT",
- "dependencies": {
- "@vue/devtools-api": "^6.6.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/posva"
- },
- "peerDependencies": {
- "vue": "^3.5.0"
- }
- },
- "node_modules/vue-router/node_modules/@vue/devtools-api": {
- "version": "6.6.4",
- "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
- "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
- "license": "MIT"
- },
"node_modules/vue-tsc": {
"version": "3.2.5",
"dev": true,
diff --git a/package.json b/package.json
index 416e4f1..58353c5 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,13 @@
{
- "name": "ZWJJ2026",
+ "name": "my-vue-app",
"private": true,
- "version": "1.0",
+ "version": "0.0.0",
"type": "module",
"scripts": {
"dev": "bunx --bun vite",
- "build": "bunx vue-tsc -b && bunx --bun vite build",
+ "build": " bunx --bun vite build",
"preview": "bunx --bun vite preview",
- "type-check": "bunx vue-tsc --noEmit",
- "dockerPush": "bun run build && docker build -f Dockerfile.dist -t wintsa/zwzjjstool2026:latest . && docker push wintsa/zwzjjstool2026:latest"
+ "type-check": "bunx vue-tsc --noEmit"
},
"dependencies": {
"@ag-grid-community/locale": "^35.1.0",
@@ -24,18 +23,20 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"decimal.js": "^10.6.0",
+ "docxtemplater": "^3.68.5",
"exceljs": "^4.4.0",
+ "file-saver": "^2.0.5",
"localforage": "^1.10.0",
"lucide-vue-next": "^0.563.0",
"motion-v": "^2.0.0",
"pinia": "^3.0.4",
"pinia-plugin-persistedstate": "^4.7.1",
+ "pizzip": "^3.2.0",
"reka-ui": "^2.8.0",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.18",
"vue": "^3.5.25",
"vue-i18n": "^11.3.0",
- "vue-router": "^4.6.4",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
diff --git a/public/background.png b/public/background.png
new file mode 100644
index 0000000..849942d
Binary files /dev/null and b/public/background.png differ
diff --git a/public/bg-home.png b/public/bg-home.png
new file mode 100644
index 0000000..7edcc2a
--- /dev/null
+++ b/public/bg-home.png
@@ -0,0 +1 @@
+iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0CAYAAADl8HLGAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4SU
\ No newline at end of file
diff --git a/public/related-files.png b/public/related-files.png
deleted file mode 100644
index e4d5677..0000000
Binary files a/public/related-files.png and /dev/null differ
diff --git a/public/template-doc.docx b/public/template-doc.docx
new file mode 100644
index 0000000..119fe90
Binary files /dev/null and b/public/template-doc.docx differ
diff --git a/public/template-excel.xlsx b/public/template-excel.xlsx
new file mode 100644
index 0000000..51eb9cf
Binary files /dev/null and b/public/template-excel.xlsx differ
diff --git a/public/组 4@2x.png b/public/组 4@2x.png
new file mode 100644
index 0000000..78fcb4d
Binary files /dev/null and b/public/组 4@2x.png differ
diff --git a/public/组 5@2x.png b/public/组 5@2x.png
new file mode 100644
index 0000000..e09f59f
Binary files /dev/null and b/public/组 5@2x.png differ
diff --git a/public/组 6@2x.png b/public/组 6@2x.png
new file mode 100644
index 0000000..65cda32
Binary files /dev/null and b/public/组 6@2x.png differ
diff --git a/src/App.vue b/src/App.vue
index 7c2aa3f..b1f618d 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,3 +1,323 @@
+
+
-
+
+
+
+
{{ t('app.projectConflict.title') }}
+
+ {{ t('app.projectConflict.desc', { name: currentProjectName }) }}
+
+
+ {{ t('app.projectConflict.countdown', { seconds: closeCountdown }) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/app/components/WorkspaceShell.vue b/src/features/app/components/WorkspaceShell.vue
deleted file mode 100644
index 1da72e2..0000000
--- a/src/features/app/components/WorkspaceShell.vue
+++ /dev/null
@@ -1,318 +0,0 @@
-
-
-
-
-
-
-
{{ t('app.projectConflict.title') }}
-
- {{ t('app.projectConflict.desc', { name: currentProjectName }) }}
-
-
- {{ t('app.projectConflict.countdown', { seconds: closeCountdown }) }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/features/disclaimer/components/DisclaimerPage.vue b/src/features/disclaimer/components/DisclaimerPage.vue
deleted file mode 100644
index 88307a2..0000000
--- a/src/features/disclaimer/components/DisclaimerPage.vue
+++ /dev/null
@@ -1,197 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ t('disclaimerPage.eyebrow') }}
-
- {{ t('disclaimerPage.pageTitle') }}
-
-
- {{ t('disclaimerPage.lastUpdatedLabel') }}
- {{ t('disclaimerPage.lastUpdatedValue') }}
-
-
- {{ t('disclaimerPage.leadText') }}
-
-
-
-
-
-
-
-
- {{ section.title }}
-
- {{ paragraph }}
-
-
-
-
- {{ t('disclaimerPage.confirm.title') }}
- {{ t('disclaimerPage.confirm.desc1') }}
- {{ t('disclaimerPage.confirm.desc2') }}
-
-
-
-
-
- {{ t('disclaimerPage.confirm.hint') }}
-
-
-
-
-
-
-
-
diff --git a/src/features/ht/components/HtBaseInfo.vue b/src/features/ht/components/HtBaseInfo.vue
index 8455b68..ba7ed48 100644
--- a/src/features/ht/components/HtBaseInfo.vue
+++ b/src/features/ht/components/HtBaseInfo.vue
@@ -21,15 +21,23 @@ const storageKey = () => `ht-base-info-${props.contractId}`
const quality = ref(DEFAULT_QUALITY)
const duration = ref('')
const lastSavedSnapshot = ref('')
-
-const saveForm = (force = false) => {
+import { useDataStore } from '@/pinia/zx'
+const saveForm = async(force = false) => {
const payload: HtBaseInfoState = {
quality: quality.value,
duration: duration.value
}
const snapshot = JSON.stringify(payload)
if (!force && snapshot === lastSavedSnapshot.value) return
+ // ✅ 使用 upsertBatch:存在则更新,不存在则新增
zxFwPricingStore.setKeyState(storageKey(), payload)
+ const data=[]
+ //@ts-ignore
+ payload.id=props.contractId
+ data.push(payload)
+ const rows = data.map(row => ({ ...row, type: `${props.contractId}-Htbaseinfo` }))
+ await useDataStore().upsertBatch(rows)
+
lastSavedSnapshot.value = snapshot
}
@@ -68,7 +76,7 @@ onBeforeUnmount(() => {
{{ t('htBaseInfo.qualityLabel') }}
@@ -77,7 +85,7 @@ onBeforeUnmount(() => {
{{ t('htBaseInfo.durationLabel') }}
diff --git a/src/features/ht/components/HtContractSummary.vue b/src/features/ht/components/HtContractSummary.vue
index f3db7e6..5f8b8bc 100644
--- a/src/features/ht/components/HtContractSummary.vue
+++ b/src/features/ht/components/HtContractSummary.vue
@@ -1,4 +1,4 @@
-
+
+
+
+
+
+
+
+
+ {{ t('htZxFw.title') }}
+
+
+
{{ t('htZxFw.warning') }}
+
+
+
+
+
+
+
+
+
+ {{ t('htZxFw.dialog.resetTitle') }}
+
+ {{ t('htZxFw.dialog.resetDesc', { name: pendingClearServiceName }) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('htZxFw.dialog.deleteTitle') }}
+
+ {{ t('htZxFw.dialog.deleteDesc', { name: pendingDeleteServiceName }) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/ht/components/htCard.vue b/src/features/ht/components/htCard.vue
index 3da05d1..27ddb26 100644
--- a/src/features/ht/components/htCard.vue
+++ b/src/features/ht/components/htCard.vue
@@ -177,15 +177,15 @@ const scheduleRefreshContractBudget = () => {
// 2. 定义分类项的 TS 类型(核心:明确 categories 结构)
interface XmCategoryItem {
key:
- | 'info'
| 'base-info'
- | 'consult-category-factor'
| 'major-factor'
- | 'work-grid'
| 'contract'
- | 'additional-work-fee'
- | 'reserve-fee'
- | 'all';
+ | 'Investment'
+ |'land-scale-method'
+ |'workload-method'
+ |'hourly-method'
+ |'work-content'
+ |'other-service'
label: string;
component: Component; // 标记为 Vue 组件类型
}
@@ -229,6 +229,26 @@ const zxfwView = markRaw(
})
);
+
+const summaryview = markRaw(
+ defineComponent({
+ name: 'SummaryWithProps',
+ setup() {
+ const AsyncSummary = defineAsyncComponent({
+ loader: () => import('@/features/ht/components/Summary.vue'),
+ onError: (err) => {
+ console.error('加载 Summary 组件失败:', err);
+ }
+ });
+ return () => h(AsyncSummary, {
+ contractId: props.contractId,
+ contractName: props.contractName,
+ projectInfoKey: props.projectInfoKey
+ });
+ }
+ })
+);
+
const consultCategoryFactorView = markRaw(
defineComponent({
name: 'HtConsultCategoryFactorWithProps',
@@ -328,17 +348,93 @@ const summaryView = markRaw(
}
})
)
+const createPricingPane = (name: string) =>
+ markRaw(
+ defineComponent({
+ name,
+ setup() {
+ const AsyncPricingView = defineAsyncComponent({
+ loader: () => import(`@/features/pricing/components/${name}.vue`),
+ onError: err => {
+ console.error('load PricingMethodView failed:', err)
+ }
+ })
+ return () => h(AsyncPricingView, {
+ contractId: props.contractId,
+ contractName: props.contractName,
+ serviceId: props.contractId,
+ projectInfoKey: props.projectInfoKey
+ })
+ }
+ })
+ )
+
+const workContentPane = markRaw(
+defineComponent({
+ name: 'WorkContentPane',
+ setup() {
+ const AsyncWorkContentGrid = defineAsyncComponent({
+ loader: () => import('@/features/shared/components/WorkContentGrid.vue'),
+ onError: err => {
+ console.error('load WorkContentGrid failed:', err)
+ }
+ })
+ return () => h(AsyncWorkContentGrid, {
+ title: t('zxFwView.workContentTitle'),
+ storageKey: `work-content-${props.contractId}-${props.contractId}`,
+ contractId: props.contractId,
+ projectInfoKey: props.projectInfoKey,
+ serviceId: props.contractId,
+ dictMode: 'service',
+ "show-no-column": true
+ })
+ }
+})
+)
+
+const investmentScaleView = createPricingPane('InvestmentScalePricingPane')
+const landScaleView = createPricingPane('LandScalePricingPane')
+const workloadView = createPricingPane('WorkloadPricingPane')
+const hourlyView = createPricingPane('HourlyPricingPane')
+const otherService = createPricingPane('OtherService')
// 4. 给分类数组添加严格类型标注
const xmCategories = computed(() => [
{ key: 'base-info', label: t('htCard.categories.baseInfo'), component: htBaseInfoView },
- { key: 'info', label: t('htCard.categories.scaleInfo'), component: htView },
- { key: 'contract', label: t('htCard.categories.services'), component: zxfwView },
- { key: 'consult-category-factor', label: t('htCard.categories.consultFactor'), component: consultCategoryFactorView },
{ key: 'major-factor', label: t('htCard.categories.majorFactor'), component: majorFactorView },
- { key: 'additional-work-fee', label: t('htCard.categories.additionalFee'), component: additionalWorkFeeView },
- { key: 'reserve-fee', label: t('htCard.categories.reserveFee'), component: reserveFeeView },
- { key: 'all', label: t('htCard.categories.summary'), component: summaryView },
+ { key: 'contract', label: t('htCard.categories.services'), component: zxfwView },
+ { key: 'Investment', label: t('zxFwView.categories.investmentScale'), component: investmentScaleView },
+ {
+ key: 'land-scale-method',
+ label: t('zxFwView.categories.landScale'),
+ component: landScaleView
+ },
+ {
+ key: 'workload-method',
+ label: t('zxFwView.categories.workload'),
+ component: workloadView
+ },
+ {
+ key: 'hourly-method',
+ label: t('zxFwView.categories.hourly'),
+ component: hourlyView
+ },
+ {
+ key: 'work-content',
+ label: t('zxFwView.categories.workContent'),
+ component: workContentPane
+ },
+ // // 👇 完美补齐
+ {
+ key: 'other-service',
+ label: t('zxFwView.categories.otherservice'),
+ component: otherService
+ },
+ {
+ key: 'Summary',
+ label: t('htCard.categories.summary'),
+ component: summaryview
+ }
]);
watch(budgetRefreshSignature, (next, prev) => {
diff --git a/src/features/ht/components/htInfo.vue b/src/features/ht/components/htInfo.vue
index cbc963c..e414ed0 100644
--- a/src/features/ht/components/htInfo.vue
+++ b/src/features/ht/components/htInfo.vue
@@ -16,16 +16,10 @@ const XM_DB_KEY = computed(() => {
})
const BASE_INFO_KEY = computed(() => props.projectInfoKey || 'xm-base-info-v1')
const { t } = useI18n()
-const titleText = computed(() => `${t('htInfo.scaleDetailTitle')}:${t('htInfo.scaleDetailHint')}`)
-
+
diff --git a/src/features/ht/components/zxFw.vue b/src/features/ht/components/zxFw.vue
index 40c07b9..3ec8011 100644
--- a/src/features/ht/components/zxFw.vue
+++ b/src/features/ht/components/zxFw.vue
@@ -1,5 +1,18 @@
-
-
@@ -1346,6 +1794,7 @@ onActivated(async () => {
{
:deep(.zxfw-process-option--en) {
width: 100%;
}
+
+
+
diff --git a/src/features/pricing/components/InvestmentScalePricingPane.vue b/src/features/pricing/components/InvestmentScalePricingPane.vue
index f74c9a6..c2acdc0 100644
--- a/src/features/pricing/components/InvestmentScalePricingPane.vue
+++ b/src/features/pricing/components/InvestmentScalePricingPane.vue
@@ -1,8 +1,8 @@
@@ -1191,10 +2039,7 @@ const processCellFromClipboard = (params: any) => {
-
-
{{ t('pricingPane.investment.title') }}
- {{ t('pricingPane.investment.titleHint') }}
-
+
{{ t('pricingPane.investment.title') }}
{{ t('pricingPane.projectCount') }}
{
-
+
@@ -1259,9 +2104,10 @@ const processCellFromClipboard = (params: any) => {
-
diff --git a/src/features/pricing/components/LandScalePricingPane.vue b/src/features/pricing/components/LandScalePricingPane.vue
index d52dbf0..80408ad 100644
--- a/src/features/pricing/components/LandScalePricingPane.vue
+++ b/src/features/pricing/components/LandScalePricingPane.vue
@@ -1,11 +1,11 @@
+
+
+
+
+
+
+
{{ props.title || t('otherService.title') }}
+
+
+
+
+
+
{{ title || "费用明细" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('htZxFw.dialog.resetTitle') }}
+
+ {{ t('htZxFw.dialog.resetDesc', { name: pendingClearServiceName }) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('htZxFw.dialog.deleteTitle') }}
+
+ {{ t('htZxFw.dialog.deleteDesc', { name: pendingDeleteServiceName }) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/pricing/components/WorkloadPricingPane.vue b/src/features/pricing/components/WorkloadPricingPane.vue
index 3e48d94..2c0d2b4 100644
--- a/src/features/pricing/components/WorkloadPricingPane.vue
+++ b/src/features/pricing/components/WorkloadPricingPane.vue
@@ -1,8 +1,8 @@
-
+
-
-
- {{ t('serviceSelector.titleHint') }}
-
+
-
+
+
\ No newline at end of file
diff --git a/src/features/shared/components/WorkContentGrid.vue b/src/features/shared/components/WorkContentGrid.vue
index dfc1df4..8a33deb 100644
--- a/src/features/shared/components/WorkContentGrid.vue
+++ b/src/features/shared/components/WorkContentGrid.vue
@@ -1,5 +1,5 @@
diff --git a/src/features/shared/components/XmFactorGrid.vue b/src/features/shared/components/XmFactorGrid.vue
index cd5d9ba..7332187 100644
--- a/src/features/shared/components/XmFactorGrid.vue
+++ b/src/features/shared/components/XmFactorGrid.vue
@@ -10,6 +10,7 @@ import { useZxFwPricingStore } from '@/pinia/zxFwPricing'
import { useKvStore } from '@/pinia/kv'
import { syncContractFactorsToPricing } from '@/lib/zxFwPricingSync'
import { withReadonlyAutoHeight } from '@/lib/agGridReadonlyAutoHeight'
+import {useDataStore} from "@/pinia/zx";
interface DictItem {
code: string
@@ -62,16 +63,15 @@ const formatReadonlyFactor = (value: unknown) => {
if (value == null || value === '') return ''
const parsed = parseNumberOrNull(value, { precision: 3 })
if (parsed == null) return ''
- return String(Number(parsed))
+ return parsed.toFixed(3)
}
const formatEditableFactor = (params: any) => {
if (params.value == null || params.value === '') return t('xmFactorGrid.clickToInput')
const parsed = parseNumberOrNull(params.value, { precision: 3 })
if (parsed == null) return ''
- return String(Number(parsed))
+ return parsed.toFixed(3)
}
-
const sortedDictEntries = () =>
Object.entries(props.dict)
.filter((entry): entry is [string, DictItem] => {
@@ -87,7 +87,7 @@ const sortedDictEntries = () =>
if (Number.isFinite(aOrder) && !Number.isFinite(bOrder)) return -1
if (!Number.isFinite(aOrder) && Number.isFinite(bOrder)) return 1
return String(a[1]?.code || a[0]).localeCompare(String(b[1]?.code || b[0]))
- })
+ })
const buildCodePath = (code: string, selfId: string, codeIdMap: Map) => {
const parts = code.split('-').filter(Boolean)
@@ -124,11 +124,13 @@ const buildDefaultRows = (): FactorRow[] => {
standardFactor,
budgetValue: props.initBudgetValueFromStandard ? standardFactor : null,
remark: '',
- path: buildCodePath(item.code, id, codeIdMap)
+ // path: buildCodePath(item.code, id, codeIdMap)
+ path:[]
}
})
}
+
type SourceRow = Pick & Partial>
const hasMeaningfulFactorValue = (rows: SourceRow[] | undefined) =>
Array.isArray(rows) &&
@@ -138,16 +140,6 @@ const hasMeaningfulFactorValue = (rows: SourceRow[] | undefined) =>
return hasBudgetValue || hasRemark
})
-const hasUsablePersistedRows = (state: GridState | null | undefined) =>
- Array.isArray(state?.detailRows) &&
- state.detailRows.some(row => {
- const hasFactor =
- typeof row?.budgetValue === 'number' ||
- typeof row?.standardFactor === 'number'
- const hasRemark = typeof row?.remark === 'string' && row.remark.trim() !== ''
- return hasFactor || hasRemark || String(row?.id || '').trim() !== ''
- })
-
const mergeWithDictRows = (rowsFromDb: SourceRow[] | undefined): FactorRow[] => {
const dbValueMap = new Map()
for (const row of rowsFromDb || []) {
@@ -174,6 +166,15 @@ const mergeWithDictRows = (rowsFromDb: SourceRow[] | undefined): FactorRow[] =>
}
const columnDefs: ColDef[] = [
+ {
+ headerName: t('xmFactorGrid.columns.projectname'),
+ field: 'name',
+ // cellClass: 'ag-right-aligned-cell',
+ minWidth: 86,
+ maxWidth: 300,
+ headerClass: 'ag-right-aligned-header',
+ flex: 2,
+ },
{
headerName: t('xmFactorGrid.columns.standardFactor'),
field: 'standardFactor',
@@ -237,14 +238,15 @@ const columnDefs: ColDef[] = [
const gridColumnDefs = computed(() => withReadonlyAutoHeight(columnDefs))
const autoGroupColumnDef: ColDef = {
- headerName: t('xmFactorGrid.columns.groupName'),
- minWidth: 220,
- flex: 2.2,
+ headerName: t('xmFactorGrid.columns.code'),
+ // minWidth: 220,
+ flex: 0.5,
+ width:100,
cellRendererParams: {
suppressCount: true
},
valueFormatter: params => {
- if (params.data?.code && params.data?.name) return `${params.data.code} ${params.data.name}`
+ if (params.data?.code && params.data?.name) return `${params.data.code}`
const key = String(params.node?.key || '')
const dictItem = (props.dict as DictSource)[key]
return dictItem ? `${dictItem.code} ${dictItem.name}` : ''
@@ -257,6 +259,11 @@ const saveToIndexedDB = async () => {
detailRows: JSON.parse(JSON.stringify(detailRows.value))
}
zxFwPricingStore.setKeyState(props.storageKey, payload)
+ const rows = detailRows.value.map(row => ({ ...row, type: `${props.storageKey}-factor` }))
+
+ const stats = await useDataStore().upsertBatch(rows)
+ console.log('💾 数据保存成功:', stats)
+
} catch (error) {
console.error('saveToIndexedDB failed:', error)
}
@@ -318,7 +325,7 @@ const saveFactorChangeState = async (changedRowIds: string[]) => {
const loadGridState = async (storageKey: string): Promise => {
if (!storageKey) return null
const piniaData = await zxFwPricingStore.loadKeyState(storageKey)
- if (hasUsablePersistedRows(piniaData)) return piniaData
+ if (piniaData?.detailRows && Array.isArray(piniaData.detailRows)) return piniaData
// 兼容历史 kvStore 数据:命中后迁移到 pinia keyed state。
const legacyData = await kvStore.getItem(storageKey)
diff --git a/src/features/shared/components/xmCommonAgGrid.vue b/src/features/shared/components/xmCommonAgGrid.vue
index cf6abdf..ce16510 100644
--- a/src/features/shared/components/xmCommonAgGrid.vue
+++ b/src/features/shared/components/xmCommonAgGrid.vue
@@ -9,7 +9,7 @@ import { withReadonlyAutoHeight } from '@/lib/agGridReadonlyAutoHeight'
import { decimalAggSum, roundTo, sumByNumber } from '@/lib/decimal'
import { parseNumberOrNull } from '@/lib/number'
import { formatThousandsFlexible } from '@/lib/numberFormat'
-import { getIndustryDisplayName, getMajorDictEntries, isMajorIdInIndustryScope } from '@/sql'
+import { getIndustryDisplayName, getMajorDictEntries, isMajorIdInIndustryScope, xmProjectConfig } from '@/sql'
import { syncContractScaleToPricing, type ContractScaleSyncResult } from '@/lib/zxFwPricingSync'
import { SwitchRoot, SwitchThumb } from 'reka-ui'
import { useKvStore } from '@/pinia/kv'
@@ -22,8 +22,6 @@ import {
ToastViewport
} from 'reka-ui'
import { Button } from '@/components/ui/button'
-import { CircleHelp } from 'lucide-vue-next'
-import { TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger } from '@/components/ui/tooltip'
@@ -326,25 +324,61 @@ interface ContractScaleChangeState {
updatedAt: number
}
+const XM_PROJECT_PHASE_KEY = 'xm-project-phase-v1'
+
+interface ProjectPhaseState {
+ feePhase?: string
+ feeStage?: string
+}
+
const props = defineProps<{
title: string
dbKey: string
xmInfoKey?: string | null
baseInfoKey?: string
- titleHint?: string
- titleHintAria?: string
}>()
let persistTimer: ReturnType | null = null
const gridApi = ref | null>(null)
const activeIndustryId = ref('')
-const totalLabel = computed(() => {
- const industryName = getIndustryDisplayName(activeIndustryId.value.trim(), locale.value)
- return industryName ? t('pricingScale.totalInvestmentByIndustry', { industryName }) : t('pricingScale.totalInvestment')
-})
+const totalLabel = ref(xmProjectConfig.pinnedTotalLabel)
const roughCalcEnabled = ref(false)
const visibleRowData = computed(() => { return detailRows.value.filter(row => !row.hide) })
+const feePhaseOptions = xmProjectConfig.feePhaseOptions
+const feeStageOptions = xmProjectConfig.feeStageOptions
+const feePhase = ref('')
+const feeStage = ref('')
+
+const loadPhaseState = async () => {
+ try {
+ const state = await kvStore.getItem(XM_PROJECT_PHASE_KEY)
+ if (state) {
+ feePhase.value = state.feePhase || ''
+ feeStage.value = state.feeStage || ''
+ }
+ } catch (error) {
+ console.error('load phase state failed:', error)
+ }
+}
+
+const savePhaseState = async () => {
+ try {
+ await kvStore.setItem(XM_PROJECT_PHASE_KEY, {
+ feePhase: feePhase.value,
+ feeStage: feeStage.value
+ })
+ } catch (error) {
+ console.error('save phase state failed:', error)
+ }
+}
+
+watch([feePhase, feeStage], () => {
+ void savePhaseState()
+})
+
+void loadPhaseState()
+
const refreshPinnedTotalLabelCell = () => {
if (!gridApi.value) return
const pinnedTopNode = gridApi.value.getPinnedTopRow(0)
@@ -398,34 +432,26 @@ const columnDefs: ColDef[] = [
}
},
{
- headerName: t('pricingScale.columns.landArea'),
- field: 'landArea',
+ headerName: '造价金额(元)',
+ field: 'amountYuan',
headerClass: 'ag-right-aligned-header',
- minWidth: 100,
+ minWidth: 120,
flex: 1,
- editable: params => !roughCalcEnabled.value && !params.node?.group && !params.node?.rowPinned && Boolean(params.data?.hasArea),
- cellClass: params =>
- !params.node?.group && !params.node?.rowPinned && params.data?.hasArea
- ? 'editable-cell-line'
- : '',
+ editable: false,
+ aggFunc: decimalAggSum,
+ valueGetter: params => params.data?.amount,
cellClassRules: {
- 'ag-right-aligned-cell': () => true,
- 'editable-cell-empty': params =>
- !params.node?.group && !params.node?.rowPinned && Boolean(params.data?.hasArea) && (params.value == null || params.value === '')
+ 'ag-right-aligned-cell': () => true
},
- valueParser: params => parseNumberOrNull(params.newValue, { precision: 3 }),
valueFormatter: params => {
if (roughCalcEnabled.value) {
return ''
}
- if (!params.node?.group && !params.node?.rowPinned && !params.data?.hasArea) {
+ const amount = params.value
+ if (typeof amount !== 'number' || !Number.isFinite(amount)) {
return ''
}
- if (!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')) {
- return t('pricingScale.clickToInput')
- }
- if (params.value == null) return ''
- return formatThousandsFlexible(params.value, 3)
+ return formatThousandsFlexible(roundTo(amount * 10000, 0), 0)
}
}
]
@@ -435,9 +461,6 @@ const autoGroupColumnDef: ColDef = {
headerName: t('pricingScale.columns.majorGroup'),
minWidth: 200,
flex: 2,
- cellClassRules: {
- 'ag-summary-label-cell': params => Boolean(params.node?.rowPinned)
- },
cellRendererParams: {
suppressCount: true
},
@@ -763,24 +786,10 @@ onMounted(() => {