Sin descripción
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.vue 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <script setup>
  2. import { getCurrentInstance, onMounted, ref } from 'vue';
  3. import { onBeforeRouteLeave, useRouter } from 'vue-router';
  4. import { useEmergencyStore } from '@/stores/emergencyManager.js';
  5. const emergencyInfo = useEmergencyStore();
  6. const {
  7. proxy
  8. } = getCurrentInstance();
  9. const base_url = '/sgsafe/KeyMattersManagement';
  10. /* 通用方法: 重置list数据 */
  11. const basicReset = () => {
  12. finished.value = false;
  13. loading.value = true;
  14. pageNum.value = 1;
  15. list.value = [];
  16. };
  17. /* 返回上一级页面 */
  18. const router = useRouter();
  19. /* 查询数据 */
  20. const pageNum = ref(1);
  21. const pageSize = ref(10);
  22. const total = ref(0);
  23. const resultData = ref([]);
  24. const fetchData = ref({
  25. itemTitle: '',
  26. itemSource: 'ASSIGNED',
  27. });
  28. const onSearch = () => {
  29. basicReset();
  30. onLoad();
  31. };
  32. const resetCondition = () => {
  33. basicReset();
  34. fetchData.value.itemTitle = '';
  35. onLoad();
  36. };
  37. /* 查询请求 */
  38. const queryFetch = async () => {
  39. const url = base_url + '/query';
  40. const param = {
  41. page: pageNum.value,
  42. rows: pageSize.value,
  43. params: JSON.stringify(fetchData.value)
  44. };
  45. try {
  46. const res = await proxy.$axios.post(url, param);
  47. if (res.data.code === 0) {
  48. total.value = res.data.data.total;
  49. resultData.value = res.data.data.records;
  50. } else {
  51. console.log('查询失败!' + res.data.msg);
  52. }
  53. } catch (error) {
  54. console.error('请求出错:', error);
  55. }
  56. };
  57. /* 列表加载与下拉刷新 */
  58. const list = ref([]);
  59. const refreshing = ref(false);
  60. const loading = ref(false);
  61. const finished = ref(false);
  62. const onRefresh = () => {
  63. basicReset();
  64. onLoad();
  65. };
  66. const onLoad = async () => {
  67. if (refreshing.value) {
  68. list.value = [];
  69. pageNum.value = 1;
  70. refreshing.value = false;
  71. }
  72. try {
  73. await queryFetch();
  74. if (pageSize.value * pageNum.value < total.value) {
  75. list.value = [...list.value, ...resultData.value];
  76. openStates.value = new Array(list.value.length).fill(true);
  77. pageNum.value++;
  78. } else {
  79. list.value = [...list.value, ...resultData.value];
  80. openStates.value = new Array(list.value.length).fill(true);
  81. finished.value = true;
  82. }
  83. } catch (error) {
  84. console.log(error);
  85. finished.value = true;
  86. } finally {
  87. loading.value = false;
  88. }
  89. };
  90. /**
  91. * 按钮实现swipe-cell滑动
  92. */
  93. const openStates = ref([]);
  94. const swipeCellRefs = ref([]);
  95. const getSwipeCellRef = (el, index) => {
  96. if (el) {
  97. swipeCellRefs.value[index] = el;
  98. }
  99. };
  100. const openSwipe = (idx) => {
  101. openStates.value = new Array(list.value.length).fill(true);
  102. if (idx >= 0 && idx < swipeCellRefs.value.length) {
  103. openStates.value[idx] = false;
  104. swipeCellRefs.value[idx].open('right');
  105. }
  106. document.addEventListener('click', handleDocumentClick);
  107. };
  108. const closeSwipe = (idx) => {
  109. if (idx >= 0 && idx < swipeCellRefs.value.length) {
  110. openStates.value[idx] = true;
  111. swipeCellRefs.value[idx].close();
  112. }
  113. };
  114. /** 滑动监听 **/
  115. const handleSwipeOpen = (idx) => {
  116. openStates.value[idx] = false;
  117. };
  118. const handleSwipeClose = (idx) => {
  119. openStates.value[idx] = true;
  120. };
  121. /**
  122. * 当点击滑动单元格时,开始监听点击事件
  123. */
  124. const handleDocumentClick = (event) => {
  125. openStates.value = new Array(list.value.length).fill(true);
  126. };
  127. /**
  128. * pinia读取和缓存数据
  129. */
  130. onMounted(() => {
  131. if (emergencyInfo.conditionalQueryAttributes) {
  132. fetchData.value.itemTitle = emergencyInfo.conditionalQueryAttributes;
  133. }
  134. basicReset();
  135. onLoad();
  136. })
  137. onBeforeRouteLeave((to, from, next) => {
  138. if (to.path === '/keyMatters/view' || to.path === '/keyMatters/report') {
  139. emergencyInfo.$patch({
  140. conditionalQueryAttributes: fetchData.value.itemTitle
  141. });
  142. } else {
  143. emergencyInfo.clearMainDeptInfo();
  144. }
  145. next();
  146. });
  147. </script>
  148. <template>
  149. <div class="page-container">
  150. <van-sticky>
  151. <van-nav-bar title="重点事项汇报">
  152. </van-nav-bar>
  153. <van-search
  154. v-model="fetchData.itemTitle"
  155. @search="onSearch"
  156. @clear="resetCondition"
  157. placeholder="请输入事项标题"
  158. />
  159. </van-sticky>
  160. <div class="scroll-container">
  161. <van-pull-refresh
  162. v-model="refreshing"
  163. success-text="刷新成功"
  164. @refresh="onRefresh"
  165. >
  166. <van-list
  167. class="listDiv"
  168. :immediate-check="false"
  169. v-model:loading="loading"
  170. :finished="finished"
  171. finished-text="没有更多了"
  172. @load="onLoad"
  173. >
  174. <div v-for="(item,idx) in list" :key="item.id">
  175. <van-swipe-cell
  176. title-style="color: #007aff"
  177. class="goods-card"
  178. :ref="el => getSwipeCellRef(el, idx)"
  179. @open="handleSwipeOpen(idx)"
  180. @close="handleSwipeClose(idx)"
  181. >
  182. <template #default>
  183. <div class="swipe-cell-default">
  184. <van-cell :to="{ path: '/keyMatters/view', query: { keyMatter: JSON.stringify(item) } }">
  185. <template #title>
  186. <span class="bold-title" style="margin-right: 10px">{{ item.itemTitle }}</span>
  187. <van-tag style="margin-right: 10px" :type="item.isFinished === '已完成' ? 'success' : 'danger'">{{ item.isFinished }}</van-tag>
  188. <van-tag :type="item.isOverdue === '逾期' ? 'danger' : 'success'">{{ item.isOverdue === '逾期' ? '逾期' : '未逾期' }}</van-tag>
  189. </template>
  190. <template #label>
  191. <span style="margin-right: 10px">事项内容:{{ item.itemContent }}</span>
  192. </template>
  193. </van-cell>
  194. <div class="swipe-cell-default-icon">
  195. <van-icon v-if="openStates[idx]" name="arrow-double-left" @click.stop="openSwipe(idx)" />
  196. <van-icon v-else name="arrow-double-right" @click.stop="closeSwipe(idx)" />
  197. </div>
  198. </div>
  199. </template>
  200. <template #right>
  201. <van-button class="delete-button" square type="primary" text="汇报"
  202. :to="{ path: '/keyMatters/report', query: { keyMatter: JSON.stringify(item) } }" />
  203. </template>
  204. </van-swipe-cell>
  205. </div>
  206. </van-list>
  207. </van-pull-refresh>
  208. </div>
  209. </div>
  210. </template>
  211. <style scoped>
  212. .page-container {
  213. height: 100vh; /* 关键:外层容器高度设为视口高度 */
  214. display: flex;
  215. flex-direction: column;
  216. }
  217. /* overflow-y: auto; !* 启用垂直滚动 *!*/
  218. .scroll-container {
  219. flex: 1;
  220. overflow: auto;
  221. -webkit-overflow-scrolling: touch; /* iOS 平滑滚动 */
  222. }
  223. /* 可选:隐藏滚动条(视觉优化) */
  224. .scroll-container::-webkit-scrollbar {
  225. display: none;
  226. }
  227. .goods-card {
  228. margin: 0;
  229. }
  230. .delete-button {
  231. height: 100%;
  232. }
  233. .bold-title {
  234. font-weight: bold;
  235. color: #333;
  236. }
  237. .swipe-cell-default {
  238. display: flex;
  239. background-color: #ffffff;
  240. justify-content: center;
  241. align-items: center;
  242. }
  243. .swipe-cell-default-icon {
  244. width: 60px;
  245. display: flex;
  246. justify-content: center;
  247. }
  248. </style>