ylong 8 månader sedan
förälder
incheckning
7f41dd4a10
100 ändrade filer med 1254 tillägg och 195 borttagningar
  1. 207 0
      composables/useBarcode.js
  2. 10 8
      config/audioUtil.js
  3. 1 1
      config/request.js
  4. 366 0
      docs/Vue3使用指南.md
  5. 2 1
      main.js
  6. 1 1
      pages.json
  7. 5 1
      pages/book/index.vue
  8. 4 1
      pages/index/audit/confirm-receipt.vue
  9. 6 2
      pages/index/audit/express-order.vue
  10. 4 1
      pages/index/audit/scan-order.vue
  11. 11 5
      pages/index/detail/batch-audit.vue
  12. 10 5
      pages/index/detail/book-audit.vue
  13. 215 107
      pages/index/detail/components/OrderInfo.vue
  14. 274 0
      pages/index/detail/components/SmsModal.vue
  15. 10 4
      pages/index/detail/index.vue
  16. 4 1
      pages/index/entry/book-weight.vue
  17. 5 1
      pages/index/entry/commodity-scan.vue
  18. 4 1
      pages/index/entry/scan-book.vue
  19. 4 1
      pages/index/express/quick-check.vue
  20. 3 0
      pages/index/express/quick-unpack.vue
  21. 4 1
      pages/index/express/route-exception.vue
  22. 5 1
      pages/index/express/transfer-sign.vue
  23. 5 1
      pages/index/express/warehouse-sign.vue
  24. 5 1
      pages/index/express/weight-modify.vue
  25. 1 1
      pages/index/index.vue
  26. 5 2
      pages/index/offline/check-order.vue
  27. 4 5
      pages/index/wms/bad-in.vue
  28. 5 1
      pages/index/wms/bad-out-order.vue
  29. 4 1
      pages/index/wms/bad-out.vue
  30. 5 1
      pages/index/wms/location-order-list.vue
  31. 5 1
      pages/index/wms/location-order.vue
  32. 5 1
      pages/index/wms/location-select.vue
  33. 4 1
      pages/index/wms/order-query-list.vue
  34. 4 1
      pages/index/wms/order-query.vue
  35. 7 6
      pages/index/wms/speedy-check.vue
  36. 1 0
      pages/index/wms/task-detail.vue
  37. 1 1
      pages/my/page/warehouse.vue
  38. BIN
      unpackage/cache/apk/__UNI__65C1C73_cm.apk
  39. 1 0
      unpackage/cache/apk/apkurl
  40. 0 0
      unpackage/cache/apk/cmManifestCache.json
  41. 4 0
      unpackage/cache/certdata
  42. 4 0
      unpackage/cache/cloudcertificate/certini
  43. BIN
      unpackage/cache/cloudcertificate/package.keystore
  44. 24 23
      unpackage/cache/wgt/__UNI__65C1C73/__uniappview.html
  45. 1 1
      unpackage/cache/wgt/__UNI__65C1C73/app-config-service.js
  46. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/app-service.js
  47. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/app.css
  48. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/manifest.json
  49. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/book/index.css
  50. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/audit/confirm-receipt.css
  51. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/audit/express-order.css
  52. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/audit/isbn-order.css
  53. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/audit/scan-order.css
  54. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/audit/sender.css
  55. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/detail/batch-audit.css
  56. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/detail/book-audit.css
  57. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/detail/index.css
  58. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/detail/user-orders.css
  59. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/entry/book-weight.css
  60. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/entry/commodity-scan.css
  61. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/entry/scan-book.css
  62. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/logistics-detail.css
  63. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/quick-check.css
  64. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/quick-unpack.css
  65. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/route-exception.css
  66. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/transfer-sign.css
  67. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/warehouse-sign.css
  68. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/weight-modify.css
  69. 1 1
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/index.css
  70. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/offline/check-order.css
  71. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/offline/check-record.css
  72. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/statistic/after-sale.css
  73. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/statistic/audit.css
  74. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/statistic/package.css
  75. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/bad-in.css
  76. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/bad-off.css
  77. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/bad-out-order.css
  78. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/bad-out.css
  79. 1 1
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/good-in.css
  80. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/location-order-list.css
  81. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/location-order.css
  82. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/location-select.css
  83. 1 1
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/medium-in.css
  84. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/order-query-list.css
  85. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/order-query.css
  86. 1 1
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/secondary-in.css
  87. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/speedy-check-add.css
  88. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/speedy-check.css
  89. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/task-detail.css
  90. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/warehouse-select.css
  91. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/login/login.css
  92. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/my/my.css
  93. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/audit-unfinished.css
  94. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/book-display.css
  95. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/password.css
  96. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/school.css
  97. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/user-info.css
  98. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/version.css
  99. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/volume.css
  100. 0 0
      unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/warehouse.css

+ 207 - 0
composables/useBarcode.js

@@ -0,0 +1,207 @@
+import { ref, onMounted, onUnmounted, onShow } from 'vue'
+import { 
+  useInit, 
+  useGlobalEvent, 
+  updateActivePageOnShow,
+  cleanupOnPageUnload 
+} from '@/utils/useBarcodeModule.js'
+
+/**
+ * Vue3 Composable - 条码扫描
+ * @param {Object} options 配置选项
+ * @param {Function} options.onScan 扫描成功回调
+ * @param {Function} options.onError 扫描失败回调
+ * @param {boolean} options.autoInit 是否自动初始化
+ */
+export function useBarcode(options = {}) {
+  const {
+    onScan,
+    onError,
+    autoInit = false
+  } = options
+
+  // 响应式状态
+  const isScanning = ref(false)
+  const isInitialized = ref(false)
+  const scanResult = ref(null)
+  const scanHistory = ref([])
+  const error = ref(null)
+
+  // 内部状态
+  let removeListener = null
+
+  /**
+   * 初始化扫描器
+   */
+  const init = async () => {
+    try {
+      if (isInitialized.value) {
+        console.warn('扫描器已经初始化')
+        return true
+      }
+
+      useInit()
+      isInitialized.value = true
+      error.value = null
+      
+      console.log('扫描器初始化成功')
+      return true
+    } catch (err) {
+      error.value = err
+      if (onError) {
+        onError(err)
+      }
+      console.error('扫描器初始化失败:', err)
+      return false
+    }
+  }
+
+  /**
+   * 开始扫描
+   */
+  const startScan = async () => {
+    try {
+      // 确保扫描器已初始化
+      if (!isInitialized.value) {
+        const success = await init()
+        if (!success) return false
+      }
+
+      if (isScanning.value) {
+        console.warn('扫描器已经在运行中')
+        return true
+      }
+
+      // 注册扫描事件监听
+      removeListener = useGlobalEvent(handleScanResult)
+      isScanning.value = true
+      error.value = null
+
+      console.log('开始扫描监听')
+      return true
+    } catch (err) {
+      error.value = err
+      if (onError) {
+        onError(err)
+      }
+      console.error('开始扫描失败:', err)
+      return false
+    }
+  }
+
+  /**
+   * 停止扫描
+   */
+  const stopScan = () => {
+    try {
+      if (removeListener) {
+        removeListener()
+        removeListener = null
+      }
+      
+      isScanning.value = false
+      console.log('停止扫描监听')
+      return true
+    } catch (err) {
+      error.value = err
+      if (onError) {
+        onError(err)
+      }
+      console.error('停止扫描失败:', err)
+      return false
+    }
+  }
+
+  /**
+   * 处理扫描结果
+   */
+  const handleScanResult = (result) => {
+    try {
+      console.log('收到扫描结果:', result)
+      
+      // 解析扫描结果
+      const barcode = result.barcode || result.data || result.code || String(result)
+      const timestamp = new Date().toLocaleString()
+      
+      const scanData = {
+        barcode,
+        timestamp,
+        rawData: result
+      }
+      
+      // 更新状态
+      scanResult.value = scanData
+      
+      // 添加到历史记录
+      scanHistory.value.unshift(scanData)
+      
+      // 限制历史记录数量
+      if (scanHistory.value.length > 100) {
+        scanHistory.value = scanHistory.value.slice(0, 100)
+      }
+      
+      // 执行回调
+      if (onScan) {
+        onScan(scanData)
+      }
+      
+      error.value = null
+      
+    } catch (err) {
+      error.value = err
+      if (onError) {
+        onError(err)
+      }
+      console.error('处理扫描结果失败:', err)
+    }
+  }
+
+  /**
+   * 清空扫描历史
+   */
+  const clearHistory = () => {
+    scanHistory.value = []
+    scanResult.value = null
+  }
+
+  /**
+   * 清理资源
+   */
+  const cleanup = () => {
+    stopScan()
+    cleanupOnPageUnload()
+  }
+
+  // 生命周期钩子
+  onMounted(() => {
+    if (autoInit) {
+      init()
+    }
+  })
+
+  onShow(() => {
+    // 页面显示时更新活跃页面
+    updateActivePageOnShow()
+  })
+
+  onUnmounted(() => {
+    cleanup()
+  })
+
+  // 返回API
+  return {
+    // 状态
+    isScanning,
+    isInitialized,
+    scanResult,
+    scanHistory,
+    error,
+    
+    // 方法
+    init,
+    startScan,
+    stopScan,
+    clearHistory,
+    cleanup
+  }
+} 

