1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618 |
- <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="onRemove(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;
- }
- },
- // 删除模块
- onRemove(index) {
- console.log(index);
- this.$confirm("此操作将删除该模块, 是否继续?", "提示", {
- confirmButtonText: "确定",
- cancelButtonText: "取消",
- type: "warning",
- })
- .then(() => {
- this.coms.splice(index, 1);
- this.$emit("onRebuild", this.coms);
- })
- .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>
|