yangg 2 mesiacov pred
rodič
commit
c3934c34d3

+ 9 - 0
src/views/questionBank/list/api.ts

@@ -63,4 +63,13 @@ export function GetcategoryList(params: any) {
 		method: 'get',
 		params: {...params,tenant_id:1},
 	});
+}
+
+// 批量更新标签
+export function BatchUpdateTags(data: any) {
+	return request({
+		url: '/api/system/interview_question/batch_update_tags',
+		method: 'get',
+		data
+	});
 }

+ 120 - 0
src/views/questionBank/list/components/BatchTagsDialog.vue

@@ -0,0 +1,120 @@
+<template>
+  <el-dialog
+    v-model="dialogVisible"
+    title="批量绑定标签"
+    width="500px"
+    :close-on-click-modal="false"
+    @closed="handleClosed"
+  >
+    <el-form :model="form" label-width="100px">
+      <el-form-item label="选中题目">
+        <div class="selected-count">已选择 {{ selectedQuestions.length }} 个题目</div>
+      </el-form-item>
+      <el-form-item label="选择标签" required>
+        <el-select
+          v-model="form.tagIds"
+          multiple
+          filterable
+          placeholder="请选择要绑定的标签"
+          style="width: 100%"
+        >
+          <el-option
+            v-for="item in tagOptions"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          />
+        </el-select>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="dialogVisible = false">取消</el-button>
+      <el-button type="primary" @click="handleConfirm" :loading="loading">确认绑定</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, onMounted } from 'vue';
+import { GetTagList } from '../api';
+import { useBatchUpdateTags } from '../crud';
+import { successMessage, warningMessage } from '../../../../utils/message';
+
+const props = defineProps({
+  crudExpose: {
+    type: Object,
+    required: true
+  }
+});
+
+const { batchUpdateTags } = useBatchUpdateTags(props.crudExpose);
+
+const dialogVisible = ref(false);
+const loading = ref(false);
+const selectedQuestions = ref<any[]>([]);
+const tagOptions = ref<any[]>([]);
+
+const form = reactive({
+  tagIds: [] as number[]
+});
+
+// 获取标签列表
+const fetchTags = async () => {
+  try {
+    const res = await GetTagList({ page: 1, limit: 1000, tenant_id: 1 });
+    if (res.code === 0 && res.data && res.data.items) {
+      tagOptions.value = res.data.items;
+    }
+  } catch (error) {
+    console.error('获取标签数据失败', error);
+  }
+};
+
+// 打开对话框
+const open = (selection: any[]) => {
+  selectedQuestions.value = selection;
+  dialogVisible.value = true;
+  form.tagIds = [];
+};
+
+// 确认绑定
+const handleConfirm = async () => {
+  if (form.tagIds.length === 0) {
+    warningMessage('请至少选择一个标签');
+    return;
+  }
+
+  loading.value = true;
+  try {
+    // 提取所有选中题目的ID
+    const questionIds = selectedQuestions.value.map(item => item.id);
+    await batchUpdateTags(questionIds, form.tagIds);
+    dialogVisible.value = false;
+  } finally {
+    loading.value = false;
+  }
+};
+
+// 对话框关闭后的处理
+const handleClosed = () => {
+  form.tagIds = [];
+  selectedQuestions.value = [];
+};
+
+// 初始化时获取标签数据
+onMounted(() => {
+  fetchTags();
+});
+
+// 暴露方法给父组件
+defineExpose({
+  open
+});
+</script>
+
+<style scoped>
+.selected-count {
+  font-size: 14px;
+  color: #606266;
+}
+</style> 

+ 72 - 7
src/views/questionBank/list/crud.tsx

@@ -1,9 +1,10 @@
 import { CreateCrudOptionsProps, CreateCrudOptionsRet, AddReq, DelReq, EditReq, dict, compute } from '@fast-crud/fast-crud';
 import * as api from './api';
 import { dictionary } from '/@/utils/dictionary';
-import { successMessage } from '../../../utils/message';
+import { successMessage, warningMessage } from '../../../utils/message';
 import { auth } from '/@/utils/authFunction';
 import { ref, onMounted } from 'vue';
+import { ElMessage } from 'element-plus';
 
 /**
  *
@@ -68,6 +69,24 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
 		fetchTags();
 	}); */
 
