Procházet zdrojové kódy

小程序新增快捷审核

yuanmingze před 4 měsíci
rodič
revize
432e3a4ce9

+ 1 - 1
src/pages-sub-admin/serviceManagement/taskList.ts

@@ -27,7 +27,7 @@ export default [
     title: '服务待审核',
     color: '#8E3F3B',
     role: [4],
-    url: '/pages-sub-service-mangement/taskReportapproval/index',
+    url: '/pages-sub-service-mangement/servicesToBeReviewed/index',
     backgroundColor: 'linear-gradient(94.41deg, #FFFCFC -14.28%, #F4E1E0 77.47%);',
     img: 'https://yy-cloud-oss.oss-cn-beijing.aliyuncs.com/img/kcdc.png'
   },

+ 965 - 0
src/pages-sub-service-mangement/servicesToBeReviewed/index.vue

@@ -0,0 +1,965 @@
+<template>
+  <view class="service-reviewed">
+    <view class="reviewed-header">
+      <view class="search-content">
+        <view
+          class="search-list"
+          :class="{ current: searchParams.year }"
+          @click="searchClick('year')"
+        >
+          <text>执行包年度</text>
+          <uv-icon
+            name="arrow-down-fill"
+            :color="searchParams.year ? '#6eb657' : '#000'"
+            size="12"
+          ></uv-icon>
+        </view>
+        <view
+          class="search-list"
+          :class="{ current: searchParams.quarter }"
+          @click="searchClick('quarter')"
+        >
+          <text>执行包季度</text>
+          <uv-icon
+            name="arrow-down-fill"
+            :color="searchParams.quarter ? '#6eb657' : '#000'"
+            size="12"
+          ></uv-icon>
+        </view>
+        <view
+          class="search-list"
+          :class="{ current: searchParams.createTime }"
+          @click="searchClick('createTime')"
+        >
+          <text>服务提交时间</text>
+          <uv-icon
+            name="arrow-down-fill"
+            :color="searchParams.createTime ? '#6eb657' : '#000'"
+            size="12"
+          ></uv-icon>
+        </view>
+        <view
+          class="search-list"
+          :class="{ current: searchParams.taskTypeId }"
+          @click="searchClick('taskTypeId')"
+        >
+          <text>服务类型</text>
+          <uv-icon
+            name="arrow-down-fill"
+            :color="searchParams.taskTypeId ? '#6eb657' : '#000'"
+            size="12"
+          ></uv-icon>
+        </view>
+        <view
+          class="search-list"
+          :class="{ current: searchParams.vendorId }"
+          @click="searchClick('vendorId')"
+        >
+          <text>服务供应商</text>
+          <uv-icon
+            name="arrow-down-fill"
+            :color="searchParams.vendorId ? '#6eb657' : '#000'"
+            size="12"
+          ></uv-icon>
+        </view>
+        <view
+          class="search-list"
+          :class="{ current: searchParams.salesId }"
+          @click="searchClick('salesId')"
+        >
+          <text>代表姓名</text>
+          <uv-icon
+            name="arrow-down-fill"
+            :color="searchParams.salesId ? '#6eb657' : '#000'"
+            size="12"
+          ></uv-icon>
+        </view>
+        <view
+          class="search-list"
+          :class="{ current: searchParams.mahName }"
+          @click="searchClick('mahName')"
+        >
+          <text>产品所属生产企业</text>
+          <uv-icon
+            name="arrow-down-fill"
+            :color="searchParams.mahName ? '#6eb657' : '#000'"
+            size="12"
+          ></uv-icon>
+        </view>
+        <view
+          class="search-list"
+          :class="{ current: searchParams.skuId }"
+          @click="searchClick('skuId')"
+        >
+          <text>关联产品名称</text>
+          <uv-icon
+            name="arrow-down-fill"
+            :color="searchParams.skuId ? '#6eb657' : '#000'"
+            size="12"
+          ></uv-icon>
+        </view>
+        <view
+          class="search-list"
+          :class="{ current: searchParams.provAbbr }"
+          @click="searchClick('provAbbr')"
+        >
+          <text>执行包所属省份</text>
+          <uv-icon
+            name="arrow-down-fill"
+            :color="searchParams.provAbbr ? '#6eb657' : '#000'"
+            size="12"
+          ></uv-icon>
+        </view>
+        <view
+          class="search-list"
+          :class="{ current: searchParams.pkgIds }"
+          @click="searchClick('pkgIds')"
+        >
+          <text>上游服务部名称</text>
+          <uv-icon
+            name="arrow-down-fill"
+            :color="searchParams.pkgIds ? '#6eb657' : '#000'"
+            size="12"
+          ></uv-icon>
+        </view>
+      </view>
+      <view class="clear" @click="clearSearch">
+        <uv-icon name="close-circle" color="#000" size="24"></uv-icon>
+      </view>
+    </view>
+    <!-- 审核 -->
+    <view class="review-title">
+      <checkbox-group @change="checkboxAllChange">
+        <label>
+          <checkbox :checked="checkedAll" style="transform: scale(0.8)" color="#6eb657" />全选
+        </label>
+      </checkbox-group>
+      <view class="r-review" @click="allCheckedReview">
+        <uv-icon size="20" name="share-square" color="#6eb657"></uv-icon>
+        <text>批量审核</text>
+      </view>
+    </view>
+    <view class="list" v-if="hasInfo" :class="{ hidden: showRef }">
+      <view class="item" v-for="(item, index) in dataList" :key="item.id">
+        <view class="top">
+          <view class="checked" @click.stop.prevent>
+            <checkbox-group @change="itemChecked(item)">
+              <label>
+                <checkbox
+                  :checked="item.checked"
+                  style="transform: scale(0.8)"
+                  :disabled="false"
+                  backgroundColor="#fff"
+                />
+              </label>
+            </checkbox-group>
+          </view>
+          <view class="top-l">
+            <image src="@/static/images/icon/review.png" class="image" />
+            <text>{{ item.createTime }}</text>
+          </view>
+        </view>
+        <view class="content" @click="onDetail(item)">
+          <view class="title">
+            <view class="task-name">{{ getTaskName(item) }}</view>
+            <view class="score">+{{ item.taskScore }}积分</view>
+          </view>
+          <view class="item-detail">
+            <view class="num"> 任务编号:{{ item.taskNumber }} </view>
+          </view>
+        </view>
+      </view>
+    </view>
+    <noData v-else />
+
+    <!-- 选择器内容 -->
+    <uv-datetime-picker
+      ref="datetimeRef"
+      :mode="datetimePickerMode"
+      @confirm="confirm"
+    ></uv-datetime-picker>
+    <!-- 内容选择器 -->
+    <uv-action-sheet ref="actionSheetRef" :actions="list" @select="confirm"> </uv-action-sheet>
+
+    <!--  -->
+    <uv-picker
+      ref="pickerRef"
+      :columns="[pickerColumns]"
+      :keyName="pickerLabel"
+      @confirm="confirm"
+    ></uv-picker>
+
+    <uv-popup
+      ref="popupRef"
+      mode="center"
+      :close-on-click-overlay="false"
+      round="16"
+      :safeAreaInsetBottom="false"
+      @change="popupChange"
+    >
+      <view class="pretreatment">
+        <view class="title">批量审核预处理结果</view>
+        <view class="tips">
+          本次批量审核,拟处理服务 【{{ pretreatmentInfo?.total?.length }}】 个, 成功预留【{{
+            pretreatmentInfo?.available?.length
+          }}】个,忽略【{{ pretreatmentInfo?.locked?.length }}】个,
+          继续审核请点击“确定”,放弃请点击“取消”(有效期三分钟)。
+        </view>
+        <view class="table">
+          <uni-table border stripe emptyText="暂无更多数据">
+            <!-- 表头行 -->
+            <uni-tr>
+              <uni-th align="center" width="50">任务ID</uni-th>
+              <uni-th align="center">预留结果</uni-th>
+              <uni-th align="center">结果说明</uni-th>
+              <uni-th align="center">锁定至</uni-th>
+            </uni-tr>
+            <uni-tr v-for="(item, index) in pretreatmentInfo?.total" :key="item?.taskTypeId" index>
+              <uni-td>{{ item.taskId }}</uni-td>
+              <uni-td>
+                <text :class="item.status === '成功' ? 'status-success' : 'status-fail'">{{
+                  item.status
+                }}</text>
+              </uni-td>
+              <uni-td>{{ item.lockInfo }}</uni-td>
+              <uni-td>{{ item.expireAt }}</uni-td>
+            </uni-tr>
+          </uni-table>
+        </view>
+        <view class="btns">
+          <view class="colse" @click="lockedDialogClose">取消</view>
+          <view class="confirm" @click="lockedBtn">确认</view>
+        </view>
+      </view>
+    </uv-popup>
+
+    <uv-popup
+      ref="reviewFormRef"
+      mode="center"
+      :close-on-click-overlay="false"
+      round="16"
+      :safeAreaInsetBottom="false"
+      @change="popupChange"
+    >
+      <view class="pretreatment">
+        <view class="title">审核</view>
+        <view class="tips">
+          审核令牌有效期为3分钟,请在【{{ expireTime }}】前完成审核操作,如果失效,请重新提交。
+        </view>
+        <view class="form">
+          <uv-form labelPosition="left" :model="reviewForm" ref="form" labelWidth="80">
+            <uv-form-item label="审批意见:" prop="reviewForm.checkResult" borderBottom>
+              <uv-radio-group v-model="reviewForm.checkResult">
+                <uv-radio label="通过" :name="true" activeColor="#72b25b"> </uv-radio>
+                <text class="margin"></text>
+                <uv-radio label="拒绝" :name="false" activeColor="#72b25b"> </uv-radio>
+              </uv-radio-group>
+            </uv-form-item>
+            <uv-form-item label="意见说明:" prop="reviewForm.checkMessage" borderBottom>
+              <uv-textarea v-model="reviewForm.checkMessage"> </uv-textarea>
+            </uv-form-item>
+          </uv-form>
+        </view>
+        <view class="btns">
+          <view class="colse" @click="handleClose">取消</view>
+          <view class="confirm" @click="checkBtn">确认</view>
+        </view>
+      </view>
+    </uv-popup>
+  </view>
+</template>
+
+<script setup lang="ts">
+import {
+  getTaskV2PageApi,
+  getTaskTypeAvailApi,
+  getDeptv2Avail,
+  getUserV2Avail,
+  getDrug2Avail,
+  getPkgV2Api,
+  getPretreatmentApi,
+  pretreatmentClearApi,
+  getTaskV2TokenApi,
+  taskV2CheckBatchApi
+} from '@/service/modules/serviceReviewed'
+import { onShow } from '@dcloudio/uni-app'
+
+import abbreviationsProvinces from '@/utils/abbreviationsProvinces'
+import { getDictByNameApi } from '@/service/modules/getDict'
+import dayjs from 'dayjs'
+import { ref, reactive, onMounted } from 'vue'
+import { onReachBottom } from '@dcloudio/uni-app'
+import noData from '@/components/noData/index.vue'
+import { useLoginStore } from '@/store/login'
+
+const loginStore = useLoginStore()
+
+const params = reactive({
+  nodeId: '',
+  currentPage: 1,
+  pageSize: 20,
+  total: 0
+})
+
+const hasInfo = ref(true)
+const dataList = ref<any[]>([])
+
+const dict = reactive({
+  taskTypeAvailArr: [],
+  deptListArr: [],
+  userListArr: [],
+  mahNameArr: [],
+  drugListArr: [],
+  currDrugList: [],
+  relPkgNameArr: [] as any[]
+})
+
+const getDictFn = () => {
+  getTaskTypeAvailApi().then((res) => (dict.taskTypeAvailArr = res.data))
+  getDeptv2Avail().then((res) => (dict.deptListArr = res.data))
+  getUserV2Avail().then((res) => (dict.userListArr = res.data))
+  getDictByNameApi('mah_name').then((res: any) => (dict.mahNameArr = res.data))
+  getDrug2Avail().then((res: any) => (dict.drugListArr = res.data))
+  getPkgV2Api().then((res) => {
+    let arr: any[] = []
+    let data = res.data
+    for (let key in data) {
+      let obj = {
+        label: key,
+        value: data[key]
+      }
+      arr.push(obj)
+    }
+    dict.relPkgNameArr = arr
+  })
+}
+const getDatalist = async () => {
+  const obj = Object.assign({
+    current: params.currentPage,
+    size: params.pageSize,
+    taskStatus: 3,
+    nodeId: params.nodeId,
+    ...searchParams.value
+  })
+  uni.showLoading({
+    title: '正在获取数据'
+  })
+  const res = await getTaskV2PageApi(obj)
+  if (res.code === 0) {
+    params.total = res.data.total
+    res?.data?.records?.forEach((item: any) => {
+      item.checked = false
+    })
+    dataList.value = dataList.value.concat(res.data.records)
+
+    hasInfo.value = !!dataList.value.length
+    uni.hideLoading()
+  }
+  uni.hideLoading()
+}
+
+const checkedAll = ref(false)
+const checkboxAllChange = () => {
+  checkedAll.value = !checkedAll.value
+
+  dataList.value.forEach((item) => (item.checked = checkedAll.value))
+  if (checkedAll.value) {
+    checkdIds.value = dataList.value.map((item) => item.taskId)
+  } else {
+    checkdIds.value = []
+  }
+}
+
+const checkdIds = ref<any[]>([])
+
+const itemChecked = (item: any) => {
+  item.checked = !item.checked
+  let arr = dataList.value.filter((item) => item.checked)
+  checkdIds.value = arr?.map((item) => item.taskId)
+}
+const allCheckedReview = () => {
+  if (!checkdIds.value.length) {
+    return uni.showToast({
+      title: '请选择审核项',
+      icon: 'none'
+    })
+  }
+  getPretreatment()
+}
+
+const pretreatmentInfo = ref()
+const lockedInfo = ref()
+
+const getPretreatment = async () => {
+  const res = await getPretreatmentApi({
+    taskIds: checkdIds.value,
+    nodeId: checkNodeId.value
+  })
+  if (res.code === 0) {
+    pretreatmentInfo.value = res.data
+    lockedInfo.value = res.data.locked
+  }
+  popupRef.value.open()
+}
+
+const showRef = ref(false)
+const popupChange = (e) => {
+  showRef.value = e.show
+}
+
+const lockedDialogClose = async () => {
+  const taskIds = pretreatmentInfo.value.available.map((item) => item.taskId)
+  if (pretreatmentInfo.value?.token?.token) {
+    const obj = {
+      taskIds,
+      token: pretreatmentInfo.value?.token?.token,
+      nodeId: checkNodeId.value
+    }
+    await pretreatmentClearApi(obj)
+  }
+  popupRef.value.close()
+  init()
+  lockedInfo.value = []
+  checkdIds.value = []
+  checkedAll.value = false
+}
+const lockedBtn = async () => {
+  if (pretreatmentInfo.value.available.length) {
+    popupRef.value.close()
+    lockedInfo.value = []
+    getToken()
+  } else {
+    uni.showToast({
+      title: '当前无可审核数据!',
+      icon: 'none'
+    })
+    popupRef.value.close()
+  }
+}
+
+const handleClose = () => {
+  reviewFormRef.value.close()
+  init()
+}
+
+const checkBtn = async () => {
+  if (!reviewForm.checkResult && !reviewForm.checkMessage) {
+    return uni.showToast({
+      title: '请完善审核表单',
+      icon: 'none'
+    })
+  }
+  const ids = pretreatmentInfo.value?.available?.map((item) => item.taskId)
+  let obj = {
+    token: token.value,
+    taskIds: ids,
+    checkResult: reviewForm.checkResult,
+    checkMessage: reviewForm.checkMessage,
+    nodeId: checkNodeId.value
+  }
+  try {
+    const res = await taskV2CheckBatchApi(obj)
+    if (res.code === 0) {
+      uni.showToast({
+        title: '审核成功',
+        icon: 'none'
+      })
+      handleClose()
+    }
+  } catch (err) {
+    console.log('err', err)
+  }
+}
+
+const token = ref('')
+const expireTime = ref('')
+
+const reviewFormRef = ref()
+
+const reviewForm = reactive({
+  checkResult: '',
+  checkMessage: ''
+})
+const getToken = async () => {
+  const res = await getTaskV2TokenApi({ taskIds: checkdIds.value })
+  if (res.code === 0) {
+    token.value = res.data.token
+    expireTime.value = res.data.expireTime
+    reviewFormRef.value.open()
+  } else {
+    uni.showToast({
+      title: '获取token失败',
+      icon: 'none'
+    })
+  }
+}
+
+const onDetail = (row: any) => {
+  uni.navigateTo({
+    url: `/pages-sub-service-mangement/taskAuditDetail/index?id=${row.taskId}&type=1&show=true`
+  })
+}
+const getTaskName = (row: any) => {
+  const taskTypeId = row.taskTypeId
+  const curr: any = dict.taskTypeAvailArr.find((iten: any) => iten.id === taskTypeId)
+  return curr ? curr.name : ''
+}
+
+const popupRef = ref()
+
+class SearchParams {
+  year = ''
+  quarter = ''
+  createTime = ''
+  taskTypeId = ''
+  vendorId = ''
+  salesId = ''
+  mahName = ''
+  skuId = ''
+  provAbbr = ''
+  pkgIds = ''
+}
+
+const searchParams = ref(new SearchParams())
+
+const clearSearch = () => {
+  searchParams.value = new SearchParams()
+  const lastYear = dayjs().subtract(1, 'year').format('YYYY')
+  searchParams.value.year = lastYear
+  init()
+}
+
+const currType = ref('')
+const datetimeRef = ref()
+const datetimePickerMode = ref('')
+
+const list = ref<any[]>([])
+
+let quarterList = [
+  { name: '第一季度', value: '1' },
+  { name: '第二季度', value: '2' },
+  { name: '第三季度', value: '3' },
+  { name: '第四季度', value: '4' }
+]
+
+const actionSheetRef = ref()
+
+const pickerRef = ref()
+const pickerColumns = ref<any[]>([])
+const pickerLabel = ref('')
+const searchClick = (type: string) => {
+  currType.value = type
+  switch (type) {
+    case 'year':
+      datetimePickerMode.value = 'year'
+      datetimeRef.value.open()
+      break
+    case 'quarter':
+      list.value = quarterList
+      actionSheetRef.value.open()
+      break
+    case 'createTime':
+      datetimePickerMode.value = 'date'
+      datetimeRef.value.open()
+      break
+    case 'taskTypeId':
+      pickerColumns.value = dict.taskTypeAvailArr
+      pickerLabel.value = 'name'
+      pickerRef.value.open()
+      break
+    case 'vendorId':
+      pickerColumns.value = dict.deptListArr
+      pickerLabel.value = 'name'
+      pickerRef.value.open()
+      break
+    case 'salesId':
+      pickerColumns.value = dict.userListArr
+      pickerLabel.value = 'realName'
+      pickerRef.value.open()
+      break
+    case 'mahName':
+      pickerColumns.value = dict.mahNameArr
+      pickerLabel.value = 'label'
+      pickerRef.value.open()
+      break
+
+    case 'skuId':
+      // 选择关联产品 需要先选择生产企业
+      const name = searchParams.value.mahName
+      if (!name) {
+        return uni.showToast({
+          title: '请先选择生产企业',
+          icon: 'none'
+        })
+      }
+      const currList = dict.drugListArr[name]
+      dict.currDrugList = currList
+      pickerColumns.value = dict.currDrugList
+      pickerLabel.value = 'drugName'
+      pickerRef.value.open()
+      break
+    case 'provAbbr':
+      pickerColumns.value = abbreviationsProvinces
+      pickerRef.value.open()
+      break
+    case 'pkgIds':
+      pickerColumns.value = dict.relPkgNameArr
+      pickerLabel.value = 'label'
+      pickerRef.value.open()
+      break
+
+    default:
+      break
+  }
+}
+
+const confirm = (e: any) => {
+  switch (currType.value) {
+    case 'year':
+      searchParams.value.year = dayjs(e.value).format('YYYY')
+      break
+    case 'quarter':
+      searchParams.value.quarter = e.value
+      break
+    case 'createTime':
+      searchParams.value.createTime = dayjs(e.value).format('YYYY-MM-DD')
+      break
+    case 'taskTypeId':
+      searchParams.value.taskTypeId = e?.value[0]?.id
+      break
+    case 'vendorId':
+      searchParams.value.vendorId = e?.value[0]?.entId
+      break
+    case 'salesId':
+      searchParams.value.salesId = e?.value[0]?.userId
+      break
+    case 'mahName':
+      searchParams.value.mahName = e?.value[0]?.value
+      break
+    case 'skuId':
+      searchParams.value.skuId = e?.value[0]?.id
+      break
+    case 'provAbbr':
+      searchParams.value.provAbbr = e?.value[0]
+      break
+    case 'pkgIds':
+      searchParams.value.pkgIds = e?.value[0]
+      break
+    default:
+      break
+  }
+  init()
+}
+
+const init = () => {
+  params.currentPage = 1
+  params.total = 0
+  dataList.value = []
+  checkedAll.value = false
+  checkdIds.value = []
+
+  reviewForm.checkMessage = ''
+  reviewForm.checkResult = ''
+
+  getDatalist()
+}
+
+onReachBottom(() => {
+  if (dataList.value.length === params.total) return
+  params.currentPage++
+  getDatalist()
+})
+
+const checkNodeId = ref()
+onShow(async () => {
+  const lastYear = dayjs().subtract(1, 'year').format('YYYY')
+  searchParams.value.year = lastYear
+  await getDictFn()
+
+  let userInfo: any = loginStore.currentUserInfo
+  const roles: number[] = userInfo?.roles || []
+
+  let nodeId: any = ''
+  switch (true) {
+    // 43	地市管理员
+    case roles.includes(43):
+      nodeId = 1
+      checkNodeId.value = 2
+      break
+    // 4	区域管理员
+    case roles.includes(4):
+      nodeId = 2
+      checkNodeId.value = 3
+      break
+    // 42	市场管理员: 获取审核节点为3和9   nodeid为12
+    case roles.includes(42):
+      nodeId = 12
+      checkNodeId.value = 8
+      break
+
+    // 40	商务管理员: 获取审核节点为3和8   nodeid为11
+    case roles.includes(40):
+      nodeId = 11
+      checkNodeId.value = 9
+      break
+    case roles.includes(41) && roles.includes(39):
+      nodeId = 24
+      break
+    // 41	事业部分管领导
+    case roles.includes(41):
+      nodeId = 9
+      checkNodeId.value = 5
+      break
+    // 39	事业部总经理
+    case roles.includes(39):
+      nodeId = 15
+      checkNodeId.value = 6
+      break
+    default:
+      nodeId = 1
+  }
+
+  params.nodeId = nodeId
+
+  init()
+})
+</script>
+
+<style lang="scss" scoped>
+.service-reviewed {
+  padding: 0 30rpx;
+  .reviewed-header {
+    width: 690rpx;
+    height: 80rpx;
+    margin-bottom: 30rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    background-color: #fff;
+    position: fixed;
+    top: 0;
+    z-index: 999;
+
+    .search-content {
+      width: 630rpx;
+      overflow-x: auto;
+      display: flex;
+      flex-wrap: nowrap;
+
+      .search-list {
+        flex: none;
+        flex-shrink: 0;
+        display: flex;
+        align-items: center;
+        padding-right: 20rpx;
+        line-height: 80rpx;
+        text {
+          margin-right: 6rpx;
+          font-weight: 600;
+        }
+      }
+      .current {
+        color: #6eb657;
+      }
+    }
+    .clear {
+      display: flex;
+      justify-content: right;
+    }
+  }
+
+  .review-title {
+    margin-top: 100rpx;
+  }
+
+  .r-review {
+    display: flex;
+    align-items: center;
+    color: #6eb657;
+    text {
+      margin-left: 10rpx;
+    }
+  }
+  .list {
+    margin-top: 30rpx;
+    .item {
+      box-shadow: 0px 4rpx 4rpx 0px rgba(0, 0, 0, 0.05);
+      margin-bottom: 20rpx;
+      border-radius: 16rpx;
+      .top {
+        padding: 0 30rpx;
+        box-sizing: border-box;
+        height: 100rpx;
+        background-color: #6eb657;
+        border-top-left-radius: 16rpx;
+        border-top-right-radius: 16rpx;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        .top-l {
+          display: flex;
+          align-items: center;
+
+          .image {
+            width: 28rpx;
+            height: 28rpx;
+          }
+          text {
+            font-size: 26rpx;
+            color: #fff;
+            line-height: 36rpx;
+            margin-left: 20rpx;
+          }
+        }
+        .top-r {
+          display: flex;
+          align-items: center;
+          text {
+            display: block;
+            width: 10rpx;
+            height: 10rpx;
+            background-color: #fff;
+            border-radius: 50%;
+            margin-right: 10rpx;
+          }
+          .status {
+            color: #fff;
+            font-size: 28rpx;
+            line-height: 40rpx;
+          }
+        }
+      }
+      .content {
+        background-color: #fff;
+        padding: 30rpx;
+        box-sizing: border-box;
+        .title {
+          display: flex;
+          justify-content: space-between;
+          margin-bottom: 20rpx;
+          align-items: center;
+          .task-name {
+            font-size: 32rpx;
+            line-height: 45rpx;
+            color: #313131;
+          }
+          .score {
+            font-size: 28rpx;
+            color: #72b25b;
+          }
+        }
+        .item-detail {
+          display: flex;
+          justify-content: space-between;
+          .num {
+            font-weight: 400;
+            font-size: 20rpx;
+            line-height: 32rpx;
+            color: #999999;
+          }
+        }
+      }
+    }
+  }
+}
+
+.history {
+  width: 630rpx;
+  margin: 0 auto;
+  padding: 0 30rpx;
+
+  .header {
+    text-align: center;
+    line-height: 105rpx;
+    font-size: 36rpx;
+    font-weight: 600;
+  }
+  .his-list {
+    height: 70vh;
+    overflow-y: auto;
+
+    .his-item {
+      padding: 15rpx 0;
+      border-bottom: 1px solid #eee;
+      .his-text {
+        line-height: 36rpx;
+        font-size: 22rpx;
+        text {
+          color: #333;
+        }
+        .label {
+          color: #000;
+          font-weight: 6000;
+        }
+      }
+    }
+  }
+}
+
+.review-title {
+  margin: 30rpx 0;
+  display: flex;
+  justify-content: space-between;
+}
+
+.pretreatment {
+  width: 690rpx;
+  padding: 30rpx;
+  box-sizing: border-box;
+
+  .title {
+    text-align: center;
+    font-weight: 700;
+    font-size: 36rpx;
+    line-height: 60rpx;
+  }
+  .tips {
+    color: rgb(233 77 77);
+    font-size: 28rpx;
+    line-height: 32rpx;
+  }
+  .table {
+    margin-top: 20rpx;
+    max-height: 60vh;
+    overflow-y: auto;
+  }
+  .form {
+    margin-top: 20rpx;
+  }
+  .btns {
+    display: flex;
+    justify-content: space-between;
+    margin-top: 30rpx;
+
+    view {
+      width: 260rpx;
+      line-height: 80rpx;
+      font-size: 28rpx;
+      text-align: center;
+      border-radius: 45rpx;
+      border: 1px solid #999;
+    }
+    .colse {
+      color: #999;
+    }
+    .confirm {
+      background-color: #72b25b;
+      border: none;
+      color: #fff;
+    }
+  }
+}
+.status-success {
+  color: #85ce61;
+}
+.status-fail {
+  color: rgb(233 77 77);
+}
+.hidden {
+  height: 85vh !important;
+  overflow-y: hidden !important;
+}
+.margin {
+  margin-right: 30rpx;
+}
+</style>

