Răsfoiți Sursa

feature:增加 项目升降级,转储备

liuzl 3 ani în urmă
părinte
comite
c7987420d3

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+frontend_mobile/node_modules/
+frontend_mobile/unpackage/

+ 29 - 0
frontend_mobile/api/base/distr.js

@@ -0,0 +1,29 @@
+import micro_request from '@/utils/micro_request'
+
+const basePath = process.uniEnv.VUE_APP_ParentPath
+export default {
+  // 获取省列表
+  getProvinceInfo(query) {
+    return micro_request.postRequest(basePath, 'District', 'GetProvinceList', query)
+  },
+  // 获取列表
+  getList(query) {
+    return micro_request.postRequest(basePath, 'Distributor', 'GetList', query)
+  },
+  //创建经销商
+  doAdd(query) {
+    return micro_request.postRequest(basePath, 'Distributor', 'Create', query)
+  },
+  //修改经销商
+  doEdit(query) {
+    return micro_request.postRequest(basePath, 'Distributor', 'UpdateById', query)
+  },
+  // 删除
+  doDelete(query) {
+    return micro_request.postRequest(basePath, 'Distributor', 'DeleteByIds', query)
+  },
+  //详情
+  getEntity(query) {
+    return micro_request.postRequest(basePath, 'Distributor', 'GetEntityById', query)
+  },
+}

+ 21 - 0
frontend_mobile/api/base/product.js

@@ -0,0 +1,21 @@
+import micro_request from '@/utils/micro_request'
+
+const basePath = process.uniEnv.VUE_APP_ParentPath
+export default {
+  // 获取列表
+  getList(query) {
+    return micro_request.postRequest(basePath, 'Product', 'GetList', query)
+  },
+  doAdd(query) {
+    return micro_request.postRequest(basePath, 'Product', 'Create', query)
+  },
+  doEdit(query) {
+    return micro_request.postRequest(basePath, 'Product', 'UpdateById', query)
+  },
+  doDelete(query) {
+    return micro_request.postRequest(basePath, 'Product', 'DeleteByIds', query)
+  },
+  getDetails(query) {
+    return micro_request.postRequest(basePath, 'Product', 'GetEntityById', query)
+  },
+}

+ 136 - 0
frontend_mobile/components/SelectCustomer.vue

