<!--
 * @Author: wanglj wanglijie@dashoo.cn
 * @Date: 2025-03-24 09:17:15
 * @LastEditors: wanglj wanglijie@dashoo.cn
 * @LastEditTime: 2025-03-28 11:39:21
 * @FilePath: \labsop_h5\src\view\instr\detail.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <div class="instr-detail">
    <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"
          />
          {{ noticeInfo.noticeTitle }}
        </div>
      </van-swipe-item>
    </van-swipe>
    <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)"
        />
      </div>
      <div class="i-right ml10">
        <div class="h100 flex flex-top flex-column flex-between">
          <div class="flex flex-top mb4 ml2">
            <div class="detailTxt name">{{ state.instDetail.instName }}({{ state.instDetail.instCode }})</div>
          </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"
              />
              <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"
              />
              <div class="detailTxt">
                {{ state.instDetail.placeAddress + setLaboratoryName(state.instDetail.laboratoryName) }}
              </div>
            </div>
          </footer>
        </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>
    <div
      v-if="active === 'info'"
      class="content"
    >
      <div class="card">
        <h4>仪器信息</h4>
        <ul>
          <li>
            <label>名称</label>
            <span>{{ state.instDetail.instName }}</span>
          </li>
          <li>
            <label>编号</label>
            <span>{{ state.instDetail.instCode }}</span>
          </li>
          <li>
            <label>仪器型号</label>
            <span>{{ state.instDetail.instNameEn }}</span>
          </li>
          <li>
            <label>当前状态</label>
            <span>{{ state.instStatus[state.instDetail.instStatus] }}</span>
          </li>
          <li>
            <label>所属组织</label>
            <span>{{ state.instDetail.belongOrgName }}</span>
          </li>
          <li>
            <label>位置</label>
            <span>{{ state.instDetail.placeAddress }}</span>
          </li>
          <li>
            <label>负责人</label>
            <span>{{ state.instDetail.instHeadName }}</span>
          </li>
          <li>
            <label>联系方式</label>
            <span>{{ state.instDetail.instHeadTel }}</span>
          </li>
        </ul>
      </div>
      <div class="card">
        <h4>申请须知</h4>
        <div class="text">{{ state.instDetail.applicationNotes }}</div>
      </div>
      <div class="card">
        <h4>主要功能</h4>
        <div class="text">{{ state.instDetail.instFunctFeat }}</div>
      </div>
      <div
        class="card"
        v-if="isNeedGrant"
        @click="applicationAuth"
      >
        <h4>资质申请</h4>
      </div>
      <div
        class="card"
        v-if="isNeedGrant"
        @click="applyTraining"
      >
        <h4>培训申请</h4>
      </div>
      <!-- <div class="card">
            <h4>相关附件</h4>
            <template v-for="item in state.instFiles">
              <div class="file-item">
                <a href="javascript: void(0);" @click="realDown(item.docName, item.docUrl)">{{ item.docName }}</a>
              </div>
            </template>
          </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"
      >
        <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>
              <van-tag
                v-else-if="item.appointStatus == '11'"
                type="warning"
              >
                已退回
              </van-tag>
              <van-tag
                v-else-if="item.appointStatus == '20'"
                type="success"
              >
                已通过
              </van-tag>
              <van-tag
                v-else-if="item.appointStatus == '30'"
                type="danger"
              >
                已驳回
              </van-tag>
              <van-tag
                v-else-if="item.appointStatus == '40'"
                type="warning"
              >
                已取消
              </van-tag>
              <van-tag
                v-else-if="item.appointStatus == '50'"
                type="default"
              >
                已上机
              </van-tag>
              <van-tag
                v-else-if="item.appointStatus == '60'"
                type="primary"
              >
                已完成
              </van-tag>
              <van-tag
                v-else-if="item.appointStatus == '70'"
                type="warning"
              >
                审核超时
              </van-tag>
              <van-tag
                v-else-if="item.appointStatus == '80'"
                type="danger"
              >
                超时取消
              </van-tag>
              <van-tag
                v-else-if="item.appointStatus == '90'"
                type="danger"
              >
                超时未上机
              </van-tag>
            </header>
            <p class="inst-title">
              <span>预约仪器</span>
              <span class="title ml8">{{ item.instName }}({{ item.instCode }})</span>
            </p>
            <p class="inst-title">
              <span>预约时间</span>
              <span class="title ml8">
                {{ formatDate(new Date(item.startTime), 'YYYY-mm-dd HH:MM') }}~{{
                  formatDate(new Date(item.endTime), 'YYYY-mm-dd HH:MM')
                }}
              </span>
            </p>
            <p class="inst-title">
              <span>预约时长</span>
              <span class="title ml8">{{ getAppointTime(item) }}</span>
            </p>
            <p class="inst-title">
              <span>违约情况</span>
              <span class="title ml8">{{ getBreachTypes(item) }}</span>
            </p>
            <p class="inst-title">
              <span>扣分明细</span>
              <span class="title ml8">{{ item.breachScore }}分</span>
            </p>
            <p class="inst-title">
              <span>备注</span>
              <span class="title ml8">{{ item.remark }}</span>
            </p>
            <footer class="flex justify-between mt4">
              <span class="title">{{ item.userName }}</span>
              <span class="time">{{ formatDate(new Date(item.createdTime), 'mm-dd HH:MM') }}</span>
            </footer>
          </div>
        </template>
      </van-cell>
    </van-list>
    <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>
  <!-- 通知 -->
  <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>
  </van-popup>
  <!-- 申请须知 -->
  <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>
      </footer>
    </div>
  </van-popup>
  <AddAuthDialog ref="addAuthDialogRef" />
</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: '' })

  const isNeedGrant = ref(false)

  const addAuthDialogRef = ref()

  const { userInfos } = useUserInfos()

  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 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 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',
    })
    // @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()
    }
  }
  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 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
    }
    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 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('培训申请提交成功')
      })
      .catch(() => {})
  }

  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) {
        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;
          text-overflow: ellipsis;
        }
      }
    }
    > 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;
      }
    }
    .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;
      }
      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;
          }
        }
      }
      .text {
        white-space: pre-wrap;
      }
    }
    .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;
        }
      }
    }
  }
  .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;
      }
    }
  }
  :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>
