Browse Source

feature(项目): 项目管理更改字段添加审批流

ZZH-wl 2 years ago
parent
commit
1b75447594

+ 11 - 3
src/api/proj/business.js

@@ -18,14 +18,22 @@ export default {
   doDelete(query) {
     return micro_request.postRequest(basePath, 'Business', 'DeleteByIds', query)
   },
-  // 项目调级
-  businessGradation(query) {
-    return micro_request.postRequest(basePath, 'Business', 'BusinessGradation', query)
+  // 项目升级
+  businessUpgrade(query) {
+    return micro_request.postRequest(basePath, 'Business', 'BusinessUpgrade', query)
+  },
+  // 项目降级
+  businessDowngrade(query) {
+    return micro_request.postRequest(basePath, 'Business', 'BusinessDowngrade', query)
   },
   // 项目转移
   businessTransfer(query) {
     return micro_request.postRequest(basePath, 'Business', 'BusinessTransfer', query)
   },
+  // 转为储备项目
+  businessConvertToReserve(query) {
+    return micro_request.postRequest(basePath, 'Business', 'ConvertToReserve', query)
+  },
   // 设置首要联系人
   setPrimacyContact(query) {
     return micro_request.postRequest(basePath, 'Business', 'SetPrimacyContact', query)

+ 20 - 31
src/components/currency/index.vue

@@ -8,13 +8,7 @@
 -->
 <template>
   <div>
-    <el-input
-      v-bind="$attrs"
-      v-model.trim="num"
-      @blur="inputMoney($event)"
-      @change="handleChange"
-      @focus="uninputMoney($event)"
-      @input="returnNum" />
+    <el-input v-bind="$attrs" v-model.trim="num" @blur="inputMoney($event)" @focus="uninputMoney($event)" />
   </div>
 </template>
 
@@ -29,43 +23,38 @@
     },
     data() {
       return {
-        num: '',
+        // num: '',
       }
     },
-    watch: {
-      value() {
-        this.num = this.formatPrice(this.value)
+    computed: {
+      num: {
+        get() {
+          if (this.value === '') {
+            return ''
+          }
+          if (this.value.length > 0 && this.value[0] === '¥') {
+            return this.CurrencyFomatNumber(this.value)
+          }
+          return this.formatPrice(this.value)
+        },
+        set(val) {
+          this.$emit('input', val)
+          this.$emit('change', this.CurrencyFomatNumber(val))
+        },
       },
     },
-    mounted() {
-      this.num = this.formatPrice(this.value)
-    },
     methods: {
-      returnNum() {
-        if (this.num) {
-          this.$emit('input', this.CurrencyFomatNumber(this.num))
-        }
-      },
-      handleChange(val) {
-        this.$nextTick(() => {
-          this.$emit('change', this.CurrencyFomatNumber(val))
-        })
-      },
       // 失焦显示数字类型
       inputMoney(el) {
-        let temp = Number(el.target.value) || null
-        this.num = this.formatPrice(temp)
+        this.num = Number(el.target.value) || null
       },
       // 获得焦点金额去掉格式
       uninputMoney(el) {
-        if (el.target.value) {
-          this.num = this.CurrencyFomatNumber(el.target.value)
-        } else {
-          this.num = null
-        }
+        this.num = el.target.value
       },
       //去除千分位中的‘,’
       CurrencyFomatNumber(num, n = 2) {
+        num = String(num)
         let number = num.replace('¥', '')
         if (number != null && number != '' && number != undefined) {
           number = number.replace(/,/g, '') //去除千分位的','

+ 9 - 8
src/components/select/SelectBusiness.vue

@@ -1,16 +1,16 @@
 <template>
   <el-dialog append-to-body :title="title" :visible.sync="innerVisible" @close="close">
-    <el-row>
+    <el-row v-if="add" style="margin-top: -30px">
       <el-col :span="24">
         <div style="float: right">
           <el-button size="mini" type="primary" @click="handleAdd">新建项目</el-button>
-          <el-dropdown style="margin-left: 10px" trigger="click">
-            <el-button icon="el-icon-more" size="mini" />
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>
-              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
+          <!--          <el-dropdown style="margin-left: 10px" trigger="click">-->
+          <!--            <el-button icon="el-icon-more" size="mini" />-->
+          <!--            <el-dropdown-menu slot="dropdown">-->
+          <!--              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>-->
+          <!--              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>-->
+          <!--            </el-dropdown-menu>-->
+          <!--          </el-dropdown>-->
         </div>
       </el-col>
     </el-row>
@@ -97,6 +97,7 @@
         type: String,
         default: '选择项目',
       },
+      add: Boolean,
       multiple: Boolean,
       queryParams: {
         type: Object,

+ 3 - 3
src/components/select/SelectBusinessContact.vue

@@ -23,8 +23,8 @@
         :sortable="item.sortable"
         :width="item.width">
         <template #default="{ row }">
-          <span v-if="item.prop === 'policy'">
-            {{ selectDictLabel(yesNoOptions, row.policy) }}
+          <span v-if="item.prop === 'isDecision'">
+            {{ selectDictLabel(yesNoOptions, row.isDecision) }}
           </span>
           <span v-else-if="item.prop === 'cuctGender'">
             {{ selectDictLabel(sexOptions, row.cuctGender) }}
@@ -124,7 +124,7 @@
           {
             label: '关键决策人',
             width: 'auto',
-            prop: 'policy',
+            prop: 'isDecision',
           },
           {
             label: '性别',

+ 9 - 8
src/components/select/SelectCustomer.vue

@@ -1,16 +1,16 @@
 <template>
   <el-dialog append-to-body :title="title" :visible.sync="innerVisible" @close="close">
-    <el-row>
+    <el-row v-if="add" style="margin-top: -30px">
       <el-col :span="24">
         <div style="float: right">
           <el-button size="mini" type="primary" @click="handleAdd">新建客户</el-button>
-          <el-dropdown style="margin-left: 10px" trigger="click">
-            <el-button icon="el-icon-more" size="mini" />
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>
-              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
+          <!--          <el-dropdown style="margin-left: 10px" trigger="click">-->
+          <!--            <el-button icon="el-icon-more" size="mini" />-->
+          <!--            <el-dropdown-menu slot="dropdown">-->
+          <!--              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>-->
+          <!--              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>-->
+          <!--            </el-dropdown-menu>-->
+          <!--          </el-dropdown>-->
         </div>
       </el-col>
     </el-row>
@@ -89,6 +89,7 @@
         type: String,
         default: '选择客户',
       },
+      add: Boolean,
       multiple: Boolean,
       queryParams: {
         type: Object,

+ 12 - 11
src/components/select/SelectCustomerContact.vue

@@ -1,16 +1,16 @@
 <template>
   <el-dialog append-to-body :title="title" :visible.sync="innerVisible" @close="close">
-    <el-row>
+    <el-row v-if="add" style="margin-top: -30px">
       <el-col :span="24">
         <div style="float: right">
           <el-button size="mini" type="primary" @click="handleAdd">新建联系人</el-button>
-          <el-dropdown style="margin-left: 10px" trigger="click">
-            <el-button icon="el-icon-more" size="mini" />
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>
-              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
+          <!--          <el-dropdown style="margin-left: 10px" trigger="click">-->
+          <!--            <el-button icon="el-icon-more" size="mini" />-->
+          <!--            <el-dropdown-menu slot="dropdown">-->
+          <!--              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>-->
+          <!--              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>-->
+          <!--            </el-dropdown-menu>-->
+          <!--          </el-dropdown>-->
         </div>
       </el-col>
     </el-row>
@@ -42,8 +42,8 @@
         :sortable="item.sortable"
         :width="item.width">
         <template #default="{ row }">
-          <span v-if="item.prop === 'policy'">
-            {{ selectDictLabel(yesNoOptions, row.policy) }}
+          <span v-if="item.prop === 'isDecision'">
+            {{ selectDictLabel(yesNoOptions, row.isDecision) }}
           </span>
           <span v-else-if="item.prop === 'cuctGender'">
             {{ selectDictLabel(sexOptions, row.cuctGender) }}
@@ -85,6 +85,7 @@
         type: String,
         default: '选择客户联系人',
       },
+      add: Boolean,
       multiple: Boolean,
       // 示例{ custId: id, custName: custName}
       defaultCustomer: {
@@ -146,7 +147,7 @@
           {
             label: '关键决策人',
             width: 'auto',
-            prop: 'policy',
+            prop: 'isDecision',
           },
           {
             label: '性别',

+ 9 - 8
src/components/select/SelectDistributor.vue

@@ -1,16 +1,16 @@
 <template>
   <el-dialog append-to-body :title="title" :visible.sync="innerVisible" @close="close">
-    <el-row>
+    <el-row v-if="add" style="margin-top: -30px">
       <el-col :span="24">
         <div style="float: right">
           <el-button size="mini" type="primary" @click="handleAdd">新建经销商</el-button>
-          <el-dropdown style="margin-left: 10px" trigger="click">
-            <el-button icon="el-icon-more" size="mini" />
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>
-              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
+          <!--          <el-dropdown style="margin-left: 10px" trigger="click">-->
+          <!--            <el-button icon="el-icon-more" size="mini" />-->
+          <!--            <el-dropdown-menu slot="dropdown">-->
+          <!--              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>-->
+          <!--              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>-->
+          <!--            </el-dropdown-menu>-->
+          <!--          </el-dropdown>-->
         </div>
       </el-col>
     </el-row>
@@ -77,6 +77,7 @@
         type: String,
         default: '选择经销商/代理商',
       },
+      add: Boolean,
       multiple: Boolean,
       queryParams: {
         type: Object,

+ 9 - 8
src/components/select/SelectProduct.vue

@@ -1,16 +1,16 @@
 <template>
   <el-dialog append-to-body :title="title" :visible.sync="innerVisible" @close="close">
-    <el-row>
+    <el-row v-if="add" style="margin-top: -30px">
       <el-col :span="24">
         <div style="float: right">
           <el-button size="mini" type="primary" @click="handleAdd">新建产品</el-button>
-          <el-dropdown style="margin-left: 10px" trigger="click">
-            <el-button icon="el-icon-more" size="mini" />
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>
-              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
+          <!--          <el-dropdown style="margin-left: 10px" trigger="click">-->
+          <!--            <el-button icon="el-icon-more" size="mini" />-->
+          <!--            <el-dropdown-menu slot="dropdown">-->
+          <!--              <el-dropdown-item icon="el-icon-upload2">导入</el-dropdown-item>-->
+          <!--              <el-dropdown-item icon="el-icon-download">导出</el-dropdown-item>-->
+          <!--            </el-dropdown-menu>-->
+          <!--          </el-dropdown>-->
         </div>
       </el-col>
     </el-row>
@@ -77,6 +77,7 @@
         type: String,
         default: '选择产品',
       },
+      add: Boolean,
       multiple: Boolean,
       queryParams: {
         type: Object,

+ 28 - 9
src/views/customer/components/Contact.vue

@@ -32,18 +32,30 @@
             <el-input v-model="contactForm.email" placeholder="请输入邮箱" />
           </el-form-item>
         </el-col>
+        <el-col :span="12">
+          <el-form-item label="部门" prop="dept">
+            <el-input v-model="contactForm.dept" placeholder="请输入部门" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="职务" prop="postion">
             <el-input v-model="contactForm.postion" placeholder="请输入职务" />
           </el-form-item>
         </el-col>
+        <el-col :span="12">
+          <el-form-item label="办公地点" prop="officeLocation">
+            <el-input v-model="contactForm.officeLocation" placeholder="请输入办公地点" />
+          </el-form-item>
+        </el-col>
       </el-row>
       <el-row :gutter="20">
         <el-col :span="12">
-          <el-form-item label="是否关键决策人" prop="policy">
-            <el-radio-group v-model="contactForm.policy">
-              <el-radio :label="0">否</el-radio>
-              <el-radio :label="1">是</el-radio>
+          <el-form-item label="是否关键决策人" prop="isDecision">
+            <el-radio-group v-model="contactForm.isDecision">
+              <el-radio label="10">是</el-radio>
+              <el-radio label="20">否</el-radio>
             </el-radio-group>
           </el-form-item>
         </el-col>
@@ -109,18 +121,24 @@
           custName: '', //客户名称
           cuctName: '', //联系人名字
           cuctGender: '10', //性别(10男20女)
-          postion: '', //职位
           telephone: '', //电话
           wechat: '', //微信
           email: '', //邮箱
+          dept: '', //部门
+          postion: '', //岗位
+          officeLocation: '', //办公地点
+          isDecision: '20', //是否决策人 (10是20否)
           remark: '', //备注
-          policy: 0, //是否决策人 0 不是  1 是
         },
         contactRules: {
           cuctName: [{ required: true, trigger: 'blur', message: '请输入联系人姓名' }],
           custName: [{ required: true, trigger: 'blur', message: '请输入客户名称' }],
+          cuctGender: [{ required: true, trigger: 'blur', message: '请输入性别' }],
+          dept: [{ required: true, trigger: 'blur', message: '请输入部门名称' }],
+          postion: [{ required: true, trigger: 'blur', message: '请输入岗位名称' }],
+          wechat: [{ required: true, trigger: 'blur', message: '请输入微信号' }],
           telephone: [{ required: true, trigger: 'blur', validator: validateTel }],
-          email: [{ trigger: 'blur', validator: validateEmail }],
+          email: [{ required: true, trigger: 'blur', validator: validateEmail }],
         },
       }
     },
@@ -157,12 +175,13 @@
           custName: '', //客户名称
           cuctName: '', //联系人名字
           cuctGender: '10', //性别(10男20女)
-          postion: '', //职位
           telephone: '', //电话
           wechat: '', //微信
           email: '', //邮箱
+          dept: '', //部门
+          postion: '', //职位
+          isDecision: '20', //是否决策人 (10是20否)
           remark: '', //备注
-          policy: 0, //是否决策人 0 不是  1 是
         }
         this.$refs.contactForm.clearValidate()
       },

+ 5 - 1
src/views/customer/detail.vue

@@ -198,7 +198,7 @@
               <el-table-column align="center" label="邮箱" prop="email" />
               <el-table-column align="center" label="是否决策人">
                 <template slot-scope="scope">
-                  <el-switch v-model="scope.row.policy" :active-value="1" disabled :inactive-value="0" />
+                  <el-switch v-model="scope.row.isDecision" active-value="10" disabled inactive-value="20" />
                 </template>
               </el-table-column>
               <el-table-column align="center" label="操作">
@@ -619,6 +619,7 @@
     height: calc(100vh - 60px - 12px * 2 - 40px);
     display: flex;
     padding: 20px 40px;
+
     > .el-row {
       flex: 1;
       width: 100%;
@@ -627,6 +628,7 @@
         height: 100%;
       }
     }
+
     .title {
       p,
       h3 {
@@ -685,8 +687,10 @@
 
         .el-tab-pane {
           height: 100%;
+
           .el-descriptions {
             table-layout: fixed;
+
             .is-bordered {
               table-layout: fixed;
             }

+ 42 - 14
src/views/proj/business/components/BusinessEdit.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-dialog append-to-body :title="title" :visible.sync="dialogFormVisible" @close="close">
+  <el-dialog append-to-body :title="title" :visible.sync="dialogFormVisible" width="60%" @close="close">
     <el-steps :active="activeSteps" align-center style="margin: -15px 0 15px 0">
       <el-step title="创建项目" />
       <el-step title="添加产品" />
@@ -22,11 +22,6 @@
               @focus="handleSelectCustomer" />
           </el-form-item>
         </el-col>
-        <!--        <el-col :span="12">-->
-        <!--          <el-form-item label="获取日期" prop="obtainTime">-->
-        <!--            <el-date-picker v-model="form.obtainTime" placeholder="选择日期" style="width: 100%" type="datetime" />-->
-        <!--          </el-form-item>-->
-        <!--        </el-col>-->
         <el-col :span="8">
           <el-form-item label="项目来源" prop="nboSource">
             <el-select v-model="form.nboSource" clearable placeholder="项目来源" style="width: 100%">
@@ -70,11 +65,25 @@
               @focus="handleSelectDistributor" />
           </el-form-item>
         </el-col>
+        <el-col :span="8">
+          <el-form-item label="产品线" prop="productLine">
+            <el-select v-model="form.productLine" placeholder="请选择" style="width: 100%">
+              <el-option v-for="item in productLineOptions" :key="item.key" :label="item.value" :value="item.key" />
+            </el-select>
+          </el-form-item>
+        </el-col>
         <el-col :span="8">
           <el-form-item label="项目预算" prop="nboBudget">
             <amount-input v-model.trim="form.nboBudget" placeholder="请输入金额" />
           </el-form-item>
         </el-col>
+        <el-col :span="8">
+          <el-form-item label="是否大项目" prop="isBig">
+            <el-select v-model="form.isBig" placeholder="请选择" style="width: 100%">
+              <el-option v-for="item in yesOrNoOptions" :key="item.key" :label="item.value" :value="item.key" />
+            </el-select>
+          </el-form-item>
+        </el-col>
         <!--        <el-col :span="8">-->
         <!--          <el-form-item label="预计成交价格" prop="estTransPrice">-->
         <!--            <amount-input v-model.trim="form.estTransPrice" placeholder="请输入金额" />-->
@@ -115,7 +124,7 @@
           </el-form-item>
         </el-col>
 
-        <el-col :span="16">
+        <el-col :span="24">
           <el-form-item label="备注信息" prop="remark">
             <el-input v-model="form.remark" placeholder="请输入备注信息" rows="3" show-word-limit type="textarea" />
           </el-form-item>
@@ -233,7 +242,9 @@
           saleName: undefined,
           distributorId: undefined,
           distributorName: undefined,
+          productLine: undefined,
           nboBudget: 0,
+          isBig: '20',
           planPurchaseTime: undefined,
           estTransTime: undefined,
           estTransPrice: undefined,
@@ -245,7 +256,7 @@
           products: undefined,
 
           // 跟进
-          followTime: undefined,
+          followTime: new Date(),
           followUserId: undefined,
           followUserName: undefined,
           followContent: undefined,
@@ -260,6 +271,8 @@
           distributorName: [
             { validator: validateDistributor, trigger: ['blur', 'change'], message: '请选择经销商/代理商' },
           ],
+          isBig: [{ required: true, trigger: ['blur', 'change'], message: '请选择是否大项目' }],
+          productLine: [{ required: true, trigger: ['blur', 'change'], message: '请选择产品线' }],
           // 跟进
           followTime: [{ required: true, trigger: ['blur', 'change'], message: '请输入跟进时间' }],
           followContent: [{ required: true, trigger: ['blur', 'change'], message: '请输入跟进内容' }],
@@ -268,6 +281,8 @@
         dialogFormVisible: false,
         nboSourceOptions: [],
         salesModelOptions: [],
+        productLineOptions: [],
+        yesOrNoOptions: [],
         queryContact: {},
         customerInfo: {},
         productData: [],
@@ -283,14 +298,22 @@
     },
     created() {},
     mounted() {
-      this.getDicts('proj_nbo_source').then((response) => {
-        this.nboSourceOptions = response.data.values || []
-      })
-      this.getDicts('proj_sales_model').then((response) => {
-        this.salesModelOptions = response.data.values || []
-      })
+      this.getOptions()
     },
     methods: {
+      getOptions() {
+        Promise.all([
+          this.getDicts('proj_nbo_source'),
+          this.getDicts('proj_sales_model'),
+          this.getDicts('sys_product_line'),
+          this.getDicts('sys_yes_no'),
+        ]).then(([nboSource, salesModel, productLine, yesOrNo]) => {
+          this.nboSourceOptions = nboSource.data.values || []
+          this.salesModelOptions = salesModel.data.values || []
+          this.productLineOptions = productLine.data.values || []
+          this.yesOrNoOptions = yesOrNo.data.values || []
+        })
+      },
       nextStep() {
         console.log(typeof this.form.nboBudget)
         if (this.activeSteps === 1) {
@@ -433,3 +456,8 @@
     },
   }
 </script>
+<style lang="scss" scoped>
+  .el-form-item--small.el-form-item {
+    margin-bottom: 10px;
+  }
+</style>

+ 257 - 29
src/views/proj/business/components/BusinessGradation.vue

@@ -1,22 +1,145 @@
 <template>
   <div style="display: inline-block; margin: 0 10px">
-    <el-button :disabled="nboType === 'A'" type="primary" @click="handleClick('升级')">升级</el-button>
-    <el-button :disabled="nboType === 'C'" type="danger" @click="handleClick('降级')">降级</el-button>
-    <el-dialog :title="title" :visible.sync="dialogFormVisible" width="500px" @close="close">
-      <el-form ref="form" label-width="80px" :model="form" :rules="rules">
-        <el-form-item label="项目类别" prop="nboType">
+    <el-button :disabled="!['20', '30'].includes(businessInfo.nboType)" type="primary" @click="handleClick('up')">
+      升级
+    </el-button>
+    <el-button :disabled="!['10', '20'].includes(businessInfo.nboType)" type="danger" @click="handleClick('down')">
+      降级
+    </el-button>
+    <el-dialog append-to-body :title="title" :visible.sync="dialogFormVisible" width="60%" @close="close">
+      <el-form ref="form" :model="form" :rules="rules">
+        <el-form-item label="项目级别" prop="nboType">
           <el-select v-model="form.nboType" placeholder="请选择项目类别" style="width: 100%">
-            <el-option :disabled="nboType === 'A'" label="A" value="A" />
-            <el-option label="B" value="B" />
-            <el-option :disabled="nboType === 'C'" label="C" value="C" />
+            <el-option
+              :disabled="
+                (type === 'up' && businessInfo.nboType === '10') ||
+                (type === 'down' && ['10', '20'].includes(businessInfo.nboType))
+              "
+              label="A"
+              value="10" />
+            <el-option :disabled="businessInfo.nboType === '20'" label="B" value="20" />
+            <el-option
+              :disabled="type === 'up' && ['10', '20', '30'].includes(businessInfo.nboType)"
+              label="C"
+              value="30" />
+            <el-option v-if="type === 'down' && businessInfo.nboType === '10'" label="储备" value="50" />
           </el-select>
         </el-form-item>
-        <el-form-item label="备注信息" prop="remark">
+        <!--   C-B     项目预算 经销商/代理商 技术支持时间 技术支持人员 技术支持内容 总部对接人 项目预算期限 资金来源 产品/方案满足情况-->
+        <el-row v-if="type === 'up' && form.nboType !== '30'" :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="项目预算" prop="nboBudget">
+              <amount-input v-model.trim="form.nboBudget" placeholder="请输入金额" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="经销商/代理商" prop="distributorName">
+              <el-input v-model="form.distributorName" readonly @focus="handleSelectDistributor" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="总部对接人" prop="parentReceiver">
+              <el-input v-model="form.parentReceiver" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="技术支持人员" prop="technicalSupportName" :required="type === 'up'">
+              <el-input v-model="form.technicalSupportName" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="技术支持内容" prop="technicalSupportContent">
+              <el-input v-model="form.technicalSupportContent" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="技术支持时间" prop="technicalSupportTime" :required="type === 'up'">
+              <el-date-picker
+                v-model="form.technicalSupportTime"
+                placeholder="选择日期"
+                style="width: 100%"
+                type="datetime" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row v-if="type === 'up' && form.nboType !== '30'" :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="项目预算期限" prop="nboBudgetTime">
+              <el-date-picker v-model="form.nboBudgetTime" placeholder="选择日期" style="width: 100%" type="datetime" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="资金来源" prop="capitalSource">
+              <el-input v-model="form.capitalSource" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="产品/方案满足情况" prop="productSatisfaction">
+              <el-input v-model="form.productSatisfaction" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <!--    B-A    采购方式	采购时间	是否采纳大数技术参数(上传附件)	决策部门	决策人员	经销商与客户历史成交信息	经销商销售人员	维护部门及人员-->
+        <el-row v-if="type === 'up' && form.nboType === '10'" :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="采购方式" prop="purchasingWay">
+              <el-select v-model="form.purchasingWay" placeholder="请选择" style="width: 100%">
+                <el-option v-for="item in purchasingWayOptions" :key="item.key" :label="item.value" :value="item.key" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="采购时间" prop="purchasingTime">
+              <el-date-picker
+                v-model="form.purchasingTime"
+                placeholder="选择日期"
+                style="width: 100%"
+                type="datetime" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="决策人员" prop="makerName">
+              <el-input v-model="form.makerName" readonly @focus="handleSelectContact" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="决策部门" prop="makerDept">
+              <el-input v-model="form.makerDept" readonly />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="经销商与客户历史成交信息" prop="historicalTransactionInfo">
+              <el-input v-model="form.historicalTransactionInfo" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="经销商销售人员" prop="dealerSalesName">
+              <el-input v-model="form.dealerSalesName" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="维护部门及人员" prop="accendant">
+              <el-input v-model="form.accendant" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="是否采纳大数技术参数   " prop="isAdoptDashoo">
+              <el-radio-group v-model="form.isAdoptDashoo">
+                <el-radio label="10">是</el-radio>
+                <el-radio label="20">否</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-form-item label="备注原因" prop="remark">
           <el-input
             v-model="form.remark"
             maxlength="300"
-            placeholder="请输入备注信息"
-            rows="5"
+            placeholder="请输入备注原因"
+            rows="3"
             show-word-limit
             type="textarea" />
         </el-form-item>
@@ -26,14 +149,31 @@
         <el-button type="primary" @click="save">确 定</el-button>
       </template>
     </el-dialog>
+
+    <!-- 选择客户决策人弹窗 -->
+    <select-contact
+      ref="selectContact"
+      :default-customer="customerInfo"
+      :query-params="queryContact"
+      @save="selectContact" />
+    <!-- 选择经销商弹窗 -->
+    <select-distributor ref="selectDistributor" @save="selectDistributor" />
   </div>
 </template>
 
 <script>
   import businessApi from '@/api/proj/business'
+  import AmountInput from '@/components/currency/index.vue'
+  import SelectContact from '@/components/select/SelectCustomerContact'
+  import SelectDistributor from '@/components/select/SelectDistributor'
 
   export default {
     name: 'BusinessGradation',
+    components: {
+      AmountInput,
+      SelectContact,
+      SelectDistributor,
+    },
     props: {
       // 项目Id
       busId: {
@@ -41,30 +181,107 @@
         required: true,
       },
       // 项目类别
-      nboType: {
-        type: String,
+      businessInfo: {
+        type: Object,
         required: true,
-        validator: function (value) {
-          // 这个值必须匹配下列字符串中的一个
-          return ['A', 'B', 'C'].includes(value)
-        },
       },
     },
     data() {
+      const validateTechnicalSupport = (rule, value, callback) => {
+        if (!value && this.type === 'up') callback(new Error('不能为空'))
+        else callback()
+      }
       return {
         title: '项目',
+        type: '',
         form: {
           id: undefined,
+          distributorId: undefined,
+          distributorName: undefined,
+          makerId: undefined,
+          makerName: undefined,
+          makerDept: undefined,
+          makerPost: undefined,
+          makerTelephone: undefined,
+          nboType: undefined,
+          nboBudget: undefined,
+          technicalSupportName: undefined,
+          technicalSupportContent: undefined,
+          technicalSupportTime: undefined,
+          parentReceiver: undefined,
+          nboBudgetTime: undefined,
+          capitalSource: undefined,
+          productSatisfaction: undefined,
+          purchasingWay: undefined,
+          purchasingTime: undefined,
+          isAdoptDashoo: undefined,
+          historicalTransactionInfo: undefined,
+          dealerSalesId: undefined,
+          dealerSalesName: undefined,
+          accendant: undefined,
           remark: undefined,
         },
-        rules: {},
+        rules: {
+          nboType: [{ required: true, trigger: ['blur', 'change'], message: '请选择项目级别' }],
+          nboBudget: [{ required: true, trigger: ['blur', 'change'], message: '请输入项目预算' }],
+          distributorName: [{ required: true, trigger: ['blur', 'change'], message: '请选择经销商/代理商' }],
+          technicalSupportName: [
+            { validator: validateTechnicalSupport, trigger: ['blur', 'change'], message: '请输入技术支持人员' },
+          ],
+          technicalSupportContent: [{ required: true, trigger: ['blur', 'change'], message: '请输入技术支持内容' }],
+          technicalSupportTime: [
+            { validator: validateTechnicalSupport, trigger: ['blur', 'change'], message: '请选择技术支持时间' },
+          ],
+          remark: [{ required: true, trigger: ['blur', 'change'], message: '请输入原因' }],
+        },
         dialogFormVisible: false,
+        yesOrNoOptions: [],
+        purchasingWayOptions: [],
+
+        queryContact: {},
+        customerInfo: {},
       }
     },
+    mounted() {
+      this.getDicts('proj_purchasing_way').then((response) => {
+        this.purchasingWayOptions = response.data.values || []
+      })
+    },
     methods: {
+      handleSelectContact() {
+        if (!this.queryContact.custId) {
+          this.$message.warning('请先选择客户')
+          return
+        }
+        this.$refs.selectContact.open()
+      },
+      selectContact(val) {
+        if (val && val.length > 0) {
+          this.form.makerId = val[0].id
+          this.form.makerName = val.map((item) => item.cuctName)
+          this.form.makerDept = val.map((item) => item.makerDept)
+          this.form.makerPost = val.map((item) => item.postion)
+          this.form.makerTelephone = val.map((item) => item.telephone)
+        }
+      },
+      handleSelectDistributor() {
+        this.$refs.selectDistributor.open()
+      },
+      selectDistributor(val) {
+        if (val && val.length > 0) {
+          this.form.distributorId = val[0].id
+          this.form.distributorName = val.map((item) => item.distName).join()
+        }
+      },
       // 业务调级(升级、降级)
       handleClick(type) {
-        this.title = type
+        if (type === 'up') {
+          this.title = '升级'
+        }
+        if (type === 'down') {
+          this.title = '降级'
+        }
+        this.type = type
         this.form.id = this.busId
         this.dialogFormVisible = true
       },
@@ -78,18 +295,29 @@
         this.dialogFormVisible = false
       },
       save() {
-        // if ((this.title === '降级' && this.nboType === 'A') || (this.title === '升级' && this.nboType === 'C')) {
-        //   this.form.nboType = 'B'
-        // } else {
-        //   this.form.nboType = this.title === '升级' ? 'A' : 'C'
-        // }
-        this.$baseConfirm('你确定要对当前项目' + this.title + '吗', null, async () => {
-          const { msg } = await businessApi.businessGradation(this.form)
-          this.$baseMessage(msg, 'success')
-          this.$emit('fetch-data')
-          this.close()
+        this.$refs['form'].validate(async (valid) => {
+          if (valid) {
+            this.$baseConfirm('你确定要对当前项目' + this.title + '吗', null, async () => {
+              if (this.type === 'up') {
+                const { msg } = await businessApi.businessUpgrade(this.form)
+                this.$baseMessage(msg, 'success')
+              }
+              if (this.type === 'down') {
+                const { msg } = await businessApi.businessDowngrade(this.form)
+                this.$baseMessage(msg, 'success')
+              }
+
+              this.$emit('fetch-data')
+              this.close()
+            })
+          }
         })
       },
     },
   }
 </script>
+<style lang="scss" scoped>
+  .el-form-item--small.el-form-item {
+    margin-bottom: 10px;
+  }
+</style>

+ 3 - 2
src/views/proj/business/components/DetailsContact.vue

@@ -21,10 +21,11 @@
       <el-table-column align="center" label="岗位" prop="postion" show-overflow-tooltip />
       <el-table-column align="center" label="电话" prop="telephone" show-overflow-tooltip />
       <el-table-column align="center" label="微信" prop="wechat" show-overflow-tooltip />
-      <el-table-column align="center" label="邮箱" prop="email" show-overflow-tooltip />
+      <el-table-column align="center" label="办公地点" prop="officeLocation" show-overflow-tooltip />
+      <!--      <el-table-column align="center" label="邮箱" prop="email" show-overflow-tooltip />-->
       <!--      <el-table-column align="center" label="是否决策人">-->
       <!--        <template slot-scope="scope">-->
-      <!--          <el-switch v-model="scope.row.policy" :active-value="1" disabled :inactive-value="0" />-->
+      <!--          <el-switch v-model="scope.row.isDecision" active-value="10" disabled inactive-value="20" />-->
       <!--        </template>-->
       <!--      </el-table-column>-->
       <el-table-column align="center" label="操作" show-overflow-tooltip>

+ 1 - 1
src/views/proj/business/components/DetailsFollow.vue

@@ -81,7 +81,7 @@
       }
     },
     mounted() {
-      console.log(this.busId)
+      // console.log(this.busId)
     },
     methods: {
       // 跟进记录详情

+ 30 - 7
src/views/proj/business/components/DetailsRecords.vue

@@ -19,7 +19,7 @@
                            :src="avatar" /> -->
           <vab-icon class="user-avatar" icon="account-circle-fill" />
           <div class="text">
-            <p class="action">{{ item.opnPeople }} {{ opnTypeFormat(item.opnType) }}</p>
+            <p class="action">{{ item.opnPeople !== '-1' ? item.opnPeople : '' }} {{ opnTypeFormat(item.opnType) }}</p>
             <p>{{ item.opnDate }}</p>
             <div v-if="item.opnContent">
               <p v-if="item.opnType === '30'">
@@ -28,7 +28,13 @@
               </p>
               <p v-if="item.opnType === '40' || item.opnType === '50'">
                 项目类别:
-                <span>{{ item.opnContent.origNboType + ' => ' + item.opnContent.nboType }}</span>
+                <span>
+                  {{
+                    selectDictLabel(nboTypeOptions, item.opnContent.origNboType) +
+                    ' => ' +
+                    selectDictLabel(nboTypeOptions, item.opnContent.nboType)
+                  }}
+                </span>
               </p>
 
               <p v-if="item.opnContent.custName">
@@ -62,11 +68,16 @@
       },
     },
     data() {
-      return {}
+      return {
+        nboTypeOptions: [],
+      }
     },
 
     mounted() {
-      console.log(this.dynamicsList)
+      // console.log(this.dynamicsList)
+      this.getDicts('proj_nbo_type').then((response) => {
+        this.nboTypeOptions = response.data.values || []
+      })
     },
 
     methods: {
@@ -76,17 +87,29 @@
         } else if (opnType === '20') {
           return '更新了项目'
         } else if (opnType === '30') {
-          return '项目转移'
+          return '更新项目状态'
         } else if (opnType === '40') {
           return '项目升级'
+        } else if (opnType === '41') {
+          return '项目升级审批'
         } else if (opnType === '50') {
           return '项目降级'
+        } else if (opnType === '51') {
+          return '项目降级审批'
         } else if (opnType === '60') {
-          return '设置首要联系人'
+          return '项目转移'
+        } else if (opnType === '61') {
+          return '项目转移审批'
         } else if (opnType === '70') {
           return '关联了联系人'
-        } else if (opnType === '80') {
+        } else if (opnType === '71') {
           return '解除关联了联系人'
+        } else if (opnType === '72') {
+          return '设置首要联系人'
+        } else if (opnType === '80') {
+          return '项目转为储备项目'
+        } else if (opnType === '81') {
+          return '项目转为储备审批'
         } else {
           return ''
         }

+ 61 - 0
src/views/proj/business/components/ToReserve.vue

@@ -0,0 +1,61 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialogFormVisible" width="500px" @close="close">
+    <el-form ref="form" label-width="80px" :model="form" :rules="rules">
+      <el-form-item label="转化原因" prop="projConversionReason">
+        <el-input
+          v-model="form.projConversionReason"
+          maxlength="300"
+          placeholder="请输入转化原因"
+          rows="5"
+          show-word-limit
+          type="textarea" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="close">取 消</el-button>
+      <el-button type="primary" @click="save">确 定</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+  import businessApi from '@/api/proj/business'
+
+  export default {
+    name: 'Transfer',
+    data() {
+      return {
+        form: {
+          id: undefined,
+          projConversionReason: undefined,
+        },
+        rules: {
+          projConversionReason: [{ required: true, message: '不能为空', trigger: ['blur', 'change'] }],
+        },
+        title: '转储备项目',
+        dialogFormVisible: false,
+      }
+    },
+    methods: {
+      open(id) {
+        this.form.id = id
+        this.dialogFormVisible = true
+      },
+      close() {
+        this.$refs['form'].resetFields()
+        this.form = this.$options.data().form
+        this.dialogFormVisible = false
+      },
+      save() {
+        this.$refs['form'].validate(async (valid) => {
+          if (valid) {
+            const { msg } = await businessApi.businessConvertToReserve(this.form)
+            this.$baseMessage(msg, 'success')
+            this.$emit('fetch-data')
+            this.close()
+          }
+        })
+      },
+    },
+  }
+</script>

+ 3 - 2
src/views/proj/business/components/Transfer.vue

@@ -9,11 +9,11 @@
           suffix-icon="el-icon-user-solid"
           @focus="handleSelectUser" />
       </el-form-item>
-      <el-form-item label="备注信息" prop="remark">
+      <el-form-item label="备注原因" prop="remark">
         <el-input
           v-model="form.remark"
           maxlength="300"
-          placeholder="请输入备注信息"
+          placeholder="请输入备注原因"
           rows="5"
           show-word-limit
           type="textarea" />
@@ -45,6 +45,7 @@
         },
         rules: {
           userName: [{ required: true, message: '不能为空', trigger: ['blur', 'change'] }],
+          remark: [{ required: true, message: '不能为空', trigger: ['blur', 'change'] }],
         },
         title: '转移项目',
         dialogFormVisible: false,

+ 115 - 44
src/views/proj/business/detail.vue

@@ -7,52 +7,54 @@
           <h3>
             {{ details.nboName }}
             <span>
-              <business-gradation :bus-id="id" :nbo-type="details.nboType" @fetch-data="init" />
+              <!--升级、降级-->
+              <business-gradation :bus-id="id" :business-info="details" @fetch-data="init" />
               <el-button @click="handleTransfer">转移项目</el-button>
+              <el-button :disabled="details.nboType === '40' || details.nboType === '50'" @click="handleToReserve">
+                转为储备
+              </el-button>
               <el-button>创建工单</el-button>
               <el-button @click="createContract">创建合同</el-button>
             </span>
           </h3>
         </div>
         <header>
-          <el-descriptions :colon="false" :column="6" direction="vertical">
+          <el-descriptions :colon="false" :column="7" direction="vertical">
             <el-descriptions-item content-class-name="my-content" label="项目编码" label-class-name="my-label">
               {{ details.nboCode }}
             </el-descriptions-item>
             <el-descriptions-item content-class-name="my-content" label="客户名称" label-class-name="my-label">
               {{ details.custName }}
             </el-descriptions-item>
-            <el-descriptions-item content-class-name="my-content" label="项目预算" label-class-name="my-label">
-              {{ details.nboBudget }}
-            </el-descriptions-item>
             <el-descriptions-item content-class-name="my-content" label="销售工程师" label-class-name="my-label">
               {{ details.saleName }}
             </el-descriptions-item>
-            <el-descriptions-item content-class-name="my-content" label="项目类型" label-class-name="my-label">
-              {{ details.nboType }} 类
+            <el-descriptions-item content-class-name="my-content" label="项目级别" label-class-name="my-label">
+              {{ selectDictLabel(nboTypeOptions, details.nboType) }}
+            </el-descriptions-item>
+            <el-descriptions-item content-class-name="my-content" label="产品线" label-class-name="my-label">
+              {{ selectDictLabel(productLineOptions, details.productLine) }}
+            </el-descriptions-item>
+            <el-descriptions-item content-class-name="my-content" label="项目预算" label-class-name="my-label">
+              ¥{{ details.nboBudget }}
             </el-descriptions-item>
-            <el-descriptions-item content-class-name="my-content" label="最后跟进时间" label-class-name="my-label">
-              {{ details.finalFollowTime }}
+            <el-descriptions-item content-class-name="my-content" label="最跟进时间" label-class-name="my-label">
+              {{ parseTime(details.finalFollowTime, '{y}-{m}-{d} {h}:{i}') }}
             </el-descriptions-item>
           </el-descriptions>
         </header>
         <el-tabs v-model="activeName" @tab-click="handleClick">
-          <el-tab-pane label="跟进记录" name="follow">
-            <details-follow ref="follow" :bus-id="id" />
-          </el-tab-pane>
           <el-tab-pane label="详细信息" name="details">
-            <el-descriptions border :column="2" size="medium">
+            <el-descriptions border :column="2" size="small">
               <el-descriptions-item label="项目名称">
                 {{ details.nboName }}
               </el-descriptions-item>
               <el-descriptions-item label="客户名称">
                 {{ details.custName }}
               </el-descriptions-item>
-              <el-descriptions-item label="预计成交价格">
-                {{ details.estTransPrice }}
-              </el-descriptions-item>
+              <el-descriptions-item label="预计成交价格">¥{{ details.estTransPrice }}</el-descriptions-item>
               <el-descriptions-item label="预计成交日期">
-                {{ details.estTransTime }}
+                {{ parseTime(details.estTransTime, '{y}-{m}-{d}') }}
               </el-descriptions-item>
               <el-descriptions-item label="主要联系人">
                 {{ details.contactName }}
@@ -67,14 +69,13 @@
                 {{ details.distributorName }}
               </el-descriptions-item>
               <el-descriptions-item label="下次联系时间">
-                {{ details.nextFollowTime }}
+                {{ parseTime(details.nextFollowTime, '{y}-{m}-{d} {h}:{i}') }}
               </el-descriptions-item>
-              <el-descriptions-item label="最跟进时间">
-                {{ details.finalFollowTime }}
+              <el-descriptions-item label="最跟进时间">
+                {{ parseTime(details.finalFollowTime, '{y}-{m}-{d} {h}:{i}') }}
               </el-descriptions-item>
-
               <el-descriptions-item label="计划采购时间">
-                {{ details.planPurchaseTime }}
+                {{ parseTime(details.planPurchaseTime, '{y}-{m}-{d}') }}
               </el-descriptions-item>
               <el-descriptions-item label="风险情况">
                 {{ details.riskProfile }}
@@ -88,6 +89,52 @@
               <el-descriptions-item label="介入情况">
                 {{ details.intervention }}
               </el-descriptions-item>
+
+              <!--  C-B  -->
+              <el-descriptions-item label="技术支持时间">
+                {{ parseTime(details.technicalSupportTime, '{y}-{m}-{d} {h}:{i}') }}
+              </el-descriptions-item>
+              <el-descriptions-item label="技术支持人员">
+                {{ details.technicalSupportName }}
+              </el-descriptions-item>
+              <el-descriptions-item label="技术支持内容">
+                {{ details.technicalSupportContent }}
+              </el-descriptions-item>
+              <el-descriptions-item label="总部对接人">
+                {{ details.parentReceiver }}
+              </el-descriptions-item>
+              <el-descriptions-item label="项目预算期限">
+                {{ parseTime(details.nboBudgetTime, '{y}-{m}-{d} {h}:{i}') }}
+              </el-descriptions-item>
+              <el-descriptions-item label="资金来源">
+                {{ details.capitalSource }}
+              </el-descriptions-item>
+              <el-descriptions-item label="产品/方案满足情况">
+                {{ details.productSatisfaction }}
+              </el-descriptions-item>
+
+              <!--  B-A  -->
+              <el-descriptions-item label="采购方式">
+                {{ details.purchasingWay }}
+              </el-descriptions-item>
+              <el-descriptions-item label="采购时间">
+                {{ parseTime(details.purchasingTime, '{y}-{m}-{d} {h}:{i}') }}
+              </el-descriptions-item>
+              <el-descriptions-item label="决策人员">
+                {{ details.makerName }}
+              </el-descriptions-item>
+              <el-descriptions-item label="决策部门">
+                {{ details.makerDept }}
+              </el-descriptions-item>
+              <el-descriptions-item label="经销商销售人员">
+                {{ details.dealerSalesName }}
+              </el-descriptions-item>
+              <el-descriptions-item label="维护部门及人员">
+                {{ details.accendant }}
+              </el-descriptions-item>
+              <el-descriptions-item label="是否采纳大数技术参数">
+                {{ selectDictLabel(yesOrNoOptions, details.isAdoptDashoo) }}
+              </el-descriptions-item>
               <el-descriptions-item label="创建人">
                 {{ details.createdName }}
               </el-descriptions-item>
@@ -102,6 +149,9 @@
               </el-descriptions-item>
             </el-descriptions>
           </el-tab-pane>
+          <el-tab-pane label="跟进记录" name="follow">
+            <details-follow ref="follow" :bus-id="id" />
+          </el-tab-pane>
           <el-tab-pane label="联系人" name="contact">
             <details-contact
               ref="contact"
@@ -143,6 +193,8 @@
     <edit ref="edit" @fetch-data="init" />
     <!-- 转移 -->
     <transfer ref="transfer" @fetch-data="init" />
+    <!-- 转储备项目 -->
+    <to-reserve ref="toReserve" @fetch-data="init" />
     <!-- 合同 -->
     <contract-edit ref="contract" :business-data="[details]" />
   </div>
@@ -159,6 +211,7 @@
   import DetailsContract from './components/DetailsContract'
   import DetailsRecords from './components/DetailsRecords'
   import DetailsFollow from './components/DetailsFollow'
+  import ToReserve from './components/ToReserve.vue'
   import ContractEdit from '@/views/contract/components/Edit'
 
   export default {
@@ -167,6 +220,7 @@
       BusinessGradation,
       Edit,
       Transfer,
+      ToReserve,
       DetailsContact,
       DetailsContract,
       DetailsRecords,
@@ -179,7 +233,7 @@
         details: { nboType: '' },
         product: [],
         abstract: {},
-        activeName: 'follow',
+        activeName: 'details',
         selectRows: [],
         followList: [],
         contactList: [],
@@ -187,7 +241,14 @@
         belongLoading: false,
         belongTotal: 0,
         belongs: [],
+        yesOrNoOptions: [],
+        nboTypeOptions: [],
+        nboSourceOptions: [],
         salesModelOptions: [],
+        productLineOptions: [],
+        nboPhaseOptions: [],
+        nboStatusOptions: [],
+        approStatusOptions: [],
       }
     },
     computed: {
@@ -198,21 +259,26 @@
     },
     created() {
       this.id = parseInt(this.$route.query.id)
-    },
-    mounted() {
       this.init()
-      this.getDicts('proj_sales_model').then((response) => {
-        this.salesModelOptions = response.data.values || []
-      })
     },
+    mounted() {},
     methods: {
       init() {
         Promise.all([
           businessApi.getEntityById({ id: this.id }),
+          this.getDicts('proj_nbo_type'),
+          this.getDicts('proj_nbo_source'),
+          this.getDicts('proj_sales_model'),
+          this.getDicts('sys_product_line'),
+          this.getDicts('sys_yes_no'),
           this.getRecord(),
-          this.handleClick({ name: this.activeName }),
-        ]).then(([details]) => {
+        ]).then(([details, nboType, nboSource, salesModel, productLine, yesOrNo]) => {
           if (details.data) this.details = details.data
+          this.nboTypeOptions = nboType.data.values || []
+          this.nboSourceOptions = nboSource.data.values || []
+          this.salesModelOptions = salesModel.data.values || []
+          this.productLineOptions = productLine.data.values || []
+          this.yesOrNoOptions = yesOrNo.data.values || []
         })
       },
       async getRecord() {
@@ -227,7 +293,7 @@
           }
 
           this.dynamicsList = records
-          console.log(this.dynamicsList)
+          // console.log(this.dynamicsList)
         }
       },
       async handleClick(tab) {
@@ -252,6 +318,11 @@
           return
         }
       },
+      // 转为储备项目
+      handleToReserve() {
+        this.$refs.toReserve.open(this.id)
+      },
+      // 转移项目
       handleTransfer() {
         this.$refs.transfer.open(this.details)
       },
@@ -272,19 +343,19 @@
         this.$refs.contract.init()
       },
       // 业务调级(升级、降级)
-      handleBusinessGradation(type) {
-        let data = { id: this.id, nboType: '' }
-        if ((type === '降级' && this.details.nboType === 'A') || (type === '升级' && this.details.nboType === 'C')) {
-          data.nboType = 'B'
-        } else {
-          data.nboType = type === '升级' ? 'A' : 'C'
-        }
-        this.$baseConfirm('你确定要对当前项目' + type + '吗', null, async () => {
-          const { msg } = await businessApi.businessGradation(data)
-          this.$baseMessage(msg, 'success')
-          await this.init()
-        })
-      },
+      // handleBusinessGradation(type) {
+      //   let data = { id: this.id, nboType: '' }
+      //   if ((type === '降级' && this.details.nboType === 'A') || (type === '升级' && this.details.nboType === 'C')) {
+      //     data.nboType = 'B'
+      //   } else {
+      //     data.nboType = type === '升级' ? 'A' : 'C'
+      //   }
+      //   this.$baseConfirm('你确定要对当前项目' + type + '吗', null, async () => {
+      //     const { msg } = await businessApi.businessGradation(data)
+      //     this.$baseMessage(msg, 'success')
+      //     await this.init()
+      //   })
+      // },
       back() {
         this.$router.go(-1)
       },

+ 232 - 41
src/views/proj/business/index.vue

@@ -1,12 +1,12 @@
 <template>
   <div class="business-container">
     <el-tabs v-model="activeName" @tab-click="handleTabClick">
-      <el-tab-pane label="全部项目" name="ALL" />
-      <el-tab-pane label="C类项目" name="C" />
-      <el-tab-pane label="B类项目" name="B" />
-      <el-tab-pane label="A类项目" name="A" />
-      <el-tab-pane label="成交项目" name="DEAL" />
-      <el-tab-pane label="无效项目" name="VOID" />
+      <el-tab-pane label="全部项目" name="all" />
+      <el-tab-pane label="C类项目" name="30" />
+      <el-tab-pane label="B类项目" name="20" />
+      <el-tab-pane label="A类项目" name="10" />
+      <el-tab-pane label="成交项目" name="40" />
+      <el-tab-pane label="储备项目" name="50" />
     </el-tabs>
 
     <vab-query-form>
@@ -59,7 +59,7 @@
       </vab-query-form-right-panel>
     </vab-query-form>
 
-    <el-table v-loading="listLoading" :data="list" :height="height" @selection-change="setSelectRows">
+    <el-table ref="busTable" v-loading="listLoading" :data="list" :height="height" @selection-change="setSelectRows">
       <el-table-column align="center" show-overflow-tooltip type="selection" />
       <el-table-column
         v-for="(item, index) in finallyColumns"
@@ -72,11 +72,21 @@
         :sortable="item.sortable"
         :width="item.width">
         <template #default="{ row }">
-          <el-button v-if="item.prop === 'nboName'" class="link-button" type="text" @click="handleDetail(row)">
-            {{ row.nboName }}
+          <el-button
+            v-if="item.prop === 'nboCode' || item.prop === 'nboName'"
+            class="link-button"
+            type="text"
+            @click="handleDetail(row)">
+            {{ row[item.prop] }}
           </el-button>
-          <span v-else-if="item.prop === 'estTransPrice'">
-            {{ formatPrice(row.estTransPrice) }}
+          <span v-else-if="item.prop === 'nboType'">
+            {{ selectDictLabel(nboTypeOptions, row.nboType) }}
+          </span>
+          <span v-else-if="item.prop === 'nboSource'">
+            {{ selectDictLabel(nboSourceOptions, row.nboSource) }}
+          </span>
+          <span v-else-if="item.prop === 'salesModel'">
+            {{ selectDictLabel(salesModelOptions, row.salesModel) }}
           </span>
           <span v-else-if="item.prop === 'approStatus'">
             {{ selectDictLabel(approStatusOptions, row.approStatus) }}
@@ -87,6 +97,21 @@
           <span v-else-if="item.prop === 'nboPhase'">
             {{ selectDictLabel(nboPhaseOptions, row.nboPhase) }}
           </span>
+          <span v-else-if="item.prop === 'productLine'">
+            {{ selectDictLabel(productLineOptions, row.productLine) }}
+          </span>
+          <span v-else-if="item.prop === 'isBig'">
+            {{ selectDictLabel(yesOrNoOptions, row.isBig) }}
+          </span>
+          <span v-else-if="item.prop === 'estTransPrice'">
+            {{ formatPrice(row.estTransPrice) }}
+          </span>
+          <span v-else-if="item.prop === 'nboBudget'">
+            {{ formatPrice(row.nboBudget) }}
+          </span>
+          <span v-else-if="item.prop === 'filingTime'">
+            {{ parseTime(row.filingTime, '{y}-{m}-{d} {h}:{i}') }}
+          </span>
           <span v-else-if="item.prop === 'finalFollowTime'">
             {{ parseTime(row.finalFollowTime, '{y}-{m}-{d} {h}:{i}') }}
           </span>
@@ -134,10 +159,17 @@
     components: { Edit, Transfer, TableTool, FollowAdd },
     data() {
       return {
-        activeName: 'ALL',
+        activeName: 'all',
         height: this.$baseTableHeight(3),
         checkList: [],
         columns: [
+          {
+            label: '项目编码',
+            width: 'auto',
+            minWidth: '120',
+            prop: 'nboCode',
+            sortable: false,
+          },
           {
             label: '项目名称',
             width: 'auto',
@@ -147,41 +179,160 @@
             disableCheck: true,
           },
           {
-            label: '关联客户',
+            label: '所在省',
+            width: 'auto',
+            minWidth: '120',
+            prop: 'custProvince',
+          },
+          {
+            label: '所在市',
+            width: 'auto',
+            minWidth: '120',
+            prop: 'custCity',
+          },
+          {
+            label: '销售工程师',
+            width: 'auto',
+            minWidth: '120',
+            prop: 'saleName',
+          },
+          {
+            label: '客户名称',
             width: 'auto',
             minWidth: '280',
             prop: 'custName',
           },
           {
-            label: '审批状态',
+            label: '项目备案时间',
+            width: '140px',
+            prop: 'filingTime',
+          },
+          {
+            label: '项目来源',
+            width: '140px',
+            prop: 'nboSource',
+          },
+          {
+            label: '销售模式',
+            width: '120px',
+            prop: 'salesModel',
+          },
+          {
+            label: '经销商/代理商',
             width: '120px',
-            prop: 'approStatus',
+            prop: 'distributorName',
           },
           {
-            label: '项目状态',
+            label: '产品线',
             width: '120px',
-            prop: 'nboStatus',
+            prop: 'productLine',
           },
           {
-            label: '项目类别',
+            label: '项目别',
             width: '120px',
             prop: 'nboType',
           },
           {
-            label: '项目金额',
+            label: '项目预算(万元)',
             width: '120px',
-            prop: 'estTransPrice',
+            prop: 'nboBudget',
           },
           {
-            label: '最后跟进时间',
+            label: '是否为大项目',
+            width: '120px',
+            prop: 'isBig',
+          },
+          {
+            label: '最新跟进时间',
             width: '140px',
             prop: 'finalFollowTime',
           },
           {
-            label: '下次跟进时间',
+            label: '最新跟进人',
+            width: '120px',
+            prop: 'finalFollowName',
+          },
+          {
+            label: '项目成交时间',
             width: '140px',
-            prop: 'nextFollowTime',
+            prop: 'projClosingTime',
           },
+          {
+            label: '合同金额',
+            width: '140px',
+            prop: 'contractAmount',
+          },
+          {
+            label: '项目转化时间',
+            width: '140px',
+            prop: 'projConversionTime',
+          },
+          {
+            label: '转化原因',
+            width: '140px',
+            prop: 'projConversionReason',
+          },
+        ],
+        allColumns: [
+          '项目编码',
+          '销售工程师',
+          '所在省',
+          '所在市',
+          '客户名称',
+          '项目备案时间',
+          '项目来源',
+          '销售模式',
+          '经销商/代理商',
+          '产品线',
+          '项目级别',
+          '项目预算(万元)',
+          '是否为大项目',
+          '最新跟进时间',
+        ],
+        abcColumns: [
+          '项目编码',
+          '所在省',
+          '所在市',
+          '销售工程师',
+          '客户名称',
+          '项目备案时间',
+          '项目来源',
+          '销售模式',
+          '经销商/代理商',
+          '产品线',
+          '项目预算(万元)',
+          '是否为大项目',
+          '最新跟进时间',
+          '最新跟进',
+        ],
+        dealColumns: [
+          '项目编码',
+          '所在省',
+          '所在市',
+          '销售工程师',
+          '客户名称',
+          '项目备案时间',
+          '项目来源',
+          '销售模式',
+          '经销商/代理商',
+          '产品线',
+          '是否为大项目',
+          '项目成交时间',
+          '合同金额',
+        ],
+        reserveColumns: [
+          '项目编码',
+          '所在省',
+          '所在市',
+          '销售工程师',
+          '客户名称',
+          '项目备案时间',
+          '项目来源',
+          '销售模式',
+          '经销商/代理商',
+          '产品线',
+          '项目转化时间',
+          '转化原因',
         ],
         list: [],
         listLoading: true,
@@ -196,7 +347,11 @@
           nboType: undefined,
           saleName: undefined,
         },
+        yesOrNoOptions: [],
         nboTypeOptions: [],
+        nboSourceOptions: [],
+        salesModelOptions: [],
+        productLineOptions: [],
         nboPhaseOptions: [],
         nboStatusOptions: [],
         approStatusOptions: [],
@@ -205,31 +360,67 @@
     },
     computed: {
       finallyColumns() {
-        return this.columns.filter((item) => this.checkList.includes(item.label))
+        switch (this.activeName) {
+          case '10':
+          case '20':
+          case '30':
+            return this.columns.filter(
+              (item) => this.checkList.includes(item.label) && this.abcColumns.includes(item.label)
+            )
+          case '40':
+            return this.columns.filter(
+              (item) => this.checkList.includes(item.label) && this.dealColumns.includes(item.label)
+            )
+          case '50':
+            return this.columns.filter(
+              (item) => this.checkList.includes(item.label) && this.reserveColumns.includes(item.label)
+            )
+          default:
+            return this.columns.filter(
+              (item) => this.checkList.includes(item.label) && this.allColumns.includes(item.label)
+            )
+        }
       },
     },
     created() {
       this.fetchData()
-      this.getDicts('proj_nbo_type').then((response) => {
-        this.nboTypeOptions = response.data.values || []
-      })
-      this.getDicts('proj_nbo_phase').then((response) => {
-        this.nboPhaseOptions = response.data.values || []
-      })
-      this.getDicts('proj_nbo_status').then((response) => {
-        this.nboStatusOptions = response.data.values || []
-      })
-      this.getDicts('proj_appro_status').then((response) => {
-        this.approStatusOptions = response.data.values || []
-      })
+      this.getOptions()
+    },
+    updated() {
+      if (this.$refs.busTable && this.$refs.busTable.doLayout) {
+        this.$refs.busTable.doLayout()
+      }
     },
     methods: {
-      approStatusFormat() {},
+      getOptions() {
+        Promise.all([
+          this.getDicts('proj_nbo_type'),
+          this.getDicts('proj_nbo_source'),
+          this.getDicts('proj_sales_model'),
+          this.getDicts('sys_product_line'),
+          this.getDicts('sys_yes_no'),
+          // this.getDicts('proj_nbo_phase'),
+          // this.getDicts('proj_nbo_status'),
+          // this.getDicts('proj_appro_status'),
+        ])
+          .then(([nboType, nboSource, salesModel, productLine, yesOrNo]) => {
+            this.nboTypeOptions = nboType.data.values || []
+            this.nboSourceOptions = nboSource.data.values || []
+            this.salesModelOptions = salesModel.data.values || []
+            this.productLineOptions = productLine.data.values || []
+            this.yesOrNoOptions = yesOrNo.data.values || []
+            // this.nboPhaseOptions = nboPhase.data.values || []
+            // this.nboStatusOptions = nboStatus.data.values || []
+            // this.approStatusOptions = approStatus.data.values || []
+          })
+          .catch((err) => console.log(err))
+      },
       handleTabClick() {
-        this.queryForm.nboType = this.activeName
-        // 全不项目,成交项目,无效项目 项目类型不传
-        if (this.activeName === 'ALL' || this.activeName === 'DEAL' || this.activeName === 'VOID') {
-          this.queryForm.nboType = ''
+        console.log(this.activeName)
+        if (this.activeName !== 'all') {
+          this.queryForm.nboType = this.activeName
+        } else {
+          this.queryForm.nboType = undefined
         }
         this.fetchData()
       },