diff --git a/api/product.js b/api/product.js index 4b3c730..07769d9 100644 --- a/api/product.js +++ b/api/product.js @@ -81,11 +81,6 @@ const request8081 = config => { dataType: 'json' }).then(response => { let [error, res] = response - console.log('=== 8081端口响应详情 ===') - // console.log('响应状态码:', res.statusCode) - console.log('响应头:', res.header) - console.log('响应数据:', res.data) - console.log('响应数据类型:', typeof res.data) if (error) { toast('后端接口连接异常') @@ -93,6 +88,12 @@ const request8081 = config => { return } + console.log('=== 8081端口响应详情 ===') + // console.log('响应状态码:', res.statusCode) + console.log('响应头:', res.header) + console.log('响应数据:', res.data) + console.log('响应数据类型:', typeof res.data) + const code = res.data.code || 200 const msg = res.data.msg || '请求失败' diff --git a/manifest.json b/manifest.json index a542f59..b011686 100644 --- a/manifest.json +++ b/manifest.json @@ -21,21 +21,19 @@ "distribute" : { "android" : { "permissions" : [ - "", - "", - "", - "", - "", - "", - "", + "", "", - "", - "", - "", - "", "", "", - "" + "", + "", + "", + "", + "", + "", + "", + "", + "" ] }, "ios" : { @@ -50,7 +48,7 @@ }, "quickapp" : {}, "mp-weixin" : { - "appid" : "wxccd7e2a0911b3397", + "appid" : "wxe94413d023e0e7df", "setting" : { "urlCheck" : false, "es6" : false, @@ -60,7 +58,13 @@ "optimization" : { "subPackages" : true }, - "usingComponents" : true + "usingComponents" : true, + "networkTimeout": { + "request": 10000, + "connectSocket": 10000, + "uploadFile": 10000, + "downloadFile": 10000 + } }, "vueVersion" : "2", "h5" : { diff --git a/pages/enter/enter.vue b/pages/enter/enter.vue index cfe3376..b69526c 100644 --- a/pages/enter/enter.vue +++ b/pages/enter/enter.vue @@ -19,20 +19,16 @@ - + - + 对准商品条码,自动识别 - + - - - 正在扫描... - @@ -42,14 +38,10 @@ {{ scanPaused ? '继续扫码' : '暂停扫码' }} - - - 全屏扫码 - - + 扫码功能需要在App中使用 @@ -58,12 +50,42 @@ - - - + + + + + + + {{ item.name }} + {{ item.barcode }} + ¥{{ item.price }} + + + + 移除商品 + + + + 进货数量 + + + + 进货价 + + + + + + + + 暂未录入商品 请在上方选择商品录入方式 - + + + + + @@ -75,375 +97,232 @@ export default { flashOn: false, scanPaused: false, isScanning: false, - barcodeInstance: null + barcodeInstance: null, + goodsList: [ + { + name: '怡宝饮用纯净水350ml', + barcode: '6901285991240', + price: 1, + quantity: 1, + image: '/static/yibao.png' + } + ] }; }, - // ✅ 修复核心:用mounted初始化,页面DOM渲染完成后再创建扫码控件 mounted() { // #ifdef APP-PLUS - console.log('=== 扫码页面 mounted ==='); - this.initScan(); + console.log('页面 mounted 触发'); + // 关键修复:等待 Webview 完全渲染后再初始化 + this.$nextTick(() => { + setTimeout(() => { + this.initScan(); + }, 300); // 延迟 300ms 确保原生层准备就绪 + }); // #endif }, onShow() { // #ifdef APP-PLUS - console.log('=== 扫码页面 onShow ==='); - // 每次页面显示时都检查权限并初始化(处理从设置返回的情况) - this.initScan(); + // 从后台返回或从设置返回时,重新检查 + if (!this.barcodeInstance) { + this.$nextTick(() => { + setTimeout(() => { + this.requestCameraAuth().then(() => { + this.initBarcodeScan(); + }).catch(err => { + console.log('权限不足,无法重新初始化'); + }); + }, 300); + }); + } // #endif }, onUnload() { - this.destroyScan(); // 统一销毁扫码控件 + this.destroyScan(); }, methods: { goBack() { - this.destroyScan(); // 返回时销毁 + this.destroyScan(); uni.navigateBack({ delta: 1 }); }, - + goImport() { + uni.navigateTo({ url: '/pages/Import/Import' }); + }, + goNoCode() { + uni.navigateTo({ url: '/pages/NoCode/NoCode' }); + }, goRecord() { uni.showToast({ title: '记录功能开发中', icon: 'none' }); }, - - goImport() { - uni.navigateTo({ - url: '/pages/Import /Import ' - }); - }, - // ✅ 新增:统一的初始化方法(处理权限和扫码初始化) initScan() { - console.log('开始初始化扫码流程...'); - console.log('当前平台:', uni.getSystemInfoSync().platform); - console.log('plus对象是否存在:', !!plus); - console.log('plus.barcode是否存在:', !!(plus && plus.barcode)); - - // 先申请相机权限,再初始化扫码 this.requestCameraAuth().then(() => { - console.log('相机权限已获取,开始初始化扫码'); this.initBarcodeScan(); }).catch(err => { - console.error('相机权限获取失败:', err); - - // 显示友好的权限提示 + console.error('权限获取失败:', err); uni.showModal({ title: '权限提示', - content: '需要相机权限才能使用扫码功能\n\n请点击"去设置"开启相机权限', + content: '请前往设置开启相机权限', confirmText: '去设置', - cancelText: '取消', success: (res) => { if (res.confirm) { - // 跳转到系统设置页面 - if (uni.getSystemInfoSync().platform === 'android') { - const Intent = plus.android.importClass('android.content.Intent'); - const Settings = plus.android.importClass('android.provider.Settings'); - const Uri = plus.android.importClass('android.net.Uri'); - - const intent = new Intent(); - intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - const uri = Uri.fromParts('package', plus.android.runtimeActivity.getPackageName(), null); - intent.setData(uri); - - plus.android.runtimeMainActivity().startActivity(intent); - } else { - // iOS 跳转到设置 - plus.runtime.openURL('app-settings:'); - } - } else { - // 用户取消,返回上一页 - uni.navigateBack({ delta: 1 }); + this.openAppSettings(); } } }); }); }, - // ✅ 新增:统一销毁扫码控件,防止内存泄漏 + requestCameraAuth() { + return new Promise((resolve, reject) => { + // ... 这里保持原来的权限申请代码不变 ... + // (如果不确定可以保留之前修复的代码) + const platform = uni.getSystemInfoSync().platform; + if (platform === 'android') { + const main = plus.android.runtimeMainActivity(); + const Permission = plus.android.importClass('android.Manifest.permission'); + const PackageManager = plus.android.importClass('android.content.pm.PackageManager'); + if (main.checkSelfPermission(Permission.CAMERA) === PackageManager.PERMISSION_GRANTED) { + resolve(); + } else { + plus.android.requestPermissions(['android.permission.CAMERA'], (res) => { + res[0].granted ? resolve() : reject('用户拒绝'); + }, reject); + } + } else { + resolve(); + } + }); + }, + + openAppSettings() { + // ... 这里保持原来的跳转设置代码不变 ... + try { + plus.android.importClass('android.content.Intent'); + plus.android.importClass('android.provider.Settings'); + plus.android.importClass('android.net.Uri'); + const mainActivity = plus.android.runtimeMainActivity(); + const intent = new android.content.Intent(); + intent.setAction(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + const uri = android.net.Uri.fromParts('package', mainActivity.getPackageName(), null); + intent.setData(uri); + intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK); + mainActivity.startActivity(intent); + } catch (e) { + uni.showToast({ title: '跳转失败,请手动开启', icon: 'none' }); + } + }, + + initBarcodeScan() { + if (!plus || !plus.barcode) return; + + this.destroyScan(); + this.isScanning = true; + + const sysInfo = uni.getSystemInfoSync(); + const statusBarHeight = sysInfo.statusBarHeight || 0; + const navBarHeight = 44; + const totalNavBarHeight = statusBarHeight + navBarHeight; + + // 调试:打印高度计算结果 + console.log('高度计算:', { statusBarHeight, navBarHeight, totalNavBarHeight }); + + // 调整位置:确保扫码框在搜索栏下方 + const scanTop = totalNavBarHeight + 80; + const scanWidth = sysInfo.windowWidth - 30; + const scanHeight = 250; // 固定高度测试,避免宽高比计算错误导致高度为0 + + // 创建控件 + const barcode = plus.barcode.create('barcode', + [plus.barcode.CODE_128, plus.barcode.EAN_13, plus.barcode.EAN_8], + { + top: scanTop, + left: 15, + width: scanWidth, + height: scanHeight, + scanbarColor: '#e60012', + frameColor: '#e60012', + background: '#000', + zIndex: 9999 // 强制置顶 + } + ); + + barcode.onmarked = (type, result) => { + if (result) { + console.log('扫码结果:', result); + this.addGoodsByBarcode(result); + } + }; + + // 关键:获取当前 Webview 并挂载 + const currentWebview = this.$scope.$getAppWebview(); + if (currentWebview) { + currentWebview.append(barcode); + console.log('扫码控件已挂载到 Webview'); + } else { + console.error('获取 Webview 失败,无法挂载'); + } + + barcode.start(); + this.barcodeInstance = barcode; + }, + destroyScan() { if (this.barcodeInstance) { this.barcodeInstance.close(); this.barcodeInstance = null; } this.isScanning = false; - this.scanPaused = false; - this.flashOn = false; }, - // ✅ 新增:动态申请相机权限(支持 Android 和 iOS) - requestCameraAuth() { - return new Promise((resolve, reject) => { - try { - const platform = uni.getSystemInfoSync().platform; - console.log('当前平台:', platform); - - if (platform === 'android') { - // Android 平台权限申请 - console.log('Android 平台,开始申请相机权限...'); - - // 先检查是否已有权限 - const main = plus.android.runtimeMainActivity(); - const Permission = plus.android.importClass('android.Manifest.permission'); - const PackageManager = plus.android.importClass('android.content.pm.PackageManager'); - - const permission = Permission.CAMERA; - const result = main.checkSelfPermission(permission); - - console.log('Android 权限检查结果:', result); - - if (result === PackageManager.PERMISSION_GRANTED) { - console.log('Android 已有相机权限'); - resolve(); - } else { - console.log('Android 需要申请相机权限'); - plus.android.requestPermissions( - ['android.permission.CAMERA'], - (res) => { - console.log('Android 权限请求回调:', res); - if (res && res.length > 0) { - const authResult = res[0].granted; - console.log('Android 相机权限授予结果:', authResult); - if (authResult) { - resolve(); - } else { - reject('用户拒绝了相机权限'); - } - } else { - reject('权限请求返回异常'); - } - }, - (err) => { - console.error('Android 权限请求失败:', err); - reject(err); - } - ); - } - } else if (platform === 'ios') { - // iOS 平台权限申请 - console.log('iOS 平台,相机权限在使用时自动申请'); - - // iOS 的相机权限通常在第一次使用相机时自动申请 - // 我们可以直接尝试初始化扫码,如果权限被拒绝会触发系统弹窗 - resolve(); - } else { - console.log('非移动端平台,跳过权限申请'); - resolve(); - } - } catch (error) { - console.error('权限申请异常:', error); - reject(error); - } - }); - }, - - // ✅ 修复所有参数错误的扫码初始化核心方法 - initBarcodeScan() { - if (!plus) { - console.log('plus 对象不存在,无法初始化扫码'); - return; - } - - // 如果已有扫码实例,先销毁再重新创建 - if (this.barcodeInstance) { - console.log('已存在扫码实例,先销毁再重新创建'); - this.destroyScan(); - } - - console.log('开始初始化扫码控件'); - this.isScanning = true; - this.scanPaused = false; - - // 获取屏幕宽高和系统信息,适配所有机型【无单位纯数字,核心修复】 - const sysInfo = uni.getSystemInfoSync(); - const statusBarHeight = sysInfo.statusBarHeight || 0; - const navBarHeight = 44; - const totalNavBarHeight = statusBarHeight + navBarHeight; - - const scanWidth = sysInfo.windowWidth - 30; // 左右各留15px边距 - const scanHeight = sysInfo.windowWidth * 0.7; // 宽高比适配,扫码框更美观 - const scanTop = totalNavBarHeight + 80; // 动态计算顶部距离(导航栏+操作栏+间距) - - console.log('系统信息:', { - statusBarHeight, - navBarHeight, - totalNavBarHeight, - scanTop, - scanWidth, - scanHeight - }); - - // 创建扫码控件 【修复:所有尺寸参数为纯数字,无px】 - const barcode = plus.barcode.create('barcode', - [plus.barcode.CODE_128, plus.barcode.EAN_13, plus.barcode.EAN_8, plus.barcode.QR], // 增加常用码制,识别更广 - { - top: scanTop, - left: 15, - width: scanWidth, - height: scanHeight, - scanbarColor: '#e60012', // 扫码线颜色 - background: '#000', - frameColor: '#e60012', // 扫码框颜色 - scanbarRate: 2, // 扫码线速度 - scanbarStyle: 'style-radar', // 扫码线样式 - conserve: true, // 保持扫码状态 - filename: '_doc/barcode/' // 保存路径 - } - ); - - console.log('扫码控件创建成功'); - - // 扫码成功回调 - barcode.onmarked = (type, result) => { - if (!result) return; // 过滤空结果 - console.log('识别成功:', result); - this.isScanning = false; - uni.showModal({ - title: '扫码成功', - content: `获取到的编码号:${result}`, - showCancel: false, - success: () => { - // ✅ 修复:扫码成功后完整重置状态+继续扫码 - this.isScanning = true; - this.resumeScan(); - } - }); - }; - - // 扫码错误回调 - barcode.onerror = (error) => { - console.error('扫码错误:', error); - uni.showToast({ title: '扫码异常,请重试', icon: 'none' }); - }; - - // 挂载到当前页面 - const currentWebview = plus.webview.currentWebview(); - console.log('当前webview:', currentWebview); - console.log('扫码控件配置:', { - top: scanTop, - left: 15, - width: scanWidth, - height: scanHeight - }); - - currentWebview.append(barcode); - console.log('✅ 扫码控件已成功挂载到webview'); - - // 启动扫码并添加回调处理 - barcode.start((result) => { - console.log('扫码启动回调:', result); - if (result.code === 0) { - console.log('✅ 扫码已成功启动,相机画面应该显示'); - this.barcodeInstance = barcode; - - // 延迟检查扫码控件状态 - setTimeout(() => { - console.log('扫码控件状态检查:', { - exists: !!this.barcodeInstance, - isScanning: this.isScanning - }); - }, 1000); - } else { - console.error('❌ 扫码启动失败:', result.message); - uni.showModal({ - title: '扫码启动失败', - content: `错误信息: ${result.message || '未知错误'}\n请检查相机权限是否已开启`, - showCancel: false - }); - } - }); - - console.log('扫码控件已挂载,正在启动...'); - }, - - // H5环境扫码(不变,兼容用) - startScan() { - uni.scanCode({ - success: (res) => { - uni.showModal({ title: '扫码成功', content: `获取到的编码号:${res.result}`, showCancel: false }); - }, - fail: () => uni.showToast({ title: '扫码失败', icon: 'none' }) - }); - }, - - // 暂停/继续扫码(逻辑优化) - pauseScan() { - if (!this.barcodeInstance) return; - this.scanPaused = !this.scanPaused; - this.scanPaused ? this.barcodeInstance.pause() : this.barcodeInstance.resume(); - uni.showToast({ title: this.scanPaused ? '扫码已暂停' : '扫码已继续', icon: 'none' }); - }, - - // 恢复扫码 - resumeScan() { - if (this.barcodeInstance && this.scanPaused) { - this.barcodeInstance.resume(); - this.scanPaused = false; - this.isScanning = true; - } - }, - - // 手电开关(不变,逻辑正常) toggleFlash() { - if (!this.barcodeInstance) return; - this.flashOn = !this.flashOn; - this.barcodeInstance.setFlash(this.flashOn); - uni.showToast({ title: this.flashOn ? '手电已开启' : '手电已关闭', icon: 'none' }); + if (this.barcodeInstance) { + this.flashOn = !this.flashOn; + this.barcodeInstance.setFlash(this.flashOn); + } }, - // 打开全屏扫码(使用 uni.scanCode 原生API) - openFullscreenScan() { - console.log('打开全屏扫码'); - - // 暂停嵌入式扫码 + pauseScan() { if (this.barcodeInstance) { - this.barcodeInstance.pause(); + this.scanPaused = !this.scanPaused; + this.scanPaused ? this.barcodeInstance.pause() : this.barcodeInstance.resume(); } - - // 调用 uniapp 原生扫码API,核心配置 - uni.scanCode({ - scanType: ['barCode', 'qrCode'], // 支持条形码和二维码 - onlyFromCamera: true, // 只使用相机,不从相册选择 - success: (res) => { - console.log('全屏扫码成功:', res); - - // 显示扫码结果 - uni.showModal({ - title: '扫码成功', - content: `获取到的编码号:${res.result}`, - showCancel: false, - success: () => { - // 恢复嵌入式扫码 - this.resumeScan(); - } - }); - }, - fail: (err) => { - console.error('全屏扫码失败:', err); - - // 恢复嵌入式扫码 - this.resumeScan(); - - if (err.errMsg !== 'scanCode:fail cancel') { - uni.showToast({ - title: '扫码失败,请重试', - icon: 'none' - }); - } - } - }); + }, + + addGoodsByBarcode(barcode) { + const mockGoods = { + name: '测试商品-' + barcode, + barcode: barcode, + price: 10, + quantity: 1, + image: '/static/yibao.png' + }; + this.goodsList.push(mockGoods); + uni.showToast({ title: '识别成功', icon: 'success' }); + }, + + removeGoods(index) { + this.goodsList.splice(index, 1); + }, + + submitList() { + uni.showToast({ title: '提交成功', icon: 'success' }); + setTimeout(() => uni.navigateBack(), 1000); } } }; \ No newline at end of file diff --git a/pages/index.vue b/pages/index.vue index 8aa3793..59dcd72 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -335,13 +335,12 @@ export default { .one{ width: 100%; - height: 100rpx; + height: 200rpx; /* background-image: url("/static/images/banner/banner01.jpg"); */ background-color: firebrick; - box-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.02); + box-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.02); margin-bottom: 4rpx; - z-index: -1; - position: relative; + z-index: -1; /* 最底层 */ } .barsOne{ position: absolute; @@ -593,12 +592,10 @@ export default { font-weight: bold; } .daiBan1{ - padding: 0rpx 10rpx; /* font-weight: bold; */ } .daiBan2{ - /* padding: 0rpx 270rpx; */ padding-left: 278rpx; color: red; @@ -656,15 +653,6 @@ export default { box-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.02); } -.one{ - width: 100%; - height: 200rpx; - /* background-image: url("/static/images/banner/banner01.jpg"); */ - background-color: firebrick; - box-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.02); - margin-bottom: 4rpx; - z-index: -1; /* 最底层 */ -} .brand { font-size: 32rpx; font-weight: bold; @@ -673,13 +661,11 @@ export default { .store-name { font-size: 28rpx; - margin-top: 2rpx; } .status-right { display: flex; - /* flex-direction: column; */ /* align-items: flex-end; */ } @@ -705,6 +691,7 @@ export default { /* min-height: 100vh; */ padding: 20rpx; /* background-color: #f8f9fa; */ + box-sizing: border-box; } /* 顶部状态栏 - 图片版本 */ @@ -731,9 +718,7 @@ export default { } /* 中间:店铺信息和状态 */ .status-center { - padding-left: 14rpx; - - + padding-left: 14rpx; } .store-name { @@ -775,18 +760,11 @@ export default { .close-icon { width: 70rpx; height: 52rpx; - /* margin-right: 0rpx; */ - /* padding: 2rpx; */ - - } .close-icons { width: 172rpx; height: 98rpx; - /* margin-right: 0rpx; */ padding: 2rpx; - - } .status-text { @@ -807,57 +785,153 @@ export default { .main-content { flex: 1; padding: 20rpx; - height: 10000rpx; + height: auto; /* 修复高度固定导致的滚动问题 */ + box-sizing: border-box; } -/* 功能网格样式 */ +/* 功能网格样式 - 最终修复版 */ .function-grid { - text-align: center; + text-align: center; display: flex; flex-wrap: wrap; - justify-content: flex-start; - margin-bottom: 20rpx; + justify-content: space-between; /* 关键:自动分配间距 */ + align-items: flex-start; + margin: 0 auto 20rpx; background: white; border-radius: 16rpx; - padding: 40rpx 20rpx; + padding: 30rpx 20rpx; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); + width: calc(100% - 40rpx); + box-sizing: border-box; } -/* H5平台 - 使用px单位 */ -/* #ifdef H5 */ -.function-grid { - padding: 40px 20px; +/* 网格项 - 核心修复 */ +.grid-item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 23%; /* 容错宽度,避免换行 */ + margin-bottom: 30rpx; + box-sizing: border-box; + padding: 10rpx 0; } -.function-grid .grid-item { - width: calc(25% - 20px); - margin-right: 20px; - margin-bottom: 20px; - flex-shrink: 0; +/* 图标容器 - 统一rpx单位,修复显示问题 */ +.item-icon { + width: 80rpx; + height: 80rpx; + background-image: url('/static/Frame 61.png'); + background-size: 100% 100%; /* 完全填充容器 */ + background-repeat: no-repeat; + background-position: center; + border-radius: 20rpx; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 10rpx; +} +.item-iconb { + width: 80rpx; + height: 80rpx; + background-image: url('/static/Frame 67.png'); + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; + border-radius: 20rpx; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 10rpx; +} +.item-iconc { + width: 80rpx; + height: 80rpx; + background-image: url('/static/Frame 71.png'); + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; + border-radius: 20rpx; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 10rpx; +} +.item-icond { + width: 80rpx; + height: 80rpx; + background-image: url('/static/Frame 68.png'); + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; + border-radius: 20rpx; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 10rpx; +} +.item-icone { + width: 80rpx; + height: 80rpx; + background-image: url('/static/Frame 66.png'); + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 10rpx; +} +.item-iconf { + width: 80rpx; + height: 80rpx; + background-image: url('/static/Frame 76.png'); + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 10rpx; +} +.item-icong { + width: 80rpx; + height: 80rpx; + background-image: url('/static/Frame 64.png'); + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; + border-radius: 20rpx; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 10rpx; +} +.item-iconh { + width: 80rpx; + height: 80rpx; + background-image: url('/static/Frame 64.png'); + background-size: 100% 100%; + background-repeat: no-repeat; + background-position: center; + border-radius: 20rpx; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 10rpx; } -.function-grid .grid-item:nth-child(4n) { - margin-right: 0; +/* 文字样式 - 确保不换行 */ +.item-text { + font-size: 24rpx; + color: #333; + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + line-height: 1.2; } -/* #endif */ - -/* App平台 - 使用rpx单位 */ -/* #ifdef APP-PLUS */ -.function-grid { - padding: 40rpx 20rpx; -} - -.function-grid .grid-item { - width: calc(25% - 20rpx); - margin-right: 20rpx; - margin-bottom: 20rpx; - flex-shrink: 0; -} - -.function-grid .grid-item:nth-child(4n) { - margin-right: 0; -} -/* #endif */ .function-grids { display: inline-flex; @@ -868,9 +942,9 @@ export default { border-radius: 16rpx; padding: 30rpx; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); + box-sizing: border-box; } .function-gridss { - /* display: inline-flex; */ width: 100%; justify-content: space-between; margin-bottom: -16rpx; @@ -878,147 +952,14 @@ export default { border-radius: 16rpx; padding: 20rpx; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); - } + box-sizing: border-box; +} .two{ - display: inline-flex; - /* flex: 1; */ - margin-bottom: -8rpx; -} -.grid-item { - display: flex; - flex-direction: column; - align-items: center; - width: 150rpx; -} - -.item-icon { - width: 100rpx; - height: 100rpx; - /* background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); */ - background-image: url('/static/Frame 61.png'); - background-size: 106rpx 106rpx; /* 宽度 高度 */ - - background-repeat: no-repeat; /* 关键:禁止重复 */ - background-position: center; /* 可选:居中显示 */ - border-radius: 20rpx; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: -15rpx; -} -.item-iconb { - width: 100rpx; - height: 100rpx; - /* background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); */ - background-image: url('/static/Frame 67.png'); - background-size: 106rpx 106rpx; /* 宽度 高度 */ - - background-repeat: no-repeat; /* 关键:禁止重复 */ - background-position: center; /* 可选:居中显示 */ - border-radius: 20rpx; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: -15rpx; -} -.item-iconc { - width: 100rpx; - height: 100rpx; - /* background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); */ - background-image: url('/static/Frame 71.png'); - background-size: 106rpx 106rpx; /* 宽度 高度 */ - - background-repeat: no-repeat; /* 关键:禁止重复 */ - background-position: center; /* 可选:居中显示 */ - border-radius: 20rpx; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: -15rpx; -} -.item-icond { - /* width: 100rpx; */ - /* height: 100rpx; */ - /* background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); */ - background-image: url('/static/Frame 68.png'); - background-size: 106rpx 106rpx; /* 宽度 高度 */ - - background-repeat: no-repeat; /* 关键:禁止重复 */ - background-position: center; /* 可选:居中显示 */ - border-radius: 20rpx; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: -15rpx; -} -.item-icone { - /* width: 100rpx; */ - /* height: 100rpx; */ - /* background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); */ - background-image: url('/static/Frame 66.png'); - background-size: 106rpx 106rpx; /* 宽度 高度 */ - - background-repeat: no-repeat; /* 关键:禁止重复 */ - background-position: center; /* 可选:居中显示 */ - display: flex; - align-items: center; - justify-content: center; - margin-bottom: -15rpx; -} -.item-iconf { - /* width: 100rpx; */ - /* height: 100rpx; */ - /* background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); */ - background-image: url('/static/Frame 76.png'); - background-size: 106rpx 106rpx; /* 宽度 高度 */ - - background-repeat: no-repeat; /* 关键:禁止重复 */ - background-position: center; /* 可选:居中显示 */ - display: flex; - align-items: center; - justify-content: center; - margin-bottom: -15rpx; -} -.item-icong { - /* width: 100rpx; */ - /* height: 100rpx; */ - /* background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); */ - background-image: url('/static/Frame 64.png'); - background-size: 106rpx 106rpx; /* 宽度 高度 */ - - background-repeat: no-repeat; /* 关键:禁止重复 */ - background-position: center; /* 可选:居中显示 */ - border-radius: 20rpx; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: -15rpx; -}.item-iconh { - width: 100rpx; - height: 100rpx; - /* background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); */ - background-image: url('/static/Frame 64.png'); - background-size: 106rpx 106rpx; /* 宽度 高度 */ - - background-repeat: no-repeat; /* 关键:禁止重复 */ - background-position: center; /* 可选:居中显示 */ - border-radius: 20rpx; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: -15rpx; -} - -/* .icon { - font-size: 50rpx; -} */ - -.item-text { - font-size: 24rpx; - color: #333; - text-align: center; - line-height: 4.2; + display: inline-flex; + margin-bottom: -8rpx; + width: 100%; + box-sizing: border-box; } /* 收入预估卡片 */ @@ -1028,6 +969,7 @@ export default { padding: 30rpx; margin-bottom: 30rpx; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); + box-sizing: border-box; } .card-header { @@ -1070,6 +1012,7 @@ export default { display: flex; justify-content: center; align-items: center; + box-sizing: border-box; } .placeholder-chart { @@ -1095,6 +1038,7 @@ export default { padding: 40rpx; margin-bottom: 30rpx; text-align: center; + box-sizing: border-box; } .promotion-text { @@ -1115,6 +1059,7 @@ export default { box-shadow: 0 -4rpx 12rpx rgba(0, 0, 0, 0.05); position: sticky; bottom: 20rpx; + box-sizing: border-box; } .upgrade-text { @@ -1128,267 +1073,42 @@ export default { color: #667eea; } .closeView{ - padding-left: 158rpx + padding-left: 158rpx; + box-sizing: border-box; } .xianjin{ - padding-left: 12rpx -} -/* 响应式调整 - 使用margin替代gap提高兼容性 */ - -/* H5平台 - 使用px单位 */ -/* #ifdef H5 */ -@media (min-width: 751px) { - .function-grid .grid-item { - width: calc(25% - 20px); - margin-right: 20px; - } - - .function-grid .grid-item:nth-child(4n) { - margin-right: 0; - } - - .item-icon, - .item-iconb, - .item-iconc, - .item-icond, - .item-icone, - .item-iconf, - .item-icong, - .item-iconh { - width: 80px; - height: 80px; - background-size: 80px 80px; - } - - .item-text { - font-size: 14px; - } + padding-left: 12rpx; + box-sizing: border-box; } -@media (max-width: 750px) and (min-width: 601px) { - .function-grid .grid-item { - width: calc(25% - 15px); - margin-right: 15px; +/* 响应式适配 - 仅用rpx和百分比 */ +@media (max-width: 600rpx) { + .grid-item { + width: 22%; /* 小屏进一步缩小宽度,避免溢出 */ } - - .function-grid .grid-item:nth-child(4n) { - margin-right: 0; - } - - .item-icon, - .item-iconb, - .item-iconc, - .item-icond, - .item-icone, - .item-iconf, - .item-icong, - .item-iconh { - width: 70px; - height: 70px; - background-size: 70px 70px; - } - - .item-text { - font-size: 12px; - } -} - -@media (max-width: 600px) and (min-width: 401px) { - .function-grid .grid-item { - width: calc(25% - 12px); - margin-right: 12px; - } - - .function-grid .grid-item:nth-child(4n) { - margin-right: 0; - } - - .item-icon, - .item-iconb, - .item-iconc, - .item-icond, - .item-icone, - .item-iconf, - .item-icong, - .item-iconh { - width: 60px; - height: 60px; - background-size: 60px 60px; - } - - .item-text { - font-size: 11px; - } -} - -@media (max-width: 400px) { - .function-grid .grid-item { - width: calc(25% - 10px); - margin-right: 10px; - } - - .function-grid .grid-item:nth-child(4n) { - margin-right: 0; - } - - .item-icon, - .item-iconb, - .item-iconc, - .item-icond, - .item-icone, - .item-iconf, - .item-icong, - .item-iconh { - width: 50px; - height: 50px; - background-size: 50px 50px; - } - - .item-text { - font-size: 10px; - } - - .stats { - flex-wrap: wrap; - } - - .stat-item { - width: 50%; - } -} -/* #endif */ - -/* App平台 - 使用rpx单位 */ -/* #ifdef APP-PLUS */ -@media (min-width: 751rpx) { - .function-grid .grid-item { - width: calc(25% - 20rpx); - margin-right: 20rpx; - } - - .function-grid .grid-item:nth-child(4n) { - margin-right: 0; - } - - .item-icon, - .item-iconb, - .item-iconc, - .item-icond, - .item-icone, - .item-iconf, - .item-icong, - .item-iconh { - width: 100rpx; - height: 100rpx; - background-size: 100rpx 100rpx; - } - - .item-text { - font-size: 24rpx; - } -} - -@media (max-width: 750rpx) and (min-width: 601rpx) { - .function-grid .grid-item { - width: calc(25% - 15rpx); - margin-right: 15rpx; - } - - .function-grid .grid-item:nth-child(4n) { - margin-right: 0; - } - - .item-icon, - .item-iconb, - .item-iconc, - .item-icond, - .item-icone, - .item-iconf, - .item-icong, - .item-iconh { - width: 86rpx; - height: 86rpx; - background-size: 86rpx 86rpx; - } - - .item-text { - font-size: 22rpx; - } -} - -@media (max-width: 600rpx) and (min-width: 401rpx) { - .function-grid .grid-item { - width: calc(25% - 12rpx); - margin-right: 12rpx; - } - - .function-grid .grid-item:nth-child(4n) { - margin-right: 0; - } - - .item-icon, - .item-iconb, - .item-iconc, - .item-icond, - .item-icone, - .item-iconf, - .item-icong, - .item-iconh { + .item-icon, .item-iconb, .item-iconc, .item-icond, + .item-icone, .item-iconf, .item-icong, .item-iconh { width: 70rpx; height: 70rpx; - background-size: 70rpx 70rpx; } - .item-text { font-size: 20rpx; } } -@media (max-width: 400rpx) { - .function-grid .grid-item { - width: calc(25% - 10rpx); - margin-right: 10rpx; +/* 横屏适配 */ +@media (orientation: landscape) { + .one { + height: 150rpx; } - - .function-grid .grid-item:nth-child(4n) { - margin-right: 0; + .function-grid { + padding: 20rpx 10rpx; } - - .item-icon, - .item-iconb, - .item-iconc, - .item-icond, - .item-icone, - .item-iconf, - .item-icong, - .item-iconh { - width: 60rpx; - height: 60rpx; - background-size: 60rpx 60rpx; + .grid-item { + width: 15%; /* 横屏时自动调整为6列 */ } - .item-text { font-size: 18rpx; } - - .stats { - flex-wrap: wrap; - } - - .stat-item { - width: 50%; - } -} -/* #endif */ - -/* 横屏适配 */ -@media screen and (orientation: landscape) { - .one { - height: 150px; - } - - .function-grid { - padding: 15rpx 15rpx; - } } \ No newline at end of file diff --git a/pages/product/product.vue b/pages/product/product.vue index 14ef3d3..39d3fad 100644 --- a/pages/product/product.vue +++ b/pages/product/product.vue @@ -79,7 +79,7 @@ - + {{ item.productName }} diff --git a/project.config.json b/project.config.json new file mode 100644 index 0000000..721a326 --- /dev/null +++ b/project.config.json @@ -0,0 +1,35 @@ +{ + "setting": { + "es6": true, + "postcss": true, + "minified": true, + "uglifyFileName": false, + "enhance": true, + "packNpmRelationList": [], + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "useCompilerPlugins": false, + "minifyWXML": true, + "compileWorklet": false, + "uploadWithSourceMap": true, + "packNpmManually": false, + "minifyWXSS": true, + "localPlugins": false, + "disableUseStrict": false, + "condition": false, + "swc": false, + "disableSWC": true + }, + "compileType": "miniprogram", + "simulatorPluginLibVersion": {}, + "packOptions": { + "ignore": [], + "include": [] + }, + "appid": "wxe94413d023e0e7df", + "editorSetting": {}, + "libVersion": "3.14.0" +} \ No newline at end of file diff --git a/project.private.config.json b/project.private.config.json new file mode 100644 index 0000000..83634ac --- /dev/null +++ b/project.private.config.json @@ -0,0 +1,21 @@ +{ + "libVersion": "3.14.0", + "projectname": "RuoYi-App-master", + "setting": { + "urlCheck": true, + "coverView": true, + "lazyloadPlaceholderEnable": false, + "skylineRenderEnable": false, + "preloadBackgroundData": false, + "autoAudits": false, + "showShadowRootInWxmlPanel": true, + "compileHotReLoad": true, + "useApiHook": true, + "useStaticServer": false, + "useLanDebug": false, + "showES6CompileOption": false, + "checkInvalidKey": true, + "ignoreDevUnusedFiles": true, + "bigPackageSizeSupport": false + } +} \ No newline at end of file diff --git a/utils/request.js b/utils/request.js index 914dd2d..a8878a6 100644 --- a/utils/request.js +++ b/utils/request.js @@ -10,67 +10,86 @@ const baseUrl = config.baseUrl const request = config => { // 是否需要设置 token const isToken = (config.headers || {}).isToken === false - config.header = config.header || { - 'Content-Type': 'application/json;charset=UTF-8' - } - if (getToken() && !isToken) { - config.header['Authorization'] = 'Bearer ' + getToken() + // 修复:合并header,而非覆盖,保证Content-Type不丢失 + config.header = { + 'Content-Type': 'application/json;charset=UTF-8', + ...config.header // 自定义header在后,可覆盖默认值 } - console.log('Token:', getToken()) + // 修复:Token非空时才拼接,避免Bearer undefined + const token = getToken() + if (token && !isToken) { + config.header['Authorization'] = 'Bearer ' + token + } + + console.log('Token:', token) console.log('请求头:', config.header) // get请求映射params参数 if (config.params) { let url = config.url + '?' + tansParams(config.params) - url = url.slice(0, -1) + // 修复:避免参数为空时最后多一个?(比如params是空对象) + url = url.endsWith('?') ? url.slice(0, -1) : url config.url = url } + return new Promise((resolve, reject) => { const requestUrl = config.baseUrl ? config.baseUrl + config.url : baseUrl + config.url - console.log('请求URL:', requestUrl) + console.log('最终请求URL:', requestUrl) console.log('请求配置:', config) uni.request({ method: config.method || 'get', - timeout: config.timeout || timeout, + timeout: config.timeout || timeout, url: requestUrl, data: config.data, header: config.header, dataType: 'json' }).then(response => { let [error, res] = response - console.log('响应数据:', res) - console.log('响应状态码:', res.statusCode) - console.log('响应内容:', res.data) + // 第一步:先判断网络层错误(微信拦截/连接失败) if (error) { - toast('后端接口连接异常') - reject('后端接口连接异常') + const errMsg = `后端接口连接异常: ${error.errMsg || error.message}` + toast(errMsg) + reject(new Error(errMsg)) return } + + // 第二步:判断HTTP状态码(非200的情况) + if (res.statusCode !== 200) { + const errMsg = `接口HTTP异常: ${res.statusCode}` + toast(errMsg) + reject(new Error(errMsg)) + return + } + + // 第三步:处理业务状态码 const code = res.data.code || 200 const msg = errorCode[code] || res.data.msg || errorCode['default'] + if (code === 401) { showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => { if (res.confirm) { - store.dispatch('LogOut').then(res => { + store.dispatch('LogOut').then(() => { uni.reLaunch({ url: '/pages/login' }) }) } }) - reject('无效的会话,或者会话已过期,请重新登录。') + reject(new Error('无效的会话,或者会话已过期,请重新登录。')) } else if (code === 403) { console.log('403错误详情:', res.data) toast('没有权限访问该资源') - reject('403') + reject(new Error('403')) } else if (code === 500) { toast(msg) - reject('500') + reject(new Error('500')) } else if (code !== 200) { toast(msg) - reject(code) + reject(new Error(code.toString())) } + + // 成功返回业务数据 resolve(res.data) }) .catch(error => { @@ -88,4 +107,4 @@ const request = config => { }) } -export default request +export default request \ No newline at end of file