index.vue 8.9 KB

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