index.vue 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. <template>
  2. <div class="flex h-full w-full flex-col">
  3. <div
  4. class="__hover flex items-center text-sm text-[var(--czr-main-color)]"
  5. @click="toBack"
  6. >
  7. <SvgIcon
  8. name="czr_arrow"
  9. rotate="180"
  10. size="13"
  11. :active="true"
  12. class="mr-1"
  13. />应用中心
  14. </div>
  15. <div class="bm-main-box mt-4">
  16. <div class="grid h-full w-full grid-cols-3 gap-4">
  17. <div
  18. class="col-span-2 flex flex-col gap-2 overflow-hidden rounded-lg bg-[#F6F8FC] p-4"
  19. >
  20. <div
  21. class="flex h-14 w-full items-center gap-2.5 rounded-lg bg-[#ffffff] px-6"
  22. >
  23. <div class="text-2xl font-bold text-[#303133]">编排</div>
  24. <div class="text-[#576275]" v-if="state.autoSaveTimestamp">
  25. 自动保存{{ state.autoSaveTimestamp }}
  26. </div>
  27. <div class="mx-auto" />
  28. <div
  29. class="flex items-center text-[var(--czr-error-color)]"
  30. v-if="state.autoSaveTimestamp"
  31. >
  32. <SvgIcon
  33. name="czr_tip"
  34. color="var(--czr-error-color)"
  35. class="mr-1"
  36. />
  37. 有未发布的修改
  38. </div>
  39. <CzrButton type="primary" title="发布" @click="onPublish" />
  40. <el-popover
  41. :show-arrow="false"
  42. width="26rem"
  43. placement="bottom-end"
  44. :popper-style="{
  45. padding: 0,
  46. }"
  47. >
  48. <template #reference>
  49. <div
  50. class="__hover flex h-8 w-8 items-center justify-center rounded-sm border-1 border-[var(--czr-main-color)]"
  51. >
  52. <SvgIcon name="history" :active="true" size="16" />
  53. </div>
  54. </template>
  55. <div>
  56. <div
  57. class="flex h-11 w-full items-center bg-[url('@/assets/images/knowledge/knowledge-back-test.png')] bg-[length:100%_100%] bg-no-repeat px-4 text-base font-bold text-[#303133]"
  58. >
  59. 历史版本
  60. </div>
  61. <div class="h-[68vh] overflow-y-auto px-4 py-2">
  62. <template v-for="(item, index) in state.history">
  63. <div class="flex">
  64. <div
  65. class="relative mr-3 flex flex-col items-center justify-center"
  66. >
  67. <div
  68. class="h-[50%] w-0.5"
  69. :class="`${index > 0 ? 'bg-[#DEE9FF]' : ''}`"
  70. />
  71. <div
  72. class="h-[50%] w-0.5"
  73. :class="`${index < state.history.length - 1 ? 'bg-[#DEE9FF]' : ''}`"
  74. />
  75. <div
  76. class="absolute flex size-2 items-center justify-center rounded bg-[var(--czr-main-color)]"
  77. >
  78. <div class="size-1 rounded bg-[#DEE9FF]" />
  79. </div>
  80. </div>
  81. <div
  82. class="my-2 flex flex-1 items-center justify-between rounded-lg bg-[#F4F8FF] px-4 py-3"
  83. >
  84. <div
  85. class="text-base font-bold"
  86. :class="{
  87. 'text-[var(--czr-success-color)]':
  88. item.type === 'publish' || item.type === 'apply',
  89. 'text-[var(--czr-warning-color)]':
  90. item.type === 'submit',
  91. 'text-[#2E3238]': item.type === 'create',
  92. }"
  93. >
  94. {{ item.type }}
  95. </div>
  96. <div class="text-[#909399]">{{ item.date }}</div>
  97. </div>
  98. </div>
  99. </template>
  100. </div>
  101. </div>
  102. </el-popover>
  103. </div>
  104. <CzrForm class="form" ref="ref_form">
  105. <div class="grid h-full flex-1 grid-cols-2 gap-4">
  106. <div class="col-span-1 flex flex-col rounded-lg bg-[#ffffff]">
  107. <div
  108. class="flex h-12 w-full items-center gap-2.5 bg-[url('@/assets/images/knowledge/knowledge-back-test.png')] bg-[length:100%_100%] bg-no-repeat px-6"
  109. >
  110. <div class="mr-auto font-bold text-[#303133]">提示词</div>
  111. <CzrButton
  112. type="normal"
  113. title="保存为模板"
  114. @click="onAddTipsTemplate"
  115. />
  116. <CzrButton
  117. type="normal"
  118. title="使用模板"
  119. @click="onTipsTemplate"
  120. />
  121. </div>
  122. <div class="flex-1 p-4">
  123. <textarea
  124. class="h-full w-full"
  125. style="resize: none; line-height: 1.4"
  126. ref="ref_tips"
  127. v-model="state.form.tips"
  128. ></textarea>
  129. </div>
  130. </div>
  131. <div
  132. class="col-span-1 overflow-y-auto rounded-lg bg-[#ffffff] p-4"
  133. >
  134. <div class="__czr-title_2">模型选择</div>
  135. <div class="mt-4">
  136. <CzrFormColumn
  137. class="__czr-table-form-column"
  138. required
  139. label="模型选择"
  140. :span="24"
  141. v-model:param="state.form.model.name"
  142. placeholder="点击选择模型"
  143. readonly
  144. @click="onModel"
  145. default-error-msg="请选择模型"
  146. />
  147. </div>
  148. <div class="__czr-title_2 mt-4">
  149. 组件
  150. <template v-if="state.form.components.length > 0">
  151. ({{ state.form.components.length }})
  152. </template>
  153. <!-- <CzrButton type="normal" title="新增" class="ml-auto" />-->
  154. </div>
  155. <template v-if="state.form.components.length > 0"> </template>
  156. <template v-else>
  157. <div
  158. class="mt-2 flex h-8 items-center justify-center rounded-sm bg-[#F6F8FC] text-xs text-[#A7ADB9]"
  159. >
  160. 暂未添加组件
  161. </div>
  162. </template>
  163. <div class="__czr-title_2 mt-4">
  164. 知识库
  165. <template v-if="state.form.knowledges.length > 0">
  166. ({{ state.form.knowledges.length }})
  167. </template>
  168. <CzrButton
  169. type="normal"
  170. title="新增"
  171. class="ml-auto"
  172. @click="onAddKnowledge"
  173. />
  174. </div>
  175. <template v-if="state.form.knowledges.length > 0">
  176. <div
  177. class="mt-2 flex max-h-42 flex-col gap-2 overflow-y-auto pr-2"
  178. >
  179. <template v-for="(item, index) in state.form.knowledges">
  180. <div class="flex items-center gap-1.5">
  181. <div
  182. class="flex flex-1 items-center overflow-hidden rounded-sm bg-[#F6F8FC] p-2.5"
  183. >
  184. <img
  185. src="@/assets/images/knowledge/knowledge-item-icon.png"
  186. class="mr-4 size-6"
  187. />
  188. <div
  189. class="flex-1 text-sm font-bold text-[#2E3238]"
  190. v-title
  191. >
  192. {{ item.name }}
  193. </div>
  194. </div>
  195. <SvgIcon
  196. class="__hover"
  197. name="czr_del"
  198. color="var(--czr-error-color)"
  199. @click="state.form.knowledges.splice(index, 1)"
  200. />
  201. </div>
  202. </template>
  203. </div>
  204. </template>
  205. <template v-else>
  206. <div
  207. class="mt-2 flex h-8 items-center justify-center rounded-sm bg-[#F6F8FC] text-xs text-[#A7ADB9]"
  208. >
  209. 暂未添加知识库
  210. </div>
  211. </template>
  212. <div class="__czr-title_2 mt-4">
  213. 工作流
  214. <template v-if="state.form.workflows.length > 0">
  215. ({{ state.form.workflows.length }})
  216. </template>
  217. <CzrButton
  218. type="normal"
  219. title="新增"
  220. class="ml-auto"
  221. @click="onAddWorkflow"
  222. />
  223. </div>
  224. <template v-if="state.form.workflows.length > 0">
  225. <div
  226. class="mt-2 flex max-h-42 flex-col gap-2 overflow-y-auto pr-2"
  227. >
  228. <template v-for="(item, index) in state.form.workflows">
  229. <div class="flex items-center gap-1.5">
  230. <div
  231. class="flex flex-1 items-center overflow-hidden rounded-sm bg-[#F6F8FC] p-2.5"
  232. >
  233. <img
  234. src="@/assets/images/workflow/workflow-default-icon.png"
  235. class="mr-4 size-15"
  236. />
  237. <div
  238. class="flex flex-1 flex-col gap-2 overflow-hidden"
  239. >
  240. <div
  241. class="text-sm font-bold text-[#2E3238]"
  242. v-title
  243. >
  244. {{ item.name }}
  245. </div>
  246. <div
  247. class="text-sm text-[#6F7889]"
  248. v-title="{ lines: 2 }"
  249. >
  250. {{ item.description }}
  251. </div>
  252. </div>
  253. </div>
  254. <SvgIcon
  255. class="__hover"
  256. name="czr_del"
  257. color="var(--czr-error-color)"
  258. @click="state.form.workflows.splice(index, 1)"
  259. />
  260. </div>
  261. </template>
  262. </div>
  263. </template>
  264. <template v-else>
  265. <div
  266. class="mt-2 flex h-8 items-center justify-center rounded-sm bg-[#F6F8FC] text-xs text-[#A7ADB9]"
  267. >
  268. 暂未添加工作流
  269. </div>
  270. </template>
  271. <div class="__czr-title_2 mt-4">开场白</div>
  272. <div class="mt-4">
  273. <CzrFormColumn
  274. class="__czr-table-form-column"
  275. required
  276. label-width="0px"
  277. :span="24"
  278. v-model:param="state.form.prologue"
  279. link="rich"
  280. :height="300"
  281. default-error-msg="请输入开场白"
  282. />
  283. </div>
  284. <div class="__czr-title_2 mt-4">
  285. 开场白引导问题
  286. <template v-if="state.form.prologueQuestions.length > 0">
  287. ({{ state.form.prologueQuestions.length }})
  288. </template>
  289. <div class="ml-auto">
  290. <el-radio-group
  291. v-model="state.form.prologueType"
  292. size="small"
  293. >
  294. <el-radio-button value="three">显示前3条</el-radio-button>
  295. <el-radio-button value="all">显示全部</el-radio-button>
  296. </el-radio-group>
  297. </div>
  298. </div>
  299. <div class="mt-2 flex flex-col">
  300. <div
  301. class="drag-body col relative flex max-h-42 flex-col gap-2 overflow-y-auto pr-2"
  302. ref="ref_prologueBody"
  303. v-if="state.dragRefresh"
  304. >
  305. <template
  306. v-for="(item, index) in state.form.prologueQuestions"
  307. >
  308. <div
  309. class="flex items-center gap-2"
  310. style="-webkit-user-drag: element"
  311. >
  312. <SvgIcon
  313. name="czr_drag"
  314. color="#999999"
  315. class="drag-icon cursor-move"
  316. />
  317. <div
  318. class="__hover flex h-7 flex-1 items-center rounded-sm bg-[#F6F8FC] px-2.5 text-sm text-[#A7ADB9]"
  319. @click="onPrologue(item)"
  320. >
  321. <template v-if="item.__edit">
  322. <CzrFormColumn
  323. ref="ref_prologue"
  324. class="transparent-input"
  325. label-width="0px"
  326. :span="24"
  327. v-model:param="item.__value"
  328. :transparent="true"
  329. :clearable="false"
  330. maxlength="40"
  331. show-word-limit
  332. @keyup.enter.stop="onEditPrologue(item)"
  333. @blur="onEditPrologue(item)"
  334. />
  335. </template>
  336. <template v-else> {{ item.value }} </template>
  337. </div>
  338. <SvgIcon
  339. class="__hover"
  340. name="czr_del"
  341. color="var(--czr-error-color)"
  342. @click="state.form.prologueQuestions.splice(index, 1)"
  343. />
  344. </div>
  345. </template>
  346. </div>
  347. <div class="mt-2 flex items-center gap-2">
  348. <div
  349. class="__hover flex h-7 flex-1 items-center rounded-sm bg-[#F6F8FC] px-2.5 text-sm text-[#A7ADB9]"
  350. @click="onPrologue(null)"
  351. >
  352. <template v-if="state.prologuesAdd.__edit">
  353. <CzrFormColumn
  354. ref="ref_prologue"
  355. class="transparent-input"
  356. label-width="0px"
  357. :span="24"
  358. v-model:param="state.prologuesAdd.value"
  359. :transparent="true"
  360. :clearable="false"
  361. maxlength="40"
  362. show-word-limit
  363. @keyup.enter.stop="onAddPrologue"
  364. @blur="state.prologuesAdd.__edit = false"
  365. />
  366. </template>
  367. <template v-else> 点击输入问题,enter以新增 </template>
  368. </div>
  369. </div>
  370. </div>
  371. <div class="__czr-title_2 mt-4">用户输入方式</div>
  372. <div class="mt-4">
  373. <CzrFormColumn
  374. class="__czr-table-form-column"
  375. required
  376. label="输入方式"
  377. :span="24"
  378. v-model:param="state.form.method"
  379. link="select"
  380. :options="[
  381. { value: 1, label: '文字/语音输入' },
  382. { value: 2, label: '语音通话' },
  383. ]"
  384. :clearable="false"
  385. />
  386. <div
  387. class="mt-4 flex items-center"
  388. v-if="state.form.method == 2"
  389. >
  390. <div class="flex-1">
  391. <CzrFormColumn
  392. class="__czr-table-form-column"
  393. required
  394. label="语音包"
  395. :span="24"
  396. v-model:param="state.form.voicePackage"
  397. link="select"
  398. :options="[
  399. { value: 1, label: '语音包1' },
  400. { value: 2, label: '语音包2' },
  401. ]"
  402. :clearable="false"
  403. >
  404. <template #row="{ row }">
  405. <div class="flex h-full items-center">
  406. {{ row.label }}
  407. <div
  408. class="__hover ml-auto text-[var(--czr-main-color)]"
  409. @click.stop=""
  410. >
  411. 试听
  412. </div>
  413. </div>
  414. </template>
  415. </CzrFormColumn>
  416. </div>
  417. <div
  418. class="__hover ml-4 text-sm text-[var(--czr-main-color)]"
  419. >
  420. 试听
  421. </div>
  422. </div>
  423. </div>
  424. <div class="__czr-title_2 mt-4">
  425. 问题建议
  426. <div class="ml-auto">
  427. <el-checkbox-group
  428. v-model="state.form.advise.types"
  429. size="small"
  430. >
  431. <el-checkbox-button value="open">
  432. 开启
  433. </el-checkbox-button>
  434. <template v-if="state.form.advise.types.includes('open')">
  435. <el-checkbox-button value="tips">
  436. 自定义提示词
  437. </el-checkbox-button>
  438. <el-checkbox-button value="knowledge">
  439. 仅从知识库建议
  440. </el-checkbox-button>
  441. </template>
  442. </el-checkbox-group>
  443. </div>
  444. </div>
  445. <template v-if="state.form.advise.types.includes('open')">
  446. <div class="mt-4">
  447. <CzrFormColumn
  448. class="__czr-table-form-column"
  449. required
  450. label="模型选择"
  451. :span="24"
  452. v-model:param="state.form.advise.model.name"
  453. placeholder="点击选择模型"
  454. readonly
  455. @click="onAdviseModel"
  456. default-error-msg="请选择问题建议模型"
  457. />
  458. <div
  459. class="mt-2 flex h-10 items-center gap-1 rounded-sm bg-[#FFFAEA] px-3.5 text-sm text-[#6F7889]"
  460. >
  461. <SvgIcon
  462. name="czr_tip"
  463. color="var(--czr-warning-color)"
  464. />
  465. 应用每次回复后,根据对话内容提出最多3条问题建议
  466. </div>
  467. <template v-if="state.form.advise.types.includes('tips')">
  468. <div class="mt-2">
  469. <CzrFormColumn
  470. class="__czr-table-form-column"
  471. label-width="0px"
  472. :span="24"
  473. v-model:param="state.form.advise.tips"
  474. type="textarea"
  475. :rows="4"
  476. placeholder="问题应该与你最后一轮的回复紧密相关,可以引发进一步的讨论。&#10;问题不要与上文已经提问或者回答过的内容重复。&#10;每句话只包含一个问题,但也可以不是问句而是一句指令。&#10;推荐你有能力回答的问题。"
  477. />
  478. </div>
  479. </template>
  480. </div>
  481. <template
  482. v-if="state.form.advise.types.includes('knowledge')"
  483. >
  484. <div class="__czr-title_2 mt-4">
  485. 问题建议知识库
  486. <template v-if="state.form.advise.knowledges.length > 0">
  487. ({{ state.form.advise.knowledges.length }})
  488. </template>
  489. <CzrButton
  490. type="normal"
  491. title="新增"
  492. class="ml-auto"
  493. @click="onAddAdviseKnowledge"
  494. />
  495. </div>
  496. <template v-if="state.form.advise.knowledges.length > 0">
  497. <div
  498. class="mt-2 flex max-h-42 flex-col gap-2 overflow-y-auto pr-2"
  499. >
  500. <template
  501. v-for="(item, index) in state.form.advise.knowledges"
  502. >
  503. <div class="flex items-center gap-1.5">
  504. <div
  505. class="flex h-10 flex-1 items-center overflow-hidden rounded-sm bg-[#F6F8FC] px-2.5"
  506. >
  507. <img
  508. src="@/assets/images/knowledge/knowledge-item-icon-2.png"
  509. class="mr-4 size-6"
  510. />
  511. <div
  512. class="flex-1 text-sm font-bold text-[#2E3238]"
  513. v-title
  514. >
  515. {{ item.name }}
  516. </div>
  517. </div>
  518. <SvgIcon
  519. class="__hover"
  520. name="czr_del"
  521. color="var(--czr-error-color)"
  522. @click="
  523. state.form.advise.knowledges.splice(index, 1)
  524. "
  525. />
  526. </div>
  527. </template>
  528. </div>
  529. </template>
  530. <template v-else>
  531. <div
  532. class="mt-2 flex h-8 items-center justify-center rounded-sm bg-[#F6F8FC] text-xs text-[#A7ADB9]"
  533. >
  534. 暂未添加问题建议知识库
  535. </div>
  536. </template>
  537. </template>
  538. </template>
  539. </div>
  540. </div>
  541. </CzrForm>
  542. </div>
  543. <div
  544. class="col-span-1 flex flex-col gap-2 overflow-hidden rounded-lg bg-[#F6F8FC] p-4"
  545. >
  546. <div
  547. class="flex h-14 w-full items-center gap-2.5 rounded-lg bg-[#ffffff] px-6"
  548. >
  549. <div class="text-2xl font-bold text-[#303133]">预览</div>
  550. <div
  551. class="flex items-center gap-2 text-sm text-[var(--czr-error-color)]"
  552. v-if="modelApplyCpt"
  553. >
  554. <SvgIcon name="czr_tip" color="var(--czr-error-color)" />
  555. 编排中有申请中的模型,预览暂不可用
  556. </div>
  557. <el-tooltip content="重新开始" :raw-content="true" placement="top">
  558. <SvgIcon class="__hover ml-auto" name="refresh" :active="true" />
  559. </el-tooltip>
  560. </div>
  561. <div class="relative flex-1 overflow-hidden">
  562. <chat />
  563. <div
  564. v-if="!state.isDebug"
  565. class="absolute inset-0 flex h-full w-full flex-col rounded-lg bg-white/50 p-20 backdrop-blur-sm"
  566. >
  567. <div class="text-2xl font-bold text-[#1d2939]">编排已改变</div>
  568. <div class="mt-6 text-[#667085]">
  569. 修改编排将重置调试区域,确定吗?
  570. </div>
  571. <div class="mt-6 flex gap-2">
  572. <CzrButton
  573. type="primary"
  574. title="重新开始"
  575. icon="refresh"
  576. size="18"
  577. @click="state.isDebug = true"
  578. />
  579. <CzrButton
  580. type="normal"
  581. title="取消"
  582. @click="state.isDebug = true"
  583. />
  584. </div>
  585. </div>
  586. </div>
  587. </div>
  588. </div>
  589. </div>
  590. <knowledgeSelect
  591. v-model:show="state.knowledgeSelect.show"
  592. :transfer="state.knowledgeSelect.transfer"
  593. @refresh="getKnowledge"
  594. />
  595. <modelSelect
  596. v-model:show="state.modelSelect.show"
  597. :transfer="state.modelSelect.transfer"
  598. @refresh="getModel"
  599. />
  600. <workflowSelect
  601. v-model:show="state.workflowSelect.show"
  602. :transfer="state.workflowSelect.transfer"
  603. @refresh="getWorkflow"
  604. />
  605. <templateSelect
  606. v-model:show="state.templateSelect.show"
  607. @insert="(val) => ((state.form.tips = val), ref_tips.focus())"
  608. />
  609. <templateDetail
  610. v-model:show="state.templateDetail.show"
  611. :transfer="state.templateDetail.transfer"
  612. />
  613. <CzrDialog
  614. :show="state.publish.show"
  615. title="发布"
  616. @onClose="state.publish.show = false"
  617. @onSubmit="onPublishSubmit"
  618. width="42.5rem"
  619. height="auto"
  620. >
  621. <div class="bm-form">
  622. <CzrForm ref="ref_formPublish">
  623. <CzrFormColumn
  624. required
  625. label="发布渠道"
  626. :span="24"
  627. v-model:param="state.publish.form.name"
  628. link="select"
  629. :options="[
  630. { label: '个人', value: '1' },
  631. { label: '公共空间(需审批)', value: '2' },
  632. ]"
  633. :clearable="false"
  634. />
  635. <CzrFormColumn
  636. v-if="state.publish.form.name == 2"
  637. label="申请留言"
  638. :span="24"
  639. v-model:param="state.publish.form.description"
  640. type="textarea"
  641. :rows="10"
  642. />
  643. </CzrForm>
  644. </div>
  645. </CzrDialog>
  646. </div>
  647. </template>
  648. <script setup lang="ts">
  649. import {
  650. computed,
  651. getCurrentInstance,
  652. inject,
  653. nextTick,
  654. onMounted,
  655. reactive,
  656. ref,
  657. watch,
  658. } from 'vue'
  659. import { useRoute, useRouter } from 'vue-router'
  660. import { ElLoading, ElMessage } from 'element-plus'
  661. import { useDialogStore, useDictionaryStore } from '@/stores'
  662. import { Search } from '@element-plus/icons-vue'
  663. import knowledgeSelect from './knowledge-select.vue'
  664. import modelSelect from './model-select.vue'
  665. import { isValue, YMDHms } from '@/utils/czr-util'
  666. import Sortable from 'sortablejs'
  667. import { debounce } from 'lodash'
  668. import chat from '@/views/chat/index.vue'
  669. import templateSelect from './template-select.vue'
  670. import templateDetail from './template-detail.vue'
  671. import workflowSelect from './workflow-select.vue'
  672. import CzrForm from '@/components/czr-ui/CzrForm.vue'
  673. import CzrDialog from '@/components/czr-ui/CzrDialog.vue'
  674. const DictionaryStore = useDictionaryStore()
  675. const DialogStore = useDialogStore()
  676. const route = useRoute()
  677. const router = useRouter()
  678. const emit = defineEmits([])
  679. const props = defineProps({})
  680. const { proxy }: any = getCurrentInstance()
  681. const state: any = reactive({
  682. ID: route.params.id,
  683. autoSaveTimestamp: '',
  684. form: {
  685. tips: '',
  686. model: { name: '' },
  687. components: [],
  688. knowledges: [
  689. {
  690. name: '水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水',
  691. description:
  692. '水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水',
  693. },
  694. ],
  695. workflows: [
  696. {
  697. name: '水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水',
  698. description:
  699. '水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水水',
  700. },
  701. ],
  702. prologue: '',
  703. prologueQuestions: [
  704. { value: '1' },
  705. { value: '2' },
  706. { value: '3' },
  707. { value: '4' },
  708. { value: '5' },
  709. ],
  710. prologueType: 'three',
  711. method: 1,
  712. voicePackage: '',
  713. advise: {
  714. types: [],
  715. model: { name: '' },
  716. tips: '',
  717. knowledges: [],
  718. },
  719. },
  720. detail: {},
  721. knowledgeSelect: {
  722. show: false,
  723. transfer: {},
  724. },
  725. modelSelect: {
  726. show: false,
  727. transfer: {},
  728. },
  729. workflowSelect: {
  730. show: false,
  731. transfer: {},
  732. },
  733. templateSelect: {
  734. show: false,
  735. },
  736. templateDetail: {
  737. show: false,
  738. transfer: {},
  739. },
  740. publish: {
  741. show: false,
  742. transfer: {},
  743. form: {},
  744. },
  745. prologuesAdd: {
  746. value: '',
  747. },
  748. dragRefresh: true,
  749. isDebug: true,
  750. history: [
  751. { type: 'submit', date: '2024-03-06 22:24:54' },
  752. { type: 'publish', date: '2024-03-06 22:24:54' },
  753. { type: 'apply', date: '2024-03-06 22:24:54' },
  754. { type: 'publish', date: '2024-03-06 22:24:54' },
  755. { type: 'submit', date: '2024-03-06 22:24:54' },
  756. { type: 'publish', date: '2024-03-06 22:24:54' },
  757. { type: 'submit', date: '2024-03-06 22:24:54' },
  758. { type: 'publish', date: '2024-03-06 22:24:54' },
  759. { type: 'create', date: '2024-03-06 22:24:54' },
  760. ],
  761. })
  762. const ref_form = ref()
  763. const ref_formPublish = ref()
  764. const ref_tips = ref()
  765. const ref_prologue = ref()
  766. const ref_prologueBody = ref()
  767. const modelApplyCpt = computed(() => {
  768. return true
  769. })
  770. const initDetail = () => {
  771. if (state.ID) {
  772. state.detail = {}
  773. // pluginDetail(state.ID)
  774. // .then(({ data }: any) => {
  775. // state.detail = data
  776. // })
  777. // .catch(() => {})
  778. // .finally(() => {})
  779. initDrag()
  780. } else {
  781. router.push({ name: 'd446bfb3-4605-477f-a0f4-b7a0a1aa78fe' })
  782. }
  783. }
  784. const initDrag = () => {
  785. nextTick(() => {
  786. const tbody =
  787. ref_prologueBody.value.parentElement.querySelector('.drag-body')
  788. new Sortable(tbody, {
  789. animation: 150,
  790. handle: '.drag-icon', // 设置可拖拽行的类名(el-table自带的类名)
  791. onEnd: ({ newIndex, oldIndex }: any) => {
  792. const d = [...state.form.prologueQuestions]
  793. const targetRow = d[oldIndex]
  794. d.splice(oldIndex, 1)
  795. d.splice(newIndex, 0, targetRow)
  796. state.form.prologueQuestions = [...d]
  797. state.dragRefresh = false
  798. setTimeout(() => {
  799. state.dragRefresh = true
  800. initDrag()
  801. }, 0)
  802. },
  803. })
  804. })
  805. }
  806. const toBack = () => {
  807. router.push({
  808. name: 'd446bfb3-4605-477f-a0f4-b7a0a1aa78fe',
  809. })
  810. }
  811. const onAddKnowledge = () => {
  812. state.knowledgeSelect.transfer = {
  813. ids: state.form.knowledges.map((v) => v.id),
  814. type: 'knowledge',
  815. }
  816. state.knowledgeSelect.show = true
  817. }
  818. const onAddAdviseKnowledge = () => {
  819. state.knowledgeSelect.transfer = {
  820. ids: state.form.advise.knowledges.map((v) => v.id),
  821. type: 'advise',
  822. }
  823. state.knowledgeSelect.show = true
  824. }
  825. const onPrologue = (row) => {
  826. if (row) {
  827. row.__value = row.value + ''
  828. row.__edit = true
  829. } else {
  830. state.prologuesAdd.__edit = true
  831. }
  832. const t = setInterval(() => {
  833. const r = ref_prologue.value
  834. if (r) {
  835. if (r.length) {
  836. r[0].focus()
  837. } else {
  838. r.focus()
  839. }
  840. clearInterval(t)
  841. }
  842. }, 100)
  843. }
  844. const onAddPrologue = () => {
  845. state.form.prologueQuestions.push({ value: state.prologuesAdd.value + '' })
  846. state.prologuesAdd.value = ''
  847. }
  848. const onEditPrologue = (row) => {
  849. if (isValue(row.__value.trim())) {
  850. row.value = row.__value + ''
  851. }
  852. row.__edit = false
  853. }
  854. const getKnowledge = (arr) => {
  855. switch (state.knowledgeSelect.transfer.type) {
  856. case 'knowledge':
  857. {
  858. state.form.knowledges.push(...arr)
  859. }
  860. break
  861. case 'advise':
  862. {
  863. state.form.advise.knowledges.push(...arr)
  864. }
  865. break
  866. }
  867. }
  868. const getModel = (val) => {
  869. switch (state.modelSelect.transfer.type) {
  870. case 'model':
  871. {
  872. state.form.model = val
  873. }
  874. break
  875. case 'advise':
  876. {
  877. state.form.advise.model = val
  878. }
  879. break
  880. }
  881. }
  882. const onModel = () => {
  883. state.modelSelect.transfer = {
  884. type: 'model',
  885. id: state.form.model.id,
  886. }
  887. state.modelSelect.show = true
  888. }
  889. const onAdviseModel = () => {
  890. state.modelSelect.transfer = {
  891. type: 'advise',
  892. id: state.form.advise.model.id,
  893. }
  894. state.modelSelect.show = true
  895. }
  896. const onPublish = () => {
  897. ref_form.value
  898. .submit()
  899. .then(() => {
  900. if (state.detail.type == 1) {
  901. if (state.form.workflows.length === 0) {
  902. ElMessage.warning('请添加工作流!')
  903. return
  904. }
  905. }
  906. if (state.form.advise.types.includes('knowledge')) {
  907. if (state.form.advise.knowledges.length === 0) {
  908. ElMessage.warning('请添加问题建议知识库!')
  909. return
  910. }
  911. }
  912. // if (modelApplyCpt.value) {
  913. // DialogStore.confirm({
  914. // content: `编排中有申请中的模型,暂不可发布!`,
  915. // props: {
  916. // showSubmit: false,
  917. // showCancel: false,
  918. // },
  919. // })
  920. // }
  921. // if (1) {
  922. // DialogStore.confirm({
  923. // title: '发布失败',
  924. // content: `该应用有发布中的申请,无法提交发布!<br/>申请提交时间:2023-02-02 15:21:23`,
  925. // onSubmit: () => {},
  926. // props: {
  927. // submitText: '撤销上一次的申请,重新发布',
  928. // cancelText: '等待审批',
  929. // },
  930. // })
  931. // }
  932. if (1) {
  933. state.publish.transfer = {}
  934. state.publish.show = true
  935. }
  936. })
  937. .catch((e) => {
  938. ElMessage({
  939. message: e[0].message,
  940. grouping: true,
  941. type: 'warning',
  942. })
  943. })
  944. }
  945. const onPublishSubmit = () => {
  946. ref_formPublish.value
  947. .submit()
  948. .then(() => {
  949. DialogStore.confirm({
  950. content: `请确认是否提交?`,
  951. onSubmit: () => {
  952. state.publish.show = false
  953. },
  954. })
  955. })
  956. .catch((e) => {
  957. ElMessage({
  958. message: e[0].message,
  959. grouping: true,
  960. type: 'warning',
  961. })
  962. })
  963. }
  964. watch(
  965. () => state.form,
  966. (n) => {
  967. autoSave(n)
  968. },
  969. { deep: true },
  970. )
  971. const autoSave = debounce((v) => {
  972. const loading = ElLoading.service({
  973. text: '自动保存中……',
  974. background: 'rgba(0, 0,0, 0.3)',
  975. })
  976. setTimeout(() => {
  977. loading.close()
  978. state.autoSaveTimestamp = YMDHms(new Date())
  979. state.isDebug = false
  980. }, 1000)
  981. }, 3000)
  982. const onAddTipsTemplate = () => {
  983. state.templateDetail.transfer = {
  984. mode: 'add',
  985. tips: state.form.tips + '',
  986. }
  987. state.templateDetail.show = true
  988. }
  989. const onTipsTemplate = () => {
  990. state.templateSelect.show = true
  991. }
  992. const onAddWorkflow = () => {
  993. state.workflowSelect.transfer = {
  994. id: state.form.workflows[0]?.id,
  995. }
  996. state.workflowSelect.show = true
  997. }
  998. const getWorkflow = (val) => {
  999. state.form.workflows = [val]
  1000. }
  1001. onMounted(() => {
  1002. initDictionary()
  1003. initDetail()
  1004. })
  1005. const initDictionary = () => {
  1006. // DictionaryStore.initModelProvides()
  1007. // DictionaryStore.initModelTypes()
  1008. }
  1009. </script>
  1010. <style lang="scss" scoped>
  1011. :deep(.form) {
  1012. flex: 1;
  1013. overflow: hidden;
  1014. .el-form {
  1015. width: 100%;
  1016. height: 100%;
  1017. .el-row {
  1018. width: 100%;
  1019. height: 100%;
  1020. .transparent-input {
  1021. .el-input__wrapper {
  1022. padding: 0;
  1023. }
  1024. }
  1025. }
  1026. }
  1027. }
  1028. .__czr-title_2 {
  1029. height: 2rem;
  1030. }
  1031. </style>