+	// 添加批量更新标签的方法
+	const batchUpdateTags = async (questionIds: number[], tagIds: number[]) => {
+		try {
+			const res = await api.BatchUpdateTags({
+				question_ids: questionIds,
+				tag_ids: tagIds,
+				tenant_id: 1
+			});
+			if (res.code === 0) {
+				successMessage('批量更新标签成功');
+				// 刷新列表
+				crudExpose.doRefresh();
+			}
+		} catch (error) {
+			console.error('批量更新标签失败', error);
+		}
+	};
+
 	return {
 		crudOptions: {
 			request: {
@@ -84,6 +103,25 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
 					add: {
 						show: auth('role:Create'),
 					},
+					// 添加批量绑定标签按钮
+					/* batchBindTags: {
+						text: '批量绑定标签',
+						type: 'primary',
+						show: true,
+						order: 2,
+						click: () => {
+							// 尝试不同的方式获取选中行
+							const selection = crudExpose.getSelection?.() || crudExpose.selectedRows || [];
+							console.log('选中的行:', selection);
+							
+							if (!selection || selection.length === 0) {
+								warningMessage('请先选择要操作的题目');
+								return;
+							}
+							// 打开批量绑定标签对话框
+							context.openBatchTagsDialog(selection);
+						},
+					}, */
 				},
 			},
 			rowHandle: {
@@ -122,16 +160,17 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
 				},
 			},
 			columns: {
-				/* _index: {
-					title: '序号',
+				_selection: {
+					title: '选择',
 					form: { show: false },
 					column: {
-						type: 'index',
+						type: 'selection',
 						align: 'center',
-						width: '70px',
-						columnSetDisabled: true, //禁止在列设置中选择
+						width: 50,
+						fixed: 'left',
+						columnSetDisabled: true,
 					},
-				}, */
+				},
 				id: {
 					title: 'ID',
 					column: { show: true ,width:80,},
@@ -528,6 +567,32 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
 					}
 				},
 			},
+			// 确保表格配置正确
+			table: {
+				selection: true,
+			},
 		},
 	};
 };
+
+// 导出批量更新标签方法,供组件使用
+export const useBatchUpdateTags = (crudExpose: any) => {
+	const batchUpdateTags = async (questionIds: number[], tagIds: number[]) => {
+		try {
+			const res = await api.BatchUpdateTags({
+				question_ids: questionIds,
+				tag_ids: tagIds,
+				tenant_id: 1
+			});
+			if (res.code === 0) {
+				successMessage('批量更新标签成功');
+				// 刷新列表
+				crudExpose.doRefresh();
+			}
+		} catch (error) {
+			console.error('批量更新标签失败', error);
+		}
+	};
+	
+	return { batchUpdateTags };
+};

+ 17 - 3
src/views/questionBank/list/index.vue

@@ -2,19 +2,24 @@
 	<fs-page>
 		<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
 		<PermissionDrawerCom />
+		<BatchTagsDialog ref="batchTagsDialogRef" :crudExpose="crudExpose" />
 	</fs-page>
 </template>
 
 <script lang="ts" setup name="role">
-import { defineAsyncComponent, onMounted } from 'vue';
+import { defineAsyncComponent, onMounted, ref } from 'vue';
 import { useFs } from '@fast-crud/fast-crud';
 import { createCrudOptions } from './crud';
 import { RoleDrawerStores } from './stores/RoleDrawerStores';
 import { RoleMenuBtnStores } from './stores/RoleMenuBtnStores';
 import { RoleMenuFieldStores } from './stores/RoleMenuFieldStores';
 import { RoleUsersStores } from './stores/RoleUsersStores';
+import { successMessage } from '../../../utils/message';
 
 const PermissionDrawerCom = defineAsyncComponent(() => import('./components/RoleDrawer.vue'));
+const BatchTagsDialog = defineAsyncComponent(() => import('./components/BatchTagsDialog.vue'));
+
+const batchTagsDialogRef = ref();
 
 const RoleDrawer = RoleDrawerStores(); // 角色-抽屉
 const RoleMenuBtn = RoleMenuBtnStores(); // 角色-菜单
@@ -22,7 +27,17 @@ const RoleMenuField = RoleMenuFieldStores();// 角色-菜单-字段
 const RoleUsers = RoleUsersStores();// 角色-用户
 const { crudBinding, crudRef, crudExpose } = useFs({
 	createCrudOptions,
-	context: { RoleDrawer, RoleMenuBtn, RoleMenuField },
+	context: { 
+		RoleDrawer, 
+		RoleMenuBtn, 
+		RoleMenuField,
+		$message: {
+			warning: (msg: string) => successMessage(msg)
+		},
+		openBatchTagsDialog: (selection) => {
+			batchTagsDialogRef.value.open(selection);
+		}
+	},
 });
 
 // 页面打开后获取列表数据
@@ -31,6 +46,5 @@ onMounted(async () => {
 	crudExpose.doRefresh();
 	// 获取全部用户
 	RoleUsers.get_all_users();
-
 });
 </script>