123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635 |
- <template>
- <div class="doc-container">
- <div class="editor-top">
- <div class="left">
- <div class="doc" v-if="type == 'document'">
- <span>当前打开文档:</span
- >{{ docAttr.title == "" ? "新建文档" : docAttr.title }}
- </div>
- <div class="doc" v-else-if="type == 'module'">
- <span>当前打开模块:</span
- >{{ coms[0].name == "" ? "新建模块" : coms[0].name }}
- </div>
- <div class="doc" v-else>
- <span>当前打开模版:</span
- >{{ docAttr.title == "" ? "新建模版" : docAttr.title }}
- </div>
- <div class="creator">
- <span>创建者:</span
- ><!-- {{ userInfo && userInfo.username }} -->
- </div>
- </div>
- <div class="right">
- <el-button
- type="primary"
- size="mini"
- @click="onSaveAs"
- v-if="
- type !== 'module' && type == 'document' && articleId == undefined
- "
- >保存文档</el-button
- ><!-- v-if="docAttr.id > 0" -->
- <el-button
- type="primary"
- size="mini"
- @click="renew"
- v-if="
- articleId !== undefined && type !== 'module' && type == 'document'
- "
- >更新文档</el-button
- >
- <!-- <el-popover
- placement="bottom"
- trigger="click"
- v-if="type !== 'module' && type !== 'document'"
- > -->
- <el-button
- type="primary"
- v-if="type !== 'module' && type !== 'document' && !articleId"
- @click="onSaveUpload"
- >保存</el-button
- >
- <el-button
- type="primary"
- v-if="type !== 'module' && type !== 'document' && articleId"
- @click="onUpload"
- >更新</el-button
- >
- <!-- <el-button
- slot="reference"
- type="primary"
- size="mini"
- style="margin: 0 10px"
- v-if="$store.state.user.name == 'admin'"
- >保存并更新模版</el-button
- >
- </el-popover> -->
- <!-- <el-button
- type="primary"
- size="mini"
- v-if="$store.state.user.name == 'admin'"
- @click="onSaveUpload"
- >保存并更新模版</el-button
- > -->
- <el-button
- type="primary"
- size="mini"
- v-if="type !== 'module' && type == 'document'"
- @click="onOpenView"
- >预览导出
- </el-button>
- <el-button type="primary" size="mini" @click="onClose">
- 关闭文档
- </el-button>
- </div>
- </div>
- <div class="editor-content">
- <!-- 文档选择面板 -->
- <div
- class="left_scheme"
- v-if="type !== 'module'"
- :class="{ collapsed: isSchemeCollapsed }"
- >
- <div class="scheme-header">
- <div class="title">
- 请选择文档
- <i class="el-icon-menu" @click="toggleSchemePanel"></i>
- </div>
- <div class="search">
- <el-input
- v-model="searchKey"
- placeholder="请输入搜索"
- prefix-icon="el-icon-search"
- clearable
- @keyup.enter.native="handleSearch"
- @clear="handleClear"
- >
- </el-input>
- </div>
- <!-- <div class="action-btns">
- <el-button type="primary" size="small" @click="createScheme"
- >新建方案</el-button
- >
- <el-button type="primary" size="small" @click="createCategory"
- >新建分类</el-button
- >
- </div> -->
- <div class="current-scheme">
- 当前文档: {{ currentScheme || "已选择方案三" }}
- </div>
- </div>
- <div class="scheme-content" v-show="!isSchemeCollapsed">
- <el-tree
- :data="schemeData"
- :props="defaultProps"
- @node-click="handleNodeClick"
- :default-expanded-keys="expandedKeys"
- node-key="id"
- ref="documentTree"
- >
- <span class="custom-tree-node" slot-scope="{ node, data }">
- <span @click="onLoadArticle(data.id)">
- <i class="el-icon-folder" v-if="data.children"></i>
- <i class="el-icon-document" v-else></i>
- {{ node.label }}
- </span>
- </span>
- </el-tree>
- </div>
- </div>
- <!-- 资源面板 -->
- <div class="natural" :class="{ collapsed: isResourceCollapsed }">
- <div class="resource-header-title">
- <div class="title-left">
- <span>请选择模块</span>
- </div>
- <i class="el-icon-menu" @click="toggleResourcePanel"></i>
- </div>
- <div class="resource-container" v-show="!isResourceCollapsed">
- <div class="resource-header">
- <el-input
- v-model="templateSearchKey"
- placeholder="请输入选择"
- prefix-icon="el-icon-search"
- clearable
- @keyup.enter.native="handleTemplateSearch"
- @clear="handleResourceClear"
- >
- </el-input>
- <!-- <div class="action-btns">
- <el-button type="primary" @click="createResource"
- >新建资源</el-button
- >
- <el-button type="primary" @click="createResourceCategory"
- >新建资源分类</el-button
- >
- </div> -->
- </div>
- <!-- <div class="resource-status">
- 已打开1个资源,已选择3个资源
- <el-button size="small" plain @click="refreshResources"
- >更新</el-button
- >
- </div> -->
- <div class="resource-content">
- <el-collapse v-model="activeCategories">
- <el-collapse-item
- v-for="(category, index) in categoryList"
- :key="index"
- :title="category.name"
- :name="category.id"
- >
- <template slot="title">
- <span>{{ category.name }}</span>
- </template>
- <div class="resource-list">
- <draggable
- v-model="category.templates"
- :options="{
- group: { name: 'itxst', pull: 'clone' },
- sort: true,
- }"
- :disabled="type == 'module'"
- @end="handleDragEnd"
- >
- <transition-group>
- <div
- v-for="template in category.templates"
- :key="template.dcb_id || template.name"
- class="resource-item"
- :data-template-id="template.dcb_id"
- >
- <el-checkbox
- v-model="template.selected"
- @change="
- (val) =>
- handleTemplateSelect(category, template, val)
- "
- :disabled="isTemplateUsed(template)"
- >
- {{ template.dcb_name }}
- </el-checkbox>
- </div>
- </transition-group>
- </draggable>
- </div>
- </el-collapse-item>
- </el-collapse>
- </div>
- </div>
- </div>
- <!-- <div class="neary-doc">
- <div class="left-content">
- <div class="new-article">
- <div v-if="showView == 0 && type !== 'module'">
- <el-collapse v-model="activeNames">
- <el-collapse-item
- title="最新文档"
- name="-1"
- v-if="type == 'document'"
- >
- <div
- v-for="(it, index) in articleList"
- draggable
- :key="it.id"
- :data-index="index"
- data-type="article"
- class="sub-menus"
- >
- <div @click="onLoadArticle(it.id)" style="cursor: pointer">
- {{ it.title }}
- </div>
- </div>
- </el-collapse-item>
- <el-collapse-item
- title="模版列表"
- name="-2"
- v-if="showView == 0"
- >
- <div
- v-for="(it, index) in templateList"
- draggable
- :key="it.id"
- :data-index="index"
- data-type="article"
- class="sub-menus"
- >
- <div @click="onTemplateInfo(it.id)" style="cursor: pointer">
- {{ it.title }}
- </div>
- </div>
- </el-collapse-item>
- </el-collapse>
- </div>
- <div v-if="showView == 1" class="scrollable-container">
- <el-collapse
- v-model="activeModel"
- :accordion="true"
- @change="handleItemClick"
- class="borderless-collapse"
- >
- <el-collapse-item
- v-for="(item, itemIndex) in categoryList"
- :key="itemIndex"
- :title="item.name"
- :name="item.id"
- class="min-width-content"
- >
- <el-collapse
- v-if="item.children && item.children.length"
- v-model="item.activeChildren"
- @change="handleItemVal"
- v-show="item.children"
- class="borderless-collapse"
- >
- <el-collapse-item
- v-for="(child, childIndex) in item.children"
- :key="childIndex"
- :title="child.name"
- :name="child.id"
- class="min-width-content"
- >
- <el-collapse
- v-if="child.children && child.children.length"
- v-model="child.activeChildren"
- @change="handleChildItemVal"
- v-show="child.children"
- class="borderless-collapse"
- >
- <el-collapse-item
- v-for="(
- grandChild, grandChildIndex
- ) in child.children"
- :key="grandChildIndex"
- :title="grandChild.name"
- :name="grandChild.id"
- class="min-width-content"
- >
- <el-collapse
- v-if="
- grandChild.children && grandChild.children.length
- "
- v-model="grandChild.activeChildren"
- @change="handleGrandChildItemVal"
- v-show="grandChild.children"
- class="borderless-collapse"
- >
- <el-collapse-item
- v-for="(
- greatGrandChild, greatGrandChildIndex
- ) in grandChild.children"
- :key="greatGrandChildIndex"
- :title="greatGrandChild.name"
- :name="greatGrandChild.id"
- class="min-width-content"
- >
- <el-collapse
- v-if="
- greatGrandChild.children &&
- greatGrandChild.children.length
- "
- v-model="greatGrandChild.activeChildren"
- @change="handlegreatGrandChildItemVal"
- v-show="greatGrandChild.children"
- class="borderless-collapse"
- >
- <el-collapse-item
- v-for="(
- fiveChild, fiveIndex
- ) in greatGrandChild.children"
- :key="fiveIndex"
- :title="fiveChild.name"
- :name="fiveChild.id"
- class="min-width-content"
- >
- <draggable
- v-model="fiveChild.dataList"
- :options="{
- group: { name: 'itxst', pull: 'clone' },
- sort: true,
- }"
- :disabled="type === 'module'"
- >
- <transition-group>
- <div
- class="sub-menus min-width-content"
- v-for="(
- fiveIts, fiveIndex
- ) in fiveChild.dataList"
- :key="fiveIndex"
- >
- <div style="cursor: move">
- {{ fiveIts.name }}
- </div>
- </div>
- </transition-group>
- </draggable>
- </el-collapse-item>
- </el-collapse>
- <draggable
- v-model="greatGrandChild.dataList"
- :options="{
- group: { name: 'itxst', pull: 'clone' },
- sort: true,
- }"
- :disabled="type == 'module'"
- >
- <transition-group>
- <div
- class="sub-menus min-width-content"
- v-for="(
- its, index
- ) in greatGrandChild.dataList"
- :key="index"
- >
- <div style="cursor: move">
- {{ its.name }}
- </div>
- </div>
- </transition-group>
- </draggable>
- </el-collapse-item>
- </el-collapse>
- <draggable
- v-model="grandChild.dataList"
- :options="{
- group: { name: 'itxst', pull: 'clone' },
- sort: true,
- }"
- :disabled="type == 'module'"
- >
- <transition-group>
- <div
- class="sub-menus min-width-content"
- v-for="(it, index) in grandChild.dataList"
- :key="index"
- >
- <div style="cursor: move">{{ it.name }}</div>
- </div>
- </transition-group>
- </draggable>
- </el-collapse-item>
- </el-collapse>
- <draggable
- v-model="child.dataList"
- :options="{
- group: { name: 'itxst', pull: 'clone' },
- sort: true,
- }"
- :disabled="type == 'module'"
- >
- <transition-group>
- <div
- class="sub-menus min-width-content"
- v-for="(it, index) in child.dataList"
- :key="index"
- >
- <div style="cursor: move">{{ it.name }}</div>
- </div>
- </transition-group>
- </draggable>
- </el-collapse-item>
- </el-collapse>
- <draggable
- v-model="item.dataList"
- :options="{
- group: { name: 'itxst', pull: 'clone' },
- sort: true,
- }"
- :disabled="type == 'module'"
- >
- <transition-group>
- <div
- class="sub-menus min-width-content"
- v-for="(it, index) in item.dataList"
- :key="index"
- >
- <div style="cursor: move">{{ it.name }}</div>
- </div>
- </transition-group>
- </draggable>
- </el-collapse-item>
- </el-collapse>
- </div>
- </div>
- </div>
- <div class="right-sidebarew">
- <div
- v-if="type !== 'module'"
- class="sidebar-item"
- :class="showView == 0 ? 'active-item' : ''"
- @click="viewDocument"
- >
- <span v-if="type == 'document'">查看文档</span>
- <span v-else>查看模版</span>
- </div>
- <div
- v-if="type !== 'document'"
- class="sidebar-item"
- :class="showView == 1 ? 'active-item' : ''"
- @click="viewModule"
- >
- 模块列表
- </div>
- </div>
- </div> -->
- <div class="leftContent">
- <div class="catalog-content">
- <!-- 目录内容展示区域 -->
- <el-tree
- :data="catalogData"
- :props="catalogProps"
- default-expand-all
- @node-click="handleCatalogClick"
- draggable
- :allow-drop="allowDrop"
- :allow-drag="allowDrag"
- @node-drag-end="handleDragEnd"
- >
- <span class="custom-tree-node" slot-scope="{ data }">
- <span v-if="data.isEditing">
- <el-input
- v-model="data.editingContent"
- size="mini"
- @blur="handleEditComplete(data)"
- @keyup.enter.native="handleEditComplete(data)"
- ref="editInput"
- ></el-input>
- </span>
- <span v-else @dblclick="handleStartEdit(data)">
- {{ data.label }}
- </span>
- </span>
- </el-tree>
- </div>
- </div>
- <div class="editor-main">
- <!-- 添加tab页导航 -->
- <div class="editor-tabs">
- <el-tabs v-model="activeTab" type="card" @tab-click="handleClick">
- <el-tab-pane label="目录" name="catalog">
- <div class="catalog-content">
- <!-- 目录内容展示区域 -->
- <el-tree
- v-if="activeTab === 'catalog'"
- :data="catalogData"
- :props="{ children: 'children', label: 'label' }"
- node-key="id"
- draggable
- @node-drag-end="handleDirectoryDragEnd"
- >
- <span class="custom-tree-node" slot-scope="{ node, data }">
- <template v-if="data.isEditing">
- <el-input
- v-model="data.content"
- :ref="`directory-input-${data.id}`"
- size="mini"
- @blur="handleDirectorySave(data)"
- @keyup.enter.native="handleDirectorySave(data)"
- />
- </template>
- <template v-else>
- <span @dblclick="handleDirectoryEdit(data)">{{
- data.label
- }}</span>
- <span class="directory-actions">
- <el-button
- type="text"
- size="mini"
- @click="handleDirectoryEdit(data)"
- >
- 编辑
- </el-button>
- </span>
- </template>
- </span>
- </el-tree>
- </div>
- </el-tab-pane>
- <el-tab-pane label="模板内容" name="template">
- <div class="template-content">
- <!-- <div class="search-box">
- <el-input
- v-model="templateSearchKey"
- placeholder="搜索模板"
- @keyup.enter="handleTemplateSearch"
- clearable
- @clear="handleTemplateClear"
- >
- <i slot="prefix" class="el-input__icon el-icon-search"></i>
- </el-input>
- </div> -->
- <!-- 原有的menus和editor内容 -->
- <div class="menus-box">
- <menus
- @onEvents="onInsert"
- @onVariable="uptadeVariable"
- :comArr="coms"
- ></menus>
- </div>
- <div
- class="editor-box"
- ref="tabHtml"
- v-loading="loading"
- element-loading-text="加载中..."
- element-loading-spinner="el-icon-loading"
- >
- <editor
- ref="editor"
- :coms="coms"
- :comIndex="comIndex"
- :isAdmin="isAdmin"
- :templateCate="categoryList"
- :insertCmd="insertCmd"
- @onSetActiveIndex="onSetActiveIndex"
- @onInsert="onInsert"
- @onLoadArticle="onLoadArticle"
- @onRebuild="onRebuild"
- @onDelete="onRemove"
- @onSetComs="onSetComs"
- ></editor>
- </div>
- </div>
- </el-tab-pane>
- </el-tabs>
- </div>
- </div>
- <div class="module-list-container">
- <draggable
- v-model="coms"
- @add="onAdd"
- @update="onDragEnd"
- @end="onDragComplete"
- group="itxst"
- animation="300"
- handle=".drag-handle"
- :scroll="true"
- :scrollSensitivity="100"
- :scrollSpeed="20"
- >
- <transition-group style="display: block">
- <template v-for="(it, index) in coms">
- <div
- :key="index"
- class="module-item"
- :class="comIndex == index ? 'active-module' : ''"
- >
- <div class="drag-handle">
- <img
- src="@/icons/svg/drag.svg"
- style="width: 20px"
- icon-class="drag"
- />
- </div>
- <div class="module-info">
- <div class="module-content">
- <div class="module-category">
- <span class="label">模块分类:</span>
- <span class="value">{{
- getCategory(it.category_id)
- }}</span>
- </div>
- <div class="module-name">
- <span class="label">模块名称:</span>
- <span class="value">{{ it.dcb_name }}</span>
- </div>
- </div>
- </div>
- <div class="module-actions">
- <el-button
- v-if="type !== 'document'"
- type="text"
- size="mini"
- @click="onSaveTemplate(it)"
- >
- <i class="el-icon-document-add"></i> 保存
- </el-button>
- <el-button
- type="text"
- size="mini"
- @click="onEdit(index, it.isEdit !== 1 ? 1 : 2)"
- >
- <i :class="it.isEdit !== 1 ? 'el-icon-edit' : 'el-icon-view'"></i>
- {{ it.isEdit !== 1 ? "编辑" : "预览" }}
- </el-button>
- <el-button
- type="text"
- size="mini"
- @click="onRemoveMdel(index)"
- >
- <i class="el-icon-delete"></i> 删除
- </el-button>
- </div>
- </div>
- </template>
- </transition-group>
- </draggable>
- </div>
- </div>
- <!-- 新增资源选择弹框 -->
- <!-- <el-dialog
- title="请选择可用的资源"
- :visible.sync="resourceDialogVisible"
- width="800px"
- custom-class="resource-dialog"
- >
- <div class="resource-container">
- <div class="resource-header">
- <el-input
- v-model="resourceSearchKey"
- placeholder="请输入选择"
- prefix-icon="el-icon-search"
- clearable
- >
- </el-input>
- <div class="action-btns">
- <el-button type="primary" @click="createResource"
- >新建资源</el-button
- >
- <el-button type="primary" @click="createResourceCategory"
- >新建资源分类</el-button
- >
- </div>
- </div>
- <div class="resource-status">
- 已打开1个资源,已选择3个资源
- <el-button size="small" plain @click="refreshResources"
- >更新</el-button
- >
- </div>
- <div class="resource-content">
- <el-collapse v-model="activeCategories">
-
- <el-collapse-item name="dlp">
- <template slot="title">
- <span>DLP产品</span>
- <i class="el-icon-arrow-up"></i>
- </template>
- <div class="resource-list">
- <div
- v-for="item in dlpProducts"
- :key="item.id"
- class="resource-item"
- >
- <el-checkbox v-model="item.selected">
- {{ item.name }}
- </el-checkbox>
- <i class="el-icon-menu"></i>
- </div>
- </div>
- </el-collapse-item>
-
- <el-collapse-item name="led">
- <template slot="title">
- <span>LED产品系列</span>
- <i class="el-icon-arrow-up"></i>
- </template>
- <div class="resource-list">
- <div
- v-for="item in ledProducts"
- :key="item.id"
- class="resource-item"
- >
- <el-checkbox v-model="item.selected">
- {{ item.name }}
- </el-checkbox>
- <i class="el-icon-menu"></i>
- </div>
- </div>
- </el-collapse-item>
-
- <el-collapse-item name="processor">
- <template slot="title">
- <span>处理器</span>
- <i class="el-icon-arrow-up"></i>
- </template>
- <div class="resource-list">
- <div
- v-for="item in processors"
- :key="item.id"
- class="resource-item"
- >
- <el-checkbox v-model="item.selected">
- {{ item.name }}
- </el-checkbox>
- <i class="el-icon-menu"></i>
- </div>
- </div>
- </el-collapse-item>
-
- <el-collapse-item name="service">
- <template slot="title">
- <span>售后服务</span>
- <i class="el-icon-arrow-up"></i>
- </template>
- <div class="resource-list">
- <div
- v-for="item in services"
- :key="item.id"
- class="resource-item"
- >
- <el-checkbox v-model="item.selected">
- {{ item.name }}
- </el-checkbox>
- <i class="el-icon-menu"></i>
- </div>
- </div>
- </el-collapse-item>
- </el-collapse>
- </div>
- </div>
- </el-dialog> -->
- <el-dialog
- :visible.sync="showViewForm"
- :close-on-click-modal="false"
- append-to-body
- v-el-drag-dialog
- width="850px"
- custom-class="prod-verify"
- title="文档预览"
- >
- <ViewForm :coms="coms" :docAttr="docAttr"></ViewForm>
- </el-dialog>
- <el-dialog
- :visible.sync="showProductAttr"
- append-to-body
- v-el-drag-dialog
- :close-on-click-modal="false"
- width="850px"
- custom-class="prod-verify"
- title="插入产品属性"
- >
- <ProductAttr
- :docAttr="docAttr"
- @onInsertProductAttr="onInsertProductAttr"
- ></ProductAttr>
- </el-dialog>
- <el-dialog
- :visible.sync="docVisible"
- append-to-body
- v-el-drag-dialog
- :close-on-click-modal="false"
- width="500px"
- custom-class="prod-verify"
- title="文档信息"
- >
- <el-form
- :model="docForm"
- :rules="docRules"
- ref="docRef"
- label-width="120px"
- >
- <el-form-item label="文档标题:" prop="dcm_title">
- <el-input
- v-model="docForm.dcm_title"
- style="width: 60%"
- class="input-item"
- placeholder="请填写文档标题"
- :disabled="docAttr.id > 0"
- />
- </el-form-item>
- <el-form-item label="文档模板类别:" prop="dcm_type">
- <el-select
- v-model="docForm.dcm_type"
- style="width: 60%"
- placeholder="请选择文档模板类别"
- :disabled="docAttr.id > 0"
- >
- <!-- <el-option
- v-for="(item, index) in articleCategoryList"
- :key="index"
- :label="item.name"
- :value="item.id"
- /> -->
- <el-option label="官方模板" :value="1" />
- <el-option label="私有模板" :value="2" />
- <el-option label="共享模板" :value="3" />
- </el-select>
- </el-form-item>
- <el-form-item label="文档分类:">
- <el-select
- v-model="docForm.dcm_category_id"
- style="width: 60%"
- placeholder="请选择文档模板类别"
- :disabled="docAttr.id > 0"
- ><el-option
- v-for="(item, index) in articleCategoryList"
- :key="index"
- :label="item.name"
- :value="item.id"
- />
- </el-select>
- <!-- {{ userInfo && userInfo.username }} -->
- </el-form-item>
- </el-form>
- <span slot="footer" class="dialog-footer">
- <el-button @click="closeDoc">取 消</el-button>
- <el-button type="primary" @click="submitDoc">确 定</el-button>
- </span>
- </el-dialog>
- </div>
- </template>
- <script>
- import { findData } from "@/api/sourceData";
- /* import utils from "@/utils/fun"; // 方法类 */
- import { searchDocument, pageDocument } from "@/api/document";
- import menus from "./com/menus";
- import editor from "./com/editor";
- import Attribute from "./com/components/Attribute";
- import attributeVar from "./com/components/Attribute/attributeVar/index.vue";
- import ProductAttr from "./com/components/ProductAttr";
- import {
- searchTemplateCategory,
- searchTemplate,
- getTemplateInfo,
- getAllCategory,
- createTemplate,
- updateTemplate,
- } from "@/api/template";
- import docAttr from "./com/components/Attribute/docAttr";
- import comList from "./com/components/Attribute/comList";
- import Directory from "./com/components/Attribute/Directory";
- import { getCurrentUserInfo } from "@/api/api";
- import {
- createDocument,
- updateDocument,
- getDocumentInfo,
- exportDocument,
- searchDocumentCategory,
- } from "@/api/document";
- import ViewForm from "./com/view";
- import elDragDialog from "@/directive/el-drag-dialog";
- import draggable from "vuedraggable";
- import htmlDocx from "html-docx-js/dist/html-docx";
- import { searchFormula } from "@/api/formula";
- import axios from "axios";
- import settings from "@/settings";
- // import htmlDocx from "htmlDocx";
- export default {
- name: "create",
- components: {
- menus,
- editor,
- Attribute,
- comList,
- docAttr,
- ViewForm,
- ProductAttr,
- Directory,
- draggable,
- attributeVar,
- },
- directives: {
- elDragDialog,
- },
- data() {
- return {
- activeNames: "-1",
- nestedActiveNames: [],
- articleList: [],
- activeModel: "",
- templateList: [],
- categoryList: [],
- //组件相关
- coms: [],
- comIndex: 9999, //当前组件索引
- showProductAttr: false,
- comList: [],
- //文档属性
- docAttr: {
- id: 0,
- dcm_category_id: "",
- title: "",
- content: "",
- status: 5,
- links: "",
- linkProduct: [],
- linkProject: [],
- projects: "",
- },
- insertCmd: null,
- showViewForm: false,
- isAdmin: 2, //1是管理员,2非管理员
- //当前选中表格
- tabExt: {
- row: 0,
- col: 0,
- },
- userInfo: null,
- articleId: 0,
- loading: false, // 增加 loading 状态
- showView: 0, //查看 文档/模块
- childrenList: "",
- value: [],
- AttributeIndex: 0,
- catalogIndex: 0, //目录信息
- docuComIndex: 3,
- type: "",
- docVisible: false,
- docForm: {
- dcm_title: "",
- dcm_type: "",
- dcm_category_id: "",
- },
- docRules: {
- dcm_title: [
- { required: true, message: "请输文档名称", trigger: "blur" },
- ],
- dcm_type: [
- { required: true, message: "请选择文档模板分类", trigger: "change" },
- ],
- dcm_category_id: [
- { required: true, message: "请选择文档分类", trigger: "change" },
- ],
- },
- articleCategoryList: [],
- //方案
- searchKey: "",
- currentScheme: "",
- expandedKeys: [], // 默认展开的节点
- schemeData: [],
- defaultProps: {
- children: "children",
- label: "label",
- },
- /* 资源 */
- resourceDialogVisible: false,
- resourceSearchKey: "",
- activeCategories: ["dlp", "led", "processor", "service"],
- dlpProducts: [
- { id: 1, name: "产品选型/DLP/单元/", selected: false },
- { id: 2, name: "产品选型/DLP/机芯/", selected: true },
- { id: 3, name: "产品选型/DLP/控制盒/", selected: true },
- ],
- ledProducts: [
- { id: 4, name: "产品选型/LED/黄河系/", selected: false },
- { id: 5, name: "产品选型/LED/华夏系/", selected: true },
- { id: 6, name: "产品选型/LED/黄河单元/", selected: false },
- ],
- processors: [
- { id: 7, name: "产品选型/处理器/D301/", selected: false },
- { id: 8, name: "产品选型/处理器/IPWH300/", selected: false },
- { id: 9, name: "产品选型/处理器/IPWD400/", selected: false },
- ],
- services: [
- { id: 10, name: "产品选型/处理器/IPWH300/", selected: false },
- { id: 11, name: "产品选型/处理器/IPWH301/", selected: false },
- { id: 12, name: "产品选型/处理器/IPWD400/", selected: false },
- ],
- /* 目录/模板 */
- activeTab: "template", // 默认显示模板内容tab
- catalogData: [], // 目录数据
- catalogProps: {
- children: "children",
- label: "label",
- },
- templateSearchKey: "", // 添加模板搜索关键字
- originalTemplateList: [], // 保存原始模板列表
- isSaving: false,
- saveAs: false,
- isSchemeCollapsed: false,
- isResourceCollapsed: false,
- };
- },
- watch: {
- coms: {
- handler(newComs, oldComs) {
- this.updateAttrs(newComs, oldComs);
- },
- immediate: true, //立即执行
- deep: true,
- },
- articleId: {
- handler(val) {
- if (val == null || val == undefined || val <= 0) return;
- if (this.$route.query.type == "document") {
- this.loadArticle(val);
- } else {
- this.onTemplateInfo(val);
- }
- //
- },
- immediate: true,
- deep: true,
- },
- coms: {
- handler(newComs) {
- this.updateCatalog(newComs);
- },
- deep: true,
- },
- comIndex: {
- handler(newIndex) {
- // 高亮当前选中模块对应的目录项
- this.$nextTick(() => {
- this.highlightCurrentCatalogItem(newIndex);
- });
- },
- },
- },
- async mounted() {
- this.articleId = this.$route.query.articleId;
- this.type = this.$route.query.type;
- if (this.type == "module") {
- this.showView = 1;
- }
- this.searchArticle();
- await this.initCategoryList();
- await this.initCurrentUser();
- let templateId = this.$route.query.templateId;
- if (templateId > 0) {
- this.loadTemplateInfo(templateId);
- }
- this.isAdmin = 2; //this.userInfo ? this.userInfo.roleInfo.is_admin : 2;
- this.initArticleCategoryList();
- if (this.type !== "module" && this.type !== "document") {
- document.title = "新建模版-" + settings.title;
- }
- if (
- this.type !== "module" &&
- this.type !== "document" &&
- this.articleId !== undefined
- ) {
- document.title = this.docAttr.title + settings.title;
- }
- this.$nextTick(() => {
- const arrows = document.querySelectorAll(".el-collapse-item__arrow");
- arrows.forEach((arrow) => {
- arrow.style.margin = "0";
- });
- });
- this.initTemplateSelection();
- this.expandedKeys = []; // 初始化展开节点数组
- //this.initCatalog(); // 初始化目录
- },
- methods: {
- /* 切换目录/模板 */
- handleClick(val) {
- if (val.name === "catalog") {
- this.updateCatalog(this.coms);
- }
- },
- // 更新目录数据
- updateCatalog(modules) {
- let catalogData = [];
- modules.forEach((module, moduleIndex) => {
- // 获取并排序目录类型的属性
- const directoryAttrs = module.attrs
- .filter((attr) => attr.type === "Directory")
- .sort((a, b) => {
- // 首先按层级排序
- if (a.level !== b.level) return a.level - b.level;
- // 同层级按编号自然排序
- return a.number.localeCompare(b.number, undefined, {
- numeric: true,
- });
- });
- directoryAttrs.forEach((attr) => {
- const catalogItem = {
- id: attr.id,
- label: `${attr.number} ${attr.content}`,
- level: attr.level,
- moduleIndex: moduleIndex,
- content: attr.content,
- number: attr.number,
- children: [],
- isEditing: false,
- };
- // 根据level确定目录层级
- if (attr.level === 1) {
- catalogData.push(catalogItem);
- } else {
- // 查找父级目录并添加为子项
- const parent = this.findParentDirectory(catalogData, attr.number);
- if (parent) {
- parent.children.push(catalogItem);
- }
- }
- });
- });
- this.catalogData = catalogData;
- this.$nextTick(() => this.$forceUpdate());
- },
- // 添加 findParentDirectory 辅助方法
- findParentDirectory(catalogData, number) {
- const parentNumber = number.split(".").slice(0, -1).join(".");
- const findInChildren = (items) => {
- for (let item of items) {
- if (item.label.startsWith(parentNumber + " ")) {
- return item;
- }
- if (item.children) {
- const found = findInChildren(item.children);
- if (found) return found;
- }
- }
- return null;
- };
- return findInChildren(catalogData);
- },
- /* 方案点击 */
- handleNodeClick(data) {
- console.log(data);
- this.currentScheme = data.label;
- this.resourceDialogVisible = true; // 点击方案时打开资选择弹框
- },
- createScheme() {
- // 实现新建方案逻辑
- this.$message.success("新建方案");
- },
- createCategory() {
- // 实现新建分类逻辑
- this.$message.success("新建分类");
- },
- /* 资源 */
- createResource() {
- this.$message.success("新建资源");
- },
- createResourceCategory() {
- this.$message.success("新建资源分类");
- },
- refreshResources() {
- this.$message.success("刷新资源列表");
- },
- /* 目录模板 */
- handleCatalogClick(data) {
- // 如果正在编辑,不触发其他操作
- if (data.isEditing) return;
- // 其他点击处理逻辑...
- console.log("点击的目录项:", data);
- },
- handleItemVal(value) {
- this.$forceUpdate();
- this.loadChildren(value);
- },
- handleChildItemClick(child) {
- if (!child.children) {
- this.loadChildren(child);
- }
- },
- handleChildItemVal(value) {
- this.$forceUpdate();
- this.loadChildren(value);
- },
- handleGrandChildItemClick(grandChild) {
- if (!grandChild.children) {
- this.loadChildren(grandChild);
- }
- },
- handleGrandChildItemVal(value) {
- this.loadChildren(value);
- this.$forceUpdate();
- },
- handlegreatGrandChildItemVal(greatGrandChild) {
- this.loadChildren(greatGrandChild);
- this.$forceUpdate();
- },
- async loadChildren(category) {
- const category_id = category[category.length - 1];
- try {
- const res = await searchTemplateCategory({ parent_id: category_id });
- if (res.status != 200 || res.data.length == 0) return;
- const newChildren = res.data;
- for (let i = 0; i < newChildren.length; i++) {
- newChildren[i].dataList = await this.getTemplateList(
- newChildren[i].id
- );
- }
- this.insertChildrenById(this.categoryList, category_id, newChildren);
- console.log(this.categoryList);
- this.$forceUpdate(); // Force Vue to re-render the component
- } catch (error) {
- console.error("Error fetching template categories:", error);
- }
- },
- insertChildrenById(list, id, newChildren) {
- for (let item of list) {
- if (item.id === id) {
- this.$set(item, "children", newChildren); // Use Vue.set to ensure reactivity
- return true; // Stop searching once the item is found
- }
- if (item.children && item.children.length > 0) {
- const found = this.insertChildrenById(item.children, id, newChildren);
- if (found) return true; // Stop searching if the item is found in deeper levels
- }
- }
- return false; // Continue searching
- },
- /* 取消新增 */
- closeDoc() {
- this.docVisible = false;
- this.docForm = {
- dcm_title: "",
- dcm_type: "",
- dcm_category_id: "",
- };
- },
- /* 确定新增模块*/
- submitDoc() {
- this.$refs.docRef.validate((valid) => {
- if (valid) {
- this.docAttr.dcm_title = this.docForm.dcm_title;
- this.docAttr.dcm_type = this.docForm.dcm_type;
- this.docAttr.dcm_category_id = this.docForm.dcm_category_id;
- this.onSave();
- }
- });
- },
- //加载文档分类
- initArticleCategoryList() {
- let _this = this;
- searchDocumentCategory({ page: 1, pageSize: 99, status: 5 }).then(
- (res) => {
- if (res.status != 200) return;
- _this.articleCategoryList = res.data.dataList;
- }
- );
- },
- updateAttrs(newComs, oldComs) {
- newComs.forEach((newCom, comIndex) => {
- const oldCom = oldComs[comIndex];
- console.log("oldCom:", oldCom, "newCom:", newCom);
- if (oldCom) {
- newCom.attrs.forEach((newAttr, attrIndex) => {
- const oldAttr = oldCom.attrs[attrIndex];
- if (oldAttr && newAttr.content !== oldAttr.content) {
- // 内容发生变化,进行全局更新
- this.updateGlobalAttr(newAttr.name, newAttr.content);
- }
- });
- }
- });
- },
- updateGlobalAttr(attrId, newContent) {
- // 遍历所有组件,更新匹配的属性
- this.coms.forEach((com) => {
- console.log(com);
- com.attrs.forEach((attr) => {
- // 只更新非 variableNull 类型的属性
- if (attr.name === attrId && attr.type !== "variableNull") {
- attr.content = newContent;
- }
- });
- // 如果是文本区域,更新内容中的占位符
- if (com.dcb_type === "TextArea") {
- com.content = com.content.replace(
- new RegExp(`{{${attrId}}}`, "g"),
- (match) => {
- const attr = com.attrs.find((a) => a.id === attrId);
- if (attr && attr.type !== "variableNull") {
- return newContent;
- }
- return match; // 保留 variableNull 类型的原始占位符
- }
- );
- }
- });
- // 触发视图更新
- this.replaceData(this.coms);
- this.$forceUpdate();
- },
- async replaceData(data) {
- for (let item of this.coms) {
- for (let el of item.attrs) {
- let attrId = el.id;
- if (el.type === "formual") {
- try {
- let formual = await this.analysisFormual(el);
- formual = await this.getRemote(formual);
- el.content = eval(formual);
- } catch (error) {
- console.error("处理公式时出错:", error);
- }
- } else if (el.type === "variableNull") {
- // 保留 variableNull 类型的原始内容
- el.content = el.content || "请输入";
- }
- }
- }
- return data;
- },
- //分析公式
- async analysisFormual(attrs) {
- let _this = this;
- // console.log("开始分析公式:", attrs.formula);
- var pattern = /(\[.*?\]){3}/;
- var formual = attrs.formula;
- var reg = new RegExp(pattern);
- while (true) {
- var items = formual.match(reg);
- if (items == null) break;
- let itemName = items[0];
- // console.log("处理项:", itemName);
- try {
- let data = await _this.getFormualData(itemName);
- // console.log(`获取到的数据: ${itemName} = ${data}`);
- if (data === null || data === undefined || isNaN(data)) {
- console.warn(`获取到的数据无效: ${itemName}`);
- formual = formual.replace(itemName, "(0)");
- } else {
- formual = formual.replace(itemName, `(${parseFloat(data)})`);
- }
- } catch (error) {
- console.error(`处理 ${itemName} 时出错:`, error);
- formual = formual.replace(itemName, "(0)");
- }
- }
- // console.log("分析后的公式:", formual);
- return formual;
- },
- async getFormualData(formualItem) {
- let _this = this;
- // console.log("开始获取公式数据:", formualItem);
- var pattern = /\[(.*?)\]\[(.*?)\]\[(.*?)\]/;
- var reg = new RegExp(pattern);
- let items = formualItem.match(reg);
- // console.log("解析结果:", items);
- let calResult = 0;
- if (items && items[1] == "T") {
- calResult = await _this.getModuleData(items[2], items[3]);
- } else {
- console.warn("无法解析公式项:", formualItem);
- }
- // console.log("计算结果:", calResult);
- return calResult;
- },
- //获取本地文档模块数据
- async getModuleData(code, attrName) {
- let _this = this;
- // console.log(`尝试获取模块数据: code=${code}, attrName=${attrName}`);
- // console.log("当前 coms:", _this.coms);
- let item = _this.coms.filter((o) => o.name == code);
- // console.log(`找到的模块:`, item);
- if (item.length > 0) {
- let attr = item[0].attrs.filter((o) => o.name == attrName);
- // console.log(`找到的属性:`, attr);
- if (attr.length > 0) {
- // console.log(`返回的值:`, attr[0].content);
- return parseFloat(attr[0].content);
- }
- }
- // console.log("未找到匹配的模块或属性,返回 0");
- return 0;
- },
- async getRemote(formual) {
- let _this = this;
- var pattern = /\[(.*?)\]\[(.*?)\]\[(.*?)\]\[(.*?)\]/;
- var reg = new RegExp(pattern);
- while (true) {
- let items = formual.match(reg);
- if (items == null) break;
- if (items[1] == "R") {
- //表示获取远程数据
- var dataIndex = items[4];
- dataIndex = items[4].split(",");
- let calResult = await _this.getRemoteData(
- items[2],
- items[3],
- dataIndex[0],
- dataIndex[1]
- );
- let itemName = items[0];
- // 检查calResult是否为数字
- if (!isNaN(calResult)) {
- formual = formual.replace(
- itemName,
- "(" + parseFloat(calResult) + ")"
- );
- } else {
- formual = formual.replace(itemName, `"${calResult}"`);
- }
- formual = formual.replace(
- itemName,
- "(" + parseFloat(calResult) + ")"
- );
- }
- }
- return formual;
- },
- async getRemoteData(code, sheet, row, col) {
- let _this = this;
- let result = 0;
- let par = {
- code: code,
- sheetName: sheet,
- row: row,
- col: col,
- };
- /* if (!this.isEditing) {
- this.loading = true;
- this.progress = 0;
- try {
- const updateProgress = setInterval(() => {
- if (this.progress < 90) {
- this.progress += 10;
- }
- }, 100);
- let res = await findData(par);
- if (res.status == 200) {
- result = res.data.result;
- }
- this.progress = 100;
- clearInterval(updateProgress);
- } catch (error) {
- console.error("Error fetching remote data:", error);
- } finally {
- setTimeout(() => {
- this.loading = false;
- this.progress = 0;
- }, 1000);
- }
- } else { */
- // 如果正在编辑,直接获取数据而不显示进度条
- try {
- let res = await findData(par);
- if (res.status == 200) {
- result = res.data.result;
- // 添加数据类型检查和转换
- if (typeof result === "string" && !isNaN(result)) {
- result = parseFloat(result);
- }
- }
- } catch (error) {
- console.error("获取远程数据错误:", error);
- }
- /* } */
- return result;
- },
- /*
- handleItemVal(value) {
- console.log(value);
- this.$forceUpdate();
- }, */
- async handleItemClick(item) {
- const category = this.categoryList.find((cat) => cat.id === item);
- if (!category) return;
- if (!category.children) {
- try {
- const res = await searchTemplateCategory({ parent_id: item });
- if (res.status != 200 || res.data.length == 0) return;
- category.children = res.data;
- for (let i = 0; i < category.children.length; i++) {
- category.children[i].dataList = await this.getTemplateList(
- category.children[i].id
- );
- }
- } catch (error) {
- console.error("Error fetching template categories:", error);
- }
- }
- // 触发视图更新
- this.$set(category, "activeChildren", category.activeChildren || []);
- },
- /* 切换标签 */
- viewDocument() {
- this.showView = 0;
- },
- viewModule() {
- this.showView = 1;
- },
- /* 更新变 */
- /* uptadeVariable(value) {
- for (const item of this.coms) {
- for (const el of item.attrs) {
- if (el.type === "variable") {
- if (el.data.id == value.id) {
- el.content = value.value;
- el.data = value;
- }
- } else if (el.type === "constant") {
- if (el.data.id == value.id) {
- el.content = value.value;
- el.data = value;
- }
- }
- }
- }
- } */
- uptadeVariable(value) {
- const { id, value: newValue } = value;
- this.coms.forEach((item) => {
- item.attrs.forEach((el) => {
- if (
- (el.type === "variable" || el.type === "constant") &&
- el.data.id === id
- ) {
- el.content = newValue;
- el.data = value;
- }
- });
- });
- },
- /* 更新检索内容 */
- async uptadeSearch() {
- for (const item of this.coms) {
- for (const el of item.attrs) {
- if (el.type === "ai") {
- // await this.retrieval(el);
- }
- }
- }
- },
- /* 初始化检索 */
- async retrieval(el) {
- this.loading = true; // 开始加载动画
- try {
- const response = await axios.post(
- "http://58.246.234.210:7860/api/v1/run/3f84a841-cefd-44b3-9555-568cc3b6c2d2?stream=false",
- {
- input_value: el.search,
- output_type: "chat",
- input_type: "chat",
- tweaks: {
- "ChatInput-em6qC": {},
- "ParseData-yO3YQ": {},
- "Prompt-Wj75b": {},
- "ChatOutput-zy9na": {},
- "SplitText-O1knk": {},
- "File-4j6Zd": {},
- "OllamaEmbeddings-xbYXX": {},
- "Chroma-OIejP": {},
- "OllamaModel-04mEO": {},
- "OllamaEmbeddings-UGvLP": {},
- "Chroma-HzukO": {},
- },
- },
- {
- headers: {
- "Content-Type": "application/json",
- },
- }
- );
- if (response.status === 200) {
- // 假设返回的数据在 response.data.outputs[0].outputs[0].results.message.data.text 中
- const resultText =
- response.data.outputs[0].outputs[0].results.message.data.text;
- // 将搜索词和生成的内容存在 searchResult 对象中
- el.content = resultText; // 重新赋值给原数组对应 content
- }
- } catch (error) {
- console.error("Error during retrieval:", error);
- this.$message.error("检索失败,请稍后重试");
- } finally {
- this.loading = false; // 结束加载动画
- }
- },
- async loadTemplateInfo(id) {
- try {
- // 获取模板信息
- const { data } = await getTemplateInfo(id);
- console.log(!data.dcb_attrs || !data.dcb_type);
- // 设置默认值
- if (!data.dcb_attrs || !data.dcb_type) {
- Object.assign(data, {
- dcb_attrs: "[]",
- dcb_nr: "请填写内容",
- lay_id: "textArea",
- dcb_type: "TextArea",
- });
- }
- // 设置文档标题
- document.title = data.name
- ? `${data.name}-${settings.title}`
- : "新建模块-" + settings.title;
- // 解析属性
- data.dcb_attrs = JSON.parse(data.dcb_attrs);
- data.content = data.dcb_nr;
- data.type = data.dcb_type;
- data.name = data.dcb_name;
- data.attrs = data.dcb_attrs;
- // 获取公式并更新属性
- const {
- data: { dataList },
- } = await searchFormula({ page: 1, pageSize: 999 });
- console.log(data);
- data.dcb_attrs = data.dcb_attrs.map((item) => {
- const formula = dataList.find((el) => el.id === item.id);
- return formula
- ? { ...item, formula: formula.formula, data: formula }
- : item;
- });
- // 从 content 中提取 {{}} 包裹的 ID
- const contentIds = (data.dcb_nr.match(/{{([^}]+)}}/g) || []).map(
- (match) => match.slice(2, -2).trim()
- );
- // 过滤 attrs,只保留在 content 中出的 ID
- data.dcb_attrs = data.dcb_attrs.filter((item) =>
- contentIds.includes(item.id)
- );
- this.coms = [data];
- } catch (error) {
- console.error("加载模板信息失败:", error);
- }
- },
- onExport(e) {
- let _this = this;
- _this.comIndex = -1;
- let content = _this.$refs.tabHtml.innerHTML;
- },
- onOpenView(e) {
- console.log("this.coms", this.coms);
- this.showViewForm = true;
- },
- onClose() {
- this.$confirm("是否要关闭文档?", "提示", {
- confirmButtonText: "确定",
- cancelButtonText: "取消",
- type: "warning",
- })
- .then(() => {
- this.$router.back();
- })
- .catch(() => {
- this.$message({
- type: "info",
- message: "已取消",
- });
- });
- },
- loadArticle(e) {
- let _this = this;
- _this.onLoadArticle(e);
- /* getDocumentInfo({
- id: e,
- }).then((res) => {
- if (res.status != 200) return;
- _this.onLoadArticle(res.data);
- }); */
- },
- handleDragStart(e) {
- let data = {};
- if (e.target.dataset.type == "article") {
- let index = e.target.dataset.index;
- data = {
- optType: e.target.dataset.type,
- item: this.articleList[index],
- };
- } else {
- let index = e.target.dataset.index;
- let subIndex = e.target.dataset.subIndex;
- let item = this.categoryList[index].dataList[subIndex];
- delete item.category;
- data = {
- ...item,
- optType: e.target.dataset.type,
- key: "addNew",
- attrs: JSON.parse(item.attrs),
- };
- }
- e.dataTransfer.setData("item", JSON.stringify(data));
- this.operation = "drag";
- },
- onRebuild(comList) {
- try {
- // 深拷贝以避免引用问题
- const newComList = JSON.parse(JSON.stringify(comList));
- // 确保每个组件的属性都被正确处理
- newComList.forEach((com) => {
- // 确保 dcb_attrs 是数组
- if (!Array.isArray(com.dcb_attrs)) {
- com.dcb_attrs = [];
- }
- // 确保 attrs 是数组
- if (!Array.isArray(com.attrs)) {
- com.attrs = [];
- }
- // 处理其他必要的属性
- com.content = com.content || com.dcb_nr || "";
- com.dcb_nr = com.content || com.dcb_nr || "";
- com.type = com.dcb_type || com.type;
- com.name = com.dcb_name || com.name;
- });
- // 更新组件列表
- this.coms = newComList;
- // 保存到本地存储
- this.saveToLocalStorage();
- } catch (error) {
- console.error("重建组件时出错:", error);
- this.$message.error("重建组件失败:" + error.message);
- }
- },
- // 添加一个保存到本地存储的方法
- saveToLocalStorage() {
- try {
- localStorage.setItem("document_coms", JSON.stringify(this.coms));
- } catch (error) {
- console.warn("保存到本地存储失败:", error);
- }
- },
- //初始化当前用户信息
- async initCurrentUser() {
- let _this = this;
- let res = await getCurrentUserInfo();
- if (res.status != 200) return;
- _this.userInfo = res.data;
- },
- //加载文档信息
- async onLoadArticle(id) {
- try {
- this.loading = true;
- // 在加载文档前重置所有模板状态
- this.resetAllTemplateSelections();
- const res = await getDocumentInfo(id);
- if (res.status !== 200) {
- throw new Error("Invalid response status");
- }
- this.docAttr = {
- dcm_id: res.data.dcm_id,
- dcm_type: Number(res.data.dcm_type),
- dcm_category_id: res.data.dcm_category_id,
- dcm_title: res.data.dcm_title,
- content: "",
- status: res.data.status,
- is_template: res.data.is_template,
- linkProduct: res.data.linkProduct,
- links: res.data.links,
- linkProject: res.data.linkProject,
- projects: res.data.projects,
- };
- // 同时更新 docForm
- this.docForm = {
- dcm_title: res.data.dcm_title,
- dcm_type: Number(res.data.dcm_type),
- dcm_category_id: res.data.dcm_category_id, // 确保这个字段也被设置
- };
- const templateData =
- typeof res.data.dcm_data === "string"
- ? JSON.parse(res.data.dcm_data)
- : res.data.dcm_data;
- const updatedComs = await Promise.all(
- templateData.map(async (el) => {
- /* let templateInfo = { data: {} };
- if (this.type !== "document") {
- templateInfo = await getTemplateInfo({ id: el.id });
- } */
- const formulaData = await searchFormula({ page: 1, pageSize: 999 });
- const attrs = el.attrs;
- /* typeof templateInfo.data.attrs === "string"
- ? JSON.parse(templateInfo.data.attrs)
- : templateInfo.data.attrs || []; // Add a fallback empty array */
- attrs.forEach((item) => {
- if (item && item.data && item.data.id) {
- const matchedFormula = formulaData.data.dataList.find(
- (ite) => ite.id === item.data.id
- );
- if (matchedFormula) {
- item.data = matchedFormula;
- item.formula = matchedFormula.formula;
- }
- }
- });
- return { ...el /* , ...templateInfo.data, attrs */ };
- })
- );
- this.coms = updatedComs;
- console.log("coms", updatedComs);
- if (this.type === "document" && this.articleId !== undefined) {
- document.title = `${this.docAttr.title}-${settings.title}`;
- }
- this.uptadeSearch();
- this.initTemplateSelection();
- } catch (error) {
- console.error("Error in onLoadArticle:", error);
- } finally {
- this.loading = false;
- }
- },
- /* 加载模版信息 */
- async onTemplateInfo(id) {
- try {
- this.loading = true;
- // 在加载模板前重置所有模板状态
- this.resetAllTemplateSelections();
- // 获取文档信息
- const res = await getDocumentInfo({ id });
- if (res.status !== 200 || !res.data) {
- throw new Error("无效的响应或未收到数据");
- }
- // 设置文档属性
- this.docAttr = {
- id: this.docAttr.id,
- category_id: Number(this.docAttr.category_id),
- title: res.data.title,
- content: "",
- status: res.data.status,
- is_template: res.data.is_template,
- linkProduct: res.data.linkProduct || [],
- links: res.data.links || "",
- linkProject: res.data.linkProject || [],
- projects: res.data.projects || "",
- };
- // 解析文档数据
- const documentData = res.data.data ? JSON.parse(res.data.data) : [];
- console.log(documentData);
- const updatedComs = await Promise.all(
- documentData.map(async (docEl) => {
- if (!docEl || !docEl.id) {
- console.warn("无效的文档项:", docEl);
- return null;
- }
- // 获取模板信息
- const templateInfo = await getTemplateInfo({ id: docEl.id });
- // 获取公式数据
- const formulaData = await searchFormula({ page: 1, pageSize: 999 });
- // 使用模板的 content 作为基础
- let content = templateInfo.data.content;
- // 使用模板的 attrs 作为基础,排除 Directory 类型
- let attrs = templateInfo.data.attrs
- ? JSON.parse(templateInfo.data.attrs).filter(
- (attr) => attr.type !== "Directory"
- )
- : [];
- // 从文档数据中提取所有 Directory 类型的属性
- const docDirectories = docEl.attrs.filter(
- (attr) => attr.type === "Directory"
- );
- // 将文档中的 Directory 属性添加到 attrs 中
- attrs = [...attrs, ...docDirectories];
- // 解析 content 中的所有项
- const contentItems = (content.match(/{{([^}]+)}}/g) || []).map(
- (match) => match.slice(2, -2)
- );
- console.log("contentItems", contentItems);
- // 确保 content 中引用的所有 Directory 项都存在于 attrs 中
- contentItems.forEach((itemId) => {
- if (
- itemId.startsWith("Directory_") &&
- !attrs.some((attr) => attr.id === itemId)
- ) {
- const [, moduleIndex, level] = itemId.split("_");
- attrs.push({
- type: "Directory",
- id: itemId,
- name: "目录信息",
- intro: "目录信息",
- number: "",
- content: "",
- level: parseInt(level),
- moduleIndex: parseInt(moduleIndex),
- });
- }
- });
- // 更新公式数据
- attrs = attrs.map((item) => {
- if (item.type === "formual" && item.data && item.data.id) {
- const matchedFormula = formulaData.data.dataList.find(
- (ite) => ite.id === item.data.id
- );
- if (matchedFormula) {
- return {
- ...item,
- data: matchedFormula,
- formula: matchedFormula.formula,
- };
- }
- }
- return item;
- });
- // 返回更新后的数据,以模板信息为主,但 Directory 项完全使用文档信息
- return { ...templateInfo.data, attrs, content };
- })
- );
- // 过滤掉无效的组件
- this.coms = updatedComs.filter(Boolean);
- console.log("组件", this.coms);
- console.log("模版", this.docAttr);
- if (this.articleId !== undefined) {
- document.title = `${this.docAttr.title}-${settings.title}`;
- }
- this.uptadeSearch();
- this.initTemplateSelection();
- } catch (error) {
- console.error("加载模板信息时出错:", error);
- this.$message.error("加载模板信息时出错,请稍后重试");
- } finally {
- this.loading = false;
- }
- },
- onRemove(index) {
- const removedComponent = this.coms[index];
- // 移除组件
- this.coms.splice(index, 1);
- // 如果是从模板创建的组件,更新对应模板的选中状态
- if (removedComponent.dcb_id) {
- const template = this.categoryList
- .flatMap((category) => category.templates || [])
- .find((t) => t.dcb_id === removedComponent.dcb_id);
- if (template) {
- this.updateTemplateSelection(template, false);
- }
- }
- },
- /* 目录信息 */
- onCatalogIndex(e) {
- this.catalogIndex = e;
- if (
- (this.docuComIndex =
- 3 || this.comIndex == 9998 || this.AttributeIndex == 1)
- ) {
- this.comIndex = 0;
- this.AttributeIndex = 0;
- this.docuComIndex = 0;
- }
- this.$nextTick(() => {
- this.$forceUpdate();
- });
- },
- onSetActiveIndexs(e) {
- this.docuComIndex = e;
- if (
- this.AttributeIndex == 1 ||
- this.comIndex == 9998 ||
- this.catalogIndex == 9997
- ) {
- this.catalogIndex = 0;
- this.AttributeIndex = 0;
- this.comIndex = 0;
- }
- },
- //设置当前索引
- onSetActiveIndex(e) {
- this.comIndex = e;
- if (
- this.AttributeIndex == 1 ||
- this.docuComIndex == 3 ||
- this.catalogIndex == 9997
- ) {
- this.catalogIndex = 0;
- this.docuComIndex = 0;
- }
- },
- /* 属性变量 */
- onAttributeIndex(e) {
- this.AttributeIndex = e;
- if (
- (this.docuComIndex =
- 3 || this.comIndex == 9998 || this.catalogIndex == 9997)
- ) {
- this.catalogIndex = 0;
- this.comIndex = 0;
- this.docuComIndex = 0;
- }
- },
- /* 更新 */
- renew() {
- let _this = this;
- _this.docVisible = true;
- this.docForm.dcm_title = _this.docAttr.dcm_title;
- this.docForm.dcm_type = _this.docAttr.dcm_type;
- },
- /* 保存 */
- onSaveAs(e) {
- let _this = this;
- if (_this.coms.length <= 0) {
- _this.$alert("请填写内容");
- return;
- }
- _this.docAttr.dcm_id = "";
- _this.docVisible = true;
- this.docForm.dcm_title = _this.docAttr.dcm_title;
- this.docForm.dcm_type = _this.docAttr.dcm_type;
- },
- //保存文档
- onSave(e) {
- let _this = this;
- if (_this.coms.length <= 0) {
- _this.$alert("增加组件");
- return;
- }
- if (_this.docAttr.dcm_type == "" || _this.docAttr.dcm_type <= 0) {
- _this.$alert("请选择文档分类");
- return;
- }
- if (_this.docAttr.dcm_title == "") {
- _this.$alert("请填写文档标题");
- return;
- }
- _this.docAttr.links = JSON.stringify(_this.docAttr.linkProduct);
- _this.docAttr.projects = JSON.stringify(_this.docAttr.linkProject);
- _this.docAttr.dcm_data = JSON.stringify(_this.coms);
- _this.docAttr.is_template = 0;
- /* _this.docAttr.user_name = _this.$store.state.user.name;
- _this.docAttr.user_id = _this.$store.state.user.id; 获取用户id,名称 */
- if (_this.docAttr.dcm_id > 0) {
- updateDocument(_this.docAttr).then((res) => {
- if (res.status !== 200) return; //更新文档
- _this.docAttr.id = res.data;
- _this.$alert("文档更新成功");
- _this.docVisible = false;
- _this.docForm = {
- dcm_title: "",
- dcm_type: "",
- dcm_category_id: "",
- };
- _this.searchArticle();
- });
- } else {
- createDocument(_this.docAttr).then((res) => {
- if (res.status !== 200) return; //保存文档
- _this.docAttr.id = res.data;
- _this.articleId = res.data;
- _this.$alert("文档保存成功");
- _this.docVisible = false;
- _this.docForm = {
- dcm_title: "",
- dcm_type: "",
- dcm_category_id: "",
- };
- _this.searchArticle();
- });
- }
- },
- /*更新 */
- onUpload() {
- let _this = this;
- if (_this.coms.length <= 0) {
- _this.$alert("增加组件");
- return;
- }
- /* if (_this.docAttr.category_id == "" || _this.docAttr.category_id <= 0) {
- _this.$alert("请选择分类");
- return;
- } */
- if (_this.docAttr.title == "") {
- _this.$alert("请填写模版标题");
- return;
- }
- _this.docAttr.links = JSON.stringify(_this.docAttr.linkProduct);
- _this.docAttr.projects = JSON.stringify(_this.docAttr.linkProject);
- _this.docAttr.data = JSON.stringify(_this.coms);
- _this.docAttr.is_template = 1;
- _this.docAttr.id = this.$route.query.articleId;
- /* _this.docAttr.user_name = _this.$store.state.user.name;
- _this.docAttr.user_id = _this.$store.state.user.id; 获取用户id,名称*/
- updateDocument(_this.docAttr).then((res) => {
- if (res.status != 200) return; //更新文档
- _this.docAttr.id = res.data;
- _this.$alert("模版更新成功");
- _this.searchArticle();
- });
- },
- /* 保存并更新版 */
- onSaveUpload(e) {
- let _this = this;
- if (_this.coms.length <= 0) {
- _this.$alert("增加组件");
- return;
- }
- /* if (_this.docAttr.category_id == "" || _this.docAttr.category_id <= 0) {
- _this.$alert("请选择分类");
- return;
- } */
- if (_this.docAttr.title == "") {
- _this.$alert("请填写模版标题");
- return;
- }
- _this.docAttr.links = JSON.stringify(_this.docAttr.linkProduct);
- _this.docAttr.projects = JSON.stringify(_this.docAttr.linkProject);
- _this.docAttr.data = JSON.stringify(_this.coms);
- _this.docAttr.is_template = 1;
- /* _this.docAttr.user_name = _this.$store.state.user.name;
- _this.docAttr.user_id = _this.$store.state.user.id; 获取用户id,名称*/
- /* if (_this.docAttr.id > 0) {
- updateDocument(_this.docAttr).then((res) => {
- if (res.status != 200) return; //更新文档
- _this.docAttr.id = res.data;
- _this.$alert("模版更新成功");
- _this.searchArticle();
- });
- } else { */
- createDocument(_this.docAttr).then((res) => {
- if (res.status != 200) return; //保存文档
- _this.docAttr.id = res.data;
- _this.articleId = res.data;
- _this.$alert("模版保存成功");
- _this.searchArticle();
- });
- /* } */
- },
- //设置组件值
- onSetComs(e) {
- let _this = this;
- _this.coms = [...e];
- },
- onAddLayer(cateIndex, dataIndex) {
- let _this = this;
- let item = _this.categoryList[cateIndex].dataList[dataIndex];
- let data = {
- ...item,
- attrs: JSON.parse(item.attrs),
- };
- delete data.category;
- _this.coms.push(data);
- _this.comIndex = _this.coms.length - 1;
- },
- //处理插入事件
- onInsert(e) {
- let _this = this;
- switch (e.key) {
- case "article": //插入图文
- _this.insertArticle();
- break;
- case "table": //插入图表
- _this.insertTable();
- break;
- case "sourceData": //插入原数据
- _this.insertSourceData(e);
- break;
- case "formual": //插入公式
- _this.insertFormual(e);
- break;
- case "constant": //插入常量
- _this.insertConstant(e);
- break;
- case "variable": //插入变量
- _this.insertVariable(e);
- break;
- case "pager": //插入分页符
- _this.insertPager();
- break;
- case "attr":
- // 直接调用插入逻辑,不再检查 linkProduct
- let com = _this.coms[_this.comIndex];
- if (com && e.content) {
- let data = {
- type: "ProductAttr",
- id: e.content.id,
- dataId: "",
- name: "商品属性",
- intro: "商品属性",
- content: e.content.content || "",
- attrs: e.content.attrs,
- };
- com.attrs.push(data);
- _this.insertCmd = {
- content: "{{" + data.id + "}}",
- };
- // 可选:将产品信息添加到文档关联商品
- if (e.content.attrs.productInfo) {
- const productInfo = e.content.attrs.productInfo;
- if (!_this.docAttr.linkProduct) {
- _this.docAttr.linkProduct = [];
- }
- // 避免重复添加
- if (
- !_this.docAttr.linkProduct.some(
- (p) => p.dcp_p_no === productInfo.dcp_p_no
- )
- ) {
- _this.docAttr.linkProduct.push(productInfo);
- }
- }
- }
- break;
- case "Directory": //插入主题
- _this.insertDirectory(e);
- break;
- case "addNew": //插入新记录
- _this.insertNew(e);
- break;
- case "InsertNull":
- _this.insertVal();
- break;
- case "ai": //插入ai
- _this.insertAI(e);
- break;
- }
- },
- /* 插入空值 */
- insertVal() {
- let _this = this;
- if (_this.comIndex < 0) {
- _this.$alert("请选择插入图层");
- return false;
- }
- let com = _this.coms[_this.comIndex];
- let uniqueId = "val" + Date.now(); // 使用时间戳创建唯一ID
- let data = {
- type: "variableNull",
- id: uniqueId,
- dataId: "",
- name: "非变量",
- intro: "",
- content: "请输入",
- data: "",
- };
- com.attrs.push(data);
- if (com.type == "TextArea") {
- //如果是图文,更新内容
- _this.insertCmd = {
- content: "{{" + data.id + "}}",
- };
- } else {
- //仅对图表中插入有效
- if (_this.comIndex >= 0) {
- _this.setTableData(data.id);
- }
- }
- },
- /* 插入ai */
- insertAI(e) {
- let _this = this;
- if (_this.comIndex < 0) {
- _this.$alert("请选择插入图层");
- return false;
- }
- let com = _this.coms[_this.comIndex];
- let data = {
- type: "ai",
- id: "ai" + (com.attrs.length + 1),
- dataId: "",
- name: "AI",
- intro: "插入AI",
- content: e.content.result,
- search: e.content.searchTerm,
- };
- com.attrs.push(data);
- if (com.type == "TextArea") {
- //如果是图文,更新内容
- _this.insertCmd = {
- content: "{{" + data.id + "}}",
- };
- }
- },
- insertProductAttr() {
- let _this = this;
- if (_this.comIndex < 0) {
- _this.$alert("请选择插入图层");
- return false;
- }
- let com = _this.coms[_this.comIndex];
- if (!com) {
- _this.$alert("请先添加文档内容");
- return false;
- }
- // 允许直接插入产品属性,移除原有的限制检查
- this.showProductAttr = true;
- },
- //插入目录
- insertDirectory(e) {
- if (this.comIndex < 0) {
- this.$message.warning("请选择插入图层");
- return;
- }
- const com = this.coms[this.comIndex];
- const currentLevel = e.content.level || 1;
- try {
- // 生成目录编号和内容
- const { number, content } = this.generateDirectoryItem(
- this.comIndex,
- currentLevel
- );
- console.log(number);
- const directoryItem = {
- type: "Directory",
- id: `Directory_${this.comIndex}_${currentLevel}_${Date.now()}`,
- name: "目录信息",
- intro: "目录信息",
- number,
- content: content || "新建目录项",
- level: currentLevel,
- moduleIndex: this.comIndex,
- };
- com.attrs.push(directoryItem);
- // 更新文本内容
- this.insertCmd = {
- content: `{{${directoryItem.id}}}`,
- };
- // 更新目录树
- this.updateCatalog(this.coms);
- // 强制更新视图
- this.$nextTick(() => {
- this.$forceUpdate();
- });
- } catch (error) {
- console.error("Error inserting directory:", error);
- this.$message.error("插入目录失败,请重试");
- }
- },
- // 添加 findParentNumber 方法
- findParentNumber(moduleIndex, level) {
- if (level <= 1) {
- return (moduleIndex + 1).toString();
- }
- const module = this.coms[moduleIndex];
- if (!module || !module.attrs) return "";
- // 获取所有目录类型的属性并按编号排序
- const directories = module.attrs
- .filter((attr) => attr.type === "Directory" && attr.level < level)
- .sort((a, b) => {
- const aNum = a.number.split(".").map(Number);
- const bNum = b.number.split(".").map(Number);
- for (let i = 0; i < Math.min(aNum.length, bNum.length); i++) {
- if (aNum[i] !== bNum[i]) return aNum[i] - bNum[i];
- }
- return aNum.length - bNum.length;
- });
- // 找到最近的上级目录
- const parentDir = directories[directories.length - 1];
- return parentDir ? parentDir.number : (moduleIndex + 1).toString();
- },
- // 修改 generateDirectoryItem 方法
- generateDirectoryItem(moduleIndex, level) {
- const module = this.coms[moduleIndex];
- const existingDirs = module.attrs.filter(
- (attr) => attr.type === "Directory" && attr.level === level
- );
- const parentNumber = this.findParentNumber(moduleIndex, level);
- const siblingCount = existingDirs.length;
- let number;
- if (level === 1) {
- number = (moduleIndex + 1).toString();
- } else {
- number = `${parentNumber}.${siblingCount + 1}`;
- }
- return {
- number,
- content: `第${number}章`, // 默认内容
- };
- },
- // 插入新记录
- insertNew(e) {
- this.coms.push(e);
- // 如果是从模板拖拽的,更新模板选中状态
- if (e.dcb_id) {
- const template = this.categoryList
- .flatMap((category) => category.templates || [])
- .find((t) => t.dcb_id === e.dcb_id);
- if (template) {
- this.updateTemplateSelection(template, true);
- }
- }
- },
- //插入分页
- insertPager() {
- let _this = this;
- if (_this.comIndex < 0) {
- _this.$alert("请选择插入图层");
- return false;
- }
- let com = _this.coms[_this.comIndex];
- let data = {
- type: "pager",
- id: "pager" + (com.attrs.length + 1),
- name: "分页符",
- intor: "强制分页",
- content: "",
- };
- com.attrs.push(data);
- if (com.type == "TextArea") {
- //如果是图文,更新内容
- _this.insertCmd = {
- content: "<div>{{" + data.id + "}}</div>",
- };
- }
- },
- //插入图文
- insertArticle() {
- /* let _this = this;
- _this.coms.push({
- type: "TextArea",
- lay_id: "textArea",
- code: "模块名",
- name: "图文",
- intro: "图文介绍",
- isEdit: 2,
- content: "请填写内容",
- attrs: [],
- });
- _this.comIndex = _this.coms.length - 1; */
- let _this = this;
- let newArticle = {
- type: "TextArea",
- lay_id: "textArea",
- code: "模块名",
- name: "图文",
- intro: "图文介绍",
- isEdit: 2,
- content: "请填写内容",
- attrs: [],
- };
- _this.coms.push(newArticle);
- _this.comIndex = _this.coms.length - 1;
- // 添加一些日志来帮助调试
- console.log("New article added:", newArticle);
- console.log("Current coms:", _this.coms);
- console.log("New comIndex:", _this.comIndex);
- },
- //插入表格
- insertTable() {
- let _this = this;
- _this.coms.push({
- type: "Table",
- lay_id: "Table",
- code: "模块名",
- name: "图表名称",
- intro: "图表介绍",
- isEdit: 2,
- tableHeader: this.initTableHeader(),
- tableData: [{}],
- htmlData: "",
- attrs: [],
- });
- _this.comIndex = _this.coms.length - 1;
- },
- initTableHeader() {
- var start = 65;
- var data = [];
- for (var i = start; i <= start + 25; i++) {
- data.push(String.fromCharCode(i));
- }
- return data;
- },
- //插入变量
- insertConstant(e) {
- let _this = this;
- // console.log("insertconstant");
- if (_this.comIndex < 0) {
- _this.$alert("请选择插入图层");
- return false;
- }
- let com = _this.coms[_this.comIndex];
- let data = {
- type: "constant",
- id: e.content.code + (com.attrs.length + 1),
- dataId: e.id,
- name: e.content.code,
- intro: e.content.intro,
- content: e.content.value,
- data: e.content,
- };
- com.attrs.push(data);
- if (com.type == "TextArea") {
- //如果是图文,更新内容
- _this.insertCmd = {
- content: "{{" + data.id + "}}",
- };
- } else {
- //仅对图表中插入有效
- if (_this.comIndex >= 0) {
- _this.setTableData(data.id);
- }
- }
- },
- //插入变量
- insertVariable(e) {
- let _this = this;
- if (_this.comIndex < 0) {
- _this.$alert("请选择插入图层");
- return false;
- }
- let com = _this.coms[_this.comIndex];
- let data = {
- type: "variable",
- id: e.content.code + (com.attrs.length + 1),
- dataId: e.id,
- name: e.content.code,
- intro: e.content.intro,
- content: e.content.value,
- data: e.content,
- };
- com.attrs.push(data);
- if (com.type == "TextArea") {
- //如果是图文,更新内容
- _this.insertCmd = {
- content: "{{" + data.id + "}}",
- };
- } else {
- //仅对图表中插入有效
- if (_this.comIndex >= 0) {
- _this.setTableData(data.id);
- }
- }
- },
- //插入原数据
- insertSourceData(e) {
- let _this = this;
- if (_this.comIndex < 0) {
- _this.$alert("请选择插入图层");
- return false;
- }
- let com = _this.coms[_this.comIndex];
- let data = {
- type: "sourceData",
- id: "sourceData" + (com.attrs.length + 1),
- dataId: "",
- name: "源数据",
- intro: "插入源数据",
- formula:
- "[R][" +
- e.content.tb +
- "][" +
- e.content.sheet +
- "][" +
- e.content.r +
- "," +
- e.content.c +
- "]",
- content: e.content.value,
- data: e.content,
- };
- com.attrs.push(data);
- if (com.type == "TextArea") {
- //如果是图文,更新内容
- _this.insertCmd = {
- content: "{{" + data.id + "}}",
- };
- }
- },
- //插入公式
- insertFormual(e) {
- let _this = this;
- if (_this.comIndex < 0) {
- _this.$alert("请选择插入图层");
- return false;
- }
- let com = _this.coms[_this.comIndex];
- let data = {
- type: "formual",
- id: "formual" + (com.attrs.length + 1),
- dataId: e.id,
- name: e.content.name,
- intro: e.content.intro,
- formula: e.content.formula,
- content: 0,
- data: e.content,
- };
- com.attrs.push(data);
- if (com.type == "TextArea") {
- //如果是图文,更新内容
- _this.insertCmd = {
- content: "{{" + data.id + "}}",
- };
- } else {
- //仅对图表中插入有效
- if (_this.comIndex >= 0) {
- _this.setTableData(data.id);
- }
- }
- },
- //获取模版分类信息
- async initCategoryList() {
- let _this = this;
- try {
- let res = await searchTemplateCategory({
- page: 1,
- pageSize: 99,
- parent_id: 0,
- status: 5,
- });
- if (res.status != 200) return;
- // 处理分类数据
- _this.categoryList = await Promise.all(
- res.data.dataList.map(async (category) => {
- // 获取该分类下的模板列表
- const templates = await _this.getTemplateList(category.id);
- // 只保留category_id与当前分类id匹配的模板
- const filteredTemplates = templates.filter(
- (template) => template.category_id === category.id
- );
- return {
- ...category,
- templates: filteredTemplates.map((template) => ({
- ...template,
- selected: false, // 添加选中状态
- })),
- };
- })
- );
- // 过滤掉没有模板的分类
- _this.categoryList = _this.categoryList.filter(
- (category) => category.templates && category.templates.length > 0
- );
- console.log("处理后的分类数据:", _this.categoryList);
- } catch (error) {
- console.error("初始化分类列表失败:", error);
- }
- },
- //获取模版列表
- async getTemplateList(categoryId) {
- let _this = this;
- let res = await searchTemplate({
- page: 1,
- pageSize: 999,
- category_id: categoryId,
- status: 5,
- });
- if (res.status != 200) return [];
- let dataList = res.data.dataList.map((item) => {
- try {
- // 处理属性值
- if (item.dcb_attrs) {
- // 如果存在 dcb_attrs,优先使用它并确保正确解析
- item.attrs =
- typeof item.dcb_attrs === "string"
- ? JSON.parse(item.dcb_attrs)
- : item.dcb_attrs;
- } else if (!item.attrs) {
- // 如果既没有 dcb_attrs 也没有 attrs,设置为空数组
- item.attrs = [];
- } else {
- // 如果有 attrs 但是是字符串,解析它
- item.attrs =
- typeof item.attrs === "string"
- ? JSON.parse(item.attrs)
- : item.attrs;
- }
- // 确保 content 存在
- item.content = item.dcb_nr || item.content || "";
- // 从 content 中提取所有 {{}} 包裹的 ID
- const contentIds = (item.content.match(/{{([^}]+)}}/g) || []).map(
- (match) => match.slice(2, -2).trim()
- );
- // 只在有 contentIds 时进行过滤
- if (contentIds.length > 0) {
- item.attrs = Array.isArray(item.attrs)
- ? item.attrs.filter(
- (attr) => attr && attr.id && contentIds.includes(attr.id)
- )
- : [];
- }
- // 确保 attrs 是数组
- if (!Array.isArray(item.attrs)) {
- item.attrs = [];
- }
- } catch (error) {
- console.error("Error processing template item:", error, item);
- item.attrs = [];
- }
- return item;
- });
- console.log("处理后的数据列表:", dataList);
- return dataList;
- },
- //获取文档模板列表
- async searchArticle() {
- try {
- // 获取文档分类
- const categoryRes = await searchDocumentCategory({
- page: 1,
- pageSize: 999,
- });
- if (categoryRes.status !== 200) return;
- // 获取文档列表
- const documentRes = await pageDocument({
- page: 1,
- pageSize: 99,
- isContentShow: true,
- });
- if (documentRes.status !== 200) return;
- // 处理数据为树形结构
- this.schemeData = categoryRes.data.dataList.map((category) => ({
- label: category.name,
- id: category.id,
- children: documentRes.data.dataList
- .filter((doc) => doc.dcm_category_id === category.id)
- .map((doc) => ({
- label: doc.dcm_title,
- id: doc.dcm_id,
- type: "document",
- })),
- }));
- // 更新默认展开的节点 - 展开所有分类
- this.expandedKeys = this.schemeData.map((category) => category.id);
- console.log("Processed schemeData:", this.schemeData);
- } catch (error) {
- console.error("Error processing document data:", error);
- this.$message.error("获取文档数据失败");
- }
- },
- // 添加模板选择处理方法
- /* handleTemplateSelect(category, template, value) {
- template.selected = value;
- console.log("Selected template:", {
- category: category.name,
- template: template.dcb_name,
- selected: value,
- });
- // 这里可以添加其他选择逻辑
- }, */
- // 检查模板是否已被使用
- isTemplateUsed(template) {
- const isUsed = this.coms.some((com) => com.dcb_id === template.dcb_id);
- if (isUsed) {
- // 如果模板被使用,设置 selected 为 true
- template.selected = true;
- // 同步其他分类中相同模板的选中状态
- this.categoryList.forEach((category) => {
- const sameTemplate = category.templates?.find(
- (t) => t.dcb_id === template.dcb_id
- );
- if (sameTemplate) {
- sameTemplate.selected = true;
- }
- });
- }
- /* return isUsed; */
- },
- // 处理模板选择
- handleTemplateSelect(category, template, isSelected) {
- // 更新模板选中状态
- template.selected = isSelected;
- if (isSelected) {
- // 如果是选中,添加到组件列表
- /* const newComponent = {
- ...template,
- type: template.dcb_type || "TextArea",
- lay_id: template.lay_id || "textArea",
- content: template.dcb_nr || "",
- attrs:
- typeof template.dcb_attrs === "string"
- ? JSON.parse(template.dcb_attrs)
- : template.dcb_attrs || [],
- };
- this.coms.push(newComponent); */
- } else {
- // 如果取消选中,从组件列表中移除
- /* const index = this.coms.findIndex(
- (com) => com.dcb_id === template.dcb_id
- );
- if (index !== -1) {
- this.coms.splice(index, 1);
- } */
- }
- // 同步其他分类中相同模板的选中状态
- this.categoryList.forEach((cat) => {
- if (cat.id !== category.id) {
- const sameTemplate = cat.templates?.find(
- (t) => t.dcb_id === template.dcb_id
- );
- if (sameTemplate) {
- sameTemplate.selected = isSelected;
- }
- }
- });
- },
- // 初始化模板选中状态
- initTemplateSelection() {
- // 先重置所有选中状态
- this.resetAllTemplateSelections();
- // 然后根据已渲染组件更新选中状态
- this.coms.forEach((com) => {
- this.categoryList.forEach((category) => {
- const template = category.templates?.find(
- (t) => t.dcb_id === com.dcb_id
- );
- if (template) {
- template.selected = true;
- }
- });
- });
- },
- // 修改后的 handleDragEnd 方法
- handleDragEnd(evt) {
- // 检查是否是克隆操作
- if (!evt || !evt.item || evt.pullMode !== "clone") {
- return;
- }
- // 获取拖拽的数据
- const draggedData = evt.item.dataset;
- if (!draggedData) {
- return;
- }
- // 从拖拽的DOM元素中获取模板ID
- const templateId = evt.item.getAttribute("data-template-id");
- if (!templateId) {
- return;
- }
- // 查找对应的模板
- const draggedTemplate = this.categoryList
- .flatMap((category) => category.templates || [])
- .find((template) => template.dcb_id === templateId);
- if (draggedTemplate) {
- this.updateTemplateSelection(draggedTemplate, true);
- }
- },
- // 更新模板选中状态的通用方法
- updateTemplateSelection(template, isSelected) {
- // 更新所有分类中相同模板的选中状态
- this.categoryList.forEach((category) => {
- const sameTemplate = category.templates?.find(
- (t) => t.dcb_id === template.dcb_id
- );
- if (sameTemplate) {
- sameTemplate.selected = isSelected;
- }
- });
- },
- // 添加重置所有模板选中状态的方法
- resetAllTemplateSelections() {
- this.categoryList.forEach((category) => {
- if (category.templates) {
- category.templates.forEach((template) => {
- template.selected = false;
- });
- }
- });
- },
- // 处理搜索
- async handleSearch() {
- if (!this.searchKey.trim()) {
- return;
- }
- try {
- this.loading = true;
- const res = await pageDocument({
- page: 1,
- pageSize: 999,
- dcm_title: this.searchKey.trim(),
- });
- if (res.status === 200) {
- // 更新树形数据
- const searchResults = res.data.dataList.map((doc) => ({
- id: doc.dcm_id,
- label: doc.dcm_title,
- children: null,
- }));
- const searchResultNode = {
- id: "search-result", // 为搜索结果节点添加唯一ID
- label: "搜索结果",
- children: searchResults,
- };
- // 更新树形数据
- this.schemeData = [
- searchResultNode,
- /* ...this.schemeData.filter(item => item.label !== "搜索结果") */
- ];
- // 更新需要展开的节点keys
- this.expandedKeys = [
- "search-result", // 展开搜索结果分类
- ...searchResults.map((item) => item.id), // 展开所有搜索结果项
- ];
- // 强制更新树形组件
- this.$nextTick(() => {
- if (this.$refs.documentTree) {
- this.$refs.documentTree.store.defaultExpandedKeys =
- this.expandedKeys;
- this.$refs.documentTree.updateKeyChildren();
- }
- });
- // 如果没有搜索结果,显示提示
- if (searchResults.length === 0) {
- this.$message.info("未找到匹配的文档");
- }
- }
- } catch (error) {
- console.error("搜索文档失败:", error);
- this.$message.error("搜索失败,请重试");
- } finally {
- this.loading = false;
- }
- },
- // 修改清空处理方法
- async handleClear() {
- this.searchKey = "";
- this.expandedKeys = []; // 清空展开的节点
- await this.searchArticle();
- // 重置树形组件的展开状态
- this.$nextTick(() => {
- if (this.$refs.documentTree) {
- this.$refs.documentTree.store.defaultExpandedKeys = [];
- this.$refs.documentTree.updateKeyChildren();
- }
- });
- },
- // 添加搜索处理方法
- async handleResourceSearch() {
- /* const searchKey = this.resourceSearchKey.toLowerCase().trim();
-
- // 遍历所有分类
- this.categoryList.forEach(category => {
- if (category.templates) {
- // 过滤模板列表
- const filteredTemplates = category.templates.filter(template =>
- template.dcb_name.toLowerCase().includes(searchKey)
- );
-
- // 使用 Vue.set 确保响应式更新
- this.$set(category, 'templates', filteredTemplates);
- }
- }); */
- if (!this.templateSearchKey.trim()) {
- return;
- }
- try {
- // 调用搜索模板接口
- const res = await searchTemplate({
- page: 1,
- pageSize: 999,
- dcb_name: this.templateSearchKey.trim(),
- });
- if (res.status === 200) {
- // 保存当前分类的原始模板
- this.originalTemplateList = [...this.categoryList];
- // 处理搜索结果
- const searchResults = res.data.dataList.map((template) => {
- // 确保模板数据格式正确
- if (!template.attrs) {
- template.attrs = "[]";
- }
- try {
- template.attrs =
- typeof template.attrs === "string"
- ? JSON.parse(template.attrs)
- : template.attrs;
- } catch (error) {
- console.error("Error parsing template attrs:", error);
- template.attrs = [];
- }
- return template;
- });
- // 更新分类列表,将搜索结果放在一个特殊分类下
- this.categoryList = [
- {
- id: "search-results",
- name: "搜索结果",
- templates: searchResults.map((template) => ({
- ...template,
- selected: this.coms.some(
- (com) => com.dcb_id === template.dcb_id
- ),
- })),
- },
- ];
- }
- } catch (error) {
- console.error("搜索模板失败:", error);
- this.$message.error("搜索失败,请重试");
- }
- },
- // 添加清除搜索处理方法
- handleResourceClear() {
- // 重置搜索并恢复原始列表
- this.resourceSearchKey = "";
- this.initCategoryList();
- },
- // 处理模板搜索
- async handleTemplateSearch() {
- /* if (!this.templateSearchKey.trim()) {
- return;
- } */
- console.log(12);
- try {
- // 调用搜索模板接口
- const res = await searchTemplate({
- page: 1,
- pageSize: 999,
- dcb_name: this.templateSearchKey.trim(),
- });
- if (res.status === 200) {
- // 保存当前分类的原始模板
- this.originalTemplateList = [...this.categoryList];
- // 处理搜索结果
- const searchResults = res.data.dataList.map((template) => {
- // 确保模板数据格式正确
- if (!template.attrs) {
- template.attrs = "[]";
- }
- try {
- template.attrs =
- typeof template.attrs === "string"
- ? JSON.parse(template.attrs)
- : template.attrs;
- } catch (error) {
- console.error("Error parsing template attrs:", error);
- template.attrs = [];
- }
- return template;
- });
- // 更新分类列表,将搜索结果放在一个特殊分类下
- this.categoryList = [
- {
- id: "search-results",
- name: "搜索结果",
- templates: searchResults.map((template) => ({
- ...template,
- selected: this.coms.some(
- (com) => com.dcb_id === template.dcb_id
- ),
- })),
- },
- ];
- }
- } catch (error) {
- console.error("搜索模板失败:", error);
- this.$message.error("搜索失败,请重试");
- }
- },
- // 清空搜索
- async handleTemplateClear() {
- this.templateSearchKey = "";
- // 如果有保存的原始列表,恢复它
- if (this.originalTemplateList.length > 0) {
- this.categoryList = [...this.originalTemplateList];
- } else {
- // 否则重新初始化分类列表
- await this.initCategoryList();
- }
- },
- // 添加一个用于检查产品是否已关联的方法
- isProductLinked(dcp_p_no) {
- return (
- this.docAttr.linkProduct &&
- this.docAttr.linkProduct.some((p) => p.dcp_p_no === dcp_p_no)
- );
- },
- // 修改文档属性更新方法
- updateDocAttr() {
- // ... 其他代码保持不变 ...
- if (this.docAttr.linkProduct && this.docAttr.linkProduct.length > 0) {
- this.docAttr.links = JSON.stringify(this.docAttr.linkProduct);
- }
- // ... 其他代码保持不变 ...
- },
- // 添加或修改以下方法
- getCategory(categoryId) {
- // 处理数组格式的categoryId
- if (Array.isArray(categoryId)) {
- categoryId = categoryId[categoryId.length - 1]; // 获取数组最后一个值
- }
- // 如果没有categoryId,直接返回空字符串
- if (!categoryId) return "";
- const findCategory = (list) => {
- if (!list || !Array.isArray(list)) return null;
- for (const category of list) {
- // 确保进行数字比较
- if (
- Number(category.id) === Number(categoryId) ||
- Number(category.dcb_category_id) === Number(categoryId)
- ) {
- return category.name || category.dcb_name;
- }
- // 检查templates
- if (category.templates) {
- const template = category.templates.find(
- (t) =>
- Number(t.dcb_category_id) === Number(categoryId) ||
- Number(t.category_id) === Number(categoryId)
- );
- if (template) {
- return category.name;
- }
- }
- // 递归检查子分类
- if (category.children) {
- const found = findCategory(category.children);
- if (found) return found;
- }
- }
- return null;
- };
- // 在分类列表中查找
- const categoryName = findCategory(this.categoryList);
- // 如果找到分类名称则返回,否则返回格式化后的分类ID
- return categoryName || (categoryId ? String(categoryId) : "");
- },
- // 添加目录编号更新方法
- updateDirectoryNumbers() {
- this.coms.forEach((com, moduleIndex) => {
- if (com.attrs) {
- // 获取当前模块中的所有目录类型属性
- const directoryAttrs = com.attrs.filter(
- (attr) => attr.type === "Directory"
- );
- // 更新每个目录的编号
- directoryAttrs.forEach((dir, index) => {
- // 生成新的编号
- const number = this.generateLevelPrefix(moduleIndex, dir.level);
- // 更新目录编号
- this.$set(dir, "number", number);
- });
- }
- });
- },
- // 简化拖拽完成处理
- onDragComplete() {
- this.$nextTick(() => {
- // 只在存在目录类型的属性时才更新编号
- if (
- this.coms.some(
- (com) =>
- com.attrs && com.attrs.some((attr) => attr.type === "Directory")
- )
- ) {
- this.updateDirectoryNumbers();
- }
- // 触发重建事件
- this.$emit("onRebuild", this.coms);
- });
- },
- // 简化拖拽结束处理
- onDragEnd() {
- // 可以添加其他拖拽结束后的处理逻辑
- this.$forceUpdate();
- },
- // 简化添加处理
- onAdd(evt) {
- console.log("Added new module:", evt.added);
- this.$nextTick(() => {
- if (
- this.coms.some(
- (com) =>
- com.attrs && com.attrs.some((attr) => attr.type === "Directory")
- )
- ) {
- this.updateDirectoryNumbers();
- }
- this.$emit("onRebuild", this.coms);
- });
- },
- // 保存模板
- async onSaveTemplate(item) {
- let data = {};
- // 遍历原始对象,只保留 dcb_ 开头的属性
- Object.keys(item).forEach((key) => {
- if (key.startsWith("dcb_")) {
- data[key] = item[key];
- }
- });
- // 特殊字段映射
- data.dcb_nr = item.content;
- data.dcb_attrs = JSON.stringify(item.attrs);
- data.dcb_type = item.type;
- data.dcb_name = item.name;
- // 处理分类ID
- if (Array.isArray(item.category_id)) {
- data.category_id = item.category_id[item.category_id.length - 1];
- } else {
- data.category_id = item.category_id;
- }
- data.status = 5;
- try {
- if (!item.dcb_id || this.saveAs) {
- const res = await createTemplate(data);
- if (res.code === 200) {
- item.id = res.data;
- this.$alert("模块信息保存成功");
- this.saveAs = false;
- }
- } else {
- const res = await updateTemplate(data);
- if (res.code === 200) {
- this.$alert("模块信息更新成功");
- }
- }
- item.selDisabled = false;
- item.valDisabled = false;
- this.$forceUpdate();
- } catch (error) {
- console.error("保存模板失败:", error);
- this.$message.error("保存失败:" + error.message);
- }
- },
- // 编辑/预览切换
- async onEdit(index, state) {
- try {
- if (this.isSaving) return;
- this.isSaving = true;
- // 保存当前组件的完整数据
- const currentCom = JSON.parse(JSON.stringify(this.coms[index]));
- if (state === 2) {
- // 从编辑切换到预览
- const componentRef = this.$refs[`textArea${index}`];
- if (componentRef && componentRef[0]) {
- await componentRef[0].save();
- }
- }
- // 更新编辑状态
- this.coms = this.coms.map((it, idx) => {
- if (idx === index) {
- return {
- ...currentCom, // 保持原有属性
- isEdit: state,
- attrs: currentCom.attrs || [], // 确保attrs不会丢失
- dcb_attrs: currentCom.dcb_attrs || [], // 确保dcb_attrs不会丢失
- };
- }
- return {
- ...it,
- isEdit: 2,
- };
- });
- // 更新当前索引
- this.comIndex = index;
- // 触发重建
- await this.onRebuild(this.coms);
- } catch (error) {
- /* console.error("切换模式失败:", error);
- this.$message.error("切换模式失败:" + error.message); */
- } finally {
- this.isSaving = false;
- }
- },
- // 删除模块
- onRemoveMdel(index) {
- const removedComponent = this.coms[index];
-
- this.$confirm('确认删除该模块?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }).then(() => {
- // 从组件数组中移除
- this.coms.splice(index, 1);
-
- // 如果删除的组件来自模板,更新对应模板的选中状态
- if (removedComponent.dcb_id) {
- // 遍历所有分类查找对应的模板
- this.categoryList.forEach(category => {
- const template = (category.templates || []).find(t => t.dcb_id === removedComponent.dcb_id);
- if (template) {
- // 取消模板的选中状态
- this.updateTemplateSelection(template, false);
- template.selected = false;
- }
- });
- }
-
- this.$message({
- type: 'success',
- message: '删除成功!'
- });
- }).catch(() => {
- this.$message({
- type: 'info',
- message: '已取消删除'
- });
- });
- },
- // 过滤属性
- filterAttrs(item) {
- if (!item.content && !item.dcb_nr) return;
- // 保存原始属性
- const originalAttrs = item.attrs || [];
- const originalDcbAttrs = item.dcb_attrs || [];
- // 从内容中提取ID
- const contentIds = (
- (item.content || item.dcb_nr).match(/{{([^}]+)}}/g) || []
- ).map((match) => match.slice(2, -2).trim());
- if (contentIds.length > 0) {
- // 只过滤掉确实不存在的ID
- item.attrs = originalAttrs.filter(
- (attr) =>
- attr &&
- (contentIds.includes(attr.id) ||
- attr.type === "ProductAttr" || // 保留特殊类型属性
- attr.type === "variableNull")
- );
- if (item.dcb_attrs) {
- item.dcb_attrs = originalDcbAttrs.filter(
- (attr) =>
- attr &&
- (contentIds.includes(attr.id) ||
- attr.type === "ProductAttr" ||
- attr.type === "variableNull")
- );
- }
- }
- },
- handleDragStart(event, data) {
- // 只允许拖拽一级目录
- if (data.level !== 1) {
- event.preventDefault();
- return;
- }
- // 存储被拖拽的目录项和对应的模块索引
- event.dataTransfer.setData(
- "text/plain",
- JSON.stringify({
- moduleIndex: data.moduleIndex,
- label: data.label,
- })
- );
- },
- handleDrop(event, targetData) {
- event.preventDefault();
- try {
- const dragData = JSON.parse(event.dataTransfer.getData("text/plain"));
- const sourceIndex = dragData.moduleIndex;
- const targetIndex = targetData.moduleIndex;
- // 确保是不同位置的拖放
- if (sourceIndex === targetIndex) {
- return;
- }
- // 1. 移动模块
- const movedModule = this.coms.splice(sourceIndex, 1)[0];
- this.coms.splice(targetIndex, 0, movedModule);
- // 2. 更新所有模块的目录编号
- this.updateDirectoryNumbers();
- // 3. 重新生成目录数据
- this.handleClick({ name: "catalog" });
- } catch (error) {
- console.error("Drop handling error:", error);
- }
- },
- updateDirectoryNumbers() {
- this.coms.forEach((module, moduleIndex) => {
- const directoryAttrs = module.attrs.filter(
- (attr) => attr.type === "Directory"
- );
- directoryAttrs.forEach((attr) => {
- // 更新目录的模块索引
- attr.moduleIndex = moduleIndex;
- // 更新目录编号
- const numbers = attr.number.split(".");
- numbers[0] = (moduleIndex + 1).toString();
- attr.number = numbers.join(".");
- // 更新显示的标签
- attr.content = attr.content.replace(/^\d+/, moduleIndex + 1);
- });
- });
- },
- allowDrop(draggingNode, dropNode, type) {
- // 只允许同级之间的拖放,不允许嵌套
- return type !== "inner";
- },
- allowDrag(draggingNode) {
- return draggingNode.level === 1;
- },
- handleDragEnd(event) {
- // 处理拖拽结束事件
- console.log("Drag end:", event);
- },
- // 处理拖拽结束事件
- handleDragEnd(draggingNode, dropNode, dropType) {
- if (!dropNode || !dropType) {
- console.log("无效的拖放操作");
- return;
- }
- console.log("拖拽节点:", draggingNode.data);
- console.log("目标节点:", dropNode.data);
- console.log("放置类型:", dropType);
- // 获取源模块和目标模块的索引
- const sourceIndex = draggingNode.data.moduleIndex;
- const targetIndex = dropNode.data.moduleIndex;
- if (typeof sourceIndex !== "number" || typeof targetIndex !== "number") {
- console.error("无法确定模块索引");
- return;
- }
- // 计算最终目标位置
- let finalTargetIndex = targetIndex;
- // 根据放置类型调整目标位置
- if (dropType === "next") {
- finalTargetIndex++;
- }
- // 如果源位置在目标位置之前,需要调整目标位置
- if (sourceIndex < finalTargetIndex) {
- finalTargetIndex--;
- }
- console.log("移动模块:", {
- from: sourceIndex,
- to: finalTargetIndex,
- type: dropType,
- });
- // 执行模块移动
- const [movedModule] = this.coms.splice(sourceIndex, 1);
- this.coms.splice(finalTargetIndex, 0, movedModule);
- // 更新所有模块的编号和目录结构
- this.$nextTick(() => {
- this.updateModulesAndDirectories();
- // 强制更新视图
- this.$forceUpdate();
- });
- },
- // 改进的查找模块索引方法
- findModuleIndex(nodeData) {
- console.log("查找模块索引:", nodeData);
- // 首先尝试使用直接的moduleIndex
- if (typeof nodeData.moduleIndex === "number") {
- return nodeData.moduleIndex;
- }
- // 然后尝试从编号中获取索引
- if (nodeData.number) {
- const moduleNumber = parseInt(nodeData.number.split(".")[0]);
- if (!isNaN(moduleNumber)) {
- // 因为编号是从1开始的,所以需要减1来获取索引
- return moduleNumber - 1;
- }
- }
- // 最后尝试在coms数组中查找匹配的模块
- return this.coms.findIndex((module) => {
- const directoryAttr = module.attrs?.find((attr) => {
- if (attr.type !== "Directory") return false;
- if (attr.level !== 1) return false;
- // 尝试多种匹配方式
- if (attr.id === nodeData.id) return true;
- if (attr.moduleIndex === nodeData.moduleIndex) return true;
- if (attr.number && nodeData.number && attr.number === nodeData.number)
- return true;
- return false;
- });
- return !!directoryAttr;
- });
- },
- // 更新模块和目录结构
- updateModulesAndDirectories() {
- console.log("开始更新模块和目录结构");
- console.log("更新前的模块列表:", JSON.parse(JSON.stringify(this.coms)));
- this.coms.forEach((module, moduleIndex) => {
- if (!module.attrs) return;
- const directoryAttrs = module.attrs.filter(
- (attr) => attr.type === "Directory"
- );
- directoryAttrs.forEach((attr) => {
- // 更新模块索引
- attr.moduleIndex = moduleIndex;
- // 更新编号
- const numbers = attr.number.split(".");
- numbers[0] = (moduleIndex + 1).toString();
- const newNumber = numbers.join(".");
- // 更新属性
- attr.number = newNumber;
- // 更新内容
- if (attr.content) {
- const contentParts = attr.content.split(" ");
- contentParts[0] = newNumber;
- attr.content = contentParts.join(" ");
- }
- });
- });
- console.log("更新后的模块列表:", JSON.parse(JSON.stringify(this.coms)));
- // 重新生成目录树
- this.$nextTick(() => {
- this.handleClick({ name: "catalog" });
- });
- },
- // 生成目录树数据
- generateCatalogData() {
- // 这里应该是你原有的生成目录数据的逻辑
- // 确保调用正确的方法来更新目录视图
- this.handleClick({ name: "catalog" });
- },
- toggleSchemePanel() {
- this.isSchemeCollapsed = !this.isSchemeCollapsed;
- },
- toggleResourcePanel() {
- this.isResourceCollapsed = !this.isResourceCollapsed;
- },
- // 更新目录结构
- updateCatalog(coms) {
- try {
- if (!Array.isArray(coms) || coms.length === 0) {
- this.catalogData = [];
- return;
- }
- let catalogData = [];
- coms.forEach((item, moduleIndex) => {
- if (!item || !item.attrs) return;
- // 获取所有Directory类型的属性并排序
- const directoryAttrs = item.attrs
- .filter((attr) => attr && attr.type === "Directory")
- .sort((a, b) => {
- if (!a || !b) return 0;
- return (a.number || "").localeCompare(b.number || "", undefined, {
- numeric: true,
- });
- });
- directoryAttrs.forEach((attr) => {
- if (!attr) return;
- // 确保目录内容正确显示
- const content = attr.content || attr.name || "";
- const number = this.generateDirectoryNumber(
- moduleIndex,
- attr.level
- );
- const catalogItem = {
- id: `${moduleIndex}-${attr.id || ""}`,
- label: `${number} ${content}`.trim(),
- level: attr.level || 1,
- moduleIndex: moduleIndex,
- number: number,
- children: [],
- };
- // 更新原始属性的编号和内容
- attr.number = number;
- attr.content = content;
- // 根据level确定目录层级
- if (attr.level === 1) {
- catalogData.push(catalogItem);
- } else {
- const parent = this.findParentDirectory(catalogData, number);
- if (parent) {
- parent.children = parent.children || [];
- parent.children.push(catalogItem);
- }
- }
- });
- });
- // 更新目录数据
- this.catalogData = this.sortCatalogData(catalogData);
- // 更新原始组件中的目录信息
- this.updateComponentDirectories(coms);
- } catch (error) {
- console.error("Error updating catalog:", error);
- this.catalogData = [];
- }
- },
- // 生成目录编号
- generateDirectoryNumber(moduleIndex, level) {
- let number = "";
- if (level === 1) {
- // 一级标题使用模块序号
- number = (moduleIndex + 1).toString();
- } else {
- // 查找父级目录编号
- const parentNumber = this.findParentNumber(moduleIndex, level);
- // 获取当前级别的计数
- const siblings = this.getSiblingDirectories(
- moduleIndex,
- level,
- parentNumber
- );
- const currentCount = siblings.length + 1;
- // 组合编号
- number = `${parentNumber}.${currentCount}`;
- }
- return number;
- },
- // 获取同级目录项
- getSiblingDirectories(moduleIndex, level, parentNumber) {
- const siblings = [];
- // 遍历所有模块查找同级目录
- for (let i = 0; i < moduleIndex; i++) {
- const module = this.coms[i];
- if (module.attrs) {
- module.attrs.forEach((attr) => {
- if (
- attr.type === "Directory" &&
- attr.level === level &&
- attr.number.startsWith(parentNumber)
- ) {
- siblings.push(attr);
- }
- });
- }
- }
- return siblings;
- },
- // 更新组件中的目录信息
- updateComponentDirectories(coms) {
- coms.forEach((com, moduleIndex) => {
- if (!com.attrs) return;
- com.attrs.forEach((attr) => {
- if (attr.type === "Directory") {
- // 更新目录编号
- const number = this.generateDirectoryNumber(
- moduleIndex,
- attr.level
- );
- attr.number = number;
- // 确保内容正确显示
- if (!attr.content || attr.content.includes("未命名目录")) {
- attr.content = attr.name || `第${number}章`;
- }
- // 更新moduleIndex
- attr.moduleIndex = moduleIndex;
- }
- });
- });
- },
- // 处理拖拽结束后的更新
- handleDragEnd(draggingNode, dropNode, dropType) {
- if (!dropNode || !dropType) {
- console.log("无效的拖放操作");
- return;
- }
- // 获取源模块和目标模块的索引
- const sourceIndex = this.findModuleIndex(draggingNode.data);
- const targetIndex = this.findModuleIndex(dropNode.data);
- if (typeof sourceIndex !== "number" || typeof targetIndex !== "number") {
- console.error("无法确定模块索引");
- return;
- }
- // 计算最终目标位置
- let finalTargetIndex = targetIndex;
- if (dropType === "next") {
- finalTargetIndex++;
- }
- if (sourceIndex < finalTargetIndex) {
- finalTargetIndex--;
- }
- // 执行模块移动
- const [movedModule] = this.coms.splice(sourceIndex, 1);
- this.coms.splice(finalTargetIndex, 0, movedModule);
- // 更新目录结构
- this.$nextTick(() => {
- this.updateCatalog(this.coms);
- this.$forceUpdate();
- });
- },
- // 改进的查找父目录方法
- findParentDirectory(catalogData, number) {
- if (!number || !number.includes(".")) return null;
- const parentNumber = number.split(".").slice(0, -1).join(".");
- const findInItems = (items) => {
- for (let item of items) {
- if (item.number === parentNumber) {
- return item;
- }
- if (item.children && item.children.length > 0) {
- const found = findInItems(item.children);
- if (found) return found;
- }
- }
- return null;
- };
- return findInItems(catalogData);
- },
- // 高亮当前选中的目录项
- highlightCurrentCatalogItem(moduleIndex) {
- if (!this.$refs.catalogTree) return;
- const findNode = (data) => {
- for (let item of data) {
- if (item.moduleIndex === moduleIndex) {
- this.$refs.catalogTree.setCurrentKey(item.id);
- return true;
- }
- if (item.children && item.children.length) {
- if (findNode(item.children)) return true;
- }
- }
- return false;
- };
- findNode(this.catalogData);
- },
- // 处理目录项点击
- handleCatalogClick(data) {
- // 如果正在编辑,不触发其他操作
- if (data.isEditing) return;
- // 其他点击处理逻辑...
- console.log("点击的目录项:", data);
- },
- // 处理组件内容更新
- onSetComs(newComs) {
- this.coms = newComs;
- this.updateCatalog(newComs);
- },
- // 处理拖拽结束后的目录更新
- handleDragEnd() {
- this.$nextTick(() => {
- this.updateCatalog(this.coms);
- });
- },
- // 添加 sortCatalogData 方法
- sortCatalogData(catalogData) {
- if (!Array.isArray(catalogData)) {
- return [];
- }
- // 递归排序函数
- const sortItems = (items) => {
- return items
- .sort((a, b) => {
- // 按照编号进行数字排序
- const aNum = a.number.split(".").map(Number);
- const bNum = b.number.split(".").map(Number);
- // 比较每一级的编号
- for (let i = 0; i < Math.min(aNum.length, bNum.length); i++) {
- if (aNum[i] !== bNum[i]) {
- return aNum[i] - bNum[i];
- }
- }
- // 如果前面的编号都相同,较短的编号在前
- return aNum.length - bNum.length;
- })
- .map((item) => {
- // 递归排序子目录
- if (item.children && item.children.length > 0) {
- item.children = sortItems(item.children);
- }
- return item;
- });
- };
- // 对顶层目录进行排序
- return sortItems(catalogData);
- },
- // 添加允许拖拽和放置的方法
- allowDrag(node) {
- // 允许所有节点拖拽
- return true;
- },
- allowDrop(draggingNode, dropNode, type) {
- // 不允许跨级拖拽,只允许同级拖拽
- return draggingNode.data.level === dropNode.data.level;
- },
- handleDragEnd(draggingNode, dropNode, dropType, ev) {
- if (!dropNode) return;
- // 获取拖拽节点和目标节点的模块索引
- const dragModuleIndex = draggingNode.data.moduleIndex;
- const dropModuleIndex = dropNode.data.moduleIndex;
- // 如果是同一级目录的拖拽
- if (draggingNode.data.level === dropNode.data.level) {
- // 更新模块顺序
- const dragModule = this.coms[dragModuleIndex];
- this.coms.splice(dragModuleIndex, 1);
- // 根据放置类型确定插入位置
- const targetIndex =
- dropType === "before" ? dropModuleIndex : dropModuleIndex + 1;
- this.coms.splice(targetIndex, 0, dragModule);
- // 重新生成目录编号
- this.updateDirectoryNumbers();
- }
- },
- // 更新目录编号的方法
- updateDirectoryNumbers() {
- this.coms.forEach((module, moduleIndex) => {
- const directories = module.attrs.filter(
- (attr) => attr.type === "Directory"
- );
- directories.forEach((dir) => {
- const { level } = dir;
- const { number, content } = this.generateNumberedContent(
- moduleIndex,
- level
- );
- dir.number = number;
- // 只更新编号部分,保留原有内容
- dir.content = dir.content.replace(/^[\d.]+/, number);
- });
- });
- // 强制更新视图
- this.$nextTick(() => {
- this.updateCatalog(this.coms);
- this.$forceUpdate();
- });
- },
- // 开始编辑目录
- handleStartEdit(data) {
- // 设置编辑状态和临时编辑内容
- this.$set(data, "isEditing", true);
- this.$set(
- data,
- "editingContent",
- data.label.split(" ").slice(1).join(" ")
- ); // 只编辑内容部分,保留编号
- // 等待DOM更新后聚焦输入框
- this.$nextTick(() => {
- if (this.$refs.editInput && this.$refs.editInput[0]) {
- this.$refs.editInput[0].focus();
- }
- });
- },
- // 完成编辑
- handleEditComplete(data) {
- if (!data.isEditing) return;
- // 获取原始编号
- const number = data.label.split(" ")[0];
- // 更新目录树节点的显示文本
- data.label = `${number} ${data.editingContent}`;
- // 更新对应模块的目录属性
- const { moduleIndex } = data;
- const module = this.coms[moduleIndex];
- if (module) {
- const directoryAttr = module.attrs.find(
- (attr) => attr.type === "Directory" && attr.number === number
- );
- if (directoryAttr) {
- directoryAttr.content = data.editingContent;
- }
- }
- // 清除编辑状态
- this.$delete(data, "isEditing");
- this.$delete(data, "editingContent");
- // 强制更新视图
- this.$forceUpdate();
- },
- // 添加新方法:更新目录显示
- updateDirectoryDisplay(com) {
- // 按级别和编号排序目录
- const directories = com.attrs
- .filter((attr) => attr.type === "Directory")
- .sort((a, b) => {
- if (a.level !== b.level) return a.level - b.level;
- return a.number.localeCompare(b.number, undefined, { numeric: true });
- });
- // 更新每个目录的显示内容
- directories.forEach((dir) => {
- const pattern = new RegExp(`{{${dir.id}}}`, "g");
- com.content = com.content.replace(
- pattern,
- `${dir.number} {{${dir.id}}}`
- );
- });
- },
- handleDirectoryDragEnd(event, data) {
- // 处理拖拽结束事件
- console.log("Drag end:", event);
- this.handleDirectorySave(data);
- },
- // ... existing code ...
- /* 插入产品属性 */
- onInsertProductAttr(e) {
- if (this.comIndex < 0) {
- this.$message.warning("请选择插入图层");
- return false;
- }
- const com = this.coms[this.comIndex];
- if (!com) {
- this.$message.warning("请先添加文档内容");
- return false;
- }
- // 生成唯一ID
- const attrId = `ProductAttr_${Date.now()}`;
- const data = {
- type: "ProductAttr",
- id: attrId,
- name: "商品属性",
- intro: "商品属性",
- content: e.content || "",
- attrs: e.attrs || {},
- };
- // 添加到组件属性中
- com.attrs.push(data);
- // 更新文本内容
- this.insertCmd = {
- content: `{{${attrId}}}`,
- };
- // 如果有产品信息,添加到文档关联商品
- if (e.productInfo) {
- if (!this.docAttr.linkProduct) {
- this.docAttr.linkProduct = [];
- }
- // 避免重复添加
- if (
- !this.docAttr.linkProduct.some(
- (p) => p.dcp_p_no === e.productInfo.dcp_p_no
- )
- ) {
- this.docAttr.linkProduct.push(e.productInfo);
- }
- }
- // 关闭产品属性选择框(如果有的话)
- this.showProductAttr = false;
- // 强制更新视图
- this.$nextTick(() => {
- this.$forceUpdate();
- });
- return true;
- },
- // 添加一个解析目录内容的方法
- parseDirectoryContent(content) {
- if (!content) return "";
- // 匹配 {{Directory_x_x_xxxxxxxxxx}} 格式的内容
- const directoryPattern = /{{(Directory_\d+_\d+_\d+)}}/g;
- return content.replace(directoryPattern, (match, directoryId) => {
- // 遍历所有组件查找对应的目录项
- for (const com of this.coms) {
- const directoryAttr = com.attrs.find(
- (attr) => attr.type === "Directory" && attr.id === directoryId
- );
- if (directoryAttr) {
- // 返回格式化的目录内容:编号 + 内容
- return `${directoryAttr.number} ${directoryAttr.content}`;
- }
- }
- return match; // 如果找不到对应的目录项,保持原样
- });
- },
- // 修改预览处理方法
- handlePreview() {
- this.showViewForm = true;
- // 处理预览内容
- const previewContent = this.coms.map((com) => {
- // 深拷贝以避免修改原始数据
- const previewCom = JSON.parse(JSON.stringify(com));
- // 如果有内容字段,处理目录内容
- if (previewCom.content) {
- previewCom.content = this.parseDirectoryContent(previewCom.content);
- }
- // 处理属性中的目录内容
- if (previewCom.attrs) {
- previewCom.attrs = previewCom.attrs.map((attr) => {
- if (attr.type === "Directory") {
- return {
- ...attr,
- content: `${attr.number} ${attr.content}`,
- };
- }
- return attr;
- });
- }
- return previewCom;
- });
- // 更新预览数据
- this.previewData = previewContent;
- },
- // 在 ViewForm 组件中添加内容解析
- // 确保 ViewForm 组件接收并正确处理目录内容
- },
- };
- </script>
- <style lang="scss">
- @import "./create.scss";
- .el-collapse,
- .el-collapse-item__wrap {
- border: none;
- }
- .el-collapse,
- .el-collapse-item__header {
- border: none;
- .el-collapse-item__arrow {
- margin: 0;
- }
- }
- .borderless-collapse {
- border: none;
- ::v-deep .el-collapse-item__header,
- ::v-deep .el-collapse-item__wrap,
- ::v-deep .el-collapse-item__content,
- ::v-deep .el-collapse-item {
- border: none;
- }
- ::v-deep .el-collapse-item__wrap {
- border-bottom: none !important;
- }
- }
- .scrollable-container {
- overflow-x: auto;
- white-space: nowrap;
- width: 350px;
- padding-bottom: 10px;
- }
- .min-width-content {
- /* display: inline-block;
- vertical-align: top; */
- min-width: 150px;
- white-space: normal;
- }
- // 树节点样式调整
- ::v-deep .el-tree-node__content {
- height: 32px;
- &:hover {
- background-color: #f5f7fa;
- }
- }
- ::v-deep .el-tree-node.is-current > .el-tree-node__content {
- background-color: #f0f7ff;
- color: #409eff;
- }
- /*.el-collapse-item {
- display: inline-block;
- vertical-align: top;
- } */
- .resource-list {
- .resource-category {
- margin-bottom: 10px;
- .category-title {
- font-weight: bold;
- margin-bottom: 5px;
- color: #606266;
- }
- .resource-items {
- padding-left: 20px;
- .resource-item {
- margin: 5px 0;
- .el-checkbox {
- display: flex;
- align-items: center;
- }
- }
- }
- }
- }
- .template-content {
- .search-box {
- padding: 10px;
- border-bottom: 1px solid #ebeef5;
- .el-input {
- width: 300px;
- }
- }
- }
- .module-list-container {
- width: 320px;
- margin-top: 110px;
- /* position: absolute;
- top: 135px;
- right: 111px; */
- /* border: 1px solid #dcdfe6; */
- border-radius: 4px;
- padding: 10px;
- .module-item {
- display: flex;
- align-items: center;
- padding: 10px;
- border-bottom: 1px solid #ebeef5;
- &:last-child {
- border-bottom: none;
- }
- &.active-module {
- background-color: #f5f7fa;
- }
- .drag-handle {
- cursor: move;
- margin-right: 15px;
- }
- .module-info {
- flex: 1;
- .module-category,
- .module-name {
- display: flex;
- align-items: center;
- margin-bottom: 5px;
- &:last-child {
- margin-bottom: 0;
- }
- .label {
- color: #606266;
- margin-right: 10px;
- min-width: 70px;
- }
- .value {
- color: #303133;
- }
- }
- }
- }
- }
- .custom-tree-node {
- cursor: move;
- user-select: none;
- }
- .custom-tree-node[draggable="false"] {
- cursor: default;
- }
- /* 拖拽时的视觉反馈 */
- .is-drop-inner {
- border: 2px dashed #409eff;
- }
- .left_scheme,
- .natural {
- transition: width 0.3s;
- overflow: hidden;
- &.collapsed {
- width: 50px !important;
- .scheme-header,
- .resource-header-title {
- padding: 10px;
- .title,
- .title-left {
- display: none;
- }
- .el-icon-menu {
- margin-left: 0;
- }
- }
- }
- .el-icon-menu {
- cursor: pointer;
- padding: 5px;
- transition: transform 0.3s;
- &:hover {
- color: #409eff;
- }
- }
- &.collapsed .el-icon-menu {
- transform: rotate(180deg);
- }
- }
- .catalog-content {
- .el-tree {
- background: transparent;
- .el-tree-node__content {
- height: auto;
- padding: 8px 0;
- &:hover {
- background-color: rgba(64, 158, 255, 0.1);
- }
- }
- .custom-tree-node {
- flex: 1;
- display: flex;
- align-items: center;
- padding-right: 8px;
- font-size: 14px;
- i {
- margin-right: 5px;
- }
- }
- }
- }
- // 添加模块高亮动画
- @keyframes highlight-pulse {
- 0% {
- background-color: transparent;
- }
- 50% {
- background-color: rgba(64, 158, 255, 0.2);
- }
- 100% {
- background-color: transparent;
- }
- }
- .highlight {
- animation: highlight-pulse 2s ease-in-out;
- }
- /* 添加到组件的 <style> 部分 */
- .leftContent {
- .el-tree {
- .el-tree-node {
- position: relative;
- /* 为每个节点添加左侧垂直线 */
- &:before {
- content: "";
- position: absolute;
- left: 8px; /* 调整线条位置 */
- top: 0;
- bottom: 0;
- width: 2px;
- background-color: #1aad19; /* 线条颜色 */
- z-index: 1;
- }
- /* 移除最后一个子节点的垂直线延伸 */
- &:last-child:before {
- height: 20px; /* 调整到节点中心位置 */
- }
- /* 为每个节点添加水平连接线 */ /* 与垂直线对齐 */ /* 水平线长度 */
- /* .el-tree-node__content:before {
- content: "";
- position: absolute;
- left: 8px;
- top: 50%;
- width: 16px;
- height: 2px;
- background-color: #1aad19;
- z-index: 1;
- } */
- }
- /* 移除根节点的垂直线 */
- & > .el-tree-node:before {
- display: none;
- }
- /* 移除第一层节点的连接线 */
- & > .el-tree-node > .el-tree-node__content:before {
- display: none;
- }
- /* 调整节点内容的位置,为线条留出空间 */
- .el-tree-node__content {
- position: relative;
- /* 调整缩进 */
- }
- /* 确保展开箭头在正确位置 */
- .el-tree-node__expand-icon {
- padding: 6px;
- margin-left: 10px;
- }
- }
- }
- /* 自定义树节点样式 */
- .custom-tree-node {
- flex: 1;
- display: flex;
- align-items: center;
- padding: 0 8px;
- font-size: 14px;
- /* 编辑输入框样式 */
- .el-input {
- margin-left: -4px;
- }
- }
- .custom-tree-node {
- flex: 1;
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding-right: 8px;
- }
- .directory-actions {
- opacity: 0;
- transition: opacity 0.2s;
- }
- .custom-tree-node:hover .directory-actions {
- opacity: 1;
- }
- .module-actions {
- display: flex;
- gap: 8px; /* 按钮之间的间距 */
- align-items: center;
- white-space: nowrap;
- flex-direction: column;
- }
- .module-actions .el-button {
- padding: 3px 0;
- margin-left: 0;
- }
- </style>
|