@@ -0,0 +1,136 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-02-15 10:34:49
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-02-20 11:38:06
+ * @Description: file content
+ * @FilePath: \frontend_mobile\components\SelectCustomer.vue
+-->
+<template>
+  <view>
+    <u-popup :show="selectVisible" @close="close">
+      <view class="tit">选择客户</view>
+      <view class="search-container">
+        <view class="search-input">
+          <u-input
+            clearable
+            placeholderStyle="font-size:26rpx"
+            :customStyle="{ height: '66rpx' }"
+            v-model="queryForm.custName"
+            prefixIcon="search"
+            prefixIconStyle="font-size: 22px;color: #909399"
+            placeholder="请输入客户名称"
+            shape="circle"
+            border="surround"></u-input>
+        </view>
+        <view class="search-btn" @click="getUserList()">搜索</view>
+      </view>
+      <u-empty mode="list" v-if="userList.length == 0"></u-empty>
+      <view class="concat-list" v-else>
+        <u-radio-group v-model="userValue" placement="column">
+          <view class="radio-item" v-for="item in userList" :key="item.id">
+            <u-radio :label="item.label" :name="item.id" @change="radioChange"></u-radio>
+          </view>
+        </u-radio-group>
+      </view>
+    </u-popup>
+  </view>
+</template>
+
+<script>
+  import customerApi from '@/api/customer'
+  import to from 'await-to-js'
+  export default {
+    name: 'OmsCustomerContact',
+    props: {
+      queryParams: {
+        type: Object,
+        default() {
+          return {}
+        },
+      },
+    },
+    data() {
+      return {
+        selectVisible: false,
+        userList: [],
+        queryForm: {
+          custName: '',
+          pageNum: 1,
+          pageSize: 999,
+        },
+        // u-radio-group的v-model绑定的值如果设置为某个radio的name,就会被默认选中
+        userValue: null,
+        selected: null,
+      }
+    },
+
+    methods: {
+      async getUserList() {
+        let params = Object.assign(this.queryForm, this.queryParams)
+        const [err, res] = await to(customerApi.getList(params))
+        if (err) return
+        if (res.code == 200) {
+          if (res.data.list.length > 0) {
+            this.userList = res.data.list.map((item) => ({
+              id: item.id,
+              label: `${item.custName}/${item.custIndustry}`,
+              name: item.custName,
+            }))
+          } else {
+            this.userList = []
+          }
+        }
+      },
+      open() {
+        this.selectVisible = true
+        this.getUserList()
+      },
+      close() {
+        this.selectVisible = false
+        this.$emit('close', this.selected)
+      },
+      radioChange(n) {
+        this.selected = this.userList.find((item) => item.id == n)
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .tit {
+    font-size: 26rpx;
+    font-weight: bold;
+    padding: 30rpx 0 0 30rpx;
+  }
+  .search-container {
+    padding: 30rpx 30rpx 0 30rpx;
+    display: flex;
+    align-items: center;
+    .search-input {
+      flex: 1;
+    }
+    .search-btn {
+      text-align: center;
+      line-height: 60rpx;
+      border-radius: 12rpx;
+      width: 100rpx;
+      height: 60rpx;
+      font-size: 26rpx;
+      margin: 0 0 0 12rpx;
+      background: $u-primary;
+      color: #ffffff;
+    }
+  }
+  .concat-list {
+    padding: 0 0 20rpx 0;
+    width: 100%;
+    height: 900rpx;
+    overflow: auto;
+    margin-top: 20rpx;
+    .radio-item {
+      padding: 20rpx 30rpx;
+      border-bottom: 1px solid #ccc;
+    }
+  }
+</style>

+ 129 - 0
frontend_mobile/components/SelectDealer.vue

@@ -0,0 +1,129 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-02-15 10:34:49
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-02-20 15:15:45
+ * @Description: file content
+ * @FilePath: \frontend_mobile\components\SelectDealer.vue
+-->
+<template>
+  <view>
+    <u-popup :show="selectVisible" @close="close">
+      <view class="tit">选择经销商/代理商</view>
+      <view class="search-container">
+        <view class="search-input">
+          <u-input
+            clearable
+            placeholderStyle="font-size:26rpx"
+            :customStyle="{ height: '66rpx' }"
+            v-model="queryForm.distName"
+            prefixIcon="search"
+            prefixIconStyle="font-size: 22px;color: #909399"
+            placeholder="请输入客户名称"
+            shape="circle"
+            border="surround"></u-input>
+        </view>
+        <view class="search-btn" @click="getList()">搜索</view>
+      </view>
+      <view class="tit">经销商名称/助记名/所在省份/归属销售/负责人</view>
+      <u-empty mode="list" v-if="userList.length == 0"></u-empty>
+      <view class="concat-list" v-else>
+        <u-radio-group v-model="userValue" placement="column">
+          <view class="radio-item" v-for="item in userList" :key="item.id">
+            <u-radio :label="item.label" :name="item.id" @change="radioChange"></u-radio>
+          </view>
+        </u-radio-group>
+      </view>
+    </u-popup>
+  </view>
+</template>
+
+<script>
+  import distrApi from '@/api/base/distr'
+  import to from 'await-to-js'
+  export default {
+    name: 'OmsCustomerContact',
+    data() {
+      return {
+        selectVisible: false,
+        userList: [],
+        queryForm: {
+          distName: '',
+          pageNum: 1,
+          pageSize: 999,
+        },
+        // u-radio-group的v-model绑定的值如果设置为某个radio的name,就会被默认选中
+        userValue: null,
+        selected: null,
+      }
+    },
+
+    methods: {
+      async getList() {
+        let params = this.queryForm
+        const [err, res] = await to(distrApi.getList(params))
+        if (err) return
+        if (res.code == 200) {
+          if (res.data.list.length > 0) {
+            this.userList = res.data.list.map((item) => ({
+              id: item.id,
+              label: `${item.distName}/${item.abbrName}/${item.provinceDesc}/${item.belongSale}/${item.distBoss}`,
+              name: item.distName,
+            }))
+          } else {
+            this.userList = []
+          }
+        }
+      },
+      open() {
+        this.selectVisible = true
+        this.getList()
+      },
+      close() {
+        this.selectVisible = false
+        this.$emit('close', this.selected)
+      },
+      radioChange(n) {
+        this.selected = this.userList.find((item) => item.id == n)
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .tit {
+    font-size: 26rpx;
+    font-weight: bold;
+    padding: 30rpx 0 0 30rpx;
+  }
+  .search-container {
+    padding: 30rpx 30rpx 0 30rpx;
+    display: flex;
+    align-items: center;
+    .search-input {
+      flex: 1;
+    }
+    .search-btn {
+      text-align: center;
+      line-height: 60rpx;
+      border-radius: 12rpx;
+      width: 100rpx;
+      height: 60rpx;
+      font-size: 26rpx;
+      margin: 0 0 0 12rpx;
+      background: $u-primary;
+      color: #ffffff;
+    }
+  }
+  .concat-list {
+    padding: 0 0 20rpx 0;
+    width: 100%;
+    height: 900rpx;
+    overflow: auto;
+    margin-top: 20rpx;
+    .radio-item {
+      padding: 20rpx 30rpx;
+      border-bottom: 1px solid #ccc;
+    }
+  }
+</style>

+ 167 - 0
frontend_mobile/components/SelectProduct.vue

@@ -0,0 +1,167 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-02-15 10:34:49
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-02-20 18:20:37
+ * @Description: file content
+ * @FilePath: \frontend_mobile\components\SelectProduct.vue
+-->
+<template>
+  <view>
+    <u-popup :show="selectVisible" @close="close">
+      <view class="tit">选择产品</view>
+      <view class="search-container">
+        <view class="search-input">
+          <u-input
+            clearable
+            placeholderStyle="font-size:26rpx"
+            :customStyle="{ height: '66rpx' }"
+            v-model="queryForm.prodName"
+            prefixIcon="search"
+            prefixIconStyle="font-size: 22px;color: #909399"
+            placeholder="请输入产品名称"
+            shape="circle"
+            border="surround"></u-input>
+        </view>
+        <view class="search-btn" @click="getProjectList()">搜索</view>
+      </view>
+      <view class="tit">产品名称/产品类别/产品型号</view>
+
+      <view class="flex_l allCheck">
+        <u-checkbox-group placement="column">
+          <u-checkbox label="全部" :checked="isallcheck" @change="checkboxChange"></u-checkbox>
+        </u-checkbox-group>
+      </view>
+      <u-empty mode="list" v-if="checkboxList.length == 0"></u-empty>
+      <view class="concat-list" v-else>
+        <u-checkbox-group v-model="userValue" placement="column">
+          <view class="radio-item" v-for="item in checkboxList" :key="item.id">
+            <u-checkbox
+              :label="item.label"
+              :name="item.id"
+              :checked="item.ischeck"
+              @change="radioChange(item)"></u-checkbox>
+          </view>
+        </u-checkbox-group>
+      </view>
+    </u-popup>
+  </view>
+</template>
+
+<script>
+  import productApi from '@/api/base/product'
+  import to from 'await-to-js'
+  export default {
+    name: 'OmsCustomerContact',
+    data() {
+      return {
+        selectVisible: false,
+        checkboxList: [],
+        queryForm: {
+          prodName: '',
+          pageNum: 1,
+          pageSize: 999,
+          type: '全部客户',
+        },
+        // u-radio-group的v-model绑定的值如果设置为某个radio的name,就会被默认选中
+        userValue: null,
+        isallcheck: false, //全选
+        checkedId: [],
+      }
+    },
+
+    methods: {
+      async getProjectList() {
+        let params = Object.assign(this.queryForm, this.queryParams)
+        const [err, res] = await to(productApi.getList(params))
+        if (err) return
+        if (res.code == 200) {
+          if (res.data.list) {
+            this.checkboxList = res.data.list.map((item) => ({
+              ...item,
+              label: `${item.prodName}/${item.prodClass}/${item.prodCode}`,
+              ischeck: false,
+              prodNum: '1',
+            }))
+          } else {
+            this.checkboxList = []
+          }
+          let allChecked = this.checkboxList.length == 0 ? false : this.checkboxList.every((el) => el.ischeck === true)
+          if (allChecked) {
+            this.isallcheck = true //都有 全选
+          } else {
+            this.isallcheck = false // 反选
+          }
+        }
+      },
+      open() {
+        this.selectVisible = true
+        this.getProjectList()
+      },
+      close() {
+        this.selectVisible = false
+        let selected = this.checkboxList.filter((item) => item.ischeck)
+        this.$emit('close', selected)
+      },
+      radioChange(item) {
+        item.ischeck = !item.ischeck
+        let allChecked = this.checkboxList.length == 0 ? false : this.checkboxList.every((el) => el.ischeck === true)
+        if (allChecked) {
+          this.isallcheck = true //都有 全选
+        } else {
+          this.isallcheck = false // 反选
+        }
+        console.log(' this.isallcheck', this.isallcheck)
+      },
+      // 全部
+      checkboxChange() {
+        this.isallcheck = !this.isallcheck
+        this.checkboxList.forEach((el) => {
+          el.ischeck = this.isallcheck
+        })
+        console.log(this.checkboxList)
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .tit {
+    font-size: 26rpx;
+    font-weight: bold;
+    padding: 30rpx 0 0 30rpx;
+  }
+  .search-container {
+    padding: 30rpx 30rpx 0 30rpx;
+    display: flex;
+    align-items: center;
+    .search-input {
+      flex: 1;
+    }
+    .search-btn {
+      text-align: center;
+      line-height: 60rpx;
+      border-radius: 12rpx;
+      width: 100rpx;
+      height: 60rpx;
+      font-size: 26rpx;
+      margin: 0 0 0 12rpx;
+      background: $u-primary;
+      color: #ffffff;
+    }
+  }
+  .allCheck {
+    padding: 30rpx 0 0 30rpx;
+  }
+  .concat-list {
+    padding: 0 0 20rpx 0;
+    width: 100%;
+    height: 900rpx;
+    overflow: auto;
+    margin-top: 20rpx;
+    .radio-item {
+      padding: 20rpx 30rpx;
+      border-bottom: 1px solid #ccc;
+    }
+  }
+</style>

+ 94 - 0
frontend_mobile/components/currency/index.vue

@@ -0,0 +1,94 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-01-10 16:18:28
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-01-17 17:44:24
+ * @Description: file content
+ * @FilePath: \订单全流程管理系统\src\components\currency\index.vue
+-->
+<template>
+  <view>
+    <u-input
+      v-model="num"
+      @blur="inputMoney($event)"
+      @change="handleChange"
+      @focus="uninputMoney($event)"
+      @input="returnNum" />
+  </view>
+</template>
+
+<script>
+  export default {
+    name: 'AmountInput',
+    props: {
+      value: {
+        type: [String, Number],
+        default: '0',
+      },
+    },
+    data() {
+      return {
+        num: '',
+      }
+    },
+    watch: {
+      value() {
+        this.num = this.formatPrice(this.value)
+      },
+    },
+    mounted() {
+      this.num = this.formatPrice(this.value)
+    },
+    methods: {
+      returnNum() {
+        if (this.num) {
+          this.$emit('input', this.CurrencyFomatNumber(this.num))
+        }
+      },
+      handleChange(value) {
+        this.$nextTick(() => {
+          this.$emit('change', this.CurrencyFomatNumber(value))
+        })
+      },
+      // 失焦显示数字类型
+      inputMoney(value) {
+        let temp = Number(value) || null
+        this.num = this.formatPrice(temp)
+      },
+      // 获得焦点金额去掉格式
+      uninputMoney() {
+        this.num = this.CurrencyFomatNumber(this.num)
+      },
+      //去除千分位中的‘,’
+      CurrencyFomatNumber(num, n = 2) {
+        let number = num.replace('¥', '')
+        if (number != null && number != '' && number != undefined) {
+          number = number.replace(/,/g, '') //去除千分位的','
+          if (isNaN(number)) {
+            //判断是否是数字
+            number = '0'
+          } else {
+            number = Math.round(number * Math.pow(10, n)) / Math.pow(10, n) //n幂
+            number = number.toString()
+          }
+        } else {
+          number = '0'
+        }
+        //a.indexOf(x,y);返回x值在a字符串值中从y位置开始检索首次出现的位置
+        var numLength = number.indexOf('.')
+        //判断传递的值是整数增加小数点再补"0"
+        if (numLength < 0) {
+          numLength = number.length
+          number += '.'
+        }
+        //不足n位小数的,循环补"0"
+        while (number.length <= numLength + n) {
+          number += '0'
+        }
+        return parseFloat(number)
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped></style>

+ 73 - 0
frontend_mobile/pages/project/components/transferReserve.vue

@@ -0,0 +1,73 @@
+<template>
+  <view>
+    <!-- 转储备项目 -->
+    <u-modal
+      :show="modelVisible"
+      :showCancelButton="true"
+      @confirm="handleConfirm()"
+      @cancel="close()"
+      :asyncClose="true"
+      title="转储备项目">
+      <view class="slot-content" style="width: 100%">
+        <view class="flex">
+          <text>转化原因:</text>
+          <u-textarea
+            v-model="addFrom.projConversionReason"
+            placeholder="请输入转化原因"
+            height="180"
+            :count="true"
+            maxlength="500"></u-textarea>
+        </view>
+      </view>
+    </u-modal>
+  </view>
+</template>
+
+<script>
+  import projectApi from '../../../api/project'
+  import to from 'await-to-js'
+  export default {
+    data() {
+      return {
+        modelVisible: false,
+        addFrom: {
+          projConversionReason: '',
+          id: null,
+        },
+      }
+    },
+    methods: {
+      open(id) {
+        this.addFrom.id = id
+        this.modelVisible = true
+      },
+      // 移入公海
+      async handleConfirm() {
+        let params = this.addFrom
+        const [err, res] = await to(projectApi.toReserve(params))
+        if (err) return this.close()
+        console.log(res.code)
+        if (res.code == 200) {
+          this.$refs.uToast.show({
+            type: 'loading',
+            message: '转储备成功',
+            complete: () => {
+              this.modelVisible = false
+              this.$emit('fetchList')
+            },
+          })
+        } else {
+          this.close()
+        }
+      },
+      // 关闭移入公海模块
+      close() {
+        this.addFrom.id = []
+        this.addFrom.projConversionReason = ''
+        this.modelVisible = false
+      },
+    },
+  }
+</script>
+
+<style></style>

+ 875 - 0
frontend_mobile/pages/project/create.vue

@@ -0,0 +1,875 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-01-12 11:57:48
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-02-21 19:28:18
+ * @Description: file content
+ * @FilePath: \frontend_mobile\pages\project\create.vue
+-->
+<template>
+  <view class="home">
+    <view class="nav">
+      <view :style="{ paddingTop }">
+        <view class="title" :style="[{ height }, { lineHeight: height }]">
+          <view class="back" @click="goBack()">
+            <u-icon name="arrow-left" color="#ffffff" size="22"></u-icon>
+          </view>
+          <text>项目创建</text>
+        </view>
+      </view>
+    </view>
+    <view class="main">
+      <view class="step1" v-if="step == 1">
+        <u-form :model="addForm" :rules="rules" ref="addForm" label-width="0">
+          <u-form-item prop="nboName" borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              项目名称
+            </view>
+            <u-input
+              placeholder="输入项目名称"
+              v-model="addForm.nboName"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item prop="custName" borderBottom customStyle="padding:40rpx 0 30rpx" @click="$refs.cust.open()">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              关联客户
+            </view>
+            <u-input
+              v-model="addForm.custName"
+              disabled
+              disabledColor="#ffffff"
+              placeholder="请选择关联客户"
+              border="none"></u-input>
+            <u-icon slot="right" name="arrow-right"></u-icon>
+          </u-form-item>
+          <u-form-item
+            prop="nboSourceVal"
+            borderBottom
+            customStyle="padding:40rpx 0 30rpx"
+            @click="showNboSource = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              项目来源
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择项目来源"
+              v-model="addForm.nboSourceVal"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item prop="contactName" borderBottom customStyle="padding:40rpx 0 30rpx" @click="openContactUser()">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              主要联系人
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择主要联系人"
+              v-model="addForm.contactName"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              职位
+            </view>
+            <u-input
+              placeholder="请输入职位"
+              v-model="addForm.contactPostion"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              联系电话
+            </view>
+            <u-input
+              placeholder="请输入联系电话"
+              v-model="addForm.contactTelephone"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item prop="saleName" borderBottom customStyle="padding:40rpx 0 30rpx" @click="$refs.user.open()">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              销售工程师
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择销售工程师"
+              v-model="addForm.saleName"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item prop="salesVal" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showModel = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              销售模式
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择销售模式"
+              v-model="addForm.salesVal"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="$refs.dealer.open()">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              经销商/代理商
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择经销商/代理商"
+              v-model="addForm.distributorName"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item prop="productLineVal" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showLine = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              产品线
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择产品线"
+              v-model="addForm.productLineVal"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showSource = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              项目预算
+            </view>
+            <u-input
+              type="number"
+              placeholder="输入项目预算"
+              v-model="addForm.nboBudget"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+            <!-- <amount-input v-model="addForm.nboBudget" placeholder="请输入金额" /> -->
+          </u-form-item>
+          <u-form-item prop="isBigVal" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showLarge = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              是否大项目
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择是否大项目"
+              v-model="addForm.isBigVal"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showEstTransDate = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              预计成交时间
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择预计成交时间"
+              v-model="addForm.estTransTime"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showPlanDate = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              计划采购时间
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择计划采购时间"
+              v-model="addForm.planPurchaseTime"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showDate = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              风险情况
+            </view>
+            <u-input
+              placeholder="输入风险情况"
+              v-model="addForm.riskProfile"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showDate = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              困难点
+            </view>
+            <u-input
+              placeholder="输入困难点"
+              v-model="addForm.difficulty"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showDate = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              竞争公司
+            </view>
+            <u-input
+              placeholder="输入竞争公司"
+              v-model="addForm.competitor"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showDate = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              介入情况
+            </view>
+            <u-input
+              placeholder="输入介入情况"
+              v-model="addForm.intervention"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              备注
+            </view>
+            <u-input
+              placeholder="输入备注"
+              v-model="addForm.remark"
+              border="none"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+        </u-form>
+      </view>
+      <view class="step2" v-else-if="step == 2">
+        <view class="step-tit">添加产品</view>
+        <view class="add-btn" @click="$refs.product.open()">添加产品</view>
+        <view class="product-wrap">
+          <view class="product-item" v-for="(v, i) in productList" :key="v.id">
+            <view class="product-label flex_l">
+              产品编码:
+              <view class="product-val">{{ v.prodCode }}</view>
+            </view>
+            <view class="product-label flex_l">
+              产品名称:
+              <view class="product-val">{{ v.prodName }}</view>
+            </view>
+            <view class="product-label flex_l">
+              产品类别:
+              <view class="product-val">{{ v.prodClass }}</view>
+            </view>
+            <view class="product-label flex_l">
+              产品单价:
+              <view class="product-val">
+                <u-input v-model="productList[i].guidPrice" clearable></u-input>
+              </view>
+            </view>
+            <view class="product-label flex_l">
+              产品数量:
+              <view class="product-val">
+                <u-input v-model="productList[i].prodNum" clearable></u-input>
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="step3" v-else-if="step == 3">
+        <u-form :model="addForm" :rules="rules" ref="addForm" label-width="0">
+          <u-form-item
+            prop="followTime"
+            borderBottom
+            customStyle="padding:40rpx 0 30rpx"
+            @click="showFollowDate = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              跟进时间
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择跟进时间"
+              v-model="addForm.followTime"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item
+            prop="followUserName"
+            borderBottom
+            customStyle="padding:40rpx 0 30rpx"
+            @click="$refs.allUser.open()">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              负责人员
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择负责人员"
+              v-model="addForm.followUserName"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item prop="followContent" borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              跟进内容
+            </view>
+            <u-input
+              placeholder="请输入跟进内容"
+              v-model="addForm.followContent"
+              border="none"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+        </u-form>
+      </view>
+      <view class="center">
+        <view class="handle-btn" v-if="step > 1" @click="previousStep">上一步</view>
+        <view class="handle-btn" v-if="step < 3" @click="nextStep">下一步</view>
+        <view class="handle-btn" v-if="step == 3" @click="handleAdd">保存</view>
+      </view>
+    </view>
+    <!-- 选择下次时间 -->
+    <u-datetime-picker
+      v-if="showEstTransDate"
+      :show="showEstTransDate"
+      mode="datetime"
+      v-model="addForm.estTransTime"
+      @cancel="showEstTransDate = false"
+      @confirm="pickEstTransDate"></u-datetime-picker>
+    <!-- 计划采购时间 -->
+    <u-datetime-picker
+      v-if="showPlanDate"
+      :show="showPlanDate"
+      mode="datetime"
+      v-model="addForm.planPurchaseTime"
+      @cancel="showPlanDate = false"
+      @confirm="pickPlanDate"></u-datetime-picker>
+    <!-- 跟进时间 -->
+    <u-datetime-picker
+      v-if="showFollowDate"
+      :show="showFollowDate"
+      mode="datetime"
+      v-model="addForm.followTime"
+      @cancel="showFollowDate = false"
+      @confirm="pickFollowDate"></u-datetime-picker>
+    <!-- 选择客户 -->
+    <select-customer ref="cust" @close="closeCust()"></select-customer>
+    <!-- 选择客户联系人 -->
+    <customer-contact ref="contact" @close="closeContact()"></customer-contact>
+    <!-- 选择销售 -->
+    <select-user ref="user" :query-params="{ roles: ['Sales', 'SalesManager'] }" @close="closeUser()"></select-user>
+    <!-- 选择经销商 -->
+    <select-dealer ref="dealer" @close="closeDealer()"></select-dealer>
+    <!-- 选择用户 -->
+    <select-user ref="allUser" @close="closeAllUser()"></select-user>
+    <!-- 选择产品 -->
+    <select-product ref="product" @close="closeProduct()"></select-product>
+    <!-- 项目来源 -->
+    <u-picker
+      :show="showNboSource"
+      :columns="nboSourceColumns"
+      keyName="value"
+      @cancel="showNboSource = false"
+      @confirm="pickSource"></u-picker>
+    <!-- 产品线 -->
+    <u-picker
+      :show="showLine"
+      :columns="productLineColumns"
+      keyName="value"
+      @cancel="showLine = false"
+      @confirm="pickLine"></u-picker>
+    <!-- 销售模式 -->
+    <u-picker
+      :show="showModel"
+      :columns="salesModelColumns"
+      keyName="value"
+      @cancel="showModel = false"
+      @confirm="pickModel"></u-picker>
+    <!-- 大项目 -->
+    <u-picker
+      :show="showLarge"
+      :columns="yesOrNoColumns"
+      keyName="value"
+      @cancel="showLarge = false"
+      @confirm="pickLarge"></u-picker>
+    <u-notify ref="uNotify"></u-notify>
+    <u-toast ref="uToast"></u-toast>
+  </view>
+</template>
+<script>
+  import projectApi from 'api/project'
+  import customerApi from '../../api/customer'
+  import to from 'await-to-js'
+  import SelectCustomer from 'components/SelectCustomer'
+  import CustomerContact from 'components/CustomerContact'
+  import SelectUser from 'components/SelectUser'
+  import SelectDealer from 'components/SelectDealer'
+  import AmountInput from 'components/currency'
+  import SelectProduct from 'components/SelectProduct'
+  export default {
+    name: 'omsIndex',
+    components: { SelectCustomer, CustomerContact, SelectUser, SelectDealer, AmountInput, SelectProduct },
+    data() {
+      const validateDistributor = (rule, value, callback) => {
+        if ('' === value && this.form.salesModel !== '10')
+          callback(
+            new Error(
+              this.$refs.uNotify.show({
+                top: this.height + this.paddingTop + 10,
+                type: 'warning',
+                message: '请选择经销商/代理商',
+                duration: 1000 * 3,
+              })
+            )
+          )
+        else callback()
+      }
+      return {
+        step: 1,
+        height: '',
+        paddingTop: '',
+        showNboSource: false, //项目来源选择
+        showModel: false, //销售模式选择
+        showLine: false, //产品线选择
+        showLarge: false, //是否是大项目选择
+        nboSourceColumns: [], //项目来源
+        salesModelColumns: [], //销售模式
+        productLineColumns: [], //产品线
+        yesOrNoColumns: [], //是否是大项目
+        showEstTransDate: false, //选择预计成交时间
+        showPlanDate: false, //计划采购时间
+        showFollowDate: false, //计划采购时间
+        addForm: {
+          nboName: '', //项目名称
+          custId: '', //关联客户id
+          custName: '', //关联客户
+          nboSource: '', //项目来源
+          nboSourceVal: '', //项目来源文字
+          contactId: '', //联系人id
+          contactName: '', //联系人姓名
+          contactPostion: '', //联系人职位
+          contactTelephone: '', //联系人电话
+          saleName: '', //销售工程师
+          saleId: '', //销售工程师id
+          salesModel: '', //销售模式(10直销20经销30代理)
+          salesVal: '', //销售模式文字
+          distributorId: '', //经销商/代理商ID
+          distributorName: '', //经销商/代理商名称
+          productLine: '', //产品线来源
+          productLineVal: '', //产品线文字
+          nboBudget: '', //项目预算
+          isBig: '', //是否是大项目
+          isBigVal: '', //是否是大项目文字
+          estTransTime: this.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}'), //预计成交时间
+          planPurchaseTime: this.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}'), //计划采购时间
+          riskProfile: '', //风险情况
+          difficulty: '', //困难点
+          competitor: '', //竞争公司
+          intervention: '', //介入情况
+          remark: '', //备注
+          followTime: this.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}'), //跟进时间
+          followUserId: '', //跟进用户id
+          followUserName: '', //跟进用户id
+          followContent: '', //跟进内容
+        },
+        rules: {
+          nboName: [{ required: true, trigger: ['blur', 'change'], message: '请输入项目名称' }],
+          custName: [{ required: true, trigger: ['blur', 'change'], message: '请选择关联客户' }],
+          nboSourceVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择项目来源' }],
+          contactName: [{ required: true, trigger: ['blur', 'change'], message: '请选择主要联系人' }],
+          saleName: [{ required: true, trigger: ['blur', 'change'], message: '请选择销售工程师' }],
+          salesModelVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择销售模式' }],
+          distributorName: [
+            { validator: validateDistributor, trigger: ['blur', 'change'], message: '请选择经销商/代理商' },
+          ],
+          isBigVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择是否大项目' }],
+          productLineVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择产品线' }],
+          // 跟进
+          followTime: [{ required: true, trigger: ['blur', 'change'], message: '请输入跟进时间' }],
+          followContent: [{ required: true, trigger: ['blur', 'change'], message: '请输入跟进内容' }],
+        },
+        productList: [],
+      }
+    },
+    onLoad(option) {
+      console.log(option.id) //打印出上个页面传递的参数。
+      this.addForm.custId = parseInt(option.id)
+    },
+    created() {
+      const navData = uni.getMenuButtonBoundingClientRect()
+      this.height = navData.height + 'px'
+      this.paddingTop = navData.top + 'px'
+    },
+    onShow() {
+      if (this.addForm.custId) {
+        this.getCustomerDetail()
+      }
+      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.nboSourceColumns = [nboSource.data.values] || []
+          this.salesModelColumns = [salesModel.data.values] || []
+          this.productLineColumns = [productLine.data.values] || []
+          this.yesOrNoColumns = [yesOrNo.data.values] || []
+        })
+      },
+      async getCustomerDetail() {
+        const [err, res] = await to(customerApi.getDetail({ ids: [this.addForm.custId] }))
+        if (err) return
+        if (res && res.code == 200) {
+          console.log(res)
+          this.addForm.custName = res.data.list[0].custName
+        }
+      },
+      // 打开主要联系人
+      openContactUser() {
+        if (!this.addForm.custId) {
+          this.$refs.uNotify.show({
+            top: this.height + this.paddingTop + 10,
+            type: 'warning',
+            message: '请先选择客户',
+            duration: 1000 * 3,
+          })
+        } else {
+          this.$refs.contact.open(this.addForm.custId)
+        }
+      },
+      // 关闭选择客户
+      closeCust(user) {
+        if (user) {
+          console.log(user)
+          this.addForm.custId = user.id
+          this.addForm.custName = user.name
+        }
+      },
+      // 经销商
+      closeDealer(dealer) {
+        if (dealer) {
+          console.log(dealer)
+          this.addForm.distributorId = dealer.id
+          this.addForm.distributorName = dealer.name
+        }
+      },
+      // 关闭选择客户联系人
+      closeContact(user) {
+        if (user) {
+          console.log(user)
+          this.addForm.contactId = user.id
+          this.addForm.contactName = user.label
+        }
+      },
+      // 关闭选择销售
+      closeUser(user) {
+        if (user) {
+          console.log(user)
+          this.addForm.saleId = user.id
+          this.addForm.saleName = user.label
+        }
+      },
+      // 全部用户
+      closeAllUser(user) {
+        if (user) {
+          console.log(user)
+          this.addForm.followUserId = user.id
+          this.addForm.followUserName = user.label
+        }
+      },
+      closeProduct(product) {
+        let data = [...this.productList, ...product]
+        this.productList = data
+        console.log(this.productList)
+      },
+      // 选择来源
+      pickSource(e) {
+        this.addForm.nboSource = e.value[0].key
+        this.addForm.nboSourceVal = e.value[0].value
+        this.showNboSource = false
+      },
+      // 选择产品线
+      pickLine(e) {
+        this.addForm.productLine = e.value[0].key
+        this.addForm.productLineVal = e.value[0].value
+        this.showLine = false
+      },
+      // 选择销售类型
+      pickModel(e) {
+        this.addForm.salesModel = e.value[0].key
+        this.addForm.salesVal = e.value[0].value
+        this.showModel = false
+      },
+      // 是否大项目
+      pickLarge(e) {
+        this.addForm.isBig = e.value[0].key
+        this.addForm.isBigVal = e.value[0].value
+        this.showLarge = false
+      },
+      // 选择预计成交时间
+      async pickEstTransDate(e) {
+        this.showEstTransDate = false
+        const timeFormat = uni.$u.timeFormat
+        let timeValue = await timeFormat(e.value, 'yyyy-mm-dd hh:MM')
+        this.addForm.estTransTime = timeValue
+        console.log(timeValue)
+      },
+      // 计划采购时间
+      async pickPlanDate(e) {
+        this.showPlanDate = false
+        const timeFormat = uni.$u.timeFormat
+        let timeValue = await timeFormat(e.value, 'yyyy-mm-dd hh:MM')
+        this.addForm.planPurchaseTime = timeValue
+        console.log(timeValue)
+      },
+      // 跟进时间
+      async pickFollowDate(e) {
+        this.showFollowDate = false
+        const timeFormat = uni.$u.timeFormat
+        let timeValue = await timeFormat(e.value, 'yyyy-mm-dd hh:MM')
+        this.addForm.followTime = timeValue
+        console.log(timeValue)
+      },
+      nextStep() {
+        if (this.step == 1) {
+          this.$refs.addForm
+            .validate()
+            .then(async () => {
+              this.step++
+            })
+            .catch((err) => {
+              console.log(err)
+              this.$refs.uNotify.show({
+                top: this.height + this.paddingTop + 10,
+                type: 'warning',
+                message: err[0].message,
+                duration: 1000 * 3,
+              })
+            })
+        } else if (this.step == 2) {
+          if (this.productList.length == 0) {
+            this.$refs.uNotify.show({
+              top: this.height + this.paddingTop + 10,
+              type: 'warning',
+              message: '请选择产品',
+              duration: 1000 * 3,
+            })
+            return
+          }
+          this.step++
+        }
+      },
+      previousStep() {
+        if (this.step > 1) {
+          this.step--
+        }
+      },
+      handleAdd() {
+        this.$refs.addForm
+          .validate()
+          .then(async () => {
+            console.log(this.addForm)
+            let params = this.addForm
+            params.nboBudget = Number(params.nboBudget)
+            let products = this.productList.map((item) => ({
+              ProdId: item.id,
+              ProdName: item.prodName,
+              ProdCode: item.prodCode,
+              ProdClass: item.prodClass,
+              ProdNum: Number(item.prodNum),
+              ProdPrice: Number(item.guidPrice),
+            }))
+            params.products = products
+            const [err, res] = await to(projectApi.create(params))
+            if (err) return
+            if (res && res.code == 200) {
+              this.$refs.uToast.show({
+                type: 'success',
+                message: '创建成功',
+                complete: () => {
+                  this.goBack()
+                },
+              })
+            }
+          })
+          .catch((err) => {
+            console.log(err)
+            this.$refs.uNotify.show({
+              top: this.height + this.paddingTop + 10,
+              type: 'warning',
+              message: err[0].message,
+              duration: 1000 * 3,
+            })
+          })
+      },
+      goBack() {
+        uni.navigateBack({
+          //关闭当前页面,返回上一页面或多级页面。
+          delta: 1,
+        })
+      },
+    },
+  }
+</script>
+<style>
+  page {
+    background: #f2f3f5;
+  }
+</style>
+<style lang="scss" scoped>
+  .home {
+    padding-top: 188rpx;
+
+    .nav {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 284rpx;
+      background: #3c9cff;
+      .title {
+        position: relative;
+        text-align: center;
+        font-size: 32rpx;
+        font-weight: bold;
+        color: #ffffff;
+        .back {
+          position: absolute;
+          top: 0;
+          bottom: 0;
+          margin: auto;
+          left: 70rpx;
+          display: flex;
+        }
+      }
+    }
+
+    .main {
+      position: absolute;
+      width: 100%;
+      height: calc(100vh - 188rpx);
+      background: #ffffff;
+      box-shadow: 0 6rpx 19rpx 2rpx rgba(0, 45, 132, 0.15);
+      border-radius: 31rpx 31rpx 0 0;
+      padding: 0 32rpx;
+      overflow: auto;
+      padding-bottom: 64rpx;
+      .step-tit {
+        text-align: center;
+        line-height: 60rpx;
+        font-size: 26rpx;
+        color: #000;
+      }
+      .form-label {
+        font-size: 32rpx;
+        font-weight: bold;
+        color: #323232;
+        padding-bottom: 18rpx;
+        .label-tag {
+          width: 15rpx;
+          height: 15rpx;
+          background: rgba(62, 126, 248, 0.6);
+          border-radius: 50%;
+          margin-right: -4rpx;
+        }
+      }
+      .handle-btn {
+        width: 234rpx;
+        height: 92rpx;
+        background: #3c9cff;
+        border-radius: 31rpx;
+        margin: 30rpx auto 0;
+        font-size: 32rpx;
+        color: #ffffff;
+        text-align: center;
+        line-height: 92rpx;
+      }
+    }
+    .step2 {
+      .product-wrap {
+        .product-item {
+          margin: 30rpx 0;
+          padding: 20rpx;
+          border-radius: 10px;
+          box-shadow: 0 6rpx 19rpx 2rpx rgba(0, 45, 132, 0.15);
+          .product-label {
+            padding: 20rpx 0 20rpx 20rpx;
+          }
+        }
+      }
+      .add-btn {
+        color: #fff;
+        width: 120rpx;
+        height: 60rpx;
+        padding: 0rpx 8rpx;
+        font-size: 12rpx;
+        background: #3c9cff;
+        border-radius: 3px;
+        text-align: center;
+        line-height: 60rpx;
+        font-size: 22rpx;
+      }
+    }
+  }
+</style>

+ 310 - 0
frontend_mobile/pages/project/downgrade.vue

@@ -0,0 +1,310 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-01-12 11:57:48
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-02-21 15:10:27
+ * @Description: file content
+ * @FilePath: \frontend_mobile\pages\project\downgrade.vue
+-->
+<template>
+  <view class="home">
+    <view class="nav">
+      <view :style="{ paddingTop }">
+        <view class="title" :style="[{ height }, { lineHeight: height }]">
+          <view class="back" @click="goBack()">
+            <u-icon name="arrow-left" color="#ffffff" size="22"></u-icon>
+          </view>
+          <text>项目降级</text>
+        </view>
+      </view>
+    </view>
+    <view class="main">
+      <u-form :model="addForm" :rules="rules" ref="addForm" label-width="0">
+        <u-form-item prop="nboType" borderBottom customStyle="padding:40rpx 0 30rpx">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            项目级别
+          </view>
+          <u-radio-group v-model="addForm.nboType" placement="row">
+            <u-radio
+              customStyle="margin-right:40rpx"
+              :disabled="['10', '20'].includes(projectDetails.nboType)"
+              label="A"
+              name="10"></u-radio>
+            <u-radio
+              customStyle="margin-right:40rpx"
+              :disabled="projectDetails.nboType === '20'"
+              label="B"
+              name="20"></u-radio>
+            <u-radio customStyle="margin-right:40rpx" label="C" name="30"></u-radio>
+            <u-radio v-if="projectDetails.nboType === '10'" label="储备" name="50"></u-radio>
+          </u-radio-group>
+        </u-form-item>
+        <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            技术支持人员
+          </view>
+          <u-input
+            placeholder="输入技术支持人员"
+            v-model="addForm.technicalSupportName"
+            border="none"
+            suffixIconStyle="color:#CDCDCD"
+            clearable
+            customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+        </u-form-item>
+        <u-form-item prop="technicalSupportContent" borderBottom customStyle="padding:40rpx 0 30rpx">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            技术支持内容
+          </view>
+          <u-input
+            placeholder="输入技术支持内容"
+            v-model="addForm.technicalSupportContent"
+            border="none"
+            suffixIconStyle="color:#CDCDCD"
+            clearable
+            customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+        </u-form-item>
+        <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showSupportDate = true">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            技术支持时间
+          </view>
+          <u-input
+            :readonly="true"
+            placeholder="请选择技术支持时间"
+            v-model="addForm.technicalSupportTime"
+            border="none"
+            suffixIcon="arrow-down"
+            suffixIconStyle="color:#CDCDCD"
+            clearable
+            customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+        </u-form-item>
+        <u-form-item prop="remark" customStyle="padding:40rpx 0 30rpx">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            备注原因
+          </view>
+          <u-textarea
+            fontSize="26rpx"
+            v-model="addForm.remark"
+            placeholder="请输入备注原因"
+            height="180"
+            :count="true"
+            maxlength="300"></u-textarea>
+        </u-form-item>
+      </u-form>
+      <view class="save" @click="handleDowngrade">提交</view>
+    </view>
+    <!-- 技术支持时间 -->
+    <u-datetime-picker
+      v-if="showSupportDate"
+      :show="showSupportDate"
+      mode="datetime"
+      v-model="addForm.technicalSupportTime"
+      @cancel="showSupportDate = false"
+      @confirm="pickSupportDate"></u-datetime-picker>
+    <u-notify ref="uNotify"></u-notify>
+    <u-toast ref="uToast"></u-toast>
+    <u-modal
+      :show="showModal"
+      content="确认进行项目降级?"
+      :showCancelButton="true"
+      @cancel="this.showModal = false"
+      @confirm="this.handleDownApi()"></u-modal>
+  </view>
+</template>
+<script>
+  import projectApi from '../../api/project'
+  import to from 'await-to-js'
+  export default {
+    name: 'omsIndex',
+    data() {
+      return {
+        height: '',
+        paddingTop: '',
+        showSupportDate: false, //技术支持时间
+        addForm: {
+          nboType: '', //项目及别
+          technicalSupportName: '', //技术支持人员
+          technicalSupportContent: null, //技术支持内容
+          technicalSupportTime: '', //技术支持时间
+          remark: '', //备注
+          id: 0, //项目id
+        },
+        showModal: false,
+        projectDetails: {},
+        rules: {
+          nboType: {
+            type: 'string',
+            required: true,
+            message: '请选择项目级别',
+            trigger: ['blur'],
+          },
+          technicalSupportContent: {
+            type: 'string',
+            required: true,
+            message: '请输入技术支持内容',
+            trigger: ['blur'],
+          },
+          remark: {
+            type: 'string',
+            required: true,
+            message: '请输入备注内容',
+            trigger: ['blur'],
+          },
+        },
+      }
+    },
+    created() {
+      const navData = uni.getMenuButtonBoundingClientRect()
+      this.height = navData.height + 'px'
+      this.paddingTop = navData.top + 'px'
+    },
+    onLoad(option) {
+      console.log(option.id) //打印出上个页面传递的参数。
+      this.addForm.id = parseInt(option.id)
+    },
+    onShow() {
+      this.getDetails()
+    },
+    methods: {
+      async getDetails() {
+        const [err, res] = await to(projectApi.getDetail({ id: this.addForm.id }))
+        if (err) return
+        if (res.code == 200) {
+          this.projectDetails = res.data
+          this.addForm = Object.assign(this.addForm, this.projectDetails)
+          this.addForm.nboType = ''
+          this.addForm.technicalSupportName = ''
+          this.addForm.technicalSupportContent = ''
+          this.addForm.technicalSupportTime = this.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}')
+          this.addForm.remark = ''
+        }
+      },
+      // 时间
+      async pickSupportDate(e) {
+        this.showSupportDate = false
+        const timeFormat = uni.$u.timeFormat
+        let timeValue = await timeFormat(e.value, 'yyyy-mm-dd hh:MM')
+        this.addForm.technicalSupportTime = timeValue
+        console.log(timeValue)
+      },
+      handleDowngrade() {
+        this.$refs.addForm
+          .validate()
+          .then(async () => {
+            this.showModal = true
+          })
+          .catch((err) => {
+            console.log(err)
+            this.$refs.uNotify.show({
+              top: this.height + this.paddingTop + 10,
+              type: 'warning',
+              message: err[0].message,
+              duration: 1000 * 3,
+            })
+          })
+      },
+      async handleDownApi() {
+        let params = this.addForm
+        const [err, res] = await to(projectApi.downgrade(params))
+        this.showModal = false
+        if (err) return
+        if (res && res.code == 200) {
+          this.$refs.uToast.show({
+            type: 'success',
+            message: '提交成功',
+            complete: () => {
+              this.goBack()
+            },
+          })
+        }
+      },
+      closeUser(user) {
+        if (user) {
+          console.log(user)
+          this.addForm.userId = user.id
+          this.addForm.userName = user.label
+        }
+      },
+      goBack() {
+        uni.navigateBack({
+          //关闭当前页面,返回上一页面或多级页面。
+          delta: 1,
+        })
+      },
+    },
+  }
+</script>
+<style>
+  page {
+    background: #f2f3f5;
+  }
+</style>
+<style lang="scss" scoped>
+  .home {
+    padding-top: 188rpx;
+
+    .nav {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 284rpx;
+      background: #3e7ef8;
+      .title {
+        position: relative;
+        text-align: center;
+        font-size: 32rpx;
+        font-weight: bold;
+        color: #ffffff;
+        .back {
+          position: absolute;
+          top: 0;
+          bottom: 0;
+          margin: auto;
+          left: 70rpx;
+          display: flex;
+        }
+      }
+    }
+
+    .main {
+      position: absolute;
+      width: 100%;
+      height: calc(100vh - 188rpx);
+      background: #ffffff;
+      box-shadow: 0 6rpx 19rpx 2rpx rgba(0, 45, 132, 0.15);
+      border-radius: 31rpx 31rpx 0 0;
+      padding: 0 32rpx;
+      overflow: auto;
+      padding-bottom: 64rpx;
+      .form-label {
+        font-size: 32rpx;
+        font-weight: bold;
+        color: #323232;
+        padding-bottom: 18rpx;
+        .label-tag {
+          width: 15rpx;
+          height: 15rpx;
+          background: rgba(62, 126, 248, 0.6);
+          border-radius: 50%;
+          margin-right: -4rpx;
+        }
+      }
+      .save {
+        width: 569rpx;
+        height: 92rpx;
+        background: #3e7ef8;
+        border-radius: 31rpx;
+        margin: 116rpx auto 0;
+        font-size: 32rpx;
+        color: #ffffff;
+        text-align: center;
+        line-height: 92rpx;
+      }
+    }
+  }
+</style>

+ 640 - 0
frontend_mobile/pages/project/upgrade.vue

@@ -0,0 +1,640 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-01-12 11:57:48
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-02-21 17:47:39
+ * @Description: file content
+ * @FilePath: \frontend_mobile\pages\project\upgrade.vue
+-->
+<template>
+  <view class="home">
+    <view class="nav">
+      <view :style="{ paddingTop }">
+        <view class="title" :style="[{ height }, { lineHeight: height }]">
+          <view class="back" @click="goBack()">
+            <u-icon name="arrow-left" color="#ffffff" size="22"></u-icon>
+          </view>
+          <text>项目升级</text>
+        </view>
+      </view>
+    </view>
+    <view class="main">
+      <u-form :model="addForm" :rules="rules" ref="addForm" label-width="0">
+        <u-form-item prop="nboType" borderBottom customStyle="padding:40rpx 0 30rpx">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            项目级别
+          </view>
+          <u-radio-group v-model="addForm.nboType" placement="row">
+            <u-radio
+              customStyle="margin-right:40rpx"
+              :disabled="projectDetails.nboType === '10'"
+              label="A"
+              name="10"></u-radio>
+            <u-radio
+              customStyle="margin-right:40rpx"
+              :disabled="projectDetails.nboType === '20'"
+              label="B"
+              name="20"></u-radio>
+            <u-radio
+              :disabled="['10', '20', '30'].includes(projectDetails.nboType)"
+              customStyle="margin-right:40rpx"
+              label="C"
+              name="30"></u-radio>
+            <!-- <u-radio v-if="projectDetails.nboType === '10'" label="储备" name="50"></u-radio> -->
+          </u-radio-group>
+        </u-form-item>
+        <view v-if="addForm.nboType !== '30'">
+          <u-form-item prop="nboBudget" borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              项目预算
+            </view>
+            <u-input
+              placeholder="输入项目预算"
+              v-model="addForm.nboBudget"
+              border="none"
+              type="number"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item
+            prop="distributorName"
+            borderBottom
+            customStyle="padding:40rpx 0 30rpx"
+            @click="$refs.dealer.open()">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              经销商/代理商
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择经销商/代理商"
+              v-model="addForm.distributorName"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item prop="parentReceiver" borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              总部对接人
+            </view>
+            <u-input
+              placeholder="输入总部对接人"
+              v-model="addForm.parentReceiver"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+        </view>
+        <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            技术支持人员
+          </view>
+          <u-input
+            placeholder="输入技术支持人员"
+            v-model="addForm.technicalSupportName"
+            border="none"
+            suffixIconStyle="color:#CDCDCD"
+            clearable
+            customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+        </u-form-item>
+        <u-form-item prop="technicalSupportContent" borderBottom customStyle="padding:40rpx 0 30rpx">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            技术支持内容
+          </view>
+          <u-input
+            placeholder="输入技术支持内容"
+            v-model="addForm.technicalSupportContent"
+            border="none"
+            suffixIconStyle="color:#CDCDCD"
+            clearable
+            customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+        </u-form-item>
+        <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showSupportDate = true">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            技术支持时间
+          </view>
+          <u-input
+            :readonly="true"
+            placeholder="请选择技术支持时间"
+            v-model="addForm.technicalSupportTime"
+            border="none"
+            suffixIcon="arrow-down"
+            suffixIconStyle="color:#CDCDCD"
+            clearable
+            customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+        </u-form-item>
+        <view v-if="addForm.nboType !== '30'">
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showBudgetDate = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              项目预算期限
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择项目预算期限"
+              v-model="addForm.nboBudgetTime"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              资金来源
+            </view>
+            <u-input
+              placeholder="输入资金来源"
+              v-model="addForm.capitalSource"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              产品/方案满足情况
+            </view>
+            <u-input
+              placeholder="输入产品/方案满足情况"
+              v-model="addForm.productSatisfaction"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+        </view>
+        <view v-if="addForm.nboType === '10'">
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showChasingWay = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              采购方式
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择采购方式"
+              v-model="addForm.purchasingWayVal"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="showPurchasingDate = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              采购时间
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择采购时间"
+              v-model="addForm.technicalSupportTime"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx" @click="selectContact()">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              决策人员
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="输入决策人员"
+              v-model="addForm.makerName"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              决策部门
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="输入决策部门"
+              v-model="addForm.makerDept"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              经销商与客户历史成交信息
+            </view>
+            <u-input
+              placeholder="输入经销商与客户历史成交信息"
+              v-model="addForm.historicalTransactionInfo"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              经销商销售人员
+            </view>
+            <u-input
+              placeholder="输入经销商销售人员"
+              v-model="addForm.dealerSalesName"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              维护部门及人员
+            </view>
+            <u-input
+              placeholder="输入维护部门及人员"
+              v-model="addForm.accendant"
+              border="none"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              是否采纳大数技术参数
+            </view>
+            <u-radio-group v-model="addForm.isAdoptDashoo" placement="row">
+              <u-radio customStyle="margin-right:40rpx" label="是" name="10"></u-radio>
+              <u-radio customStyle="margin-right:40rpx" label="否" name="20"></u-radio>
+            </u-radio-group>
+          </u-form-item>
+        </view>
+        <u-form-item prop="remark" customStyle="padding:40rpx 0 30rpx">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            备注原因
+          </view>
+          <u-textarea
+            fontSize="26rpx"
+            v-model="addForm.remark"
+            placeholder="请输入备注原因"
+            height="180"
+            :count="true"
+            maxlength="300"></u-textarea>
+        </u-form-item>
+      </u-form>
+      <view class="save" @click="handleDowngrade">提交</view>
+    </view>
+    <!-- 技术支持时间 -->
+    <u-datetime-picker
+      v-if="showSupportDate"
+      :show="showSupportDate"
+      mode="datetime"
+      v-model="addForm.technicalSupportTime"
+      @cancel="showSupportDate = false"
+      @confirm="pickSupportDate"></u-datetime-picker>
+    <!-- 项目预算期限 -->
+    <u-datetime-picker
+      v-if="showBudgetDate"
+      :show="showBudgetDate"
+      mode="datetime"
+      v-model="addForm.nboBudgetTime"
+      @cancel="showBudgetDate = false"
+      @confirm="pickBudgetDate"></u-datetime-picker>
+    <!-- 采购时间 -->
+    <u-datetime-picker
+      v-if="showPurchasingDate"
+      :show="showPurchasingDate"
+      mode="datetime"
+      v-model="addForm.purchasingTime"
+      @cancel="showPurchasingDate = false"
+      @confirm="pickPurchasingDate"></u-datetime-picker>
+    <!-- 采购方式 -->
+    <u-picker
+      :show="showChasingWay"
+      :columns="[purchasingWayOptions]"
+      keyName="value"
+      @cancel="showChasingWay = false"
+      @confirm="pickModel"></u-picker>
+    <!-- 选择经销商 -->
+    <select-dealer ref="dealer" @close="closeDealer()"></select-dealer>
+    <!-- 客户联系人 -->
+    <customer-contact ref="contact" @close="closeContact()"></customer-contact>
+    <u-notify ref="uNotify"></u-notify>
+    <u-toast ref="uToast"></u-toast>
+    <u-modal
+      :show="showModal"
+      content="确认进行项目升级?"
+      :showCancelButton="true"
+      @cancel="this.showModal = false"
+      @confirm="this.handleDownApi()"></u-modal>
+  </view>
+</template>
+<script>
+  import projectApi from '../../api/project'
+  import to from 'await-to-js'
+  import SelectDealer from 'components/SelectDealer'
+  import CustomerContact from '../../components/CustomerContact'
+  export default {
+    name: 'omsIndex',
+    components: { SelectDealer, CustomerContact },
+    data() {
+      return {
+        height: '',
+        paddingTop: '',
+        showSupportDate: false, //技术支持时间
+        showBudgetDate: false, //项目预算时间
+        showPurchasingDate: false, //采购时间
+        showChasingWay: false,
+        purchasingWayOptions: [],
+        addForm: {
+          nboType: '', //项目及别
+          nboBudget: 0, //项目预算
+          distributorName: '', //经销商
+          distributorId: '', //经销商ID
+          parentReceiver: '', //项目对接人
+          technicalSupportName: '', //技术支持人员
+          technicalSupportContent: null, //技术支持内容
+          technicalSupportTime: '', //技术支持时间
+          nboBudgetTime: this.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}'), //项目预算时间
+          capitalSource: '', //资金来源
+          productSatisfaction: '', //产品方案满足情况
+          purchasingWay: '', //采购方式id
+          purchasingWayVal: '', //采购方式
+          purchasingTime: this.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}'), //采购时间
+          makerId: '', //决策人
+          makerName: '', //决策人
+          makerDept: '', //决策部门
+          historicalTransactionInfo: '', //输入经销商与客户历史成交信息
+          dealerSalesName: '', //经销商销售人员
+          accendant: '', //维护部门及人员
+          isAdoptDashoo: '', //是否是大项目选择
+          remark: '', //备注
+          id: 0, //项目id
+        },
+        showModal: false,
+        projectDetails: {},
+        rules: {
+          nboType: {
+            type: 'string',
+            required: true,
+            message: '请选择项目级别',
+            trigger: ['blur'],
+          },
+          technicalSupportContent: {
+            type: 'string',
+            required: true,
+            message: '请输入技术支持内容',
+            trigger: ['blur'],
+          },
+          nboBudget: {
+            type: 'string',
+            required: true,
+            message: '请输入项目预算',
+            trigger: ['blur'],
+          },
+          distributorName: {
+            type: 'string',
+            required: true,
+            message: '请选择经销商',
+            trigger: ['blur'],
+          },
+          remark: {
+            type: 'string',
+            required: true,
+            message: '请输入备注内容',
+            trigger: ['blur'],
+          },
+        },
+      }
+    },
+    created() {
+      const navData = uni.getMenuButtonBoundingClientRect()
+      this.height = navData.height + 'px'
+      this.paddingTop = navData.top + 'px'
+    },
+    onLoad(option) {
+      console.log(option.id) //打印出上个页面传递的参数。
+      this.addForm.id = parseInt(option.id)
+    },
+    onShow() {
+      this.getDetails()
+      this.getOptions()
+    },
+    methods: {
+      getOptions() {
+        Promise.all([this.getDicts('proj_purchasing_way')])
+          .then(([purchasing]) => {
+            this.purchasingWayOptions = purchasing.data.values || []
+          })
+          .catch((err) => console.log(err))
+      },
+      async getDetails() {
+        const [err, res] = await to(projectApi.getDetail({ id: this.addForm.id }))
+        if (err) return
+        if (res.code == 200) {
+          this.projectDetails = res.data
+          this.addForm = Object.assign(this.addForm, this.projectDetails)
+          this.addForm.nboType = ''
+          this.addForm.technicalSupportName = ''
+          this.addForm.technicalSupportContent = ''
+          this.addForm.technicalSupportTime = this.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}')
+          this.addForm.nboBudgetTime = this.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}')
+          this.addForm.remark = ''
+        }
+      },
+      // 选择采购方式
+      pickModel(e) {
+        this.addForm.purchasingWay = e.value[0].key
+        this.addForm.purchasingWayVal = e.value[0].value
+        this.showChasingWay = false
+      },
+      // 经销商
+      closeDealer(dealer) {
+        if (dealer) {
+          console.log(dealer)
+          this.addForm.distributorId = dealer.id
+          this.addForm.distributorName = dealer.name
+        }
+      },
+      selectContact() {
+        if (!this.addForm.custId) {
+          this.$refs.uNotify.show({
+            top: this.height + this.paddingTop + 10,
+            type: 'warning',
+            message: '请先选择客户',
+            duration: 1000 * 3,
+          })
+          return
+        }
+        this.$refs.contact.open(this.addForm.custId)
+      },
+      // 关闭选择客户联系人
+      closeContact(user) {
+        if (user) {
+          console.log(user)
+          this.addForm.makerId = user.id
+          this.addForm.makerName = user.cuctName
+          this.addForm.makerDept = user.dept
+          // this.addForm.makerPost = user.postion
+          // this.addForm.makerTelephone = user.telephone
+        }
+      },
+      // 技术支持时间
+      async pickSupportDate(e) {
+        this.showSupportDate = false
+        const timeFormat = uni.$u.timeFormat
+        let timeValue = await timeFormat(e.value, 'yyyy-mm-dd hh:MM')
+        this.addForm.technicalSupportTime = timeValue
+        console.log(timeValue)
+      },
+      // 项目预算时间
+      async pickBudgetDate(e) {
+        this.showBudgetDate = false
+        const timeFormat = uni.$u.timeFormat
+        let timeValue = await timeFormat(e.value, 'yyyy-mm-dd hh:MM')
+        this.addForm.nboBudgetTime = timeValue
+        console.log(timeValue)
+      },
+      // 采购时间
+      async pickPurchasingDate(e) {
+        this.showPurchasingDate = false
+        const timeFormat = uni.$u.timeFormat
+        let timeValue = await timeFormat(e.value, 'yyyy-mm-dd hh:MM')
+        this.addForm.purchasingTime = timeValue
+        console.log(timeValue)
+      },
+      handleDowngrade() {
+        this.$refs.addForm
+          .validate()
+          .then(async () => {
+            this.showModal = true
+          })
+          .catch((err) => {
+            console.log(err)
+            this.$refs.uNotify.show({
+              top: this.height + this.paddingTop + 10,
+              type: 'warning',
+              message: err[0].message,
+              duration: 1000 * 3,
+            })
+          })
+      },
+      async handleDownApi() {
+        let params = this.addForm
+        params.nboBudget = Number(params.nboBudget)
+        const [err, res] = await to(projectApi.upgrade(params))
+        this.showModal = false
+        if (err) return
+        if (res && res.code == 200) {
+          this.$refs.uToast.show({
+            type: 'success',
+            message: '提交成功',
+            complete: () => {
+              this.goBack()
+            },
+          })
+        }
+      },
+      closeUser(user) {
+        if (user) {
+          console.log(user)
+          this.addForm.userId = user.id
+          this.addForm.userName = user.label
+        }
+      },
+      goBack() {
+        uni.navigateBack({
+          //关闭当前页面,返回上一页面或多级页面。
+          delta: 1,
+        })
+      },
+    },
+  }
+</script>
+<style>
+  page {
+    background: #f2f3f5;
+  }
+</style>
+<style lang="scss" scoped>
+  .home {
+    padding-top: 188rpx;
+
+    .nav {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 284rpx;
+      background: #3e7ef8;
+      .title {
+        position: relative;
+        text-align: center;
+        font-size: 32rpx;
+        font-weight: bold;
+        color: #ffffff;
+        .back {
+          position: absolute;
+          top: 0;
+          bottom: 0;
+          margin: auto;
+          left: 70rpx;
+          display: flex;
+        }
+      }
+    }
+
+    .main {
+      position: absolute;
+      width: 100%;
+      height: calc(100vh - 188rpx);
+      background: #ffffff;
+      box-shadow: 0 6rpx 19rpx 2rpx rgba(0, 45, 132, 0.15);
+      border-radius: 31rpx 31rpx 0 0;
+      padding: 0 32rpx;
+      overflow: auto;
+      padding-bottom: 64rpx;
+      .form-label {
+        font-size: 32rpx;
+        font-weight: bold;
+        color: #323232;
+        padding-bottom: 18rpx;
+        .label-tag {
+          width: 15rpx;
+          height: 15rpx;
+          background: rgba(62, 126, 248, 0.6);
+          border-radius: 50%;
+          margin-right: -4rpx;
+        }
+      }
+      .save {
+        width: 569rpx;
+        height: 92rpx;
+        background: #3e7ef8;
+        border-radius: 31rpx;
+        margin: 116rpx auto 0;
+        font-size: 32rpx;
+        color: #ffffff;
+        text-align: center;
+        line-height: 92rpx;
+      }
+    }
+  }
+</style>