+ 65 - 57
src/pages-sub-service-mangement/taskAuditDetail/index.vue

@@ -47,13 +47,7 @@
 
     <view class="review-btn botton-content" v-if="showBtn">
       <view class="review-form">
-        <uv-form
-          labelPosition="left"
-          :model="reviewForm"
-          :rules="reviewFormRules"
-          ref="reviewFormRef"
-          labelWidth="80"
-        >
+        <uv-form labelPosition="left" :model="reviewForm" ref="reviewFormRef" labelWidth="80">
           <uv-form-item label="审核说明" prop="taskStatusInfo" borderBottom required>
             <uv-textarea
               v-model="reviewForm.taskStatusInfo"
@@ -64,8 +58,8 @@
         </uv-form>
       </view>
       <view class="btn">
-        <view class="cancel" @click="reviewFn('4')">拒绝</view>
-        <view class="confirm" @click="reviewFn('3')">通过</view>
+        <view class="cancel" @click="reviewFn(false)">拒绝</view>
+        <view class="confirm" @click="reviewFn(true)">通过</view>
       </view>
     </view>
   </view>
@@ -79,7 +73,8 @@ import {
   getSignInfoByTaskIdApi,
   getQrCodeByUrlApi
 } from '@/service/modules/getTask'
-import { approvalTaskApi, approvalReportApi } from '@/service/modules/taskAudit'
+
+import { getTaskV2TokenApi, checkSingleApi } from '@/service/modules/serviceReviewed'
 
 import { onLoad } from '@dcloudio/uni-app'
 import { reactive, ref } from 'vue'
