Procházet zdrojové kódy

Merge branch 'feature/enter-room' of wanglj/labsop_h5 into master

徐凯 před 8 měsíci
rodič
revize
a5cb95c8cf

+ 1 - 0
components.d.ts

@@ -25,6 +25,7 @@ declare module 'vue' {
     VanDialog: typeof import('vant/es')['Dialog']
     VanEmpty: typeof import('vant/es')['Empty']
     VanField: typeof import('vant/es')['Field']
+    VanFloatingBubble: typeof import('vant/es')['FloatingBubble']
     VanForm: typeof import('vant/es')['Form']
     VanIcon: typeof import('vant/es')['Icon']
     VanImage: typeof import('vant/es')['Image']

+ 19 - 14
src/api/platform/appoint/index.ts

@@ -12,55 +12,60 @@ export function usePlatformAppointApi() {
   return {
     // 创建
     create(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'Create', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'Create', params)
     },
     // 列表
     getList(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'GetList', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'GetList', params)
     },
     // 详情
     getDetail(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'GetEntityById', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'GetEntityById', params)
     },
     // 修改
     updateById(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'UpdateById', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'UpdateById', params)
     },
     // 删除
     deleteById(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'DeleteById', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'DeleteById', params)
     },
     // 审批
     approve(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'Approve', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'Approve', params)
     },
     // 撤销
     quashApprove(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'QuashApprove', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'QuashApprove', params)
     },
     // 首页获取平台预约列表
     getHomePlatAppointList(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'GetListByPlatformId', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'GetListByPlatformId', params)
     },
     // 待确认列表
     getConfirmedQueue(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'GetConfirmedQueue', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'GetConfirmedQueue', params)
     },
     // 获取次月待出室人员
     nextMonthPerson(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'NextMonthPerson', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'NextMonthPerson', params)
     },
     // 入室确认
     markNextMonthEntry(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'MarkNextMonthEntry', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'MarkNextMonthEntry', params)
     },
     // 上传
     createFile(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'CreateFile', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'CreateFile', params)
     },
     // 重新上传
     updateByIdAfterRefuse(params?: Object) {
-      return request.postRequest(basePath, 'PlatPlatformAppoint', 'UpdateByIdAfterRefuse', params);
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'UpdateByIdAfterRefuse', params)
+    },
+
+    // 获取当前登录人的入室申请
+    getUserInfoList(params?: Object) {
+      return request.postRequest(basePath, 'PlatPlatformAppoint', 'GetUserInfoList', params)
     }
-  };
+  }
 }

+ 5 - 4
src/layout/entry.vue

@@ -8,9 +8,9 @@
 -->
 <template>
   <router-view></router-view>
-  <van-tabbar route :placeholder="true">
-    <van-tabbar-item replace to="/entry/add" icon="send-gift-o">入室申请</van-tabbar-item>
-    <van-tabbar-item replace to="/entry" icon="coupon-o">我的入室</van-tabbar-item>
+  <van-tabbar route :placeholder="true" v-if="route.path !== '/entry/add'">
+    <van-tabbar-item replace to="/entry" icon="send-gift-o">入室申请</van-tabbar-item>
+    <van-tabbar-item replace to="/entry/mine" icon="coupon-o">我的入室</van-tabbar-item>
     <!-- <van-tabbar-item replace to="/entry/appoint" icon="cluster-o">入室预约</van-tabbar-item> -->
   </van-tabbar>
 </template>
@@ -19,12 +19,13 @@
   import to from 'await-to-js'
   import { showDialog } from 'vant'
   import { ref } from 'vue'
-  import { useRouter } from 'vue-router'
+  import { useRouter, useRoute } from 'vue-router'
   import { useUserInfo } from '/@/stores/userInfo'
   import { Local } from '/@/utils/storage'
 
   const active = ref(0)
   const router = useRouter()
