Просмотр исходного кода

feature:登录增加记住密码、解决客户模块类型字段显示错误的问题、增加新建经销商、增加客户新增联系人功能、打卡增加表单

liuzl 2 лет назад
Родитель
Сommit
227e8e6988

+ 3 - 3
App.vue

@@ -20,14 +20,14 @@
       updateManager.onCheckForUpdate(function (res) {
         // 请求完新版本信息的回调
         if (res.hasUpdate) {
-          updateManager.onUpdateReady(function (res2) {
+          updateManager.onUpdateReady(function () {
             uni.showModal({
               title: '更新提示',
               content: '发现新版本,是否重启应用?',
               cancelColor: '#eeeeee',
               confirmColor: '#FF0000',
-              success(res2) {
-                if (res2.confirm) {
+              success(resp) {
+                if (resp.confirm) {
                   // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
                   updateManager.applyUpdate()
                 }

+ 5 - 1
api/base/distr.js

@@ -2,10 +2,14 @@ import micro_request from '@/utils/micro_request'
 
 const basePath = process.uniEnv.VUE_APP_ParentPath
 export default {
-  // 获取省列表
+  // 获取省市县区列表
   getProvinceInfo(query) {
     return micro_request.postRequest(basePath, 'District', 'GetList', query)
   },
+  // 获取省数据
+  getProvinceList(query) {
+    return micro_request.postRequest(basePath, 'District', 'GetProvinceList', query)
+  },
   // 获取经销商列表
   getList(query) {
     return micro_request.postRequest(basePath, 'Distributor', 'GetList', query)

+ 4 - 0
api/customer/index.js

@@ -43,4 +43,8 @@ export default {
   getAbstract(query) {
     return micro_request.postRequest(basePath, 'Customer', 'GetCustAbstract', query)
   },
+  // 新建联系人
+  createContact(query) {
+    return micro_request.postRequest(basePath, 'Contact', 'Create', query)
+  },
 }

+ 2 - 1
components/SelectUser.vue

@@ -2,7 +2,7 @@
  * @Author: liuzhenlin 461480418@qq.ocm
  * @Date: 2023-02-15 10:34:49
  * @LastEditors: liuzhenlin
- * @LastEditTime: 2023-02-23 11:20:56
+ * @LastEditTime: 2023-03-22 11:51:17
  * @Description: file content
  * @FilePath: \oms\components\SelectUser.vue
 -->
@@ -87,6 +87,7 @@
       },
       close() {
         this.selectVisible = false
+        console.log(this.selected)
         this.$emit('close', this.selected)
       },
       radioChange(n) {

+ 14 - 0
pages.json

@@ -191,6 +191,20 @@
         "navigationStyle": "custom"
       },
       "tit": "日程"
+    },
+    {
+      "path": "pages/publicPages/concatCreate",
+      "style": {
+        "navigationStyle": "custom"
+      },
+      "tit": "新建联系人"
+    },
+    {
+      "path": "pages/distributor/create",
+      "style": {
+        "navigationStyle": "custom"
+      },
+      "tit": "新建经销商"
     }
   ],
   "tabBar": {

+ 1 - 0
pages/contract/detail.vue

@@ -165,6 +165,7 @@
       this.paddingTop = navData.top + 'px'
     },
     onShow() {
+      this.openBtnWidth = false
       this.getCustomerDetail()
     },
     methods: {

+ 13 - 4
pages/customer/components/contacts.vue

@@ -33,13 +33,17 @@
             <view class="val">{{ v.cuctName }}</view>
           </view>
           <view class="flex_l">
-            <view class="label">岗位:</view>
+            <view class="label">职务:</view>
             <view class="val">{{ v.postion }}</view>
           </view>
           <view class="flex_l">
             <view class="label">电话:</view>
             <view class="val">{{ v.telephone }}</view>
           </view>
+          <view class="flex_l">
+            <view class="label">是否是决策人:</view>
+            <view class="val">{{ v.isDecision == '10' ? '是' : '否' }}</view>
+          </view>
           <view class="flex_l">
             <view class="label">微信:</view>
             <view class="val">{{ v.wechat }}</view>
@@ -71,12 +75,17 @@
         contactList: [],
       }
     },
-
-    mounted() {
+    onHide(options) {
+      console.log(323232)
+    },
+    onShow() {
+      console.log(111111)
       this.getContacts()
       // console.log('customerId', this.customerId)
     },
-
+    mounted() {
+      this.getContacts()
+    },
     methods: {
       async getContacts() {
         let params = {

+ 10 - 1
pages/customer/details.vue

@@ -88,8 +88,9 @@
       </view>
     </view>
     <!-- 新增按钮 -->
-    <view class="fixed-btn-group" v-if="!isPublic" :style="{ width: openBtnWidth ? '400rpx' : '90rpx' }">
+    <view class="fixed-btn-group" v-if="!isPublic" :style="{ width: openBtnWidth ? '480rpx' : '90rpx' }">
       <view class="flex1" v-if="openBtnWidth">
+        <view class="btn center" @click="linkToConcat()">联</view>
         <view class="btn center" @click="linkToProject()">项</view>
         <view class="btn center" @click="linkToTransfer()">转</view>
         <view class="btn center" @click="$refs.moveCust.open(customerId)">公</view>
@@ -160,6 +161,8 @@
       this.paddingTop = navData.top + 'px'
     },
     onShow() {
+      this.curTabIndex = 0
+      this.openBtnWidth = false
       this.getCustomerDetail()
       this.getAbstractDetail()
     },
@@ -207,6 +210,12 @@
           url: '/pages/project/create?id=' + this.customerId,
         })
       },
+      linkToConcat() {
+        uni.navigateTo({
+          //保留当前页面,跳转到应用内的某个页面
+          url: '/pages/publicPages/concatCreate?id=' + this.customerId + '&name=' + this.customerData.custName,
+        })
+      },
       goBack() {
         uni.navigateBack({
           //关闭当前页面,返回上一页面或多级页面。

+ 8 - 5
pages/customer/index.vue

@@ -86,11 +86,14 @@
                 </view>
                 <view class="info-row flex_l">
                   <text class="info-label">客户类别:</text>
-                  <u-text color="#323232" size="24rpx" :text="v.custIndustry"></u-text>
+                  <u-text
+                    color="#323232"
+                    size="24rpx"
+                    :text="selectDictLabel(industryOptions, v.custIndustry)"></u-text>
                 </view>
                 <view class="info-row flex_l">
                   <text class="info-label">最后跟进时间:</text>
-                  <u-text color="#323232" size="24rpx" :text="parseTime(v.followUpDate,'{y}-{m}-{d}') || '-'"></u-text>
+                  <u-text color="#323232" size="24rpx" :text="parseTime(v.followUpDate, '{y}-{m}-{d}') || '-'"></u-text>
                 </view>
                 <view class="flex_l">
                   <view class="transfer-btn mr20" @click.stop="linkToTransfer(v.id)">
@@ -146,7 +149,7 @@
         filterVisible: false, //筛选组件状态
         custName: '', //客户名称
         followUpDate: '', //最后跟进时间
-        industryChecked: 0, //选择的行业id
+        industryChecked: null, //选择的行业id
         industryOptions: [],
         // levelChecked: 0, //选择的级别id
         // levelOptions: [],
@@ -183,7 +186,7 @@
       // 重置
       reset() {
         this.followUpDate = ''
-        this.industryChecked = 0
+        this.industryChecked = null
         // this.levelChecked = 0
       },
       // 确认
@@ -211,7 +214,7 @@
         let params = {
           custName: this.custName,
           followUpDate: this.followUpDate,
-          indusTry: this.industryChecked,
+          custIndustry: this.industryChecked,
           isPublic: false,
           pageNum: this.pageNum,
           pageSize: this.pageSize,

+ 3 - 3
pages/customer/transfer.vue

@@ -2,7 +2,7 @@
  * @Author: liuzhenlin 461480418@qq.ocm
  * @Date: 2023-01-12 11:57:48
  * @LastEditors: liuzhenlin
- * @LastEditTime: 2023-02-15 15:28:15
+ * @LastEditTime: 2023-03-21 17:54:54
  * @Description: file content
  * @FilePath: \oms\pages\customer\transfer.vue
 -->
@@ -60,7 +60,7 @@
     </view>
     <u-notify ref="uNotify"></u-notify>
     <u-toast ref="uToast"></u-toast>
-    <select-user ref="user" :query-params="{ roles: ['Sales', 'SalesManager'] }" @close="closeUser()"></select-user>
+    <select-user ref="user" :query-params="{ roles: ['SalesEngineer'] }" @close="closeUser($event)"></select-user>
   </view>
 </template>
 <script>
@@ -204,7 +204,7 @@
         .label-tag {
           width: 15rpx;
           height: 15rpx;
-          background:  #ff4d4f;
+          background: #ff4d4f;
           border-radius: 50%;
           margin-right: 10rpx;
         }

+ 324 - 0
pages/distributor/create.vue

@@ -0,0 +1,324 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-01-12 11:57:48
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-03-22 11:26:04
+ * @Description: file content
+ * @FilePath: \oms\pages\distributor\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">
+      <u-form :model="addForm" :rules="rules" ref="addForm" label-width="0">
+        <u-form-item prop="distName" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            名称
+          </view>
+          <u-input border="none" v-model="addForm.distName" placeholder="请输入名称"></u-input>
+        </u-form-item>
+        <u-form-item prop="abbrName" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">助记名</view>
+          <u-input border="none" v-model="addForm.abbrName" placeholder="请输入助记名"></u-input>
+        </u-form-item>
+        <u-form-item prop="distDesc" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">说明</view>
+          <u-input border="none" maxlength="11" v-model="addForm.distDesc" placeholder="请输入说明"></u-input>
+        </u-form-item>
+        <u-form-item prop="distBoss" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            负责人
+          </view>
+          <u-input border="none" v-model="addForm.distBoss" placeholder="请输入负责人"></u-input>
+        </u-form-item>
+        <u-form-item prop="distBossPhone" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            电话
+          </view>
+          <u-input maxlength="11" border="none" v-model="addForm.distBossPhone" placeholder="请输入电话"></u-input>
+        </u-form-item>
+        <u-form-item prop="businessScope" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            业务范围
+          </view>
+          <u-input border="none" v-model="addForm.businessScope" placeholder="请输入业务范围"></u-input>
+        </u-form-item>
+        <u-form-item prop="provinceDesc" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showProvince = true">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            选择省份
+          </view>
+          <u-input
+            :readonly="true"
+            placeholder="请选择省份"
+            v-model="addForm.provinceDesc"
+            border="none"
+            suffixIcon="arrow-down"
+            suffixIconStyle="color:#CDCDCD"
+            clearable
+            customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+        </u-form-item>
+        <u-form-item prop="belongSale" borderBottom customStyle="padding:40rpx 0 30rpx" @click="openUser()">
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            销售工程师
+          </view>
+          <u-input
+            :readonly="true"
+            placeholder="请选择销售工程师"
+            v-model="addForm.belongSale"
+            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 34rpx" borderBottom>
+          <view class="form-label flex_l">备注</view>
+          <u-textarea
+            v-model="addForm.remark"
+            placeholder="请输入备注"
+            maxlength="800"
+            height="190rpx"
+            count
+            customStyle="border-radius:16rpx"></u-textarea>
+        </u-form-item>
+      </u-form>
+      <view class="center">
+        <view class="handle-btn" @click="handleAdd">保存</view>
+      </view>
+    </view>
+    <!-- 选择省 -->
+    <u-picker
+      :show="showProvince"
+      :columns="provinceColumns"
+      keyName="distName"
+      @cancel="showProvince = false"
+      @confirm="pickProvince"></u-picker>
+    <!-- 选择销售 -->
+    <select-user ref="user" :query-params="{ roles: ['SalesEngineer'] }" @close="closeUser($event)"></select-user>
+    <u-notify ref="uNotify"></u-notify>
+    <u-toast ref="uToast"></u-toast>
+  </view>
+</template>
+<script>
+  import to from 'await-to-js'
+  import distrApi from '../../api/base/distr'
+  import SelectUser from 'components/SelectUser'
+  export default {
+    name: 'omsIndex',
+    components: { SelectUser },
+    data() {
+      return {
+        height: '',
+        paddingTop: '',
+        showProvince: false,
+        provinceColumns: [],
+        addForm: {
+          distName: '',
+          abbrName: '',
+          distDesc: '',
+          distBoss: '',
+          distBossPhone: '',
+          businessScope: '',
+          provinceId: null,
+          provinceDesc: '',
+          belongSale: '',
+          belongSaleId: 0,
+          remark: '',
+        },
+        rules: {
+          distName: [{ required: true, trigger: 'blur', message: '请输入名称' }],
+          distBoss: [{ required: true, trigger: 'blur', message: '请输入负责人' }],
+          distBossPhone: [
+            {
+              pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+              message: '请输入正确的手机号码',
+              trigger: 'blur',
+              required: true,
+            },
+          ],
+          businessScope: [{ required: true, trigger: 'blur', message: '请填写业务范围' }],
+          provinceDesc: [{ required: true, trigger: 'blur', message: '请选择省份' }],
+          belongSale: [{ required: true, trigger: 'blur', message: '请填写归属销售' }],
+        },
+      }
+    },
+    onLoad(option) {
+      console.log(option)
+      this.addForm.custId = Number(option.id)
+      this.addForm.custName = option.name
+    },
+    created() {
+      const navData = uni.getMenuButtonBoundingClientRect()
+      this.height = navData.height + 'px'
+      this.paddingTop = navData.top + 'px'
+    },
+    mounted() {
+      this.getOptions()
+    },
+    methods: {
+      getOptions() {
+        Promise.all([distrApi.getProvinceList()])
+          .then(([province]) => {
+            this.provinceColumns = [province.data.list]
+          })
+          .catch((err) => console.log(err))
+      },
+      openUser() {
+        this.$refs.user.open()
+      },
+      // 关闭选择销售
+      closeUser(user) {
+        console.log(user)
+        if (user) {
+          this.addForm.belongSaleId = user.id
+          this.addForm.belongSale = user.label
+        }
+      },
+      // 省份选择
+      pickProvince(e) {
+        console.log(e)
+        this.addForm.provinceId = e.value[0].id
+        this.addForm.provinceDesc = e.value[0].distName
+        this.showProvince = false
+      },
+      handleAdd() {
+        this.$refs.addForm
+          .validate()
+          .then(async () => {
+            let params = this.addForm
+            console.log(params)
+            const [err, res] = await to(distrApi.doAdd(params))
+            if (err) return
+            if (res && res.code == 200) {
+              this.$refs.uToast.show({
+                type: 'success',
+                message: '创建成功',
+                complete: () => {
+                  uni.navigateBack({
+                    //关闭当前页面,返回上一页面或多级页面。
+                    delta: 1,
+                  })
+                },
+              })
+            }
+          })
+          .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: #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: #ff4d4f;
+          border-radius: 50%;
+          margin-right: 10rpx;
+        }
+      }
+
+      .upload-file-box {
+        padding: 20rpx 0;
+        position: relative;
+
+        .upload-btn {
+          position: absolute;
+          right: 0;
+          top: 26rpx;
+        }
+      }
+    }
+
+    .handle-btn {
+      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>

+ 1 - 0
pages/distributor/details.vue

@@ -125,6 +125,7 @@
       this.paddingTop = navData.top + 'px'
     },
     onShow() {
+      this.openBtnWidth = false
       this.getDistrDetail()
     },
     methods: {

+ 10 - 0
pages/distributor/index.vue

@@ -64,6 +64,10 @@
         </view>
       </scroll-view>
     </view>
+    <!-- 新增按钮 -->
+    <view class="fixed-btn center" @click="openAdd()">
+      <u-icon name="plus" color="#fff" size="20"></u-icon>
+    </view>
     <!-- 消息提示 -->
     <u-toast ref="uToast"></u-toast>
   </view>
@@ -96,6 +100,12 @@
       this.searchList()
     },
     methods: {
+      openAdd() {
+        uni.navigateTo({
+          //保留当前页面,跳转到应用内的某个页面
+          url: '/pages/distributor/create',
+        })
+      },
       getOptions() {
         Promise.all([this.getDicts('cust_idy')])
           .then(([industry]) => {

+ 148 - 31
pages/home/checkIn.vue

@@ -24,19 +24,56 @@
           <u-text :lines="1" size="24rpx" text="打卡记录"></u-text>
         </view>
       </view>
+      <view class="main-form" v-if="!showList">
+        <u-form :model="form" :rules="rules" ref="form" label-width="0">
+          <u-form-item prop="punchVal" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showCheckType = true">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              打卡类型
+            </view>
+            <u-input
+              :readonly="true"
+              placeholder="请选择销售模式"
+              v-model="form.punchVal"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+          <u-form-item
+            prop="targetName"
+            borderBottom
+            customStyle="padding:40rpx 0 30rpx"
+            v-if="form.punchType > 10"
+            @click="openSelectUser()">
+            <view class="form-label flex_l">
+              <view class="label-tag"></view>
+              {{ form.punchType == 20 ? '客户' : '经销商' }}
+            </view>
+            <u-input
+              :readonly="true"
+              :placeholder="`请选择${form.punchType == 20 ? '客户' : '经销商'}`"
+              v-model="form.targetName"
+              border="none"
+              suffixIcon="arrow-down"
+              suffixIconStyle="color:#CDCDCD"
+              clearable
+              customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          </u-form-item>
+        </u-form>
+      </view>
       <view class="main-container">
         <template v-if="!showList">
           <view class="btn" @click="checkIn">打卡</view>
           <view class="location">
-            <u-text @click="getLocation" :lines="1" :block="true" align="center" size="32rpx" :text="address">
-            </u-text>
+            <u-text @click="getLocation" :lines="1" :block="true" align="center" size="32rpx" :text="address"></u-text>
             <u-loading-icon mode="circle" size="24rpx" :show="show"></u-loading-icon>
           </view>
         </template>
-        <u-list @scrolltolower="scrolltolower" v-else>
+        <u-list @scrolltolower="scrolltolower" lowerThreshold="200" v-else>
           <u-list-item v-for="(item, index) in checkList" :key="index">
-            <u-cell :title="item.punchTime" :label="item.punchLocation">
-            </u-cell>
+            <u-cell :title="item.punchTime" :label="item.punchLocation"></u-cell>
           </u-list-item>
         </u-list>
       </view>
@@ -48,26 +85,44 @@
         <u-icon name="plus-circle-fill" color="blue" size="28"></u-icon>
       </view>
     </uni-file-picker> -->
+    <!-- 打卡类型 -->
+    <u-picker
+      :show="showCheckType"
+      :columns="[checkTypeColumns]"
+      keyName="value"
+      @cancel="showCheckType = false"
+      @confirm="pickCheckType"></u-picker>
+    <!-- 选择经销商 -->
+    <select-dealer ref="dealer" @close="closeDealer($event)"></select-dealer>
+    <!-- 选择客户 -->
+    <select-customer ref="cust" @close="closeCust($event)"></select-customer>
+    <u-notify ref="uNotify"></u-notify>
   </view>
 </template>
 
 <script>
-  import {
-    mapGetters
-  } from 'vuex'
+  import { mapGetters } from 'vuex'
   import to from 'await-to-js'
   import api from '@/api/system'
+  import SelectDealer from 'components/SelectDealer'
+  import SelectCustomer from 'components/SelectCustomer'
   export default {
+    components: { SelectDealer, SelectCustomer },
     data() {
       return {
         height: '',
         paddingTop: '',
         address: '获取定位',
+        showCheckType: false,
         form: {
+          targetId: undefined, //经销商/代理商ID
+          targetName: undefined, //经销商/代理商名称
+          punchType: '', //打卡类型
+          punchVal: '',
           punchLat: 0,
           punchLng: 0,
           punchLocation: '',
-          punchImg: ''
+          punchImg: '',
         },
         show: false,
         imageValue: [],
@@ -75,8 +130,24 @@
         checkList: [],
         queryForm: {
           pageNum: 1,
-          pageSize: 10
-        }
+          pageSize: 10,
+        },
+        checkTypeColumns: [
+          { key: '10', value: '居家' },
+          { key: '20', value: '客户' },
+          { key: '30', value: '经销商' },
+          // { key: 40, value: '代理商' },
+        ],
+        rules: {
+          punchVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择打卡类型' }],
+          targetName: [
+            {
+              required: true,
+              trigger: ['blur', 'change'],
+              message: `请选择用户`,
+            },
+          ],
+        },
       }
     },
     computed: {
@@ -88,29 +159,65 @@
       this.height = navData.height + 'px'
       this.paddingTop = navData.top + 'px'
     },
+    watch: {
+      'form.punchType'(val) {
+        this.form.targetId = undefined
+        this.form.targetName = undefined
+      },
+    },
     methods: {
+      // 选择打卡类型
+      pickCheckType(e) {
+        this.form.punchType = e.value[0].key
+        this.form.punchVal = e.value[0].value
+        this.showCheckType = false
+      },
+      // 经销商
+      closeDealer(dealer) {
+        if (dealer) {
+          this.form.targetId = dealer.id
+          this.form.targetName = dealer.name
+        }
+      },
+      // 关闭选择客户
+      closeCust(user) {
+        if (user) {
+          this.form.targetId = user.id
+          this.form.targetName = user.name
+        }
+      },
+      openSelectUser() {
+        if (this.form.punchType == 30) {
+          this.$refs.dealer.open()
+        } else {
+          this.$refs.cust.open()
+        }
+      },
       getLocation() {
         this.show = true
         const _this = this
         uni.getLocation({
           type: 'wgs84',
-          success: function(res) {
-            const latitude = res.latitude.toString();
-            const longitude = res.longitude.toString();
+          success: function (res) {
+            const latitude = res.latitude.toString()
+            const longitude = res.longitude.toString()
             uni.request({
               header: {
-                "Content-Type": "application/text"
+                'Content-Type': 'application/text',
               },
-              url: process.uniEnv.VUE_APP_PROTOCOL + 'apis.map.qq.com/ws/geocoder/v1/?location=' + latitude + ',' + longitude +
+              url:
+                process.uniEnv.VUE_APP_PROTOCOL +
+                'apis.map.qq.com/ws/geocoder/v1/?location=' +
+                latitude +
+                ',' +
+                longitude +
                 '&key=6REBZ-BRN6J-BMAFY-FIRI3-SMK43-G3FXU',
               success(re) {
                 if (re.statusCode === 200) {
-                  _this.address = re.data.result.address;
-                  _this.form = {
-                    punchLat: latitude,
-                    punchLng: longitude,
-                    punchLocation: re.data.result.address
-                  }
+                  _this.address = re.data.result.address
+                  _this.form.punchLat = latitude
+                  _this.form.punchLng = longitude
+                  _this.form.punchLocation = re.data.result.address
                   _this.show = false
                 } else {
                   _this.address = '点击重试'
@@ -120,13 +227,24 @@
                   })
                 }
               },
-              fail: err => _this.show = false
-            });
+              fail: (err) => (_this.show = false),
+            })
           },
-          fail: err => _this.show = false
-        });
+          fail: (err) => (_this.show = false),
+        })
       },
       async checkIn() {
+        const [fail, resp] = await to(this.$refs.form.validate())
+        console.log(fail)
+        if (fail && fail.length > 0) {
+          this.$refs.uNotify.show({
+            top: this.height + this.paddingTop + 10,
+            type: 'warning',
+            message: fail[0].message,
+            duration: 1000 * 3,
+          })
+          return
+        }
         if (!this.form.punchLat || !this.form.punchLng) {
           this.address = '点击重试'
           return this.$refs.uToast.show({
@@ -139,12 +257,12 @@
         const [err, res] = await uni.chooseImage({
           count: 1, //默认9
           sizeType: ['original'], //可以指定是原图还是压缩图,默认二者都有
-          sourceType:['camera']
+          sourceType: ['camera'],
         })
         // console.log(res, 'rs');
         if (err) return
         this.select(res)
-        res.tempFiles[0].name = (new Date()).getTime() + ''
+        res.tempFiles[0].name = new Date().getTime() + ''
         res.tempFiles[0].type = ''
         // console.log(res.tempFiles[0], typeof res.tempFiles[0])
       },
@@ -170,7 +288,7 @@
           },
           success: (res) => {
             this.form.punchImg = action
-            api.checkIn(this.form).then(res => {
+            api.checkIn(this.form).then((res) => {
               this.$refs.uToast.show({
                 type: 'success',
                 message: '打卡成功',
@@ -201,7 +319,6 @@
         } else {
           this.loadStatus = 'nomore'
         }
-
       },
       scrolltolower() {
         if (this.list.length < this.total && this.loadStatus != 'loading') {
@@ -216,7 +333,7 @@
           delta: 1,
         })
       },
-    }
+    },
   }
 </script>
 <style lang="scss" scoped>

+ 1 - 1
pages/home/index.vue

@@ -444,7 +444,7 @@
                 },
                 {
                   type: 'value',
-                  name: res.data.id == 20000 ? '签约完成率(%)' : '回款率(%)',
+                  name: res.data.id == 20000 || 20002 ? '签约完成率(%)' : '回款率(%)',
                   min: 0,
                   max: 100,
                   alignTicks: true,

+ 18 - 2
pages/login/index.vue

@@ -2,9 +2,9 @@
  * @Author: liuzhenlin 461480418@qq.ocm
  * @Date: 2023-01-12 11:57:48
  * @LastEditors: liuzhenlin
- * @LastEditTime: 2023-01-20 10:12:06
+ * @LastEditTime: 2023-03-21 15:37:55
  * @Description: file content
- * @FilePath: \crm\pages\login\index.vue
+ * @FilePath: \oms\pages\login\index.vue
 -->
 <template>
   <view class="login">
@@ -33,6 +33,11 @@
             clearable></u-input>
         </u-form-item>
       </u-form>
+      <view style="padding-top: 30rpx">
+        <u-checkbox-group v-model="loginForm.rememberPassword">
+          <u-checkbox shape="circle" label="记住密码" name="checked"></u-checkbox>
+        </u-checkbox-group>
+      </view>
       <u-text
         color="#CDCDCD"
         size="20rpx"
@@ -57,6 +62,7 @@
         loginForm: {
           username: '',
           password: '',
+          rememberPassword: [],
         },
         rules: {
           username: {
@@ -74,6 +80,15 @@
         },
       }
     },
+    onLoad() {
+      // 检查本地存储是否保存了用户名和密码
+      const userInfo = uni.getStorageSync('userInfo')
+      if (userInfo) {
+        this.loginForm.username = userInfo.username
+        this.loginForm.password = userInfo.password
+        this.loginForm.rememberPassword = ['checked']
+      }
+    },
     created() {
       const navData = uni.getMenuButtonBoundingClientRect()
       this.height = navData.height + 'px'
@@ -83,6 +98,7 @@
     methods: {
       ...mapActions(['login']),
       async handleLogin() {
+        console.log(this.loginForm.rememberPassword)
         const [valid] = await to(this.$refs.loginForm.validate())
         if (valid !== null) return
         await this.login(this.loginForm)

+ 7 - 4
pages/openSeaCustomer/index.vue

@@ -99,7 +99,10 @@
                 </view>
                 <view class="info-row flex_l">
                   <text class="info-label">客户类别:</text>
-                  <u-text color="#323232" size="24rpx" :text="v.custIndustry"></u-text>
+                  <u-text
+                    color="#323232"
+                    size="24rpx"
+                    :text="selectDictLabel(industryOptions, v.custIndustry)"></u-text>
                 </view>
                 <view class="info-row flex_l">
                   <text class="info-label">最后跟进时间:</text>
@@ -156,7 +159,7 @@
         filterVisible: false, //筛选组件状态
         custName: '', //客户名称
         followUpDate: '', //最后跟进时间
-        industryChecked: 0, //选择的行业id
+        industryChecked: null, //选择的行业id
         industryOptions: [],
         // levelChecked: 0, //选择的级别id
         // levelOptions: [],
@@ -193,7 +196,7 @@
       // 重置
       reset() {
         this.followUpDate = ''
-        this.industryChecked = 0
+        this.industryChecked = null
         // this.levelChecked = 0
       },
       // 确认
@@ -221,7 +224,7 @@
         let params = {
           custName: this.custName,
           followUpDate: this.followUpDate,
-          indusTry: this.industryChecked,
+          custIndustry: this.industryChecked,
           isPublic: true,
           pageNum: this.pageNum,
           pageSize: this.pageSize,

+ 10 - 26
pages/project/create.vue

@@ -135,14 +135,14 @@
             borderBottom
             customStyle="padding:40rpx 0 30rpx"
             @click="$refs.dealer.open()"
-            v-if="addForm.salesModel != '10'">
+            v-if="addForm.salesModel > 10">
             <view class="form-label flex_l">
               <view class="label-tag"></view>
-              经销商/代理商
+              经销商
             </view>
             <u-input
               :readonly="true"
-              placeholder="请选择经销商/代理商"
+              placeholder="请选择经销商"
               v-model="addForm.distributorName"
               border="none"
               suffixIcon="arrow-down"
@@ -386,17 +386,17 @@
       @cancel="showFollowDate = false"
       @confirm="pickFollowDate"></u-datetime-picker>
     <!-- 选择客户 -->
-    <select-customer ref="cust" @close="closeCust()"></select-customer>
+    <select-customer ref="cust" @close="closeCust($event)"></select-customer>
     <!-- 选择客户联系人 -->
-    <customer-contact ref="contact" @close="closeContact()"></customer-contact>
+    <customer-contact ref="contact" @close="closeContact($event)"></customer-contact>
     <!-- 选择销售 -->
-    <select-user ref="user" :query-params="{ roles: ['Sales', 'SalesManager'] }" @close="closeUser()"></select-user>
+    <select-user ref="user" :query-params="{ roles: ['SalesEngineer'] }" @close="closeUser($event)"></select-user>
     <!-- 选择经销商 -->
-    <select-dealer ref="dealer" @close="closeDealer()"></select-dealer>
+    <select-dealer ref="dealer" @close="closeDealer($event)"></select-dealer>
     <!-- 选择用户 -->
-    <select-user ref="allUser" @close="closeAllUser()"></select-user>
+    <select-user ref="allUser" @close="closeAllUser($event)"></select-user>
     <!-- 选择产品 -->
-    <select-product ref="product" @close="closeProduct()"></select-product>
+    <select-product ref="product" @close="closeProduct($event)"></select-product>
     <!-- 项目来源 -->
     <u-picker
       :show="showNboSource"
@@ -444,20 +444,6 @@
     name: 'omsIndex',
     components: { SelectCustomer, CustomerContact, SelectUser, SelectDealer, 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: '',
@@ -513,9 +499,7 @@
           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: '请选择经销商/代理商' },
-          ],
+          distributorName: [{ required: true, trigger: ['blur', 'change'], message: '请选择经销商/代理商' }],
           isBigVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择是否大项目' }],
           productLineVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择产品线' }],
           // 跟进

+ 1 - 0
pages/project/details.vue

@@ -212,6 +212,7 @@
       this.paddingTop = navData.top + 'px'
     },
     onShow() {
+      this.openBtnWidth = false
       this.getProjectDetail()
     },
     watch: {

+ 1 - 1
pages/project/transfer.vue

@@ -51,7 +51,7 @@
     </view>
     <u-notify ref="uNotify"></u-notify>
     <u-toast ref="uToast"></u-toast>
-    <select-user ref="user" @close="closeUser()"></select-user>
+    <select-user ref="user" @close="closeUser($event)"></select-user>
   </view>
 </template>
 <script>

+ 9 - 9
pages/project/upgrade.vue

@@ -341,9 +341,9 @@
       @cancel="showChasingWay = false"
       @confirm="pickModel"></u-picker>
     <!-- 选择经销商 -->
-    <select-dealer ref="dealer" @close="closeDealer()"></select-dealer>
+    <select-dealer ref="dealer" @close="closeDealer($event)"></select-dealer>
     <!-- 客户联系人 -->
-    <customer-contact ref="contact" @close="closeContact()"></customer-contact>
+    <customer-contact ref="contact" @close="closeContact($event)"></customer-contact>
     <u-notify ref="uNotify"></u-notify>
     <u-toast ref="uToast"></u-toast>
     <u-modal
@@ -636,13 +636,13 @@
           }
         }
       },
-      closeUser(user) {
-        if (user) {
-          console.log(user)
-          this.addForm.userId = user.id
-          this.addForm.userName = user.label
-        }
-      },
+      // closeUser(user) {
+      //   if (user) {
+      //     console.log(user)
+      //     this.addForm.userId = user.id
+      //     this.addForm.userName = user.label
+      //   }
+      // },
       goBack() {
         uni.navigateBack({
           //关闭当前页面,返回上一页面或多级页面。

+ 276 - 0
pages/publicPages/concatCreate.vue

@@ -0,0 +1,276 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-01-12 11:57:48
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-03-22 10:41:11
+ * @Description: file content
+ * @FilePath: \oms\pages\publicPages\concatCreate.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="cuctName" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            姓名
+          </view>
+          <u-input border="none" v-model="addForm.cuctName" placeholder="请输入姓名"></u-input>
+        </u-form-item>
+        <u-form-item prop="custName" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            客户名称
+          </view>
+          <u-input disabled border="none" v-model="addForm.custName" placeholder="请输入客户名称"></u-input>
+        </u-form-item>
+        <u-form-item prop="telephone" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">手机号码</view>
+          <u-input border="none" maxlength="11" v-model="addForm.telephone" placeholder="请输入手机号码"></u-input>
+        </u-form-item>
+        <u-form-item prop="wechat" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">微信</view>
+          <u-input border="none" v-model="addForm.wechat" placeholder="请输入微信"></u-input>
+        </u-form-item>
+        <u-form-item prop="email" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">邮箱</view>
+          <u-input border="none" v-model="addForm.email" placeholder="请输入邮箱"></u-input>
+        </u-form-item>
+        <u-form-item prop="dept" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">部门</view>
+          <u-input border="none" v-model="addForm.dept" placeholder="请输入部门"></u-input>
+        </u-form-item>
+        <u-form-item prop="postion" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            职务
+          </view>
+          <u-input border="none" v-model="addForm.postion" placeholder="请输入职务"></u-input>
+        </u-form-item>
+        <u-form-item prop="officeLocation" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">办公地点</view>
+          <u-input border="none" v-model="addForm.officeLocation" placeholder="请输入办公地点"></u-input>
+        </u-form-item>
+        <u-form-item prop="isDecision" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            是否关键决策人
+          </view>
+          <u-radio-group v-model="addForm.isDecision" placement="row">
+            <u-radio name="10" label="是" customStyle="margin-right:14rpx"></u-radio>
+            <u-radio name="20" label="否"></u-radio>
+          </u-radio-group>
+        </u-form-item>
+        <u-form-item prop="isDecision" customStyle="padding:40rpx 0 34rpx" borderBottom>
+          <view class="form-label flex_l">
+            <view class="label-tag"></view>
+            性别
+          </view>
+          <u-radio-group v-model="addForm.cuctGender" placement="row">
+            <u-radio name="10" label="男" customStyle="margin-right:14rpx"></u-radio>
+            <u-radio name="20" label="女"></u-radio>
+          </u-radio-group>
+        </u-form-item>
+      </u-form>
+      <view class="center">
+        <view class="handle-btn" @click="handleAdd">保存</view>
+      </view>
+    </view>
+    <u-notify ref="uNotify"></u-notify>
+    <u-toast ref="uToast"></u-toast>
+  </view>
+</template>
+<script>
+  import to from 'await-to-js'
+  import customerApi from '../../api/customer'
+  export default {
+    name: 'omsIndex',
+    data() {
+      return {
+        height: '',
+        paddingTop: '',
+        addForm: {
+          cuctName: '',
+          telephone: '',
+          wechat: '',
+          email: '',
+          dept: '',
+          postion: '',
+          officeLocation: '',
+          custId: 0,
+          custName: '',
+          isDecision: '20', //是否决策人 (10是20否)
+          cuctGender: '10', //性别(10男20女)
+        },
+        rules: {
+          cuctName: { required: true, trigger: ['blur'], message: '请输入联系人姓名' },
+          custName: { required: true, trigger: ['blur'], message: '请输入客户名称' },
+          cuctGender: { required: true, trigger: ['blur'], message: '请输入性别' },
+          postion: { required: true, trigger: ['blur'], message: '请输入岗位名称' },
+          telephone: [
+            {
+              validator: (rule, value, callback) => {
+                if (value !== '') {
+                  const reg = /^1[3456789]\d{9}$/
+                  if (!reg.test(value)) {
+                    callback(new Error('手机号格式不正确'))
+                  } else {
+                    callback()
+                  }
+                } else {
+                  callback()
+                }
+              },
+            },
+          ],
+        },
+      }
+    },
+    onLoad(option) {
+      console.log(option)
+      this.addForm.custId = Number(option.id)
+      this.addForm.custName = option.name
+    },
+    created() {
+      const navData = uni.getMenuButtonBoundingClientRect()
+      this.height = navData.height + 'px'
+      this.paddingTop = navData.top + 'px'
+    },
+    mounted() {},
+    methods: {
+      handleAdd() {
+        this.$refs.addForm
+          .validate()
+          .then(async () => {
+            let params = this.addForm
+            console.log(params)
+            const [err, res] = await to(customerApi.createContact(params))
+            if (err) return
+            if (res && res.code == 200) {
+              this.$refs.uToast.show({
+                type: 'success',
+                message: '创建成功',
+                complete: () => {
+                  uni.navigateBack({
+                    //关闭当前页面,返回上一页面或多级页面。
+                    delta: 1,
+                  })
+                },
+              })
+            }
+          })
+          .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: #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: #ff4d4f;
+          border-radius: 50%;
+          margin-right: 10rpx;
+        }
+      }
+
+      .upload-file-box {
+        padding: 20rpx 0;
+        position: relative;
+
+        .upload-btn {
+          position: absolute;
+          right: 0;
+          top: 26rpx;
+        }
+      }
+    }
+
+    .handle-btn {
+      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>

+ 21 - 10
store/index.js

@@ -102,19 +102,30 @@ const store = new Vuex.Store({
      * @param {*} userInfo
      */
     async login({ commit, dispatch }, userInfo) {
+      console.log(userInfo.rememberPassword)
       const [err, res] = await to(userApi.login(userInfo))
       if (err) return
-      uni.showToast({
-        title: '登录成功',
-        icon: 'none',
-        complete: async () => {
-          commit('setToken', res.data.token)
-          uni.reLaunch({
-            url: '/pages/home/index',
+      if (res.code == 200) {
+        if (userInfo.rememberPassword[0] && userInfo.rememberPassword[0] == 'checked') {
+          uni.setStorageSync('userInfo', {
+            username: userInfo.username,
+            password: userInfo.password,
           })
-          await dispatch('getUserInfo')
-        },
-      })
+        } else {
+          uni.removeStorageSync('userInfo')
+        }
+        uni.showToast({
+          title: '登录成功',
+          icon: 'none',
+          complete: async () => {
+            commit('setToken', res.data.token)
+            uni.reLaunch({
+              url: '/pages/home/index',
+            })
+            await dispatch('getUserInfo')
+          },
+        })
+      }
     },
     /**
      * @description 获取用户信息接口

+ 31 - 0
style/common.scss

@@ -188,10 +188,41 @@ view {
     }
 }
 
+.form-item {
+    padding-bottom: 30rpx;
+    .form-label {
+        font-size: 30rpx;
+        font-weight: bold;
+        color: #323232;
+        padding-bottom: 18rpx;
+        .label-tag {
+            width: 15rpx;
+            height: 15rpx;
+            background: #ff4d4f;
+            border-radius: 50%;
+            margin-right: 10rpx;
+        }
+    }
+}
+
 .data-list {
     .info-item {
         .label {
             min-width: 130rpx;
         }
     }
+}
+
+.form-label {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #323232;
+    padding-bottom: 18rpx;
+    .label-tag {
+        width: 15rpx;
+        height: 15rpx;
+        background: #ff4d4f;
+        border-radius: 50%;
+        margin-right: 10rpx;
+    }
 }

+ 2 - 2
utils/index.js

@@ -271,8 +271,8 @@ export function formatPrice(price, currency = 'CNY') {
 }
 
 // 回显数据字典
-export function selectDictLabel(datas, value, productList) {
-  console.log(datas, productList)
+export function selectDictLabel(datas, value) {
+  console.log(datas, value)
   if (!datas || datas.length == 0) {
     return value
   }