template-select.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <template>
  2. <CzrDialog
  3. :show="show"
  4. :title="titleCpt"
  5. @onClose="$emit('update:show', false)"
  6. width="80%"
  7. height="90%"
  8. :loading="state.loading"
  9. :show-close="false"
  10. :show-submit="false"
  11. >
  12. <div class="bm-form flex h-full w-full flex-col p-4">
  13. <div class="flex items-center">
  14. <CzrButton
  15. :type="state.tab === Tab.System ? 'primary' : 'normal'"
  16. title="系统"
  17. @click="state.tab = Tab.System"
  18. />
  19. <CzrButton
  20. :type="state.tab === Tab.User ? 'primary' : 'normal'"
  21. title="个人"
  22. @click="state.tab = Tab.User"
  23. class="ml-4"
  24. />
  25. <CzrFormColumn
  26. width="15.63rem"
  27. class="__czr-table-form-column ml-auto"
  28. :span="24"
  29. label-width="0px"
  30. v-model:param="state.text"
  31. placeholder="输入关键词以检索"
  32. :prefix-icon="Search"
  33. />
  34. </div>
  35. <div class="mt-4 grid flex-1 grid-cols-3 gap-4 overflow-hidden">
  36. <div
  37. class="col-span-1 mr-2 flex flex-col gap-2 overflow-y-auto pr-2 pb-1"
  38. >
  39. <template v-for="item in state.list[state.tab]">
  40. <div
  41. class="__hover flex flex-col rounded-lg px-4 py-3"
  42. style="border: var(--czr-border)"
  43. :style="`${state.selected?.id == item.id ? 'border-color: var(--czr-main-color);background-color: rgba(var(--czr-main-color-rgb), 0.1)' : ''}`"
  44. @click="state.selected = item"
  45. >
  46. <div class="font-bold text-[#2E3238]">{{ item.name }}</div>
  47. <div class="mt-2 text-sm text-[#606266]" v-title>
  48. {{ item.description }}
  49. </div>
  50. </div>
  51. </template>
  52. </div>
  53. <div
  54. class="col-span-2 flex flex-col overflow-hidden pr-1"
  55. v-if="state.selected"
  56. >
  57. <div
  58. class="flex-1 overflow-y-auto bg-gradient-to-b from-[#2853F7]/10 to-[#ffffff]/10 p-4 text-base text-[#606266] shadow"
  59. style="line-height: 1.4"
  60. >
  61. {{ state.selected.content }}
  62. </div>
  63. <div class="mt-4 flex justify-end gap-4">
  64. <div
  65. class="__czr-dialog-foot_submit __hover"
  66. @click="onCopy(state.selected.content)"
  67. >
  68. 复制
  69. </div>
  70. <div
  71. class="__czr-dialog-foot_cancel __hover"
  72. @click="onInsert(state.selected.content)"
  73. >
  74. 插入
  75. </div>
  76. </div>
  77. </div>
  78. </div>
  79. </div>
  80. </CzrDialog>
  81. </template>
  82. <script setup lang="ts">
  83. import {
  84. computed,
  85. getCurrentInstance,
  86. nextTick,
  87. reactive,
  88. ref,
  89. watch,
  90. } from 'vue'
  91. import { ElMessage, ElMessageBox } from 'element-plus'
  92. import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
  93. import { copy } from '@/utils/czr-util'
  94. import CzrDialog from '@/components/czr-ui/CzrDialog.vue'
  95. import { Search } from '@element-plus/icons-vue'
  96. import { debounce } from 'lodash'
  97. import { pluginDel } from '@/api/modules/model'
  98. import { promptTemplatesSearch } from '@/api/modules/app/tips'
  99. const AppStore = useAppStore()
  100. const DictionaryStore = useDictionaryStore()
  101. const DialogStore = useDialogStore()
  102. const emit = defineEmits(['update:show', 'insert'])
  103. const props = defineProps({
  104. show: { default: false },
  105. transfer: <any>{},
  106. })
  107. enum Tab {
  108. System = 'SYSTEM',
  109. User = 'PERSONAL',
  110. }
  111. const state: any = reactive({
  112. tab: Tab.System,
  113. text: '',
  114. list: {
  115. [Tab.System]: [],
  116. [Tab.User]: [],
  117. },
  118. selected: null,
  119. })
  120. const titleCpt = computed(() => {
  121. let t = '提示词模板'
  122. return t
  123. })
  124. const isViewCpt = computed(() => props.transfer?.mode === 'view')
  125. watch(
  126. () => props.show,
  127. (n) => {
  128. if (n) {
  129. initData()
  130. state.selected = null
  131. initDictionary()
  132. }
  133. },
  134. )
  135. const setText = debounce((v) => {
  136. initData()
  137. }, 1000)
  138. watch(
  139. () => state.text,
  140. (n) => {
  141. setText(n)
  142. },
  143. )
  144. const initData = () => {
  145. const params = {
  146. page: 1,
  147. size: 9999,
  148. }
  149. const arrSystem: any = []
  150. const arrUser: any = []
  151. promptTemplatesSearch(params)
  152. .then(({ data }: any) => {
  153. data.records?.forEach((v) => {
  154. if (v.type === Tab.System) {
  155. arrSystem.push(v)
  156. } else if (v.type === Tab.User) {
  157. arrUser.push(v)
  158. }
  159. })
  160. state.list[Tab.System] = arrSystem
  161. state.list[Tab.User] = arrUser
  162. console.log(state.list)
  163. })
  164. .catch(() => {})
  165. .finally(() => {})
  166. }
  167. const onCopy = (str) => {
  168. copy(str)
  169. ElMessage.success('复制成功!')
  170. }
  171. const onInsert = (str) => {
  172. DialogStore.confirm({
  173. title: '插入确认',
  174. content: `插入后将覆盖提示词内容,请确认是否插入?`,
  175. onSubmit: () => {
  176. emit('insert', str)
  177. emit('update:show', false)
  178. },
  179. })
  180. }
  181. const initDictionary = () => {}
  182. </script>
  183. <style lang="scss" scoped></style>