ソースを参照

修复权限问题

沐梦. 3 日 前
コミット
5514ccc010

+ 1 - 1
src/api/customer/customerInfo/index.ts

@@ -76,7 +76,7 @@ export function listCustomerListPage(query?: any) {
  */
 export function listValidCustomer(query?: any) {
   return request({
-    url: '/customer/customerInfo/customerList',
+    url: '/customer/customerInfo/list',
     method: 'get',
     params: {
       ...query,

+ 12 - 2
src/views/common/businessActivity.vue

@@ -32,8 +32,18 @@
                 </div>
               </div>
               <div class="user-ops">
-                <el-button link class="btn-edit" @click="handleEditMember(item)">编辑</el-button>
-                <el-button link class="btn-delete" @click="handleDeleteMember(item)">删除</el-button>
+                <el-button 
+                  v-if="!( (computedDataType === 12 && (item.roleCode === '1' || item.roleCode === 'B0001' || item.roleCode === '3')) || ((computedDataType === 1 || computedDataType === 2) && (item.roleCode === '1' || item.roleCode === '3')) )" 
+                  link 
+                  class="btn-edit" 
+                  @click="handleEditMember(item)"
+                >编辑</el-button>
+                <el-button 
+                  v-if="!( (computedDataType === 12 && (item.roleCode === '1' || item.roleCode === 'B0001' || item.roleCode === '3')) || ((computedDataType === 1 || computedDataType === 2) && (item.roleCode === '1' || item.roleCode === '3')) )" 
+                  link 
+                  class="btn-delete" 
+                  @click="handleDeleteMember(item)"
+                >删除</el-button>
               </div>
             </div>
           </div>

+ 7 - 1
src/views/customer/valid/index.vue

@@ -191,11 +191,13 @@ import { listLevel } from "@/api/customer/customerLevel";
 import { listComStaff } from "@/api/system/comStaff/index";
 import { deptTreeSelect } from "@/api/system/dept";
 import { debounce } from 'lodash-es';
+import { useUserStore } from "@/store/modules/user";
 import CustomerDetail from "./detail.vue";
 
 const proxy = getCurrentInstance().proxy;
 const { Q0001: corpTypeOptions, cooperation_status: cooperationOptions } = toRefs(reactive(proxy.useDict("Q0001", "cooperation_status")));
 const router = useRouter();
+const userStore = useUserStore();
 
 const loading = ref(false);
 const total = ref(0);
@@ -224,7 +226,11 @@ const handleTabClick = (key) => {
   queryParams.serviceStaffId = undefined;
 
   if (key === 'mine') {
-    // 待对接当前用户信息
+    const currentStaff = staffOptions.value.find(s => String(s.userId) === String(userStore.userId));
+    if (currentStaff) {
+      queryParams.salesPersonId = currentStaff.staffId;
+      queryParams.serviceStaffId = currentStaff.staffId;
+    }
   }
   handleQuery();
 };

+ 18 - 2
src/views/saleManage/leads/add.vue

@@ -114,6 +114,18 @@
                 </el-select>
               </el-form-item>
             </el-col>
+            <el-col :span="12">
+              <el-form-item label="产品支持" prop="productSupport">
+                <el-select v-model="form.productSupport" placeholder="请选择" filterable style="width: 100%" clearable @change="handleProductSupportChange">
+                  <el-option
+                    v-for="item in userOptions"
+                    :key="item.staffId"
+                    :label="item.staffName"
+                    :value="item.staffId"
+                  />
+                </el-select>
+              </el-form-item>
+            </el-col>
           </el-row>
         </div>
 
@@ -248,7 +260,9 @@ const localCustomerOptions = ref([]);
 const form = reactive({
   izClue: 1,
   status: '1',
-  fileNo: ''
+  fileNo: '',
+  productSupport: undefined,
+  productSupportName: undefined
 });
 
 const rules = reactive({
@@ -310,7 +324,9 @@ const reset = () => {
     status: '1',
     fileNo: '',
     activityNo: undefined,
-    profession: undefined
+    profession: undefined,
+    productSupport: undefined,
+    productSupportName: undefined
   });
   fileList.value = [];
   if (formRef.value) formRef.value.resetFields();

+ 26 - 0
src/views/saleManage/leads/edit.vue

@@ -101,6 +101,15 @@
               </el-form-item>
             </el-col>
           </el-row>
+          <el-row :gutter="30">
+            <el-col :span="12">
+              <el-form-item label="产品支持" prop="productSupport">
+                <el-select v-model="form.productSupport" placeholder="请选择" filterable style="width: 100%" clearable @change="handleProductSupportChange">
+                  <el-option v-for="item in computedProductSupportOptions" :key="item.staffId" :label="item.staffName" :value="String(item.staffId)" />
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
         </div>
 
         <div class="form-section">
@@ -252,6 +261,15 @@ const computedUserOptions = computed(() => {
   return options;
 });
 
+const computedProductSupportOptions = computed(() => {
+  const options = [...(props.userOptions || [])];
+  if (form.productSupport && form.productSupportName) {
+    const exists = options.some(i => String(i.staffId) === String(form.productSupport));
+    if (!exists) options.unshift({ staffId: form.productSupport, staffName: form.productSupportName });
+  }
+  return options;
+});
+
 const computedCompanyOptions = computed(() => {
   const options = [...(props.companyOptions || [])];
   if (form.companyNo && form.companyName) {
@@ -290,6 +308,7 @@ const loadDetail = (id) => {
     if (form.companyNo !== undefined && form.companyNo !== null) form.companyNo = String(form.companyNo);
     if (form.customerNo !== undefined && form.customerNo !== null) form.customerNo = String(form.customerNo);
     if (form.leader !== undefined && form.leader !== null) form.leader = String(form.leader);
+    if (form.productSupport !== undefined && form.productSupport !== null) form.productSupport = String(form.productSupport);
     if (form.projectLevel !== undefined && form.projectLevel !== null) form.projectLevel = String(form.projectLevel);
     if (form.procurementMethod !== undefined && form.procurementMethod !== null) form.procurementMethod = String(form.procurementMethod);
     if (form.activityNo !== undefined && form.activityNo !== null) form.activityNo = String(form.activityNo);
@@ -344,6 +363,13 @@ const handleLeaderChange = (id) => {
   }
 };
 
+const handleProductSupportChange = (id) => {
+  const staff = props.userOptions.find(i => i.staffId === id);
+  if (staff) {
+    form.productSupportName = staff.staffName;
+  }
+};
+
 const handleUploadSuccess = (res) => {
   if (res.code === 200) {
     fileList.value.push({ 

+ 19 - 1
src/views/saleManage/leads/index.vue

@@ -278,6 +278,12 @@
           </el-select>
         </el-form-item>
 
+        <el-form-item label="产品支持" required>
+          <el-select v-model="claimForm.productSupport" filterable placeholder="请选择" style="width: 100%">
+            <el-option v-for="item in userOptions" :key="item.staffId" :label="item.staffName" :value="item.staffId" />
+          </el-select>
+        </el-form-item>
+
         <el-form-item label="保留已有项目负责人" required>
           <el-radio-group v-model="claimForm.keepOldManager">
             <el-radio :value="true">是</el-radio>
@@ -342,7 +348,9 @@ const claimForm = reactive({
   ids: [],
   leader: undefined,
   currentLeaderName: '',
-  keepOldManager: false
+  keepOldManager: false,
+  productSupport: undefined,
+  productSupportName: ''
 });
 const userStore = useUserStore();
 const { 
@@ -492,6 +500,8 @@ const handleBatchClaim = () => {
   claimForm.leader = undefined; // 不再默认回显自己
   claimForm.currentLeaderName = '';
   claimForm.keepOldManager = false;
+  claimForm.productSupport = undefined;
+  claimForm.productSupportName = '';
   claimOpen.value = true;
 };
 
@@ -502,6 +512,8 @@ const handleClaim = (row) => {
   claimForm.leader = (row.leader && !isSelf) ? String(row.leader) : undefined;
   claimForm.currentLeaderName = isSelf ? '' : (row.leaderName || '');
   claimForm.keepOldManager = false;
+  claimForm.productSupport = row.productSupport ? String(row.productSupport) : undefined;
+  claimForm.productSupportName = row.productSupportName || findUserName(row.productSupport) || '';
   claimOpen.value = true;
 };
 
@@ -512,10 +524,16 @@ const submitClaim = () => {
     proxy.$modal.msgError("请选择项目负责人");
     return;
   }
+  if (!claimForm.productSupport) {
+    proxy.$modal.msgError("请选择产品支持");
+    return;
+  }
   const leaderName = computedClaimUserOptions.value.find(i => String(i.staffId) === String(claimForm.leader))?.staffName;
+  const productSupportName = userOptions.value.find(i => String(i.staffId) === String(claimForm.productSupport))?.staffName;
   const params = {
     ...claimForm,
     leaderName,
+    productSupportName,
     // 兼容性字段补全
     leaderId: claimForm.leader,
     managerId: claimForm.leader,

+ 11 - 1
src/views/saleManage/platformSelection/add.vue

@@ -72,7 +72,16 @@
                 <el-input v-model="drawerForm.platformName" placeholder="请输入平台名称" />
               </el-form-item>
             </el-col>
-            <el-col :span="16">
+            <el-col :span="8">
+              <el-form-item label="产品支持" prop="productSupport" label-for="productSupportSelect">
+                <el-select id="productSupportSelect" v-model="drawerForm.productSupport" style="width:100%" placeholder="请选择" filterable clearable>
+                  <el-option v-for="item in options.user" :key="item.userId || item.staffId" :label="item.nickName || item.staffName" :value="String(item.userId || item.staffId)" />
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="24">
               <el-form-item label="平台链接" prop="platformLink">
                 <el-input v-model="drawerForm.platformLink" placeholder="请输入平台链接" />
               </el-form-item>
@@ -309,6 +318,7 @@ const drawerFormRef = ref(null);
 const drawerForm = ref({
   projectStatus: 1,
   bidPeriodType: 1,
+  productSupport: undefined,
   fileList: [],
   memberList: []
 });

+ 20 - 17
src/views/saleManage/platformSelection/detail.vue

@@ -61,6 +61,8 @@
                     <el-descriptions-item label="项目状态">{{ getStatusLabel(drawerForm.projectStatus) }}</el-descriptions-item>
                     <el-descriptions-item label="项目级别">{{ displayProjectLevelName }}</el-descriptions-item>
                     <el-descriptions-item label="项目类型">{{ displayProjectTypeName }}</el-descriptions-item>
+                    <el-descriptions-item label="负责人">{{ drawerForm.leaderName || findUserName(drawerForm.leader) }}</el-descriptions-item>
+                    <el-descriptions-item label="产品支持">{{ drawerForm.productSupportName || findUserName(drawerForm.productSupport) }}</el-descriptions-item>
                     <el-descriptions-item label="平台名称" :span="2">{{ drawerForm.platformName }}</el-descriptions-item>
                     <el-descriptions-item label="平台链接" :span="3">{{ drawerForm.platformLink }}</el-descriptions-item>
                   </el-descriptions>
@@ -1065,17 +1067,18 @@ const displayIndustryName = computed(() => {
   if (drawerForm.value.industryCategoryName && isNaN(Number(drawerForm.value.industryCategoryName))) return drawerForm.value.industryCategoryName;
   if (drawerForm.value.industry && isNaN(Number(drawerForm.value.industry))) return drawerForm.value.industry;
   
-  // 否则通过 ID 查找
+const flatten = (list) => {
+  let res = [];
+  list.forEach(i => {
+    res.push(i);
+    if (i.children) res = res.concat(flatten(i.children));
+  });
+  return res;
+};
+
+// 否则通过 ID 查找
   const professionId = drawerForm.value.profession || drawerForm.value.industry;
   if (professionId && props.options.industryList) {
-    const flatten = (list) => {
-      let res = [];
-      list.forEach(i => {
-        res.push(i);
-        if (i.children) res = res.concat(flatten(i.children));
-      });
-      return res;
-    };
     const flatList = flatten(props.options.industryList);
     const found = flatList.find(i => String(i.id) === String(professionId))?.industryCategoryName || '';
     if (found) return found;
@@ -1089,20 +1092,20 @@ const displayDeptName = computed(() => {
   if (name && isNaN(Number(name))) return name;
 
   // 第二兑底:通过部门 ID 在父组件传入的部门树中反查
-  const deptId = drawerForm.value.deptNo || drawerForm.value.deptId ||
-                 drawerForm.value.createDept || (isNaN(Number(name)) ? '' : name);
-  if (deptId && props.options?.dept?.length) {
-    const flatten = (list) => {
-      let res = [];
-      list.forEach(i => { res.push(i); if (i.children) res = res.concat(flatten(i.children)); });
-      return res;
-    };
+  const deptId = drawerForm.value.deptNo || drawerForm.value.deptId;
+  if (deptId && props.options.dept) {
     const found = flatten(props.options.dept).find(d => String(d.id) === String(deptId));
     if (found) return found.label || found.deptName || '';
   }
   return '';
 });
 
+const findUserName = (id) => {
+  if (!id) return '';
+  const user = props.options.user?.find(u => String(u.userId || u.staffId || u.id) === String(id));
+  return user ? (user.nickName || user.staffName || user.name) : id;
+};
+
 </script>
 
 <style scoped lang="scss">

+ 44 - 1
src/views/saleManage/platformSelection/edit.vue

@@ -71,7 +71,16 @@
                 <el-input v-model="drawerForm.platformName" placeholder="请输入平台名称" />
               </el-form-item>
             </el-col>
-            <el-col :span="16">
+            <el-col :span="8">
+              <el-form-item label="产品支持" prop="productSupport" label-for="productSupportSelect">
+                <el-select id="productSupportSelect" v-model="drawerForm.productSupport" style="width:100%" placeholder="请选择" filterable clearable @change="handleProductSupportChange">
+                  <el-option v-for="item in computedProductSupportOptions" :key="item.userId || item.staffId" :label="item.nickName || item.staffName" :value="String(item.userId || item.staffId)" />
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="24">
               <el-form-item label="平台链接" prop="platformLink">
                 <el-input v-model="drawerForm.platformLink" placeholder="请输入平台链接" />
               </el-form-item>
@@ -300,6 +309,24 @@ const computedUserOptions = computed(() => {
   return list;
 });
 
+const computedProductSupportOptions = computed(() => {
+  const list = [...(props.options.user || [])];
+  const supportId = drawerForm.value.productSupport;
+  if (supportId) {
+    const exists = list.some(u => String(u.userId || u.staffId) === String(supportId));
+    if (!exists && (drawerForm.value.productSupportName || drawerForm.value.staffSupportName)) {
+      const name = drawerForm.value.productSupportName || drawerForm.value.staffSupportName;
+      list.unshift({
+        userId: supportId,
+        staffId: supportId,
+        nickName: name,
+        staffName: name
+      });
+    }
+  }
+  return list;
+});
+
 const remoteSearchCustomer = async (query) => {
   customerLoading.value = true;
   try {
@@ -368,9 +395,16 @@ const loadData = async () => {
       customName: data.customName || data.customerName, // 字段映射增强
       leader: data.leader ? String(data.leader) : (data.leaderId ? String(data.leaderId) : ''),
       leaderName: data.leaderName || data.staffName,
+      productSupport: data.productSupport ? String(data.productSupport) : '',
       shortlistedRequirement: data.shortlistedRequirement || data.condition || data.requirement,
       finalizationType: data.finalizationType || data.shortlistedType
     };
+
+    // 补全 productSupportName
+    if (data.productSupport) {
+      const user = props.options.user?.find(u => String(u.userId || u.staffId) === String(data.productSupport));
+      drawerForm.value.productSupportName = user ? (user.nickName || user.staffName) : '';
+    }
     if (data.fileNo) {
       const ossRes = await listByIds(data.fileNo);
       drawerForm.value.fileList = (ossRes.data || []).map(i => ({
@@ -395,6 +429,15 @@ const loadData = async () => {
   }
 };
 
+const handleProductSupportChange = (val) => {
+  const user = computedProductSupportOptions.value.find(u => String(u.userId || u.staffId) === String(val));
+  if (user) {
+    drawerForm.value.productSupportName = user.nickName || user.staffName;
+  } else {
+    drawerForm.value.productSupportName = undefined;
+  }
+};
+
 const handleSubmit = async () => {
   if (!drawerFormRef.value) return;
   await drawerFormRef.value.validate(async (valid) => {

+ 9 - 0
src/views/saleManage/projectSelection/add.vue

@@ -63,6 +63,13 @@
                   </el-select>
                 </el-form-item>
               </el-col>
+              <el-col :span="8">
+                <el-form-item label="产品支持" prop="productSupport">
+                  <el-select v-model="form.productSupport" placeholder="请选择" style="width: 100%" clearable filterable>
+                    <el-option v-for="item in userOptions" :key="item.staffId || item.userId" :label="item.staffName || item.nickName" :value="String(item.staffId || item.userId)" />
+                  </el-select>
+                </el-form-item>
+              </el-col>
             </el-row>
             <el-form-item label="项目名称" prop="projectName">
               <el-input v-model="form.projectName" placeholder="请输入项目名称" />
@@ -241,6 +248,7 @@ const form = reactive({
   signUpDeadline: undefined,
   leader: undefined,
   leaderName: undefined,
+  productSupport: undefined,
   serviceTime: undefined
 });
 
@@ -277,6 +285,7 @@ const reset = () => {
     businessType: undefined,
     projectLevel: undefined,
     leader: undefined,
+    productSupport: undefined,
     projectName: undefined,
     amount: undefined,
     entryFee: undefined,

+ 7 - 0
src/views/saleManage/projectSelection/detail.vue

@@ -62,6 +62,7 @@
                   <el-descriptions-item label="项目状态">{{ getStatusLabel(detailData.projectStatus) }}</el-descriptions-item>
                   <el-descriptions-item label="项目级别">{{ getLevelLabel(detailData.projectLevel) }}</el-descriptions-item>
                   <el-descriptions-item label="项目类型">{{ getTypeLabel(detailData.businessType) }}</el-descriptions-item>
+                  <el-descriptions-item label="产品支持">{{ detailData.productSupportName || findUserName(detailData.productSupport) }}</el-descriptions-item>
                 </el-descriptions>
               </div>
 
@@ -916,6 +917,12 @@ const findCompanyName = (val) => {
   return company ? (company.companyName || company.deptName || company.name) : (detailData.value.companyName || value);
 };
 
+const findUserName = (id) => {
+  if (!id) return '';
+  const user = props.userOptions?.find(u => String(u.staffId || u.userId || u.id) === String(id));
+  return user ? (user.staffName || user.nickName) : id;
+};
+
 const getList = () => { emit('success'); };
 
 defineExpose({ open });

+ 32 - 0
src/views/saleManage/projectSelection/edit.vue

@@ -64,6 +64,13 @@
                   </el-select>
                 </el-form-item>
               </el-col>
+              <el-col :span="8">
+                <el-form-item label="产品支持" prop="productSupport">
+                  <el-select v-model="form.productSupport" placeholder="请选择" style="width: 100%" clearable filterable @change="handleProductSupportChange">
+                    <el-option v-for="item in computedProductSupportOptions" :key="item.staffId || item.userId" :label="item.staffName || item.nickName" :value="String(item.staffId || item.userId)" />
+                  </el-select>
+                </el-form-item>
+              </el-col>
             </el-row>
             <el-form-item label="项目名称" prop="projectName">
               <el-input v-model="form.projectName" placeholder="请输入项目名称" />
@@ -273,6 +280,15 @@ const computedUserOptions = computed(() => {
   return options;
 });
 
+const computedProductSupportOptions = computed(() => {
+  const options = [...(props.userOptions || [])];
+  if (form.productSupport && form.productSupportName) {
+    const exists = options.some(i => String(i.staffId || i.userId) === String(form.productSupport));
+    if (!exists) options.unshift({ staffId: form.productSupport, staffName: form.productSupportName });
+  }
+  return options;
+});
+
 const computedCustomerOptions = computed(() => {
   const options = [...customerOptions.value];
   if (form.customNo && form.customName) {
@@ -297,11 +313,18 @@ const loadDetail = (id) => {
     // 强制转字符串以适配回显
     form.companyNo = data.companyNo ? String(data.companyNo) : '';
     form.leader = data.leader ? String(data.leader) : '';
+    form.productSupport = data.productSupport ? String(data.productSupport) : '';
     form.projectLevel = data.projectLevel ? String(data.projectLevel) : '';
     form.businessType = data.businessType ? String(data.businessType) : '';
     form.shortlistedType = data.shortlistedType ? String(data.shortlistedType) : '';
     form.profession = data.profession ? String(data.profession) : '';
 
+    // 补全 productSupportName
+    if (data.productSupport) {
+      const user = props.userOptions.find(u => String(u.staffId || u.userId) === String(data.productSupport));
+      form.productSupportName = user ? (user.staffName || user.nickName) : '';
+    }
+
     // 字段回显增强:将 VO/DTO 字段名映射回 Entity 字段名
     if (data.customerName && !data.customName) form.customName = data.customerName;
     if (data.winRate && !data.winningRate) form.winningRate = data.winRate;
@@ -365,6 +388,15 @@ const handleLeaderChange = (val) => {
   }
 };
 
+const handleProductSupportChange = (val) => {
+  const user = computedProductSupportOptions.value.find(u => String(u.staffId || u.userId) === String(val));
+  if (user) {
+    form.productSupportName = user.staffName || user.nickName;
+  } else {
+    form.productSupportName = undefined;
+  }
+};
+
 const handleUploadSuccess = (res) => {
   if (res.code === 200) {
     fileList.value.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId });