销售报价单列表页增加统计内容及接口联调、添加报价单天天客户名称及对应限制功能
5个文件已修改
258 ■■■■ 已修改文件
src/api/sales/quotation.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/style/index.scss 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/makepager/CommonSearch.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/sales/quotation/AddQuotationDialog.vue 130 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/sales/quotation/index.vue 85 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/sales/quotation.js
@@ -32,3 +32,11 @@
    data
  })
}
// 报价单统计
export function getQuotationStatistics(data) {
  return request({
    url: "/api/quotation/statistics",
    method: "get",
    data
  })
}
src/assets/style/index.scss
@@ -11,3 +11,24 @@
  border: 0;
  outline: 0;
}
.Badge {
  width: 6px;
  height: 6px;
  background: red;
  border-radius: 100%;
  display: inline-block;
  margin-bottom: 1px;
  margin-right: 5px;
}
.success {
  background: #06c062;
}
.error {
  background: #f62f2f;
}
.warning-radio {
  background: #e6a23c;
}
.warning {
  background: rgba(0, 0, 0, 0.4);
}
src/components/makepager/CommonSearch.vue
@@ -26,14 +26,14 @@
            <dd class="top_right_bottom">{{ twoObject.label }}</dd>
          </dl>
        </div>
        <div class="top_left" style="width: 10%">
        <div class="top_left" style="width: 20%">
          <dl>
            <dd class="font_weight">{{ totalObject.value }}</dd>
            <dd class="top_right_bottom">{{ totalObject.label }}</dd>
          </dl>
        </div>
        <div class="top_right" style="width: 50%; margin-right: 15px">
          <dl v-for="item in otherOptions" :key="item.value">
          <dl v-for="(item, index) in otherOptions" :key="index">
            <dd class="font_weight">
              {{ item.value }}
            </dd>
@@ -131,7 +131,7 @@
        {
          value: 2,
          label: "安全库存",
          status: "success"
          status: "warning-radio"
        },
        {
          value: 12,
@@ -243,7 +243,7 @@
      display: flex;
      justify-content: right;
      .top_left {
        width: 10%;
        width: 20%;
        border-right: 1px solid #ccc;
        display: flex;
        padding-right: 2%;
@@ -308,12 +308,6 @@
        }
      }
    }
  }
  .success {
    background: #06c062;
  }
  .yellow {
    background: #e6a23c;
  }
}
src/views/sales/quotation/AddQuotationDialog.vue
@@ -165,8 +165,44 @@
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="销售机会" prop="sale_chance_name"
                :rules="[{ required: autoCodeHeadersObj.Xsjh=='yes'?true:false, validator: this.checkChance, trigger: 'change' }]">
                <el-form-item label="客户名称" prop="client_name">
                  <div class="custom-name">
                    <el-autocomplete
                      style="width: 100%"
                      v-model="editConfig.infomation.client_name"
                      :fetch-suggestions="
                        (queryString, callback) => {
                          querySearchAsync(queryString, callback, 'client')
                        }
                      "
                      value-key="name"
                      @select="handleSelectClient('client', $event)"
                    ></el-autocomplete>
                    <div class="common-select-btn" @click="selClientClick('client')">
                      <i class="el-icon-circle-plus-outline" title="选择"></i>
                    </div>
                    <div
                      v-if="editConfig.infomation.client_name && editConfig.infomation.client_name.length > 0"
                      class="common-select-btn"
                      @click="clearupClient('client')"
                    >
                      <i class="el-icon-remove-outline" title="清除"></i>
                    </div>
                  </div>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item
                  label="销售机会"
                  prop="sale_chance_name"
                  :rules="[
                    {
                      required: autoCodeHeadersObj.Xsjh == 'yes' ? true : false,
                      validator: this.checkChance,
                      trigger: 'change'
                    }
                  ]"
                >
                  <div class="custom-name">
                    <el-autocomplete
                      v-model="editConfig.infomation.sale_chance_name"
