master
parent
c2192303fe
commit
90476adffa
|
|
@ -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 || '请求失败'
|
||||
|
||||
|
|
|
|||
|
|
@ -21,21 +21,19 @@
|
|||
"distribute" : {
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<!-- 扫码核心必要权限 -->",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"",
|
||||
"<!-- 网络相关(仅当扫码后需要联网查商品时保留) -->",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"",
|
||||
"<!-- 基础必要权限(如无特殊需求可保留) -->",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>"
|
||||
]
|
||||
},
|
||||
"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" : {
|
||||
|
|
|
|||
|
|
@ -19,20 +19,16 @@
|
|||
<input type="text" placeholder="搜索商品名称、条码" placeholder-class="search-placeholder" />
|
||||
</view>
|
||||
<button class="btn batch-import" @click="goImport">批量导入</button>
|
||||
<button class="btn no-code">无码/生鲜</button>
|
||||
<button class="btn no-code" @click="goNoCode">无码/生鲜</button>
|
||||
</view>
|
||||
|
||||
<!-- 条码扫描区域 【修复:调整定位和层级】 -->
|
||||
<!-- 条码扫描区域 -->
|
||||
<view class="scan-area">
|
||||
<view class="scan-tip">对准商品条码,自动识别</view>
|
||||
|
||||
<!-- App环境使用扫码控件 【这里的view只做占位,扫码控件是原生图层叠加】 -->
|
||||
<!-- App环境扫码 -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view class="scan-view" id="barcode-view"></view>
|
||||
<view class="scan-status" v-if="isScanning">
|
||||
<view class="scan-line"></view>
|
||||
<text class="scan-status-text">正在扫描...</text>
|
||||
</view>
|
||||
<view class="scan-controls" v-if="isScanning">
|
||||
<view class="control-item" @click.stop="toggleFlash">
|
||||
<uni-icons type="flash" size="22" color="#fff"></uni-icons>
|
||||
|
|
@ -42,14 +38,10 @@
|
|||
<uni-icons type="pause" size="22" color="#fff"></uni-icons>
|
||||
<text class="control-text">{{ scanPaused ? '继续扫码' : '暂停扫码' }}</text>
|
||||
</view>
|
||||
<view class="control-item" @click.stop="openFullscreenScan">
|
||||
<uni-icons type="scan" size="22" color="#fff"></uni-icons>
|
||||
<text class="control-text">全屏扫码</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- H5环境显示提示 -->
|
||||
<!-- H5环境提示 -->
|
||||
<!-- #ifndef APP-PLUS -->
|
||||
<view class="h5-tip">
|
||||
<text class="tip-text">扫码功能需要在App中使用</text>
|
||||
|
|
@ -58,12 +50,42 @@
|
|||
<!-- #endif -->
|
||||
</view>
|
||||
|
||||
<!-- 空状态区域 -->
|
||||
<view class="empty-area">
|
||||
<image src="/static/empty-icon.png" mode="widthFix" class="empty-icon"></image>
|
||||
<!-- 已录入商品列表 -->
|
||||
<view class="goods-list" v-if="goodsList.length > 0">
|
||||
<view class="goods-item" v-for="(item, index) in goodsList" :key="index">
|
||||
<view class="goods-info">
|
||||
<image :src="item.image || '/static/default-goods.png'" class="goods-img"></image>
|
||||
<view class="goods-detail">
|
||||
<text class="goods-name">{{ item.name }}</text>
|
||||
<text class="goods-barcode">{{ item.barcode }}</text>
|
||||
<text class="goods-price">¥{{ item.price }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-actions">
|
||||
<view class="action-btn remove" @click="removeGoods(index)">移除商品</view>
|
||||
</view>
|
||||
<view class="goods-form">
|
||||
<view class="form-item">
|
||||
<text class="label required">进货数量</text>
|
||||
<input type="number" v-model="item.quantity" class="input" placeholder="请输入数量" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">进货价</text>
|
||||
<input type="number" v-model="item.price" class="input" placeholder="请输入价格" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-area" v-else>
|
||||
<text class="empty-title">暂未录入商品</text>
|
||||
<text class="empty-desc">请在上方选择商品录入方式</text>
|
||||
<uni-icons type="arrowup" size="14" color="#ccc"></uni-icons>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-area">
|
||||
<button class="submit-btn" @click="submitList" :disabled="goodsList.length === 0">提交清单</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 页面基础样式 */
|
||||
.input-list-page {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.navbar {
|
||||
width: 100%;
|
||||
height: calc(var(--status-bar-height) + 44px);
|
||||
|
|
@ -477,8 +356,9 @@ export default {
|
|||
color: #fff;
|
||||
}
|
||||
|
||||
/* 功能操作栏 */
|
||||
.operation-bar {
|
||||
margin-top: var(--status-bar-height) + 44px;
|
||||
margin-top: calc(var(--status-bar-height) + 44px);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -517,15 +397,15 @@ export default {
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
/* ✅ 修复:扫码区域样式优化,适配原生扫码图层 */
|
||||
/* 扫码区域(关键修复:增加z-index) */
|
||||
.scan-area {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
min-height: 350px;
|
||||
margin-top: 10px;
|
||||
background-color: transparent;
|
||||
background-color: #fff;
|
||||
z-index: 1; /* 确保扫码区域在最上层 */
|
||||
}
|
||||
|
||||
.scan-tip {
|
||||
|
|
@ -549,40 +429,7 @@ export default {
|
|||
overflow: hidden;
|
||||
position: relative;
|
||||
background-color: #000;
|
||||
border: 2px solid #e60012;
|
||||
}
|
||||
|
||||
.scan-status {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9;
|
||||
pointer-events: none; /* 不遮挡扫码识别 */
|
||||
}
|
||||
|
||||
.scan-line {
|
||||
width: 80%;
|
||||
height: 2px;
|
||||
background-color: #e60012;
|
||||
animation: scanMove 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes scanMove {
|
||||
0% { transform: translateY(0); opacity: 0; }
|
||||
50% { opacity: 1; }
|
||||
100% { transform: translateY(250px); opacity: 0; }
|
||||
}
|
||||
|
||||
.scan-status-text {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
margin-top: 20px;
|
||||
z-index: 2; /* 关键修复:确保扫码容器层级 */
|
||||
}
|
||||
|
||||
.scan-controls {
|
||||
|
|
@ -591,7 +438,8 @@ export default {
|
|||
left: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
justify-content: center;
|
||||
gap: 40px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
z-index: 10;
|
||||
|
|
@ -606,28 +454,23 @@ export default {
|
|||
padding: 8px 12px;
|
||||
border-radius: 8px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
transition: all 0.3s ease;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.control-item:active {
|
||||
background-color: rgba(230, 0, 18, 0.6);
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.control-text {
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* H5端提示 */
|
||||
.h5-tip {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60px 20px;
|
||||
background-color: #fff;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
|
|
@ -645,6 +488,109 @@ export default {
|
|||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* 商品列表 */
|
||||
.goods-list {
|
||||
flex: 1;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.goods-item {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.goods-info {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 4px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.goods-detail {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.goods-barcode {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
font-size: 14px;
|
||||
color: #e60012;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.goods-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.remove {
|
||||
background-color: #fef0f0;
|
||||
color: #ff4d4f;
|
||||
border: 1px solid #ffccc7;
|
||||
}
|
||||
|
||||
/* 商品表单 */
|
||||
.goods-form {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.required::before {
|
||||
content: '*';
|
||||
color: #e60012;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.input {
|
||||
height: 32px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
padding: 0 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-area {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
|
@ -652,14 +598,6 @@ export default {
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin-bottom: 15px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
|
|
@ -670,7 +608,28 @@ export default {
|
|||
|
||||
.empty-desc {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin-bottom: 10px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 提交按钮区域 */
|
||||
.submit-area {
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
background-color: #e60012;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.submit-btn:disabled {
|
||||
background-color: #ccc;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
612
pages/index.vue
612
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;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -79,7 +79,7 @@
|
|||
</view>
|
||||
<view class="goods-top" @tap="goToStockDetail(item)">
|
||||
<view class="goods-tou">
|
||||
<image :src="item.mainImage ? 'http://193.112.94.36:8081' + item.mainImage : '/static/687b6f95b14eff60f4b77147b3726ab2.jpg'"></image>
|
||||
<image :src="item.mainImage ? 'http://193.112.94.36:8081' + item.mainImage : '/static/687b6f95b14eff60f4b77147b3726ab2.jpg' "></image>
|
||||
</view>
|
||||
<view class="goods-info">
|
||||
<text class="goods-name">{{ item.productName }}</text>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue