|
|
@@ -0,0 +1,540 @@
|
|
|
+<!--
|
|
|
+ * @Author: wanglj wanglijie@dashoo.cn
|
|
|
+ * @Date: 2025-03-24 09:17:15
|
|
|
+ * @LastEditors: wanglj wanglijie@dashoo.cn
|
|
|
+ * @LastEditTime: 2025-03-26 15:28:13
|
|
|
+ * @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="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">
|
|
|
+ <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">
|
|
|
+ <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), 'mm-dd HH:MM') }}~{{ formatDate(new Date(item.endTime), '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>
|
|
|
+ <van-action-bar-icon icon="wap-home-o" text="首页" @click="onRouterPush('/home')" />
|
|
|
+ <van-action-bar-icon icon="calendar-o" text="周视图" />
|
|
|
+ <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-button type="primary" text="立即预约" @click="onAppoint" />
|
|
|
+ </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>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+ import to from 'await-to-js'
|
|
|
+ import { useRoute, useRouter } from 'vue-router'
|
|
|
+ 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'
|
|
|
+ const route = useRoute()
|
|
|
+ const router = useRouter()
|
|
|
+ const instApi = useInstrApi()
|
|
|
+ const instDocApi = useInstDocApi()
|
|
|
+ const noticeApi = useNoticeApi()
|
|
|
+ const useAppointApi = useUseAppointApi()
|
|
|
+ const blacklistApi = useBlackApi()
|
|
|
+ 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
|
|
|
+ })
|
|
|
+ const noticeInfo = ref({ noticeTitle: '', noticeContent: '' })
|
|
|
+ // 获取仪器详情
|
|
|
+ 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 () => {
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ onRouterPush('/instr-appoint', { id: state.instDetail.id })
|
|
|
+ }
|
|
|
+ const onRouterPush = (val: string, params?: any) => {
|
|
|
+ router.push({
|
|
|
+ path: val,
|
|
|
+ query: { ...params }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ onMounted(() => {
|
|
|
+ const id = route.query.id ? +route.query.id : 0
|
|
|
+ getDetail(id)
|
|
|
+ })
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .instr-detail {
|
|
|
+ height: calc(100% - 50px);
|
|
|
+ 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: 80px;
|
|
|
+ background-color: #fff;
|
|
|
+ padding: 12px;
|
|
|
+ }
|
|
|
+ .inst-info {
|
|
|
+ display: flex;
|
|
|
+ }
|
|
|
+ .i-right {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 14px;
|
|
|
+ height: 80px;
|
|
|
+ .i-r-icon {
|
|
|
+ width: 15px;
|
|
|
+ height: 15px;
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .detailTxt {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #333333;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ &.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>
|