@@ -336,6 +372,7 @@
import SelectContactDialog from "@/views/other/commonDialog/SelectContactDialog"
import SelectChanceDialog from "@/views/other/commonDialog/SelectChanceDialog"
import codeMixin from "@/components/makepager/mixin/codeMixin"
import { getSaleChanceList } from "@/api/sales/salesOpportunity"
export default {
  name: "QuotationDialog",
  mixins: [codeMixin],
@@ -361,10 +398,10 @@
    },
    contactNamelist() {
      return this.$store.state.getClientName.contactNamelist
    },
    saleChancelist() {
      return this.$store.state.getClientName.saleChancelist
    }
    // saleChancelist() {
    //   return this.$store.state.getClientName.saleChancelist
    // }
  },
  data() {
    return {
@@ -376,7 +413,8 @@
        quotationName: [{ required: true, message: "请输入", trigger: "blur" }],
        quotation_status_id: [{ required: true, message: "请选择", trigger: "change" }],
        // sale_chance_name: [{ required: true, validator: this.checkChance, trigger: "change" }],
        member_id: [{ required: true, validator: this.validateMemberId, trigger: "change" }]
        member_id: [{ required: true, validator: this.validateMemberId, trigger: "change" }],
        client_name: [{ required: true, message: "请选择客户名称", trigger: "change" }]
      },
      memberOptions: [],
      quotationStatusOptions: [], // 报价单状态
@@ -410,24 +448,29 @@
      tableData: [],
      productId: 1,
      isNoProduct: true,
      objCode: { name: "", page: 0, pageSize: 0, type: "报价编码", codeStandID: "" }
      objCode: { name: "", page: 0, pageSize: 0, type: "报价编码", codeStandID: "" },
      clientOptions: [], // 客户
      saleChancelist: []
    }
  },
  created() {
    this.$store.dispatch("geClient")
    this.$store.dispatch("geContact")
    this.$store.dispatch("geChance")
    // this.$store.dispatch("geChance")
    this.setTableForm()
    this.getCommonData()
    this.formInfo()
    this.getUseSystemSet({modeType:'bjd'})
    this.getUseSystemSet({ modeType: "bjd" })
    if (this.editConfig.title === "编辑") {
      this.getSaleChanceList({ id: this.editConfig.infomation.client_id })
    }
  },
  watch: {
    "editConfig.visible"(val) {
      if (val) {
        this.formInfo()
      }
    },
    }
  },
  methods: {
    formInfo() {
@@ -441,7 +484,7 @@
      getAllData()
        .then((res) => {
          this.memberOptions = res.data.member
          this.quotationStatusOptions = res.data.quotationStatus?res.data.quotationStatus:[]
          this.quotationStatusOptions = res.data.quotationStatus ? res.data.quotationStatus : []
          if (this.editConfig.title === "新建") {
            let username = document.cookie.replace(/(?:(?:^|.*;\s*)username\s*=\s*([^;]*).*$)|^.*$/, "$1")
            this.memberOptions.map((item) => {
@@ -449,10 +492,13 @@
                this.$set(this.editConfig.infomation, "member_id", item.id)
              }
            })
            this.$set(this.editConfig.infomation,'quotation_status_id',this.quotationStatusOptions.length>0?this.quotationStatusOptions[0].id:'')
            this.$set(
              this.editConfig.infomation,
              "quotation_status_id",
              this.quotationStatusOptions.length > 0 ? this.quotationStatusOptions[0].id : ""
            )
          }
          this.dataProcess()
          // this.dataProcess()
        })
        .catch((err) => {
          console.log(err)
@@ -481,11 +527,11 @@
            this.$message.error("产品名称不能为空")
          } else {
            for (let i = 0; i < this.tableData.length; i++) {
              if (this.tableData[i].cost||Number(this.tableData[i].cost)==0) {
                let reg = /^\+?[1-9]\d*$/;
                if(!reg.test(this.tableData[i].cost)){
              if (this.tableData[i].cost || Number(this.tableData[i].cost) == 0) {
                let reg = /^\+?[1-9]\d*$/
                if (!reg.test(this.tableData[i].cost)) {
                  this.$message.error("成本单价需要填写大于0的2位小数!")
                  return true;
                  return true
                }
              }
            }
@@ -568,6 +614,7 @@
      console.log(value)
      if (value === "client") {
        this.clientId = item.id
        this.getSaleChanceList(item)
      } else if (value === "chance") {
        this.saleChanceId = item.id
      } else {
@@ -580,6 +627,7 @@
      } else if (value === "contact") {
        this.editSelectContactConfig.editVisible = true
      } else if (value === "chance") {
        this.editSelectChanceConfig.clientId = this.clientId
        this.editSelectChanceConfig.editVisible = true
      }
    },
@@ -594,6 +642,7 @@
      } else {
        this.editConfig.infomation.client_name = row.name
        this.clientId = row.id
        this.getSaleChanceList(row)
      }
      this.refresh()
    },
@@ -611,6 +660,19 @@
      }
      this.refresh()
    },
    // 销售机会列表
    async getSaleChanceList(item) {
      await getSaleChanceList({
        page: 1,
        pageSize: 15,
        search_map: {
          client_id: item.id
        }
      }).then((res) => {
        console.log(res)
        this.saleChancelist = res.data.list
      })
    },
    // 添加附件
    addAnnexClick() {},
    // 设置允许上传文件格式
