Alex 9 ヶ月 前
コミット
a63783bc11
62 ファイル変更1958 行追加789 行削除
  1. 6 9
      App.vue
  2. 52 0
      config/permission.js
  3. 71 66
      config/request.js
  4. 3 1
      main.js
  5. 6 0
      pages.json
  6. 59 0
      pages/index/detail/components/AuditInfo.vue
  7. 61 49
      pages/index/detail/components/BookInfo.vue
  8. 67 37
      pages/index/detail/components/UserInfoCard.vue
  9. 200 162
      pages/index/detail/index.vue
  10. 54 0
      pages/index/detail/user-orders.vue
  11. 1 1
      pages/index/entry/book-weight.vue
  12. 2 2
      pages/index/express/components/ExceptionItem.vue
  13. 19 8
      pages/index/express/quick-check.vue
  14. 2 1
      pages/index/express/quick-unpack.vue
  15. 1 1
      pages/index/express/transfer-sign.vue
  16. 1 1
      pages/index/express/warehouse-sign.vue
  17. 2 1
      pages/index/express/weight-modify.vue
  18. 14 2
      pages/index/index.vue
  19. 2 1
      pages/index/offline/check-order.vue
  20. 1 1
      pages/index/wms/bad-in.vue
  21. 14 2
      pages/index/wms/bad-out-order.vue
  22. 15 0
      pages/index/wms/bad-out.vue
  23. 1 1
      pages/index/wms/components/BadOutCard.vue
  24. 139 123
      pages/index/wms/location-select.vue
  25. 18 5
      pages/index/wms/speedy-check.vue
  26. 12 25
      pages/index/wms/task-detail.vue
  27. 25 16
      pages/login/login.vue
  28. 44 44
      pages/my/components/orderItem.vue
  29. 0 0
      unpackage/dist/build/app-plus/app-config-service.js
  30. 0 0
      unpackage/dist/build/app-plus/app-service.js
  31. 0 0
      unpackage/dist/build/app-plus/pages/index/audit/isbn-order.css
  32. 0 0
      unpackage/dist/build/app-plus/pages/index/audit/sender.css
  33. 0 0
      unpackage/dist/build/app-plus/pages/index/detail/book-audit.css
  34. 0 0
      unpackage/dist/build/app-plus/pages/index/detail/index.css
  35. 0 0
      unpackage/dist/build/app-plus/pages/index/detail/user-orders.css
  36. 0 0
      unpackage/dist/build/app-plus/pages/index/express/quick-check.css
  37. 0 0
      unpackage/dist/build/app-plus/pages/index/express/quick-unpack.css
  38. 0 0
      unpackage/dist/build/app-plus/pages/index/express/route-exception.css
  39. 0 0
      unpackage/dist/build/app-plus/pages/index/express/transfer-sign.css
  40. 0 0
      unpackage/dist/build/app-plus/pages/index/express/warehouse-sign.css
  41. 0 0
      unpackage/dist/build/app-plus/pages/index/express/weight-modify.css
  42. 1 1
      unpackage/dist/build/app-plus/pages/index/index.css
  43. 0 0
      unpackage/dist/build/app-plus/pages/index/offline/check-order.css
  44. 0 0
      unpackage/dist/build/app-plus/pages/index/wms/bad-in.css
  45. 0 0
      unpackage/dist/build/app-plus/pages/index/wms/bad-out-order.css
  46. 0 0
      unpackage/dist/build/app-plus/pages/index/wms/location-select.css
  47. 0 0
      unpackage/dist/build/app-plus/pages/index/wms/order-query-list.css
  48. 0 0
      unpackage/dist/build/app-plus/pages/index/wms/speedy-check.css
  49. 0 0
      unpackage/dist/build/app-plus/pages/index/wms/task-detail.css
  50. 0 0
      unpackage/dist/build/app-plus/pages/login/login.css
  51. 0 0
      unpackage/dist/build/app-plus/pages/my/page/audit-unfinished.css
  52. 0 0
      unpackage/dist/dev/app-plus/app-config-service.js
  53. 157 169
      unpackage/dist/dev/app-plus/app-service.js
  54. 2 2
      unpackage/dist/dev/app-plus/pages/index/audit/isbn-order.css
  55. 2 2
      unpackage/dist/dev/app-plus/pages/index/audit/sender.css
  56. 22 0
      unpackage/dist/dev/app-plus/pages/index/detail/book-audit.css
  57. 2 2
      unpackage/dist/dev/app-plus/pages/index/detail/index.css
  58. 799 0
      unpackage/dist/dev/app-plus/pages/index/detail/user-orders.css
  59. 9 9
      unpackage/dist/dev/app-plus/pages/index/wms/location-select.css
  60. 1 1
      unpackage/dist/dev/app-plus/pages/login/login.css
  61. 2 2
      unpackage/dist/dev/app-plus/pages/my/page/audit-unfinished.css
  62. 69 42
      utils/VolumeTTS.js

+ 6 - 9
App.vue