+ 10 - 8
config/audioUtil.js

@@ -1,18 +1,20 @@
-import { ref } from 'vue';
+import { ref } from "vue";
 
 // 创建音频上下文引用
 const audioContext = ref(null);
 
 // 初始化音频
 export const initClickSound = () => {
-    audioContext.value = uni.createInnerAudioContext();
-    audioContext.value.src = '/static/bap.mp3';
-    audioContext.value.volume = 0.8;
+  audioContext.value = uni.createInnerAudioContext();
+  audioContext.value.src = "/static/bap.mp3";
+  audioContext.value.volume = 0.8;
 };
 
 // 播放点击音效
 export const playClickSound = () => {
-    if (audioContext.value) {
-        audioContext.value.play();
-    }
-};    
+  // #ifdef APP-PLUS
+  if (audioContext.value) {
+    audioContext.value.play();
+  }
+  // #endif
+};

+ 1 - 1
config/request.js

@@ -1,7 +1,7 @@
 /**
  * 文档地址:https://uiadmin.net/uview-plus/js/http.html
  */
-const baseUrl = "https://bpi.shuhi.com";
+const baseUrl = "https://bk.shuhi.com";
 export function initRequest() {
     console.log("初始化了 http 请求代码");
     // 初始化请求配置

+ 366 - 0
docs/Vue3使用指南.md

@@ -0,0 +1,366 @@
+# Vue3 中使用扫描模块指南
+
+本文档说明如何在 Vue3 项目中使用 iData 扫描模块。
+
+## 📁 文件结构
+
+```
+project/
+├── utils/
+│   └── useBarcodeModule.js     # 扫描模块核心工具
+├── composables/
+│   └── useBarcode.js          # Vue3 composable 封装
+├── pages/
+│   ├── simple-scan.vue        # 简单使用示例
+│   ├── scan-example.vue       # 完整功能示例
+│   └── composable-scan.vue    # Composable 使用示例
+└── docs/
+    └── Vue3使用指南.md        # 本文档
+```
+
+## 🚀 快速开始
+
+### 1. 基础使用方式
+
+最简单的使用方式,直接在 Vue3 页面中导入和使用:
+
+```vue
+<template>
+  <view class="container">
+    <button @click="startScan" :disabled="isScanning">
+      {{ isScanning ? '扫描中...' : '开始扫描' }}
+    </button>
+    
+    <view v-if="scanResult">
+      扫描结果:{{ scanResult }}
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { ref, onUnmounted, onShow } from 'vue'
+import { 
+  useInit, 
+  useGlobalEvent, 
+  updateActivePageOnShow,
+  cleanupOnPageUnload 
+} from '@/utils/useBarcodeModule.js'
+
+const scanResult = ref('')
+const isScanning = ref(false)
+let removeListener = null
+
+const startScan = async () => {
+  // 初始化扫描模块
+  useInit()
+  
+  // 注册扫描事件监听
+  removeListener = useGlobalEvent((result) => {
+    const barcode = result.barcode || result.data || result.code
+    scanResult.value = barcode
+    console.log('扫描结果:', result)
+  })
+  
+  isScanning.value = true
+}
+
+const stopScan = () => {
+  if (removeListener) {
+    removeListener()
+    removeListener = null
+  }
+  isScanning.value = false
+}
+
+onShow(() => {
+  updateActivePageOnShow()
+})
+
+onUnmounted(() => {
+  if (removeListener) {
+    removeListener()
+  }
+  cleanupOnPageUnload()
+})
+</script>
+```
+
+### 2. 使用 Composable(推荐)
+
+更优雅的方式是使用 composable:
+
+```vue
+<template>
+  <view class="container">
+    <button @click="startScan" :disabled="isScanning">
+      {{ isScanning ? '扫描中...' : '开始扫描' }}
+    </button>
+    
+    <button @click="stopScan" :disabled="!isScanning">
+      停止扫描
+    </button>
+    
+    <view v-if="scanResult">
+      <text>条码:{{ scanResult.barcode }}</text>
+      <text>时间:{{ scanResult.timestamp }}</text>
+    </view>
+    
+    <view v-if="error" class="error">
+      错误:{{ error.message }}
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { useBarcode } from '@/composables/useBarcode.js'
+
+const {
+  isScanning,
+  scanResult,
+  error,
+  startScan,
+  stopScan
+} = useBarcode({
+  onScan: (scanData) => {
+    uni.showToast({
+      title: `扫描成功: ${scanData.barcode}`,
+      icon: 'success'
+    })
+  },
+  onError: (err) => {
+    uni.showToast({
+      title: '扫描出错',
+      icon: 'error'
+    })
+  },
+  autoInit: true
+})
+</script>
+```
+
+## 📚 API 说明
+
+### 核心模块 API
+
+#### `useInit()`
+初始化扫描模块。
+
+```javascript
+import { useInit } from '@/utils/useBarcodeModule.js'
+
+useInit()
+```
+
+#### `useGlobalEvent(callback)`
+注册全局扫描事件监听器。
+
+```javascript
+import { useGlobalEvent } from '@/utils/useBarcodeModule.js'
+
+const removeListener = useGlobalEvent((result) => {
+  console.log('扫描结果:', result)
+})
+
+// 移除监听器
+removeListener()
+```
+
+**参数:**
+- `callback`: 扫描结果回调函数
+  - `result`: 扫描结果对象
+
+**返回值:**
+- `Function`: 移除监听器的函数
+
+#### `updateActivePageOnShow()`
+更新当前活跃页面,在页面的 `onShow` 生命周期中调用。
+
+```javascript
+import { updateActivePageOnShow } from '@/utils/useBarcodeModule.js'
+import { onShow } from 'vue'
+
+onShow(() => {
+  updateActivePageOnShow()
+})
+```
+
+#### `cleanupOnPageUnload()`
+清理页面回调,在页面的 `onUnmounted` 生命周期中调用。
+
+```javascript
+import { cleanupOnPageUnload } from '@/utils/useBarcodeModule.js'
+import { onUnmounted } from 'vue'
+
+onUnmounted(() => {
+  cleanupOnPageUnload()
+})
+```
+
+### Composable API
+
+#### `useBarcode(options)`
+Vue3 composable,提供响应式的扫描功能。
+
+```javascript
+import { useBarcode } from '@/composables/useBarcode.js'
+
+const {
+  isScanning,
+  isInitialized,
+  scanResult,
+  scanHistory,
+  error,
+  init,
+  startScan,
+  stopScan,
+  clearHistory,
+  cleanup
+} = useBarcode(options)
+```
+
+**Options 参数:**
+- `onScan`: 扫描成功回调
+- `onError`: 扫描失败回调
+- `autoInit`: 是否自动初始化(默认 false)
+
+**返回的响应式状态:**
+- `isScanning`: 是否正在扫描
+- `isInitialized`: 是否已初始化
+- `scanResult`: 最新扫描结果
+- `scanHistory`: 扫描历史记录
+- `error`: 错误信息
+
+**返回的方法:**
+- `init()`: 初始化扫描器
+- `startScan()`: 开始扫描
+- `stopScan()`: 停止扫描
+- `clearHistory()`: 清空扫描历史
+- `cleanup()`: 清理资源
+
+## 🔥 最佳实践
+
+### 1. 生命周期管理
+
+正确管理页面生命周期是避免内存泄漏的关键:
+
+```vue
+<script setup>
+import { onShow, onUnmounted } from 'vue'
+import { updateActivePageOnShow, cleanupOnPageUnload } from '@/utils/useBarcodeModule.js'
+
+// 页面显示时更新活跃页面
+onShow(() => {
+  updateActivePageOnShow()
+})
+
+// 页面卸载时清理
+onUnmounted(() => {
+  cleanupOnPageUnload()
+})
+</script>
+```
+
+### 2. 错误处理
+
+始终处理可能的错误:
+
+```vue
+<script setup>
+const handleScan = async () => {
+  try {
+    const success = await startScan()
+    if (!success) {
+      uni.showToast({
+        title: '扫描启动失败',
+        icon: 'error'
+      })
+    }
+  } catch (error) {
+    console.error('扫描错误:', error)
+    uni.showToast({
+      title: '扫描出错',
+      icon: 'error'
+    })
+  }
+}
+</script>
+```
+
+### 3. 结果验证
+
+对扫描结果进行验证和格式化:
+
+```javascript
+const handleScanResult = (result) => {
+  try {
+    // 提取条码内容
+    const barcode = result.barcode || result.data || result.code || String(result)
+    
+    // 验证条码格式
+    if (!barcode || barcode.length < 3) {
+      throw new Error('无效的条码格式')
+    }
+    
+    // 处理业务逻辑
+    processBarcode(barcode)
+    
+  } catch (error) {
+    console.error('处理扫描结果失败:', error)
+    uni.showToast({
+      title: '条码格式错误',
+      icon: 'error'
+    })
+  }
+}
+```
+
+### 4. 性能优化
+
+限制历史记录数量,避免内存过度使用:
+
+```javascript
+const addToHistory = (scanData) => {
+  scanHistory.value.unshift(scanData)
+  
+  // 限制历史记录数量
+  if (scanHistory.value.length > 100) {
+    scanHistory.value = scanHistory.value.slice(0, 100)
+  }
+}
+```
+
+## ⚠️ 注意事项
+
+1. **平台兼容性**:此模块仅支持 uni-app APP 端(App-Plus)
+2. **设备要求**:需要 iData 扫描设备和对应的原生插件
+3. **权限需求**:可能需要相机权限等设备权限
+4. **内存管理**:务必在页面卸载时清理监听器
+5. **多页面管理**:模块已处理多页面切换,但仍需正确调用生命周期方法
+
+## 🐛 常见问题
+
+### Q: 扫描没有反应?
+A: 检查以下几点:
+- 确保已正确初始化 (`useInit()`)
+- 确保已注册监听器 (`useGlobalEvent()`)
+- 确保在 `onShow` 中调用了 `updateActivePageOnShow()`
+- 检查设备是否支持扫描功能
+
+### Q: 切换页面后扫描结果发送到错误页面?
+A: 确保在每个使用扫描的页面的 `onShow` 生命周期中调用 `updateActivePageOnShow()`
+
+### Q: 页面卸载后仍然收到扫描事件?
+A: 确保在 `onUnmounted` 生命周期中调用清理函数
+
+### Q: 内存泄漏问题?
+A: 检查是否正确清理了监听器和页面回调
+
+## 📝 示例页面
+
+项目中提供了三个示例页面:
+
+1. **simple-scan.vue** - 最简单的使用方式
+2. **scan-example.vue** - 完整功能展示
+3. **composable-scan.vue** - 使用 composable 的优雅方式
+
+建议从简单示例开始,然后根据需要选择合适的实现方式。 

+ 2 - 1
main.js

@@ -16,7 +16,7 @@ import VolumeTTS from "@/utils/VolumeTTS.js";
 let ttsModule = new VolumeTTS();
 
 // #ifdef APP
-import { useInit, useGlobalEvent, updateActivePageOnShow } from "./utils/useBarcodeModule";
+import { useInit, useGlobalEvent, updateActivePageOnShow,cleanupOnPageUnload } from "./utils/useBarcodeModule";
 useInit();
 // #endif
 
@@ -40,6 +40,7 @@ uni.$u.ttsModule = ttsModule;
 // #ifdef APP
 uni.$u.useGlobalEvent = useGlobalEvent;
 uni.$u.updateActivePageOnShow = updateActivePageOnShow;
+uni.$u.cleanupOnPageUnload = cleanupOnPageUnload;
 uni.$u.playClickSound = playClickSound;
 // #endif
 

+ 1 - 1
pages.json

@@ -261,7 +261,7 @@
 				{
 					"path": "entry/commodity-scan",
 					"style": {
-						"navigationBarTitleText": "商品档案扫码"
+						"navigationBarTitleText": "商品档案推送"
 					}
 				},
 				{

+ 5 - 1
pages/book/index.vue

@@ -38,7 +38,8 @@
 	} from 'vue'
 	import {
 		onLoad,
-		onShow
+		onShow,
+		onUnload
 	} from '@dcloudio/uni-app'
 	import FeedbackPopup from './components/feedbackPopup.vue';
 
@@ -114,6 +115,9 @@
 	onShow(() => {
 		uni.$u.updateActivePageOnShow()
 	})
+	onUnload(() => {
+		uni.$u.cleanupOnPageUnload()
+	})
 </script>
 
 <style lang="scss" scoped>

+ 4 - 1
pages/index/audit/confirm-receipt.vue

@@ -34,7 +34,7 @@
 
 <script setup>
 import { ref } from "vue";
-import { onLoad, onShow } from "@dcloudio/uni-app";
+import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
 
 const formData = ref({
     searchType: "2",
@@ -79,6 +79,9 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow();
 });
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 6 - 2
pages/index/audit/express-order.vue

@@ -13,7 +13,7 @@
                 <view class="search-box">
                     <u-input custom-style="width:100rpx" v-model="form.search"
                         :placeholder="form.searchType == '1' ? '扫描/输入订单编号' : '扫描/输入物流单号'" border="surround" clearable @focus="playGlobalSound"
-                        placeholder-style="font-size:32rpx" :custom-style="{ 'font-size': '32rpx' }">
+                        placeholder-style="font-size:32rpx" :customStyle="{ 'fontSize': '32rpx' }">
                     </u-input>
                     <u-button color="#c8c8c8" text="查询" @click="handleSearch" />
                 </view>
@@ -34,7 +34,8 @@ import {
 } from 'vue';
 import {
     onLoad,
-    onShow
+    onShow,
+    onUnload
 } from '@dcloudio/uni-app'
 
 const form = ref({
@@ -98,6 +99,9 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 4 - 1
pages/index/audit/scan-order.vue

@@ -61,7 +61,7 @@
 import {
     ref
 } from 'vue';
-import { onLoad, onShow } from "@dcloudio/uni-app"
+import { onLoad, onShow, onUnload } from "@dcloudio/uni-app"
 
 //点击全局音效
 function playGlobalSound(){
@@ -160,6 +160,9 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 11 - 5
pages/index/detail/batch-audit.vue

@@ -32,7 +32,7 @@
 
 <script setup>
 import { ref } from "vue";
-import { onLoad, onShow } from "@dcloudio/uni-app";
+import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
 import BookItem from "./components/BookItem2.vue";
 
 const detailMap = ref({});
@@ -73,6 +73,9 @@ function handleScan(isbn) {
         return;
     }
 
+    //取 isbn 的后四位字符串进行播报
+    let isbnStr = `${isbn.slice(-4)}`;
+
     let isbns = orderDetail.value.detailVoList.map((item) => item.isbn);
     //订单总数本
     if (isbns.includes(isbn)) {
@@ -85,17 +88,17 @@ function handleScan(isbn) {
             let scannedNum = scannedBooks.value.filter((item) => item == isbn).length || 0;
 
             if (scannedNum >= notAuditNum) {
-                let text = `${isbn}已超出订单中的数量`;
+                let text = `${isbnStr}已超出订单中的数量`;
                 return uni.$u.ttsModule.speak(text);
             } else {
                 //扫描到套装书
                 if (book.suit == 1) {
-                    let text = `${isbn}请注意套装书是否齐全`;
+                    let text = `${isbnStr}请注意套装书是否齐全`;
                     uni.$u.ttsModule.speak(text);
                 }
                 //扫描到需要取出的书
                 if (book.bookWarn == 1) {
-                    let text = `请注意${isbn}需要取出`;
+                    let text = `请注意${isbnStr}需要取出`;
                     uni.$u.ttsModule.speak(text);
                 }
 
@@ -104,7 +107,7 @@ function handleScan(isbn) {
             }
         }
     } else {
-        let text = `此订单中不存在${isbn}这本书 `;
+        let text = `此订单中不存在${isbnStr}这本书 `;
         uni.$u.ttsModule.speak(text);
     }
 }
@@ -195,6 +198,9 @@ onShow(() => {
     checkUserId.value = uni.getStorageSync("userInfo")?.userId;
     orderDetail.value = uni.getStorageSync("orderDetail");
 });
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 10 - 5
pages/index/detail/book-audit.vue

@@ -64,7 +64,7 @@
 
 <script setup>
 import { ref, nextTick } from "vue";
-import { onLoad, onShow } from "@dcloudio/uni-app";
+import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
 import AuditInfo from "./components/AuditInfo.vue";
 import FileInfo from "./components/FileInfo.vue";
 
@@ -129,6 +129,8 @@ function handleScan(isbn) {
         uni.$u.ttsModule.speak(text);
         return;
     }
+    //取 isbn 的后四位字符串进行播报
+    let isbnStr = `${isbn.slice(-4)}`;
 
     let isbns = orderDetail.value.detailVoList.map((item) => item.isbn);
 
@@ -139,19 +141,19 @@ function handleScan(isbn) {
             let noAuditNum = book.auditCommentList.filter((item) => item.sts == 0).length;
             console.log(noAuditNum, 'noAuditNum')
             if (noAuditNum == 0) {
-                let text = `${isbn}已超出订单中的数量`;
+                let text = `${isbnStr}已超出订单中的数量`;
                 uni.$u.ttsModule.speak(text);
                 return;
             }
 
             //扫描到套装书
             if (book.suit == 1) {
-                let text = `${isbn}请注意套装书是否齐全`;
+                let text = `${isbnStr}请注意套装书是否齐全`;
                 uni.$u.ttsModule.speak(text);
             }
             //扫描到需要取出的书
             if (book.bookWarn == 1) {
-                let text = `请注意${isbn}需要取出`;
+                let text = `请注意${isbnStr}需要取出`;
                 uni.$u.ttsModule.speak(text);
             }
 
@@ -162,7 +164,7 @@ function handleScan(isbn) {
             });
         }
     } else {
-        let text = `此订单中不存在${isbn}这本书 `;
+        let text = `此订单中不存在${isbnStr}这本书 `;
         uni.$u.ttsModule.speak(text);
     }
 }
@@ -239,6 +241,9 @@ onShow(() => {
     }
     uni.$u.updateActivePageOnShow();
 });
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 215 - 107
pages/index/detail/components/OrderInfo.vue