@@ -96,7 +91,6 @@ import { useLoginStore } from '@/store/login'
 
 const loginStore = useLoginStore()
 let userInfo: any = loginStore.currentUserInfo
-const roles: number[] = userInfo.roles
 
 const reviewStore = useReview()
 // 文本展示类型
@@ -133,24 +127,26 @@ onLoad((e) => {
   reviewStore.setCurrentInfo('')
 
   if (e?.show === 'true') {
-    if (roles.includes(currentInfo.value.checkState.roleId)) {
-      showBtn.value = true
-    }
-
-    if ((roles.includes(40) || roles.includes(42)) && currentInfo.value.checkState.roleId == -1) {
-      showBtn.value = true
-    }
-    if (roles.includes(39) && currentInfo.value.checkState.nextNodeId == -1) {
-      showBtn.value = false
-    }
+    showBtn.value = true
   }
 
   if (e?.id) {
     detailId.value = e.id
     getTaskDetail()
+    getToken()
   }
 })
 
+const token = ref('')
+const getToken = async () => {
+  const res = await getTaskV2TokenApi({
+    taskIds: [detailId.value]
+  })
+  if (res.code === 0) {
+    token.value = res.data.token
+  }
+}
+
 const detailInfo = ref()
 const taskTypeId = ref()
 const isShareImg = ref(false)
@@ -234,48 +230,60 @@ const reviewFormRef = ref()
 const reviewForm = reactive({
   taskStatusInfo: ''
 })
-const reviewFormRules = reactive({
-  taskStatusInfo: {
-    type: 'string',
-    required: true,
-    message: '请输入审核说明',
-    trigger: ['blur', 'change']
-  }
-})
 
-const reviewFn = (flag: string) => {
+const reviewFn = (flag: boolean) => {
+  if (!flag && !reviewForm.taskStatusInfo) {
+    return uni.showToast({
+      title: '请输入审核说明',
+      icon: 'none'
+    })
+  }
   reviewFormRef.value
     .validate()
     .then(async () => {
-      let obj: any = {}
-      let res
-      if (currentType.value === '1') {
-        obj = {
-          id: detailId.value,
-          taskStatus: flag,
-          taskStatusInfo: reviewForm.taskStatusInfo,
-          nodeId: currentInfo.value?.checkState.curNodeId
-        }
-        res = await approvalTaskApi(obj)
-      } else if (currentType.value === '2') {
-        obj = {
-          id: currentReportId.value,
-          taskIds: detailId.value,
-          approvalOpinion: flag == '3' ? '1' : '2',
-          approvalInfo: reviewForm.taskStatusInfo,
-          taskStatusInfo: reviewForm.taskStatusInfo,
-          nodeId: currentInfo.value?.checkState.nextNodeId
-        }
-        if (roles.includes(42)) {
-          obj.nodeId = 8
-        }
-        // 40 商务组
-        if (roles.includes(40)) {
-          obj.nodeId = 9
-        }
-        res = await approvalReportApi(obj)
+      let userInfo: any = loginStore.currentUserInfo
+      const roles: number[] = userInfo?.roles || []
+
+      let nodeId: any = ''
+      switch (true) {
+        // 43	地市管理员
+        case roles.includes(43):
+          nodeId = 2
+          break
+        // 4	区域管理员
+        case roles.includes(4):
+          nodeId = 3
+          break
+        // 42	市场管理员
+        case roles.includes(42):
+          nodeId = 8
+          break
+        // 40	商务管理员
+        case roles.includes(40):
+          nodeId = 9
+          break
+        // 39	事业部总经理
+        case roles.includes(39):
+          nodeId = 6
+          break
+        // 41	事业部分管领导
+        case roles.includes(41):
+          nodeId = 5
+          break
+        default:
+          nodeId = 1
+      }
+
+      let obj: any = {
+        token: token.value,
+        taskId: detailId.value,
+        checkResult: flag,
+        checkMessage: reviewForm.taskStatusInfo,
+        nodeId: nodeId
       }
 
+      let res = await checkSingleApi(obj)
+      console.log('res', res)
       if (res.code === 0) {
         uni.showToast({
           title: '审核成功',

+ 2 - 2
src/pages-sub-service-mangement/taskManagement/index.vue

@@ -59,12 +59,12 @@
             <text>{{ item.finishRate }}%</text>
           </view>
           <view class="txt">{{ item.ysh }}/{{ item.score }}</view>
-          <view class="btns">
+          <!-- <view class="btns">
             <view class="btn" @click.stop.prevent.self="generateReportFn(item)">
               <image src="@/static/images/icon/review-img2.png" class="image" />
               <text>生成报告</text>
             </view>
-          </view>
+          </view> -->
         </view>
       </view>
     </view>

+ 7 - 0
src/pages.json

@@ -513,6 +513,13 @@
             "navigationBarBackgroundColor": "#fff"
           }
         },
+        {
+          "path": "servicesToBeReviewed/index",
+          "style": {
+            "navigationBarTitleText": "服务待审核",
+            "onReachBottomDistance": 200
+          }
+        },
         {
           "path": "serviceReviewed/index",
           "style": {

+ 23 - 0
src/service/modules/serviceReviewed.ts

@@ -1,5 +1,8 @@
 import http from '@/service'
 
+export function getTaskV2PageApi(params: any) {
+  return http.get('/admin/task/v2/page', { params })
+}
 export function getTaskV2PageCheckedApi(params: any) {
   return http.get('/admin/task/v2/page/checked', { params })
 }
@@ -27,3 +30,23 @@ export function getDrug2Avail(params?: any) {
 export function getPkgV2Api(params?: any) {
   return http.get('/admin/pkg/avail', { params })
 }
+
+export function getTaskV2TokenApi(data?: any) {
+  return http.post('/admin/task/v2/token', data)
+}
+
+export function checkSingleApi(data?: any) {
+  return http.post('/admin/task/v2/check/single', data)
+}
+
+export function getPretreatmentApi(data?: any) {
+  return http.post('/admin/task/v2/check/pretreatment', data)
+}
+
+export function pretreatmentClearApi(data?: any) {
+  return http.post('/admin/task/v2/check/pretreatment/clear', data)
+}
+
+export function taskV2CheckBatchApi(data?: any) {
+  return http.post('/admin/task/v2/check/batch', data)
+}