MessageBody.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <template>
  2. <div class="body-container" ref="body_container">
  3. <CardItem
  4. v-for="item in moke_data"
  5. :key="item.id"
  6. :name="item.name"
  7. :img_src="item.img_src"
  8. @click="handleToDetail(item)"
  9. @clickIcon="editIconHandle(item)"
  10. >
  11. <template #bottom>
  12. <div class="bottom">
  13. <div>{{ item.count }}&nbsp;{{ $t('management.document') }}</div>
  14. <div>|</div>
  15. <div>{{ item.time }}</div>
  16. </div>
  17. </template>
  18. <template #settings>
  19. <a-dropdown v-hasPermi="'system:knowledge:delete'" trigger="hover" @select="handleSelect($event, item)">
  20. <icon-more :style="{ fontSize: '20px' }" />
  21. <template #content>
  22. <!-- <a-doption :value="{ value: 'edit' }">{{ $t('management.edit') }}</a-doption> -->
  23. <a-doption :value="{ value: 'delete' }">{{ $t('management.delete') }}</a-doption>
  24. </template>
  25. </a-dropdown>
  26. </template>
  27. </CardItem>
  28. <div class="loading-tips">
  29. <a-spin v-if="scroll_bottom && pages.current < total_pages" :tip="$t('management.loadingDataTip')" />
  30. <div v-if="scroll_bottom && pages.current >= total_pages">{{ $t('management.noMoreData') }}</div>
  31. </div>
  32. </div>
  33. <a-spin class="init-loading" v-if="loading_data" :size="32" />
  34. <a-empty v-if="!moke_data.length"></a-empty>
  35. </template>
  36. <script setup>
  37. import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
  38. import { Message, Modal } from '@arco-design/web-vue';
  39. import { useRouter } from 'vue-router';
  40. import CardItem from '../../views/manage/CardItem.vue';
  41. import { getImageKnowLedge } from '../common/icon-map.js';
  42. import { funcThrottle } from '../../utils/utils';
  43. import { getKnowledgeList, deleteOwnKnowledge } from '../../apis/knowledge';
  44. import { deleteKnow } from '../../apis/rgflow-dify.js';
  45. import { bus_knowledgeSearch, bus_knowledgeIconEdit } from '../../base/event-bus';
  46. const router = useRouter();
  47. const moke_data = ref([
  48. // {
  49. // name: '知识库1',
  50. // img_src: knowledgeFrame1,
  51. // count: 292,
  52. // time: '2024:11:11 12:00:00'
  53. // }
  54. ]);
  55. const pages = reactive({
  56. current: 1,
  57. pageSize: 30
  58. });
  59. const loading_data = ref(false);
  60. // 总页码
  61. const total_pages = ref(0);
  62. const body_container = ref(null);
  63. const scroll_bottom = ref(false);
  64. // 搜索文本
  65. const search_text = ref('');
  66. const handleToDetail = (item) => {
  67. router.push({
  68. path: '/knowledge/detail',
  69. query: {
  70. id: item.id,
  71. name: item.name
  72. }
  73. });
  74. };
  75. const handleSelect = ({ value }, item) => {
  76. if (value === 'delete') {
  77. toRemove(item);
  78. }
  79. };
  80. const toRemove = (item) => {
  81. Modal.warning({
  82. title: '提示',
  83. content: '确认删除吗',
  84. okText: '确定',
  85. hideCancel: false,
  86. onOk: async () => {
  87. let data = await deleteKnow({
  88. kb_id: item.id
  89. });
  90. if (data.retcode == 0) {
  91. deleteOwnKnow(item.id);
  92. } else {
  93. Message.error('没有权限');
  94. }
  95. },
  96. onCancel: () => {}
  97. });
  98. };
  99. const deleteOwnKnow = async (id) => {
  100. try {
  101. const res = await deleteOwnKnowledge(id);
  102. if (res.code == 200) {
  103. Message.success('删除成功');
  104. pages.current = 1;
  105. moke_data.value = [];
  106. getKnowledge();
  107. } else {
  108. Message.error('删除失败');
  109. }
  110. } catch (err) {
  111. console.log(err, 'flag');
  112. }
  113. };
  114. const getKnowledge = async () => {
  115. if (pages.current == 1) {
  116. loading_data.value = true;
  117. }
  118. try {
  119. const res = await getKnowledgeList(pages.current, pages.pageSize, search_text.value);
  120. if (res.code == 200) {
  121. const data = res.data.rows.map((item) => {
  122. return {
  123. ...item,
  124. time: new Date(item.create_time).toLocaleString('zh-CN'),
  125. img_src: getImageKnowLedge(item.icon),
  126. count: item.documents ? item.documents : 0
  127. };
  128. });
  129. moke_data.value.push(...data);
  130. total_pages.value = Math.ceil(res.data.total / pages.pageSize);
  131. }
  132. } catch (err) {
  133. console.log(err, 'flag');
  134. } finally {
  135. loading_data.value = false;
  136. }
  137. };
  138. const scrollHandler = (e) => {
  139. if (e.target.scrollTop + e.target.clientHeight >= e.target.scrollHeight) {
  140. scroll_bottom.value = true;
  141. // 调用函数加载更多数据
  142. if (pages.current < total_pages.value) {
  143. pages.current += 1;
  144. getKnowledge();
  145. }
  146. }
  147. };
  148. const editIconHandle = (item) => {
  149. bus_knowledgeIconEdit.emit(item);
  150. };
  151. bus_knowledgeSearch.on((text) => {
  152. search_text.value = text;
  153. moke_data.value = [];
  154. pages.current = 1;
  155. getKnowledge();
  156. });
  157. onMounted(() => {
  158. getKnowledge();
  159. body_container.value.addEventListener('scroll', funcThrottle(scrollHandler, 500));
  160. });
  161. onBeforeUnmount(() => {
  162. bus_knowledgeSearch.off();
  163. body_container.value.removeEventListener('scroll', scrollHandler);
  164. });
  165. </script>
  166. <style scoped lang="css">
  167. .body-container {
  168. display: grid;
  169. grid-template-columns: repeat(6, 1fr);
  170. align-content: flex-start;
  171. gap: 20px;
  172. overflow-y: auto;
  173. width: 100%;
  174. padding-top: 10px;
  175. height: calc(100% - 90px);
  176. }
  177. .body-container::-webkit-scrollbar {
  178. display: none;
  179. }
  180. .bottom {
  181. display: flex;
  182. gap: 10px;
  183. }
  184. .loading-tips {
  185. grid-column: 1/-1;
  186. grid-row-start: auto;
  187. text-align: center;
  188. }
  189. .arco-spin-loading {
  190. /* width: */
  191. height: calc(100% - 80px);
  192. }
  193. .arco-empty {
  194. position: absolute;
  195. top: 50%;
  196. left: 50%;
  197. transform: translate(-50%, -50%);
  198. }
  199. .init-loading {
  200. position: absolute;
  201. top: 50%;
  202. left: 50%;
  203. transform: translate(-50%, -50%);
  204. }
  205. </style>