@@ -1,73 +1,94 @@
 <template>
-    <view class="order-info bg-white">
-        <view class="info-item flex">
-            <text class="label">订单编号</text>
-            <text style="color:#22ac38" class="flex-1 text-center content" @click="copyToClipboard(detail.orderId)">{{
-                detail.orderId }}</text>
-        </view>
-        <view class="info-item">
-            <text class="label">预估金额</text>
-            <text class="content">{{ detail.expectMoney }}</text>
-            <text class="label border-left">审核金额</text>
-            <text class="content">{{ detail.finalMoney }}</text>
-        </view>
-        <view class="info-item">
-            <text class="label">用户备注</text>
-            <text class="content">{{ detail.userRemark}}</text>
-        </view>
-        <view class="info-item" @click="handleRemark">
-            <text class="label">内部备注</text>
-            <text class="content">{{ detail?.manageRemark ? detail?.manageRemark.length > 0 ?
-                detail?.manageRemark[0]?.remark: ' ' : ' ' }}</text>
-        </view>
-        <view class="info-item">
-            <text class="label">订单状态</text>
-            <text class="content" style="color: #c5493e;">[{{ statusText }}]</text>
-        </view>
-        <view class="info-item">
-            <text class="label">快递</text>
-            <text class="content">{{ finalExpressText }}<text style="color: #409eef;" @click="copyToClipboard(detail.waybillCode)">(单号:{{ detail.waybillCode }})</text></text>
-        </view>
-        <view class="info-item">
-            <text class="label">发件人<text style="color: #e99d42;">(所有单)</text></text>
-
-            <view class="content flex flex-a-c flex-j-c">
-                <text class="content-text" @click="copyToClipboard(detail.sendMobile)">复制</text>
-                <text class="content-text ml-10 mr-10">{{ maskedSendMobile }}</text>
-                <u-icon v-if="detail.orderFrom == 1" name="weixin-circle-fill" size="18" color="#22ac38"></u-icon>
-                <u-icon v-if="detail.orderFrom == 2" name="zhifubao-circle-fill" size="18" color="#999"></u-icon>
+    <view>
+        <view class="order-info bg-white">
+            <view class="info-item flex">
+                <text class="label">订单编号</text>
+                <text style="color: #22ac38" class="flex-1 text-center content"
+                    @click="copyToClipboard(detail.orderId)">{{ detail.orderId }}</text>
             </view>
