Преглед изворни кода

feature(项目管理): 项目管理详情修改

ZZH-wl пре 2 година
родитељ
комит
dc8678dd3f

+ 1 - 1
src/components/currency/index.vue

@@ -45,7 +45,7 @@
 
     methods: {
       returnNum() {
-        this.$emit('input', this.num)
+        this.$emit('input', this.delcommafy(this.num))
       },
       handleChange(val) {
         this.$nextTick(() => {

+ 2 - 1
src/components/select/SelectBusinessContact.vue

@@ -61,13 +61,14 @@
       },
       addButton: Boolean,
       multiple: Boolean,
-      // 示例{ custId: id, custName: custName}
+      // 示例{ custId: custId, custName: custName}
       defaultCustomer: {
         type: Object,
         default() {
           return {}
         },
       },
+      // 示例{ busId: busId, custId: custId}
       queryParams: {
         type: Object,
         default() {

+ 84 - 20
src/views/proj/business/components/BusinessEdit.vue

@@ -8,12 +8,12 @@
 
     <el-form ref="form" :model="form" :rules="rules">
       <el-row v-if="activeSteps === 1" :gutter="20">
-        <el-col :span="12">
+        <el-col :span="8">
           <el-form-item label="项目名称" prop="nboName">
             <el-input v-model="form.nboName" />
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col :span="8">
           <el-form-item label="关联客户" prop="custName">
             <el-input
               v-model="form.custName"
@@ -22,46 +22,46 @@
               @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="12">
+        <!--        <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%">
               <el-option v-for="dict in nboSourceOptions" :key="dict.key" :label="dict.value" :value="dict.key" />
             </el-select>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col :span="8">
           <el-form-item label="主要联系人" prop="contactName">
             <el-input v-model="form.contactName" readonly @focus="handleSelectContact" />
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col :span="8">
           <el-form-item label="职位" prop="contactPostion">
             <el-input v-model="form.contactPostion" />
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col :span="8">
           <el-form-item label="联系电话" prop="contactTelephone">
             <el-input v-model="form.contactTelephone" />
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col :span="8">
           <el-form-item label="销售工程师" prop="saleName">
             <el-input v-model="form.saleName" readonly @focus="handleSelectSale" />
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col :span="8">
           <el-form-item label="销售模式" prop="salesModel">
             <el-select v-model="form.salesModel" clearable placeholder="销售模式" style="width: 100%">
               <el-option v-for="dict in salesModelOptions" :key="dict.key" :label="dict.value" :value="dict.key" />
             </el-select>
           </el-form-item>
         </el-col>
-        <el-col :span="12">
+        <el-col :span="8">
           <el-form-item label="经销商/代理商" prop="distributorName">
             <el-input
               v-model="form.distributorName"
@@ -70,10 +70,54 @@
               @focus="handleSelectDistributor" />
           </el-form-item>
         </el-col>
+        <el-col :span="8">
+          <el-form-item label="项目预算" prop="nboBudget">
+            <amount-input v-model.trim="form.nboBudget" placeholder="请输入金额" :value="form.nboBudget" />
+          </el-form-item>
+        </el-col>
+        <!--        <el-col :span="8">-->
+        <!--          <el-form-item label="预计成交价格" prop="estTransPrice">-->
+        <!--            <amount-input v-model.trim="form.estTransPrice" placeholder="请输入金额" />-->
+        <!--          </el-form-item>-->
+        <!--        </el-col>-->
+        <el-col :span="8">
+          <el-form-item label="预计成交时间" prop="estTransTime">
+            <el-date-picker v-model="form.estTransTime" placeholder="选择日期" style="width: 100%" type="datetime" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="计划采购时间" prop="planPurchaseTime">
+            <el-date-picker
+              v-model="form.planPurchaseTime"
+              placeholder="选择日期"
+              style="width: 100%"
+              type="datetime" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="风险情况" prop="riskProfile">
+            <el-input v-model="form.riskProfile" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="困难点" prop="difficulty">
+            <el-input v-model="form.difficulty" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="竞争公司" prop="competitor">
+            <el-input v-model="form.competitor" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="介入情况" prop="intervention">
+            <el-input v-model="form.intervention" />
+          </el-form-item>
+        </el-col>
 
-        <el-col :span="24">
+        <el-col :span="16">
           <el-form-item label="备注信息" prop="remark">
-            <el-input v-model="form.remark" placeholder="请输入备注信息" rows="5" show-word-limit type="textarea" />
+            <el-input v-model="form.remark" placeholder="请输入备注信息" rows="3" show-word-limit type="textarea" />
           </el-form-item>
         </el-col>
       </el-row>
@@ -139,6 +183,7 @@
 
 <script>
   import businessApi from '@/api/proj/business'
+  import AmountInput from '@/components/currency'
   import ProductTable from './ProductTable'
   import SelectContact from '@/components/select/SelectCustomerContact'
   import SelectCustomer from '@/components/select/SelectCustomer'
@@ -148,7 +193,15 @@
 
   export default {
     name: 'BusinessEdit',
-    components: { ProductTable, SelectContact, SelectProduct, SelectDistributor, SelectCustomer, SelectUser },
+    components: {
+      AmountInput,
+      ProductTable,
+      SelectContact,
+      SelectProduct,
+      SelectDistributor,
+      SelectCustomer,
+      SelectUser,
+    },
     props: {
       // 客户信息{ custId: id, custName: custName}
       custInfo: {
@@ -180,6 +233,14 @@
           saleName: undefined,
           distributorId: undefined,
           distributorName: undefined,
+          nboBudget: 0,
+          planPurchaseTime: undefined,
+          estTransTime: undefined,
+          estTransPrice: undefined,
+          riskProfile: undefined,
+          difficulty: undefined,
+          competitor: undefined,
+          intervention: undefined,
           remark: undefined,
           products: undefined,
 
@@ -231,6 +292,7 @@
     },
     methods: {
       nextStep() {
+        console.log(typeof this.form.nboBudget)
         if (this.activeSteps === 1) {
           this.$refs['form'].validate(async (valid) => {
             if (valid) {
@@ -286,7 +348,7 @@
       selectSales(val) {
         if (val && val.length > 0) {
           this.form.saleId = val[0].id
-          this.form.saleName = val.map((item) => item.userName).join()
+          this.form.saleName = val.map((item) => item.nickName).join()
         }
       },
       selectDistributor(val) {
@@ -296,7 +358,7 @@
         }
       },
       selectFollowUser(val) {
-        this.form.followUserName = val.map((item) => item.userName).join()
+        this.form.followUserName = val.map((item) => item.nickName).join()
       },
       selectProduct(data) {
         let projData = data.map((item) => ({
@@ -331,7 +393,9 @@
       },
       async getProductData(busId) {
         const { data } = await businessApi.getProductByBusinessId({ id: busId })
-        this.productData = data
+        if (data) {
+          this.productData = data
+        }
       },
       showEdit(row) {
         this.activeSteps = 1

+ 6 - 10
src/views/proj/business/components/DetailsContact.vue

@@ -1,12 +1,13 @@
 <template>
-  <div style="height: 100%; width: 100%">
+  <div style="height: 100%">
     <vab-query-form>
       <vab-query-form-left-panel :span="12">
         <el-input
-          v-model="queryForm.keyWords"
+          v-model="queryForm.cuctName"
           placeholder="请输入姓名"
           prefix-icon="el-icon-search"
-          style="width: 50%" />
+          style="width: 50%"
+          @keyup.enter.native="fetchData" />
       </vab-query-form-left-panel>
       <vab-query-form-right-panel :span="12">
         <el-button icon="el-icon-plus" @click="handleAddContact">新建联系人</el-button>
@@ -14,12 +15,7 @@
         <el-button type="danger" @click="handleDisassociation">解除关联</el-button>
       </vab-query-form-right-panel>
     </vab-query-form>
-    <el-table
-      v-loading="listLoading"
-      border
-      :data="contactList"
-      height="calc(100% - 42px)"
-      @selection-change="setSelectRows">
+    <el-table v-loading="listLoading" :data="contactList" height="calc(100% - 42px)" @selection-change="setSelectRows">
       <el-table-column align="center" type="selection" />
       <el-table-column align="center" label="姓名" prop="cuctName" />
       <el-table-column align="center" label="岗位" prop="postion" />
@@ -33,7 +29,7 @@
       <!--      </el-table-column>-->
       <el-table-column align="center" label="操作">
         <template slot-scope="scope">
-          <el-button v-if="scope.row.id !== primacyContactId" type="text" @click="setPrimacyContact(scope.row)">
+          <el-button v-if="scope.row.contactId !== primacyContactId" type="text" @click="setPrimacyContact(scope.row)">
             设为首要联系人
           </el-button>
           <p v-else>首要联系人</p>

+ 284 - 0
src/views/proj/business/components/DetailsContract.vue

@@ -0,0 +1,284 @@
+<template>
+  <div style="height: 100%">
+    <vab-query-form>
+      <vab-query-form-left-panel :span="12">
+        <el-input
+          v-model="queryForm.contractName"
+          clearable
+          placeholder="合同名称"
+          style="width: 50%"
+          @keyup.enter.native="fetchData" />
+      </vab-query-form-left-panel>
+    </vab-query-form>
+    <el-table v-loading="listLoading" border :data="list" height="calc(100% - 42px)" @selection-change="setSelectRows">
+      <el-table-column align="center" show-overflow-tooltip type="selection" />
+      <el-table-column
+        v-for="(item, index) in columns"
+        :key="index"
+        align="center"
+        :label="item.label"
+        :min-width="item.width"
+        :prop="item.prop"
+        show-overflow-tooltip>
+        <template #default="{ row }">
+          <span v-if="item.prop === 'contractAmount'">
+            {{ formatPrice(row.contractAmount) }}
+          </span>
+          <span v-else-if="item.label === '合同时间'">
+            {{ parseTime(row.contractStartTime, '{y}-{m}-{d}') }}~{{ parseTime(row.contractEndTime, '{y}-{m}-{d}') }}
+          </span>
+          <span v-else>{{ row[item.prop] }}</span>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+  import contractApi from '@/api/contract'
+  import to from 'await-to-js'
+
+  export default {
+    name: 'DetailsContract',
+    data() {
+      return {
+        busId: undefined,
+        queryForm: {
+          contractName: undefined,
+          pageNo: 1,
+          pageSize: 9999,
+        },
+        listLoading: false,
+        selectRows: [],
+        checkList: [],
+        columns: [
+          {
+            label: '合同编号',
+            width: '160px',
+            prop: 'contractCode',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同名称',
+            width: '280px',
+            prop: 'contractName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同类型',
+            width: '100px',
+            prop: 'contractType',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同金额',
+            width: '120px',
+            prop: 'contractAmount',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '合同时间',
+            width: '180px',
+            prop: 'distributorName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '审批状态',
+            width: '100px',
+            prop: 'approStatus',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '销售工程师',
+            width: '120px',
+            prop: 'inchargeName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '公司签约人',
+            width: '120px',
+            prop: 'signatoryName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '客户签约人',
+            width: '120px',
+            prop: 'custSignatoryName',
+            sortable: false,
+            disableCheck: false,
+          },
+          {
+            label: '经销商/代理商',
+            width: '120px',
+            prop: 'distributorName',
+            sortable: false,
+            disableCheck: false,
+          },
+        ],
+        list: [],
+      }
+    },
+    mounted() {},
+    methods: {
+      open(busId) {
+        this.busId = busId
+        this.fetchData()
+      },
+      setSelectRows(val) {
+        this.selectRows = val
+      },
+      async fetchData() {
+        this.listLoading = true
+        const params = { ...this.queryForm }
+        params.nboId = this.busId
+        const [err, res] = await to(contractApi.getList(params))
+        if (err) return (this.listLoading = false)
+        this.list = res.data.list || []
+        this.total = res.data.total
+        this.listLoading = false
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .follow {
+    height: 100%;
+    padding: 10px 20px;
+    overflow: auto;
+
+    > li {
+      display: flex;
+
+      + li {
+        margin-top: 10px;
+      }
+    }
+
+    .date {
+      width: 100px;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+
+      h2,
+      h3 {
+        margin: 0;
+      }
+
+      h2 {
+        font-size: 26px;
+        line-height: 32px;
+      }
+    }
+
+    .content {
+      flex: 1;
+      list-style: none;
+
+      > li {
+        border: 1px solid rgb(215, 232, 244);
+        background: rgb(247, 251, 254);
+        border-radius: 4px;
+        padding: 8px;
+        overflow: hidden;
+
+        .text-container {
+          display: flex;
+        }
+
+        .comments {
+          padding-left: 60px;
+          margin-top: 10px;
+          max-height: 190px;
+          overflow: auto;
+
+          li {
+            display: flex;
+            border-top: 1px solid #e3e5e7;
+
+            .text {
+              flex: 1;
+              padding: 0 10px;
+
+              p {
+                font-weight: 500;
+                margin: 0;
+                line-height: 32px;
+              }
+
+              p:first-child {
+                line-height: 30px;
+                font-weight: bold;
+              }
+
+              p:last-child {
+                font-size: 12px;
+                color: #9499a0;
+                text-align: right;
+              }
+            }
+          }
+        }
+
+        + li {
+          margin-top: 10px;
+        }
+      }
+
+      .user-avatar {
+        font-size: 40px;
+      }
+
+      .text {
+        flex: 1;
+        padding-left: 20px;
+        padding-right: 10px;
+
+        p {
+          font-weight: 500;
+          margin: 0;
+          line-height: 32px;
+
+          span {
+            color: #1d66dc;
+          }
+        }
+
+        .action {
+          display: flex;
+          justify-content: space-between;
+
+          span:first-child {
+            font-weight: bold;
+            color: #333;
+          }
+        }
+
+        .footer {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+        }
+      }
+    }
+  }
+
+  .no-follow {
+    height: 100%;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 12px;
+    color: rgba(0, 0, 0, 0.65);
+  }
+</style>

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

@@ -52,7 +52,7 @@
 
 <script>
   export default {
-    name: 'Records',
+    name: 'DetailsRecords',
     props: {
       dynamicsList: {
         // eslint-disable-next-line vue/require-prop-type-constructor

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

@@ -50,7 +50,7 @@
   import followApi from '@/api/customer/follow'
 
   export default {
-    name: 'ConfigEdit',
+    name: 'FollowAdd',
     props: {
       // 跟进信息
       followup: {

+ 6 - 1
src/views/proj/business/components/ProductTable.vue

@@ -25,7 +25,12 @@
               @change="handleChange(row)" />
           </span>
           <span v-else-if="item.prop == 'prodNum'">
-            <el-input-number v-model="row.prodNum" :min="0" size="mini" @change="handleChange(row)" />
+            <el-input
+              v-model.trim="row.prodNum"
+              :min="1"
+              onkeyup="value=value.replace(/[^\d]/g,'')"
+              size="mini"
+              @change="handleChange(row)" />
           </span>
           <span v-else-if="item.label == '合计'">
             {{ calculatedDiscount(row.prodPrice, row.prodNum) }}

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

@@ -58,8 +58,7 @@
         if (val && val.length > 0) {
           this.form.userId = val[0].id
         }
-        this.form.userName = val.map((item) => item.userName).join()
-        console.log(this.form.userName)
+        this.form.userName = val.map((item) => item.nickName).join()
       },
       open(row) {
         this.form.Id = row.id

+ 39 - 15
src/views/proj/business/detail.vue

@@ -1,14 +1,18 @@
 <template>
   <div class="details">
-    <el-row :gutter="10">
-      <el-col :span="16">
+    <div class="side-layout">
+      <div class="info">
         <div class="title">
           <p>项目</p>
           <h3>
             {{ details.nboName }}
             <span>
-              <el-button :disabled="details.nboType === 'A'" @click="handleBusinessGradation('升级')">升级</el-button>
-              <el-button :disabled="details.nboType === 'C'" @click="handleBusinessGradation('降级')">降级</el-button>
+              <el-button :disabled="details.nboType === 'A'" type="primary" @click="handleBusinessGradation('升级')">
+                升级
+              </el-button>
+              <el-button :disabled="details.nboType === 'C'" type="danger" @click="handleBusinessGradation('降级')">
+                降级
+              </el-button>
               <el-button @click="handleTransfer">转移项目</el-button>
               <el-button>创建工单</el-button>
               <el-button @click="createContract">创建合同</el-button>
@@ -18,7 +22,7 @@
         <header>
           <el-descriptions :colon="false" :column="6" direction="vertical">
             <el-descriptions-item content-class-name="my-content" label="项目编码" label-class-name="my-label">
-              {{ details.nboName }}
+              {{ details.nboCode }}
             </el-descriptions-item>
             <el-descriptions-item content-class-name="my-content" label="客户名称" label-class-name="my-label">
               {{ details.custName }}
@@ -49,7 +53,7 @@
               <el-descriptions-item label="客户名称">
                 {{ details.custName }}
               </el-descriptions-item>
-              <el-descriptions-item label="项目金额">
+              <el-descriptions-item label="预计成交价格">
                 {{ details.estTransPrice }}
               </el-descriptions-item>
               <el-descriptions-item label="预计成交日期">
@@ -70,6 +74,25 @@
               <el-descriptions-item label="下次联系时间">
                 {{ details.nextFollowTime }}
               </el-descriptions-item>
+              <el-descriptions-item label="最后跟进时间">
+                {{ details.finalFollowTime }}
+              </el-descriptions-item>
+
+              <el-descriptions-item label="计划采购时间">
+                {{ details.planPurchaseTime }}
+              </el-descriptions-item>
+              <el-descriptions-item label="风险情况">
+                {{ details.riskProfile }}
+              </el-descriptions-item>
+              <el-descriptions-item label="困难点">
+                {{ details.difficulty }}
+              </el-descriptions-item>
+              <el-descriptions-item label="竞争公司">
+                {{ details.competitor }}
+              </el-descriptions-item>
+              <el-descriptions-item label="介入情况">
+                {{ details.intervention }}
+              </el-descriptions-item>
               <el-descriptions-item label="创建人">
                 {{ details.createdName }}
               </el-descriptions-item>
@@ -79,9 +102,6 @@
               <el-descriptions-item label="更新时间">
                 {{ details.updatedTime }}
               </el-descriptions-item>
-              <el-descriptions-item label="最后跟进时间">
-                {{ details.finalFollowTime }}
-              </el-descriptions-item>
               <el-descriptions-item label="备注" :span="24">
                 {{ details.remark }}
               </el-descriptions-item>
@@ -95,7 +115,9 @@
               :primacy-contact-id="details.contactId"
               @fetch-data="init" />
           </el-tab-pane>
-          <el-tab-pane label="合同记录" name="contract" />
+          <el-tab-pane label="合同记录" name="contract">
+            <details-contract ref="detailsContract" :bus-id="id" />
+          </el-tab-pane>
           <el-tab-pane label="工单记录" name="worksheet" />
           <el-tab-pane label="归属记录" name="belong">
             <el-table v-loading="belongLoading" border :data="belongs" height="calc(100% - 42px)">
@@ -112,15 +134,15 @@
             </el-table>
           </el-tab-pane>
         </el-tabs>
-      </el-col>
-      <el-col :span="8">
+      </div>
+      <div class="info-side">
         <div class="buttons">
           <el-button type="primary" @click="handleEdit">编辑</el-button>
           <el-button @click="handleDelete">删除</el-button>
         </div>
         <details-records :dynamics-list="dynamicsList" />
-      </el-col>
-    </el-row>
+      </div>
+    </div>
     <!-- 编辑 -->
     <edit ref="edit" @fetch-data="init" />
     <!-- 转移 -->
@@ -137,13 +159,14 @@
   import Edit from './components/BusinessEdit'
   import Transfer from './components/Transfer'
   import DetailsContact from './components/DetailsContact'
+  import DetailsContract from './components/DetailsContract'
   import DetailsRecords from './components/DetailsRecords'
   import DetailsFollow from './components/DetailsFollow'
   import ContractEdit from '@/views/contract/components/Edit'
 
   export default {
     name: 'BusinessDetail',
-    components: { Edit, Transfer, DetailsContact, DetailsRecords, DetailsFollow, ContractEdit },
+    components: { Edit, Transfer, DetailsContact, DetailsContract, DetailsRecords, DetailsFollow, ContractEdit },
     data() {
       return {
         id: undefined,
@@ -202,6 +225,7 @@
           await this.$refs.contact.fetchData()
           return
         } else if (tab.name == 'contract') {
+          this.$refs.detailsContract.open(this.id)
           return
         } else if (tab.name == 'worksheet') {
           return

+ 4 - 1
src/views/proj/business/index.vue

@@ -75,7 +75,10 @@
           <el-button v-if="item.prop === 'nboName'" class="link-button" type="text" @click="handleDetail(row)">
             {{ row.nboName }}
           </el-button>
-          <span v-else-if="item.prop === 'approStatus'">{{ row[item.prop] }}</span>
+          <span v-else-if="item.prop === 'estTransPrice'">
+            {{ formatPrice(row.estTransPrice) }}
+          </span>
+          <span v-else-if="item.prop === 'approStatus'"></span>
           <span v-else>{{ row[item.prop] }}</span>
         </template>
       </el-table-column>