index.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. <template>
  2. <view class="operation-container">
  3. <!-- 直接循环 -->
  4. <view class="section" v-for="item in menuData" :key="item.path">
  5. <view class="section-title">{{ item.meta.title }}</view>
  6. <view class="grid-container">
  7. <view
  8. class="grid-item"
  9. v-for="child in item.children"
  10. :style="{ gridColumn: child.query.span ? 'span 2' : 'span 1' }"
  11. :key="child.path"
  12. :class="child.query.type"
  13. @click="handleNavigation(child.path)"
  14. >
  15. {{ formatName(child.meta.title) }}
  16. </view>
  17. </view>
  18. </view>
  19. </view>
  20. </template>
  21. <script setup>
  22. import { ref, computed, onMounted } from "vue";
  23. import { onLoad } from "@dcloudio/uni-app";
  24. // 菜单数据和加载状态
  25. const menuData = ref([]);
  26. let menuPromise = null;
  27. //获取权限菜单 - 只调用一次
  28. async function getMenuList() {
  29. // 如果已经有数据,直接返回
  30. if (menuData.value && menuData.value.length > 0) {
  31. return menuData.value;
  32. }
  33. // 如果已有一个正在进行的请求,则返回该Promise
  34. if (menuPromise) {
  35. return menuPromise;
  36. }
  37. // 创建新的请求
  38. menuPromise = uni.$u.http
  39. .get("/app/appUser/getRouters")
  40. .then((res) => {
  41. const data = res.data;
  42. menuData.value = data.map((item) => {
  43. item.children = item.children.map((child) => {
  44. child.query = child.query ? JSON.parse(child.query) : {};
  45. return child;
  46. });
  47. return item;
  48. });
  49. return data;
  50. })
  51. .catch((err) => {
  52. // 处理错误情况
  53. console.error("获取菜单数据失败", err);
  54. return [];
  55. })
  56. .finally(() => {
  57. // 请求完成后,重置Promise
  58. menuPromise = null;
  59. });
  60. return menuPromise;
  61. }
  62. //获取按钮权限
  63. function getButtonList() {
  64. uni.$u.http.get("/app/appUser/getInfo").then((res) => {
  65. if (res.code == 200) {
  66. // 保存到本地存储
  67. uni.setStorageSync("buttonList", res.permissions);
  68. }
  69. });
  70. }
  71. //获取音频信息配置
  72. function getAudioConfig() {
  73. uni.$u.http.get("/app/appConf/getAudioConfig").then((res) => {
  74. if (res.code == 200) {
  75. uni.setStorageSync("audioConfig", res.data);
  76. }
  77. });
  78. }
  79. // 页面加载时初始化数据
  80. onLoad(() => {
  81. // 显示加载中提示
  82. uni.showLoading({
  83. title: '加载中...',
  84. mask: true
  85. });
  86. // 初始化菜单和按钮数据
  87. Promise.all([getMenuList(), getButtonList()])
  88. .finally(() => {
  89. // 数据加载完成后,隐藏加载提示
  90. uni.hideLoading();
  91. });
  92. getAudioConfig();
  93. });
  94. const formatName = (name) => {
  95. if (!name) return "";
  96. let result = name;
  97. if (result.includes("\\n\\r")) {
  98. result = result.replace(/\\n\\r/g, "\n");
  99. }
  100. return result;
  101. };
  102. // 快递操作列表
  103. const expressOperations = ref([
  104. {
  105. name: "中转\n\r签收",
  106. path: "/pages/index/express/transfer-sign",
  107. type: "primary",
  108. },
  109. {
  110. name: "到仓\n\r签收",
  111. path: "/pages/index/express/warehouse-sign",
  112. type: "warning",
  113. },
  114. {
  115. name: "重量\n\r修改",
  116. path: "/pages/index/express/weight-modify",
  117. type: "primary",
  118. },
  119. {
  120. name: "快递\n\r验收",
  121. path: "/pages/index/express/quick-check",
  122. type: "warning",
  123. },
  124. {
  125. name: "路由签收\n\r异常",
  126. path: "/pages/index/express/route-exception",
  127. type: "primary",
  128. },
  129. {
  130. name: "快递\n\r拆包",
  131. path: "/pages/index/express/quick-unpack",
  132. type: "warning",
  133. },
  134. ]);
  135. // 审核操作列表
  136. const auditOperations = ref([
  137. {
  138. name: "确认\n\r收货",
  139. path: "/pages/index/audit/confirm-receipt",
  140. type: "primary",
  141. },
  142. {
  143. name: "扫书\n\r查单",
  144. path: "/pages/index/audit/scan-order",
  145. type: "warning",
  146. },
  147. {
  148. name: "根据快递单\n\r或订单",
  149. path: "/pages/index/audit/express-order",
  150. type: "warning",
  151. },
  152. {
  153. name: "根据\n\r发件人",
  154. path: "/pages/index/audit/sender",
  155. type: "primary",
  156. },
  157. ]);
  158. // WMS操作列表
  159. const wmsOperations = ref([
  160. {
  161. name: "中等\n\r入库",
  162. path: "/pages/index/wms/medium-in",
  163. type: "primary",
  164. },
  165. {
  166. name: "良品\n\r入库",
  167. path: "/pages/index/wms/good-in",
  168. type: "warning",
  169. },
  170. {
  171. name: "次品\n\r入库",
  172. path: "/pages/index/wms/secondary-in",
  173. type: "primary",
  174. },
  175. {
  176. name: "不良\n\r入库",
  177. path: "/pages/index/wms/bad-in",
  178. type: "warning",
  179. },
  180. {
  181. name: "不良\n\r出库",
  182. path: "/pages/index/wms/bad-out",
  183. type: "primary",
  184. },
  185. {
  186. name: "不良\n\r下架",
  187. path: "/pages/index/wms/bad-off",
  188. type: "warning",
  189. },
  190. {
  191. name: "订单\n\r查询",
  192. path: "/pages/index/wms/order-query",
  193. type: "primary",
  194. },
  195. {
  196. name: "库位\n\r订单",
  197. path: "/pages/index/wms/location-order",
  198. type: "warning",
  199. },
  200. {
  201. name: "快速盘点",
  202. path: "/pages/index/wms/speedy-check",
  203. type: "primary",
  204. span: 24,
  205. },
  206. ]);
  207. // 统计操作列表
  208. const statisticsOperations = ref([
  209. {
  210. name: "审核统计",
  211. path: "/pages/index/statistic/audit",
  212. type: "warning",
  213. span: 24,
  214. },
  215. {
  216. name: "售后\n\r统计",
  217. path: "/pages/index/statistic/after-sale",
  218. type: "primary",
  219. },
  220. {
  221. name: "打包\n\r统计",
  222. path: "/pages/index/statistic/package",
  223. type: "warning",
  224. },
  225. ]);
  226. //线下核单
  227. const offlineOperations = ref([
  228. {
  229. name: "线下\n\r核单",
  230. path: "/pages/index/offline/check-order",
  231. type: "primary",
  232. },
  233. {
  234. name: "核单\n\r记录",
  235. path: "/pages/index/offline/check-record",
  236. type: "warning",
  237. },
  238. ]);
  239. //录入信息
  240. const entryOperations = ref([
  241. {
  242. name: "扫码\n\r查书",
  243. path: "/pages/index/entry/scan-book",
  244. type: "primary",
  245. },
  246. {
  247. name: "录入\n\r书籍重量",
  248. path: "/pages/index/entry/book-weight",
  249. type: "warning",
  250. },
  251. {
  252. name: "商品档案扫码",
  253. path: "/pages/index/entry/commodity-scan",
  254. type: "primary",
  255. span: 24,
  256. },
  257. ]);
  258. // 页面跳转方法
  259. const handleNavigation = (path) => {
  260. uni.navigateTo({
  261. url: path,
  262. fail: () => {
  263. uni.showToast({
  264. title: "页面跳转失败",
  265. icon: "none",
  266. });
  267. },
  268. });
  269. };
  270. </script>
  271. <style lang="scss" scoped>
  272. .operation-container {
  273. padding: 20rpx;
  274. box-sizing: border-box;
  275. /* #ifdef H5 */
  276. padding-bottom: 100rpx;
  277. /* #endif */
  278. }
  279. .section {
  280. margin-bottom: 30rpx;
  281. background: #ffffff;
  282. border-radius: 16rpx;
  283. padding: 20rpx;
  284. padding-right: 0;
  285. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
  286. .section-title {
  287. font-size: 50rpx;
  288. font-weight: 600;
  289. color: #333;
  290. padding: 20rpx;
  291. padding-top: 0;
  292. border-bottom: 2rpx solid #f0f0f0;
  293. margin-bottom: 20rpx;
  294. }
  295. .grid-container {
  296. display: flex;
  297. flex-wrap: wrap;
  298. padding: 10rpx;
  299. .grid-item {
  300. width: calc(50% - 20rpx);
  301. min-height: 148rpx;
  302. display: flex;
  303. align-items: center;
  304. justify-content: center;
  305. text-align: center;
  306. padding: 20rpx 30rpx;
  307. line-height: 60rpx;
  308. font-size: 50rpx;
  309. border-radius: 12rpx;
  310. color: #ffffff;
  311. transition: all 0.3s;
  312. white-space: pre-wrap;
  313. box-sizing: border-box;
  314. margin-right: 20rpx;
  315. margin-bottom: 20rpx;
  316. &[style*="grid-column: span 2"] {
  317. width: calc(100% - 20rpx);
  318. margin-right: 20rpx;
  319. }
  320. &.primary {
  321. background: linear-gradient(135deg, #4cd964, #3ac555);
  322. &:active {
  323. background: linear-gradient(135deg, #3ac555, #2fb548);
  324. }
  325. }
  326. &.warning {
  327. background: linear-gradient(135deg, #ff9500, #ff8000);
  328. &:active {
  329. background: linear-gradient(135deg, #ff8000, #e67300);
  330. }
  331. }
  332. &:active {
  333. transform: scale(0.98);
  334. }
  335. }
  336. }
  337. }
  338. </style>