-        </view>
-        <view class="info-item">
-            <text class="label">发货地址</text>
-            <text class="content">{{ detail.sendAddress }}</text>
-        </view>
-        <view class="info-item">
-            <text class="label">收货仓库</text>
-            <text class="content">{{ detail.recipientAddress }}-{{ detail.recipientGodown }}-{{ detail.recipientName
-                }}</text>
-        </view>
-    </view>
-    <u-modal :show="showModal" title="编辑内部备注" :showCancelButton="true" @confirm="confirmRemark"
-        @cancel="handleCancel">
-        <view class="modal-content w100" @click="playGlobalSound">
-            <u-textarea v-model="internalRemark" placeholder="编辑内部备注" autoHeight
-                style="min-height: 100px;"></u-textarea>
-
-            <view class="mt-20 common-title">快速填入</view>
-            <view class="quick-fill mt-16">
-                <u-tag class="mr-10 mb-10" @click="fillRemark('少书给客服')" text="少书给客服"></u-tag>
-                <u-tag class="mr-10 mb-10" @click="fillRemark('多书给客服')" text="多书给客服"></u-tag>
-                <u-tag class="mr-10 mb-10" @click="fillRemark('子母件')" text="子母件"></u-tag>
-                <u-tag class="mr-10 mb-10" @click="fillRemark('书单不符给客服')" text="书单不符给客服"></u-tag>
-                <u-tag class="mr-10 mb-10" @click="fillRemark('需理赔给客服')" text="需理赔给客服"></u-tag>
+            <view class="info-item">
+                <text class="label">预估金额</text>
+                <text class="content">{{ detail.expectMoney }}</text>
+                <text class="label border-left">审核金额</text>
+                <text class="content">{{ detail.finalMoney }}</text>
+            </view>
+            <view class="info-item">
+                <text class="label">用户备注</text>
+                <text class="content">{{ detail.userRemark }}</text>
+            </view>
+            <view class="info-item" @click="handleRemark">
+                <text class="label">内部备注</text>
+                <text class="content">{{
+                    detail?.manageRemark
+                        ? detail?.manageRemark.length > 0
+                            ? detail?.manageRemark[0]?.remark
+                            : " "
+                    : " "
+                    }}</text>
+            </view>
+            <view class="info-item">
+                <text class="label">订单状态</text>
+                <text class="content" style="color: #c5493e">[{{ statusText }}]</text>
+            </view>
+            <view class="info-item">
+                <text class="label">快递</text>
+                <text class="content">{{ finalExpressText
+                    }}<text style="color: #409eef" @click="copyToClipboard(detail.waybillCode)">(单号:{{
+                        detail.waybillCode }})</text></text>
+            </view>
+            <view class="info-item">
+                <text class="label">发件人<text style="color: #e99d42">(所有单)</text></text>
+
+                <view class="content flex flex-a-c flex-j-c">
+                    <text class="content-text" @click="copyToClipboard(detail.sendMobile)">复制</text>
+                    <text class="content-text ml-10 mr-10">{{ maskedSendMobile }}</text>
+                    <u-icon v-if="detail.orderFrom == 1" name="weixin-circle-fill" size="18" color="#22ac38"
+                        @click="handleWeixin"></u-icon>
+                    <u-icon v-if="detail.orderFrom == 2" name="zhifubao-circle-fill" size="18" color="#999"
+                        @click="handleWeixin"></u-icon>
+                </view>
+            </view>
+            <view class="info-item">
+                <text class="label">发货地址</text>
+                <text class="content">{{ detail.sendAddress }}</text>
+            </view>
+            <view class="info-item">
+                <text class="label">收货仓库</text>
+                <text class="content">{{ detail.recipientAddress }}-{{ detail.recipientGodown }}-{{
+                    detail.recipientName
+                    }}</text>
             </view>
         </view>
