index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. <!--
  2. * @Author: wanglj wanglijie@dashoo.cn
  3. * @Date: 2025-03-11 18:02:10
  4. * @LastEditors: wanglj wanglijie@dashoo.cn
  5. * @LastEditTime: 2025-04-16 16:19:33
  6. * @FilePath: \vant-demo-master\vant\vue3-ts\src\view\login\index.vue
  7. * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  8. -->
  9. <template>
  10. <div class="entry-container">
  11. <van-tabs
  12. v-model:active="state.queryParams.approveStatus"
  13. @change="changeType"
  14. >
  15. <van-tab
  16. title="审批中"
  17. name="20"
  18. ></van-tab>
  19. <van-tab
  20. title="已通过"
  21. name="30"
  22. ></van-tab>
  23. <van-tab
  24. title="全部申请"
  25. name=""
  26. ></van-tab>
  27. </van-tabs>
  28. <div class="list-container">
  29. <van-list
  30. v-model:loading="state.loading"
  31. :finished="state.finished"
  32. finished-text="没有更多了"
  33. @load="onLoad"
  34. >
  35. <van-cell
  36. v-for="item in state.list"
  37. :key="item"
  38. @click="toDetail(item.appointId, item.platformType)"
  39. >
  40. <template #default>
  41. <div class="list">
  42. <header class="flex justify-between">
  43. <strong class="title">{{ `${item.memberName}的${item.platformName}入室申请` }}</strong>
  44. <van-tag
  45. v-if="item.approveStatus == 10"
  46. type="warning"
  47. >
  48. 待提交
  49. </van-tag>
  50. <van-tag
  51. v-else-if="item.approveStatus == 20"
  52. type="primary"
  53. >
  54. 审批中
  55. </van-tag>
  56. <van-tag
  57. v-else-if="item.approveStatus == 30"
  58. type="success"
  59. >
  60. 审批通过
  61. </van-tag>
  62. <van-tag
  63. v-else-if="item.approveStatus == 40"
  64. type="danger"
  65. >
  66. 审批退回
  67. </van-tag>
  68. <!-- 05 待确认 10 待上传 20 待审核 30 已驳回 35 已撤回 40 待分配 50 可入室 60 已出室 -->
  69. <van-tag
  70. v-if="item.appointStatus == '05'"
  71. class="ml4"
  72. >
  73. 待确认
  74. </van-tag>
  75. <van-tag
  76. v-else-if="item.appointStatus == '10'"
  77. class="ml4"
  78. >
  79. 待上传
  80. </van-tag>
  81. <van-tag
  82. v-else-if="item.appointStatus == '20'"
  83. type="primary"
  84. class="ml4"
  85. >
  86. 待审核
  87. </van-tag>
  88. <van-tag
  89. v-else-if="item.appointStatus == '30'"
  90. type="danger"
  91. class="ml4"
  92. >
  93. 已驳回
  94. </van-tag>
  95. <van-tag
  96. v-else-if="item.appointStatus == '35'"
  97. type="warning"
  98. class="ml4"
  99. >
  100. 已撤回
  101. </van-tag>
  102. <van-tag
  103. v-else-if="item.appointStatus == '40'"
  104. class="ml4"
  105. >
  106. 待分配
  107. </van-tag>
  108. <van-tag
  109. v-else-if="item.appointStatus == '50'"
  110. type="success"
  111. class="ml4"
  112. >
  113. 可入室
  114. </van-tag>
  115. <van-tag
  116. v-else-if="item.appointStatus == '60'"
  117. class="ml4"
  118. >
  119. 已出室
  120. </van-tag>
  121. </header>
  122. <p class="inst-title">
  123. <span>课题名称</span>
  124. <span class="title ml8">{{ item.pgName }}</span>
  125. </p>
  126. <p class="inst-title">
  127. <span>申请平台</span>
  128. <span class="title ml8">
  129. {{ formatData(item.platPlatformAppointCellRes, item.platPlatformAppointMolecularRes).platformName }}
  130. </span>
  131. </p>
  132. <p class="inst-title">
  133. <span>申请时长</span>
  134. <span class="title ml8">
  135. {{ formatData(item.platPlatformAppointCellRes, item.platPlatformAppointMolecularRes).platformTime }}
  136. </span>
  137. </p>
  138. <p class="inst-title">
  139. <span>入室周期</span>
  140. <span class="title ml8">
  141. {{
  142. item.appointEndDate
  143. ? `${formatDate(new Date(item.appointEndDate), 'YYYY-mm-dd')}~${formatDate(
  144. new Date(item.appointEndDate),
  145. 'YYYY-mm-dd',
  146. )}`
  147. : '-'
  148. }}
  149. </span>
  150. </p>
  151. <footer class="flex justify-between mt4">
  152. <span class="title">{{ item.memberName }}</span>
  153. <span class="time">{{ formatDate(new Date(item.createdTime), 'YYYY-mm-dd') }}</span>
  154. </footer>
  155. </div>
  156. </template>
  157. </van-cell>
  158. </van-list>
  159. </div>
  160. <van-floating-bubble
  161. v-model:offset="offset"
  162. icon="plus"
  163. @click="onClick"
  164. axis="y"
  165. />
  166. <!-- <van-popup v-model:show="showEntryAddDialog" position="bottom" :style="{ padding: '64px' }">
  167. <EntryAdd @entry-add-success="handleEntryAddSuccess" />
  168. </van-popup> -->
  169. <!-- 申请须知弹窗 -->
  170. <van-popup
  171. v-model:show="needToKnowShow"
  172. round
  173. :closeable="true"
  174. position="bottom"
  175. :style="{ height: '90vh' }"
  176. >
  177. <div class="need-to-know">
  178. <h4 class="mt8 mb8">{{ noticeInfo.noticeTitle }}</h4>
  179. <div
  180. class="ck-editor"
  181. v-html="noticeInfo.noticeContent"
  182. ></div>
  183. <footer>
  184. <van-button
  185. class="w100"
  186. type="primary"
  187. round
  188. :disabled="confirmDisabled"
  189. :loading="confirmDisabled"
  190. @click="confirmAppoint"
  191. >
  192. 我知道了
  193. </van-button>
  194. </footer>
  195. </div>
  196. </van-popup>
  197. </div>
  198. </template>
  199. <script name="home" lang="ts" setup>
  200. import to from 'await-to-js'
  201. import { formatDate } from '/@/utils/formatTime'
  202. import { onMounted, reactive, ref } from 'vue'
  203. import { useRouter, useRoute } from 'vue-router'
  204. import { usePlatformAppointApi } from '/@/api/platform/appoint'
  205. import { usePlatformApi } from '/@/api/platform/home'
  206. // import EntryAdd from './add.vue'
  207. import { showNotify } from 'vant'
  208. const platformAppointApi = usePlatformAppointApi()
  209. const platformApi = usePlatformApi()
  210. const router = useRouter()
  211. const route = useRoute()
  212. const offset = ref({ x: -80, y: 450 })
  213. const state = reactive({
  214. queryParams: {
  215. approveStatus: '20',
  216. pageNum: 1,
  217. pageSize: 10,
  218. },
  219. finished: false,
  220. loading: true,
  221. list: [] as any[],
  222. })
  223. const formatData = (cellRes: any[], molecularRes: any[]) => {
  224. if (cellRes && cellRes.length && (!molecularRes || !molecularRes.length)) {
  225. return { platformName: cellRes[0].platformName, platformTime: cellRes[0].platformTime }
  226. }
  227. if (molecularRes && molecularRes.length && (!cellRes || !cellRes.length)) {
  228. return { platformName: molecularRes[0].platformName, platformTime: molecularRes[0].platformTime }
  229. }
  230. if (!cellRes || !molecularRes) {
  231. return { platformName: '', platformTime: '' }
  232. }
  233. return {
  234. platformName: `${cellRes[0].platformName} / ${molecularRes[0].platformName}`,
  235. platformTime: `${cellRes[0].platformTime}个月 / ${molecularRes[0].platformTime}个月`,
  236. }
  237. }
  238. const changeType = (name: string) => {
  239. state.queryParams.pageNum = 1
  240. state.list = []
  241. onLoad()
  242. }
  243. const onLoad = async () => {
  244. const [err, res]: ToResponse = await to(platformAppointApi.getList(state.queryParams))
  245. if (err) return
  246. const list = res?.data?.list || []
  247. for (const item of list) {
  248. state.list.push(item)
  249. }
  250. state.loading = false
  251. state.queryParams.pageNum++
  252. if (list.length < state.queryParams.pageSize) {
  253. state.finished = true
  254. }
  255. }
  256. const toDetail = (id: number, platformType: string) => {
  257. router.push({
  258. path: '/entry/detail',
  259. query: {
  260. id,
  261. entryType: 'getDetail',
  262. platformType,
  263. },
  264. })
  265. }
  266. // 申请须知弹窗相关状态
  267. const needToKnowShow = ref(false)
  268. const confirmDisabled = ref(false)
  269. const noticeInfo = reactive({
  270. noticeTitle: '',
  271. noticeContent: '',
  272. })
  273. // 获取申请须知内容
  274. const getNoticeContent = async () => {
  275. // 这里可以调用API获取申请须知内容,暂时使用默认内容
  276. noticeInfo.noticeTitle = '入室申请须知'
  277. noticeInfo.noticeContent = '请仔细阅读以下入室申请须知:\n\n1. 申请人需遵守实验室各项规章制度\n2. 申请需经过审核流程\n3. 请确保填写信息准确无误\n4. 申请通过后需按时完成相关手续'
  278. }
  279. // 确认申请须知
  280. const confirmAppoint = () => {
  281. confirmDisabled.value = true
  282. // 确认后跳转到入室申请页面
  283. router.push('/entry/add')
  284. confirmDisabled.value = false
  285. needToKnowShow.value = false
  286. }
  287. const onClick = async () => {
  288. const [err, res]: ToResponse = await to(platformApi.onCheckUserCertificate({}))
  289. if (err) return
  290. const { check, message } = res.data
  291. if (check) {
  292. // 先显示申请须知弹窗
  293. await getNoticeContent()
  294. needToKnowShow.value = true
  295. } else {
  296. showNotify({
  297. type: 'warning',
  298. message,
  299. })
  300. }
  301. }
  302. onMounted(() => {
  303. const type = route.query.type
  304. if (type) {
  305. state.queryParams.approveStatus = type as string
  306. }
  307. onLoad()
  308. })
  309. </script>
  310. <style lang="scss" scoped>
  311. .entry-container {
  312. position: relative;
  313. display: flex;
  314. flex-direction: column;
  315. .list-container {
  316. overflow-y: auto;
  317. padding: 10px;
  318. border-radius: 4px;
  319. flex: 1;
  320. }
  321. .van-list {
  322. .van-cell {
  323. background-color: #fff;
  324. + .van-cell {
  325. margin-top: 10px;
  326. }
  327. header,
  328. footer {
  329. color: #333;
  330. }
  331. .title {
  332. flex: 1;
  333. white-space: nowrap;
  334. overflow: hidden;
  335. text-overflow: ellipsis;
  336. text-align: left;
  337. }
  338. .inst-title {
  339. color: #333;
  340. text-align: left;
  341. flex: 1;
  342. overflow: hidden;
  343. white-space: nowrap;
  344. text-overflow: ellipsis;
  345. margin-top: 4px;
  346. span:first-child {
  347. color: rgb(120, 120, 120);
  348. }
  349. }
  350. .time {
  351. color: #f69a4d;
  352. }
  353. }
  354. }
  355. }
  356. // 申请须知弹窗样式
  357. .ck-editor {
  358. height: calc(100vh - 100px);
  359. overflow-y: auto;
  360. padding: 0 10px;
  361. }
  362. .need-to-know {
  363. height: calc(100% - 20px);
  364. overflow: hidden;
  365. display: flex;
  366. flex-direction: column;
  367. padding: 10px 20px;
  368. white-space: pre-wrap;
  369. p {
  370. flex: 1;
  371. overflow-y: auto;
  372. }
  373. footer {
  374. flex: 0 0 45px;
  375. margin-top: 4px;
  376. border-top: 1px solid #f7f8fa;
  377. }
  378. }
  379. </style>