14
0

index.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <template>
  2. <div class="cage-container">
  3. <van-tabs v-model:active="activeStatus" @change="changeType">
  4. <van-tab title="我的笼位" :name="MyCageType.MINE_CAGE"></van-tab>
  5. <van-tab title="历史笼位" :name="MyCageType.MY_CAGE_HISTORY"></van-tab>
  6. </van-tabs>
  7. <div class="list-container">
  8. <van-list v-model:loading="state.loading" :finished="state.finished" finished-text="没有更多了" @load="onLoad">
  9. <van-cell v-for="item in state.pageList" :key="item" @click="handleCheckDetail(item)">
  10. <template #default>
  11. <div class="list">
  12. <header class="flex justify-between">
  13. <strong class="title">{{ `${item.userName}的笼位申请` }}</strong>
  14. <van-tag v-if="item.approveStatus == ApproveStatus.WAIT_SUBMIT" type="warning">待提交</van-tag>
  15. <van-tag v-else-if="item.approveStatus == ApproveStatus.APPROVING" type="primary">审核中</van-tag>
  16. <van-tag v-else-if="item.approveStatus == ApproveStatus.PASS" type="success">通过</van-tag>
  17. <van-tag v-else-if="item.approveStatus == ApproveStatus.REVOKE" type="success">撤销</van-tag>
  18. <van-tag v-else-if="item.approveStatus == ApproveStatus.REFUSE" type="danger">拒绝</van-tag>
  19. </header>
  20. <p class="inst-title">
  21. <span>课题名称</span>
  22. <span class="title ml8">{{ item.projectGroupName }}</span>
  23. </p>
  24. <p class="inst-title">
  25. <span>申请人</span>
  26. <span class="title ml8">
  27. {{ item.userName }}
  28. </span>
  29. </p>
  30. <p class="inst-title">
  31. <span>申请时间</span>
  32. <span class="title ml8">
  33. {{ formatToChineseDate(item.createdTime) }}
  34. </span>
  35. </p>
  36. <p class="inst-title">
  37. <span>开始时间</span>
  38. <span class="title ml8">
  39. {{ formatToChineseDate(item.startDate) }}
  40. </span>
  41. </p>
  42. <p class="inst-title">
  43. <span>申请笼位(个)</span>
  44. <span class="title ml8">
  45. {{ item.number }}
  46. </span>
  47. </p>
  48. <p class="inst-title">
  49. <span>退还笼位(个)</span>
  50. <span class="title ml8">
  51. {{ item.returnNumber }}
  52. </span>
  53. </p>
  54. <p class="inst-title">
  55. <span>申请状态</span>
  56. <span class="title ml8">
  57. {{ formatApproveStatus(Number(item.approveStatus)) }}
  58. </span>
  59. </p>
  60. <p class="inst-title">
  61. <span>动物类型</span>
  62. <span class="title ml8">
  63. {{ item.categoryName }}
  64. </span>
  65. </p>
  66. <p class="inst-title">
  67. <span>级别</span>
  68. <span class="title ml8">
  69. {{ LeavelList.find((leaveItem) => leaveItem.id === item.level)?.name || '' }}
  70. </span>
  71. </p>
  72. <footer class="flex justify-between mt16">
  73. <span class="title">
  74. <el-button
  75. v-if="
  76. item.approveStatus === ApproveStatus.PASS.toString() &&
  77. item.returnStatus !== ReturnStatus.COMPLETE.toString() &&
  78. userInfos.id === item.userId
  79. "
  80. style="height: 25px"
  81. type="primary"
  82. @click.stop="handleRefundable(item)"
  83. >退还</el-button
  84. >
  85. </span>
  86. <span class="time">{{ formatDate(new Date(item.createdTime), 'YYYY-mm-dd') }}</span>
  87. </footer>
  88. </div>
  89. </template>
  90. </van-cell>
  91. </van-list>
  92. </div>
  93. <DetailModal :showDialog="showDetailDialog" :isReturnCageList="false" ref="detailModalRef" @close="() => (showDetailDialog = false)" />
  94. <ReturnCageDialog ref="returnCageDialogRef" :currentRefundableItemNumber="currentRefundableItemNumber" :getTableData="handleRefresh" />
  95. </div>
  96. </template>
  97. <script lang="ts" setup>
  98. import { reactive, ref, onMounted, defineAsyncComponent, ComponentPublicInstance } from 'vue'
  99. import to from 'await-to-js'
  100. import { formatDate, formatToChineseDate } from '/@/utils/formatTime'
  101. import { ApproveStatus, ReturnStatus, LeavelList, ApproveStatusList, MyCageType } from '/@/constants/pageConstants'
  102. import { useUserInfos } from '/@/hooks/useUserInfos'
  103. import { usePlatAnimalCageApplicationApi } from '/@/api/platform/animal'
  104. interface ReturnCageDialogInstance extends ComponentPublicInstance {
  105. handleOpenRefundableDialog: (id: number) => void
  106. }
  107. interface DetailModalInstance extends ComponentPublicInstance {
  108. initForm: (id: number) => void
  109. }
  110. const DetailModal = defineAsyncComponent(() => import('/@/view/animal/application/components/Detail.vue'))
  111. const ReturnCageDialog = defineAsyncComponent(() => import('/@/view/animal/application/components/ReturnCageDialog.vue'))
  112. const { userInfos } = useUserInfos()
  113. const platAnimalCageApplicationApi = usePlatAnimalCageApplicationApi()
  114. const returnCageDialogRef = ref<ReturnCageDialogInstance>()
  115. const detailModalRef = ref<DetailModalInstance>()
  116. const showDetailDialog = ref<boolean>(false)
  117. const activeStatus = ref<MyCageType>(MyCageType.MINE_CAGE)
  118. const currentRefundableItemNumber = ref<number>(0)
  119. const state = reactive({
  120. pageList: [],
  121. loading: false,
  122. finished: false,
  123. queryParams: {
  124. pageNum: 1,
  125. pageSize: 25,
  126. isMyself: 1
  127. }
  128. })
  129. const changeType = () => {
  130. state.queryParams.pageNum = 1
  131. state.pageList = []
  132. onLoad()
  133. }
  134. const formatApproveStatus = (status: number) => {
  135. return ApproveStatusList.find((item) => item.id === status)?.name || ''
  136. }
  137. const handleRefundable = (row: any) => {
  138. currentRefundableItemNumber.value = row.number
  139. returnCageDialogRef.value.handleOpenRefundableDialog(row.id)
  140. }
  141. const handleRefresh = () => {
  142. resetQueryParams()
  143. onLoad()
  144. }
  145. const resetQueryParams = () => {
  146. ;(state.pageList = []),
  147. (state.loading = false),
  148. (state.finished = false),
  149. (state.queryParams = {
  150. pageNum: 1,
  151. pageSize: 25,
  152. isMyself: 1
  153. })
  154. }
  155. const onLoad = async (isSearch?: boolean) => {
  156. state.loading = true
  157. const apiRequest =
  158. activeStatus.value === MyCageType.MINE_CAGE
  159. ? platAnimalCageApplicationApi.getList(state.queryParams)
  160. : platAnimalCageApplicationApi.getMyCageHistoryList(state.queryParams)
  161. const [err, res]: ToResponse = await to(apiRequest)
  162. state.loading = false
  163. if (err) return
  164. const list = res?.data?.list || []
  165. if (!isSearch) {
  166. for (const item of list) {
  167. state.pageList.push(item)
  168. }
  169. state.queryParams.pageNum++
  170. if (list.length < state.queryParams.pageSize) {
  171. state.finished = true
  172. }
  173. } else {
  174. state.pageList = list
  175. }
  176. }
  177. const handleCheckDetail = (row: any) => {
  178. detailModalRef.value.initForm(row.id)
  179. showDetailDialog.value = true
  180. }
  181. onMounted(() => {
  182. onLoad()
  183. })
  184. </script>
  185. <style lang="scss" scoped>
  186. .cage-container {
  187. position: relative;
  188. display: flex;
  189. flex-direction: column;
  190. .list-container {
  191. overflow-y: auto;
  192. padding: 10px;
  193. border-radius: 4px;
  194. flex: 1;
  195. }
  196. .van-list {
  197. .van-cell {
  198. background-color: #fff;
  199. + .van-cell {
  200. margin-top: 10px;
  201. }
  202. header,
  203. footer {
  204. color: #333;
  205. }
  206. .title {
  207. flex: 1;
  208. white-space: nowrap;
  209. overflow: hidden;
  210. text-overflow: ellipsis;
  211. text-align: left;
  212. }
  213. .inst-title {
  214. color: #333;
  215. text-align: left;
  216. flex: 1;
  217. overflow: hidden;
  218. white-space: nowrap;
  219. text-overflow: ellipsis;
  220. margin-top: 4px;
  221. span:first-child {
  222. color: rgb(120, 120, 120);
  223. }
  224. }
  225. .time {
  226. color: #f69a4d;
  227. }
  228. }
  229. }
  230. }
  231. </style>