index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. <template>
  2. <!-- 头部 -->
  3. <nav-bar height="336" backPath="workspace" title="教师专业发展" rightType="button" :tabList="state.tabList" :tabBtns="state.tabBtns" :onlyTitle="false" :showFilterPicker="false" :showTabs="true" :showTabBtns="true" rightWidth="0rpx" @CommonFilterData="CommonFilterData">
  4. <template #headRightIcon>
  5. <view class="upload_button">
  6. <image class="img" src="@/static/image/icon/plusempty.png"></image>
  7. <text class="text" @click="UploadEditMyHonor('')">上传荣誉</text>
  8. </view>
  9. </template>
  10. <template #tab_btns_lef>
  11. <view class="select_box" @click="ShowDateTimePopup">
  12. <view class="select_label">{{state.dateTypeText}}</view>
  13. <uni-icons :type="state.showStatus?'up':'down'" class="select_icon"></uni-icons>
  14. </view>
  15. <!-- <uni-data-select class="date_select" v-model="state.dateType" :clear="false" placeholder="请选择" :localdata="state.dateTypeList">
  16. </uni-data-select> -->
  17. </template>
  18. </nav-bar>
  19. <view class="page_content">
  20. <scroll-view
  21. class="scroll_view_y"
  22. :scroll-top="state.scrollTop"
  23. scroll-y="true"
  24. :refresher-enabled="false"
  25. :enable-back-to-top="true"
  26. :show-scrollbar="false"
  27. :scroll-with-animation="true"
  28. refresher-default-style="none"
  29. refresher-background="#F8F9FD"
  30. :refresher-triggered="state.isRefreshing"
  31. @scrolltolower="OnLoadMore"
  32. @refresherrefresh="OnRefresh"
  33. @scroll="OnScroll">
  34. <view class="refresh_loading" v-if="state.isRefreshing"><uni-load-more status="loading" /></view>
  35. <view class="page_list">
  36. <view class="list_item" v-for="item in state.pageList" :key="item.id" @click="UploadEditMyHonor(item)">
  37. <view class="item_honor_type">
  38. <view class="type_item_left">
  39. <view class="honor_type_item">{{item.awardDatetime}}</view>
  40. <view class="honor_type_item">{{item.honorTypeName}}</view>
  41. </view>
  42. <!-- reviewStatus: 0 需审核 1 无审核 honorStatus:0 待审核 1 已完成 2 已驳回 -->
  43. <view :class="['del',{'disable':Number(item.reviewStatus) === 0 && Number(item.honorStatus) === 1}]" @click.stop="DeleteMyHonor(item)">删除</view>
  44. </view>
  45. <view class="honor_content">
  46. <image class="honor_pic" :src="item.certPicUrl"></image>
  47. <view class="honor_info">
  48. <view class="honor_name">{{item.honorName}}</view>
  49. <view class="teacher_name">获奖人:{{item.teacherName}}</view>
  50. <!-- reviewStatus: 0 需审核 1 无审核 honorStatus:0 待审核 1 已完成 2 已驳回 -->
  51. <view :class="['honor_status',{'waiting':item.honorStatus===0,'finish':item.reviewStatus == 1 || item.honorStatus===1,'reject':item.honorStatus===2}]">
  52. <template v-if="item.honorStatus===0">待审核</template>
  53. <template v-if="item.reviewStatus == 1 || item.honorStatus===1">已完成</template>
  54. <template v-if="item.honorStatus===2">已驳回</template>
  55. </view>
  56. <view class="created_at">上传时间:{{item.createdAt}}</view>
  57. </view>
  58. </view>
  59. </view>
  60. </view>
  61. <view class="no_data" v-if="!state.isLoading && state.pageList.length == 0">
  62. <image class="no_data_img" src="@/static/image/bg/no_data.png"></image>
  63. <text class="no_data_text">暂无数据</text>
  64. </view>
  65. <uni-load-more v-if="state.pageList.length > 0" :status="state.loadStatus" />
  66. </scroll-view>
  67. </view>
  68. <!-- 删除确认框 -->
  69. <popupDialog ref="popupDelDialogRef" :showFootBorder="true" :content="state.popupDelDialog.content" @DialogConfirm="DialogDelConfirm" />
  70. <uni-popup class="my_honor_selector_popup" ref="topPopup" :animation="false" type="top" background-color="#fff" :style="{'top':`${state.selectorPopupTop}rpx`}" @change="ChangeSelectorPopup">
  71. <view :class="['selector_item',{'selector_item_active':state.dateType==item.value}]" v-for="item in state.dateTypeList" @click="SelectDateTime(item)">
  72. <view class="selector_item_text">{{item.text}}</view>
  73. <uni-icons type="checkmarkempty" v-if="state.dateType==item.value" class="selector_item_icon"></uni-icons>
  74. </view>
  75. </uni-popup>
  76. </template>
  77. <script setup>
  78. import navBar from '@/components/navBar.vue';
  79. import uniDataSelect from '@/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue';
  80. import popupDialog from '@/components/popupDialog.vue';
  81. import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue';
  82. import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
  83. import {queryHonorTypeList,queryHonorList,deleteHonorData} from '@/reqApi/teacherHonor.js';
  84. import {
  85. reactive,
  86. nextTick,
  87. ref,
  88. onMounted,
  89. onUnmounted
  90. } from 'vue';
  91. import { onShow } from '@dcloudio/uni-app';
  92. const state = reactive({
  93. tabList:[],
  94. dateTypeList:[{
  95. text:'全部',
  96. value:'',
  97. },{
  98. text:'最近3月',
  99. value:'3',
  100. },{
  101. text:'最近半年',
  102. value:'6',
  103. },{
  104. text:'最近1年',
  105. value:'12',
  106. }],
  107. tabBtns:[{
  108. label:'全部',
  109. value:'',
  110. },{
  111. label:'待审核',
  112. value:'0',
  113. },{
  114. label:'已完成',
  115. value:'1',
  116. },{
  117. label:'已驳回',
  118. value:'2',
  119. }],
  120. pageLists:[],//全部数据
  121. pageList:[],//列表数据
  122. honorTypeId:'',//荣誉类型
  123. dateType:'',//获奖时间 全部-不传值,最近三个月-3,最近 6 个月-6,最近一年-12
  124. dateTypeText:'全部',
  125. honorStatus:'',//0-待审核,1-已审核(审核通过),2-已驳回(审核失败)
  126. pageSize: 30,
  127. pageNum: 1,
  128. pages:0,
  129. scrollTop:0,
  130. oldScrollTop:0,
  131. isRefreshing:false,//设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
  132. isLoading:true,//加载中
  133. noMoreData:false,//没有更多数据了
  134. loadStatus:'more',//loading状态
  135. popupDelDialog:{
  136. id:'',
  137. content:'是否确认删除?'
  138. },
  139. selectorPopupTop:'313',//弹框距离顶部的高度
  140. showStatus:false,
  141. })
  142. const topPopup = ref(null);
  143. const popupDelDialogRef = ref(null);
  144. onShow(()=>{
  145. const isLoadMyHonorList = uni.getStorageSync('isLoadMyHonorList');
  146. if(isLoadMyHonorList){
  147. OnLoadData(true);
  148. }
  149. })
  150. onMounted(() => {
  151. const sys = uni.getSystemInfoSync();
  152. const statusBarRpx = sys.statusBarHeight * 750 / sys.screenWidth;
  153. state.selectorPopupTop = Math.ceil(Math.ceil(statusBarRpx) + 313);
  154. GetHonorTypeList();
  155. OnLoadData(true);
  156. });
  157. onUnmounted(()=>{
  158. uni.setStorageSync('isLoadHonorOverview', false);
  159. })
  160. //查询荣誉类型列表
  161. const GetHonorTypeList = () => {
  162. queryHonorTypeList().then(res=>{
  163. if(res.code == 200){
  164. const list = res?.data || [];
  165. const tabList = list.map(item=>({
  166. ...item,
  167. label:item.honorTypeName,
  168. value:item.id
  169. }))
  170. state.tabList = [{label:'全部',value:''},...tabList];
  171. }
  172. })
  173. }
  174. //切换条件选择器
  175. const CommonFilterData = (filterOptions,type) => {
  176. const { tabsSelected,tabBtnSelected } = filterOptions;
  177. state.honorTypeId = tabsSelected;
  178. state.honorStatus = tabBtnSelected;
  179. OnLoadData(true)
  180. }
  181. /*
  182. *获取数据
  183. * initPage:初始分页 从第一开始
  184. */
  185. const OnLoadData = (initPage) => {
  186. state.isLoading = true;
  187. state.loadStatus = 'loading';
  188. if (initPage) {
  189. // uni.showLoading({
  190. // title: '加载中'
  191. // });
  192. state.pageNum = 1;//如果是下拉刷新、重新查询 默认加载第一页
  193. queryHonorList({
  194. honorTypeId:state.honorTypeId,//荣誉类型
  195. honorStatus:state.honorStatus,//0-待审核,1-已审核(审核通过),2-已驳回(审核失败)
  196. startDatetime:'',
  197. endDatetime:'',
  198. dateType:state.dateType,
  199. }).then(res=>{
  200. if(res.code == 200){
  201. const tableData = res?.data || [];
  202. state.pageLists = tableData;//全部数据
  203. const total = tableData?.length || 0;//总数
  204. state.pages = Math.ceil(total / state.pageSize);//总页数
  205. //默认加载
  206. state.pageList = state.pageLists.slice(0, state.pageSize);
  207. //没有更多了
  208. state.noMoreData = state.pageNum == state.pages;
  209. //分页+1
  210. state.pageNum++;
  211. state.isLoading = false;
  212. state.isRefreshing = false;//下拉刷新未被触发
  213. state.loadStatus = state.noMoreData?'no-more':'more';
  214. }
  215. }).finally(()=>{
  216. // uni.hideLoading();
  217. //返回到页面顶部
  218. if(initPage){
  219. GoTop();
  220. }
  221. })
  222. }else{
  223. const start = (state.pageNum - 1) * state.pageSize;
  224. const end = start + state.pageSize;
  225. const list = state.pageLists.slice(start, end);
  226. state.pageList = [...state.pageList, ...list];
  227. state.noMoreData = state.pageNum == state.pages;
  228. state.pageNum++;
  229. setTimeout(() => {
  230. state.isLoading = false;
  231. state.isRefreshing = false; //下拉刷新未被触发
  232. state.loadStatus = state.noMoreData?'no-more':'more';
  233. }, 0)
  234. }
  235. }
  236. // 自定义下拉刷新被触发 下拉刷新
  237. const OnRefresh = () =>{
  238. state.isRefreshing = true;//下拉刷新已经被触发
  239. OnLoadData(true);
  240. }
  241. //滚动到底部/右边 触发上拉刷新
  242. const OnLoadMore = () => {
  243. if (state.isLoading || state.noMoreData) return;
  244. OnLoadData(false);
  245. }
  246. // 滚动时触发
  247. const OnScroll = (e) => {
  248. state.oldScrollTop = e.detail.scrollTop;
  249. }
  250. //返回到顶部
  251. const GoTop = () => {
  252. // 解决view层不同步的问题
  253. state.scrollTop = state.oldScrollTop;
  254. nextTick(() => {
  255. state.scrollTop = 0
  256. });
  257. }
  258. /*
  259. *删除
  260. *reviewStatus: 0 需审核 1 无审核
  261. *honorStatus:0 待审核 1 已完成 2 已驳回
  262. */
  263. const DeleteMyHonor = (item) => {
  264. if(Number(item.reviewStatus) === 0 && Number(item.honorStatus) === 1) return false;
  265. state.popupDelDialog.id = item.id;
  266. popupDelDialogRef.value.OpenDialog();
  267. }
  268. //确定删除
  269. const DialogDelConfirm = () => {
  270. deleteHonorData(state.popupDelDialog.id).then(res=>{
  271. if(res.code == 200){
  272. uni.showToast({
  273. title: '删除成功!',
  274. icon: 'none'
  275. });
  276. OnLoadData(true);
  277. }else{
  278. uni.showToast({
  279. title: res.msg,
  280. icon: 'none'
  281. });
  282. }
  283. })
  284. }
  285. //上传 修改 查看荣誉
  286. const UploadEditMyHonor = (item) => {
  287. const id = item?.id || '';
  288. let honorStatus = Number(item.honorStatus);//0 待审核 1 已完成 2 已驳回
  289. let reviewStatus = Number(item.reviewStatus);//0 需审核 1 无审核
  290. let type = '',honorName = '';
  291. if(item){
  292. type = reviewStatus === 1 || honorStatus === 0 ? 'edit' : 'view';
  293. honorName = type == 'view' ? encodeURIComponent(item.honorName) : '';
  294. }else{
  295. type = 'upload'
  296. }
  297. uni.navigateTo({
  298. url: `/pages/teacherHonor/myHonor/uploadEditMyHonor?id=${id}&type=${type}&honorName=${honorName}`
  299. });
  300. }
  301. //显示弹框
  302. const ShowDateTimePopup = () => {
  303. topPopup.value.open();
  304. }
  305. const SelectDateTime = (item) => {
  306. state.dateTypeText = item.text;
  307. state.dateType = item.value;
  308. topPopup.value.close();
  309. }
  310. const ChangeSelectorPopup = (e) => {
  311. state.showStatus = e.show;
  312. }
  313. </script>
  314. <style lang="scss" scoped>
  315. .date_select{
  316. width: 196rpx;
  317. flex: auto;
  318. flex-shrink: 0;
  319. :deep(.uni-select__selector){
  320. position: fixed !important;
  321. top:313rpx !important;
  322. left: 24rpx;
  323. width: 196rpx;
  324. }
  325. }
  326. .select_box{
  327. width: 196rpx;
  328. height: 72rpx;
  329. padding: 16rpx;
  330. flex-shrink: 0;
  331. display: flex;
  332. align-items: center;
  333. box-sizing: border-box;
  334. background-color: #FFFFFF;
  335. border-radius: 8rpx;
  336. border: 2rpx solid #DCDFE6;
  337. font-weight: 400;
  338. font-size: 28rpx;
  339. color: #333333;
  340. .select_label{
  341. flex:1;
  342. white-space: nowrap;
  343. overflow: hidden;
  344. text-overflow: ellipsis;
  345. }
  346. .select_icon{
  347. font-size: 32rpx;
  348. margin-left: 10rpx;
  349. }
  350. }
  351. .page_content{
  352. height: calc(100% - 472rpx);
  353. .scroll_view_y{
  354. height: 100%;
  355. .refresh_loading{
  356. padding: 10rpx 0;
  357. }
  358. }
  359. .page_list{
  360. display: flex;
  361. width: 100%;
  362. flex-direction: column;
  363. .list_item{
  364. display: flex;
  365. width: 100%;
  366. flex-direction: column;
  367. margin-top: 32rpx;
  368. &:nth-child(1){
  369. margin-top: 0;
  370. }
  371. .item_honor_type{
  372. display: flex;
  373. width: 100%;
  374. align-items: center;
  375. .type_item_left{
  376. display: flex;
  377. flex:1;
  378. align-items: center;
  379. overflow: hidden;
  380. }
  381. .del{
  382. font-weight: 400;
  383. font-size: 28rpx;
  384. color: #F56C6C;
  385. &.disable{
  386. color: #bbbbbb;
  387. }
  388. }
  389. .honor_type_item{
  390. font-weight: 400;
  391. font-size: 32rpx;
  392. color: #333333;
  393. &:nth-child(1){
  394. font-weight: 500;
  395. margin-right: 24rpx;
  396. }
  397. &:nth-child(2){
  398. flex:1;
  399. white-space: nowrap;
  400. overflow: hidden;
  401. text-overflow: ellipsis;
  402. }
  403. }
  404. }
  405. .honor_content{
  406. margin-top: 16rpx;
  407. display: flex;
  408. width: 100%;
  409. padding: 16rpx;
  410. box-sizing: border-box;
  411. background-color: #F8FAFE;
  412. border-radius: 15rpx;
  413. border: 2rpx solid #EBEEF5;
  414. .honor_pic{
  415. width: 320rpx;
  416. height: 200rpx;
  417. border-radius: 8rpx;
  418. margin-right: 16rpx;
  419. flex-shrink: 0;
  420. }
  421. .honor_info{
  422. flex:1;
  423. display: flex;
  424. justify-content: space-around;
  425. flex-direction: column;
  426. overflow: hidden;
  427. .honor_name{
  428. font-weight: 500;
  429. font-size: 32rpx;
  430. color: #333333;
  431. width: 100%;
  432. white-space: nowrap;
  433. overflow: hidden;
  434. text-overflow: ellipsis;
  435. }
  436. .teacher_name{
  437. font-weight: 400;
  438. font-size: 28rpx;
  439. color: #333333;
  440. width: 100%;
  441. white-space: nowrap;
  442. overflow: hidden;
  443. text-overflow: ellipsis;
  444. }
  445. .honor_status{
  446. font-weight: 500;
  447. font-size: 28rpx;
  448. width: 100%;
  449. &.waiting{
  450. color: #2E64FA;
  451. }
  452. &.finish{
  453. color: #2BC644;
  454. }
  455. &.reject{
  456. color: #F56C6C;
  457. }
  458. }
  459. .created_at{
  460. width: 100%;
  461. white-space: nowrap;
  462. overflow: hidden;
  463. text-overflow: ellipsis;
  464. font-weight: 400;
  465. font-size: 28rpx;
  466. color: #999999;
  467. }
  468. }
  469. }
  470. }
  471. }
  472. }
  473. </style>