@@ -10,15 +10,12 @@ let touchHandler;
 
 onLaunch(() => {
     // 尝试去获取本地的 token 和用户信息,填充到 store 中
-    if (!store.token) {
-        let token = uni.getStorageSync("token");
-        if (token) {
-            store.setToken(token);
-            let userInfo = uni.getStorageSync("userInfo");
-            if (userInfo) {
-                if (userInfo.userId) {
-                    store.setUserInfo(userInfo);
-                }
+    let token = uni.getStorageSync("token");
+    if (token) {
+        let userInfo = uni.getStorageSync("userInfo");
+        if (userInfo) {
+            if (userInfo.userId) {
+                store.setUserInfo(userInfo);
             }
         }
     }

+ 52 - 0
config/permission.js

@@ -0,0 +1,52 @@
+/**
+ * 自定义权限指令
+ * 用法:v-permission="'system:user:add'"
+ * 如果用户有该权限,则显示元素;否则隐藏元素
+ * 特殊情况:如果用户权限列表包含'*:*:*',则显示所有元素
+ */
+
+export const permission = {
+  // 在绑定元素的父组件挂载时调用
+  mounted(el, binding) {
+    const { value } = binding
+    
+    // 获取用户按钮权限列表
+    const buttonList = uni.getStorageSync('buttonList') || []
+    
+    // 检查权限
+    const hasPermission = checkPermission(value, buttonList)
+    
+    if (!hasPermission) {
+      // 如果没有权限,则移除元素
+      el.parentNode && el.parentNode.removeChild(el)
+    }
+  }
+}
+
+/**
+ * 检查用户是否拥有某项权限
+ * @param {String} permission 要检查的权限标识
+ * @param {Array} buttonList 用户拥有的按钮权限列表
+ * @returns {Boolean} 是否拥有权限
+ */
+export function checkPermission(permission, buttonList) {
+  // 如果未设置权限或按钮权限列表为空,则认为没有权限
+  if (!permission || !buttonList || buttonList.length === 0) {
+    return false
+  }
+  
+  // 特殊情况:如果权限列表中包含'*:*:*',则拥有所有权限
+  if (buttonList.includes('*:*:*')) {
+    return true
+  }
+  
+  // 判断是否拥有某项权限
+  return buttonList.includes(permission)
+}
+
+// 在main.js中可以全局注册这个指令
+export default {
+  install(app) {
+    app.directive('permission', permission)
+  }
+} 

+ 71 - 66
config/request.js

@@ -1,73 +1,78 @@
-import {
-	store
-} from '@/store/index.js'
 /**
  * 文档地址:https://uiadmin.net/uview-plus/js/http.html
  */
-const baseUrl = 'https://bk.shuhi.com'
+const baseUrl = "https://bpi.shuhi.com";
 export function initRequest() {
-	console.log('初始化了 http 请求代码')
-	// 初始化请求配置
-	uni.$u.http.setConfig((config) => {
-		/* config 为默认全局配置*/
-		// config.baseURL = `http://192.168.1.2:8080`; /* 根域名 */
-		config.baseURL = baseUrl; /* 根域名 */
-		config.custom.toast = true // 默认消息有msg会显示出来
-		return config
-	})
-	// 请求拦截
-	uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作
-		// console.log('请求拦截', config)
-		// 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
-		config.data = config.data || {}
-		// 挂载 token
-		let token = store.token || uni.getStorageSync('token')
-		config.header.Authorization = token ? `Bearer ${token}` : ''
-		return config
-	}, config => { // 可使用async await 做异步操作
-		return Promise.reject(config)
-	})
+    console.log("初始化了 http 请求代码");
+    // 初始化请求配置
+    uni.$u.http.setConfig((config) => {
+        /* config 为默认全局配置*/
+        // config.baseURL = `http://192.168.1.2:8080`; /* 根域名 */
+        config.baseURL = baseUrl; /* 根域名 */
+        config.custom.toast = true; // 默认消息有msg会显示出来
+        config.sslVerify = false; // 忽略 SSL 证书验证
+        return config;
+    });
+    // 请求拦截
+    uni.$u.http.interceptors.request.use(
+        (config) => {
+            // 可使用async await 做异步操作
+            // console.log('请求拦截', config)
+            // 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
+            config.data = config.data || {};
+            // 挂载 token
+            let token = uni.getStorageSync("token");
+            config.header.Authorization = token ? `Bearer ${token}` : "";
+            return config;
+        },
+        (config) => {
+            // 可使用async await 做异步操作
+            return Promise.reject(config);
+        }
+    );
 
-	// 响应拦截
-	uni.$u.http.interceptors.response.use((response) => {
-		/* 对响应成功做点什么 可使用async await 做异步操作*/
-		// console.log('响应拦截', response)
-		const data = response.data
-		// 自定义参数
-		const custom = response.config?.custom
-		if (data.code !== 200) {
-			// 身份认证失败,需要重新登录
-			if (data.code === 401) {
-				uni.$u.toast(data.msg || '身份认证失败,请先登录')
-				uni.removeStorageSync('token')
-				store.setToken('') // 清空token
-				setTimeout(() => {
-					uni.$u.route({
-						type: 'reLaunch',
-						url: '/pages/login/login' // 跳转到登录页
-					})
-				}, 1000)
-			} else {
-				// 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
-				if (custom.toast !== false) {
-					uni.$u.toast(data.msg)
-				}
-				// 如果需要catch返回,则进行reject
-				// if (custom?.catch) {
-				//     return Promise.reject(data)
-				// } else {
-				//     // 否则返回一个pending中的promise,请求不会进入catch中
-				//     return new Promise(() => { })
-				// }
-				return data
-			}
-		}
-		// return data.data === undefined ? {} : data.data
-		return data // 这里视不同的后端返回数据格式而定
-	}, (response) => {
-		// 对响应错误做点什么 (statusCode !== 200)
-		return Promise.reject(response)
-	})
+    // 响应拦截
+    uni.$u.http.interceptors.response.use(
+        (response) => {
+            /* 对响应成功做点什么 可使用async await 做异步操作*/
+            // console.log('响应拦截', response)
+            const data = response.data;
+            // 自定义参数
+            const custom = response.config?.custom;
+            if (data.code !== 200) {
+                // 身份认证失败,需要重新登录
+                if (data.code === 401) {
+                    uni.$u.toast(data.msg || "身份认证失败,请先登录");
+                    uni.removeStorageSync("token");
+                    setTimeout(() => {
+                        uni.$u.route({
+                            type: "reLaunch",
+                            url: "/pages/login/login", // 跳转到登录页
+                        });
+                    }, 1000);
+                } else {
+                    // 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
+                    if (custom.toast !== false) {
+                        uni.$u.toast(data.msg);
+                    }
+                    // 如果需要catch返回,则进行reject
+                    // if (custom?.catch) {
+                    //     return Promise.reject(data)
+                    // } else {
+                    //     // 否则返回一个pending中的promise,请求不会进入catch中
+                    //     return new Promise(() => { })
+                    // }
+                    return data;
+                }
+            }
+            // return data.data === undefined ? {} : data.data
+            return data; // 这里视不同的后端返回数据格式而定
+        },
+        (response) => {
+            // 对响应错误做点什么 (statusCode !== 200)
+            return Promise.reject(response);
+        }
+    );
 }
 
-export default baseUrl
+export default baseUrl;

+ 3 - 1
main.js

@@ -7,6 +7,8 @@ import share from '/config/share.js'
 import {
 	initRequest
 } from '@/config/request.js'
+// 引入权限指令
+import permissionDirective from '@/config/permission.js'
 
 import VolumeTTS from '@/utils/VolumeTTS.js'
 let ttsModule = new VolumeTTS()
@@ -52,7 +54,7 @@ export function createApp() {
 	// 引入请求封装方法并执行
 	initRequest()
 	const pinia = createPinia()
-	app.use(pinia).use(uviewPlus)
+	app.use(pinia).use(uviewPlus).use(permissionDirective)
 	app.mixin(share)
 	return {
 		app,

+ 6 - 0
pages.json

@@ -100,6 +100,12 @@
 						"navigationBarTitleText": "根据快递单号或订单号查询"
 					}
 				},
+                {
+                    "path": "detail/user-orders",
+                    "style": {
+                        "navigationBarTitleText": "用户所有订单"
+                    }
+                },
 				{
 					"path": "detail/index",
 					"style": {

+ 59 - 0
pages/index/detail/components/AuditInfo.vue

@@ -38,6 +38,12 @@
                 </view>
             </view>
         </view>
+        
+        <!-- 悬浮排序按钮 -->
+        <view class="floating-sort-btn" @click="sortByAuditStatus">
+            <u-icon name="list" color="#FFFFFF" size="22"></u-icon>
+            <text class="btn-text">排序</text>
+        </view>
     </view>
 </template>
 
@@ -64,6 +70,7 @@ const initAuditList = (detail) => {
         isbn: detail.isbn,
         comList: item.com ? (typeof item.com === "string" ? item.com.split(",") : item.com) : [],
     }));
+    sortByAuditStatus();
 };
 watch(
     () => props.detail,
@@ -131,9 +138,38 @@ const toggleReason = (audit, index, item) => {
     auditCommentList.value[index] = audit;
 };
 
+/**
+ * 排序审核列表,未审核的放在前面,已审核的放在后面
+ * @returns {Array} 排序后的审核列表
+ */
+const sortByAuditStatus = () => {
+    // 创建一个新数组避免直接修改原数组的顺序
+    const sortedList = [...auditCommentList.value];
+    
+    // 排序:未审核状态(sts===0)的放前面,已审核的(sts===1或sts===3)放后面
+    sortedList.sort((a, b) => {
+        // 如果a是未审核(0),而b是已审核(1或3),则a排在前面
+        if (a.sts === 0 && (b.sts === 1 || b.sts === 3)) {
+            return -1;
+        }
+        // 如果b是未审核(0),而a是已审核(1或3),则b排在前面
+        if (b.sts === 0 && (a.sts === 1 || a.sts === 3)) {
+            return 1;
+        }
+        // 其他情况保持原顺序
+        return 0;
+    });
+    
+    // 更新引用,保持响应性
+    auditCommentList.value = sortedList;
+    
+    return sortedList;
+};
+
 defineExpose({
     formatReason,
     initAuditList,
+    sortByAuditStatus,
 });
 </script>
 
@@ -157,4 +193,27 @@ defineExpose({
 .disabled {
     background-color: #d0d0d0;
 }
+
+/* 悬浮排序按钮样式 */
+.floating-sort-btn {
+    position: fixed;
+    right: 20rpx;
+    bottom: 30%;
+    width: 90rpx;
+    height: 90rpx;
+    background: linear-gradient(135deg, #2b85e4, #5cadff);
+    border-radius: 50%;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    z-index: 999;
+    box-shadow: 0 4px 12px rgba(43, 133, 228, 0.3);
+}
+
+.btn-text {
+    font-size: 24rpx;
+    color: #FFFFFF;
+    margin-top: 4rpx;
+}
 </style>

+ 61 - 49
pages/index/detail/components/BookInfo.vue

@@ -9,8 +9,14 @@
             </view>
         </template>
 
-        <view class="book-info-item bg-white mt-12" :style="{ backgroundColor: item.backgroundColor }"
-            v-for="item in formatList" :key="item.title" :id="item.id" v-show="item?.title">
+        <view
+            class="book-info-item bg-white mt-12"
+            :style="{ backgroundColor: item.backgroundColor }"
+            v-for="item in formatList"
+            :key="item.title"
+            :id="item.id"
+            v-show="item?.title"
+        >
             <view class="book-info-item-title">{{ item.title }}</view>
             <view class="book-info-item-list">
                 <BookItem v-for="book in item.list" :key="book.bookId" :item="book" @click="handleBookClick(book)" />
@@ -20,9 +26,9 @@
 </template>
 
 <script setup>
-import { ref, watch, computed } from 'vue';
-import BookItem from './BookItem.vue';
-import toPinyin from "@/utils/toPinyin.js"
+import { ref, watch, computed } from "vue";
+import BookItem from "./BookItem.vue";
+import toPinyin from "@/utils/toPinyin.js";
 const props = defineProps({
     bookList: {
         type: Array,
@@ -30,45 +36,48 @@ const props = defineProps({
     },
     detail: {
         type: Object,
-        default: () => ({})
+        default: () => ({}),
     },
     isShow: {
         type: Boolean,
-        default: true
-    }
-})
+        default: true,
+    },
+});
 
-const emit = defineEmits(['get-all-firstLetter'])
+const emit = defineEmits(["get-all-firstLetter"]);
 
 //计算已审书籍数量
 const auditNum = computed(() => {
-    return props.bookList.reduce((total, item) => total + item.auditCommentList?.length || 0, 0)
-})
+    return props.bookList.reduce((total, item) => {
+        let num = item.auditCommentList?.filter((v) => v.sts != 0).length || 0;
+        return total + num;
+    }, 0);
+});
 
 function handleBookClick(book) {
     if (props.detail.status >= 10) {
-        uni.$u.ttsModule.speak('订单已审核完成')
-        return
+        uni.$u.ttsModule.speak("订单已审核完成");
+        return;
     }
-   
+
     uni.navigateTo({
-        url: `/pages/index/detail/book-audit?isbn=${book.isbn}&orderId=${props.detail.orderId}`
-    })
-    uni.setStorageSync('auditBook', book)
+        url: `/pages/index/detail/book-audit?isbn=${book.isbn}&orderId=${props.detail.orderId}`,
+    });
+    uni.setStorageSync("auditBook", book);
 }
 
 function getAuditCateNum(cate) {
-    let auditList = []
-    props.bookList.forEach(v => {
-        auditList.push(...(v.auditCommentList || []))
-    })
-    return auditList.filter(v => v.sts == cate).length
+    let auditList = [];
+    props.bookList.forEach((v) => {
+        auditList.push(...(v.auditCommentList || []));
+    });
+    return auditList.filter((v) => v.sts == cate).length;
 }
 
 //格式化书籍列表
 const formatBookList = (list) => {
-    const poorBooks = { title: '极差', list: [], backgroundColor: '#de868f', id: 'poor' };
-    const goodBooks = { title: '良好', list: [], backgroundColor: '#81b337', id: 'good' };
+    const poorBooks = { title: "极差", list: [], backgroundColor: "#de868f", id: "poor" };
+    const goodBooks = { title: "良好", list: [], backgroundColor: "#81b337", id: "good" };
     const otherBooks = [];
     //获取所有的首字母
     const allFirstLetter = [];
@@ -79,7 +88,8 @@ const formatBookList = (list) => {
         let firstChineseChar = null;
         for (let i = 0; i < book.bookName.length; i++) {
             const char = book.bookName.charAt(i);
-            if (/^[\u4E00-\u9FA5]$/.test(char)) { // 检查是否为中文
+            if (/^[\u4E00-\u9FA5]$/.test(char)) {
+                // 检查是否为中文
                 firstChineseChar = char;
                 break;
             }
@@ -97,30 +107,30 @@ const formatBookList = (list) => {
                 firstLetter = char;
             }
         }
-        
-        let bool = otherBooks.some(item => item.title == firstLetter);
+
+        let bool = otherBooks.some((item) => item.title == firstLetter);
         if (!bool) {
             otherBooks.push({ id: firstLetter, title: firstLetter, list: [{ ...book }] });
-            allFirstLetter.push(firstLetter)
-            emit('get-all-firstLetter', allFirstLetter)
+            allFirstLetter.push(firstLetter);
+            emit("get-all-firstLetter", allFirstLetter);
         } else {
-            otherBooks.find(item => item.title == firstLetter).list.push(book);
+            otherBooks.find((item) => item.title == firstLetter).list.push(book);
         }
     };
 
-    list.forEach(book => {
-        book.goodNum = book.auditCommentList?.filter(v => v.sts == 1).length || 0
-        book.badNum = book.auditCommentList?.filter(v => v.sts == 3).length || 0
+    list.forEach((book) => {
+        book.goodNum = book.auditCommentList?.filter((v) => v.sts == 1).length || 0;
+        book.badNum = book.auditCommentList?.filter((v) => v.sts == 3).length || 0;
 
         // Check if book is fully audited (all items have been reviewed)
-        const totalAudited = book.auditCommentList?.filter(v => v.sts !== 0).length || 0;
+        const totalAudited = book.auditCommentList?.filter((v) => v.sts !== 0).length || 0;
         const isFullyAudited = totalAudited === book.num;
 
         if (isFullyAudited) {
             // If any audit result is poor (sts === 3), push to poorBooks
-            if (book.auditCommentList.some(v => v.sts === 3)) {
+            if (book.auditCommentList.some((v) => v.sts === 3)) {
                 poorBooks.list.push(book);
-            } else if (book.auditCommentList.every(v => v.sts === 1)) {
+            } else if (book.auditCommentList.every((v) => v.sts === 1)) {
                 // If all audit results are good (sts === 1), push to goodBooks
                 goodBooks.list.push(book);
             } else {
@@ -132,21 +142,23 @@ const formatBookList = (list) => {
     });
 
     return { poorBooks, goodBooks, otherBooks };
-}
+};
 
 const formatList = ref([]);
-watch(() => props.bookList, (newVal) => {
-    let { poorBooks, goodBooks, otherBooks } = formatBookList(newVal);
-
-    // 按照首字母排序 A-Z
-    otherBooks.sort((a, b) => a.id.localeCompare(b.id));
+watch(
+    () => props.bookList,
+    (newVal) => {
+        let { poorBooks, goodBooks, otherBooks } = formatBookList(newVal);
 
-    let poor = poorBooks.list.length > 0 ? poorBooks : {}
-    let good = goodBooks.list.length > 0 ? goodBooks : {}
-    formatList.value = [...otherBooks, poor, good]
-
-}, { immediate: true, deep: true });
+        // 按照首字母排序 A-Z
+        otherBooks.sort((a, b) => a.id.localeCompare(b.id));
 
+        let poor = poorBooks.list.length > 0 ? poorBooks : {};
+        let good = goodBooks.list.length > 0 ? goodBooks : {};
+        formatList.value = [...otherBooks, poor, good];
+    },
+    { immediate: true, deep: true }
+);
 </script>
 
 <style scoped>
@@ -156,4 +168,4 @@ watch(() => props.bookList, (newVal) => {
     font-weight: 600;
     border-bottom: 1px solid #e5e5e5;
 }
-</style>
+</style>

+ 67 - 37
pages/index/detail/components/UserInfoCard.vue

@@ -1,7 +1,7 @@
 <template>
     <view class="user-info-card bg-white mt-16">
         <view class="header">
-            <text style="color: #666;">{{ detail.orderTime }}</text>
+            <text style="color: #666">{{ detail.orderTime }}</text>
             <text @click="showModal = true" class="color-green">[查看订单日志]</text>
         </view>
         <view class="content flex flex-j-b">
@@ -9,23 +9,33 @@
 
             <view class="flex flex-a-e flex-1 ml-12">
                 <view class="flex flex-d flex-1">
-                    <text class="color-green">{{ formattedName }}<text style="color: #e99d42;">(所有单)</text></text>
-                    <text class="common-text" style="margin-top: 10rpx;">共卖出{{ detail.totalNum }}本书</text>
+                    <text class="color-green" @click="handleUserOrders"
+                        >{{ formattedName }}<text style="color: #e99d42">(所有单)</text></text
+                    >
+                    <text class="common-text" style="margin-top: 10rpx">共卖出{{ detail.totalNum }}本书</text>
                     <text class="common-text">来自{{ detail.sendSsq }}</text>
-                    <text class="common-text" style="margin-top: 10rpx;">用户状态: <text :class="statusClass">{{
-                        detail.userStatus == 1 ? '正常' :
-                            detail.userStatus == 2 ? '黑名单' : '-'
-                            }}</text></text>
+                    <text class="common-text" style="margin-top: 10rpx"
+                        >用户状态:
+                        <text :class="statusClass">{{
+                            detail.userStatus == 1 ? "正常" : detail.userStatus == 2 ? "黑名单" : "-"
+                        }}</text></text
+                    >
                 </view>
 
-                <text style="min-width: 160rpx;" @click="toggleBlacklist" class="color-red">[{{ blacklistAction
-                    }}]</text>
+                <text style="min-width: 160rpx" @click="toggleBlacklist" class="color-red"
+                    >[{{ blacklistAction }}]</text
+                >
             </view>
         </view>
 
-        <u-modal v-model:show="showModal" title="订单日志" :showCancelButton="false" confirmText="关闭"
-            @confirm="showModal = false" class="log-modal">
-
+        <u-modal
+            v-model:show="showModal"
+            title="订单日志"
+            :showCancelButton="false"
+            confirmText="关闭"
+            @confirm="showModal = false"
+            class="log-modal"
+        >
             <view class="log-container">
                 <view class="log-header">
                     <text>描述</text>
@@ -38,61 +48,81 @@
                     <text class="log-item-time">{{ log.createTime }}</text>
                 </view>
             </view>
-
         </u-modal>
 
-        <u-modal v-model:show="showBlacklistModal" title="拉黑用户" :showCancelButton="true" confirmText="提交"
-            cancelText="取消" @confirm="confirmBlacklist" @cancel="showBlacklistModal = false">
-            <textarea class="reason-textarea" placeholder="请输入拉黑原因..." autoHeight bg-color="#f8f8f8"
-                border-radius="10rpx" v-model="reason" height="100px"></textarea>
+        <u-modal
+            v-model:show="showBlacklistModal"
+            title="拉黑用户"
+            :showCancelButton="true"
+            confirmText="提交"
+            cancelText="取消"
+            @confirm="confirmBlacklist"
+            @cancel="showBlacklistModal = false"
+        >
+            <textarea
+                class="reason-textarea"
+                placeholder="请输入拉黑原因..."
+                autoHeight
+                bg-color="#f8f8f8"
+                border-radius="10rpx"
+                v-model="reason"
+                height="100px"
+            ></textarea>
         </u-modal>
     </view>
 </template>
 
 <script setup>
-import { ref, computed } from 'vue';
+import { ref, computed } from "vue";
 
 const props = defineProps({
     detail: {
         type: Object,
-        default: () => ({})
-    }
+        default: () => ({}),
+    },
 });
 
+const handleUserOrders = () => {
+    uni.navigateTo({
+        url: `/pages/index/detail/user-orders?userId=${props.detail.userId}`,
+    });
+};
 const formattedName = computed(() => {
-    return props.detail?.userNick?.charAt(0) + '**';
+    return props.detail?.userNick?.charAt(0) + "**";
 });
 
 const statusClass = computed(() => {
-    return props.detail.userStatus == 1 ? 'color-green' : 'color-red';
+    return props.detail.userStatus == 1 ? "color-green" : "color-red";
 });
 
 const blacklistAction = computed(() => {
-    return props.detail.userStatus == 1 ? '加入黑名单' : '移除黑名单';
+    return props.detail.userStatus == 1 ? "加入黑名单" : "移除黑名单";
 });
 
 const showModal = ref(false);
 const showBlacklistModal = ref(false);
-const reason = ref('');
+const reason = ref("");
 
 const toggleBlacklist = () => {
     showBlacklistModal.value = true;
 };
 
 const confirmBlacklist = () => {
-    let apiStr = props.detail.userStatus == 1 ? '/app/appUser/setUserBlack' : 'app/appUser/removeUserBlack';
-    uni.$u.http.post(apiStr, {
-        userId: props.detail.userId,
-        reason: reason.value
-    }).then(res => {
-        if (res.code == 200) {
-            uni.$u.toast('操作成功');
-            showBlacklistModal.value = false;
-            props.detail.userStatus = props.detail.userStatus == 1 ? 2 : 1;
-        } else {
-            uni.$u.toast(res.msg);
-        }
-    });
+    let apiStr = props.detail.userStatus == 1 ? "/app/appUser/setUserBlack" : "app/appUser/removeUserBlack";
+    uni.$u.http
+        .post(apiStr, {
+            userId: props.detail.userId,
+            reason: reason.value,
+        })
+        .then((res) => {
+            if (res.code == 200) {
+                uni.$u.toast("操作成功");
+                showBlacklistModal.value = false;
+                props.detail.userStatus = props.detail.userStatus == 1 ? 2 : 1;
+            } else {
+                uni.$u.toast(res.msg);
+            }
+        });
 };
 </script>
 

+ 200 - 162
pages/index/detail/index.vue

@@ -3,8 +3,9 @@
         <scroll-view class="scroller" :scroll-into-view="toView" scroll-y="true" scroll-with-animation="true">
             <view class="flex flex-a-c flex-j-b bg-white bind-audit mb-16">
                 <text>绑定审核员</text>
-                <text class="text-center flex-1">{{ orderDetail.auditUserName || selectedAuditor?.userName || ''
-                    }}</text>
+                <text class="text-center flex-1">{{
+                    orderDetail.auditUserName || selectedAuditor?.userName || ""
+                }}</text>
                 <text @click="showAuditorSelector = true" class="color-primary">绑定</text>
             </view>
 
@@ -12,18 +13,27 @@
 
             <UserInfoCard :detail="orderDetail" />
 
-            <view class="mt-16" style="padding: 0 6rpx;">
-                <u-subsection :list="list" mode="subsection" :current="current"
-                    @change="handleSectionChange"></u-subsection>
-                <BookInfo v-if="current == 0" :bookList="orderDetail.detailVoList" :detail="orderDetail"
-                    @get-all-firstLetter="onGetAllFirstLetter" />
+            <view class="mt-16" style="padding: 0 6rpx">
+                <u-subsection
+                    :list="list"
+                    mode="subsection"
+                    :current="current"
+                    @change="handleSectionChange"
+                ></u-subsection>
+                <BookInfo
+                    v-if="current == 0"
+                    :bookList="orderDetail.detailVoList"
+                    :detail="orderDetail"
+                    @get-all-firstLetter="onGetAllFirstLetter"
+                />
                 <LogisticsTimeline v-if="current == 1" :list="orderDetail.trackingVoList" />
                 <FileInfo v-if="current == 2" :orderId="orderDetail.orderId" />
             </view>
         </scroll-view>
 
         <view class="fixed-left">
-            <view class="bind-code common-bg" style="margin-bottom: 30px;padding:20rpx" @click="handleBindCode">绑码
+            <view class="bind-code common-bg" style="margin-bottom: 30px; padding: 20rpx" @click="handleBindCode"
+                >绑码
             </view>
 
             <view class="common-bg flex flex-a-c flex-j-c flex-d">
@@ -35,16 +45,20 @@
 
         <view class="fixed-right">
             <view class="letter-bg flex flex-a-c flex-j-c flex-d">
-                <view class="letter-item"><u-icon name="arrow-up-fill" size="20" color="#ffffff"
-                        @click="scrollToTop"></u-icon></view>
+                <view class="letter-item"
+                    ><u-icon name="arrow-up-fill" size="20" color="#ffffff" @click="scrollToTop"></u-icon
+                ></view>
                 <view class="letter-item" v-for="item in allLetters" @click="scrollToView(item)">{{ item }}</view>
             </view>
         </view>
 
         <view class="common-bg fixed-bottom" v-if="type != 2">
-            <u-button type="warning" size="large" v-if="orderDetail.status == 5"
-                @click="handleLogisticsConfirm">物流签收</u-button>
-            <u-button type="primary" size="large" v-if="orderDetail.status == 6" @click="handleConfirm">确认收货</u-button>
+            <u-button type="warning" size="large" v-if="orderDetail.status == 5" @click="handleLogisticsConfirm"
+                >物流签收</u-button
+            >
+            <u-button type="primary" size="large" v-if="orderDetail.status == 6" @click="handleConfirm"
+                >确认收货</u-button
+            >
 
             <template v-if="orderDetail.status == 8 || orderDetail.status == 9 || orderDetail.status == 10">
                 <u-button type="warning" size="large" @click="handleScanCode">扫码</u-button>
@@ -52,228 +66,254 @@
             </template>
         </view>
 
-        <AuditorSelector :show="showAuditorSelector" @update:show="showAuditorSelector = $event"
-            @auditor-selected="handleAuditorSelected" />
+        <AuditorSelector
+            :show="showAuditorSelector"
+            @update:show="showAuditorSelector = $event"
+            @auditor-selected="handleAuditorSelected"
+        />
     </view>
 </template>
 
 <script setup>
-import { ref } from 'vue';
-import { onLoad, onShow } from '@dcloudio/uni-app';
-import AuditorSelector from './components/AuditorSelector.vue';
-import OrderInfo from './components/OrderInfo.vue';
-import UserInfoCard from './components/UserInfoCard.vue';
-import LogisticsTimeline from '../express/components/LogisticsTimeline.vue';
-import BookInfo from './components/BookInfo.vue';
-import FileInfo from './components/FileInfo.vue';
+import { ref } from "vue";
+import { onLoad, onShow } from "@dcloudio/uni-app";
+import AuditorSelector from "./components/AuditorSelector.vue";
+import OrderInfo from "./components/OrderInfo.vue";
+import UserInfoCard from "./components/UserInfoCard.vue";
+import LogisticsTimeline from "../express/components/LogisticsTimeline.vue";
+import BookInfo from "./components/BookInfo.vue";
+import FileInfo from "./components/FileInfo.vue";
 
 const showAuditorSelector = ref(false);
 const selectedAuditor = ref({});
 const handleAuditorSelected = (auditor) => {
     selectedAuditor.value = auditor;
-    orderDetail.value.auditUserId = auditor.userId
-    orderDetail.value.auditUserName = auditor.userName
+    orderDetail.value.auditUserId = auditor.userId;
+    orderDetail.value.auditUserName = auditor.userName;
+
+    uni.setStorageSync("checkUserInfo", {
+        userName: auditor.userName,
+        userId: auditor.userId,
+    });
 };
 
 //点击滚动的位置
-const toView = ref('')
+const toView = ref("");
 function scrollToView(to) {
-    toView.value = to
+    toView.value = to;
 
     uni.pageScrollTo({
-        selector: '#' + to,
-        duration: 200
-    })
+        selector: "#" + to,
+        duration: 200,
+    });
 }
 //回到顶部
 function scrollToTop() {
     uni.pageScrollTo({
         top: 0,
-        duration: 200
-    })
+        duration: 200,
+    });
 }
 
 //绑码
 function handleBindCode() {
-    uni.$u.toast('暂无开发')
+    uni.$u.toast("暂无开发");
 }
 
-
-const list = ref(['图书清单', '物流信息', '上传附件']);
+const list = ref(["图书清单", "物流信息", "上传附件"]);
 const current = ref(0);
 const handleSectionChange = (index) => {
     current.value = index;
-}
+};
 
 //监听书籍的首字母
-const allLetters = ref([])
+const allLetters = ref([]);
 function onGetAllFirstLetter(data) {
-    allLetters.value = data
+    allLetters.value = data;
 }
 
 //物流签收 /app/orderinfo/signLogistics
 function handleLogisticsConfirm() {
     uni.showModal({
-        title: '提示',
-        content: '是否确认物流签收?',
+        title: "提示",
+        content: "是否确认物流签收?",
         success: (res) => {
             if (res.confirm) {
-                uni.showLoading({ title: '加载中...', mask: true })
-                uni.$u.http.post('/app/orderinfo/signLogistics', {
-                    params: {
+                uni.showLoading({ title: "加载中...", mask: true });
+                uni.$u.http
+                    .post("/app/orderinfo/signLogistics", {
                         searchType: 1,
-                        "search": orderId.value
-                    }
-                }).then(res => {
-                    if (res.code == 200) {
-                        uni.showToast({ title: '签收成功', icon: 'none' })
-                        uni.$u.ttsModule.speak('签收成功')
-                        uni.navigateBack()
-                    }
-                }).finally(() => {
-                    uni.hideLoading()
-                })
+                        search: orderDetail.value.orderId,
+                    })
+                    .then((res) => {
+                        if (res.code == 200) {
+                            uni.showToast({ title: "签收成功", icon: "none" });
+                            uni.$u.ttsModule.speak("签收成功");
+                            uni.navigateBack();
+                        }
+                    })
+                    .finally(() => {
+                        uni.hideLoading();
+                    });
             }
-        }
-    })
+        },
+    });
 }
 
 //确认收货 /app/orderinfo/confirmOrder
 function handleConfirm() {
-    uni.showLoading({ title: '加载中...', mask: true })
-    uni.$u.http.post('/app/orderinfo/confirmOrder', {
-        searchType: 1,
-        "search": orderDetail.value.orderId
-    }).then(res => {
-        if (res.code == 200) {
-            uni.showToast({ title: '确认收货成功', icon: 'none' })
-            uni.$u.ttsModule.speak('确认收货成功')
-            getOrderDetail()
-        }
-    }).finally(() => {
-        uni.hideLoading()
-    })
+    uni.showLoading({ title: "加载中...", mask: true });
+    uni.$u.http
+        .post("/app/orderinfo/confirmOrder", {
+            searchType: 1,
+            search: orderDetail.value.orderId,
+        })
+        .then((res) => {
+            if (res.code == 200) {
+                uni.showToast({ title: "确认收货成功", icon: "none" });
+                uni.$u.ttsModule.speak("确认收货成功");
+                getOrderDetail();
+            }
+        })
+        .finally(() => {
+            uni.hideLoading();
+        });
 }
 //完成
 function handleComplete() {
-    let bookList = orderDetail.value.detailVoList
-    let bool = bookList.some(item => item.auditCommentList?.length < item.num)
+    let bookList = orderDetail.value.detailVoList;
+    let bool = bookList.some((item) => item.auditCommentList?.length < item.num);
     if (bool) {
-        let text = '还有未审核的书'
-        uni.$u.toast(text)
-        uni.$u.ttsModule.speak(text)
-        return
+        let text = "还有未审核的书";
+        uni.$u.toast(text);
+        uni.$u.ttsModule.speak(text);
+        return;
     } else {
-        uni.$u.http.post('/app/orderinfo/checkOrderFinish', {
-            checkUserId: orderDetail.value.auditUserId,
-            "orderId": orderDetail.value.orderId
-        }).then(res => {
-            if (res.code == 200) {
-                uni.showToast({ title: '审核完成', icon: 'none' })
-                uni.$u.ttsModule.speak('审核完成')
-                uni.navigateBack()
-            }
-        })
+        uni.$u.http
+            .post("/app/orderinfo/checkOrderFinish", {
+                checkUserId: orderDetail.value.auditUserId,
+                orderId: orderDetail.value.orderId,
+            })
+            .then((res) => {
+                if (res.code == 200) {
+                    uni.showToast({ title: "审核完成", icon: "none" });
+                    uni.$u.ttsModule.speak("审核完成");
+                    uni.navigateBack();
+                }
+            });
     }
 }
 
 const orderDetail = ref({ status: 0 });
 //获取订单详情
 function getOrderDetail() {
-    if (!orderId.value) return
+    if (!orderId.value) return;
     uni.showLoading({
-        title: '加载中...',
-        mask: true
-    })
-    uni.$u.http.get('/app/orderinfo/getOrderInfoForCheck', {
-        params: {
-            searchType: 1,
-            "search": orderId.value
-        }
-    }).then(res => {
-        if (res.code == 200) {
-            orderDetail.value = res.data
-            if (isOnLoad.value) {
-                if (res.data.manageRemark.length > 0 && res.data.status < 10) {
-                    uni.$u.ttsModule.speak('此订单有备注信息,请注意查看')
-                }
-                if (res.data.warnArea && res.data.warnArea.length > 0) {
-                    let text = `此订单来源于${res.data.warnArea}`
-                    uni.$u.ttsModule.speak(text)
-                }
-                isOnLoad.value = false
+        title: "加载中...",
+        mask: true,
+    });
+    uni.$u.http
+        .get("/app/orderinfo/getOrderInfoForCheck", {
+            params: {
+                searchType: 1,
+                search: orderId.value,
+            },
+        })
+        .then((res) => {
+            if (res.code == 200) {
+                orderDetail.value = res.data;
+                getCheckUserInfo();
 
                 if (res.data.auditUserId) {
                     let auditUserInfo = {
                         userName: res.data.auditUserName,
-                        userId: res.data.auditUserId
-                    }
-                    uni.setStorageSync('checkUserInfo', auditUserInfo)
+                        userId: res.data.auditUserId,
+                    };
+                    uni.setStorageSync("checkUserInfo", auditUserInfo);
                 } else {
-                    let userInfo = uni.getStorageSync('userInfo')
-                    if (userInfo) {
-                        orderDetail.value.auditUserName = userInfo.userName
-                        orderDetail.value.auditUserId = userInfo.userId
-                        uni.setStorageSync('checkUserInfo', {
-                            userName: userInfo.userName,
-                            userId: userInfo.userId
-                        })
+                    let userInfo = uni.getStorageSync("checkUserInfo");
+                    orderDetail.value.auditUserName = userInfo.userName;
+                    orderDetail.value.auditUserId = userInfo.userId;
+                }
+                if (isOnLoad.value) {
+                    if (res.data.manageRemark.length > 0 && res.data.status < 10) {
+                        uni.$u.ttsModule.speak("此订单有备注信息,请注意查看");
                     }
+                    if (res.data.warnArea && res.data.warnArea.length > 0) {
+                        let text = `此订单来源于${res.data.warnArea}`;
+                        uni.$u.ttsModule.speak(text);
+                    }
+                    isOnLoad.value = false;
                 }
+            } else {
+                uni.$u.toast(res.msg);
             }
-        } else {
-            uni.$u.toast(res.msg)
+        })
+        .finally(() => {
+            uni.hideLoading();
+        });
+}
+//获取上一次绑定的审核员信息
+function getCheckUserInfo() {
+    uni.$u.http.get("/app/orderinfo/getCheckUser").then((res) => {
+        if (res.code == 200) {
+            let userInfo = res.data;
+            orderDetail.value.auditUserName = userInfo.userName;
+            orderDetail.value.auditUserId = userInfo.userId;
+            uni.setStorageSync("checkUserInfo", {
+                userName: userInfo.userName,
+                userId: userInfo.userId,
+            });
         }
-    }).finally(() => {
-        uni.hideLoading()
-    })
+    });
 }