+  const route = useRoute()
 
   const onRouterPush = (val: string) => {
     router.push(val)

+ 4 - 3
src/router.ts

@@ -182,7 +182,7 @@ const routes = [
         meta: {
           title: '修改密码'
         }
-      },
+      }
     ]
   },
   {
@@ -218,6 +218,7 @@ const routes = [
         name: 'entryAdd',
         path: '/entry/add',
         component: () => import('/@/view/entry/add.vue'),
+        // component: () => import('/@/view/entry/index.vue'),
         meta: {
           title: '新增入室申请'
         }
@@ -268,7 +269,7 @@ const routes = [
         meta: {
           title: '考试成绩'
         }
-      },
+      }
     ]
   },
   {
@@ -294,7 +295,7 @@ const routes = [
     meta: {
       title: '在线考试'
     }
-  },
+  }
 ]
 
 const router = createRouter({

+ 78 - 12
src/view/entry/add.vue

@@ -52,6 +52,8 @@
       </van-cell-group>
       <h4 class="mb8 mt8">安全承诺</h4>
       <van-checkbox v-model="state.safePromise">本人承诺:如时候遵守实验室及个平台的各项规章制度,遵守在室的积分管理制度。</van-checkbox>
+      <!-- <h4 class="mb8 mt8">安全承诺</h4>
+      <van-checkbox v-model="state.safePromise">本人承诺:如时候遵守实验室及个平台的各项规章制度,遵守在室的积分管理制度。</van-checkbox>
       <van-checkbox v-model="state.safeRead" :disabled="!state.isRead">
         我已完整阅读并同意
         <a href="javascript:void(0);" @click.stop="onRead">《预约须知》</a>
@@ -59,12 +61,35 @@
       </van-checkbox>
       <div style="margin: 16px">
         <van-button round block type="primary" native-type="submit"> 提交 </van-button>
-      </div>
+      </div> -->
+
+      <van-action-bar placeholder>
+        <van-action-bar-icon icon="wap-home-o" text="首页" @click="router.push('/home')" />
+        <van-action-bar-icon icon="revoke" text="返回" @click="router.push('/entry')" />
+        <!-- <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="立即预约" native-type="submit" />
+      </van-action-bar>
     </van-form>
   </div>
-  <van-dialog v-model:show="noticeShow" :title="noticeInfo.noticeTitle" show-cancel-button>
+
+  <!-- <van-dialog v-model:show="noticeShow" :title="noticeInfo.noticeTitle" show-cancel-button>
     <div class="ck-editor" v-html="noticeInfo.noticeContent"></div>
-  </van-dialog>
+  </van-dialog> -->
+
+  <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>
+      <div class="ck-editor" v-html="noticeInfo.noticeContent"></div>
+      <footer>
+        <van-button class="w100" type="primary" round @click="confirmAppoint">我知道了</van-button>
+      </footer>
+    </div>
+  </van-popup>
 </template>
 
 <script name="home" lang="ts" setup>
@@ -124,13 +149,31 @@
       isMolecularChecked: '20',
       molecularTime: null,
       platOtherNeed: ''
-    }
+    },
+    needToKnowShow: false
   })
   const noticeShow = ref(false)
   const noticeInfo = reactive({
     noticeTitle: '',
     noticeContent: ''
   })