-    </u-modal>
+
+        <u-modal :show="showModal" title="编辑内部备注" :showCancelButton="true" @confirm="confirmRemark"
+            @cancel="handleCancel">
+            <view class="modal-content w100" @click="playGlobalSound">
+                <u-textarea v-model="internalRemark" placeholder="编辑内部备注" autoHeight
+                    style="min-height: 100px"></u-textarea>
+
+                <view class="mt-20 common-title">快速填入</view>
+                <view class="quick-fill mt-16">
+                    <u-tag class="mr-10 mb-10" @click="fillRemark('少书给客服')" text="少书给客服"></u-tag>
+                    <u-tag class="mr-10 mb-10" @click="fillRemark('多书给客服')" text="多书给客服"></u-tag>
+                    <u-tag class="mr-10 mb-10" @click="fillRemark('子母件')" text="子母件"></u-tag>
+                    <u-tag class="mr-10 mb-10" @click="fillRemark('书单不符给客服')" text="书单不符给客服"></u-tag>
+                    <u-tag class="mr-10 mb-10" @click="fillRemark('需理赔给客服')" text="需理赔给客服"></u-tag>
+                </view>
+            </view>
+        </u-modal>
+
+        <u-action-sheet :show="showActionSheet" :show-cancel="true" :actions="actionSheetActions" title="发送短信"
+            @close="closeActionSheet" @select="selectAction">
+        </u-action-sheet>
+
+        <!-- 短信推送弹窗 -->
+        <SmsModal ref="smsModalRef" v-model="showSmsModal" @success="handleSmsSuccess" />
+    </view>
 </template>
 
 <script setup>
-import { defineProps, computed, ref, watch } from 'vue';
+import { defineProps, computed, ref, watch } from "vue";
+import SmsModal from "./SmsModal.vue";
 
 const props = defineProps({
     orderId: String,
@@ -77,37 +98,39 @@ const props = defineProps({
     // Add more props as needed
 });
 
-let finalExpressList = { '1': '顺丰快递', '2': '京东快递', '3': '德邦快递' }
+let finalExpressList = { 1: "顺丰快递", 2: "京东快递", 3: "德邦快递" };
 let finalExpressText = computed(() => {
-    return props.detail.finalExpress ? finalExpressList[props.detail.finalExpress] : ''
+    return props.detail.finalExpress
+        ? finalExpressList[props.detail.finalExpress]
+        : "";
 });
 
-function playGlobalSound(){
-    uni.$u.playClickSound()
+function playGlobalSound() {
+    uni.$u.playClickSound();
 }
 
 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: "已完成",
 };
 
 let statusText = computed(() => {
-    return statusEnum[props.detail.status] || '未知状态';
+    return statusEnum[props.detail.status] || "未知状态";
 });
 
 const maskedSendMobile = computed(() => {
     if (props.detail.sendMobile && props.detail.sendMobile.length === 11) {
-        return props.detail.sendMobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
+        return props.detail.sendMobile.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
     }
     return props.detail.sendMobile;
 });
@@ -117,18 +140,18 @@ function copyToClipboard(text) {
         data: text,
         success: function () {
             uni.showToast({
-                title: '复制成功',
-                icon: 'success'
+                title: "复制成功",
+                icon: "success",
             });
         },
         fail: function (err) {
-            console.error('Could not copy text: ', err);
-        }
+            console.error("Could not copy text: ", err);
+        },
     });
 }
 
 const showModal = ref(false);
-const internalRemark = ref('');
+const internalRemark = ref("");
 
 function fillRemark(text) {
     internalRemark.value = text;
@@ -138,33 +161,118 @@ const remarkInfo = ref({});
 function handleRemark() {
     showModal.value = true;
     remarkInfo.value = props.detail.manageRemark?.[0] || {};
-    internalRemark.value = remarkInfo.value.remark || '';
+    internalRemark.value = remarkInfo.value.remark || "";
 }
 
 //关闭弹窗
-function handleCancel(){
-    showModal.value = false
-    playGlobalSound()
+function handleCancel() {
+    showModal.value = false;
+    playGlobalSound();
 }
 
-const emit = defineEmits(['refresh']);
+const emit = defineEmits(["refresh"]);
 function confirmRemark() {
-    playGlobalSound()
+    playGlobalSound();
     // Logic to save the remark
-    uni.$u.http.post('/app/orderinfo/setManageRemark', {
-        orderId: props.detail.orderId,
-        remark: internalRemark.value,
-        id: remarkInfo.value.id
-    }).then(res => {
-        if (res.code == 200) {
-            uni.$u.toast('保存成功')
-            uni.$u.ttsModule.speak('保存成功')
-            showModal.value = false;
-            emit('refresh')
-        } else {
-            uni.$u.toast(res.msg)
-        }
-    })
+    uni.$u.http
+        .post("/app/orderinfo/setManageRemark", {
+            orderId: props.detail.orderId,
+            remark: internalRemark.value,
+            id: remarkInfo.value.id,
+        })
+        .then((res) => {
+            if (res.code == 200) {
+                uni.$u.toast("保存成功");
+                uni.$u.ttsModule.speak("保存成功");
+                showModal.value = false;
+                emit("refresh");
+            } else {
+                uni.$u.toast(res.msg);
+            }
+        });
+}
+
+// ActionSheet相关变量和方法
+const showActionSheet = ref(false);
+const actionSheetActions = ref([
+    {
+        name: "发送短信(手机发送)",
+        value: "sms",
+    },
+    {
+        name: "一键发送短信(服务器发送)",
+        value: "server_sms",
+    },
+    {
+        name: "QQ",
+        value: "qq",
+    },
+    {
+        name: "微信",
+        value: "wechat",
+    },
+    {
+        name: "取消",
+        value: "cancel",
+    },
+]);
+
+// 处理微信图标点击
+function handleWeixin() {
+    playGlobalSound();
+    showActionSheet.value = true;
+}
+
+// 关闭ActionSheet
+function closeActionSheet() {
+    showActionSheet.value = false;
+}
+
+// 选择ActionSheet选项
+function selectAction(item) {
+    playGlobalSound();
+    showActionSheet.value = false;
+
+    if (item.value === "server_sms") {
+        // 发送短信功能
+        handleSendSMS();
+    } else if (item.value == "cancel") {
+        closeActionSheet()
+    } else {
+        // 其他功能暂无开放
+        uni.showToast({
+            title: "此功能暂无开放",
+            icon: "none",
+        });
+    }
+}
+
+// 短信弹窗相关
+const showSmsModal = ref(false);
+const smsModalRef = ref();
+
+// 发送短信功能
+function handleSendSMS() {
+    playGlobalSound();
+
+    // 打开短信弹窗
+    if (smsModalRef.value && props.detail.orderId) {
+        smsModalRef.value.handleOpen(props.detail.orderId);
+    } else {
+        uni.showToast({
+            title: "订单信息异常",
+            icon: "none",
+        });
+    }
+}
+
+// 短信发送成功回调
+function handleSmsSuccess() {
+    uni.showToast({
+        title: "短信发送成功",
+        icon: "success",
+    });
+    uni.$u.ttsModule.speak("短信发送成功");
 }
 </script>
 
@@ -208,4 +316,4 @@ function confirmRemark() {
         }
     }
 }
-</style>
+</style>

+ 274 - 0
pages/index/detail/components/SmsModal.vue

