Browse Source

feat(firm-info): 新增企业信息关联部门选择功能

- 后端新增获取可用部门选项接口,支持编辑时排除指定企业ID
- 服务层实现排除已被企业/渠道占用部门的可用部门过滤逻辑
- 前端新增新增企业弹窗,包含部门选择和类型选择功能
- 部门选择组件支持树结构展示和搜索过滤
- 新增按钮改为自定义工具栏按钮,弹出自定义新增对话框
- 新增表单字段校验和异步提交接口调用
- 移除企业实体及表单中的企业编号相关字段及映射
- 优化列表工具栏配置,移除默认新增按钮,适配新弹窗使用方式
SheepHy 1 day ago
parent
commit
a9f0df0f4e
2 changed files with 154 additions and 10 deletions
  1. 13 0
      src/api/toBManage/firm-info-api.ts
  2. 141 10
      src/views/toBManage/firm-info/index.vue

+ 13 - 0
src/api/toBManage/firm-info-api.ts

@@ -105,6 +105,19 @@ const FirmInfoAPI = {
       data,
     });
   },
+
+  /**
+   * 获取可用部门选项(用于新增/编辑企业信息时选择关联部门)
+   *
+   * @param excludeId 编辑时排除的企业ID
+   */
+  getAvailableDeptOptions(excludeId?: number) {
+    return request<any, OptionType[]>({
+      url: `${FIRMINFO_BASE_URL}/availableDeptOptions`,
+      method: "get",
+      params: { excludeId },
+    });
+  },
 };
 
 export default FirmInfoAPI;

+ 141 - 10
src/views/toBManage/firm-info/index.vue

@@ -48,11 +48,42 @@
     </page-content>
 
     <!-- 新增 -->
-    <page-modal
-      ref="addModalRef"
-      :modal-config="addModalConfig"
-      @submit-click="handleSubmitClick"
-    ></page-modal>
+    <el-dialog
+      v-model="addDialogVisible"
+      title="新增"
+      width="500px"
+      draggable
+      @close="handleAddDialogClose"
+    >
+      <el-form ref="addFormRef" :model="addFormData" :rules="addFormRules" label-width="100px">
+        <el-form-item label="类型" prop="firmType">
+          <el-radio-group v-model="addFormData.firmType" @change="handleFirmTypeChange">
+            <el-radio :value="1">企业</el-radio>
+            <el-radio :value="2">渠道</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="名称" prop="deptId">
+          <el-tree-select
+            v-model="addFormData.deptId"
+            :data="availableDeptOptions"
+            :props="{ label: 'label', value: 'value', children: 'children' }"
+            placeholder="请选择部门"
+            check-strictly
+            filterable
+            clearable
+            style="width: 100%"
+            @change="handleDeptChange"
+          />
+        </el-form-item>
+        <el-form-item label="状态" prop="status">
+          <el-switch v-model="addFormData.status" :active-value="1" :inactive-value="0" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="addDialogVisible = false">取消</el-button>
+        <el-button type="primary" :loading="addLoading" @click="handleAddSubmit">确定</el-button>
+      </template>
+    </el-dialog>
 
     <!-- 编辑 -->
     <page-modal
@@ -116,15 +147,25 @@ import usePage from "@/components/CURD/usePage";
 import html2canvas from "html2canvas";
 import { ElMessage } from "element-plus";
 
+// 可用部门选项
+const availableDeptOptions = ref<OptionType[]>([]);
+
+// 加载可用部门选项
+const loadAvailableDeptOptions = async (excludeId?: number) => {
+  try {
+    availableDeptOptions.value = await FirmInfoAPI.getAvailableDeptOptions(excludeId);
+  } catch (error) {
+    console.error("加载部门选项失败:", error);
+  }
+};
+
 // 组合式 CRUD
 const {
   searchRef,
   contentRef,
-  addModalRef,
   editModalRef,
   handleQueryClick,
   handleResetClick,
-  handleAddClick,
   handleEditClick,
   handleSubmitClick,
   handleExportClick,
@@ -132,6 +173,83 @@ const {
   handleFilterChange,
 } = usePage();
 
+// 新增弹窗相关
+const addDialogVisible = ref(false);
+const addLoading = ref(false);
+const addFormRef = ref();
+const addFormData = reactive<FirmInfoForm>({
+  firmType: 1,
+  deptId: undefined,
+  name: "",
+  status: 1,
+});
+const addFormRules = {
+  firmType: [{ required: true, message: "请选择类型", trigger: "change" }],
+  deptId: [{ required: true, message: "请选择部门", trigger: "change" }],
+};
+
+// 点击新增按钮
+const handleAddClick = async () => {
+  // 重置表单
+  addFormData.firmType = 1;
+  addFormData.deptId = undefined;
+  addFormData.name = "";
+  addFormData.status = 1;
+  // 加载可用部门
+  await loadAvailableDeptOptions();
+  addDialogVisible.value = true;
+};
+
+// 关闭新增弹窗
+const handleAddDialogClose = () => {
+  addFormRef.value?.resetFields();
+};
+
+// 类型变化时重新加载部门选项
+const handleFirmTypeChange = () => {
+  addFormData.deptId = undefined;
+  addFormData.name = "";
+};
+
+// 部门选择变化
+const handleDeptChange = (deptId: number) => {
+  // 查找选中的部门名称
+  const findDeptName = (options: OptionType[], id: number): string | undefined => {
+    for (const opt of options) {
+      if (opt.value === id) {
+        return opt.label;
+      }
+      if (opt.children && opt.children.length > 0) {
+        const found = findDeptName(opt.children, id);
+        if (found) return found;
+      }
+    }
+    return undefined;
+  };
+  const deptName = findDeptName(availableDeptOptions.value, deptId);
+  addFormData.name = deptName || "";
+};
+
+// 提交新增
+const handleAddSubmit = async () => {
+  if (!addFormRef.value) return;
+  await addFormRef.value.validate(async (valid: boolean) => {
+    if (valid) {
+      addLoading.value = true;
+      try {
+        await FirmInfoAPI.create(addFormData);
+        ElMessage.success("新增成功");
+        addDialogVisible.value = false;
+        handleQueryClick();
+      } catch (error) {
+        console.error("新增失败:", error);
+      } finally {
+        addLoading.value = false;
+      }
+    }
+  });
+};
+
 // 金额格式化函数
 const formatMoney = (value: number | undefined | null): string => {
   if (value === null || value === undefined) return "0.00";
@@ -214,8 +332,19 @@ const contentConfig: IContentConfig<FirmInfoPageQuery> = reactive({
     pageSize: 20,
     pageSizes: [10, 20, 30, 50],
   },
-  // 工具栏配置
-  toolbar: ["add", "delete"],
+  // 工具栏配置 - 移除默认的add,使用自定义新增
+  toolbar: [
+    {
+      name: "customAdd",
+      text: "新增",
+      perm: "add",
+      attrs: {
+        type: "success",
+        icon: "plus",
+      },
+    },
+    "delete",
+  ],
   defaultToolbar: ["refresh", "filter"],
   // 表格列配置
   cols: [
@@ -481,7 +610,9 @@ const dowloadQrCode = () => {
 
 // 处理工具栏按钮点击(删除等)
 const handleToolbarClick = (name: string) => {
-  console.log(name);
+  if (name === "customAdd") {
+    handleAddClick();
+  }
 };
 </script>