@@ -626,9 +688,9 @@
            name: "",
            number: "",
            price: 0,
            cost:'',
            profit:'',
            margin:'',
            cost: "",
            profit: "",
            margin: "",
            total: 0,
            unit: ""
          }
@@ -643,13 +705,13 @@
        tableData: this.tableData,
        tableColumn: [
          { label: "#", prop: "productId", width: 40 },
          { label: "产品名称", prop: "name", productName: true, isRequird: true,min:110, },
          { label: "产品名称", prop: "name", productName: true, isRequird: true, min: 110 },
          { label: "产品编号", prop: "number" },
          { label: "单位", prop: "unit" },
          { label: "销售单价", prop: "price", inputFloat: true, isRequird: true },
          { label: "成本单价", prop: "cost",input: true  },
          { label: "成本单价", prop: "cost", input: true },
          { label: "毛利", prop: "profit" },
          { label: "毛利率(%)", prop: "margin",min:90},
          { label: "毛利率(%)", prop: "margin", min: 90 },
          { label: "数量", prop: "amount", inputNumber: true, isRequird: true },
          { label: "价税合计", prop: "total", inputFloat: true }
        ]
@@ -684,14 +746,14 @@
      // this.showSummary.show = true
    },
    // 新增方式修改
    getSelectArray(val){
      if(val.length>0){
    getSelectArray(val) {
      if (val.length > 0) {
        val.map((item, index) => {
          item.productId = this.tableData.length + index+1
          item.productId = this.tableData.length + index + 1
        })
      }
      this.tableData=this.tableData.concat(val);
      this.productTableList.tableData=this.tableData
      this.tableData = this.tableData.concat(val)
      this.productTableList.tableData = this.tableData
      this.showSummary.show = true
    },
    //  产品清空
@@ -706,9 +768,9 @@
          name: "",
          number: "",
          price: 0,
          cost:'',
          profit:'',
          margin:'',
          cost: "",
          profit: "",
          margin: "",
          total: 0,
          unit: ""
        }
@@ -726,9 +788,9 @@
      if (this.editConfig.infomation.sale_chance_name && this.editConfig.infomation.sale_chance_name.length > 0) {
        callback()
      } else {
        if(this.autoCodeHeadersObj.Xsjh=='yes'){
        if (this.autoCodeHeadersObj.Xsjh == "yes") {
          callback(new Error("请选择销售机会"))
        }else{
        } else {
          callback()
        }
      }
src/views/sales/quotation/index.vue
@@ -6,7 +6,14 @@
    <div class="filter" v-else>
      <div class="filter-card">
        <CommonSearch :show-add="false" :amount-view="false" placeholder="请输入报价单号" @searchClick="onFilterSearch">
        <CommonSearch
          :show-add="false"
          :amount-view="true"
          :totalObject="totalObject"
          :otherOptions="otherOptions"
          placeholder="请输入报价单号"
          @searchClick="onFilterSearch"
        >
          <template slot="leftButton">
            <el-button size="small" type="primary" @click="addBtnClick">新建</el-button>
            <!--            <el-button size="small"  @click="delClick">删除</el-button>-->
@@ -50,8 +57,8 @@
            class="tab-pane"
            @click="getTab(0)"
            :style="{
              background: TabsIndex==0 ? '#2a78fb' : '#F1F3F8',
              color: TabsIndex==0 ? '#fff' : '#666'
              background: TabsIndex == 0 ? '#2a78fb' : '#F1F3F8',
              color: TabsIndex == 0 ? '#fff' : '#666'
            }"
          >
            产品信息
@@ -76,7 +83,7 @@
<script>
import AddQuotationDialog from "@/views/sales/quotation/AddQuotationDialog"
import { getQuotationList, getDelQuotation } from "@/api/sales/quotation"
import { getQuotationList, getDelQuotation, getQuotationStatistics } from "@/api/sales/quotation"
import pageMixin from "@/components/makepager/pager/mixin/pageMixin"
import DetailQuotation from "@/views/sales/quotation/DetailQuotation"
export default {
@@ -102,8 +109,8 @@
  },
  computed: {},
  data() {
     // 产品信息
     const productColumn = [
    // 产品信息
    const productColumn = [
      { label: "产品编号", prop: "number", default: true },
      { label: "产品名称", prop: "name" },
      { label: "数量", prop: "amount" },
@@ -111,7 +118,7 @@
      { label: "销售单价", prop: "price" },
      { label: "成本单价", prop: "cost" },
      { label: "毛利", prop: "profit" },
      { label: "毛利率(%)", prop: "margin",},
      { label: "毛利率(%)", prop: "margin" },
      { label: "价税合计", prop: "total", price: true }
    ]
    return {
@@ -163,20 +170,41 @@
        { label: "销售负责人", prop: "member_name" }, // 销售负责人
        { label: "有效期", prop: "validity_date", min: 100 }, // 修改时间
        // { label: "小计", prop: "subTotal" }, // 小计
        { label: "合计", prop: "amountTotal", price:true}, // 合计
        { label: "客戶名称", prop: "client_name",min: 120,},
        { label: "状态", prop: "quotationStatus",}
        { label: "合计", prop: "amountTotal", price: true }, // 合计
        { label: "客戶名称", prop: "client_name", min: 120 },
        { label: "状态", prop: "quotationStatus" }
      ],
      showCol: ["报价单号", "报价单名称",  "销售负责人", "有效期", "客戶名称",'合计',"状态"],
      showCol: ["报价单号", "报价单名称", "销售负责人", "有效期", "客戶名称", "合计", "状态"],
      selectRow: {},
      loading:false,
      loading: false,
      // 增加 产品信息列表
      TabsIndex:0,
      TabsIndex: 0,
      tableBottomColumn: [],
      showBottomCol: [],
      productTableList: {},
      productColumn: productColumn,
      showProductCol: ["产品编号", "产品名称", "数量", "单位", "销售单价", "成本单价", "毛利", "毛利率(%)", "价税合计"],
      totalObject: {
        value: 0,
        label: "总报价单"
      },
      otherOptions: [
        {
          value: 0,
          label: "已创建",
          status: "success"
        },
        {
          value: 0,
          label: "已审批",
          status: "success"
        },
        {
          value: 0,
          label: "已接受",
          status: "success"
        }
      ]
    }
  },
  created() {
@@ -189,8 +217,27 @@
      }
    }
    this.getData(this.search_map)
    this.getQuotationStatistics()
  },
  methods: {
    // 获取报价单统计
    async getQuotationStatistics() {
      await getQuotationStatistics().then((res) => {
        if (res.code === 200) {
          console.log(res)
          this.totalObject.value = res.data.total
          this.otherOptions.map((item) => {
            if (item.label === "已创建") {
              item.value = res.data.created
            } else if (item.label === "已审批") {
              item.value = res.data.approved
            } else if (item.label === "已接受") {
              item.value = res.data.accepted
            }
          })
        }
      })
    },
    //获取当前选中资源的id
    getTab(tab) {
      this.TabsIndex = tab
@@ -200,7 +247,7 @@
        this.showBottomCol = this.showProductCol
        this.setBottomList()
        this.getProductInventoryInfo(this.selectRow)
      }
      }
    },
    // 获取产品/库存信息
    async getProductInventoryInfo(row) {
@@ -211,7 +258,7 @@
      this.selectRow = row
      if (this.TabsIndex == 0) {
        this.getProductInventoryInfo(this.selectRow)
      }
      }
    },
    setTable() {
      this.tableList = {
@@ -289,7 +336,7 @@
                  client_name: item.client.name,
                  contact_name: item.contact.name,
                  member_name: item.member.username,
                  quotationStatus:item.quotation_status.name,
                  quotationStatus: item.quotation_status.name
                }
              })
              this.tableList.tableInfomation = list || []
@@ -327,9 +374,9 @@
    // 编辑
    handleClick(row) {
      this.editConfig.title = "编辑"
      let params = JSON.parse(JSON.stringify(row));
      this.editConfig.infomation = { ...params, currency: "人民币" }
      console.log(this.editConfig.infomation.products,'===products')
      let params = JSON.parse(JSON.stringify(row))
      this.editConfig.infomation = { ...params, currency: "人民币", sale_chance_name: params.sale_chance.name }
      console.log(this.editConfig.infomation.products, "===products")
      this.editConfig.visible = true
    },
    // 批量删除