+  const createEntryPayload = ref({})
+
+  const confirmAppoint = async () => {
+    const [err]: ToResponse = await to(platformAppointApi.create(createEntryPayload.value))
+    if (err) {
+      state.needToKnowShow = false
+      return
+    }
+    state.needToKnowShow = false
+    showNotify({
+      type: 'success',
+      message: '入室申请创建成功'
+    })
+
+    router.push('/entry')
+  }
+
   const getDicts = async () => {
     await Promise.all([dictApi.getDictDataByType('sys_user_type'), platformApi.getAllPlatformList({ noPage: true })]).then(([type, plat]) => {
       userTypeList.value = type.data.values || []
@@ -214,7 +257,8 @@
     }
   }
   const onSubmit = async (type: string) => {
-    if (!state.safePromise || !state.safeRead) {
+    onRead();
+    if (!state.safePromise) {
       showNotify({
         type: 'warning',
         message: '请阅读并勾选安全承诺!'
@@ -248,13 +292,18 @@
         return
       }
     }
-    const [err]: ToResponse = await to(platformAppointApi.create(params))
-    if (err) return
-    showNotify({
-      type: 'success',
-      message: '入室申请创建成功'
-    })
-    router.push('/entry')
+
+    createEntryPayload.value = params
+
+    state.needToKnowShow = true
+
+    // const [err]: ToResponse = await to(platformAppointApi.create(params))
+    // if (err) return
+    // showNotify({
+    //   type: 'success',
+    //   message: '入室申请创建成功'
+    // })
+    // router.push('/entry')
   }
   onMounted(async () => {
     await getDicts()
@@ -296,4 +345,21 @@
     overflow-y: auto;
     padding: 0 10px;
   }
+  .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>

+ 13 - 7
src/view/entry/detail.vue

@@ -37,14 +37,14 @@
     <div class="content">
       <div class="card">
         <h4>申请入室平台</h4>
-        <ul v-if="state.form.platformTime">
+        <ul v-if="state.form.platPlatformAppointCellRes && state.form.platPlatformAppointCellRes.length">
           <li>
             <label>申请平台</label>
-            <span>细胞</span>
+            <span>{{ state.form.platPlatformAppointCellRes[0].platformName }}</span>
           </li>
           <li>
             <label>申请时长</label>
-            <span>{{ state.form.platformTime }}个月</span>
+            <span>{{ state.form.platPlatformAppointCellRes[0].platformTime }}个月</span>
           </li>
           <li>
             <label>拟培养细胞种类</label>
@@ -55,14 +55,18 @@
             <span>{{ state.form.cellSourceType == '10' ? '普通' : '层流' }}</span>
           </li>
         </ul>
-        <ul v-else>
+        <ul
+          v-if="
+            state.form.platPlatformAppointMolecularRes && state.form.platPlatformAppointMolecularRes.length
+          "
+        >
           <li>
             <label>申请平台</label>
-            <span>分子生物平台</span>
+            <span>{{ state.form.platPlatformAppointMolecularRes[0].platformName }}</span>
           </li>
           <li>
             <label>申请时长</label>
-            <span>{{ state.form.molecularTime }}个月 </span>
+            <span>{{ state.form.platPlatformAppointMolecularRes[0].platformTime }}个月 </span>
           </li>
           <li>
             <label>其他需求</label>
@@ -217,7 +221,9 @@
       createdName: '',
       createdTime: '',
       approveStatus: '',
-      appointStatus: ''
+      appointStatus: '',
+      platPlatformAppointCellRes: [],
+      platPlatformAppointMolecularRes: []
     },
     uploadForm: {
       billList: [] as any[],

+ 28 - 4
src/view/entry/index.vue

@@ -40,11 +40,16 @@
               </p>
               <p class="inst-title">
                 <span>申请平台</span>
-                <span class="title ml8">{{ item.platformName }}</span>
+
+                <span class="title ml8">
+                  {{ formatData(item.platPlatformAppointCellRes, item.platPlatformAppointMolecularRes).platformName }}
+                </span>
               </p>
               <p class="inst-title">
                 <span>申请时长</span>
-                <span class="title ml8">{{ item.platformTime }}个月</span>
+                <span class="title ml8">
+                  {{ formatData(item.platPlatformAppointCellRes, item.platPlatformAppointMolecularRes).platformTime }}
+                </span>
               </p>
               <p class="inst-title">
                 <span>入室周期</span>
@@ -63,7 +68,10 @@
         </van-cell>
       </van-list>
     </div>
-    <!-- <van-floating-bubble v-model:offset="offset" icon="plus" @click="onClick" axis="y" /> -->
+    <van-floating-bubble v-model:offset="offset" icon="plus" @click="onClick" axis="y" />
+    <!-- <van-popup v-model:show="showEntryAddDialog" position="bottom" :style="{ padding: '64px' }">
+      <EntryAdd @entry-add-success="handleEntryAddSuccess" />
+    </van-popup> -->
   </div>
 </template>
 
@@ -73,10 +81,12 @@
   import { onMounted, reactive, ref } from 'vue'
   import { useRouter, useRoute } from 'vue-router'
   import { usePlatformAppointApi } from '/@/api/platform/appoint'
+  // import EntryAdd from './add.vue'
+
   const platformAppointApi = usePlatformAppointApi()
   const router = useRouter()
   const route = useRoute()
-  const offset = ref({ x: -80, y: 600 })
+  const offset = ref({ x: -80, y: 650 })
   const state = reactive({
     queryParams: {
       approveStatus: '20',
@@ -87,6 +97,20 @@
     loading: true,
     list: [] as any[]
   })
+
+  const formatData = (cellRes: any[], molecularRes: any[]) => {
+    if (cellRes && cellRes.length && (!molecularRes || !molecularRes.length)) {
+      return { platformName: cellRes[0].platformName, platformTime: cellRes[0].platformTime }
+    }
+    if (molecularRes && molecularRes.length && (!cellRes || !cellRes.length)) {
+      return { platformName: molecularRes[0].platformName, platformTime: molecularRes[0].platformTime }
+    }
+    return {
+      platformName: `${cellRes[0].platformName} / ${molecularRes[0].platformName}`,
+      platformTime: `${cellRes[0].platformTime}个月 / ${molecularRes[0].platformTime}个月`
+    }
+  }
+
   const changeType = (name: string) => {
     state.queryParams.pageNum = 1
     state.list = []

+ 180 - 2
src/view/entry/mine.vue

@@ -8,13 +8,191 @@
 -->
 <template>
   <div class="entry-container">
-    
+    <van-tabs v-model:active="state.queryParams.appointStatus" @change="changeType">
+      <van-tab title="待缴费" :name="EntryMineStatus.TO_BE_PAID" />
+      <van-tab title="待分配" :name="EntryMineStatus.TO_BE_ASSIGNED" />
+      <van-tab title="可入室" :name="EntryMineStatus.CAN_ENTER" />
+    </van-tabs>
+    <div class="list-container">
+      <van-list v-model:loading="state.loading" :finished="state.finished" finished-text="没有更多了" @load="onLoad">
+        <van-cell v-for="item in state.list" :key="item" @click="toDetail(item.id)">
+          <template #default>
+            <div class="list">
+              <header class="flex justify-between">
+                <strong class="title">我的入室申请</strong>
+
+                <!-- <van-tag v-if="item.approveStatus == 10" type="warning">待提交</van-tag>
+                <van-tag v-else-if="item.approveStatus == 20" type="primary">审批中</van-tag>
+                <van-tag v-else-if="item.approveStatus == 30" type="success">审批通过</van-tag>
+                <van-tag v-else-if="item.approveStatus == 40" type="danger">审批退回</van-tag> -->
+
+                <!-- 05 待确认 10 待上传 20 待审核 30 已驳回 35 已撤回 40 待分配 50 可入室 60 已出室 -->
+                <van-tag class="ml4">待缴费</van-tag>
+                <!-- <van-tag class="ml4">待分配</van-tag> -->
+                <!-- <van-tag type="success" class="ml4">可入室</van-tag> -->
+              </header>
+              <p class="inst-title">
+                <span>课题名称</span>
+                <span class="title ml8">{{ item.pgName }}</span>
+              </p>
+              <p class="inst-title">
+                <span>申请平台</span>
+                <span class="title ml8">
+                  {{ formatData(item.platPlatformAppointCellRes, item.platPlatformAppointMolecularRes).platformName }}
+                </span>
+              </p>
+              <p class="inst-title">
+                <span>申请时长</span>
+                <span class="title ml8">
+                  {{ formatData(item.platPlatformAppointCellRes, item.platPlatformAppointMolecularRes).platformTime }}
+                </span>
+              </p>
+              <p class="inst-title">
+                <span>入室周期</span>
+                <span class="title ml8">{{
+                  item.appointEndDate
+                    ? `${formatDate(new Date(item.appointEndDate), 'YYYY-mm-dd')}~${formatDate(new Date(item.appointEndDate), 'YYYY-mm-dd')}`
+                    : '-'
+                }}</span>
+              </p>
+              <p class="inst-title">
+                <span>缴费金额(¥)</span>
+                <span class="title ml8">{{ item.price }}</span>
+              </p>
+              <footer class="flex justify-between mt4">
+                <span class="title">{{ item.memberName }}</span>
+                <span class="time">{{ formatDate(new Date(item.createdTime), 'YYYY-mm-dd') }}</span>
+              </footer>
+            </div>
+          </template>
+        </van-cell>
+      </van-list>
+    </div>
   </div>
 </template>
 
 <script name="entryMine" lang="ts" setup>
-  
+  import { reactive, onMounted } from 'vue'
+  import { useRouter } from 'vue-router'
+  import to from 'await-to-js'
+
+  import { usePlatformAppointApi } from '/@/api/platform/appoint'
+  import { formatDate } from '/@/utils/formatTime'
+
+  enum EntryMineStatus {
+    TO_BE_PAID = '10',
+    TO_BE_ASSIGNED = '40',
+    CAN_ENTER = '50'
+  }
+
+  const platformAppointApi = usePlatformAppointApi()
+  const router = useRouter()
+
+  const state = reactive({
+    queryParams: {
+      appointStatus: EntryMineStatus.TO_BE_PAID,
+      pageNum: 1,
+      pageSize: 10
+    },
+    finished: false,
+    loading: true,
+    list: [] as any[]
+  })
+
+  const changeType = (name: EntryMineStatus) => {
+    state.queryParams.pageNum = 1
+    state.queryParams.appointStatus = name
+    state.list = []
+    onLoad()
+  }
+
+  const onLoad = async () => {
+    const [err, res]: ToResponse = await to(platformAppointApi.getList(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
+    }
+
+    console.log('response', res)
+  }
+
+  const formatData = (cellRes: any[], molecularRes: any[]) => {
+    if (cellRes && cellRes.length && (!molecularRes || !molecularRes.length)) {
+      return { platformName: cellRes[0].platformName, platformTime: cellRes[0].platformTime }
+    }
+    if (molecularRes && molecularRes.length && (!cellRes || !cellRes.length)) {
+      return { platformName: molecularRes[0].platformName, platformTime: molecularRes[0].platformTime }
+    }
+    return {
+      platformName: `${cellRes[0].platformName} / ${molecularRes[0].platformName}`,
+      platformTime: `${cellRes[0].platformTime}个月 / ${molecularRes[0].platformTime}个月`
+    }
+  }
+
+  const toDetail = (id: number) => {
+    router.push({
+      path: '/entry/detail',
+      query: {
+        id
+      }
+    })
+  }
+
+  onMounted(() => {
+    onLoad()
+  })
 </script>
 
 <style lang="scss" scoped>
+  .entry-container {
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    .list-container {
+      overflow-y: auto;
+      padding: 10px;
+      border-radius: 4px;
+      flex: 1;
+    }
+    .van-list {
+      .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 {
+            color: rgb(120, 120, 120);
+          }
+        }
+        .time {
+          color: #f69a4d;
+        }
+      }
+    }
+  }
 </style>