Procházet zdrojové kódy

feat(inspection): 新增/编辑弹窗门店改下拉(总部+门店) + storeId 强转 string 匹配

yangjingjing před 1 dnem
rodič
revize
8c2c059e36

+ 42 - 7
src/views/risk/inspectionTask/index.vue

@@ -163,8 +163,17 @@
         </el-row>
         <el-row :gutter="20">
           <el-col :span="12">
-            <el-form-item label="门店" prop="storeName">
-              <el-input v-model="form.storeName" placeholder="请输入门店/总部名称" maxlength="100" />
+            <el-form-item label="门店" prop="storeId">
+              <el-select
+                v-model="form.storeId"
+                placeholder="请选择总部/门店"
+                style="width: 100%"
+                filterable
+                clearable
+                @change="onStoreChange"
+              >
+                <el-option v-for="d in storeOptions" :key="d.value" :label="d.label" :value="d.value" />
+              </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -511,7 +520,8 @@ const recordLoading = ref(false);
 // 责任人/审核人选择器数据(当前登录用户所在部门及所有下级部门用户)
 const deptChainUserOptions = ref<UserVO[]>([]);
 // 门店下拉(集团总部 + 65 个门店,dept_category='门店')
-const storeOptions = ref<Array<{ label: string; value: number }>>([]);
+// value 用 string 与后端返回的 storeId (JSON 大数防精度丢失) 严格匹配
+const storeOptions = ref<Array<{ label: string; value: string }>>([]);
 // 字典
 const {
   risk_inspection_type: inspection_type_dict,
@@ -561,6 +571,7 @@ const data = reactive<any>({
     id: undefined,
     taskName: '',
     taskType: '',
+    storeId: undefined as string | undefined,
     storeName: '',
     location: '',
     cycle: '每日',
@@ -581,7 +592,7 @@ const data = reactive<any>({
     pageSize: 10,
     taskName: '',
     taskType: '',
-    storeId: undefined as number | undefined,
+    storeId: undefined as string | undefined,
     recordStatus: '',
     checkResult: ''
   },
@@ -589,7 +600,7 @@ const data = reactive<any>({
     taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
     taskType: [{ required: true, message: '请选择巡检类型', trigger: 'change' }],
     cycle: [{ required: true, message: '请选择巡检周期', trigger: 'change' }],
-    storeName: [{ required: true, message: '请输入门店', trigger: 'blur' }],
+    storeId: [{ required: true, message: '请选择门店/总部', trigger: 'change' }],
     location: [{ required: true, message: '请输入位置区域', trigger: 'blur' }],
     inspectorId: [{ required: true, message: '请选择责任人', trigger: 'change' }],
     auditorId: [{ required: true, message: '请选择审核人', trigger: 'change' }]
@@ -643,6 +654,7 @@ const resetForm = () => {
     id: undefined,
     taskName: '',
     taskType: '',
+    storeId: undefined as string | undefined,
     storeName: '',
     location: '',
     cycle: '每日',
@@ -702,6 +714,18 @@ const onAuditorChange = (val: string | number | undefined) => {
   form.value.auditorName = user?.nickName || user?.userName || '';
 };
 
+/**
+ * 选择门店后,同步回填 storeName 字段
+ */
+const onStoreChange = (val: string | number | undefined) => {
+  if (val === undefined || val === null || val === '') {
+    form.value.storeName = '';
+    return;
+  }
+  const opt = storeOptions.value.find((s) => String(s.value) === String(val));
+  form.value.storeName = opt?.label || '';
+};
+
 const onCycleChange = (val: string) => {
   timeSlotList.value = [];
   weekDayList.value = [];
@@ -756,8 +780,19 @@ const handleUpdate = async (row: RiskInspectionTaskVo) => {
   if (deptChainUserOptions.value.length === 0) {
     await loadDeptChainUsers();
   }
+  if (storeOptions.value.length === 0) {
+    await loadStores();
+  }
   const res = await getInspectionTask(row.id);
   Object.assign(form.value, res.data);
+  // storeId 统一转 string 与 storeOptions.value 严格匹配
+  if (form.value.storeId !== undefined && form.value.storeId !== null) {
+    form.value.storeId = String(form.value.storeId);
+    const opt = storeOptions.value.find((s) => s.value === form.value.storeId);
+    if (opt && !form.value.storeName) {
+      form.value.storeName = opt.label;
+    }
+  }
   // 恢复时间配置
   if (res.data?.timeSlot) {
     timeSlotList.value = res.data.timeSlot.split(',').filter((s: string) => s);
@@ -988,8 +1023,8 @@ const loadStores = async () => {
     storeOptions.value = list
       .filter((d: any) => d.deptCategory === '门店' || d.deptId === 100)
       .filter((d: any) => d.status === '0' || d.status === undefined || d.status === null)
-      .map((d: any) => ({ label: d.deptName, value: d.deptId }))
-      .sort((a, b) => a.value - b.value);
+      .map((d: any) => ({ label: d.deptName, value: String(d.deptId) }))
+      .sort((a, b) => Number(a.value) - Number(b.value));
   } catch (e) {
     console.error('加载门店列表失败', e);
     storeOptions.value = [];

+ 37 - 3
src/views/risk/qualityInspectionTask/index.vue

@@ -164,8 +164,17 @@
         </el-row>
         <el-row :gutter="20">
           <el-col :span="12">
-            <el-form-item label="门店" prop="storeName">
-              <el-input v-model="form.storeName" placeholder="请输入门店/总部名称" maxlength="100" />
+            <el-form-item label="门店" prop="storeId">
+              <el-select
+                v-model="form.storeId"
+                placeholder="请选择总部/门店"
+                style="width: 100%"
+                filterable
+                clearable
+                @change="onStoreChange"
+              >
+                <el-option v-for="d in storeOptions" :key="d.value" :label="d.label" :value="d.value" />
+              </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -562,6 +571,7 @@ const data = reactive<any>({
     id: undefined,
     taskName: '',
     taskType: '',
+    storeId: undefined as number | undefined,
     storeName: '',
     location: '',
     cycle: '每日',
@@ -590,7 +600,7 @@ const data = reactive<any>({
     taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
     taskType: [{ required: true, message: '请选择巡检类型', trigger: 'change' }],
     cycle: [{ required: true, message: '请选择巡检周期', trigger: 'change' }],
-    storeName: [{ required: true, message: '请输入门店', trigger: 'blur' }],
+    storeId: [{ required: true, message: '请选择门店/总部', trigger: 'change' }],
     location: [{ required: true, message: '请输入位置区域', trigger: 'blur' }],
     inspectorId: [{ required: true, message: '请选择责任人', trigger: 'change' }],
     auditorId: [{ required: true, message: '请选择审核人', trigger: 'change' }]
@@ -645,6 +655,7 @@ const resetForm = () => {
     id: undefined,
     taskName: '',
     taskType: '',
+    storeId: undefined as number | undefined,
     storeName: '',
     location: '',
     cycle: '每日',
@@ -704,6 +715,18 @@ const onAuditorChange = (val: string | number | undefined) => {
   form.value.auditorName = user?.nickName || user?.userName || '';
 };
 
+/**
+ * 选择门店后,同步回填 storeName 字段
+ */
+const onStoreChange = (val: string | number | undefined) => {
+  if (val === undefined || val === null || val === '') {
+    form.value.storeName = '';
+    return;
+  }
+  const opt = storeOptions.value.find((s) => s.value === val);
+  form.value.storeName = opt?.label || '';
+};
+
 const onCycleChange = (val: string) => {
   timeSlotList.value = [];
   weekDayList.value = [];
@@ -758,8 +781,19 @@ const handleUpdate = async (row: RiskInspectionTaskVo) => {
   if (deptChainUserOptions.value.length === 0) {
     await loadDeptChainUsers();
   }
+  if (storeOptions.value.length === 0) {
+    await loadStores();
+  }
   const res = await getQualityInspectionTask(row.id);
   Object.assign(form.value, res.data);
+  // 后端返回的 storeId 可能是 string(JSON 序列化大数防精度丢失),统一转 number 匹配 storeOptions
+  if (form.value.storeId !== undefined && form.value.storeId !== null) {
+    form.value.storeId = Number(form.value.storeId);
+    const opt = storeOptions.value.find((s) => s.value === form.value.storeId);
+    if (opt && !form.value.storeName) {
+      form.value.storeName = opt.label;
+    }
+  }
   // 恢复时间配置
   if (res.data?.timeSlot) {
     timeSlotList.value = res.data.timeSlot.split(',').filter((s: string) => s);