Kaynağa Gözat

feature:送样和预约按钮增加权限控制

liuzhenlin 2 hafta önce
ebeveyn
işleme
2892f8a257
1 değiştirilmiş dosya ile 450 ekleme ve 541 silme
  1. 450 541
      src/view/instr/detail.vue

+ 450 - 541
src/view/instr/detail.vue

@@ -8,21 +8,11 @@
 -->
 <template>
   <div class="instr-detail">
-    <van-swipe
-      v-if="noticeInfo.noticeTitle"
-      class="my-swipe"
-      :autoplay="5000"
-      :show-indicators="false"
-      vertical
-      height="30"
-    >
+    <van-swipe v-if="noticeInfo.noticeTitle" class="my-swipe" :autoplay="5000" :show-indicators="false" vertical
+      height="30">
       <van-swipe-item @click="state.popupShow = true">
         <div class="flex">
-          <van-icon
-            name="volume-o"
-            class="mr4"
-            :size="20"
-          />
+          <van-icon name="volume-o" class="mr4" :size="20" />
           {{ noticeInfo.noticeTitle }}
         </div>
       </van-swipe-item>
@@ -30,11 +20,7 @@
     <header class="flex">
       <div class="h100">
         <!-- <img :showLoading="true" :src="state.instDetail.instPicture" width="80px" height="80px" /> -->
-        <van-image
-          width="80px"
-          height="80px"
-          :src="getImageUrl(state.instDetail.instPicture)"
-        />
+        <van-image width="80px" height="80px" :src="getImageUrl(state.instDetail.instPicture)" />
       </div>
       <div class="i-right ml10">
         <div class="h100 flex flex-top flex-column flex-between">
@@ -43,19 +29,11 @@
           </div>
           <footer>
             <div class="flex flex-top mb4 mt-auto">
-              <img
-                class="i-r-icon"
-                src="../../assets/img/user.png"
-                v-if="state.instDetail.instHeadName"
-              />
+              <img class="i-r-icon" src="../../assets/img/user.png" v-if="state.instDetail.instHeadName" />
               <div class="detailTxt">{{ state.instDetail.instHeadName }}</div>
             </div>
             <div class="flex flex-top">
-              <img
-                class="i-r-icon"
-                src="../../assets/img/address.png"
-                v-if="state.instDetail.placeAddress"
-              />
+              <img class="i-r-icon" src="../../assets/img/address.png" v-if="state.instDetail.placeAddress" />
               <div class="detailTxt">
                 {{ state.instDetail.placeAddress + setLaboratoryName(state.instDetail.laboratoryName) }}
               </div>
@@ -64,27 +42,12 @@
         </div>
       </div>
     </header>
-    <van-tabs
-      v-model:active="active"
-      @change="tabChange"
-    >
-      <van-tab
-        title="仪器信息"
-        name="info"
-      ></van-tab>
-      <van-tab
-        title="待审核"
-        name="approval"
-      ></van-tab>
-      <van-tab
-        title="历史申请"
-        name="history"
-      ></van-tab>
+    <van-tabs v-model:active="active" @change="tabChange">
+      <van-tab title="仪器信息" name="info"></van-tab>
+      <van-tab title="待审核" name="approval"></van-tab>
+      <van-tab title="历史申请" name="history"></van-tab>
     </van-tabs>
-    <div
-      v-if="active === 'info'"
-      class="content"
-    >
+    <div v-if="active === 'info'" class="content">
       <div class="card">
         <h4>仪器信息</h4>
         <ul>
@@ -130,18 +93,10 @@
         <h4>主要功能</h4>
         <div class="text">{{ state.instDetail.instFunctFeat }}</div>
       </div>
-      <div
-        class="card"
-        v-if="isNeedGrant"
-        @click="applicationAuth"
-      >
+      <div class="card" v-if="isNeedGrant" @click="applicationAuth">
         <h4>资质申请</h4>
       </div>
-      <div
-        class="card"
-        v-if="isNeedGrant"
-        @click="applyTraining"
-      >
+      <div class="card" v-if="isNeedGrant" @click="applyTraining">
         <h4>培训申请</h4>
       </div>
       <!-- <div class="card">
@@ -151,81 +106,42 @@
                 <a href="javascript: void(0);" @click="realDown(item.docName, item.docUrl)">{{ item.docName }}</a>
               </div>
             </template>
-          </div> -->
+</div> -->
     </div>
