master
fy 2026-01-21 15:09:06 +08:00
parent c2192303fe
commit 90476adffa
8 changed files with 625 additions and 866 deletions

View File

@ -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 || '请求失败'

View File

@ -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" : {

View File

@ -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'
}
]
};
},
// mountedDOM
mounted() {
// #ifdef APP-PLUS
console.log('=== 扫码页面 mounted ===');
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;
if (this.barcodeInstance) {
this.flashOn = !this.flashOn;
this.barcodeInstance.setFlash(this.flashOn);
uni.showToast({ title: this.flashOn ? '手电已开启' : '手电已关闭', icon: 'none' });
}
},
// 使 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();
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' });
},
if (err.errMsg !== 'scanCode:fail cancel') {
uni.showToast({
title: '扫码失败,请重试',
icon: 'none'
});
}
}
});
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 {
@ -671,6 +609,27 @@ export default {
.empty-desc {
font-size: 14px;
color: #999;
margin-bottom: 10px;
}
/* 提交按钮区域 */
.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>

View File

@ -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);
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;
}
/* 顶部状态栏 - 图片版本 */
@ -732,8 +719,6 @@ export default {
/* 中间:店铺信息和状态 */
.status-center {
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;
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;
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>

View File

@ -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>

35
project.config.json Normal file
View File

@ -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"
}

View File

@ -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
}
}

View File

@ -10,25 +10,32 @@ 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({
@ -40,37 +47,49 @@ const request = config => {
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 => {