@@ -0,0 +1,274 @@
+<template>
+    <u-modal 
+        :show="visible" 
+        title="推送短信"
+        :show-cancel-button="true"
+        :showCancelButton="true"
+        :show-confirm-button="true"
+        :showConfirmButton="true"
+        confirmText="确定"
+        cancelText="关闭"
+        @confirm="handleSubmit"
+        @cancel="handleCancel"
+        @close="handleCancel"
+        width="650rpx"
+    >
+        <view class="modal-content">
+            <u-form 
+                ref="formRef"
+                :model="form" 
+                :rules="rules"
+                labelWidth="120"
+                labelPosition="top"
+            >
+                <u-form-item label="短信类型" prop="type" required>
+                    <u-radio-group 
+                        v-model="form.type" 
+                        placement="column"
+                        @change="handleChangeType"
+                    >
+                        <u-radio 
+                            v-for="item in smsContentList"
+                            :key="item.type"
+                            :name="item.type"
+                            :label="item.typeName"
+                        ></u-radio>
+                    </u-radio-group>
+                </u-form-item>
+                
+                <u-form-item label="短信预览" prop="remark" required>
+                    <u-textarea 
+                        v-model="form.remark"
+                        placeholder="请输入短信预览"
+                        :disabled="true"
+                        :rows="4"
+                        count
+                    ></u-textarea>
+                </u-form-item>
+                
+                <u-form-item label="推送历史">
+                    <view class="sms-history">
+                        <view v-if="smsRecords.length === 0" class="no-data">
+                            <text>暂无推送记录</text>
+                        </view>
+                        <view v-else class="history-list">
+                            <view 
+                                v-for="(record, index) in smsRecords" 
+                                :key="record.id || index"
+                                class="history-item"
+                            >
+                                <view class="history-header">
+                                    <text class="sender">{{ record.createName }}</text>
+                                    <text class="time">{{ record.createTime }}</text>
+                                    <text 
+                                        class="status" 
+                                        :class="record.status == 1 ? 'success' : 'fail'"
+                                    >
+                                        {{ record.status == 1 ? '成功' : '失败' }}
+                                    </text>
+                                </view>
+                                <view class="history-content">
+                                    <text>{{ record.smsContent }}</text>
+                                </view>
+                            </view>
+                        </view>
+                    </view>
+                </u-form-item>
+            </u-form>
+        </view>
+    </u-modal>
+</template>
+
+<script setup>
+import { ref, reactive, nextTick, getCurrentInstance } from 'vue';
+
+const { proxy } = getCurrentInstance();
+const emit = defineEmits(['success']);
+
+/** 弹窗是否打开 */
+const visible = defineModel({ type: Boolean });
+
+/** 表单引用 */
+const formRef = ref();
+
+/** SMS记录数据 */
+const smsRecords = ref([]);
+
+const form = reactive({
+    orderId: null,
+    type: '',
+    remark: ''
+});
+
+/** 短信内容列表 */
+const smsContentList = ref([]);
+
+/** 短信类型改变 */
+const handleChangeType = (val) => {
+    const selectedItem = smsContentList.value.find(item => item.type === val);
+    if (selectedItem) {
+        form.remark = selectedItem.smsContent;
+    }
+};
+
+/** 表单验证规则 */
+const rules = reactive({
+    type: [
+        {
+            required: true,
+            message: '请选择短信类型',
+            trigger: 'change'
+        }
+    ],
+    remark: [
+        {
+            required: true,
+            message: '请输入短信预览',
+            trigger: 'blur'
+        }
+    ]
+});
+
+/** 关闭弹窗 */
+const handleCancel = () => {
+    visible.value = false;
+    resetForm();
+};
+
+/** 重置表单 */
+const resetForm = () => {
+    form.orderId = null;
+    form.type = '';
+    form.remark = '';
+    smsRecords.value = [];
+    smsContentList.value = [];
+    formRef.value?.resetFields();
+};
+
+/** 弹窗打开事件 */
+const handleOpen = (orderId) => {
+    resetForm();
+    if (orderId) {
+        console.log('打开短信弹窗,订单ID:', orderId);
+        visible.value = true;
+        getSmsLogInfo(orderId);
+    }
+};
+
+/** 获取短信记录信息 */
+const getSmsLogInfo = (orderId) => {
+    uni.$u.http.get(`/app/orderinfo/orderSmsLog/${orderId}`).then((res) => {
+        if (res.code === 200) {
+            let data = res.data || {};
+            form.orderId = data.orderId;
+            smsRecords.value = data.smsLogList || [];
+            smsContentList.value = data.smsContentList || [];
+        } else {
+            uni.$u.toast(res.msg || '获取短信记录失败');
+        }
+    }).catch((err) => {
+        console.error('获取短信记录失败:', err);
+        uni.$u.toast('获取短信记录失败');
+    });
+};
+
+/** 提交表单 */
+const handleSubmit = () => {
+    formRef.value?.validate().then(valid => {
+        if (!valid) return;
+        
+        uni.$u.http.post('/app/orderinfo/orderSmsLogSend', {
+            orderId: form.orderId,
+            type: form.type
+        }).then((res) => {
+            if (res.code == 200) {
+                uni.$u.toast('短信发送成功');
+                emit('success');
+                handleCancel();
+            } else {
+                uni.$u.toast(res.msg || '短信发送失败');
+            }
+        }).catch((err) => {
+            console.error('短信发送失败:', err);
+            uni.$u.toast('短信发送失败');
+        });
+    }).catch(err => {
+        console.log('表单验证失败:', err);
+    });
+};
+
+defineExpose({
+    handleOpen
+});
+</script>
+
+<style lang="scss" scoped>
+.modal-content{
+    max-height: 72vh;
+    overflow: auto;
+}
+.sms-history {
+    .no-data {
+        text-align: center;
+        color: #999;
+        padding: 40rpx 0;
+    }
+    
+    .history-list {
+        .history-item {
+            margin-bottom: 20rpx;
+            padding: 20rpx;
+            background-color: #f8f9fa;
+            border-radius: 8rpx;
+            border-left: 4rpx solid #409eff;
+            
+            .history-header {
+                display: flex;
+                justify-content: space-between;
+                align-items: center;
+                margin-bottom: 10rpx;
+                
+                .sender {
+                    font-size: 28rpx;
+                    font-weight: bold;
+                    color: #333;
+                }
+                
+                .time {
+                    font-size: 24rpx;
+                    color: #666;
+                }
+                
+                .status {
+                    font-size: 24rpx;
+                    padding: 4rpx 8rpx;
+                    border-radius: 4rpx;
+                    
+                    &.success {
+                        background-color: #67c23a;
+                        color: white;
+                    }
+                    
+                    &.fail {
+                        background-color: #f56c6c;
+                        color: white;
+                    }
+                }
+            }
+            
+            .history-content {
+                font-size: 26rpx;
+                line-height: 1.5;
+                color: #666;
+            }
+        }
+    }
+}
+
+/* 自定义单选框样式 */
+:deep(.u-radio-group) {
+    .u-radio {
+        margin-bottom: 20rpx;
+    }
+}
+</style> 

+ 10 - 4
pages/index/detail/index.vue

@@ -76,7 +76,7 @@
 
 <script setup>
 import { ref } from "vue";
-import { onLoad, onShow } from "@dcloudio/uni-app";
+import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
 import AuditorSelector from "./components/AuditorSelector.vue";
 import OrderInfo from "./components/OrderInfo.vue";
 import UserInfoCard from "./components/UserInfoCard.vue";
@@ -295,6 +295,9 @@ function handleScan(isbn) {
         return;
     }
 