+
 //isbn正则校验是否符合
 function checkIsbn(isbn) {
     const isbn13Regex = /^(?:97[89]-?\d{1,5}-?\d{1,7}-?\d{1,6}-?\d)$/;
     if (isbn13Regex.test(isbn)) {
-        return true
+        return true;
     }
-    return false
+    return false;
 }
 
 //扫码之后的逻辑
 function handleScan(isbn) {
     if (!checkIsbn(isbn)) {
-        let text = `不是正确的ISBN码`
-        uni.$u.ttsModule.speak(text)
-        return
+        let text = `不是正确的ISBN码`;
+        uni.$u.ttsModule.speak(text);
+        return;
     }
 
     if (orderDetail.value.status >= 10) {
-        uni.$u.ttsModule.speak('订单已审核完成')
-        return
+        uni.$u.ttsModule.speak("订单已审核完成");
+        return;
     }
 
-    let isbns = orderDetail.value.detailVoList.map(item => item.isbn)
+    let isbns = orderDetail.value.detailVoList.map((item) => item.isbn);
 
     if (isbns.includes(isbn)) {
-        let book = orderDetail.value.detailVoList.find(item => item.isbn == isbn)
+        let book = orderDetail.value.detailVoList.find((item) => item.isbn == isbn);
 
         //扫描到套装书
         if (book.suit == 1) {
-            let text = `${isbn}请注意套装书是否齐全`
-            uni.$u.ttsModule.speak(text)
+            let text = `${isbn}请注意套装书是否齐全`;
+            uni.$u.ttsModule.speak(text);
         }
         //扫描到需要取出的书
         if (book.bookWarn == 1) {
-            let text = `请注意${isbn}需要取出`
-            uni.$u.ttsModule.speak(text)
+            let text = `请注意${isbn}需要取出`;
+            uni.$u.ttsModule.speak(text);
         }
 
         uni.navigateTo({
-            url: `/pages/index/detail/book-audit?isbn=${isbn}&orderId=${orderDetail.value.orderId}`
-        })
-        uni.setStorageSync('auditBook', book)
-        uni.setStorageSync('orderDetail', orderDetail.value)
+            url: `/pages/index/detail/book-audit?isbn=${isbn}&orderId=${orderDetail.value.orderId}`,
+        });
+        uni.setStorageSync("auditBook", book);
+        uni.setStorageSync("orderDetail", orderDetail.value);
     } else {
-        let text = `此订单中不存在${isbn}这本书 `
-        uni.$u.ttsModule.speak(text)
+        let text = `此订单中不存在${isbn}这本书 `;
+        uni.$u.ttsModule.speak(text);
     }
 }
 
@@ -281,39 +321,37 @@ function handleScan(isbn) {
 function handleScanCode() {
     uni.scanCode({
         success: (res) => {
-            res.result && handleScan(res.result)
+            res.result && handleScan(res.result);
         },
-    })
+    });
 }
 
-const orderId = ref('')
-const isOnLoad = ref(false)
+const orderId = ref("");
+const isOnLoad = ref(false);
 
 // 1 表示到货审核 2 表示查看订单
-const type = ref(1)
+const type = ref(1);
 onLoad((option) => {
-    orderId.value = option.id
-    getOrderDetail()
-    isOnLoad.value = true
-    type.value = option.type || 1
+    orderId.value = option.id;
+    getOrderDetail();
+    isOnLoad.value = true;
+    type.value = option.type || 1;
 
-    uni.removeStorageSync('scannedBooks')
+    uni.removeStorageSync("scannedBooks");
 
     // #ifdef APP-PLUS
     uni.$u.useGlobalEvent((e) => {
         if (e.barcode) {
-            handleScan(e.barcode)
+            handleScan(e.barcode);
         }
-    })
+    });
     // #endif
-})
-
+});
 
 onShow(() => {
-    uni.$u.updateActivePageOnShow()
-    getOrderDetail()
-
-})
+    uni.$u.updateActivePageOnShow();
+    getOrderDetail();
+});
 </script>
 
 <style>