-    <van-list
-      v-else
-      v-model:loading="state.loading"
-      :finished="state.finished"
-      finished-text="没有更多了"
-      @load="onLoad"
-    >
-      <van-cell
-        v-for="item in state.list"
-        :key="item.id"
-      >
+    <van-list v-else v-model:loading="state.loading" :finished="state.finished" finished-text="没有更多了" @load="onLoad">
+      <van-cell v-for="item in state.list" :key="item.id">
         <template #default>
           <div class="list">
             <header class="flex justify-between">
               <strong class="title">{{ item.userName }}的预约</strong>
-              <van-tag
-                v-if="item.appointStatus == '10'"
-                type="default"
-              >
+              <van-tag v-if="item.appointStatus == '10'" type="default">
                 待审核
               </van-tag>
-              <van-tag
-                v-else-if="item.appointStatus == '11'"
-                type="warning"
-              >
+              <van-tag v-else-if="item.appointStatus == '11'" type="warning">
                 已退回
               </van-tag>
-              <van-tag
-                v-else-if="item.appointStatus == '20'"
-                type="success"
-              >
+              <van-tag v-else-if="item.appointStatus == '20'" type="success">
                 已通过
               </van-tag>
-              <van-tag
-                v-else-if="item.appointStatus == '30'"
-                type="danger"
-              >
+              <van-tag v-else-if="item.appointStatus == '30'" type="danger">
                 已驳回
               </van-tag>
-              <van-tag
-                v-else-if="item.appointStatus == '40'"
-                type="warning"
-              >
+              <van-tag v-else-if="item.appointStatus == '40'" type="warning">
                 已取消
               </van-tag>
-              <van-tag
-                v-else-if="item.appointStatus == '50'"
-                type="default"
-              >
+              <van-tag v-else-if="item.appointStatus == '50'" type="default">
                 已上机
               </van-tag>
-              <van-tag
-                v-else-if="item.appointStatus == '60'"
-                type="primary"
-              >
+              <van-tag v-else-if="item.appointStatus == '60'" type="primary">
                 已完成
               </van-tag>
-              <van-tag
-                v-else-if="item.appointStatus == '70'"
-                type="warning"
-              >
+              <van-tag v-else-if="item.appointStatus == '70'" type="warning">
                 审核超时
               </van-tag>
-              <van-tag
-                v-else-if="item.appointStatus == '80'"
-                type="danger"
-              >
+              <van-tag v-else-if="item.appointStatus == '80'" type="danger">
                 超时取消
               </van-tag>
-              <van-tag
-                v-else-if="item.appointStatus == '90'"
-                type="danger"
-              >
+              <van-tag v-else-if="item.appointStatus == '90'" type="danger">
                 超时未上机
               </van-tag>
             </header>
@@ -265,73 +181,31 @@
         </template>
       </van-cell>
     </van-list>
-    <van-back-top
-      target=".instr-detail"
-      bottom="10vh"
-    />
+    <van-back-top target=".instr-detail" bottom="10vh" />
   </div>
   <van-action-bar placeholder>
-    <van-action-bar-icon
-      icon="wap-home-o"
-      text="首页"
-      @click="onRouterPush('/home')"
-    />
-    <van-action-bar-icon
-      :icon="state.instDetail.following ? 'star' : 'star-o'"
-      :class="{ follow: state.instDetail.following }"
-      :text="state.instDetail.following ? '取消收藏' : '收藏'"
-      @click="handleFollowInst"
-    />
-    <van-action-bar-icon
-      icon="revoke"
-      text="返回"
-      @click="onRouterPush('/instr-list')"
-    />
-    <van-action-bar-button
-      v-if="state.instDetail.instStatus == '10' && state.instDetail.isAppointment == '10'"
-      type="primary"
-      text="使用预约"
-      @click="onAppoint('use')"
-    />
-    <van-action-bar-button
-      v-if="state.instDetail.instStatus == '10' && state.instDetail.isSampleDelivery == '10'"
-      type="warning"
-      text="送样预约"
-      @click="onAppoint('sample')"
-    />
+    <van-action-bar-icon icon="wap-home-o" text="首页" @click="onRouterPush('/home')" />
+    <van-action-bar-icon :icon="state.instDetail.following ? 'star' : 'star-o'"
+      :class="{ follow: state.instDetail.following }" :text="state.instDetail.following ? '取消收藏' : '收藏'"
+      @click="handleFollowInst" />
+    <van-action-bar-icon icon="revoke" text="返回" @click="onRouterPush('/instr-list')" />
+    <van-action-bar-button v-if="state.instDetail.instStatus == '10' && state.instDetail.isAppointment == '10'"
+      v-auth="'instr_appoint_btn'" type="primary" text="使用预约" @click="onAppoint('use')" />
+    <van-action-bar-button v-if="state.instDetail.instStatus == '10' && state.instDetail.isSampleDelivery == '10'"
+      v-auth="'instr_sampleDelivery_btn'" type="warning" text="送样预约" @click="onAppoint('sample')" />
   </van-action-bar>
   <!-- 通知 -->
-  <van-popup
-    v-model:show="state.popupShow"
-    round
-    :closeable="true"
-    position="top"
-    :style="{ padding: '20px' }"
-  >
+  <van-popup v-model:show="state.popupShow" round :closeable="true" position="top" :style="{ padding: '20px' }">
     <h4>{{ noticeInfo.noticeTitle }}</h4>
-    <div
-      class="notice-container"
-      v-html="noticeInfo.noticeContent"
-    ></div>
+    <div class="notice-container" v-html="noticeInfo.noticeContent"></div>
   </van-popup>
   <!-- 申请须知 -->
-  <van-popup
-    v-model:show="state.needToKnowShow"
-    round
-    :closeable="true"
-    position="bottom"
-    :style="{ height: '90vh' }"
-  >
+  <van-popup v-model:show="state.needToKnowShow" round :closeable="true" position="bottom" :style="{ height: '90vh' }">
     <div class="need-to-know">
       <h4 class="mt8 mb8">申请须知</h4>
       <p>{{ state.instDetail.applicationNotes }}</p>
       <footer>
-        <van-button
-          class="w100"
-          type="primary"
-          round
-          @click="confirmAppoint"
-        >
+        <van-button class="w100" type="primary" round @click="confirmAppoint">
           我知道了
         </van-button>
       </footer>
@@ -341,427 +215,462 @@
 </template>
 
 <script lang="ts" setup>
-  import to from 'await-to-js'
-  import { useRoute, useRouter } from 'vue-router'
-  import { ElMessageBox, ElMessage } from 'element-plus'
-  import { useInstrApi } from '/@/api/instr'
-  import { useInstDocApi } from '/@/api/instr/document'
-  import { onMounted, reactive, ref } from 'vue'
-  import { formatDate } from '/@/utils/formatTime'
-  import { showNotify } from 'vant'
-  import download from 'downloadjs'
-  import { useNoticeApi } from '/@/api/instr/notice'
-  import { useUseAppointApi } from '/@/api/instr/useAppoint'
-  import { useBlackApi } from '/@/api/blacklist'
-  import AddAuthDialog from './addAuthorization/index.vue'
-  import { useUserInfos } from '/@/hooks/useUserInfos'
-  import { useTrainingApi } from '/@/api/instr/inst/training'
-  import { getImageUrl } from '/@/utils/url'
-
-  const route = useRoute()
-  const router = useRouter()
-  const instApi = useInstrApi()
-  const instDocApi = useInstDocApi()
-  const noticeApi = useNoticeApi()
-  const useAppointApi = useUseAppointApi()
-  const blacklistApi = useBlackApi()
-  const trainingApi = useTrainingApi()
-  const active = ref('info')
-  const state = reactive({
-    detailsLoading: false,
-    instStatus: {
-      10: '正常',
-      20: '故障',
-      30: '报废',
-    },
-    instDetail: {} as any,
-    instFiles: [] as any[],
-    loading: false,
-    finished: false,
-    queryParams: {
-      pageNum: 1,
-      pageSize: 10,
-      instId: 0,
-      appointStatus: [],
-    },
-    list: [] as any[],
-    popupShow: false,
-    needToKnowShow: false,
-    appointType: '',
-  })
-  const noticeInfo = ref({ noticeTitle: '', noticeContent: '' })
+import to from 'await-to-js'
+import { useRoute, useRouter } from 'vue-router'
+import { ElMessageBox, ElMessage } from 'element-plus'
+import { useInstrApi } from '/@/api/instr'
+import { useInstDocApi } from '/@/api/instr/document'
+import { onMounted, reactive, ref } from 'vue'
+import { formatDate } from '/@/utils/formatTime'
+import { showNotify } from 'vant'
+import download from 'downloadjs'
+import { useNoticeApi } from '/@/api/instr/notice'
+import { useUseAppointApi } from '/@/api/instr/useAppoint'
+import { useBlackApi } from '/@/api/blacklist'
+import AddAuthDialog from './addAuthorization/index.vue'
+import { useUserInfos } from '/@/hooks/useUserInfos'
+import { useTrainingApi } from '/@/api/instr/inst/training'
+import { getImageUrl } from '/@/utils/url'
 
-  const isNeedGrant = ref(false)
+const route = useRoute()
+const router = useRouter()
+const instApi = useInstrApi()
+const instDocApi = useInstDocApi()
+const noticeApi = useNoticeApi()
+const useAppointApi = useUseAppointApi()
+const blacklistApi = useBlackApi()
+const trainingApi = useTrainingApi()
+const active = ref('info')
+const state = reactive({
+  detailsLoading: false,
+  instStatus: {
+    10: '正常',
+    20: '故障',
+    30: '报废',
+  },
+  instDetail: {} as any,
+  instFiles: [] as any[],
+  loading: false,
+  finished: false,
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    instId: 0,
+    appointStatus: [],
+  },
+  list: [] as any[],
+  popupShow: false,
+  needToKnowShow: false,
+  appointType: '',
+})
+const noticeInfo = ref({ noticeTitle: '', noticeContent: '' })
 
-  const addAuthDialogRef = ref()
+const isNeedGrant = ref(false)
 
-  const { userInfos } = useUserInfos()
+const addAuthDialogRef = ref()
 
-  const getNeedGrant = async (instId: number) => {
-    const [err, res]: ToResponse = await to(useAppointApi.getNeedGrant({ instId }))
-    if (err) return
-    isNeedGrant.value = res?.data
-  }
+const { userInfos } = useUserInfos()
 
-  // 获取仪器详情
-  const getDetail = async (id: number) => {
-    state.detailsLoading = true
-    const [err, res]: ToResponse = await to(instApi.getDetail({ id }))
-    state.detailsLoading = false
-    if (err) return
-    if (res?.code === 200) {
-      state.instDetail = res.data
-      getDocs()
-      getNotice()
-    }
-  }
-  const getNotice = async () => {
-    const param = {
-      pageNum: 1,
-      pageSize: 1,
-      instId: state.instDetail.instId,
-    }
-    const [err, res]: ToResponse = await to(noticeApi.list({ ...param }))
-    if (err) return
-    noticeInfo.value = res?.data?.list.length > 0 ? res?.data?.list[0] : {}
+const getNeedGrant = async (instId: number) => {
+  const [err, res]: ToResponse = await to(useAppointApi.getNeedGrant({ instId }))
+  if (err) return
+  isNeedGrant.value = res?.data
+}
+
+// 获取仪器详情
+const getDetail = async (id: number) => {
+  state.detailsLoading = true
+  const [err, res]: ToResponse = await to(instApi.getDetail({ id }))
+  state.detailsLoading = false
+  if (err) return
+  if (res?.code === 200) {
+    state.instDetail = res.data
+    getDocs()
+    getNotice()
   }
-  // 附件列表
-  const getDocs = async () => {
-    const [err, res]: ToResponse = await to(
-      instDocApi.list({ noPage: true, instId: state.instDetail.instId, docType: '' }),
-    )
-    if (err) return
-    state.instFiles = res?.data.list || []
+}
+const getNotice = async () => {
+  const param = {
+    pageNum: 1,
+    pageSize: 1,
+    instId: state.instDetail.instId,
   }
-  const realDown = (filename: string, fileurl: string) => {
-    let ua = navigator.userAgent.toLowerCase()
-    if (ua.includes('mac')) {
-      //iOS 将文件url转换为文件流 在下载
-      downloadFun(fileurl + '?response-content-type=application/octet-stream', filename)
-    } else {
-      //android 直接用插件的方法下载即可
-      download(fileurl, filename)
-    }
+  const [err, res]: ToResponse = await to(noticeApi.list({ ...param }))
+  if (err) return
+  noticeInfo.value = res?.data?.list.length > 0 ? res?.data?.list[0] : {}
+}
+// 附件列表
+const getDocs = async () => {
+  const [err, res]: ToResponse = await to(
+    instDocApi.list({ noPage: true, instId: state.instDetail.instId, docType: '' }),
+  )
+  if (err) return
+  state.instFiles = res?.data.list || []
+}
+const realDown = (filename: string, fileurl: string) => {
+  let ua = navigator.userAgent.toLowerCase()
+  if (ua.includes('mac')) {
+    //iOS 将文件url转换为文件流 在下载
+    downloadFun(fileurl + '?response-content-type=application/octet-stream', filename)
+  } else {
+    //android 直接用插件的方法下载即可
+    download(fileurl, filename)
   }
-  // 创建a标签 实现下载
-  const downloadFun = async (blobFile, fileName) => {
-    let blob = new Blob([blobFile], {
-      type: 'application/pdf;charset=UTF-8',
-    })
+}
+// 创建a标签 实现下载
+const downloadFun = async (blobFile, fileName) => {
+  let blob = new Blob([blobFile], {
+    type: 'application/pdf;charset=UTF-8',
+  })
+  // @ts-ignore
+  if (window.navigator.msSaveOrOpenBlob) {
     // @ts-ignore
-    if (window.navigator.msSaveOrOpenBlob) {
-      // @ts-ignore
-      navigator.msSaveBlob(blob, fileName)
-    } else {
-      let link = document.createElement('a')
-      link.href = window.URL.createObjectURL(blob)
-      link.download = fileName
-      link.click()
-      window.URL.revokeObjectURL(link.href) //释放内存
-    }
-  }
-  const setLaboratoryName = (name) => {
-    return name ? `(${name})` : ''
-  }
-  const tabChange = (name: string) => {
-    if (name === 'history' || name === 'approval') {
-      state.finished = false
-      state.list = []
-      state.queryParams = {
-        pageNum: 1,
-        pageSize: 10,
-        instId: state.instDetail.id,
-        appointStatus: name === 'approval' ? ['10'] : [],
-      }
-      onLoad()
-    }
+    navigator.msSaveBlob(blob, fileName)
+  } else {
+    let link = document.createElement('a')
+    link.href = window.URL.createObjectURL(blob)
+    link.download = fileName
+    link.click()
+    window.URL.revokeObjectURL(link.href) //释放内存
   }
-  const onLoad = async () => {
-    state.loading = true
-    const [err, res]: ToResponse = await to(useAppointApi.getListByPermission(state.queryParams))
-    if (err) return
-    const list = res?.data?.list || []
-    for (const item of list) {
-      state.list.push(item)
-    }
-    state.loading = false
-    state.queryParams.pageNum++
-    if (list.length < state.queryParams.pageSize) {
-      state.finished = true
+}
+const setLaboratoryName = (name) => {
+  return name ? `(${name})` : ''
+}
+const tabChange = (name: string) => {
+  if (name === 'history' || name === 'approval') {
+    state.finished = false
+    state.list = []
+    state.queryParams = {
+      pageNum: 1,
+      pageSize: 10,
+      instId: state.instDetail.id,
+      appointStatus: name === 'approval' ? ['10'] : [],
     }
+    onLoad()
   }
-  const getBreachTypes = (row: any) => {
-    let breachTypes = <string[]>[]
-    if (row.isLate) breachTypes.push('迟到')
-    if (row.isOvertime) breachTypes.push('超时')
-    if (row.isLeaveEarly) breachTypes.push('早退')
-    if (row.isAbsence) breachTypes.push('爽约')
-    return breachTypes.join('、') || '-'
-  }
-  const getAppointTime = (row: any) => {
-    const startDate = new Date(row.startTime)
-    const endDate = new Date(row.endTime)
-    // 计算两个日期之间的时间差(以毫秒为单位)
-    const timeDifference = endDate.getTime() - startDate.getTime()
-    // 计算天数
-    const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24))
-    // 计算剩余的毫秒数
-    const remainingMilliseconds = timeDifference % (1000 * 60 * 60 * 24)
-    // 计算小时数
-    const hours = Math.floor(remainingMilliseconds / (1000 * 60 * 60))
-    // 计算剩余的毫秒数
-    const remainingMillisecondsAfterHours = remainingMilliseconds % (1000 * 60 * 60)
-    // 计算分钟数
-    const minutes = Math.floor(remainingMillisecondsAfterHours / (1000 * 60))
-    return `${days}天${hours}小时${minutes}分`
+}
+const onLoad = async () => {
+  state.loading = true
+  const [err, res]: ToResponse = await to(useAppointApi.getListByPermission(state.queryParams))
+  if (err) return
+  const list = res?.data?.list || []
+  for (const item of list) {
+    state.list.push(item)
   }
-  // 关注/取关
-  const handleFollowInst = async () => {
-    const [err] = state.instDetail.following
-      ? await to(instApi.unfollow({ ids: [state.instDetail.id] }))
-      : await to(instApi.follow({ ids: [state.instDetail.id] }))
-    if (err) return
-    showNotify({ type: 'success', message: !state.instDetail.following ? '收藏成功' : '已取消收藏' })
-    getDetail(state.instDetail.id)
+  state.loading = false
+  state.queryParams.pageNum++
+  if (list.length < state.queryParams.pageSize) {
+    state.finished = true
   }
-  const onAppoint = async (type: string) => {
-    state.appointType = type
-    state.needToKnowShow = true
-  }
-  const confirmAppoint = async () => {
-    const [err, res]: ToResponse = await to(blacklistApi.checkInBlacklist())
-    if (err) return
-    if (res.data) {
-      showNotify({ type: 'danger', message: '您已被拉入黑名单,无法预约,请联系管理员' })
-      return
-    }
-    if (state.appointType === 'sample') {
-      onRouterPush('/sample-appoint', { id: state.instDetail.id })
-    } else {
-      onRouterPush('/instr-appoint', { id: state.instDetail.id })
-    }
+}
+const getBreachTypes = (row: any) => {
+  let breachTypes = <string[]>[]
+  if (row.isLate) breachTypes.push('迟到')
+  if (row.isOvertime) breachTypes.push('超时')
+  if (row.isLeaveEarly) breachTypes.push('早退')
+  if (row.isAbsence) breachTypes.push('爽约')
+  return breachTypes.join('、') || '-'
+}
+const getAppointTime = (row: any) => {
+  const startDate = new Date(row.startTime)
+  const endDate = new Date(row.endTime)
+  // 计算两个日期之间的时间差(以毫秒为单位)
+  const timeDifference = endDate.getTime() - startDate.getTime()
+  // 计算天数
+  const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24))
+  // 计算剩余的毫秒数
+  const remainingMilliseconds = timeDifference % (1000 * 60 * 60 * 24)
+  // 计算小时数
+  const hours = Math.floor(remainingMilliseconds / (1000 * 60 * 60))
+  // 计算剩余的毫秒数
+  const remainingMillisecondsAfterHours = remainingMilliseconds % (1000 * 60 * 60)
+  // 计算分钟数
+  const minutes = Math.floor(remainingMillisecondsAfterHours / (1000 * 60))
+  return `${days}天${hours}小时${minutes}分`
+}
+// 关注/取关
+const handleFollowInst = async () => {
+  const [err] = state.instDetail.following
+    ? await to(instApi.unfollow({ ids: [state.instDetail.id] }))
+    : await to(instApi.follow({ ids: [state.instDetail.id] }))
+  if (err) return
+  showNotify({ type: 'success', message: !state.instDetail.following ? '收藏成功' : '已取消收藏' })
+  getDetail(state.instDetail.id)
+}
+const onAppoint = async (type: string) => {
+  state.appointType = type
+  state.needToKnowShow = true
+}
+const confirmAppoint = async () => {
+  const [err, res]: ToResponse = await to(blacklistApi.checkInBlacklist())
+  if (err) return
+  if (res.data) {
+    showNotify({ type: 'danger', message: '您已被拉入黑名单,无法预约,请联系管理员' })
+    return
   }
-  const onRouterPush = (val: string, params?: any) => {
-    router.push({
-      path: val,
-      query: { ...params },
-    })
+  if (state.appointType === 'sample') {
+    onRouterPush('/sample-appoint', { id: state.instDetail.id })
+  } else {
+    onRouterPush('/instr-appoint', { id: state.instDetail.id })
   }
+}
+const onRouterPush = (val: string, params?: any) => {
+  router.push({
+    path: val,
+    query: { ...params },
+  })
+}
 
-  const applicationAuth = async () => {
-    console.log('applicationAuth')
-    addAuthDialogRef.value.openDialog('personal', state.instDetail)
-  }
+const applicationAuth = async () => {
+  console.log('applicationAuth')
+  addAuthDialogRef.value.openDialog('personal', state.instDetail)
+}
 
-  const applyTraining = () => {
-    console.log('applyTraining')
-    ElMessageBox.confirm('确认发起培训申请?', '提示', {
-      confirmButtonText: '确认',
-      cancelButtonText: '取消',
-      type: 'warning',
+const applyTraining = () => {
+  console.log('applyTraining')
+  ElMessageBox.confirm('确认发起培训申请?', '提示', {
+    confirmButtonText: '确认',
+    cancelButtonText: '取消',
+    type: 'warning',
+  })
+    .then(async () => {
+      const params = {
+        instCode: state.instDetail.instCode,
+        instId: state.instDetail.id,
+        instName: state.instDetail.instName,
+        userId: userInfos.value.id,
+        userName: userInfos.value.nickName,
+      }
+      const [err]: ToResponse = await to(trainingApi.add({ ...params }))
+      if (err) return
+      ElMessage.success('培训申请提交成功')
     })
-      .then(async () => {
-        const params = {
-          instCode: state.instDetail.instCode,
-          instId: state.instDetail.id,
-          instName: state.instDetail.instName,
-          userId: userInfos.value.id,
-          userName: userInfos.value.nickName,
-        }
-        const [err]: ToResponse = await to(trainingApi.add({ ...params }))
-        if (err) return
-        ElMessage.success('培训申请提交成功')
-      })
-      .catch(() => {})
-  }
+    .catch(() => { })
+}
 
-  onMounted(() => {
-    const id = route.query.id ? +route.query.id : 0
-    getDetail(id)
-    getNeedGrant(id)
-  })
+onMounted(() => {
+  const id = route.query.id ? +route.query.id : 0
+  getDetail(id)
+  getNeedGrant(id)
+})
 </script>
 
 <style lang="scss" scoped>
-  .instr-detail {
-    flex: 1;
-    overflow-y: auto;
-    background-color: #f7f8fa;
-    .my-swipe {
-      background-color: #fff;
-      height: 30px !important;
-      line-height: 30px !important;
-      :deep(.flex) {
+.instr-detail {
+  flex: 1;
+  overflow-y: auto;
+  background-color: #f7f8fa;
+
+  .my-swipe {
+    background-color: #fff;
+    height: 30px !important;
+    line-height: 30px !important;
+
+    :deep(.flex) {
+      height: 30px;
+      overflow: hidden;
+      padding: 0 12px;
+
+      span {
+        display: inline-block;
         height: 30px;
+        line-height: 30px;
+      }
+
+      span:first-child {
+        flex: 1;
+        white-space: nowrap;
         overflow: hidden;
-        padding: 0 12px;
-        span {
-          display: inline-block;
-          height: 30px;
-          line-height: 30px;
-        }
-        span:first-child {
-          flex: 1;
-          white-space: nowrap;
-          overflow: hidden;
-          text-overflow: ellipsis;
-        }
+        text-overflow: ellipsis;
       }
     }
-    > header {
-      height: auto;
-      min-height: 80px;
-      background-color: #fff;
-      padding: 12px;
+  }
+
+  >header {
+    height: auto;
+    min-height: 80px;
+    background-color: #fff;
+    padding: 12px;
+  }
+
+  .inst-info {
+    display: flex;
+  }
+
+  .i-right {
+    flex: 1;
+    font-size: 14px;
+    height: auto;
+    min-height: 80px;
+
+    .i-r-icon {
+      width: 15px;
+      height: 15px;
+      margin-right: 10px;
     }
-    .inst-info {
-      display: flex;
+  }
+
+  .detailTxt {
+    font-size: 12px;
+    color: #333333;
+    white-space: normal;
+    overflow: visible;
+    text-overflow: unset;
+    word-break: break-all;
+
+    &.name {
+      font-weight: bold;
+      font-size: 16px;
+    }
+  }
+
+  .content {
+    padding: 10px;
+  }
+
+  .card {
+    border-radius: 4px;
+    background-color: #fff;
+    padding: 10px;
+    box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
+
+    &+.card {
+      margin-top: 10px;
     }
-    .i-right {
-      flex: 1;
-      font-size: 14px;
-      height: auto;
-      min-height: 80px;
-      .i-r-icon {
-        width: 15px;
-        height: 15px;
-        margin-right: 10px;
+
+    h4 {
+      height: 18px;
+      line-height: 18px;
+      display: flex;
+      margin-bottom: 10px;
+
+      span {
+        font-weight: normal;
+        margin-left: auto;
+      }
+
+      &::before {
+        display: inline-block;
+        content: '';
+        width: 3px;
+        height: 18px;
+        background-color: #1c9bfd;
+        margin-right: 4px;
+        vertical-align: middle;
       }
     }
-    .detailTxt {
-      font-size: 12px;
-      color: #333333;
-      white-space: normal;
-      overflow: visible;
-      text-overflow: unset;
-      word-break: break-all;
-      &.name {
-        font-weight: bold;
-        font-size: 16px;
+
+    >ul {
+      li {
+        display: flex;
+        padding: 6px 0;
+
+        label {
+          width: 80px;
+          min-width: 80px;
+          color: #969799;
+        }
+
+        span {
+          word-break: break-all;
+        }
       }
     }
-    .content {
-      padding: 10px;
+
+    .text {
+      white-space: pre-wrap;
     }
-    .card {
-      border-radius: 4px;
+  }
+
+  .van-list {
+    padding: 10px;
+    border-radius: 4px;
+    flex: 1;
+
+    .van-cell {
       background-color: #fff;
-      padding: 10px;
-      box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
-      & + .card {
+
+      +.van-cell {
         margin-top: 10px;
       }
-      h4 {
-        height: 18px;
-        line-height: 18px;
-        display: flex;
-        margin-bottom: 10px;
-        span {
-          font-weight: normal;
-          margin-left: auto;
-        }
-        &::before {
-          display: inline-block;
-          content: '';
-          width: 3px;
-          height: 18px;
-          background-color: #1c9bfd;
-          margin-right: 4px;
-          vertical-align: middle;
-        }
-      }
-      > ul {
-        li {
-          display: flex;
-          padding: 6px 0;
-          label {
-            width: 80px;
-            min-width: 80px;
-            color: #969799;
-          }
-          span {
-            word-break: break-all;
-          }
-        }
+
+      header,
+      footer {
+        color: #333;
       }
-      .text {
-        white-space: pre-wrap;
+
+      .title {
+        flex: 1;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        text-align: left;
       }
-    }
-    .van-list {
-      padding: 10px;
-      border-radius: 4px;
-      flex: 1;
-      .van-cell {
-        background-color: #fff;
-        + .van-cell {
-          margin-top: 10px;
-        }
-        header,
-        footer {
-          color: #333;
-        }
-        .title {
-          flex: 1;
-          white-space: nowrap;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          text-align: left;
-        }
-        .inst-title {
-          color: #333;
-          text-align: left;
-          flex: 1;
-          overflow: hidden;
-          white-space: nowrap;
-          text-overflow: ellipsis;
-          margin-top: 4px;
-          span:first-child {
-            display: inline-block;
-            width: 80px;
-            min-width: 80px;
-            color: rgb(120, 120, 120);
-          }
-        }
-        .time {
-          color: #f69a4d;
+
+      .inst-title {
+        color: #333;
+        text-align: left;
+        flex: 1;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        margin-top: 4px;
+
+        span:first-child {
+          display: inline-block;
+          width: 80px;
+          min-width: 80px;
+          color: rgb(120, 120, 120);
         }
       }
-    }
-  }
-  .btns {
-    flex: 1;
-    display: flex;
-    li {
-      display: flex;
-      flex-direction: column;
-      align-items: center;
-      justify-content: center;
-      padding: 0 8px;
-      font-size: 12px;
-      i {
-        margin-bottom: 4px;
+
+      .time {
+        color: #f69a4d;
       }
     }
   }
-  :deep(.follow .van-icon) {
-    color: #fdc33e;
-  }
-  .need-to-know {
-    height: calc(100% - 20px);
-    overflow: hidden;
+}
+
+.btns {
+  flex: 1;
+  display: flex;
+
+  li {
     display: flex;
     flex-direction: column;
-    padding: 10px 20px;
-    white-space: pre-wrap;
-    p {
-      flex: 1;
-      overflow-y: auto;
-    }
-    footer {
-      flex: 0 0 45px;
-      margin-top: 4px;
-      border-top: 1px solid #f7f8fa;
+    align-items: center;
+    justify-content: center;
+    padding: 0 8px;
+    font-size: 12px;
+
+    i {
+      margin-bottom: 4px;
     }
   }
+}
+
+:deep(.follow .van-icon) {
+  color: #fdc33e;
+}
+
+.need-to-know {
+  height: calc(100% - 20px);
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+  padding: 10px 20px;
+  white-space: pre-wrap;
+
+  p {
+    flex: 1;
+    overflow-y: auto;
+  }
+
+  footer {
+    flex: 0 0 45px;
+    margin-top: 4px;
+    border-top: 1px solid #f7f8fa;
+  }
+}
 </style>