DataSourceBody.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. <template>
  2. <div class="detail-body">
  3. <a-table
  4. :row-selection="rowSelection"
  5. v-model:selectedKeys="selectedKeys"
  6. :pagination="false"
  7. rowKey="id"
  8. :data="groupTemplates"
  9. :loading="is_Loading"
  10. :scroll="{ y: 'calc(100% - 64px)' }"
  11. scrollbar
  12. >
  13. <template #columns>
  14. <a-table-column
  15. v-for="item in columns"
  16. :key="item.dataIndex"
  17. :title="item.title"
  18. :data-index="item.dataIndex"
  19. :header-cell-style="{ backgroundColor: 'var(--table-th-bg)' }"
  20. align="left"
  21. :width="item.width"
  22. >
  23. <template #cell="{ record, column }">
  24. <div class="column" v-if="item.dataIndex === 'name'">
  25. <img src="../../../assets/report-template/template_name.svg" alt="" />
  26. {{ record[column.dataIndex] }}
  27. </div>
  28. <div class="column" v-else-if="item.dataIndex === 'data_source_type'">
  29. {{ record[column.dataIndex] / 1 === 1 ? 'API' : '数据库' }}
  30. </div>
  31. <div class="column" v-else-if="item.dataIndex === 'created_at'">
  32. {{ formatDateTime(record[column.dataIndex]) || '-' }}
  33. </div>
  34. <div class="column" v-else-if="item.dataIndex === 'action'">
  35. <span class="link" @click="handleEdit(record)">编辑</span>
  36. <span class="link link_del" @click="handleDelete(record)">删除</span>
  37. </div>
  38. <div class="column" v-else>
  39. {{ record[column.dataIndex] }}
  40. </div>
  41. </template>
  42. </a-table-column>
  43. </template>
  44. </a-table>
  45. <div class="pagination">
  46. <a-pagination
  47. :total="page.total"
  48. :current="page.current"
  49. :page-size="page.page_size"
  50. @change="changePageChange"
  51. @page-size-change="changePageSizeChange"
  52. show-total
  53. show-page-size
  54. />
  55. </div>
  56. </div>
  57. <DeleteModal
  58. :visible="show_delete_modal"
  59. :is_branch="is_branch"
  60. @ok="handleConfirm"
  61. @cancel="handleCancel"
  62. ></DeleteModal>
  63. </template>
  64. <script setup >
  65. import { ref, reactive, watch, computed, nextTick, onMounted } from 'vue';
  66. import { getDataSourceList, deleteDataSourceItem } from '../../conversation-dialog/api-template';
  67. import DeleteModal from '../../../components/DeleteModal.vue';
  68. import { Message } from '@arco-design/web-vue';
  69. import { formatDateTime } from '../../../utils/utils';
  70. const emit = defineEmits(['edit-template']);
  71. const selectedKeys = ref([]);
  72. const show_delete_modal = ref(false);
  73. const is_branch = ref(false);
  74. const selected_id_list = ref([]);
  75. const filter_config = ref({
  76. filter: null,
  77. filter_value: null
  78. });
  79. const rowSelection = reactive({
  80. type: 'checkbox',
  81. showCheckedAll: true,
  82. onlyCurrent: false
  83. });
  84. const columns = ref([
  85. {
  86. title: '数据源名称',
  87. dataIndex: 'metric_name',
  88. key: 'metric_name',
  89. width: 200,
  90. sortable: {
  91. sortDirections: ['ascend', 'descend']
  92. }
  93. },
  94. {
  95. title: '描述',
  96. dataIndex: 'api_description',
  97. key: 'api_description',
  98. width: 400
  99. },
  100. {
  101. title: '数据源类型',
  102. dataIndex: 'data_source_type',
  103. key: 'data_source_type'
  104. },
  105. // {
  106. // title: '创建者',
  107. // dataIndex: 'creator',
  108. // key: 'creator'
  109. // // width: 200
  110. // },
  111. {
  112. title: '创建时间',
  113. dataIndex: 'created_at',
  114. key: 'created_at',
  115. // width: 200,
  116. sortable: {
  117. sortDirections: ['ascend', 'descend']
  118. }
  119. },
  120. {
  121. title: '操作',
  122. dataIndex: 'action',
  123. key: 'action'
  124. // width: 200
  125. }
  126. ]);
  127. const page = ref({
  128. total: 0,
  129. current: 1,
  130. page_size: 20
  131. });
  132. const is_Loading = ref(false);
  133. const groupTemplates = ref([]);
  134. const is_loading_status = ref(false);
  135. const changePageChange = (current) => {
  136. page.value.current = current;
  137. getDataSourceListFun();
  138. };
  139. const changePageSizeChange = (page_size) => {
  140. page.value.page_size = page_size;
  141. getDataSourceListFun();
  142. };
  143. const getDataSourceListFun = async () => {
  144. is_Loading.value = true;
  145. try {
  146. const res = await getDataSourceList({
  147. page: page.value.current,
  148. size: page.value.page_size,
  149. metric_name: filter_config.value.filter_value || ''
  150. });
  151. if (res.code / 1 === 200) {
  152. console.log(res);
  153. groupTemplates.value = res.data || [];
  154. page.value.total = res.pages.total || 0;
  155. }
  156. } catch (error) {
  157. console.log(error);
  158. } finally {
  159. is_Loading.value = false;
  160. }
  161. };
  162. const handleDelete = async (record) => {
  163. console.log(record);
  164. selected_id_list.value = [record.id];
  165. show_delete_modal.value = true;
  166. };
  167. // 批量删除
  168. const deleteSelected = async () => {
  169. if (selectedKeys.value.length === 0) {
  170. Message.warning('请选择要删除的草稿');
  171. return;
  172. }
  173. selected_id_list.value = selectedKeys.value;
  174. if (selected_id_list.value.length > 0) {
  175. is_branch.value = true;
  176. } else {
  177. is_branch.value = false;
  178. }
  179. show_delete_modal.value = true;
  180. };
  181. const handleConfirm = async () => {
  182. try {
  183. const res = await deleteDataSourceItem({
  184. metric_id: selected_id_list.value
  185. });
  186. if (res.code / 1 === 200) {
  187. Message.success('删除成功');
  188. getDataSourceListFun();
  189. } else {
  190. Message.error('删除失败');
  191. }
  192. } catch (error) {
  193. console.log(error);
  194. Message.error('删除失败');
  195. } finally {
  196. selected_id_list.value = [];
  197. selectedKeys.value = [];
  198. show_delete_modal.value = false;
  199. is_branch.value = false;
  200. }
  201. };
  202. const handleCancel = () => {
  203. show_delete_modal.value = false;
  204. selected_id_list.value = [];
  205. selectedKeys.value = [];
  206. is_branch.value = false;
  207. };
  208. const handleStatusChange = (record) => {
  209. console.log(record);
  210. is_loading_status.value = true;
  211. editTemplateItemFunc({ id: record.id, status: record.status });
  212. };
  213. const editTemplateItemFunc = async (item) => {
  214. try {
  215. const res = await editTemplateItem({
  216. ...item
  217. });
  218. if (res.code / 1 === 200) {
  219. // Message.success('编辑成功');
  220. getDataSourceListFun();
  221. } else {
  222. // Message.error('编辑失败');
  223. }
  224. } catch (error) {
  225. console.log(error);
  226. // Message.error('编辑失败');
  227. } finally {
  228. is_loading_status.value = false;
  229. }
  230. };
  231. const handleEditRemark = (record) => {
  232. record.temp_remark = record.remark;
  233. record.is_remark_edit = true;
  234. record.show_edit_btn = false;
  235. nextTick(() => {
  236. const input = document.querySelector('.remark-edit .arco-input');
  237. if (input) {
  238. input.focus();
  239. }
  240. });
  241. };
  242. const handleSaveRemark = async (record) => {
  243. try {
  244. const res = await editTemplateItem({
  245. id: record.id,
  246. remark: record.temp_remark
  247. });
  248. if (res.code / 1 === 200) {
  249. Message.success('保存成功');
  250. record.remark = record.temp_remark;
  251. record.is_remark_edit = false;
  252. delete record.temp_remark;
  253. } else {
  254. Message.error('保存失败');
  255. }
  256. } catch (error) {
  257. console.log(error);
  258. Message.error('保存失败');
  259. }
  260. };
  261. const handleCancelRemark = (record) => {
  262. record.is_remark_edit = false;
  263. delete record.temp_remark;
  264. };
  265. const handleEdit = (record) => {
  266. emit('edit-datasource', record);
  267. };
  268. const clearFilter = (params) => {
  269. filter_config.value = {
  270. filter: params.type,
  271. filter_value: params.value
  272. };
  273. page.value.current = 1;
  274. };
  275. const toSearch = (params) => {
  276. filter_config.value = {
  277. filter: params.type,
  278. filter_value: params.value
  279. };
  280. page.value.current = 1;
  281. getDataSourceListFun();
  282. };
  283. onMounted(() => {
  284. getDataSourceListFun();
  285. });
  286. defineExpose({
  287. update: getDataSourceListFun,
  288. deleteSelected: deleteSelected,
  289. toSearch: toSearch,
  290. clearFilter: clearFilter
  291. });
  292. </script>
  293. <style scoped lang="css">
  294. .detail-body {
  295. position: relative;
  296. height: calc(100% - 52px);
  297. padding: 0 20px;
  298. z-index: 10;
  299. }
  300. .column {
  301. display: flex;
  302. align-items: center;
  303. gap: 5px;
  304. }
  305. .column .link {
  306. color: #3d3d3d;
  307. cursor: pointer;
  308. }
  309. .column .link_del {
  310. color: #e34d59;
  311. }
  312. :deep(.arco-table-element th) {
  313. background-color: var(--table-th-bg) !important;
  314. }
  315. :deep(.arco-checkbox-checked .arco-checkbox-icon) {
  316. background: var(--primary-default);
  317. }
  318. :deep(.arco-checkbox-indeterminate .arco-checkbox-icon) {
  319. background: var(--primary-default);
  320. }
  321. .pagination {
  322. margin-top: 10px;
  323. display: flex;
  324. flex-direction: row;
  325. justify-content: flex-end;
  326. }
  327. :deep(.arco-pagination-item-active, .arco-pagination-item-active:hover) {
  328. color: var(--primary-default);
  329. background: var(--title-bg);
  330. }
  331. .remark-cell {
  332. position: relative;
  333. }
  334. .remark-text {
  335. display: inline-flex;
  336. align-items: center;
  337. gap: 8px;
  338. width: 100%;
  339. }
  340. .edit-icon {
  341. cursor: pointer;
  342. color: var(--color-text-2);
  343. opacity: 0;
  344. transition: opacity 0.2s;
  345. }
  346. .remark-cell:hover .edit-icon {
  347. opacity: 1;
  348. }
  349. .edit-icon:hover {
  350. color: var(--primary-default);
  351. }
  352. .remark-edit {
  353. display: flex;
  354. flex-direction: row;
  355. align-items: center;
  356. gap: 8px;
  357. width: 100%;
  358. }
  359. .edit-actions {
  360. display: flex;
  361. gap: 8px;
  362. }
  363. .edit-actions .arco-btn {
  364. min-width: 60px;
  365. }
  366. .icon_edit_btn {
  367. font-size: 16px;
  368. cursor: pointer;
  369. }
  370. .icon_edit_btn:hover {
  371. color: var(--primary-default);
  372. }
  373. </style>