@@ -339,7 +377,7 @@ page {
     .fixed-left {
         position: fixed;
         left: 0;
-        top: 150px;
+        top: 11%;
         width: 100rpx;
 
         .common-bg {
@@ -359,7 +397,7 @@ page {
     .fixed-right {
         position: fixed;
         right: 0;
-        top: 180px;
+        top: 12%;
         width: 70rpx;
 
         .letter-bg {
@@ -376,4 +414,4 @@ page {
         }
     }
 }
-</style>
+</style>

+ 54 - 0
pages/index/detail/user-orders.vue

@@ -0,0 +1,54 @@
+<template>
+    <view class="common-page" style="padding: 0">
+        <PageScroll
+            requestStr="/app/orderinfo/getOrderListByUserId"
+            @updateList="updateList"
+            ref="scrollRef"
+            :otherParams="otherParams"
+            method="get"
+        >
+            <view class="list-con" v-if="dataList.length">
+                <OrderItem v-for="cell in dataList" :key="cell.id" :item="cell" class="mt-20"> </OrderItem>
+            </view>
+        </PageScroll>
+    </view>
+</template>
+
+<script setup>
+import { reactive } from "vue";
+import PageScroll from "@/components/pageScroll/index.vue";
+import OrderItem from "@/pages/my/components/orderItem.vue";
+import { ref } from "vue";
+import { onLoad } from "@dcloudio/uni-app";
+
+const otherParams = ref({
+    userId: "",
+});
+const scrollRef = ref(null);
+const refreshList = () => {
+    scrollRef.value?.resetUpScroll();
+};
+
+let dataList = ref([]);
+const updateList = (data, page) => {
+    dataList.value = data;
+    if (data.length > 0 && page == 1) {
+        uni.$u.ttsModule.speak("查询到" + data.length + "条数据");
+    }
+    if (data.length == 0 && page == 1) {
+        uni.$u.ttsModule.speak("未查询到数据");
+    }
+};
+// const isbnList = ref([]);
+onLoad((options) => {
+    otherParams.value.userId = options.userId;
+    refreshList();
+});
+</script>
+<style lang="scss">
+.search-area {
+    padding: 24rpx;
+    background-color: #ffffff;
+    z-index: 9;
+}
+</style>

+ 1 - 1
pages/index/entry/book-weight.vue

@@ -11,7 +11,7 @@
 
         <view class="fixed-bottom">
             <u-button size="large" type="warning" text="扫码" @click="handleScan" />
-            <u-button size="large" type="success" text="提交" @click="submitForm" />
+            <u-button size="large" type="success" text="提交" v-permission="'app:entry:bookWeight:confirm'" @click="submitForm" />
         </view>
     </view>
 </template>

+ 2 - 2
pages/index/express/components/ExceptionItem.vue

@@ -27,8 +27,8 @@
         <!-- 操作按钮 -->
         <view class="action-section">
             <u-button type="primary" text="查看物流" size="small" @click="handleCheckLogistics" />
-            <approve-button v-if="order.checkStatus == 1" @approve="handleButtonClick(2)" />
-            <reject-button v-if="order.checkStatus == 1" @reject="(reason) => handleButtonClick(3, reason)" />
+            <approve-button v-permission="'app:express:exception:approve'" v-if="order.checkStatus == 1" @approve="handleButtonClick(2)" />
+            <reject-button v-permission="'app:express:exception:reject'" v-if="order.checkStatus == 1" @reject="(reason) => handleButtonClick(3, reason)" />
             <view v-if="order.checkStatus == 2" style="color: #19be6b;">[已签收]</view>
             <view v-if="order.checkStatus == 3" style="color: #f00;">[已驳回]</view>
         </view>

+ 19 - 8
pages/index/express/quick-check.vue

@@ -45,7 +45,8 @@
 
             <view style="display: flex;">
                 <u-button size="large" type="warning" text="验收扫码" @click="handleScan" />
-                <u-button size="large" type="primary" text="提交批次" @click="handleSubmitBatch" />
+                <u-button size="large" type="primary" text="提交批次" @click="handleSubmitBatch"
+                    v-permission="'app:express:quickCheck:confirm'" />
             </view>
         </view>
 
@@ -54,12 +55,12 @@
             <view class="batch-popup" style="min-height: 300px;">
                 <view class="popup-header">
                     <text style="font-size: 32rpx;">批次</text>
+                    <view style="font-size: 32rpx;color: #007AFF;" @click="createNewBatch">
+                        <text>新建批次</text>
+                    </view>
                 </view>
 
                 <scroll-view scroll-y class="batch-list">
-                    <view class="batch-item" :class="{ active: selectedBatchId === 'new' }" @click="createNewBatch">
-                        <text>新建批次</text>
-                    </view>
                     <view v-for="batch in batchList" :key="batch.id" class="batch-item"
                         :class="{ active: selectedBatchId === batch.id }" @click="selectBatch(batch)">
                         <text>{{ batch.batchNum }}</text>
@@ -151,9 +152,11 @@ const handleScan = () => {
 
 // Function to handle creating a new batch
 const createNewBatch = () => {
-    selectedBatchId.value = 'new';
-    formData.value.batchNum = '新建批次';
-    count.value = 0; // Reset count or set to a default value
+    uni.$u.http.post('/app/batchnum/add').then(res => {
+        if (res.code == 200) {
+            getBatchList()
+        }
+    })
 };
 
 onLoad(() => {
@@ -170,5 +173,13 @@ onShow(() => {
 </script>
 
 <style lang="scss" scoped>
-@import "../components/common.scss"
+@import "../components/common.scss";
+</style>
+<style>
+.popup-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 20rpx;
+}
 </style>

+ 2 - 1
pages/index/express/quick-unpack.vue

@@ -14,7 +14,8 @@
             <view class="input-group">
                 <u-input placeholder-style="font-size:32rpx" v-model="unpackCode" placeholder="扫描/输入物流单号"
                     border="surround" />
-                <u-button type="primary" @click="confirmTrackingNumber(unpackCode)" text="确定" />
+                <u-button type="primary" @click="confirmTrackingNumber(unpackCode)" text="确定"
+                    v-permission="'app:express:quickUnpack:confirm'" />
             </view>
         </view>
 

+ 1 - 1
pages/index/express/transfer-sign.vue

@@ -10,7 +10,7 @@
 			<view class="input-group">
 				<u-input :customStyle="customStyle" :placeholder-style="placeholderStyle" v-model="form.packageCode"
 					placeholder="扫描/输入物流单号" border="surround" />
-				<u-button :customStyle="customStyle" type="info" color="#a4adb3"
+				<u-button :customStyle="customStyle" type="info" color="#a4adb3" v-permission="'app:express:transferSign:confirm'"
 					@click="handleBarcode(form.packageCode)" text="确定" />
 			</view>
 		</view>

+ 1 - 1
pages/index/express/warehouse-sign.vue

@@ -10,7 +10,7 @@
             <view class="input-group">
                 <u-input :customStyle="customStyle" :placeholder-style="placeholderStyle" v-model="form.packageCode"
                     placeholder="扫描/输入物流单号" border="surround" />
-                <u-button :customStyle="customStyle" type="info" color="#a4adb3"
+                <u-button :customStyle="customStyle" type="info" color="#a4adb3" v-permission="'app:express:warehouseSign:confirm'"
                     @click="handleBarcode(form.packageCode)" text="确定" />
             </view>
         </view>

+ 2 - 1
pages/index/express/weight-modify.vue

@@ -24,7 +24,8 @@
         <!-- 底部按钮 -->
         <view class="fixed-bottom">
             <u-button size="large" type="warning" @click="scanCode" text="扫码" class="scan-button" />
-            <u-button size="large" type="success" @click="submitForm" text="提交" class="submit-button" />
+            <u-button size="large" v-permission="'app:express:changeWeight:confirm'" type="success" @click="submitForm"
+                text="提交" class="submit-button" />
         </view>
     </view>
 </template>

+ 14 - 2
pages/index/index.vue

@@ -47,7 +47,7 @@ async function getMenuList() {
             const data = res.data;
             menuData.value = data.map((item) => {
                 item.children = item.children.map((child) => {
-                    child.query = JSON.parse(child.query);
+                    child.query = child.query ? JSON.parse(child.query) : {};
                     return child;
                 });
                 return item;
@@ -71,7 +71,17 @@ async function getMenuList() {
 function getButtonList() {
     uni.$u.http.get("/app/appUser/getInfo").then((res) => {
         if (res.code == 200) {
-            uni.setStorageSync("buttonList", res.data);
+            // 保存到本地存储
+            uni.setStorageSync("buttonList", res.permissions);
+        }
+    });
+}
+
+//获取音频信息配置
+function getAudioConfig() {
+    uni.$u.http.get("/app/appConf/getAudioConfig").then((res) => {
+        if (res.code == 200) {
+            uni.setStorageSync("audioConfig", res.data);
         }
     });
 }
@@ -90,6 +100,8 @@ onLoad(() => {
             // 数据加载完成后,隐藏加载提示
             uni.hideLoading();
         });
+
+    getAudioConfig();
 });
 
 const formatName = (name) => {

+ 2 - 1
pages/index/offline/check-order.vue

@@ -9,7 +9,8 @@
             <text class="pad-10" v-if="bookList.length > 0">共 <text style="color: #ff0000;">{{ totalBooks }}</text>
                 本,预估回收价 <text style="color: #ff0000;">¥{{ totalPrice }}</text></text>
             <view class="flex-a mt-12">
-                <u-button size="large" type="primary" text="提交" @click="handleSubmit" />
+                <u-button size="large" type="primary" text="提交" @click="handleSubmit"
+                    v-permission="'app:offline:checkOrder:confirm'" />
                 <u-button size="large" type="warning" text="扫码" @click="handleScan" />
             </view>
         </view>

+ 1 - 1
pages/index/wms/bad-in.vue

@@ -7,7 +7,7 @@
                     <u-icon name="arrow-left" color="#333333" size="20" @click="goBack"></u-icon>
                 </template>
                 <template #right>
-                    <u-text type="primary" text="提交" @click="onSubmit"></u-text>
+                    <u-text type="primary" text="提交" @click="onSubmit" v-permission="'app:wms:badIn:submit'"></u-text>
                 </template>
             </u-navbar>
         </view>

+ 14 - 2
pages/index/wms/bad-out-order.vue

@@ -63,8 +63,7 @@
 import { ref, onMounted } from "vue";
 import BadOutCard from "./components/BadOutCard.vue";
 import RemarkDialog from "./components/RemarkDialog.vue";
-import VolumeTTS from "@/utils/VolumeTTS.js";
-import { onLoad } from "@dcloudio/uni-app";
+import { onLoad, onShow } from "@dcloudio/uni-app";
 
 const searchText = ref("");
 const searchType = ref("1");
@@ -90,6 +89,15 @@ onLoad((options) => {
         searchText.value = options.searchText;
         onSearch();
     }
+
+    // #ifdef APP-PLUS
+    uni.$u.useGlobalEvent((e) => {
+        if (e.barcode) {
+            searchText.value = e.barcode;
+            onSearch();
+        }
+    });
+    // #endif
 });
 
 // 判断搜索类型
@@ -166,6 +174,10 @@ const openScan = () => {
     // #endif
 };
 
+onShow(() => {
+    uni.$u.updateActivePageOnShow();
+});
+
 // 确认出库
 const onConfirm = () => {
     uni.showModal({

+ 15 - 0
pages/index/wms/bad-out.vue

@@ -30,6 +30,7 @@
 
 <script setup>
 import { ref, computed, onMounted } from "vue";
+import { onLoad, onShow } from "@dcloudio/uni-app";
 // 搜索文本
 const searchText = ref("");
 const searchType = ref("1");
@@ -66,4 +67,18 @@ const openScan = () => {
     });
     // #endif
 };
+
+onLoad(() => {
+     // #ifdef APP-PLUS
+     uni.$u.useGlobalEvent((e) => {
+        if (e.barcode) {
+            searchText.value = e.barcode
+            onSearch()
+        }
+    })
+    // #endif
+})
+onShow(() => {
+    uni.$u.updateActivePageOnShow()
+})
 </script>

+ 1 - 1
pages/index/wms/components/BadOutCard.vue

@@ -6,7 +6,7 @@
                 <view class="quantity mt-20">数量: {{ item.num }}</view>
             </view>
             <view class="book-info ml-20 flex-1">
-                <view class="common-title mb-20">{{ item.title }}</view>
+                <view class="common-title mb-20">{{ item.bookName }}</view>
                 <view class="flex flex-j-b mb-10">
                     <view class="isbn">ISBN: {{ item.isbn }}</view>
                     <view class="set">套装: {{ item.suit == 1 ? '是' : '否' }}</view>

+ 139 - 123
pages/index/wms/location-select.vue

@@ -1,131 +1,147 @@
 <template>
-    <view class="container">
-        <!-- 库位列表 -->
-        <scroll-view scroll-y class="location-list" :style="{ height: scrollHeight + 'px' }">
-            <view v-for="(item, index) in locations" :key="index" 
-                :class="['location-item', item === positionCode ? 'location-item-selected' : '']"
-                hover-class="location-item-hover" @click="selectLocation(item)">
-                <text>{{ item }}</text>
-            </view>
-        </scroll-view>
-
-        <!-- 底部搜索框 -->
-        <view class="fixed-bottom pad-20" style="background: #ffffff;">
-            <u-search v-model="searchText" placeholder="请输入库位条码" :show-action="false" :clearabled="true"
-                @change="onSearch" height="40" :disabled="true" @click="searchText = ''">
-            </u-search>
-            <u-icon name="scan" size="28" color="#19be6b" @click="openScan"></u-icon>
-        </view>
-    </view>
+	<view class="container">
+		<!-- 库位列表 -->
+		<scroll-view scroll-y class="location-list" :style="{ height: scrollHeight + 'px' }">
+			<view v-for="(item, index) in locations" :key="index"
+				:class="['location-item', item === positionCode ? 'location-item-selected' : '']"
+				hover-class="location-item-hover" @click="selectLocation(item)">
+				<text>{{ item }}</text>
+			</view>
+		</scroll-view>
+
+		<!-- 底部搜索框 -->
+		<view class="fixed-bottom pad-20" style="background: #ffffff;">
+			<u-search v-model="searchText" placeholder="请输入库位条码" :show-action="false" :clearabled="true"
+				@search="onSearch" height="40" @click="searchText = ''">
+			</u-search>
+			<u-icon name="scan" size="28" color="#19be6b" @click="openScan"></u-icon>
+		</view>
+	</view>
 </template>
 
 <script setup>
-import { ref, computed, onMounted } from 'vue'
-import { onLoad, onShow } from '@dcloudio/uni-app'
-// 搜索文本
-const searchText = ref('')
-
-// 库位列表数据
-const locations = ref([])
-
-//根据仓库id获取库位列表
-function getLocationListByGodownId(godownId, code = "") {
-    uni.$u.http.get('/app/stock/getGodownPosition?godownId=' + godownId + '&code=' + code).then(res => {
-        if (res.code == 200) {
-            locations.value = res.data
-        }
-    })
-}
-
-// 滚动区域高度
-const scrollHeight = ref(0)
-
-
-// 搜索处理
-const onSearch = () => {
-    // 实现搜索逻辑
-    getLocationListByGodownId(godownId.value, searchText.value)
-}
-
-// 打开扫码
-const openScan = () => {
-    // #ifdef APP-PLUS || MP-WEIXIN
-    uni.scanCode({
-        success: (res) => {
-            searchText.value = res.result
-            onSearch()
-        },
-        fail: (err) => {
-            uni.showToast({
-                title: '扫码失败',
-                icon: 'error'
-            })
-        }
-    })
-    // #endif
-
-    // #ifdef H5
-    uni.showToast({
-        title: 'H5环境不支持扫码',
-        icon: 'none'
-    })
-    // #endif
-}
-
-// 选择库位
-const selectLocation = (item) => {
-    // 也可以使用事件总线或页面参数的方式传值
-    uni.$emit('updateLocation', item)
-
-    // 返回上一页
-    uni.navigateBack()
-}
-
-const godownId = ref('')
-const positionCode = ref('')
-onLoad((opts) => {
-    godownId.value = opts.godownId
-    positionCode.value = opts.positionCode
-    getLocationListByGodownId(godownId.value)
-
-    scrollHeight.value = uni.getSystemInfoSync().windowHeight - 44 - 60
-
-    // #ifdef APP-PLUS
-    uni.$u.useGlobalEvent((e) => {
-        if (e.barcode) {
-            searchText.value = e.barcode
-            getLocationListByGodownId(godownId.value, e.barcode)
-        }
-    })
-    // #endif
-})
-onShow(() => {
-    uni.$u.updateActivePageOnShow()
-})
+	import {
+		ref,
+		computed,
+		onMounted
+	} from 'vue'
+	import {
+		onLoad,
+		onShow
+	} from '@dcloudio/uni-app'
+	// 搜索文本
+	const searchText = ref('')
+
+	// 库位列表数据
+	const locations = ref([])
+
+	//根据仓库id获取库位列表
+	function getLocationListByGodownId(godownId, code = "", type = "") {
+		uni.$u.http.get('/app/stock/getGodownPosition?godownId=' + godownId + '&code=' + code).then(res => {
+			if (res.code == 200) {
+				locations.value = res.data
+				if (type == 'select') {
+					setTimeout(() => {
+						locations.value.forEach(item => {
+							if (item == code) {
+								selectLocation(item)
+							}
+						})
+					},500)
+				}
+			}
+		})
+	}
+
+	// 滚动区域高度
+	const scrollHeight = ref(0)
+
+
+	// 搜索处理
+	const onSearch = () => {
+		// 实现搜索逻辑
+		getLocationListByGodownId(godownId.value, searchText.value)
+	}
+
+	// 打开扫码
+	const openScan = () => {
+		// #ifdef APP-PLUS || MP-WEIXIN
+		uni.scanCode({
+			success: (res) => {
+				searchText.value = res.result
+				onSearch()
+			},
+			fail: (err) => {
+				uni.showToast({
+					title: '扫码失败',
+					icon: 'error'
+				})
+			}
+		})
+		// #endif
+
+		// #ifdef H5
+		uni.showToast({
+			title: 'H5环境不支持扫码',
+			icon: 'none'
+		})
+		// #endif
+	}
+
+	// 选择库位
+	const selectLocation = (item) => {
+		// 也可以使用事件总线或页面参数的方式传值
+		uni.$emit('updateLocation', item)
+
+		// 返回上一页
+		uni.navigateBack()
+	}
+
+	const godownId = ref('')
+	const positionCode = ref('')
+	onLoad((opts) => {
+		godownId.value = opts.godownId
+		positionCode.value = opts.positionCode
+		getLocationListByGodownId(godownId.value)
+
+		scrollHeight.value = uni.getSystemInfoSync().windowHeight - 44 - 60
+
+		// #ifdef APP-PLUS
+		uni.$u.useGlobalEvent((e) => {
+			if (e.barcode) {
+				searchText.value = e.barcode
+				getLocationListByGodownId(godownId.value, e.barcode, 'select')
+			}
+		})
+		// #endif
+	})
+	onShow(() => {
+		uni.$u.updateActivePageOnShow()
+	})
 </script>
 
 <style scoped>
-.container {
-    position: relative;
-}
-
-.location-list {
-    padding: 12px 0 60px;
-}
-
-.location-item {
-    background-color: #fff;
-    padding: 15px 20px;
-    margin-bottom: 1px;
-    font-size: 16px;
-}
-
-.location-item-selected {
-    background-color: #e8f5e9;
-    border-left: 4px solid #19be6b;
-}
-
-.location-item-hover {
-    background-color: #f5f5f5;
-}
+	.container {
+		position: relative;
+	}
+
+	.location-list {
+		padding: 12px 0 60px;
+	}
+
+	.location-item {
+		background-color: #fff;
+		padding: 15px 20px;
+		margin-bottom: 1px;
+		font-size: 16px;
+	}
+
+	.location-item-selected {
+		background-color: #e8f5e9;
+		border-left: 4px solid #19be6b;
+	}
+
+	.location-item-hover {
+		background-color: #f5f5f5;
+	}
 </style>

+ 18 - 5
pages/index/wms/speedy-check.vue

@@ -12,7 +12,7 @@
                 <u-icon name="arrow-left" color="#fff" size="20" @click="goBack"></u-icon>
             </template>
             <template #right>
-                <text style="color: #ffffff" @click="onSubmit">提交</text>
+                <text style="color: #ffffff" @click="onSubmit" v-permission="'app:wms:speedyCheck:confirm'">提交</text>
             </template>
         </u-navbar>
         <!-- 盘点信息选择区域 -->
@@ -272,12 +272,26 @@ const onSearch = () => {
         });
 };
 
+//扫码后判断是否是库位还是 订单号
+const dealScanText = (scanText) => {
+    let isLocation = scanText.indexOf("-") > -1 && scanText.length == 9;
+    if (isLocation) {
+        if (locationList.value.includes(scanText)) {
+            location.value = scanText;
+        } else {
+            uni.$u.toast("库位不存在");
+        }
+    } else {
+        searchValue.value = scanText;
+        onSearch();
+    }
+};
+
 const openScan = () => {
     // #ifdef APP-PLUS || MP-WEIXIN
     uni.scanCode({
         success: (res) => {
-            searchValue.value = res.result;
-            onSearch();
+            dealScanText(res.result);
         },
         fail: (err) => {
             uni.showToast({
@@ -317,8 +331,7 @@ onLoad(() => {
     // #ifdef APP-PLUS
     uni.$u.useGlobalEvent((e) => {
         if (e.barcode) {
-            searchValue.value = e.barcode;
-            onSearch();
+            dealScanText(e.barcode);
         }
     });
     // #endif

+ 12 - 25
pages/index/wms/task-detail.vue

@@ -74,7 +74,7 @@
                 placeholder="请输入订单编号/物流单号/库位号"
                 :show-action="false"
                 :clearabled="true"
-                @change="checkScanText(searchText)"
+                @search="checkScanText(searchText)"
                 height="40"
             >
             </u-search>
@@ -147,6 +147,7 @@ const confirmStockTask = () => {
     const params = {
         positionCode: curTaskInfo.value.positionCode,
         orderId: curTaskInfo.value.orderId,
+        taskCode: taskCode.value,
     };
 
     uni.$u.http.post("/app/appstock/setStockTask", params).then((res) => {
@@ -155,6 +156,7 @@ const confirmStockTask = () => {
             orderList.value[currentTask.value] = curTaskInfo.value;
 
             handleNextTask();
+            isFirstScan.value = false;
             ttsModule.value.speak("下架成功");
         } else {
             uni.showToast({
@@ -216,19 +218,12 @@ let isFirstScan = ref(false); //是否验证了库位号
 //库位号格式 字母+数字+横杠-  物流号格式 必须有字母+数字组合  订单号 数字
 const checkScanText = (scanText) => {
     console.log(scanText, "scanText");
+    let length = scanText ? scanText.length : 0;
     //先判断扫描到的scanText是库位号还是物流号或者订单号
-    let isPositionCode = scanText.indexOf("-") > -1;
+    let isPositionCode = scanText.indexOf("-") > -1 && length == 9;
     let isWaybillCode = /^(?=.*[A-Z])(?=.*\d)[A-Z0-9]+$/.test(scanText);
     let isOrderId = /^\d+$/.test(scanText);
 
-    console.log(
-        isPositionCode,
-        isWaybillCode,
-        isOrderId,
-        isFirstScan.value,
-        "isPositionCode, isWaybillCode, isOrderId"
-    );
-
     //库位号校验
     if (isPositionCode) {
         let positionCode = curTaskInfo.value.positionCode;
@@ -247,25 +242,17 @@ const checkScanText = (scanText) => {
         return;
     }
 
-    //物流号校验
-    if (isWaybillCode && !isOrderId) {
+    //物流号或者订单号校验
+    if (isWaybillCode || isOrderId) {
         let waybillCode = curTaskInfo.value.waybillCode;
-        if (waybillCode == scanText) {
+        let orderId = curTaskInfo.value.orderId;
+        if (waybillCode == scanText || orderId == scanText) {
             confirmStockTask();
         } else {
             uni.showToast({
-                title: "物流号不正确",
+                title: "订单号或物流号不匹配",
                 icon: "error",
             });
-        }
-    }
-
-    //订单号校验
-    if (isOrderId && !isWaybillCode) {
-        let orderId = curTaskInfo.value.orderId;
-        if (orderId == scanText) {
-            confirmStockTask();
-        } else {
             curTaskInfo.value.isValid = true;
         }
     }
@@ -311,8 +298,8 @@ onLoad((opts) => {
     // #endif
 });
 onShow(() => {
-    uni.$u.updateActivePageOnShow()
-})
+    uni.$u.updateActivePageOnShow();
+});
 </script>
 
 <style scoped>

+ 25 - 16
pages/login/login.vue

@@ -153,29 +153,38 @@ const handleLogin = () => {
     });
     // /actuator/debug/loginNotCode  ///app/appUser/login
     uni.$u.http
-        .post("/actuator/debug/loginNotCode", formData)
+        .post("/app/appUser/login", formData)
         .then((res) => {
             if (res.code == 200) {
                 uni.setStorageSync("token", res.data);
-                getUserInfo();
-                //获取菜单权限
-                uni.$u.http.get("/app/appUser/getRouters").then((resp) => {
-                    if (resp.code == 200) {
-                        uni.setStorageSync("menuList", resp.data);
-
-                        uni.$u.toast("登录成功");
-                        uni.switchTab({
-                            url: "/pages/index/index",
-                        });
-                        uni.$u.ttsModule.speak("书嗨,不辜负每一个爱书的人");
-                    } else {
-                        uni.$u.toast(resp.msg);
-                    }
-                });
+                setTimeout(() => {
+                    getUserInfo();
+                    //获取菜单权限
+                    uni.$u.http.get("/app/appUser/getRouters").then((resp) => {
+                        if (resp.code == 200) {
+                            uni.setStorageSync("menuList", resp.data);
+
+                            uni.$u.toast("登录成功");
+                            uni.switchTab({
+                                url: "/pages/index/index",
+                            });
+                            uni.$u.ttsModule.speak("书嗨,不辜负每一个爱书的人");
+                        } else {
+                            uni.$u.toast(resp.msg);
+                        }
+                    });
+                }, 50);
             } else {
                 uni.$u.toast(res.msg);
             }
         })
+        .catch((error) => {
+            uni.showModal({
+                title: "登录失败",
+                content: JSON.stringify(error),
+                showCancel: false,
+            });
+        })
         .finally(() => uni.hideLoading());
 };
 

+ 44 - 44
pages/my/components/orderItem.vue

@@ -4,7 +4,7 @@
         <view class="user-info">
             <image class="avatar" :src="item.imgPath" mode="aspectFill"></image>
             <view class="user-details">
-                <text class="username">{{ item.plat == 1 ? '微信用户' : '支付宝用户' }} ({{ maskedNickName }})</text>
+                <text class="username">{{ item.plat == 1 ? "微信用户" : "支付宝用户" }} ({{ maskedNickName }})</text>
                 <text class="date">共卖出{{ item.totalNum }}本书</text>
                 <text class="date">来自{{ item.sendSsq }}</text>
             </view>
@@ -22,68 +22,68 @@
                     <text>订单ID:</text>
                     <text class="link" @click="copyToClipboard(item.orderId)">{{ item.orderId }}</text>
                 </view>
-                <view class="flex-1" style="flex: 1.5;">
+                <view class="flex-1" style="flex: 1.5">
                     <text>运单号:</text>
                     <text class="link" @click="copyToClipboard(item.waybillCode)">{{ item.waybillCode }}</text>
                 </view>
             </view>
             <view class="detail-row">
                 <text class="flex-1">预估金额:{{ item.expectMoney || 0 }}</text>
-                <text class="flex-1">审核金额:{{ item.finalMoney || '待核算' }}</text>
+                <text class="flex-1">审核金额:{{ item.finalMoney || "待核算" }}</text>
             </view>
             <view class="detail-row">
-                <text>内部备注:{{ item?.manageRemark ? item?.manageRemark[0]?.remark : '-' }}</text>
+                <text>内部备注:{{ item?.manageRemark ? item?.manageRemark[0]?.remark : "-" }}</text>
             </view>
         </view>
 
         <!-- 操作按钮 -->
         <view class="action-buttons">
-            <u-button size="small" type="primary" @click="handleAudit">到货审核</u-button>
+            <u-button size="small" type="primary" @click="handleAudit" :disabled="item.status != 8 || item.status != 9"
+                >到货审核</u-button
+            >
             <u-button size="small" @click="handleView">查看</u-button>
         </view>
     </view>
 </template>
 
 <script setup>
-import {
-    ref,
-    computed
-} from 'vue'
+import { ref, computed } from "vue";
 
 const props = defineProps({
     item: {
         type: Object,
-        default: () => { }
-    }
-})
+        default: () => {},
+    },
+});
 
 const statusEnum = {
-    "0": '创建',
-    "1": '用户删除',
-    "2": '下单(待初审)',
-    "3": '初审(待取书)',
-    "4": '初审未通过',
-    "5": '快递取书(待签收)',
-    "6": '快递签收(待收货)',
-    "7": '物流签收(路由异常)',
-    "8": '仓库收货(待审核)',
-    "9": '审核中(审核未提交)',
-    "10": '已审核(待付款)',
-    "11": '已完成'
+    0: "创建",
+    1: "用户删除",
+    2: "下单(待初审)",
+    3: "初审(待取书)",
+    4: "初审未通过",
+    5: "快递取书(待签收)",
+    6: "快递签收(待收货)",
+    7: "物流签收(路由异常)",
+    8: "仓库收货(待审核)",
+    9: "审核中(审核未提交)",
+    10: "已审核(待付款)",
+    11: "已完成",
 };
 
 // 处理昵称显示
 const maskedNickName = computed(() => {
-    if (!props.item.userNick) return '';
-    return props.item.userNick.charAt(0) + '*'.repeat(props.item.userNick.length - 1);
+    let nickName = props.item.userNick || props.item.nickName;
+    if (!nickName) return "";
+    return nickName.charAt(0) + "*".repeat(nickName.length - 1);
 });
 
 let statusText = computed(() => {
-    return props.item.status ? statusEnum[props.item.status] : '-';
+    return props.item.status ? statusEnum[props.item.status] : "-";
 });
 
 // 模拟数据
-const statusColor = ref('#FF4D4F')
+const statusColor = ref("#FF4D4F");
 
 // 复制到剪贴板
 const copyToClipboard = (text) => {
@@ -91,33 +91,33 @@ const copyToClipboard = (text) => {
         data: text,
         success: () => {
             uni.showToast({
-                title: '复制成功',
-                icon: 'success'
-            })
-        }
-    })
-}
+                title: "复制成功",
+                icon: "success",
+            });
+        },
+    });
+};
 
 // 到货审核
 const handleAudit = () => {
     // 处理到货审核逻辑
     uni.navigateTo({
-        url: `/pages/index/detail/index?id=${props.item.orderId}`
-    })
-}
+        url: `/pages/index/detail/index?id=${props.item.orderId}`,
+    });
+};
 
 // 查看
 const handleView = () => {
     // 处理查看逻辑 type=2 表示查看订单
-    uni.navigateTo({  
-        url: `/pages/index/detail/index?id=${props.item.orderId}&type=2`
-    })
-}
+    uni.navigateTo({
+        url: `/pages/index/detail/index?id=${props.item.orderId}&type=2`,
+    });
+};
 </script>
 
 <style lang="scss" scoped>
 .order-card {
-    background: #FFFFFF;
+    background: #ffffff;
     border-radius: 8rpx;
     padding: 20rpx;
     margin-bottom: 20rpx;
@@ -173,7 +173,7 @@ const handleView = () => {
             margin-bottom: 12rpx;
 
             .link {
-                color: #007BFF;
+                color: #007bff;
                 text-decoration: underline;
                 cursor: pointer;
             }
@@ -192,4 +192,4 @@ const handleView = () => {
         }
     }
 }
-</style>
+</style>

ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/app-config-service.js


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/app-service.js


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/audit/isbn-order.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/audit/sender.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/detail/book-audit.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/detail/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/detail/user-orders.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/express/quick-check.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/express/quick-unpack.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/express/route-exception.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/express/transfer-sign.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/express/warehouse-sign.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/express/weight-modify.css


+ 1 - 1
unpackage/dist/build/app-plus/pages/index/index.css

@@ -1 +1 @@
-.operation-container[data-v-4129b6d2]{padding:.625rem;box-sizing:border-box}.section[data-v-4129b6d2]{margin-bottom:.9375rem;background:#fff;border-radius:.5rem;padding:.625rem;padding-right:0;box-shadow:0 .0625rem .375rem rgba(0,0,0,.05)}.section .section-title[data-v-4129b6d2]{font-size:1.5625rem;font-weight:600;color:#333;padding:.625rem;padding-top:0;border-bottom:.0625rem solid #f0f0f0;margin-bottom:.625rem}.section .grid-container[data-v-4129b6d2]{display:flex;flex-wrap:wrap;padding:.3125rem}.section .grid-container .grid-item[data-v-4129b6d2]{width:calc(50% - .625rem);min-height:4.625rem;display:flex;align-items:center;justify-content:center;text-align:center;padding:.625rem .9375rem;line-height:1.875rem;font-size:1.5625rem;border-radius:.375rem;color:#fff;transition:all .3s;white-space:pre-wrap;box-sizing:border-box;margin-right:.625rem;margin-bottom:.625rem}.section .grid-container .grid-item[style*="grid-column: span 2"][data-v-4129b6d2]{width:calc(100% - .625rem);margin-right:.625rem}.section .grid-container .grid-item.primary[data-v-4129b6d2]{background:linear-gradient(135deg,#4cd964,#3ac555)}.section .grid-container .grid-item.primary[data-v-4129b6d2]:active{background:linear-gradient(135deg,#3ac555,#2fb548)}.section .grid-container .grid-item.warning[data-v-4129b6d2]{background:linear-gradient(135deg,#ff9500,#ff8000)}.section .grid-container .grid-item.warning[data-v-4129b6d2]:active{background:linear-gradient(135deg,#ff8000,#e67300)}.section .grid-container .grid-item[data-v-4129b6d2]:active{transform:scale(.98)}
+.operation-container[data-v-af7859bf]{padding:.625rem;box-sizing:border-box}.section[data-v-af7859bf]{margin-bottom:.9375rem;background:#fff;border-radius:.5rem;padding:.625rem;padding-right:0;box-shadow:0 .0625rem .375rem rgba(0,0,0,.05)}.section .section-title[data-v-af7859bf]{font-size:1.5625rem;font-weight:600;color:#333;padding:.625rem;padding-top:0;border-bottom:.0625rem solid #f0f0f0;margin-bottom:.625rem}.section .grid-container[data-v-af7859bf]{display:flex;flex-wrap:wrap;padding:.3125rem}.section .grid-container .grid-item[data-v-af7859bf]{width:calc(50% - .625rem);min-height:4.625rem;display:flex;align-items:center;justify-content:center;text-align:center;padding:.625rem .9375rem;line-height:1.875rem;font-size:1.5625rem;border-radius:.375rem;color:#fff;transition:all .3s;white-space:pre-wrap;box-sizing:border-box;margin-right:.625rem;margin-bottom:.625rem}.section .grid-container .grid-item[style*="grid-column: span 2"][data-v-af7859bf]{width:calc(100% - .625rem);margin-right:.625rem}.section .grid-container .grid-item.primary[data-v-af7859bf]{background:linear-gradient(135deg,#4cd964,#3ac555)}.section .grid-container .grid-item.primary[data-v-af7859bf]:active{background:linear-gradient(135deg,#3ac555,#2fb548)}.section .grid-container .grid-item.warning[data-v-af7859bf]{background:linear-gradient(135deg,#ff9500,#ff8000)}.section .grid-container .grid-item.warning[data-v-af7859bf]:active{background:linear-gradient(135deg,#ff8000,#e67300)}.section .grid-container .grid-item[data-v-af7859bf]:active{transform:scale(.98)}

ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/offline/check-order.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/wms/bad-in.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/wms/bad-out-order.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/wms/location-select.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/wms/order-query-list.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/wms/speedy-check.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/index/wms/task-detail.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/login/login.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/build/app-plus/pages/my/page/audit-unfinished.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/dist/dev/app-plus/app-config-service.js


ファイルの差分が大きいため隠しています
+ 157 - 169
unpackage/dist/dev/app-plus/app-service.js


+ 2 - 2
unpackage/dist/dev/app-plus/pages/index/audit/isbn-order.css

@@ -704,7 +704,7 @@ uni-view[data-v-5ce41ee6], uni-scroll-view[data-v-5ce41ee6], uni-swiper-item[dat
 /* 透明度 */
 /* 文章场景相关 */
 .order-card[data-v-12bc2a79] {
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 0.25rem;
   padding: 0.625rem;
   margin-bottom: 0.625rem;
@@ -753,7 +753,7 @@ uni-view[data-v-5ce41ee6], uni-scroll-view[data-v-5ce41ee6], uni-swiper-item[dat
   margin-bottom: 0.375rem;
 }
 .order-card .order-details .detail-row .link[data-v-12bc2a79] {
-  color: #007BFF;
+  color: #007bff;
   text-decoration: underline;
   cursor: pointer;
 }

+ 2 - 2
unpackage/dist/dev/app-plus/pages/index/audit/sender.css

@@ -841,7 +841,7 @@ uni-view[data-v-5ce41ee6], uni-scroll-view[data-v-5ce41ee6], uni-swiper-item[dat
 /* 透明度 */
 /* 文章场景相关 */
 .order-card[data-v-12bc2a79] {
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 0.25rem;
   padding: 0.625rem;
   margin-bottom: 0.625rem;
@@ -890,7 +890,7 @@ uni-view[data-v-5ce41ee6], uni-scroll-view[data-v-5ce41ee6], uni-swiper-item[dat
   margin-bottom: 0.375rem;
 }
 .order-card .order-details .detail-row .link[data-v-12bc2a79] {
-  color: #007BFF;
+  color: #007bff;
   text-decoration: underline;
   cursor: pointer;
 }

+ 22 - 0
unpackage/dist/dev/app-plus/pages/index/detail/book-audit.css

@@ -920,6 +920,28 @@ uni-view[data-v-2fd891bb], uni-scroll-view[data-v-2fd891bb], uni-swiper-item[dat
 .disabled[data-v-9873c737] {
   background-color: #d0d0d0;
 }
+
+/* 悬浮排序按钮样式 */
+.floating-sort-btn[data-v-9873c737] {
+  position: fixed;
+  right: 0.625rem;
+  bottom: 30%;
+  width: 2.8125rem;
+  height: 2.8125rem;
+  background: linear-gradient(135deg, #2b85e4, #5cadff);
+  border-radius: 50%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  z-index: 999;
+  box-shadow: 0 4px 12px rgba(43, 133, 228, 0.3);
+}
+.btn-text[data-v-9873c737] {
+  font-size: 0.75rem;
+  color: #FFFFFF;
+  margin-top: 0.125rem;
+}
 /**
  * 这里是uni-app内置的常用样式变量
  *

+ 2 - 2
unpackage/dist/dev/app-plus/pages/index/detail/index.css

@@ -2051,7 +2051,7 @@ body {
 .order-detail .fixed-left[data-v-8b10f148] {
   position: fixed;
   left: 0;
-  top: 150px;
+  top: 11%;
   width: 3.125rem;
 }
 .order-detail .fixed-left .common-bg[data-v-8b10f148] {
@@ -2068,7 +2068,7 @@ body {
 .order-detail .fixed-right[data-v-8b10f148] {
   position: fixed;
   right: 0;
-  top: 180px;
+  top: 12%;
   width: 2.1875rem;
 }
 .order-detail .fixed-right .letter-bg[data-v-8b10f148] {

+ 799 - 0
unpackage/dist/dev/app-plus/pages/index/detail/user-orders.css

@@ -0,0 +1,799 @@
+
+/* 无任何数据的空布局 */
+.mescroll-empty[data-v-7cefd855] {
+	box-sizing: border-box;
+	width: 100%;
+	padding: 3.125rem 1.5625rem;
+	text-align: center;
+}
+.mescroll-empty.empty-fixed[data-v-7cefd855] {
+	z-index: 99;
+	position: absolute; /*transform会使fixed失效,最终会降级为absolute */
+	top: 3.125rem;
+	left: 0;
+}
+.mescroll-empty .empty-icon[data-v-7cefd855] {
+	width: 8.75rem;
+	height: 8.75rem;
+}
+.mescroll-empty .empty-tip[data-v-7cefd855] {
+	margin-top: 0.625rem;
+	height: 1.25rem;
+	font-size: 0.875rem;
+	font-family: PingFangSC;
+	font-weight: 500;
+	color: #666666;
+	line-height: 1.25rem;
+}
+.mescroll-empty .empty-btn[data-v-7cefd855] {
+	display: inline-block;
+	margin-top: 1.25rem;
+	min-width: 6.25rem;
+	padding: 0.5625rem;
+	font-size: 0.875rem;
+	border: 0.03125rem solid #e04b28;
+	border-radius: 1.875rem;
+	color: #e04b28;
+}
+.mescroll-empty .empty-btn[data-v-7cefd855]:active {
+	opacity: 0.75;
+}
+
+
+/* 回到顶部的按钮 */
+.mescroll-totop[data-v-49fff3a8] {
+	z-index: 9990;
+	position: fixed !important; /* 加上important避免编译到H5,在多mescroll中定位失效 */
+	right: 0.625rem;
+	bottom: 3.75rem;
+	width: 2.25rem;
+	height: auto;
+	border-radius: 50%;
+	opacity: 0;
+	transition: opacity 0.5s; /* 过渡 */
+	margin-bottom: var(--window-bottom); /* css变量 */
+}
+
+/* 适配 iPhoneX */
+@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
+.mescroll-totop-safearea[data-v-49fff3a8] {
+		margin-bottom: calc(var(--window-bottom) + constant(safe-area-inset-bottom)); /* window-bottom + 适配 iPhoneX */
+		margin-bottom: calc(var(--window-bottom) + env(safe-area-inset-bottom));
+}
+}
+
+/* 显示 -- 淡入 */
+.mescroll-totop-in[data-v-49fff3a8] {
+	opacity: 1;
+}
+
+/* 隐藏 -- 淡出且不接收事件*/
+.mescroll-totop-out[data-v-49fff3a8] {
+	opacity: 0;
+	pointer-events: none;
+}
+
+.mescroll-uni-warp[data-v-97b1664c] {
+	height: 100%;
+}
+.mescroll-uni-content[data-v-97b1664c] {
+	height: 100%;
+}
+.mescroll-uni[data-v-97b1664c] {
+	position: relative;
+	width: 100%;
+	height: 100%;
+	min-height: 6.25rem;
+	overflow-y: auto;
+	box-sizing: border-box;
+	/* 避免设置padding出现双滚动条的问题 */
+}
+
+/* 定位的方式固定高度 */
+.mescroll-uni-fixed[data-v-97b1664c] {
+	z-index: 1;
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	width: auto;
+	/* 使right生效 */
+	height: auto;
+	/* 使bottom生效 */
+}
+
+/* 适配 iPhoneX */
+@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
+.mescroll-safearea[data-v-97b1664c] {
+		padding-bottom: constant(safe-area-inset-bottom);
+		padding-bottom: env(safe-area-inset-bottom);
+}
+}
+
+/* 下拉刷新区域 */
+.mescroll-downwarp[data-v-97b1664c] {
+	position: absolute;
+	top: -100%;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	text-align: center;
+}
+
+/* 下拉刷新--内容区,定位于区域底部 */
+.mescroll-downwarp .downwarp-content[data-v-97b1664c] {
+	position: absolute;
+	left: 0;
+	bottom: 0;
+	width: 100%;
+	min-height: 1.875rem;
+	padding: 0.625rem 0;
+	text-align: center;
+}
+
+/* 下拉刷新--提示文本 */
+.mescroll-downwarp .downwarp-tip[data-v-97b1664c] {
+	display: inline-block;
+	font-size: 0.875rem;
+	vertical-align: middle;
+	margin-left: 0.5rem;
+	/* color: gray; 已在style设置color,此处删去*/
+}
+
+/* 下拉刷新--旋转进度条 */
+.mescroll-downwarp .downwarp-progress[data-v-97b1664c] {
+	display: inline-block;
+	width: 1rem;
+	height: 1rem;
+	border-radius: 50%;
+	border: 0.0625rem solid gray;
+	border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
+	vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-downwarp .mescroll-rotate[data-v-97b1664c] {
+	animation: mescrollDownRotate-97b1664c 0.6s linear infinite;
+}
+@keyframes mescrollDownRotate-97b1664c {
+0% {
+		transform: rotate(0deg);
+}
+100% {
+		transform: rotate(360deg);
+}
+}
+
+/* 上拉加载区域 */
+.mescroll-upwarp[data-v-97b1664c] {
+	box-sizing: border-box;
+	min-height: 3.4375rem;
+	padding: 0.9375rem 0;
+	text-align: center;
+	clear: both;
+}
+
+/*提示文本 */
+.mescroll-upwarp .upwarp-tip[data-v-97b1664c],
+.mescroll-upwarp .upwarp-nodata[data-v-97b1664c] {
+	display: inline-block;
+	font-size: 0.875rem;
+	vertical-align: middle;
+	/* color: gray; 已在style设置color,此处删去*/
+}
+.mescroll-upwarp .upwarp-tip[data-v-97b1664c] {
+	margin-left: 0.5rem;
+}
+
+/*旋转进度条 */
+.mescroll-upwarp .upwarp-progress[data-v-97b1664c] {
+	display: inline-block;
+	width: 1rem;
+	height: 1rem;
+	border-radius: 50%;
+	border: 0.0625rem solid gray;
+	border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
+	vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-upwarp .mescroll-rotate[data-v-97b1664c] {
+	animation: mescrollUpRotate-97b1664c 0.6s linear infinite;
+}
+@keyframes mescrollUpRotate-97b1664c {
+0% {
+		transform: rotate(0deg);
+}
+100% {
+		transform: rotate(360deg);
+}
+}
+
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+/* 颜色变量 */
+/* 行为相关颜色 */
+/* 文字基本颜色 */
+/* 背景颜色 */
+/* 边框颜色 */
+/* 尺寸变量 */
+/* 文字尺寸 */
+/* 图片尺寸 */
+/* Border Radius */
+/* 水平间距 */
+/* 垂直间距 */
+/* 透明度 */
+/* 文章场景相关 */
+.item[data-v-30bc23e1] {
+  line-height: 4.6875rem;
+  border-bottom: 1px solid #ccc;
+}
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+/* 颜色变量 */
+/* 行为相关颜色 */
+/* 文字基本颜色 */
+/* 背景颜色 */
+/* 边框颜色 */
+/* 尺寸变量 */
+/* 文字尺寸 */
+/* 图片尺寸 */
+/* Border Radius */
+/* 水平间距 */
+/* 垂直间距 */
+/* 透明度 */
+/* 文章场景相关 */
+uni-view[data-v-2af81691], uni-scroll-view[data-v-2af81691], uni-swiper-item[data-v-2af81691] {
+  display: flex;
+  flex-direction: column;
+  flex-shrink: 0;
+  flex-grow: 0;
+  flex-basis: auto;
+  align-items: stretch;
+  align-content: flex-start;
+}
+.u-loading-icon[data-v-2af81691] {
+  flex-direction: row;
+  align-items: center;
+  justify-content: center;
+  color: #c8c9cc;
+}
+.u-loading-icon__text[data-v-2af81691] {
+  margin-left: 4px;
+  color: #606266;
+  font-size: 14px;
+  line-height: 20px;
+}
+.u-loading-icon__spinner[data-v-2af81691] {
+  width: 30px;
+  height: 30px;
+  position: relative;
+  box-sizing: border-box;
+  max-width: 100%;
+  max-height: 100%;
+  animation: u-rotate-2af81691 1s linear infinite;
+}
+.u-loading-icon__spinner--semicircle[data-v-2af81691] {
+  border-width: 2px;
+  border-color: transparent;
+  border-top-right-radius: 100px;
+  border-top-left-radius: 100px;
+  border-bottom-left-radius: 100px;
+  border-bottom-right-radius: 100px;
+  border-style: solid;
+}
+.u-loading-icon__spinner--circle[data-v-2af81691] {
+  border-top-right-radius: 100px;
+  border-top-left-radius: 100px;
+  border-bottom-left-radius: 100px;
+  border-bottom-right-radius: 100px;
+  border-width: 2px;
+  border-top-color: #e5e5e5;
+  border-right-color: #e5e5e5;
+  border-bottom-color: #e5e5e5;
+  border-left-color: #e5e5e5;
+  border-style: solid;
+}
+.u-loading-icon--vertical[data-v-2af81691] {
+  flex-direction: column;
+}
+[data-v-2af81691]:host {
+  font-size: 0px;
+  line-height: 1;
+}
+.u-loading-icon__spinner--spinner[data-v-2af81691] {
+  animation-timing-function: steps(12);
+}
+.u-loading-icon__text[data-v-2af81691]:empty {
+  display: none;
+}
+.u-loading-icon--vertical .u-loading-icon__text[data-v-2af81691] {
+  margin: 6px 0 0;
+  color: #606266;
+}
+.u-loading-icon__dot[data-v-2af81691] {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+.u-loading-icon__dot[data-v-2af81691]:before {
+  display: block;
+  width: 2px;
+  height: 25%;
+  margin: 0 auto;
+  background-color: currentColor;
+  border-radius: 40%;
+  content: " ";
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(1) {
+  transform: rotate(30deg);
+  opacity: 1;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(2) {
+  transform: rotate(60deg);
+  opacity: 0.9375;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(3) {
+  transform: rotate(90deg);
+  opacity: 0.875;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(4) {
+  transform: rotate(120deg);
+  opacity: 0.8125;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(5) {
+  transform: rotate(150deg);
+  opacity: 0.75;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(6) {
+  transform: rotate(180deg);
+  opacity: 0.6875;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(7) {
+  transform: rotate(210deg);
+  opacity: 0.625;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(8) {
+  transform: rotate(240deg);
+  opacity: 0.5625;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(9) {
+  transform: rotate(270deg);
+  opacity: 0.5;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(10) {
+  transform: rotate(300deg);
+  opacity: 0.4375;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(11) {
+  transform: rotate(330deg);
+  opacity: 0.375;
+}
+.u-loading-icon__dot[data-v-2af81691]:nth-of-type(12) {
+  transform: rotate(360deg);
+  opacity: 0.3125;
+}
+@keyframes u-rotate-2af81691 {
+0% {
+    transform: rotate(0deg);
+}
+to {
+    transform: rotate(1turn);
+}
+}
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+/* 颜色变量 */
+/* 行为相关颜色 */
+/* 文字基本颜色 */
+/* 背景颜色 */
+/* 边框颜色 */
+/* 尺寸变量 */
+/* 文字尺寸 */
+/* 图片尺寸 */
+/* Border Radius */
+/* 水平间距 */
+/* 垂直间距 */
+/* 透明度 */
+/* 文章场景相关 */
+uni-view[data-v-ac70166d], uni-scroll-view[data-v-ac70166d], uni-swiper-item[data-v-ac70166d] {
+  display: flex;
+  flex-direction: column;
+  flex-shrink: 0;
+  flex-grow: 0;
+  flex-basis: auto;
+  align-items: stretch;
+  align-content: flex-start;
+}
+@font-face {
+  font-family: "uicon-iconfont";
+  src: url("https://at.alicdn.com/t/font_2225171_8kdcwk4po24.ttf") format("truetype");
+}
+.u-icon[data-v-ac70166d] {
+  display: flex;
+  align-items: center;
+}
+.u-icon--left[data-v-ac70166d] {
+  flex-direction: row-reverse;
+  align-items: center;
+}
+.u-icon--right[data-v-ac70166d] {
+  flex-direction: row;
+  align-items: center;
+}
+.u-icon--top[data-v-ac70166d] {
+  flex-direction: column-reverse;
+  justify-content: center;
+}
+.u-icon--bottom[data-v-ac70166d] {
+  flex-direction: column;
+  justify-content: center;
+}
+.u-icon__icon[data-v-ac70166d] {
+  font-family: uicon-iconfont;
+  position: relative;
+
+  display: flex;
+
+  flex-direction: row;
+  align-items: center;
+}
+.u-icon__icon--primary[data-v-ac70166d] {
+  color: #22ac38;
+}
+.u-icon__icon--success[data-v-ac70166d] {
+  color: #22ac38;
+}
+.u-icon__icon--error[data-v-ac70166d] {
+  color: #f56c6c;
+}
+.u-icon__icon--warning[data-v-ac70166d] {
+  color: #f9ae3d;
+}
+.u-icon__icon--info[data-v-ac70166d] {
+  color: #909399;
+}
+.u-icon__img[data-v-ac70166d] {
+  height: auto;
+  will-change: transform;
+}
+.u-icon__label[data-v-ac70166d] {
+  line-height: 1;
+}
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+/* 颜色变量 */
+/* 行为相关颜色 */
+/* 文字基本颜色 */
+/* 背景颜色 */
+/* 边框颜色 */
+/* 尺寸变量 */
+/* 文字尺寸 */
+/* 图片尺寸 */
+/* Border Radius */
+/* 水平间距 */
+/* 垂直间距 */
+/* 透明度 */
+/* 文章场景相关 */
+uni-view[data-v-5ce41ee6], uni-scroll-view[data-v-5ce41ee6], uni-swiper-item[data-v-5ce41ee6] {
+  display: flex;
+  flex-direction: column;
+  flex-shrink: 0;
+  flex-grow: 0;
+  flex-basis: auto;
+  align-items: stretch;
+  align-content: flex-start;
+}
+.u-button[data-v-5ce41ee6] {
+  width: 100%;
+}
+.u-button__text[data-v-5ce41ee6] {
+  white-space: nowrap;
+  line-height: 1;
+}
+.u-button[data-v-5ce41ee6]:before {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 100%;
+  height: 100%;
+  border: inherit;
+  border-radius: inherit;
+  transform: translate(-50%, -50%);
+  opacity: 0;
+  content: " ";
+  background-color: #000;
+  border-color: #000;
+}
+.u-button--active[data-v-5ce41ee6]:before {
+  opacity: 0.15;
+}
+.u-button__icon + .u-button__text[data-v-5ce41ee6]:not(:empty), .u-button__loading-text[data-v-5ce41ee6] {
+  margin-left: 4px;
+}
+.u-button--plain.u-button--primary[data-v-5ce41ee6] {
+  color: #22ac38;
+}
+.u-button--plain.u-button--info[data-v-5ce41ee6] {
+  color: #909399;
+}
+.u-button--plain.u-button--success[data-v-5ce41ee6] {
+  color: #22ac38;
+}
+.u-button--plain.u-button--error[data-v-5ce41ee6] {
+  color: #f56c6c;
+}
+.u-button--plain.u-button--warning[data-v-5ce41ee6] {
+  color: #f56c6c;
+}
+.u-button[data-v-5ce41ee6] {
+  height: 52px;
+  position: relative;
+  align-items: center;
+  justify-content: center;
+
+  display: flex;
+
+  flex-direction: row;
+  box-sizing: border-box;
+  flex-direction: row;
+}
+.u-button__text[data-v-5ce41ee6] {
+  font-size: 16px;
+}
+.u-button__loading-text[data-v-5ce41ee6] {
+  font-size: 16px;
+  margin-left: 4px;
+}
+.u-button--large[data-v-5ce41ee6] {
+  width: 100%;
+  height: 64px;
+  padding: 0 15px;
+  font-size: 20px;
+}
+.u-button--normal[data-v-5ce41ee6] {
+  padding: 0 12px;
+  font-size: 16px;
+}
+.u-button--small[data-v-5ce41ee6] {
+  min-width: 60px;
+  height: 30px;
+  padding: 0px 8px;
+  font-size: 12px;
+}
+.u-button--mini[data-v-5ce41ee6] {
+  height: 22px;
+  font-size: 10px;
+  min-width: 50px;
+  padding: 0px 8px;
+}
+.u-button--disabled[data-v-5ce41ee6] {
+  opacity: 0.5;
+}
+.u-button--info[data-v-5ce41ee6] {
+  color: #323233;
+  background-color: #fff;
+  border-color: #ebedf0;
+  border-width: 1px;
+  border-style: solid;
+}
+.u-button--success[data-v-5ce41ee6] {
+  color: #fff;
+  background-color: #22ac38;
+  border-color: #22ac38;
+  border-width: 1px;
+  border-style: solid;
+}
+.u-button--primary[data-v-5ce41ee6] {
+  color: #fff;
+  background-color: #22ac38;
+  border-color: #22ac38;
+  border-width: 1px;
+  border-style: solid;
+}
+.u-button--error[data-v-5ce41ee6] {
+  color: #fff;
+  background-color: #f56c6c;
+  border-color: #f56c6c;
+  border-width: 1px;
+  border-style: solid;
+}
+.u-button--warning[data-v-5ce41ee6] {
+  color: #fff;
+  background-color: #f9ae3d;
+  border-color: #f9ae3d;
+  border-width: 1px;
+  border-style: solid;
+}
+.u-button--block[data-v-5ce41ee6] {
+
+  display: flex;
+
+  flex-direction: row;
+  width: 100%;
+}
+.u-button--circle[data-v-5ce41ee6] {
+  border-top-right-radius: 100px;
+  border-top-left-radius: 100px;
+  border-bottom-left-radius: 100px;
+  border-bottom-right-radius: 100px;
+}
+.u-button--square[data-v-5ce41ee6] {
+  border-bottom-left-radius: 3px;
+  border-bottom-right-radius: 3px;
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+.u-button__icon[data-v-5ce41ee6] {
+  min-width: 1em;
+  line-height: inherit !important;
+  vertical-align: top;
+}
+.u-button--plain[data-v-5ce41ee6] {
+  background-color: #fff;
+}
+.u-button--hairline[data-v-5ce41ee6] {
+  border-width: 0.5px !important;
+}
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+/* 颜色变量 */
+/* 行为相关颜色 */
+/* 文字基本颜色 */
+/* 背景颜色 */
+/* 边框颜色 */
+/* 尺寸变量 */
+/* 文字尺寸 */
+/* 图片尺寸 */
+/* Border Radius */
+/* 水平间距 */
+/* 垂直间距 */
+/* 透明度 */
+/* 文章场景相关 */
+.order-card[data-v-12bc2a79] {
+  background: #ffffff;
+  border-radius: 0.25rem;
+  padding: 0.625rem;
+  margin-bottom: 0.625rem;
+  box-shadow: 0 0.0625rem 0.25rem rgba(0, 0, 0, 0.1);
+}
+.order-card .user-info[data-v-12bc2a79] {
+  display: flex;
+  align-items: flex-start;
+  margin-bottom: 0.625rem;
+}
+.order-card .user-info .avatar[data-v-12bc2a79] {
+  width: 2.5rem;
+  height: 2.5rem;
+  border-radius: 1.25rem;
+  margin-right: 0.625rem;
+}
+.order-card .user-info .user-details[data-v-12bc2a79] {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+}
+.order-card .user-info .user-details.right-items[data-v-12bc2a79] {
+  align-items: flex-end;
+}
+.order-card .user-info .user-details .username[data-v-12bc2a79] {
+  font-size: 0.875rem;
+  color: #333333;
+  margin-bottom: 0.125rem;
+}
+.order-card .user-info .user-details .date[data-v-12bc2a79] {
+  font-size: 0.75rem;
+  color: #999999;
+}
+.order-card .user-info .user-details .status[data-v-12bc2a79] {
+  font-size: 0.75rem;
+  font-weight: bold;
+}
+.order-card .order-details[data-v-12bc2a79] {
+  font-size: 0.8125rem;
+  color: #333333;
+  margin-bottom: 0.625rem;
+}
+.order-card .order-details .detail-row[data-v-12bc2a79] {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 0.375rem;
+}
+.order-card .order-details .detail-row .link[data-v-12bc2a79] {
+  color: #007bff;
+  text-decoration: underline;
+  cursor: pointer;
+}
+.order-card .action-buttons[data-v-12bc2a79] {
+  display: flex;
+  justify-content: space-between;
+}
+.order-card .action-buttons[data-v-12bc2a79] .u-button {
+  flex: 1;
+  margin: 0 0.3125rem;
+  height: 1.875rem;
+  font-size: 0.8125rem;
+}
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+/* 颜色变量 */
+/* 行为相关颜色 */
+/* 文字基本颜色 */
+/* 背景颜色 */
+/* 边框颜色 */
+/* 尺寸变量 */
+/* 文字尺寸 */
+/* 图片尺寸 */
+/* Border Radius */
+/* 水平间距 */
+/* 垂直间距 */
+/* 透明度 */
+/* 文章场景相关 */
+.search-area {
+  padding: 0.75rem;
+  background-color: #ffffff;
+  z-index: 9;
+}

+ 9 - 9
unpackage/dist/dev/app-plus/pages/index/wms/location-select.css

@@ -197,21 +197,21 @@ uni-view[data-v-e082a34a], uni-scroll-view[data-v-e082a34a], uni-swiper-item[dat
 }
 
 .container[data-v-b26ec186] {
-    position: relative;
+		position: relative;
 }
 .location-list[data-v-b26ec186] {
-    padding: 12px 0 60px;
+		padding: 12px 0 60px;
 }
 .location-item[data-v-b26ec186] {
-    background-color: #fff;
-    padding: 15px 20px;
-    margin-bottom: 1px;
-    font-size: 16px;
+		background-color: #fff;
+		padding: 15px 20px;
+		margin-bottom: 1px;
+		font-size: 16px;
 }
 .location-item-selected[data-v-b26ec186] {
-    background-color: #e8f5e9;
-    border-left: 4px solid #19be6b;
+		background-color: #e8f5e9;
+		border-left: 4px solid #19be6b;
 }
 .location-item-hover[data-v-b26ec186] {
-    background-color: #f5f5f5;
+		background-color: #f5f5f5;
 }

+ 1 - 1
unpackage/dist/dev/app-plus/pages/login/login.css

@@ -690,7 +690,7 @@ uni-view[data-v-5ce41ee6], uni-scroll-view[data-v-5ce41ee6], uni-swiper-item[dat
 }
 
 body {
-		background-color: #ffffff;
+    background-color: #ffffff;
 }
 
 /**

+ 2 - 2
unpackage/dist/dev/app-plus/pages/my/page/audit-unfinished.css

@@ -463,7 +463,7 @@ uni-view[data-v-5ce41ee6], uni-scroll-view[data-v-5ce41ee6], uni-swiper-item[dat
 /* 透明度 */
 /* 文章场景相关 */
 .order-card[data-v-12bc2a79] {
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 0.25rem;
   padding: 0.625rem;
   margin-bottom: 0.625rem;
@@ -512,7 +512,7 @@ uni-view[data-v-5ce41ee6], uni-scroll-view[data-v-5ce41ee6], uni-swiper-item[dat
   margin-bottom: 0.375rem;
 }
 .order-card .order-details .detail-row .link[data-v-12bc2a79] {
-  color: #007BFF;
+  color: #007bff;
   text-decoration: underline;
   cursor: pointer;
 }

+ 69 - 42
utils/VolumeTTS.js

@@ -1,83 +1,110 @@
 class VolumeTTS {
     ttsParams = {
-        lang: 'zh-CN',
+        lang: "zh-CN",
         speed: 1, // 将 0-10 转换为 0-1
         pitch: 1, // 将 0-10 转换为 0-1
         volume: 1,
     };
     TTSModule;
 
-    platform = uni.getSystemInfoSync().platform
+    platform = uni.getSystemInfoSync().platform;
 
     constructor(opts) {
-        if (opts) this.ttsParams = opts;
-
-        // #ifdef APP-PLUS  
-        this.init()
+        let audioConfig = uni.getStorageSync("audioConfig");
+        if (opts) {
+            this.ttsParams = opts;
+        } else if (audioConfig) {
+            this.ttsParams = {
+                lang: "zh-CN",
+                speed: audioConfig.audioSpeed / 10,
+                pitch: audioConfig.audioVolume,
+                volume: 1,
+            };
+        }
+        // #ifdef APP-PLUS
+        this.init();
         // #endif
     }
 
     init() {
-        this.TTSModule = uni.requireNativePlugin('nrb-tts-plugin')
-        this.TTSModule && this.TTSModule.init({
-            "lang": "zh",
-            "country": "CN"
-        }, res => {
-            if (res.success == 0) {
-                console.log('TTS初始化成功')
-            }
-        })
+        this.TTSModule = uni.requireNativePlugin("nrb-tts-plugin");
+        this.TTSModule &&
+            this.TTSModule.init(
+                {
+                    lang: "zh",
+                    country: "CN",
+                },
+                (res) => {
+                    if (res.success == 0) {
+                        console.log("TTS初始化成功");
+                    }
+                }
+            );
     }
 
     //加一个text的预处理,将text中的数字替换成 零一二三四五六七八九十
     preprocessText(text) {
         // 将text中的数字替换成 零一二三四五六七八九十
         const digitMap = {
-            '0': '零', '1': '一', '2': '二', '3': '三', '4': '四',
-            '5': '五', '6': '六', '7': '七', '8': '八', '9': '九'
+            0: "零",
+            1: "一",
+            2: "二",
+            3: "三",
+            4: "四",
+            5: "五",
+            6: "六",
+            7: "七",
+            8: "八",
+            9: "九",
         };
-        
-        return text.replace(/\d+/g, match => {
+
+        return text.replace(/\d+/g, (match) => {
             // 逐字符替换所有数字,包括10
-            return match.split('').map(digit => digitMap[digit] || digit).join('');
+            return match
+                .split("")
+                .map((digit) => digitMap[digit] || digit)
+                .join("");
         });
     }
 
     speak(text) {
-        text = this.preprocessText(text)
+        text = this.preprocessText(text);
         // #ifdef H5
         // H5端使用Web Speech API
-        if ('speechSynthesis' in window) {
-            const utterance = new SpeechSynthesisUtterance(text)
-            utterance.lang = this.ttsParams.lang
-            utterance.rate = this.ttsParams.speed
-            utterance.pitch = this.ttsParams.pitch
-            utterance.volume = this.ttsParams.volume
-            speechSynthesis.speak(utterance)
+        if ("speechSynthesis" in window) {
+            const utterance = new SpeechSynthesisUtterance(text);
+            utterance.lang = this.ttsParams.lang;
+            utterance.rate = this.ttsParams.speed;
+            utterance.pitch = this.ttsParams.pitch;
+            utterance.volume = this.ttsParams.volume;
+            speechSynthesis.speak(utterance);
         }
         // #endif
 
         // #ifdef APP-PLUS
-        let opts = this.platform == 'ios' ? {
-            "rate": this.ttsParams.speed,
-            "lang": "zh-CN",
-            "volume": 1
-        } : {
-            "pitch": this.ttsParams.pitch,
-            "speechRate": this.ttsParams.speed,
-            "queueMode": 1,
-        }
+        let opts =
+            this.platform == "ios"
+                ? {
+                      rate: this.ttsParams.speed,
+                      lang: "zh-CN",
+                      volume: 1,
+                  }
+                : {
+                      pitch: this.ttsParams.pitch,
+                      speechRate: this.ttsParams.speed,
+                      queueMode: 1,
+                  };
         this.TTSModule.speak(text, opts, (e) => {
-            console.log(e, '读取成功')
-        })
-        // #endif   
+            console.log(e, "读取成功");
+        });
+        // #endif
     }
 
     stop() {
         if (this.TTSModule) {
-            this.TTSModule.stop()
+            this.TTSModule.stop();
         }
     }
 }
 
-export default VolumeTTS
+export default VolumeTTS;

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません