knowledge-card.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <template>
  2. <div
  3. class="flex flex-col rounded-lg bg-[var(--czr-dialog-bg)] p-4"
  4. v-loading="state.query.loading"
  5. >
  6. <div>
  7. <CzrFormColumn
  8. class="__czr-table-form-column"
  9. label-width="0px"
  10. :span="8"
  11. :offset="16"
  12. v-model:param="state.text"
  13. placeholder="按名称搜索"
  14. :prefix-icon="Search"
  15. />
  16. </div>
  17. <div
  18. class="mt-2 grid max-h-[600px] flex-1 grid-cols-2 gap-4 overflow-y-auto"
  19. >
  20. <template v-for="item in state.query.result.data">
  21. <div
  22. class="__hover relative col-span-1 flex flex-col overflow-hidden rounded-lg border-1 border-[#E6E8EA] px-6 py-4"
  23. :class="{
  24. 'border-[var(--czr-main-color)]': state.selectedMap.has(item.id),
  25. }"
  26. @click="onSelect(item)"
  27. >
  28. <div class="flex">
  29. <img
  30. src="@/assets/images/knowledge/knowledge-item-icon.png"
  31. class="mr-2.5 size-11"
  32. />
  33. <div class="flex flex-1 flex-col justify-around overflow-hidden">
  34. <div class="flex items-center">
  35. <div class="flex-1 text-xl font-bold text-[#2E3238]" v-title>
  36. {{ item.name }}
  37. </div>
  38. </div>
  39. <div
  40. class="flex items-center gap-2.5 text-[0.75rem] text-[#6F7889]"
  41. >
  42. <div>文档数:{{ item.docCount }}</div>
  43. <div>|</div>
  44. <div>字符:{{ item.wordCounts }}</div>
  45. <div>|</div>
  46. <div>创建者:{{ item.userName }}</div>
  47. </div>
  48. </div>
  49. </div>
  50. <div
  51. class="mt-2.5 mb-auto text-sm text-[#606266]"
  52. style="line-height: 1.4rem"
  53. v-title="{ lines: 2 }"
  54. >
  55. {{ item.description }}
  56. </div>
  57. <template v-if="state.selectedMap.has(item.id)">
  58. <div
  59. class="absolute top-0 right-0 h-[2rem] w-[2rem] bg-[url('@/assets/images/knowledge/checked.png')]"
  60. ></div>
  61. </template>
  62. </div>
  63. </template>
  64. </div>
  65. </div>
  66. </template>
  67. <script setup lang="ts">
  68. import {
  69. computed,
  70. getCurrentInstance,
  71. nextTick,
  72. onMounted,
  73. reactive,
  74. ref,
  75. watch,
  76. } from 'vue'
  77. import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
  78. import { useRouter } from 'vue-router'
  79. import { datasetsGetAllByPage } from '@/api/modules/knowledge'
  80. import CzrFormColumn from '@/components/czr-ui/CzrFormColumn.vue'
  81. import { Search } from '@element-plus/icons-vue'
  82. import { debounce } from 'lodash'
  83. const router = useRouter()
  84. const DictionaryStore = useDictionaryStore()
  85. const DialogStore = useDialogStore()
  86. const AppStore = useAppStore()
  87. const emit = defineEmits(['update:show', 'refresh'])
  88. const { proxy } = getCurrentInstance()
  89. const props = defineProps({
  90. multiple: { default: false },
  91. ids: { default: () => <any>[] },
  92. })
  93. const state: any = reactive({
  94. selectedMap: new Map(),
  95. text: '',
  96. query: {
  97. init: false,
  98. loading: false,
  99. page: {
  100. pageNum: 1,
  101. pageSize: 20,
  102. },
  103. form: {},
  104. formReal: {},
  105. result: {
  106. total: 0,
  107. data: [],
  108. },
  109. },
  110. })
  111. const setText = debounce((v) => {
  112. state.query.form.name = v
  113. }, 1000)
  114. watch(
  115. () => state.text,
  116. (n) => {
  117. setText(n)
  118. },
  119. )
  120. watch(
  121. () => state.query.form,
  122. (n) => {
  123. if (state.query.init) {
  124. onSearch()
  125. }
  126. },
  127. { deep: true },
  128. )
  129. const onSearch = () => {
  130. state.query.formReal = JSON.parse(JSON.stringify(state.query.form))
  131. onPage(1, 100000)
  132. }
  133. const onPage = (pageNum, pageSize) => {
  134. setTimeout(() => {
  135. state.query.init = true
  136. }, 100)
  137. state.query.page = {
  138. pageNum: pageNum,
  139. pageSize: pageSize,
  140. }
  141. const params = {
  142. tenantId: AppStore.tenantInfo?.id,
  143. page: state.query.page.pageNum,
  144. size: state.query.page.pageSize,
  145. }
  146. // 添加表单参数
  147. for (const [k, v] of Object.entries(state.query.formReal)) {
  148. if (proxy.$czrUtil.isValue(v)) {
  149. params[k] = v
  150. }
  151. }
  152. state.query.loading = true
  153. datasetsGetAllByPage(params)
  154. .then(({ data }: any) => {
  155. state.query.result.total = data.totalElements
  156. state.query.result.data = data.content.filter(
  157. (v) => !props.ids.includes(v.id),
  158. )
  159. })
  160. .catch(() => {})
  161. .finally(() => {
  162. state.query.loading = false
  163. })
  164. }
  165. const onSelect = (row) => {
  166. if (state.selectedMap.has(row.id)) {
  167. state.selectedMap.delete(row.id)
  168. } else {
  169. if (!props.multiple) {
  170. state.selectedMap.clear()
  171. }
  172. state.selectedMap.set(row.id, row)
  173. }
  174. }
  175. const getData = () => {
  176. return Array.from(state.selectedMap.values())
  177. }
  178. onMounted(() => {
  179. onSearch()
  180. })
  181. defineExpose({
  182. getData,
  183. })
  184. </script>
  185. <style lang="scss" scoped></style>