+    //取 isbn 的后四位字符串进行播报
+    let isbnStr = `${isbn.slice(-4)}`;
+
     let isbns = orderDetail.value.detailVoList.map((item) => item.isbn);
 
     if (isbns.includes(isbn)) {
@@ -302,12 +305,12 @@ function handleScan(isbn) {
 
         //扫描到套装书
         if (book.suit == 1) {
-            let text = `${isbn}请注意套装书是否齐全`;
+            let text = `${isbnStr}请注意套装书是否齐全`;
             uni.$u.ttsModule.speak(text);
         }
         //扫描到需要取出的书
         if (book.bookWarn == 1) {
-            let text = `请注意${isbn}需要取出`;
+            let text = `请注意${isbnStr}需要取出`;
             uni.$u.ttsModule.speak(text);
         }
 
@@ -317,7 +320,7 @@ function handleScan(isbn) {
         uni.setStorageSync("auditBook", book);
         uni.setStorageSync("orderDetail", orderDetail.value);
     } else {
-        let text = `此订单中不存在${isbn}这本书 `;
+        let text = `此订单中不存在${isbnStr}这本书 `;
         uni.$u.ttsModule.speak(text);
     }
 }
@@ -357,6 +360,9 @@ onShow(() => {
     uni.$u.updateActivePageOnShow();
     getOrderDetail();
 });
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style>

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

@@ -18,7 +18,7 @@
 
 <script setup>
 import { ref } from 'vue';
-import { onLoad, onShow } from '@dcloudio/uni-app'
+import { onLoad, onShow, onUnload } from '@dcloudio/uni-app'
 
 const customStyle = {
     height: '100rpx',
@@ -89,4 +89,7 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>

+ 5 - 1
pages/index/entry/commodity-scan.vue

@@ -22,7 +22,8 @@
 	} from 'vue';
 	import {
 		onLoad,
-		onShow
+		onShow,
+		onUnload
 	} from '@dcloudio/uni-app'
 
 	const placeholderStyle = "font-size:32rpx"
@@ -79,6 +80,9 @@
 	onShow(() => {
 		uni.$u.updateActivePageOnShow();
 	})
+	onUnload(() => {
+		uni.$u.cleanupOnPageUnload();
+	});
 	// #endif
 </script>
 

+ 4 - 1
pages/index/entry/scan-book.vue

@@ -105,7 +105,7 @@
 
 <script setup>
 import { ref } from "vue";
-import { onLoad, onShow } from "@dcloudio/uni-app";
+import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
 
 const searchValue = ref("");
 const scannedISBN = ref("");
@@ -160,6 +160,9 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 4 - 1
pages/index/express/quick-check.vue

@@ -76,7 +76,7 @@
 import {
     ref
 } from 'vue';
-import { onLoad, onShow } from "@dcloudio/uni-app"
+import { onLoad, onShow, onUnload } from "@dcloudio/uni-app"
 
 const selectedBatchId = ref('');
 const showBatchSelector = ref(false);
@@ -170,6 +170,9 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 3 - 0
pages/index/express/quick-unpack.vue

@@ -112,6 +112,9 @@ onUnload(()=>{
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 4 - 1
pages/index/express/route-exception.vue

@@ -28,7 +28,7 @@
 import {
     ref,
 } from 'vue';
-import { onLoad, onShow } from '@dcloudio/uni-app';
+import { onLoad, onShow, onUnload } from '@dcloudio/uni-app';
 import ExceptionItem from './components/ExceptionItem.vue';
 import PageScroll from '@/components/pageScroll/index.vue';
 
@@ -83,6 +83,9 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

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

@@ -30,7 +30,8 @@
 	} from 'vue';
 	import {
 		onLoad,
-		onShow
+		onShow,
+		onUnload
 	} from '@dcloudio/uni-app'
 	import WarehouseSelector from './components/WarehouseSelector.vue';
 
@@ -103,6 +104,9 @@
 	onShow(() => {
 		uni.$u.updateActivePageOnShow()
 	})
+	onUnload(() => {
+		uni.$u.cleanupOnPageUnload();
+	});
 </script>
 
 <style lang="scss" scoped>

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

@@ -30,7 +30,8 @@ import {
 } from 'vue';
 import {
     onLoad,
-    onShow
+    onShow,
+    onUnload
 } from '@dcloudio/uni-app'
 import WarehouseSelector from './components/WarehouseSelector.vue';
 
@@ -103,6 +104,9 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

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

@@ -37,7 +37,8 @@ import {
 } from 'vue';
 import {
     onLoad,
-    onShow
+    onShow,
+    onUnload
 } from '@dcloudio/uni-app'
 import cyUpload from '@/components/cy-upload/index.vue'
 
@@ -107,6 +108,9 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style>

+ 1 - 1
pages/index/index.vue

@@ -275,7 +275,7 @@ const entryOperations = ref([
         type: "warning",
     },
     {
-        name: "商品档案扫码",
+        name: "商品档案推送",
         path: "/pages/index/entry/commodity-scan",
         type: "primary",
         span: 24,

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

@@ -19,7 +19,7 @@
 
 <script setup>
 import { ref, computed } from 'vue';
-import { onLoad, onShow } from '@dcloudio/uni-app';
+import { onLoad, onShow, onUnload } from '@dcloudio/uni-app';
 import BookItem from '../components/BookItemOrder.vue';
 
 const bookList = ref([]);
@@ -88,9 +88,12 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
 .container {
     display: flex;
     flex-direction: column;

+ 4 - 5
pages/index/wms/bad-in.vue

@@ -65,7 +65,7 @@ import {
     onMounted,
     onUnmounted,
 } from 'vue';
-import { onShow } from '@dcloudio/uni-app';
+import { onShow, onUnload } from '@dcloudio/uni-app';
 import BadItem from './components/BadItem.vue';
 import VolumeTTS from '@/utils/VolumeTTS.js'
 import RemarkDialog from './components/RemarkDialog.vue'
@@ -261,12 +261,11 @@ onMounted(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
-
-// 记得在页面卸载时移除事件监听
-onUnmounted(() => {
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
     uni.$off('updateLocation')
     uni.$off('updateWarehouse')
-})
+});
 
 // 打开备注弹窗
 const openRemarkDialog = (index, remark = '') => {

+ 5 - 1
pages/index/wms/bad-out-order.vue

@@ -63,7 +63,7 @@
 import { ref, onMounted } from "vue";
 import BadOutCard from "./components/BadOutCard.vue";
 import RemarkDialog from "./components/RemarkDialog.vue";
-import { onLoad, onShow } from "@dcloudio/uni-app";
+import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
 
 const searchText = ref("");
 const searchType = ref("1");
@@ -183,6 +183,10 @@ onShow(() => {
     uni.$u.updateActivePageOnShow();
 });
 
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
+
 // 确认出库
 const onConfirm = () => {
     uni.showModal({

+ 4 - 1
pages/index/wms/bad-out.vue

@@ -30,7 +30,7 @@
 
 <script setup>
 import { ref, computed, onMounted } from "vue";
-import { onLoad, onShow } from "@dcloudio/uni-app";
+import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
 // 搜索文本
 const searchText = ref("");
 const searchType = ref("1");
@@ -86,4 +86,7 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>

+ 5 - 1
pages/index/wms/location-order-list.vue

@@ -30,7 +30,8 @@ import {
 } from 'vue'
 import {
     onLoad,
-    onShow
+    onShow,
+    onUnload
 } from '@dcloudio/uni-app'
 import LocationOrderItem from './components/LocationOrderItem.vue'
 
@@ -110,6 +111,9 @@ onLoad((options) => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 5 - 1
pages/index/wms/location-order.vue

@@ -16,7 +16,8 @@ import {
 } from 'vue'
 import {
     onLoad,
-    onShow
+    onShow,
+    onUnload
 } from '@dcloudio/uni-app'
 
 const positionCode = ref('')
@@ -53,6 +54,9 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 5 - 1
pages/index/wms/location-select.vue

@@ -27,7 +27,8 @@
 	} from 'vue'
 	import {
 		onLoad,
-		onShow
+		onShow,
+		onUnload
 	} from '@dcloudio/uni-app'
 	// 搜索文本
 	const searchText = ref('')
@@ -123,6 +124,9 @@
 	onShow(() => {
 		uni.$u.updateActivePageOnShow()
 	})
+	onUnload(() => {
+		uni.$u.cleanupOnPageUnload();
+	});
 </script>
 
 <style scoped>

+ 4 - 1
pages/index/wms/order-query-list.vue

@@ -42,7 +42,7 @@ import {
     reactive,
     ref
 } from 'vue'
-import { onLoad, onShow } from '@dcloudio/uni-app'
+import { onLoad, onShow, onUnload } from '@dcloudio/uni-app'
 import BookInfo from '../detail/components/BookInfo.vue'
 
 const list1 = reactive([{
@@ -128,6 +128,9 @@ onLoad((options) => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 4 - 1
pages/index/wms/order-query.vue

@@ -17,7 +17,7 @@ import {
     reactive,
     ref
 } from 'vue'
-import { onLoad, onShow } from '@dcloudio/uni-app'
+import { onLoad, onShow, onUnload } from '@dcloudio/uni-app'
 
 const query = reactive({
     searchType: 2,
@@ -56,6 +56,9 @@ onLoad(() => {
 onShow(() => {
     uni.$u.updateActivePageOnShow()
 })
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
 </script>
 
 <style lang="scss" scoped>

+ 7 - 6
pages/index/wms/speedy-check.vue

@@ -321,6 +321,13 @@ const open = () => {
     showLocationPopup.value = true;
 };
 
+onShow(() => {
+    uni.$u.updateActivePageOnShow()
+})
+onUnload(() => {
+    uni.$u.cleanupOnPageUnload();
+});
+
 onLoad(() => {
     getUserDefaultWarehouse();
 
@@ -336,13 +343,7 @@ onLoad(() => {
     });
     // #endif
 });
-onShow(() => {
-    uni.$u.updateActivePageOnShow()
-})
 
-onUnload(() => {
-    uni.$off("selectedProducts");
-});
 </script>
 
 <style lang="scss" scoped>

+ 1 - 0
pages/index/wms/task-detail.vue

@@ -102,6 +102,7 @@ const taskCode = ref("");
 
 onUnload(() => {
     ttsModule.value.stop();
+    uni.$u.cleanupOnPageUnload();
 });
 
 // 点击全局音效

+ 1 - 1
pages/my/page/warehouse.vue

@@ -34,7 +34,7 @@
 	const warehouseList = ref([])
 	// 获取仓库列表
 	const getWarehouseList = () => {
-		uni.$u.http.post('/app/appUser/searchGodown?name=').then(res => {
+		uni.$u.http.post("/app/appUser/searchGodown?name=").then(res => {
 			if (res.code == 200) {
 				warehouseList.value = res.data.filter(v => v.useStatus == 1).map(v => ({
 					text: v.godownName,

BIN
unpackage/cache/apk/__UNI__65C1C73_cm.apk


+ 1 - 0
unpackage/cache/apk/apkurl

@@ -0,0 +1 @@
+https://app.liuyingyong.cn/build/download/9b4ce1f0-3871-11f0-a8bf-d5dfad5d65eb

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/apk/cmManifestCache.json


+ 4 - 0
unpackage/cache/certdata

@@ -0,0 +1,4 @@
+andrCertfile=/Applications/HBuilderX.app/Contents/HBuilderX/plugins/app-safe-pack/Test.keystore
+andrCertAlias=android
+andrCertPass=ep/Tdjka4Y7WYqDB6/S7dw==
+storePassword=ep/Tdjka4Y7WYqDB6/S7dw==

+ 4 - 0
unpackage/cache/cloudcertificate/certini

@@ -0,0 +1,4 @@
+[General]
+andrCertAlias=__UNI__65C1C73
+andrCertPass="OzpHCX5LVu1He+s6d2ygHw=="
+andrCertfile=package.keystore

BIN
unpackage/cache/cloudcertificate/package.keystore


+ 24 - 23
unpackage/cache/wgt/__UNI__65C1C73/__uniappview.html

@@ -1,23 +1,24 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="UTF-8" />
-    <title>View</title>
-    <link rel="stylesheet" href="app.css" />
-    <script>var __uniConfig = {"globalStyle":{},"darkmode":false}</script>
-    <script>
-      var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
-        CSS.supports('top: constant(a)'))
-      document.write(
-        '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
-        (coverSupport ? ', viewport-fit=cover' : '') + '" />')
-    </script>
-  </head>
-  <body>
-    <div id="app"></div>
-    <script src="uni-app-view.umd.js"></script>
-    <script src="app-wxs.js"></script>
-    <script src="app-renderjs.js"></script>
-    
-  </body>
-</html>
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <title>View</title>
+    <link rel="icon" href="data:,">
+    <link rel="stylesheet" href="app.css" />
+    <script>var __uniConfig = {"globalStyle":{},"darkmode":false}</script>
+    <script>
+      var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
+        CSS.supports('top: constant(a)'))
+      document.write(
+        '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+        (coverSupport ? ', viewport-fit=cover' : '') + '" />')
+    </script>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script src="uni-app-view.umd.js"></script>
+    <script src="app-wxs.js"></script>
+    <script src="app-renderjs.js"></script>
+    
+  </body>
+</html>

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
unpackage/cache/wgt/__UNI__65C1C73/app-config-service.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/app-service.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/app.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/manifest.json


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/book/index.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/audit/confirm-receipt.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/audit/express-order.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/audit/isbn-order.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/audit/scan-order.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/audit/sender.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/detail/batch-audit.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/detail/book-audit.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/detail/index.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/detail/user-orders.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/entry/book-weight.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/entry/commodity-scan.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/entry/scan-book.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/logistics-detail.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/quick-check.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/quick-unpack.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/route-exception.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/transfer-sign.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/warehouse-sign.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/express/weight-modify.css


+ 1 - 1
unpackage/cache/wgt/__UNI__65C1C73/pages/index/index.css

@@ -1 +1 @@
-.operation-container[data-v-a316ef9c]{padding:.625rem;box-sizing:border-box}.section[data-v-a316ef9c]{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-a316ef9c]{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-a316ef9c]{display:flex;flex-wrap:wrap;padding:.3125rem}.section .grid-container .grid-item[data-v-a316ef9c]{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-a316ef9c]{width:calc(100% - .625rem);margin-right:.625rem}.section .grid-container .grid-item.primary[data-v-a316ef9c]{background:linear-gradient(135deg,#4cd964,#3ac555)}.section .grid-container .grid-item.primary[data-v-a316ef9c]:active{background:linear-gradient(135deg,#3ac555,#2fb548)}.section .grid-container .grid-item.warning[data-v-a316ef9c]{background:linear-gradient(135deg,#ff9500,#ff8000)}.section .grid-container .grid-item.warning[data-v-a316ef9c]:active{background:linear-gradient(135deg,#ff8000,#e67300)}.section .grid-container .grid-item[data-v-a316ef9c]:active{transform:scale(.98)}
+.operation-container[data-v-5ed4a2b1]{padding:.625rem;box-sizing:border-box}.section[data-v-5ed4a2b1]{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-5ed4a2b1]{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-5ed4a2b1]{display:flex;flex-wrap:wrap;padding:.3125rem}.section .grid-container .grid-item[data-v-5ed4a2b1]{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-5ed4a2b1]{width:calc(100% - .625rem);margin-right:.625rem}.section .grid-container .grid-item.primary[data-v-5ed4a2b1]{background:linear-gradient(135deg,#4cd964,#3ac555)}.section .grid-container .grid-item.primary[data-v-5ed4a2b1]:active{background:linear-gradient(135deg,#3ac555,#2fb548)}.section .grid-container .grid-item.warning[data-v-5ed4a2b1]{background:linear-gradient(135deg,#ff9500,#ff8000)}.section .grid-container .grid-item.warning[data-v-5ed4a2b1]:active{background:linear-gradient(135deg,#ff8000,#e67300)}.section .grid-container .grid-item[data-v-5ed4a2b1]:active{transform:scale(.98)}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/offline/check-order.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/offline/check-record.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/statistic/after-sale.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/statistic/audit.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/statistic/package.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/bad-in.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/bad-off.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/bad-out-order.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/bad-out.css


+ 1 - 1
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/good-in.css

@@ -1 +1 @@
-.container[data-v-feb20296]{min-height:100vh;background-color:#f5f5f5}.developing[data-v-feb20296]{display:flex;justify-content:center;align-items:center;height:200px;background:#fff}.developing uni-text[data-v-feb20296]{font-size:16px;color:#999}
+.container[data-v-63a52bd4]{min-height:100vh;background-color:#f5f5f5}.developing[data-v-63a52bd4]{display:flex;justify-content:center;align-items:center;height:200px;background:#fff}.developing uni-text[data-v-63a52bd4]{font-size:16px;color:#999}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/location-order-list.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/location-order.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/location-select.css


+ 1 - 1
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/medium-in.css

@@ -1 +1 @@
-.container[data-v-c51d8b68]{min-height:100vh;background-color:#f5f5f5}.developing[data-v-c51d8b68]{display:flex;justify-content:center;align-items:center;height:200px;background:#fff}.developing uni-text[data-v-c51d8b68]{font-size:16px;color:#999}
+.container[data-v-cf0e6dcb]{min-height:100vh;background-color:#f5f5f5}.developing[data-v-cf0e6dcb]{display:flex;justify-content:center;align-items:center;height:200px;background:#fff}.developing uni-text[data-v-cf0e6dcb]{font-size:16px;color:#999}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/order-query-list.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/order-query.css


+ 1 - 1
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/secondary-in.css

@@ -1 +1 @@
-.container[data-v-a34069c4]{min-height:100vh;background-color:#f5f5f5}.developing[data-v-a34069c4]{display:flex;justify-content:center;align-items:center;height:200px;background:#fff}.developing uni-text[data-v-a34069c4]{font-size:16px;color:#999}
+.container[data-v-9af98d8f]{min-height:100vh;background-color:#f5f5f5}.developing[data-v-9af98d8f]{display:flex;justify-content:center;align-items:center;height:200px;background:#fff}.developing uni-text[data-v-9af98d8f]{font-size:16px;color:#999}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/speedy-check-add.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/speedy-check.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/task-detail.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/index/wms/warehouse-select.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/login/login.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/my/my.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/audit-unfinished.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/book-display.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/password.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/school.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/user-info.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/version.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/volume.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
unpackage/cache/wgt/__UNI__65C1C73/pages/my/page/warehouse.css


Vissa filer visades inte eftersom för många filer har ändrats