Bläddra i källkod

feature:增加督办列表和详情、首页修改样式、修改打卡记录数据重复

liuzl 2 år sedan
förälder
incheckning
a7ac5c4fed

+ 7 - 0
pages.json

@@ -164,6 +164,13 @@
       },
       "tit": "项目升级"
     },
+    {
+      "path": "pages/schedule/supervise/details",
+      "style": {
+        "navigationStyle": "custom"
+      },
+      "tit": "督办详情"
+    },
     {
       "path": "pages/message/index",
       "style": {

+ 1 - 1
pages/customer/components/followRecords.vue

@@ -13,7 +13,7 @@
                 <u-col span="12">
                   <view class="flex_l">
                     <text class="tit-txt text-ellipsis flex_1">
-                      {{ item.contactsName }} 跟进({{ formatType(item.followType) }})
+                      {{ item.createdName }} 跟进({{ formatType(item.followType) }})
                     </text>
                   </view>
                 </u-col>

+ 1 - 1
pages/customer/details.vue

@@ -126,7 +126,7 @@
         fllowList: [], //跟进数据
         list: [
           {
-            name: '活动记录',
+            name: '跟进记录',
             index: 0,
           },
           {

+ 1 - 1
pages/distributor/details.vue

@@ -102,7 +102,7 @@
         fllowList: [], //跟进数据
         list: [
           {
-            name: '活动记录',
+            name: '跟进记录',
             index: 0,
           },
           {

+ 2 - 1
pages/home/checkIn.vue

@@ -194,7 +194,8 @@
           return
         }
         if (res && res.code == 200) {
-          this.checkList = [...this.checkList, ...(res.data.list || [])]
+          // this.checkList = [...this.checkList, ...(res.data.list || [])]
+          this.checkList = res.data.list
           this.total = res.data.total
           this.loadStatus = this.checkList.length == this.total ? 'nomore' : 'loadmore'
         } else {

+ 19 - 48
pages/home/index.vue

@@ -2,7 +2,7 @@
  * @Author: liuzhenlin 461480418@qq.ocm
  * @Date: 2023-01-12 11:57:48
  * @LastEditors: liuzhenlin
- * @LastEditTime: 2023-02-27 17:20:10
+ * @LastEditTime: 2023-03-06 16:46:52
  * @Description: file content
  * @FilePath: \oms\pages\home\index.vue
 -->
@@ -14,15 +14,16 @@
         <view class="title" :style="[{ height }, { lineHeight: height }]">首页</view>
       </view>
     </view>
-    <view class="header">
-      <view class="h-left">
+    <view class="main">
+      <view class="header">
+        <u-swiper :list="bannerList" radius="0" interval="5000" circular></u-swiper>
+        <!-- <view class="h-left">
         <text class="name">大数华创</text>
         <text class="txt">提升工作效率,降低管理难度</text>
         <view class="line"></view>
       </view>
-      <view class="h-right"></view>
-    </view>
-    <view class="main">
+      <view class="h-right"></view> -->
+      </view>
       <view class="msg-box">
         <view class="tab-date-wrap">
           <text class="tab-date-item" @click="getReport('week')" :class="{ dateActive: tabDate == 'week' }">本周</text>
@@ -213,6 +214,11 @@
     name: 'omsIndex',
     data() {
       return {
+        bannerList: [
+          require('@/static/images/swiper/banner1.png'),
+          require('@/static/images/swiper/banner2.png'),
+          require('@/static/images/swiper/banner3.png'),
+        ],
         privateBoard: [], //个人看板数据
         height: '',
         paddingTop: '',
@@ -391,8 +397,8 @@
 </style>
 <style lang="scss" scoped>
   .home {
-    padding-top: 210rpx;
-    position: relative;
+    padding-top: 200rpx;
+    // position: relative;
     .check {
       position: fixed;
       right: 20rpx;
@@ -412,7 +418,7 @@
       top: 0;
       width: 100%;
       height: 556rpx;
-      background: linear-gradient(193deg, rgba(62, 126, 248, 1) 0%, rgba(226, 236, 255, 1) 100%);
+      background: #3e7ef8;
       border-radius: 0 0 92rpx 92rpx;
       z-index: -1;
 
@@ -424,48 +430,13 @@
       }
     }
 
-    .header {
-      padding: 0 75rpx;
-      display: flex;
-
-      .h-left {
-        box-sizing: border-box;
-        padding-top: 30rpx;
-        display: flex;
-        color: #ffffff;
-        flex: 1;
-        display: flex;
-        flex-flow: column;
-
-        .name {
-          font-size: 32rpx;
-          font-weight: bold;
-          margin-bottom: 12rpx;
-        }
-
-        .txt {
-          font-size: 24rpx;
-          margin-bottom: 20rpx;
-        }
-
-        .line {
-          width: 46rpx;
-          border: 2rpx solid #ffffff;
-        }
-      }
-
-      .h-right {
-        width: 115px;
-        height: 115px;
-        background: url('../../static/images/home1.png') no-repeat;
-        background-size: cover;
-      }
-    }
-
     .main {
       box-sizing: border-box;
       padding: 0 32rpx 46rpx;
-
+      position: absolute;
+      width: 100%;
+      height: calc(100vh - 200rpx);
+      // overflow: hidden;
       .msg-box {
         width: 100%;
         height: 185rpx;

+ 1 - 1
pages/project/components/followRecords.vue

@@ -13,7 +13,7 @@
                 <u-col span="12">
                   <view class="flex_l">
                     <text class="tit-txt text-ellipsis flex_1">
-                      {{ item.contactsName }} 跟进({{ formatType(item.followType) }})
+                      {{ item.createdName }} 跟进({{ formatType(item.followType) }})
                     </text>
                   </view>
                 </u-col>

+ 1 - 13
pages/project/details.vue

@@ -122,7 +122,7 @@
         fllowList: [], //跟进数据
         list: [
           {
-            name: '活动记录',
+            name: '跟进记录',
             index: 0,
           },
           {
@@ -319,18 +319,6 @@
         padding: 32rpx;
         overflow: auto;
         padding-bottom: 145rpx;
-        .status1 {
-          color: #4096fb;
-          background: rgba(64, 150, 251, 0.2);
-        }
-        .status2 {
-          background: rgba(255, 184, 60, 0.2);
-          color: #ffb83c;
-        }
-        .status3 {
-          color: #fe6936;
-          background: rgba(254, 105, 54, 0.2);
-        }
       }
     }
     .fixed-btn-group {

+ 44 - 65
pages/publicPages/follow.vue

@@ -22,12 +22,7 @@
       <u-form :model="addForm" :rules="rules" ref="addForm" label-width="0">
         <u-form-item prop="content" customStyle="padding:40rpx 0 34rpx">
           <view class="form-label flex_l">跟进内容</view>
-          <u-textarea
-            v-model="addForm.content"
-            placeholder="请输入跟进内容"
-            maxlength="800"
-            height="190rpx"
-            count
+          <u-textarea v-model="addForm.content" placeholder="请输入跟进内容" maxlength="800" height="190rpx" count
             customStyle="border-radius:16rpx"></u-textarea>
         </u-form-item>
         <u-form-item prop="date" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showDate = true">
@@ -35,59 +30,31 @@
             <view class="label-tag"></view>
             跟进时间
           </view>
-          <u-input
-            :readonly="true"
-            placeholder="请选择跟进时间"
-            v-model="addForm.date"
-            border="none"
-            suffixIcon="arrow-down"
-            suffixIconStyle="color:#CDCDCD"
-            clearable
-            customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          <u-input :readonly="true" placeholder="请选择跟进时间" v-model="addForm.date" border="none" suffixIcon="arrow-down"
+            suffixIconStyle="color:#CDCDCD" clearable customStyle="padding: 0 30rpx 0 12rpx"></u-input>
         </u-form-item>
         <u-form-item prop="mode" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showMode = true">
           <view class="form-label flex_l">
             <view class="label-tag"></view>
             跟进方式
           </view>
-          <u-input
-            :readonly="true"
-            placeholder="请选择跟进方式"
-            v-model="addForm.mode"
-            border="none"
-            suffixIcon="arrow-down"
-            suffixIconStyle="color:#CDCDCD"
-            clearable
-            customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          <u-input :readonly="true" placeholder="请选择跟进方式" v-model="addForm.mode" border="none" suffixIcon="arrow-down"
+            suffixIconStyle="color:#CDCDCD" clearable customStyle="padding: 0 30rpx 0 12rpx"></u-input>
         </u-form-item>
         <u-form-item prop="contactsName" borderBottom customStyle="padding:40rpx 0 30rpx" @click="open">
           <view class="form-label flex_l">
             <view class="label-tag"></view>
             联系人
           </view>
-          <u-input
-            :readonly="true"
-            placeholder="请选择客户联系人"
-            v-model="addForm.contactsName"
-            border="none"
-            suffixIcon="arrow-down"
-            suffixIconStyle="color:#CDCDCD"
-            clearable
-            customStyle="padding: 0 30rpx 0 12rpx"></u-input>
+          <u-input :readonly="true" placeholder="请选择客户联系人" v-model="addForm.contactsName" border="none"
+            suffixIcon="arrow-down" suffixIconStyle="color:#CDCDCD" clearable customStyle="padding: 0 30rpx 0 12rpx">
+          </u-input>
         </u-form-item>
       </u-form>
       <view class="upload-file-box">
         <view class="form-label flex_l">附件</view>
-        <uni-file-picker
-          file-mediatype="all"
-          v-model="imageValue"
-          mode="grid"
-          @select="select"
-          @progress="progress"
-          @success="success"
-          @fail="fail"
-          ref="upload"
-          limit="1">
+        <uni-file-picker file-mediatype="all" v-model="imageValue" mode="grid" @select="select" @progress="progress"
+          @success="success" @fail="fail" ref="upload" limit="1">
           <view class="upload-btn">
             <u-icon name="plus-circle-fill" color="blue" size="28"></u-icon>
           </view>
@@ -95,20 +62,11 @@
       </view>
       <view class="save" @click="handleAdd">保存</view>
       <!-- 选择跟进方式 -->
-      <u-picker
-        :show="showMode"
-        :columns="modeColumns"
-        keyName="label"
-        @cancel="showMode = false"
-        @confirm="pickMode"></u-picker>
+      <u-picker :show="showMode" :columns="modeColumns" keyName="label" @cancel="showMode = false" @confirm="pickMode">
+      </u-picker>
       <!-- 选择下次时间 -->
-      <u-datetime-picker
-        v-if="showDate"
-        :show="showDate"
-        mode="datetime"
-        v-model="addForm.date"
-        @cancel="showDate = false"
-        @confirm="pickDate"></u-datetime-picker>
+      <u-datetime-picker v-if="showDate" :show="showDate" mode="datetime" v-model="addForm.date"
+        @cancel="showDate = false" @confirm="pickDate"></u-datetime-picker>
     </view>
     <u-notify ref="uNotify"></u-notify>
     <u-toast ref="uToast"></u-toast>
@@ -119,7 +77,9 @@
   </view>
 </template>
 <script>
-  import { mapGetters } from 'vuex'
+  import {
+    mapGetters
+  } from 'vuex'
   import to from 'await-to-js'
   import followApi from '../../api/follow'
   import custApi from '../../api/customer'
@@ -128,7 +88,10 @@
   import CustomerContact from '../../components/CustomerContact'
   export default {
     name: 'omsIndex',
-    components: { CustomerContact, ProjectContact },
+    components: {
+      CustomerContact,
+      ProjectContact
+    },
     data() {
       return {
         imageValue: [],
@@ -137,8 +100,7 @@
         showMode: false, //选择行业
         showDate: false,
         modeColumns: [
-          [
-            {
+          [{
               label: '电话',
               id: '10',
             },
@@ -215,14 +177,18 @@
       async initData() {
         if (this.targetType == '10') {
           //客户
-          const [err, res] = await to(custApi.getDetail({ ids: [this.curId] }))
+          const [err, res] = await to(custApi.getDetail({
+            ids: [this.curId]
+          }))
           if (err) return
           if (res && res.code == 200) {
             this.details = res.data.list[0]
           }
         } else if (this.targetType == '20') {
           //项目
-          const [err, res] = await to(prodApi.getDetail({ id: this.curId }))
+          const [err, res] = await to(prodApi.getDetail({
+            id: this.curId
+          }))
           if (err) return
           if (res && res.code == 200) {
             this.details = res.data
@@ -281,8 +247,7 @@
                 targetName: this.details.nboName,
               }
             }
-            let params = Object.assign(
-              {
+            let params = Object.assign({
                 contactsId: this.addForm.contactsId,
                 contactsName: this.addForm.contactsName,
                 followContent: this.addForm.content,
@@ -340,7 +305,14 @@
             file: e.tempFiles[0].file,
           },
           success: (res) => {
-            this.addForm.files = [{ fileName: e.tempFiles[0].file.name, fileUrl: action }]
+            this.$refs.uToast.show({
+              type: 'success',
+              message: '附件上传成功',
+            })
+            this.addForm.files = [{
+              fileName: e.tempFiles[0].file.name,
+              fileUrl: action
+            }]
           },
           fail: (err) => {},
         })
@@ -384,12 +356,14 @@
       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;
@@ -411,11 +385,13 @@
       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;
@@ -424,9 +400,11 @@
           margin-right: 10rpx;
         }
       }
+
       .upload-file-box {
         padding: 20rpx 0;
         position: relative;
+
         .upload-btn {
           position: absolute;
           right: 0;
@@ -434,6 +412,7 @@
         }
       }
     }
+
     .save {
       width: 569rpx;
       height: 92rpx;

+ 2 - 2
pages/schedule/components/add.vue

@@ -2,9 +2,9 @@
  * @Author: liuzhenlin 461480418@qq.ocm
  * @Date: 2023-01-16 10:11:35
  * @LastEditors: liuzhenlin
- * @LastEditTime: 2023-01-29 11:57:00
+ * @LastEditTime: 2023-03-06 13:52:55
  * @schContentription: file content
- * @FilePath: \crm\pages\schedule\components\add.vue
+ * @FilePath: \oms\pages\schedule\components\add.vue
 -->
 <template>
   <view>

+ 0 - 245
pages/schedule/components/supervise.vue

@@ -1,245 +0,0 @@
-<!--
- * @Author: liuzhenlin 461480418@qq.ocm
- * @Date: 2023-01-16 14:35:18
- * @LastEditors: liuzhenlin
- * @LastEditTime: 2023-02-16 17:07:46
- * @Description: file content
- * @FilePath: \oms\pages\schedule\components\supervise.vue
--->
-<template>
-  <view class="supervise-main">
-    <u-tabs
-      :list="list"
-      @change="changeTabs"
-      :current="curTabIndex - 1"
-      :scrollable="false"
-      :activeStyle="{
-        color: '#323232',
-        fontWeight: 'bold',
-      }"
-      :inactiveStyle="{
-        color: '#969696',
-      }"></u-tabs>
-    <!-- 列表 -->
-    <view class="data-scroll-wrap">
-      <u-empty mode="list" text="暂无督办数据" v-if="taskList.length == 0"></u-empty>
-      <scroll-view v-else class="data-list" :scroll-top="scrollTop" :scroll-y="true" @scrolltolower="lower">
-        <view class="todo-item" v-for="(v, i) in taskList" :key="i" @click="showDesc(v)">
-          <u-row>
-            <u-col span="12">
-              <view class="header">
-                <u-row>
-                  <u-col span="12">
-                    <view class="flex_l">
-                      <image class="todo-img" src="../../../static/images/todo-img.png" mode="scaleToFill" />
-                      <text class="tit-txt flex_1">
-                        {{ v.taskTitle }}
-                      </text>
-                      <view class="do-status" :class="'status' + v.taskStatus">{{ setTaskStatus(v.taskStatus) }}</view>
-                    </view>
-                  </u-col>
-                </u-row>
-                <view class="content flex">
-                  <text class="content-txt text-ellipsis">
-                    {{ v.taskDesc }}
-                  </text>
-                </view>
-                <view class="content-footer flex_l">
-                  <text class="date mr10">
-                    {{ parseTime(v.taskStartDate, '{m}-{d} {h}:{i}') }}
-                  </text>
-                  <text class="date mr10">-</text>
-                  <text class="date">{{ parseTime(v.taskEndDate, '{m}-{d} {h}:{i}') }}</text>
-                </view>
-              </view>
-            </u-col>
-          </u-row>
-        </view>
-        <u-loadmore :status="loadStatus" />
-      </scroll-view>
-    </view>
-    <u-modal :show="showModal" :content="content" @confirm="showModal = false"></u-modal>
-  </view>
-</template>
-
-<script>
-  import taskApi from '../../../api/task'
-  import to from 'await-to-js'
-  export default {
-    name: 'omsTodo',
-
-    data() {
-      return {
-        curTabIndex: 1, //tabs状态
-        loadStatus: '', //加载状态
-        list: [
-          {
-            name: '我的待办',
-            status: 1,
-          },
-          {
-            name: '我发起的',
-            status: 2,
-          },
-          {
-            name: '我处理的',
-            status: 3,
-          },
-        ],
-        pageNum: 0,
-        pageSize: 10,
-        taskList: [], //客户列表
-        taskTotal: 0, //列表元素数量
-        showModal: false,
-        content: '', //modal内容
-      }
-    },
-
-    mounted() {
-      this.getSuperviseData()
-    },
-
-    methods: {
-      // 上拉滚动
-      lower() {
-        if (this.taskList.length < this.taskTotal && this.loadStatus != 'loading') {
-          this.$u.throttle(this.getSuperviseData(), 2000, false)
-        }
-      },
-      showDesc(v) {
-        console.log(v.taskDesc)
-        if (v.taskDesc) {
-          this.showModal = true
-          this.content = v.taskDesc
-        }
-      },
-      searchList() {
-        this.pageNum = 0
-        this.getSuperviseData(true)
-      },
-      async getSuperviseData(reset) {
-        this.loadStatus = 'loading'
-        this.pageNum++
-        let params = {
-          operateType: '' + this.curTabIndex,
-          pageNum: this.pageNum,
-          pageSize: this.pageSize,
-        }
-        const [err, res] = await to(taskApi.getList(params))
-        if (err) {
-          this.loadStatus = 'nomore'
-          return
-        }
-        if (res && res.code == 200) {
-          if (reset) {
-            this.taskList = res.data.list || []
-          } else {
-            this.taskList = [...this.taskList, ...(res.data.list || [])]
-          }
-          this.taskTotal = res.data.total
-          this.loadStatus = this.taskList.length == this.taskTotal ? 'nomore' : 'loadmore'
-          console.log(this.loadStatus)
-        } else {
-          this.loadStatus = 'nomore'
-        }
-      },
-      // 改变tab
-      changeTabs(data) {
-        console.log(data)
-        this.curTabIndex = data.status
-        this.searchList(true)
-      },
-      setTaskStatus(status) {
-        let statusObj = {
-          10: '已发起',
-          20: '进行中',
-          30: '已完成',
-        }
-        return statusObj[status]
-      },
-    },
-  }
-</script>
-
-<style lang="scss" scoped>
-  .supervise-main {
-    height: 100%;
-    .data-scroll-wrap {
-      height: calc(100vh - 366rpx);
-      padding: 30rpx 0;
-      .data-list {
-        width: 100%;
-        height: 100%;
-        background: #ffffff;
-        overflow: auto;
-        .todo-item {
-          padding: 12rpx 40rpx 12rpx 46rpx;
-          background: #f2f3f5;
-          border-radius: 15rpx;
-          margin-bottom: 32rpx;
-          .tit-txt {
-            font-size: 28rpx;
-            font-weight: bold;
-            color: #323232;
-          }
-          .content-txt {
-            font-size: 28rpx;
-            color: #646464;
-          }
-          .user-txt {
-            font-size: 20rpx;
-            color: #646464;
-          }
-          .header {
-            .todo-img {
-              flex: 0 0 24rpx;
-              height: 24rpx;
-              margin-right: 12rpx;
-            }
-            .do-status {
-              width: 70rpx;
-              height: 30rpx;
-              border-radius: 0rpx 15rpx 0rpx 0rpx;
-              text-align: center;
-              line-height: 30rpx;
-              font-size: 18rpx;
-            }
-          }
-          .content {
-            padding: 12rpx 0 12rpx 40rpx;
-            font-size: 28rpx;
-            color: #646464;
-          }
-          .content-footer {
-            padding: 0 0 12rpx 40rpx;
-            .date {
-              font-size: 24rpx;
-              color: #969696;
-            }
-            .user-img {
-              width: 46rpx;
-              height: 46rpx;
-              border-radius: 50%;
-              margin-right: 15rpx;
-            }
-          }
-        }
-        .status10 {
-          color: #4096fb;
-          background: rgba(64, 150, 251, 0.2);
-        }
-        .status20 {
-          background: rgba(255, 184, 60, 0.2);
-          color: #ffb83c;
-        }
-        .status30 {
-          color: #fe6936;
-          background: rgba(254, 105, 54, 0.2);
-        }
-      }
-    }
-    .mr10 {
-      margin-right: 10rpx;
-    }
-  }
-</style>

+ 3 - 3
pages/schedule/index.vue

@@ -46,9 +46,9 @@
   </view>
 </template>
 <script>
-  import manage from './components/manage'
-  import supervise from './components/supervise'
-  import log from './components/log'
+  import manage from './manage'
+  import supervise from './supervise'
+  import log from './log'
   export default {
     name: 'opsIndex',
     components: { manage, supervise, log },

+ 2 - 2
pages/schedule/components/log.vue → pages/schedule/log.vue

@@ -47,7 +47,7 @@
                   </text>
                 </view>
                 <view class="content-footer flex1">
-                  <text class="date">2022-12-15</text>
+                  <text class="date"> {{ parseTime(v.followDate,'{y}-{m}-{d}') }}</text>
                 </view>
               </view>
             </u-col>
@@ -61,7 +61,7 @@
 </template>
 
 <script>
-  import followApi from '../../../api/follow'
+  import followApi from '@/api/follow'
   import to from 'await-to-js'
   export default {
     name: 'omsTodo',

+ 4 - 4
pages/schedule/components/manage.vue → pages/schedule/manage.vue

@@ -80,10 +80,10 @@
 
 <script>
   import to from 'await-to-js'
-  import CustomCalendar from '../../../components/calendar'
-  import calendar from '../../../utils/date'
-  import add from './add'
-  import scheduleApi from '../../../api/schedule'
+  import CustomCalendar from '@/components/calendar'
+  import calendar from '@/utils/date'
+  import add from './components/add'
+  import scheduleApi from '@/api/schedule'
   export default {
     name: 'omsManage',
     components: {

+ 131 - 0
pages/schedule/supervise/components/taskDetails.vue

@@ -0,0 +1,131 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-02-15 16:25:58
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-03-06 16:12:12
+ * @Description: file content
+ * @FilePath: \oms\pages\schedule\supervise\components\taskDetails.vue
+-->
+<template>
+  <view>
+    <view class="info-item">
+      <u-row justify="space-between" gutter="10">
+        <u-col span="12">
+          <view class="flex_l">
+            <view class="label">督办内容:</view>
+            <view class="desc">{{ detail.taskDesc }}</view>
+          </view>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="info-item">
+      <u-row justify="space-between" gutter="10">
+        <u-col span="12">
+          <view class="flex_l">
+            <view class="label">要求完成时间:</view>
+            <view class="desc">{{ parseTime(detail.taskEndDate, '{y}-{m}-{d}') }}</view>
+          </view>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="info-item">
+      <u-row justify="space-between" gutter="10">
+        <u-col span="12">
+          <view class="flex_l">
+            <view class="label">负责人:</view>
+            <view class="desc">{{ selectDictLabel(userList, detail.mainUserId) }}</view>
+          </view>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="info-item">
+      <u-row justify="space-between" gutter="10">
+        <u-col span="12">
+          <view class="flex_l">
+            <view class="label">协办人:</view>
+            <view class="desc">{{ generateOwnerUser(detail.ownerUserId) }}</view>
+          </view>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="info-item">
+      <u-row justify="space-between" gutter="10">
+        <u-col span="12">
+          <view class="flex_l">
+            <view class="label">督办人:</view>
+            <view class="desc">{{ selectDictLabel(userList, detail.watchUserId) }}</view>
+          </view>
+        </u-col>
+      </u-row>
+    </view>
+    <view class="info-item">
+      <u-row justify="space-between" gutter="10">
+        <u-col span="12">
+          <view class="flex_l">
+            <view class="label">监办人:</view>
+            <view class="desc">{{ selectDictLabel(userList, detail.supervisorUserId) }}</view>
+          </view>
+        </u-col>
+      </u-row>
+    </view>
+  </view>
+</template>
+
+<script>
+  export default {
+    props: {
+      detail: {
+        type: [Object],
+        default: {},
+      },
+      taskTypeOption: {
+        type: [Array],
+        default: [],
+      },
+      sourceOption: {
+        type: [Array],
+        default: [],
+      },
+      userList: {
+        type: [Array],
+        default: [],
+      },
+    },
+    data() {
+      return {}
+    },
+
+    mounted() {},
+
+    methods: {
+      // 协办人
+      generateOwnerUser(ids = null) {
+        let nameArr = []
+        if (ids) {
+          let idList = ids.split(',')
+          console.log(idList)
+          idList.forEach((item) => {
+            let findUser = this.userList.find((user) => user.key == item)
+            console.log(findUser)
+            if (findUser.value) nameArr.push(findUser.value)
+          })
+        }
+        return nameArr.join(',')
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .info-item {
+    padding: 20rpx;
+    .label {
+      color: #646464;
+      font-size: 26rpx;
+    }
+    .desc {
+      font-size: 26rpx;
+      text-indent: 20rpx;
+    }
+  }
+</style>

+ 363 - 0
pages/schedule/supervise/details.vue

@@ -0,0 +1,363 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-01-12 11:57:48
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-03-06 15:57:46
+ * @Description: file content
+ * @FilePath: \oms\pages\schedule\supervise\details.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="main-top">
+        <view class="customer-box">
+          <view class="header flex1">
+            <view class="name flex_l">
+              <image class="img" src="@/static/images/menu2.png" mode="scaleToFill" />
+              <text>{{ details.taskTitle }}</text>
+            </view>
+            <view class="date">{{ parseTime(details.taskStartDate, '{y}-{m}-{d} {h}:{i}') || '-' }}</view>
+          </view>
+          <view class="info">
+            <view class="info-item">
+              <u-row>
+                <u-col span="6">
+                  <view class="flex_l">
+                    <view class="info-label">督办类型:</view>
+                    <text class="info-txt">{{ selectDictLabel(taskTypeOption, details.taskType) }}</text>
+                  </view>
+                </u-col>
+                <u-col span="6">
+                  <view class="flex_l">
+                    <view class="info-label">督办状态:</view>
+                    <text class="info-txt">{{ selectDictLabel(taskStatusOption, details.taskStatus) }}</text>
+                  </view>
+                </u-col>
+              </u-row>
+            </view>
+            <view class="info-item">
+              <u-row justify="space-between">
+                <u-col span="6">
+                  <view class="flex_l">
+                    <view class="info-label">是否超期:</view>
+                    <text class="info-txt">
+                      {{ isNotOverdue(parseTime(details.taskEndDate, '{y}-{m}-{d} 23:59:59')) ? '否' : '是' }}
+                    </text>
+                  </view>
+                </u-col>
+                <u-col span="6">
+                  <view class="flex_l">
+                    <view class="info-label">事项来源:</view>
+                    <text class="info-txt">{{ selectDictLabel(sourceOption, details.source) }}</text>
+                  </view>
+                </u-col>
+              </u-row>
+            </view>
+          </view>
+        </view>
+        <view class="tabs">
+          <u-tabs
+            @change="changeTabs"
+            :current="curTabIndex"
+            :scrollable="false"
+            :list="list"
+            :activeStyle="{
+              color: '#3E7EF8',
+              fontWeight: 'bold',
+            }"
+            :inactiveStyle="{
+              color: '#969696',
+            }"></u-tabs>
+        </view>
+      </view>
+      <view class="data-list">
+        <task-details
+          v-if="curTabIndex == 0"
+          :detail="details"
+          :taskTypeOption="taskTypeOption"
+          :sourceOption="sourceOption"
+          :userList="userList"></task-details>
+      </view>
+    </view>
+    <!-- 新增按钮 -->
+    <view class="fixed-btn-group" :style="{ width: openBtnWidth ? '480rpx' : '90rpx' }">
+      <view class="flex1" v-if="openBtnWidth">
+        <view class="btn center" @click="linkToLevel(1)">升</view>
+      </view>
+      <view class="btn center" @click="openBtnWidth = !openBtnWidth">
+        <u-icon name="plus" color="#fff" size="20"></u-icon>
+      </view>
+    </view>
+  </view>
+</template>
+<script>
+  import taskApi from '@/api/task'
+  import userApi from '@/api/system/user'
+  import to from 'await-to-js'
+  import TaskDetails from './components/taskDetails'
+  export default {
+    name: 'omsIndex',
+    components: { TaskDetails },
+    data() {
+      return {
+        openBtnWidth: false,
+        height: '',
+        paddingTop: '',
+        curTabIndex: 0,
+        list: [
+          {
+            name: '详细信息',
+            index: 0,
+          },
+          {
+            name: '进展情况',
+            index: 1,
+          },
+          {
+            name: '联系人',
+            index: 2,
+          },
+        ],
+        taskId: 0, //项目id
+        details: {}, //督办列表
+        taskTypeOption: [], //督办类型
+        sourceOption: [], //来源列表
+        userList: [], //用户列表
+        taskStatusOption: [
+          {
+            key: '10',
+            value: '发起',
+          },
+          {
+            key: '20',
+            value: '进行中',
+          },
+          {
+            key: '30',
+            value: '流程完成',
+          },
+          {
+            key: '40',
+            value: '审批拒绝',
+          },
+          {
+            key: '50',
+            value: '撤销',
+          },
+        ], //督办状态
+      }
+    },
+    onLoad(option) {
+      this.taskId = option.id
+      this.getOptions()
+    },
+    created() {
+      const navData = uni.getMenuButtonBoundingClientRect()
+      this.height = navData.height + 'px'
+      this.paddingTop = navData.top + 'px'
+    },
+    onShow() {
+      this.getOptions()
+    },
+    methods: {
+      // 改变tab
+      changeTabs(data) {
+        this.curTabIndex = data.index
+      },
+      getOptions() {
+        Promise.all([this.getDicts('task_type'), this.getDicts('plat_task_source'), userApi.getList()])
+          .then(([types, source, user]) => {
+            this.taskTypeOption = types.data.values || []
+            this.sourceOption = source.data.values || []
+            this.userList = user.data.list.map((item) => ({ key: '' + item.id, value: item.nickName }))
+            this.getDetails()
+          })
+          .catch((err) => console.log(err))
+      },
+      // 判断是否没有超期
+      isNotOverdue(date) {
+        return new Date() <= new Date(date)
+      },
+      // 协办人
+      generateOwnerUser(ids = null) {
+        let nameArr = []
+        if (ids) {
+          let idList = ids.split(',')
+          console.log(idList)
+          idList.forEach((item) => {
+            let findUser = this.userList.find((user) => user.key == item)
+            console.log(findUser)
+            if (findUser.value) nameArr.push(findUser.value)
+          })
+        }
+        return nameArr.join(',')
+      },
+      async getDetails() {
+        let params = {
+          taskId: this.taskId,
+        }
+        const [err, res] = await to(taskApi.getList(params))
+        if (err) {
+          return
+        }
+        if (res && res.code == 200) {
+          this.details = res.data.list[0] || {}
+        }
+      },
+      goBack() {
+        uni.navigateBack({
+          //关闭当前页面,返回上一页面或多级页面。
+          delta: 1,
+        })
+      },
+    },
+  }
+</script>
+<style>
+  page {
+    background: #f2f3f5;
+  }
+</style>
+<style lang="scss" scoped>
+  .home {
+    padding-top: 200rpx;
+
+    .nav {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 356rpx;
+      background: #3e7ef8;
+      border-radius: 0 0 31rpx 31rpx;
+      .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 - 200rpx);
+      overflow: hidden;
+      padding-bottom: 64rpx;
+      .main-top {
+        padding: 0 32rpx;
+      }
+      .customer-box {
+        width: 100%;
+        background: #ffffff;
+        box-shadow: 0 6rpx 19rpx 2rpx rgba(0, 45, 132, 0.15);
+        border-radius: 32rpx;
+        padding: 22rpx 38rpx 68rpx 40rpx;
+        .header {
+          .name {
+            .img {
+              width: 46rpx;
+              height: 46rpx;
+              border-radius: 50%;
+              margin-right: 8rpx;
+            }
+            text {
+              font-size: 28rpx;
+              font-weight: bold;
+              color: #323232;
+            }
+          }
+          .date {
+            font-size: 24rpx;
+            color: #3e7ef8;
+          }
+        }
+        .info {
+          .info-item {
+            margin-top: 18rpx;
+            .info-label {
+              width: 120rpx;
+              text-align: left;
+              font-size: 24rpx;
+              color: #646464;
+            }
+            .info-txt {
+              flex: 1;
+              font-size: 24rpx;
+              color: #323232;
+            }
+          }
+        }
+      }
+      .data-list {
+        margin-top: 16rpx;
+        width: 100%;
+        height: calc(100vh - 532rpx);
+        background: #ffffff;
+        padding: 32rpx;
+        overflow: auto;
+        padding-bottom: 145rpx;
+      }
+      .details-wrap {
+        background: #f6f7fb;
+        border: 1px solid #ceccca;
+        border-radius: 20rpx;
+        margin-bottom: 32rpx;
+        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
+        .header {
+          padding: 30rpx 30rpx 15rpx;
+          border-bottom: 2rpx solid #ceccca;
+        }
+        .content {
+          padding: 15rpx 30rpx 30rpx;
+        }
+      }
+    }
+    .fixed-btn-group {
+      position: fixed;
+      display: flex;
+      justify-content: space-around;
+      align-items: center;
+      width: 90rpx;
+      height: 90rpx;
+      bottom: 50rpx;
+      right: 50rpx;
+      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+      border-radius: 20px;
+      transition: all 0.2s;
+      background: #fff;
+      .red {
+        background: #ff4d4f !important;
+      }
+      .btn {
+        width: 60rpx;
+        height: 60rpx;
+        background: #3e7ef8;
+        border-radius: 50%;
+        margin: 10rpx;
+        font-size: 26rpx;
+        font-weight: bold;
+        color: #ffffff;
+      }
+    }
+  }
+</style>

+ 280 - 0
pages/schedule/supervise/index.vue

@@ -0,0 +1,280 @@
+<!--
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-02-22 11:11:21
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-03-06 15:47:47
+ * @Description: file content
+ * @FilePath: \oms\pages\schedule\supervise\index.vue
+-->
+<template>
+  <view class="supervise-main">
+    <u-tabs
+      :list="list"
+      @change="changeTabs"
+      :current="curTabIndex - 1"
+      :scrollable="false"
+      :activeStyle="{
+        color: '#323232',
+        fontWeight: 'bold',
+      }"
+      :inactiveStyle="{
+        color: '#969696',
+      }"></u-tabs>
+    <!-- 列表 -->
+    <view class="data-scroll-wrap">
+      <u-empty mode="list" text="暂无督办数据" v-if="taskList.length == 0"></u-empty>
+      <scroll-view v-else class="data-list" :scroll-top="scrollTop" :scroll-y="true" @scrolltolower="lower">
+        <view class="todo-item" v-for="(v, i) in taskList" :key="i" @click="linkToDetail(v)">
+          <u-row>
+            <u-col span="12">
+              <view class="header">
+                <u-text color="#272C36" bold :text="v.taskTitle"></u-text>
+                <view class="flex mt20">
+                  <view class="flex_1">
+                    <u-text color="#272C36" size="26rpx" :text="selectDictLabel(taskTypeOption, v.taskType)"></u-text>
+                  </view>
+                  <view>
+                    <u-text color="#AEB3BB" size="26rpx" :text="parseTime(v.taskStartDate, '{y}-{m}-{d}')"></u-text>
+                  </view>
+                </view>
+              </view>
+              <view class="content">
+                <u-row type="flex" customStyle="padding:10rpx 0">
+                  <u-col :span="3"><u-text text="状态" size="26rpx" color="#AEB3BB"></u-text></u-col>
+                  <u-col :span="9">
+                    <u-text
+                      :text="selectDictLabel(taskStatusOption, v.taskStatus)"
+                      size="26rpx"
+                      color="#272C36"></u-text>
+                  </u-col>
+                </u-row>
+                <u-row type="flex" customStyle="padding:10rpx 0">
+                  <u-col :span="3"><u-text text="督办来源" size="26rpx" color="#AEB3BB"></u-text></u-col>
+                  <u-col :span="9">
+                    <u-text :text="selectDictLabel(sourceOption, v.source)" size="26rpx" color="#272C36"></u-text>
+                  </u-col>
+                </u-row>
+                <u-row type="flex" customStyle="padding:10rpx 0">
+                  <u-col :span="3"><u-text text="是否超期" size="26rpx" color="#AEB3BB"></u-text></u-col>
+                  <u-col :span="9">
+                    <u-text
+                      :text="isNotOverdue(parseTime(v.taskEndDate, '{y}-{m}-{d} 23:59:59')) ? '否' : '是'"
+                      size="26rpx"
+                      color="#272C36"></u-text>
+                  </u-col>
+                </u-row>
+                <u-row type="flex" customStyle="padding:10rpx 0">
+                  <u-col :span="3"><u-text text="督办内容" size="26rpx" color="#AEB3BB"></u-text></u-col>
+                  <u-col :span="9"><u-text :text="v.taskDesc" size="26rpx" color="#272C36"></u-text></u-col>
+                </u-row>
+                <u-row type="flex" customStyle="padding:10rpx 0">
+                  <u-col :span="3"><u-text text="负责人" size="26rpx" color="#AEB3BB"></u-text></u-col>
+                  <u-col :span="9">
+                    <u-text :text="selectDictLabel(userList, v.mainUserId)" size="26rpx" color="#272C36"></u-text>
+                  </u-col>
+                </u-row>
+                <u-row type="flex" customStyle="padding:10rpx 0">
+                  <u-col :span="3"><u-text text="协办人" size="26rpx" color="#AEB3BB"></u-text></u-col>
+                  <u-col :span="9">
+                    <u-text :text="generateOwnerUser(v.ownerUserId)" size="26rpx" color="#272C36"></u-text>
+                  </u-col>
+                </u-row>
+                <u-row type="flex" customStyle="padding:10rpx 0">
+                  <u-col :span="3"><u-text text="监办人" size="26rpx" color="#AEB3BB"></u-text></u-col>
+                  <u-col :span="9">
+                    <u-text :text="selectDictLabel(userList, v.watchUserId)" size="26rpx" color="#272C36"></u-text>
+                  </u-col>
+                </u-row>
+                <u-row type="flex" customStyle="padding:10rpx 0">
+                  <u-col :span="3"><u-text text="督办人" size="26rpx" color="#AEB3BB"></u-text></u-col>
+                  <u-col :span="9">
+                    <u-text :text="selectDictLabel(userList, v.supervisorUserId)" size="26rpx" color="#272C36"></u-text>
+                  </u-col>
+                </u-row>
+              </view>
+            </u-col>
+          </u-row>
+        </view>
+        <u-loadmore :status="loadStatus" />
+      </scroll-view>
+    </view>
+  </view>
+</template>
+
+<script>
+  import taskApi from '@/api/task'
+  import userApi from '@/api/system/user'
+  import to from 'await-to-js'
+  export default {
+    name: 'omsTodo',
+
+    data() {
+      return {
+        curTabIndex: 2, //tabs状态
+        loadStatus: '', //加载状态
+        list: [
+          {
+            name: '我的待办',
+            status: 1,
+          },
+          {
+            name: '我发起的',
+            status: 2,
+          },
+          {
+            name: '我处理的',
+            status: 3,
+          },
+        ],
+        pageNum: 0,
+        pageSize: 10,
+        taskList: [], //督办列表
+        taskTotal: 0, //列表元素数量
+        taskTypeOption: [], //督办类型
+        sourceOption: [], //来源列表
+        userList: [], //用户列表
+        taskStatusOption: [
+          {
+            key: '10',
+            value: '发起',
+          },
+          {
+            key: '20',
+            value: '进行中',
+          },
+          {
+            key: '30',
+            value: '流程完成',
+          },
+          {
+            key: '40',
+            value: '审批拒绝',
+          },
+          {
+            key: '50',
+            value: '撤销',
+          },
+        ], //督办状态
+      }
+    },
+
+    mounted() {
+      this.getOptions()
+    },
+
+    methods: {
+      getOptions() {
+        Promise.all([this.getDicts('task_type'), this.getDicts('plat_task_source'), userApi.getList()])
+          .then(([types, source, user]) => {
+            this.taskTypeOption = types.data.values || []
+            this.sourceOption = source.data.values || []
+            this.userList = user.data.list.map((item) => ({ key: '' + item.id, value: item.nickName }))
+            this.getSuperviseData()
+          })
+          .catch((err) => console.log(err))
+      },
+      // 判断是否没有超期
+      isNotOverdue(date) {
+        return new Date() <= new Date(date)
+      },
+      // 协办人
+      generateOwnerUser(ids = null) {
+        let nameArr = []
+        if (ids) {
+          let idList = ids.split(',')
+          console.log(idList)
+          idList.forEach((item) => {
+            let findUser = this.userList.find((user) => user.key == item)
+            console.log(findUser)
+            if (findUser.value) nameArr.push(findUser.value)
+          })
+        }
+        return nameArr.join(',')
+      },
+      // 上拉滚动
+      lower() {
+        if (this.taskList.length < this.taskTotal && this.loadStatus != 'loading') {
+          this.$u.throttle(this.getSuperviseData(), 2000, false)
+        }
+      },
+      linkToDetail(v) {
+        uni.navigateTo({
+          //保留当前页面,跳转到应用内的某个页面
+          url: '/pages/schedule/supervise/details?id=' + v.id,
+        })
+      },
+      searchList() {
+        this.pageNum = 0
+        this.getSuperviseData(true)
+      },
+      async getSuperviseData(reset) {
+        this.loadStatus = 'loading'
+        this.pageNum++
+        let params = {
+          operateType: '' + this.curTabIndex,
+          pageNum: this.pageNum,
+          pageSize: this.pageSize,
+        }
+        const [err, res] = await to(taskApi.getList(params))
+        if (err) {
+          this.loadStatus = 'nomore'
+          return
+        }
+        if (res && res.code == 200) {
+          if (reset) {
+            this.taskList = res.data.list || []
+          } else {
+            this.taskList = [...this.taskList, ...(res.data.list || [])]
+          }
+          this.taskTotal = res.data.total
+          this.loadStatus = this.taskList.length == this.taskTotal ? 'nomore' : 'loadmore'
+          console.log(this.loadStatus)
+        } else {
+          this.loadStatus = 'nomore'
+        }
+      },
+      // 改变tab
+      changeTabs(data) {
+        console.log(data)
+        this.curTabIndex = data.status
+        this.searchList(true)
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .supervise-main {
+    height: 100%;
+    .data-scroll-wrap {
+      height: calc(100vh - 366rpx);
+      padding: 30rpx 0;
+      .data-list {
+        width: 100%;
+        height: 100%;
+        background: #ffffff;
+        overflow: auto;
+        .todo-item {
+          background: #f6f7fb;
+          border: 1px solid #ceccca;
+          border-radius: 20rpx;
+          margin-bottom: 32rpx;
+          box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
+          .header {
+            padding: 30rpx 30rpx 15rpx;
+            border-bottom: 2rpx solid #ceccca;
+          }
+          .content {
+            padding: 15rpx 30rpx 30rpx;
+          }
+        }
+      }
+    }
+    .mr10 {
+      margin-right: 10rpx;
+    }
+    .mt20 {
+      margin-top: 20rpx;
+    }
+  }
+</style>

BIN
static/images/swiper/banner1.png


BIN
static/images/swiper/banner2.png


BIN
static/images/swiper/banner3.png