consumer模块完成度95%,优化安卓端界面和小程序测试
This commit is contained in:
@@ -7,6 +7,10 @@
|
||||
"packageName" : "com.huawei.hisuite",
|
||||
"playground" : "standard",
|
||||
"type" : "uni-app:app-android"
|
||||
},
|
||||
{
|
||||
"playground" : "standard",
|
||||
"type" : "uni-app:app-ios"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
// Supabase 配置
|
||||
// 内网环境 - 本地部署的 Supabase
|
||||
// IP: 192.168.1.62
|
||||
// IP: 192.168.1.62
|
||||
// Kong HTTP Port: 8000
|
||||
//自己的配置自己解开即可
|
||||
//export const SUPA_URL: string = 'http://192.168.1.61:18000'
|
||||
//export const SUPA_KEY: string = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlLTEiLCJpYXQiOjE3Njk2NzY0OTgsImV4cCI6MTkyNzM1NjQ5OH0.ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
|
||||
export const SUPA_URL: string = 'http://192.168.1.61:18000'
|
||||
export const SUPA_KEY: string = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlLTEiLCJpYXQiOjE3Njk2NzY0OTgsImV4cCI6MTkyNzM1NjQ5OH0.ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
|
||||
|
||||
// WebSocket 实时连接(内网使用 ws:// 而非 wss://)
|
||||
// export const WS_URL: string = 'ws://192.168.1.61:18000/realtime/v1/websocket'
|
||||
export const WS_URL: string = 'ws://192.168.1.61:18000/realtime/v1/websocket'
|
||||
|
||||
// 备用配置(已注释,如需切换可取消注释)
|
||||
// 开发环境 - 其他内网地址
|
||||
// export const SUPA_URL: string = 'http://192.168.0.150:8080'
|
||||
// export const SUPA_KEY: string = 'your-anon-key'
|
||||
// export const WS_URL: string = 'ws://192.168.0.150:8080/realtime/v1/websocket'
|
||||
|
||||
// 生产环境 - Supabase 云服务(已注释)
|
||||
// export const SUPA_URL: string = 'https://ak3.oulog.com'
|
||||
// export const SUPA_KEY: string = 'your-anon-key'
|
||||
// export const WS_URL: string = 'wss://ak3.oulog.com/realtime/v1/websocket'
|
||||
|
||||
// 指向你的 Supabase 服务(开发/私有部署)
|
||||
// export const SUPA_URL: string = 'http://192.168.1.64:3000'
|
||||
// export const SUPA_KEY: string = 'your-anon-key'
|
||||
// export const WS_URL: string = 'ws://192.168.1.64:3000/realtime/v1'
|
||||
|
||||
// 路由配置
|
||||
export const HOME_REDIRECT: string = '/pages/mall/consumer/index'
|
||||
export const TABORPAGE: string = '/pages/mall/consumer/index'
|
||||
|
||||
// 测试模式:放开任意跳转(禁用启动页/登录/401 的强制重定向)
|
||||
export const IS_TEST_MODE: boolean = true
|
||||
@@ -116,12 +116,28 @@ export class AkSupaQueryBuilder {
|
||||
private _addCond(afield : string, op : string, value : any | null) : AkSupaQueryBuilder {
|
||||
//console.log('add cond:', op, afield, value)
|
||||
const field = encodeURIComponent(afield)!!
|
||||
// 将 null 转换为字符串 'null',避免构造对象时缺少 value 属性
|
||||
let safeValue = value;
|
||||
// 将值安全存储,避免安卓端类型转换问题
|
||||
let safeValue: any | null = value;
|
||||
if (value === null) {
|
||||
safeValue = 'null';
|
||||
} else if (Array.isArray(value)) {
|
||||
// 数组类型保持原样,用于 in 操作符
|
||||
safeValue = value;
|
||||
} else if (typeof value === 'number') {
|
||||
// 数字类型保持原样
|
||||
safeValue = value;
|
||||
} else if (typeof value === 'boolean') {
|
||||
// 布尔类型保持原样
|
||||
safeValue = value;
|
||||
} else if (typeof value !== 'string') {
|
||||
// 其他类型尝试转换为字符串
|
||||
try {
|
||||
safeValue = value.toString();
|
||||
} catch (e) {
|
||||
safeValue = '';
|
||||
}
|
||||
this._conditions.push({ field, op, value: safeValue, logic: this._nextLogic });
|
||||
}
|
||||
this._conditions.push({ field, op, value: safeValue ?? '', logic: this._nextLogic });
|
||||
//console.log(this._conditions)
|
||||
this._nextLogic = 'and';
|
||||
return this;
|
||||
@@ -209,6 +225,23 @@ export class AkSupaQueryBuilder {
|
||||
//console.log('设置 range:', from, 'to', to);
|
||||
return this;
|
||||
}
|
||||
|
||||
// 辅助函数:安全地将值转换为字符串
|
||||
private _valToStr(val: any): string {
|
||||
if (val == null) return '';
|
||||
try {
|
||||
// 尝试直接调用 toString
|
||||
return val.toString();
|
||||
} catch (e) {
|
||||
try {
|
||||
// 尝试 JSON 序列化
|
||||
return JSON.stringify(val);
|
||||
} catch (e2) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将 _conditions 强类型直接转换为 Supabase/PostgREST 查询字符串(不再用 UTSJSONObject 做中转)
|
||||
private _buildFilter() : string | null {
|
||||
if (this._conditions.length == 0 && (this._orString==null || this._orString == "")) {
|
||||
@@ -236,12 +269,13 @@ export class AkSupaQueryBuilder {
|
||||
const op = cond.op;
|
||||
const val = cond.value;
|
||||
if ((op == 'in' || op == 'not.in') && Array.isArray(val)) {
|
||||
params.push(`${k}=${op}.(${val.map(x => typeof x == 'object' ? encodeURIComponent(JSON.stringify(x)) : encodeURIComponent(x.toString())).join(',')})`);
|
||||
params.push(`${k}=${op}.(${val.map(x => this._valToStr(x)).map(x => encodeURIComponent(x)).join(',')})`);
|
||||
} else if ((op == 'is' || op == 'not.is') && (val == null || val == 'null')) {
|
||||
params.push(`${k}=${op}.null`);
|
||||
} else if (op == 'like' || op == 'ilike') {
|
||||
params.push(`${k}=${op}.${this._valToStr(val)}`);
|
||||
} else {
|
||||
const opvalstr: string = (typeof val == 'object') ? JSON.stringify(val) : (val as string);
|
||||
params.push(`${k}=${op}.${encodeURIComponent(opvalstr)}`);
|
||||
params.push(`${k}=${op}.${encodeURIComponent(this._valToStr(val))}`);
|
||||
}
|
||||
}
|
||||
// 处理 or 条件
|
||||
@@ -251,17 +285,21 @@ export class AkSupaQueryBuilder {
|
||||
const op = o.op;
|
||||
const val = o.value;
|
||||
if (op == "in" && Array.isArray(val)) {
|
||||
return `${k}.in.(${val.map(x => encodeURIComponent(x as string)).join(",")})`;
|
||||
return `${k}.in.(${val.map(x => encodeURIComponent(this._valToStr(x))).join(",")})`;
|
||||
}
|
||||
if (op == "is" && (val == null)) {
|
||||
return `${k}.is.null`;
|
||||
}
|
||||
return `${k}.${op}.${encodeURIComponent(val as string)}`;
|
||||
if (op == "like" || op == "ilike") {
|
||||
return `${k}.${op}.${this._valToStr(val)}`;
|
||||
}
|
||||
return `${k}.${op}.${encodeURIComponent(this._valToStr(val))}`;
|
||||
}).join(",");
|
||||
params.push(`or=(${orStr})`);
|
||||
}
|
||||
if (this._orString!=null && this._orString !== "") {
|
||||
params.push(`or=(${encodeURIComponent(this._orString!!)})`);
|
||||
console.log('[AkSupaQueryBuilder] or字符串:', this._orString)
|
||||
params.push(`or=(${this._orString!!})`);
|
||||
}
|
||||
return params.length > 0 ? params.join('&') : null;
|
||||
}
|
||||
@@ -316,7 +354,7 @@ export class AkSupaQueryBuilder {
|
||||
async execute() : Promise<AkReqResponse<any>> {
|
||||
//console.log('execute')
|
||||
const filter = this._buildFilter();
|
||||
//console.log('execute', filter)
|
||||
console.log('[AkSupaQueryBuilder] execute - 表:', this._table, 'filter:', filter)
|
||||
let res : any;
|
||||
switch (this._action) {
|
||||
case 'select': {
|
||||
|
||||
@@ -145,6 +145,8 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 底部占位符:确保内容不被原生 TabBar 遮挡 -->
|
||||
<view class="tabbar-safe-area"></view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部结算栏 - 已移除,移动到内容区域 -->
|
||||
@@ -966,7 +968,89 @@ const goToCheckout = () => {
|
||||
/* 必须设置 height: 0 或 overflow: hidden 可以在 flex 容器中正确收缩 */
|
||||
height: 0px;
|
||||
width: 100%;
|
||||
padding-bottom: 60px; /* 为底部结算栏留出空间 */
|
||||
padding-bottom: 20px; /* 减小内边距,因为结算栏已在内容流中 */
|
||||
}
|
||||
|
||||
/* 购物车操作栏 (移至推荐商品上方) */
|
||||
.cart-action-bar {
|
||||
background-color: white;
|
||||
margin: 10px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.action-bar-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 15px;
|
||||
}
|
||||
|
||||
.action-left {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-right {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.select-all {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.select-all-text {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.total-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.total-text {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.total-price {
|
||||
font-size: 18px;
|
||||
color: #ff5000;
|
||||
font-weight: bold;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.checkout-btn {
|
||||
background-color: #ff5000;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
padding: 8px 15px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
background-color: #fff;
|
||||
color: #ff5000;
|
||||
border: 1px solid #ff5000;
|
||||
border-radius: 20px;
|
||||
padding: 8px 15px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
/* 空购物车 */
|
||||
@@ -1672,5 +1756,11 @@ const goToCheckout = () => {
|
||||
width: 1400px; /* max-width -> width */
|
||||
}
|
||||
}
|
||||
|
||||
.tabbar-safe-area {
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
<view class="checkout-page">
|
||||
<scroll-view class="checkout-content" direction="vertical">
|
||||
<!-- 收货地址 -->
|
||||
<view class="address-section" @click="selectAddress">
|
||||
<view class="section-card address-section" @click="selectAddress">
|
||||
<view class="address-icon-wrapper">
|
||||
<text class="location-icon">📍</text>
|
||||
</view>
|
||||
<view v-if="selectedAddress" class="address-info">
|
||||
<view class="address-header">
|
||||
<text class="recipient">{{ selectedAddress!!.recipient_name }}</text>
|
||||
@@ -16,17 +19,14 @@
|
||||
</view>
|
||||
<view v-else class="no-address">
|
||||
<text class="no-address-text">请选择收货地址</text>
|
||||
<text class="no-address-arrow">›</text>
|
||||
</view>
|
||||
<view class="address-arrow-wrapper">
|
||||
<text class="address-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商品列表 (按店铺分组) -->
|
||||
<view class="products-section">
|
||||
<!-- 调试信息 -->
|
||||
<view v-if="checkoutItems.length > 0" class="debug-info">
|
||||
<text class="debug-text">共 {{ checkoutItems.length }} 件商品</text>
|
||||
</view>
|
||||
|
||||
<view class="section-card products-section">
|
||||
<view v-if="shopGroups.length > 0">
|
||||
<view v-for="group in shopGroups" :key="group.shopId" class="shop-group">
|
||||
<view class="shop-header">
|
||||
@@ -34,26 +34,24 @@
|
||||
<text class="shop-name">{{ group.shopName }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 商品列表 -->
|
||||
<view v-for="item in group.items" :key="item.id" class="product-item">
|
||||
<image class="product-image" :src="item.product_image" mode="aspectFill" />
|
||||
<view class="product-info">
|
||||
<view class="product-name-row">
|
||||
<text class="product-name">{{ item.product_name }}</text>
|
||||
<text v-if="item.sku_specifications" class="product-spec">{{ formatSpecs(item.sku_specifications) }}</text>
|
||||
<view class="product-bottom">
|
||||
<text class="product-price">¥{{ item.price }}</text>
|
||||
</view>
|
||||
<view class="product-spec-row">
|
||||
<text v-if="item.sku_specifications" class="product-spec">{{ formatSpecs(item.sku_specifications) }}</text>
|
||||
<text class="product-quantity">×{{ item.quantity }}</text>
|
||||
</view>
|
||||
<!-- 商品小计移至图片右侧 -->
|
||||
<view class="item-subtotal-row">
|
||||
<text class="item-subtotal-label">小计:</text>
|
||||
<text class="item-subtotal-price">¥{{ (item.price * item.quantity).toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 店铺小计 -->
|
||||
<view class="shop-subtotal">
|
||||
<text class="subtotal-label">配送方式</text>
|
||||
<text class="subtotal-value">快递 免邮</text>
|
||||
</view>
|
||||
<view class="shop-subtotal">
|
||||
<text class="subtotal-text">小计: </text>
|
||||
<text class="subtotal-price">¥{{ getGroupTotal(group) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -63,70 +61,76 @@
|
||||
</view>
|
||||
|
||||
<!-- 配送方式 -->
|
||||
<view class="delivery-section">
|
||||
<view class="section-card delivery-section">
|
||||
<view class="delivery-row">
|
||||
<text class="section-title">配送方式</text>
|
||||
<view class="delivery-options">
|
||||
<view class="delivery-selector">
|
||||
<view v-for="option in deliveryOptions"
|
||||
:key="option.id"
|
||||
:class="['delivery-option', { selected: selectedDelivery === option.id }]"
|
||||
:class="['delivery-pill', { selected: selectedDelivery === option.id }]"
|
||||
@click="selectDelivery(option)">
|
||||
<text class="option-name">{{ option.name }}</text>
|
||||
<text class="option-price">¥{{ option.price }}</text>
|
||||
<text v-if="selectedDelivery === option.id" class="option-selected">✓</text>
|
||||
<text class="pill-name">{{ option.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="delivery-detail" v-if="selectedDelivery">
|
||||
<text class="detail-desc">{{ deliveryOptions.find(opt => opt.id === selectedDelivery)?.description }}</text>
|
||||
<text class="detail-price">费用: ¥{{ deliveryOptions.find(opt => opt.id === selectedDelivery)?.price.toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 优惠券 -->
|
||||
<view class="coupon-section" @click="selectCoupon">
|
||||
<view class="section-card coupon-section" @click="selectCoupon">
|
||||
<view class="coupon-row">
|
||||
<text class="section-title">优惠券</text>
|
||||
<view class="coupon-info">
|
||||
<text v-if="selectedCoupon != null" class="coupon-selected">{{ selectedCoupon.template?.name ?? '已选择优惠券 (¥' + (selectedCoupon.template?.discount_value ?? 0) + ')' }}</text>
|
||||
<text v-else class="coupon-placeholder">选择优惠券</text>
|
||||
<text class="coupon-arrow">›</text>
|
||||
<view class="coupon-right-content">
|
||||
<text v-if="selectedCoupon != null" class="coupon-selected-name">{{ selectedCoupon.template?.name ?? '已选择优惠券' }}</text>
|
||||
<text v-else class="coupon-placeholder">暂无可用优惠券</text>
|
||||
<text class="arrow-icon">›</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 买家留言 -->
|
||||
<view class="remark-section">
|
||||
<view class="section-card remark-section">
|
||||
<view class="remark-row">
|
||||
<text class="section-title">买家留言</text>
|
||||
<textarea class="remark-input"
|
||||
<input class="remark-input-compact"
|
||||
v-model="remark"
|
||||
placeholder="选填,请先和商家协商一致"
|
||||
placeholder="选填,给商家留言"
|
||||
maxlength="100" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格明细 -->
|
||||
<view class="price-section">
|
||||
<text class="section-title">价格明细</text>
|
||||
<view class="price-detail">
|
||||
<view class="price-row">
|
||||
<text class="price-label">商品总价</text>
|
||||
<text class="price-value">¥{{ totalAmount.toFixed(2) }}</text>
|
||||
<view class="section-card price-section">
|
||||
<view class="price-grid">
|
||||
<view class="price-item-inline">
|
||||
<text class="price-item-label">商品</text>
|
||||
<text class="price-item-value">¥{{ totalAmount.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="price-row">
|
||||
<text class="price-label">运费</text>
|
||||
<text class="price-value">+¥{{ deliveryFee.toFixed(2) }}</text>
|
||||
<view class="price-item-inline">
|
||||
<text class="price-item-label">运费</text>
|
||||
<text class="price-item-value">+¥{{ deliveryFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view v-if="discountAmount > 0" class="price-row">
|
||||
<text class="price-label">优惠减免</text>
|
||||
<text class="price-value discount">-¥{{ discountAmount.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="price-row total">
|
||||
<text class="price-label">应付金额</text>
|
||||
<text class="price-value total-price">¥{{ actualAmount.toFixed(2) }}</text>
|
||||
<view v-if="discountAmount > 0" class="price-item-inline">
|
||||
<text class="price-item-label">优惠</text>
|
||||
<text class="price-item-value discount-text">-¥{{ discountAmount.toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="safe-area-bottom"></view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部结算栏 -->
|
||||
<view class="bottom-bar">
|
||||
<view class="price-summary">
|
||||
<text class="summary-label">合计:</text>
|
||||
<text class="summary-price">¥{{ actualAmount.toFixed(2) }}</text>
|
||||
<view class="footer-action-bar">
|
||||
<view class="footer-left">
|
||||
<text class="footer-total-label">合计:</text>
|
||||
<text class="footer-currency">¥</text>
|
||||
<text class="footer-price">{{ actualAmount.toFixed(2) }}</text>
|
||||
</view>
|
||||
<button class="submit-btn" @click="submitOrder">提交订单</button>
|
||||
<button class="footer-submit-btn" @click="submitOrder">提交订单</button>
|
||||
</view>
|
||||
|
||||
<!-- 地址选择弹窗 -->
|
||||
@@ -414,10 +418,10 @@ function getObjectKeys(obj: object): string[] {
|
||||
const checkoutItems = ref<Array<CheckoutItemType>>([])
|
||||
const selectedAddress = ref<AddressItem | null>(null)
|
||||
const deliveryOptions = ref<Array<DeliveryOptionType>>([
|
||||
{ id: 'standard', name: '快递配送', price: 8.00, description: '1-3天送达' },
|
||||
{ id: 'express', name: '加急配送', price: 15.00, description: '当天送达' }
|
||||
{ id: 'express', name: '物流快递', price: 8.00, description: '普通快递配送' },
|
||||
{ id: 'local', name: '同城配送', price: 15.00, description: '同城极速上门' }
|
||||
])
|
||||
const selectedDelivery = ref<string>('standard')
|
||||
const selectedDelivery = ref<string>('express')
|
||||
const selectedCoupon = ref<UserCouponType | null>(null)
|
||||
const remark = ref<string>('')
|
||||
const showAddressPopup = ref<boolean>(false)
|
||||
@@ -1427,15 +1431,17 @@ const goToLogin = () => {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #f5f5f5;
|
||||
background-color: #f8f8f8;
|
||||
overflow: hidden;
|
||||
align-items: center; /* PC端居中显示 */
|
||||
}
|
||||
/* 顶部栏 */
|
||||
.checkout-header {
|
||||
background-color: #ffffff;
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
@@ -1448,83 +1454,474 @@ const goToLogin = () => {
|
||||
.checkout-content {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
max-width: 800px; /* 限制PC端内容宽度 */
|
||||
min-height: 0;
|
||||
background-color: #f5f5f5;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
/* 卡片容器 */
|
||||
.no-products {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 30px 0;
|
||||
}
|
||||
.no-products-text { font-size: 14px; color: #999999; }
|
||||
|
||||
.section-card {
|
||||
background-color: #ffffff;
|
||||
margin: 12px;
|
||||
padding: 18px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.02);
|
||||
}
|
||||
|
||||
/* 自适应适配 */
|
||||
@media screen and (min-width: 768px) {
|
||||
.section-card {
|
||||
margin: 16px 0;
|
||||
}
|
||||
.delivery-options-grid {
|
||||
display: flex;
|
||||
flex-direction: row !important;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
.delivery-card {
|
||||
flex: 1;
|
||||
min-width: 280px;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
/* 底部结算栏在大屏居中并限宽 */
|
||||
.footer-action-bar {
|
||||
max-width: 800px;
|
||||
left: 50% !important;
|
||||
right: auto !important;
|
||||
transform: translateX(-50%);
|
||||
border-radius: 16px 16px 0 0;
|
||||
box-shadow: 0 -4px 16px rgba(0,0,0,0.05);
|
||||
}
|
||||
}
|
||||
|
||||
.address-section {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 10px;
|
||||
padding: 20px 15px;
|
||||
}
|
||||
|
||||
.address-icon-wrapper {
|
||||
margin-right: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.address-info { flex: 1; }
|
||||
.address-header { display: flex; align-items: center; margin-bottom: 10px; }
|
||||
.recipient { font-size: 16px; font-weight: bold; color: #333333; margin-right: 15px; }
|
||||
.phone { font-size: 14px; color: #666666; margin-right: 10px; }
|
||||
.default-tag { background-color: #ff4757; padding: 2px 8px; border-radius: 10px; }
|
||||
.tag-text { color: #ffffff; font-size: 12px; }
|
||||
.address-detail { font-size: 14px; color: #333333; line-height: 1.4; }
|
||||
.no-address { flex: 1; display: flex; justify-content: space-between; align-items: center; }
|
||||
.location-icon {
|
||||
font-size: 24px;
|
||||
color: #ff5000;
|
||||
}
|
||||
|
||||
.address-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.address-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.recipient { font-size: 17px; font-weight: bold; color: #333333; margin-right: 12px; }
|
||||
.phone { font-size: 14px; color: #666666; margin-right: 8px; }
|
||||
.default-tag { background-color: #fff0eb; border: 0.5px solid #ff5000; padding: 0 6px; border-radius: 4px; }
|
||||
.tag-text { color: #ff5000; font-size: 11px; }
|
||||
|
||||
.address-detail {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
lines: 2;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.address-arrow-wrapper {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.address-arrow {
|
||||
color: #ccc;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.no-address { flex: 1; display: flex; align-items: center; }
|
||||
.no-address-text { font-size: 16px; color: #999999; }
|
||||
.no-address-arrow { color: #999999; font-size: 18px; }
|
||||
|
||||
.products-section { background-color: #ffffff; margin-bottom: 10px; padding: 0 15px; }
|
||||
.debug-info { background-color: #f8f9fa; padding: 10px 15px; border-bottom: 1px solid #e5e5e5; margin-bottom: 10px; }
|
||||
.debug-text { font-size: 12px; color: #666; text-align: center; }
|
||||
.shop-group { background-color: #fff; margin: 10px 0; border-radius: 12px; padding: 10px; }
|
||||
.shop-header { display: flex; flex-direction: row; align-items: center; padding-bottom: 10px; border-bottom: 1px solid #f0f0f0; }
|
||||
.shop-icon { font-size: 18px; margin-right: 8px; }
|
||||
.shop-name { font-size: 16px; font-weight: bold; color: #333; }
|
||||
.shop-subtotal { display: flex; justify-content: flex-end; align-items: center; padding-top: 10px; margin-top: 5px; border-top: 1px dashed #f0f0f0; font-size: 14px; }
|
||||
.subtotal-label { color: #666; margin-right: 10px; }
|
||||
.subtotal-value { color: #333; }
|
||||
.subtotal-text { color: #333; margin-right: 5px; }
|
||||
.subtotal-price { color: #ff4757; font-weight: bold; font-size: 16px; }
|
||||
.products-section { padding: 0; }
|
||||
.debug-info { padding: 10px 15px; border-bottom: 1px solid #f5f5f5; margin-bottom: 10px; }
|
||||
.debug-text { font-size: 12px; color: #999; text-align: center; }
|
||||
.shop-group { background-color: #fff; padding: 0; }
|
||||
.shop-header { display: flex; flex-direction: row; align-items: center; padding: 5px 0 12px; }
|
||||
.shop-icon { font-size: 17px; margin-right: 6px; }
|
||||
.shop-name { font-size: 15px; font-weight: bold; color: #333; }
|
||||
.shop-subtotal { display: flex; justify-content: flex-end; align-items: center; padding: 12px 0 5px; margin-top: 5px; border-top: 1px dashed #f0f0f0; }
|
||||
.subtotal-label { color: #888; margin-right: 8px; font-size: 13px; }
|
||||
.subtotal-value { color: #666; font-size: 13px; }
|
||||
.subtotal-text { color: #333; margin-right: 5px; font-size: 14px; }
|
||||
.subtotal-price { color: #ff5000; font-weight: bold; font-size: 16px; }
|
||||
|
||||
.product-item { display: flex; padding: 15px 0; border-bottom: 1px solid #f5f5f5; }
|
||||
.product-item:last-child { border-bottom: none; }
|
||||
.product-image { width: 80px; height: 80px; border-radius: 5px; margin-right: 15px; }
|
||||
.product-item { display: flex; flex-direction: row; padding: 12px 0; }
|
||||
.product-image { width: 85px; height: 85px; border-radius: 8px; margin-right: 12px; background-color: #f8f8f8; }
|
||||
.product-info { flex: 1; display: flex; flex-direction: column; justify-content: space-between; }
|
||||
.product-name { font-size: 14px; color: #333333; line-height: 1.4; margin-bottom: 5px; lines: 2; text-overflow: ellipsis; overflow: hidden; }
|
||||
.product-spec { font-size: 12px; color: #999999; margin-bottom: 10px; }
|
||||
.product-bottom { display: flex; justify-content: space-between; align-items: center; }
|
||||
.product-price { font-size: 16px; color: #ff4757; font-weight: bold; }
|
||||
.product-quantity { font-size: 14px; color: #666666; }
|
||||
.product-name-row { display: flex; flex-direction: row; justify-content: space-between; align-items: flex-start; }
|
||||
.product-name { flex: 1; font-size: 14px; color: #333333; line-height: 1.4; lines: 2; text-overflow: ellipsis; overflow: hidden; margin-right: 12px; }
|
||||
.product-price { font-size: 15px; color: #333; font-weight: normal; }
|
||||
.product-spec-row { display: flex; flex-direction: row; justify-content: space-between; align-items: center; margin-bottom: 4px; }
|
||||
.product-spec { font-size: 12px; color: #999999; background-color: #f7f7f7; padding: 2px 6px; border-radius: 4px; }
|
||||
.product-quantity { font-size: 12px; color: #999999; }
|
||||
|
||||
.delivery-section, .coupon-section, .remark-section, .price-section { background-color: #ffffff; margin-bottom: 10px; padding: 15px; }
|
||||
.section-title { font-size: 16px; font-weight: bold; color: #333333; margin-bottom: 15px; }
|
||||
/* 配送方式重构 */
|
||||
.delivery-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.delivery-options { display: flex; flex-direction: column; }
|
||||
.delivery-option { display: flex; align-items: center; justify-content: space-between; padding: 15px; border: 1px solid #e5e5e5; border-radius: 8px; margin-bottom: 10px; }
|
||||
.delivery-option:last-child { margin-bottom: 0; }
|
||||
.delivery-option.selected { border-color: #007aff; background-color: #f0f8ff; }
|
||||
.option-name { font-size: 14px; color: #333333; }
|
||||
.option-price { font-size: 14px; color: #ff4757; font-weight: bold; }
|
||||
.option-selected { color: #007aff; font-size: 16px; }
|
||||
.delivery-selector {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.coupon-info { display: flex; align-items: center; justify-content: space-between; padding: 15px; border: 1px solid #e5e5e5; border-radius: 8px; }
|
||||
.coupon-selected { font-size: 14px; color: #007aff; }
|
||||
.coupon-placeholder { font-size: 14px; color: #999999; }
|
||||
.coupon-arrow { color: #999999; font-size: 16px; }
|
||||
.delivery-pill {
|
||||
padding: 4px 12px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 16px;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.remark-input { width: 100%; min-height: 40px; padding: 10px; border: 1px solid #e5e5e5; border-radius: 8px; font-size: 14px; color: #333333; }
|
||||
.delivery-pill.selected {
|
||||
background-color: #fff9f6;
|
||||
border-color: #ff5000;
|
||||
}
|
||||
|
||||
.price-detail { padding: 15px; background-color: #f8f9fa; border-radius: 8px; }
|
||||
.price-row { display: flex; justify-content: space-between; align-items: center; padding: 8px 0; }
|
||||
.price-row.total { border-top: 1px solid #e5e5e5; margin-top: 8px; padding-top: 15px; }
|
||||
.price-label { font-size: 14px; color: #666666; }
|
||||
.price-value { font-size: 14px; color: #333333; }
|
||||
.price-value.discount { color: #4caf50; }
|
||||
.price-value.total-price { font-size: 18px; color: #ff4757; font-weight: bold; }
|
||||
.pill-name {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.bottom-bar { background-color: #ffffff; padding: 15px; border-top: 1px solid #e5e5e5; display: flex; align-items: center; justify-content: space-between; }
|
||||
.price-summary { display: flex; align-items: flex-end; }
|
||||
.summary-label { font-size: 14px; color: #333333; margin-right: 5px; }
|
||||
.summary-price { font-size: 20px; color: #ff4757; font-weight: bold; }
|
||||
.submit-btn { background-color: #007aff; color: #ffffff; padding: 0 40px; height: 45px; border-radius: 22.5px; font-size: 16px; font-weight: bold; border: none; }
|
||||
.delivery-pill.selected .pill-name {
|
||||
color: #ff5000;
|
||||
}
|
||||
|
||||
.delivery-detail {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding-top: 8px;
|
||||
border-top: 0.5px solid #f9f9f9;
|
||||
}
|
||||
|
||||
.detail-desc {
|
||||
font-size: 11px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.detail-price {
|
||||
font-size: 11px;
|
||||
color: #ff5000;
|
||||
}
|
||||
|
||||
/* 优惠券重构 */
|
||||
.coupon-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.coupon-right-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 留言重构 */
|
||||
.remark-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.remark-input-compact {
|
||||
flex: 1;
|
||||
margin-left: 15px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
/* 价格明细横向排列 */
|
||||
.price-grid {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.price-item-inline {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.price-item-label {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.price-item-value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.item-subtotal-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.item-subtotal-label {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.item-subtotal-price {
|
||||
font-size: 14px;
|
||||
color: #ff5000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 配送方式网格 */
|
||||
.delivery-options-grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.delivery-card {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 10px;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.delivery-card.selected {
|
||||
border-color: #ff5000;
|
||||
background-color: #fff9f6;
|
||||
}
|
||||
|
||||
.option-main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.option-name {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-bottom: 4px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.option-desc {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.option-side {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.option-price {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.select-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-color: #ff5000;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.check-mark {
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
/* 优惠券样式重构 */
|
||||
.coupon-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.coupon-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.coupon-tag {
|
||||
background-color: #ff5000;
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
padding: 1px 4px;
|
||||
border-radius: 2px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.coupon-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.coupon-selected-name {
|
||||
font-size: 14px;
|
||||
color: #ff5000;
|
||||
}
|
||||
|
||||
.coupon-placeholder {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
font-size: 18px;
|
||||
color: #ccc;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
/* 留言输入 */
|
||||
.remark-input-new {
|
||||
width: 100%;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
font-size: 14px;
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
/* 价格明细列表 */
|
||||
.price-list {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.price-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
.price-item-label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.price-item-value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.discount-text {
|
||||
color: #ff5000;
|
||||
}
|
||||
|
||||
.section-title { font-size: 15px; font-weight: bold; color: #333333; }
|
||||
|
||||
/* 底部操作栏 */
|
||||
.footer-action-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 60px;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
border-top: 1px solid #f0f0f0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.footer-left {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.footer-total-label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.footer-currency {
|
||||
font-size: 14px;
|
||||
color: #ff5000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.footer-price {
|
||||
font-size: 22px;
|
||||
color: #ff5000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.footer-submit-btn {
|
||||
background-color: #ff5000;
|
||||
color: #ffffff;
|
||||
padding: 0 28px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
border-radius: 21px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.safe-area-bottom {
|
||||
height: 100px; /* 留出底部操作栏和安全区的空间 */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 弹窗样式 */
|
||||
.address-popup-mask, .address-form-mask, .confirm-popup-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); z-index: 9998; }
|
||||
|
||||
@@ -72,5 +72,48 @@
|
||||
* **日志记录**:接入 **Sentry** 或 **阿里云日志服务**,记录生产环境中的所有前端报错(尤其是支付环节)。
|
||||
* **压力测试**:上线前需进行接口压力测试,确保在促销活动期间数据库连接数不会爆满。
|
||||
|
||||
---
|
||||
|
||||
## 6. 无真机调试指南 (iOS & 鸿蒙调试方案)
|
||||
|
||||
针对您目前没有 iOS 和鸿蒙(HarmonyOS Next)实机的情况,请务必执行以下**模拟调试流程**,以确保上线后 90% 以上的兼容性。
|
||||
|
||||
### A. iOS (苹果) 远程与模拟调试
|
||||
1. **微信开发者工具“模拟器” (最简便)**:
|
||||
* 在工具底部左侧选择 `iPhone 13/14 Pro`。
|
||||
* **重点检查**: 底部 Tabbar 是否被 iPhone 的 Home Indicator (底部黑条) 遮挡。如果是,请在 CSS 中使用 `padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);`。
|
||||
2. **Chrome 浏览器 iOS 仿真 (针对 H5 端)**:
|
||||
* 将项目运行为 H5,开启 Chrome Console (F12)。
|
||||
* 选择 `iPhone` 设备仿真,手动测试 `v-if` 在不同屏幕高度下的布局抖动。
|
||||
3. **免费云真机调试 (推荐)**:
|
||||
* **腾讯云 WeTest / 阿里云移动测试**: 注册后通常有免费试用额度(如 30-60 分钟)。
|
||||
* **操作**: 上传打包好的 APK (Android) 或在微信内测环境下选择 iOS 云真机,远程控制真机屏幕进行滑屏测试。
|
||||
|
||||
### B. 鸿蒙 (HarmonyOS Next) 深度兼容
|
||||
由于鸿蒙系统现在进入了“纯血”阶段,与 Android 差异变大:
|
||||
1. **华为开发者联盟“云调试” (官方推荐)**:
|
||||
* **访问**: [华为远程真机调试](https://developer.huawei.com/consumer/cn/service/jsservicestu/appdebug.html)。
|
||||
* **步骤**:
|
||||
1. 注册并完成实名认证。
|
||||
2. 选择“远程真机”。
|
||||
3. 申请免费使用的 **Mate 60 / Pura 70 (HarmonyOS Next 预览版)**。
|
||||
* **调试重点**: 鸿蒙系统对 Webview 的内核限制较多,务必通过云真机测试“结算页”和“支付弹窗”是否能正常拉起。
|
||||
2. **DevEco Studio 远程模拟器**:
|
||||
* 安装华为官开发的 IDE `DevEco Studio`。
|
||||
* 使用内置的 `Device Manager` 启动 `Remote Emulator`。这比本地模拟器对电脑配置要求低,且渲染效果最接近真机。
|
||||
|
||||
### C. 关键代码兼容性“避坑”建议 (无真机必做)
|
||||
* **日期处理**: 严禁使用 `new Date("2024-03-10")`,在 iOS 上会返回 `Invalid Date`。**必须**统一替换为 `new Date("2024/03/10")` 或 `new Date(2024, 2, 10)`。
|
||||
* **图片显示**: iOS 微信小程序对 WebP 格式支持有限,生产环境生产建议优先使用 **JPG/PNG** 或确保 CDN 开启了自适应转换。
|
||||
* **输入框**: iOS 下 `input` 的 `focus` 自动拉起键盘可能会造成页面整体上移或错位,务必通过云真机确认“下单备注”等输入区域。
|
||||
|
||||
---
|
||||
## 7. 微信小程序上线必改项 (Final Checklist)
|
||||
|
||||
1. **正式 AppID**: 修改 `manifest.json` 中的 `mp-weixin.appid` 为正式 ID。
|
||||
2. **域名白名单**: 在微信后台添加 Supabase API 域名、图片 CDN 域名、物流查询域名。
|
||||
3. **用户隐私政策**: 获取头像、位置等接口前,必须在微信后台配置隐私协议,且在 App 内部提供可见入口。
|
||||
4. **打包优化**: 检查 `unpackage/dist/build/mp-weixin` 的大小,如超过 2MB,必须启用“分包加载”。
|
||||
|
||||
---
|
||||
*生成日期:2026-03-10*
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<view class="shop-header" @click="goToShop">
|
||||
<text class="shop-icon">🏪</text>
|
||||
<text class="shop-name">{{ shopName }}</text>
|
||||
<text class="arrow-right">></text>
|
||||
<text class="arrow-right">›</text>
|
||||
</view>
|
||||
<view v-for="item in orderItems" :key="item.id" class="product-item" @click="goToProduct(item.product_id)">
|
||||
<image :src="item.image_url != null && item.image_url != '' ? item.image_url : '/static/default-product.png'" class="product-image" mode="aspectFill"/>
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
<view class="product-info">
|
||||
<view class="price-section">
|
||||
<text class="current-price">¥{{ product.price }}</text>
|
||||
<text v-if="memberPrice > 0 && memberPrice < product.price" class="member-price-tag">会员价 ¥{{ memberPrice }}</text>
|
||||
<!-- 会员价功能已禁用 -->
|
||||
<!-- <text v-if="memberPrice > 0 && memberPrice < product.price" class="member-price-tag">会员价 ¥{{ memberPrice }}</text> -->
|
||||
<text v-if="product.original_price" class="original-price">¥{{ product.original_price }}</text>
|
||||
</view>
|
||||
<view v-if="memberDiscount > 0" class="member-discount-row">
|
||||
<!-- 会员专享折扣功能已禁用 -->
|
||||
<!-- <view v-if="memberDiscount > 0" class="member-discount-row">
|
||||
<text class="member-discount-text">会员专享 {{ memberDiscount }}折优惠</text>
|
||||
</view>
|
||||
</view> -->
|
||||
<text class="product-name">{{ product.name }}</text>
|
||||
<text class="sales-info">已售{{ product.sales }}件 · 库存{{ product.stock }}件</text>
|
||||
</view>
|
||||
@@ -69,7 +71,7 @@
|
||||
<view class="detail-cell spec-section" @click="showSpecModal" v-if="productSkus.length > 0">
|
||||
<text class="cell-label">规格</text>
|
||||
<view class="cell-content">
|
||||
<text class="spec-selected">{{ selectedSpec ?? '请选择规格' }}</text>
|
||||
<text class="spec-selected">{{ selectedSpec != '' ? selectedSpec : '请选择规格' }}</text>
|
||||
</view>
|
||||
<text class="cell-arrow">❯</text>
|
||||
</view>
|
||||
@@ -135,23 +137,54 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 规格选择弹窗 -->
|
||||
<!-- 规格选择弹窗 (京东风格) -->
|
||||
<view v-if="showSpec" class="spec-modal" @click="hideSpecModal">
|
||||
<view class="spec-content" @click.stop>
|
||||
<view class="spec-header">
|
||||
<text class="spec-title">选择规格</text>
|
||||
<text class="close-btn" @click="hideSpecModal">×</text>
|
||||
<view class="spec-header-jd">
|
||||
<image :src="getSelectedSkuImage()" class="spec-product-img" mode="aspectFill" />
|
||||
<view class="spec-info-jd">
|
||||
<view class="spec-price-row">
|
||||
<text class="price-symbol">¥</text>
|
||||
<text class="price-value">{{ getSelectedSkuPrice() }}</text>
|
||||
</view>
|
||||
<scroll-view class="spec-list" direction="vertical">
|
||||
<text class="spec-stock-jd">库存: {{ getSelectedSkuStock() }}件</text>
|
||||
<text class="spec-choosed-jd">已选: {{ selectedSpec != '' ? selectedSpec : '请选择规格' }}</text>
|
||||
</view>
|
||||
<text class="close-btn-jd" @click="hideSpecModal">×</text>
|
||||
</view>
|
||||
|
||||
<scroll-view class="spec-list-jd" scroll-y="true">
|
||||
<view class="spec-group">
|
||||
<text class="group-title">规格</text>
|
||||
<view class="group-tags">
|
||||
<view v-for="sku in productSkus" :key="sku.id"
|
||||
class="spec-item"
|
||||
class="spec-tag"
|
||||
:class="{ active: selectedSkuId === sku.id }"
|
||||
@click="selectSku(sku)">
|
||||
<text class="spec-name">{{ getSkuSpecText(sku) }}</text>
|
||||
<text class="spec-price">¥{{ sku.price }}</text>
|
||||
<text class="spec-stock">库存{{ sku.stock }}</text>
|
||||
<text class="tag-text">{{ getSkuSpecText(sku) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数量选择移入弹窗内容 -->
|
||||
<view class="spec-quantity-row">
|
||||
<text class="group-title">数量</text>
|
||||
<view class="quantity-selector-jd">
|
||||
<view class="q-btn" @click="decreaseQuantity">
|
||||
<text class="q-btn-text">-</text>
|
||||
</view>
|
||||
<input class="q-input" type="number" :value="quantity.toString()" @input="validateQuantity" />
|
||||
<view class="q-btn" @click="increaseQuantity">
|
||||
<text class="q-btn-text">+</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="spec-footer-jd">
|
||||
<button class="footer-btn cart" @click="addToCart">加入购物车</button>
|
||||
<button class="footer-btn buy" @click="buyNow">立即购买</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -692,7 +725,33 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
uni.hideLoading()
|
||||
},
|
||||
|
||||
getSelectedSkuImage(): string {
|
||||
if (this.selectedSkuId != '') {
|
||||
const sku = this.productSkus.find(s => s.id === this.selectedSkuId)
|
||||
if (sku != null && sku.image_url != null && sku.image_url != '') {
|
||||
return sku.image_url as string
|
||||
}
|
||||
}
|
||||
return this.product.images.length > 0 ? this.product.images[0] : '/static/default-product.png'
|
||||
},
|
||||
|
||||
getSelectedSkuPrice(): string {
|
||||
if (this.selectedSkuId != '') {
|
||||
const sku = this.productSkus.find(s => s.id === this.selectedSkuId)
|
||||
if (sku != null) return sku.price.toFixed(2)
|
||||
}
|
||||
return this.product.price.toFixed(2)
|
||||
},
|
||||
|
||||
getSelectedSkuStock(): number {
|
||||
if (this.selectedSkuId != '') {
|
||||
const sku = this.productSkus.find(s => s.id === this.selectedSkuId)
|
||||
this.showSpecModal()
|
||||
if (sku != null) return sku.stock
|
||||
}
|
||||
return this.product.stock
|
||||
if (success === true) {
|
||||
uni.showToast({ title: '领取成功', icon: 'success' })
|
||||
} else {
|
||||
@@ -723,7 +782,6 @@ export default {
|
||||
selectSku(sku: ProductSkuType) {
|
||||
this.selectedSkuId = sku.id
|
||||
this.selectedSpec = this.getSkuSpecText(sku)
|
||||
this.hideSpecModal()
|
||||
},
|
||||
|
||||
getSkuSpecText(sku: ProductSkuType): string {
|
||||
@@ -746,6 +804,7 @@ export default {
|
||||
|
||||
async addToCart() {
|
||||
if (this.productSkus.length > 0 && (this.selectedSkuId == null || this.selectedSkuId === '')) {
|
||||
this.showSpecModal()
|
||||
uni.showToast({
|
||||
title: '请选择规格',
|
||||
icon: 'none'
|
||||
@@ -766,6 +825,7 @@ export default {
|
||||
|
||||
if (success === true) {
|
||||
uni.showToast({ title: '已添加到购物车', icon: 'success' })
|
||||
this.hideSpecModal()
|
||||
} else {
|
||||
console.error('添加购物车返回失败')
|
||||
uni.showToast({ title: '添加失败,请登录重试', icon: 'none' })
|
||||
@@ -779,6 +839,7 @@ export default {
|
||||
|
||||
buyNow() {
|
||||
if (this.productSkus.length > 0 && (this.selectedSkuId == null || this.selectedSkuId === '')) {
|
||||
this.showSpecModal()
|
||||
uni.showToast({
|
||||
title: '请选择规格',
|
||||
icon: 'none'
|
||||
@@ -1375,70 +1436,200 @@ export default {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
display: flex;
|
||||
justify-content: flex-end; /* UVUE 推荐用 flex 布局对齐 */
|
||||
justify-content: flex-end;
|
||||
flex-direction: column;
|
||||
z-index: 999;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.spec-content {
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
padding: 30rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 1000rpx;
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
.spec-header {
|
||||
.spec-header-jd {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 1rpx solid #f2f2f2;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.spec-title {
|
||||
font-size: 32rpx;
|
||||
.spec-product-img {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-top: -60rpx;
|
||||
background-color: #fff;
|
||||
border: 4rpx solid #fff;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.spec-info-jd {
|
||||
flex: 1;
|
||||
margin-left: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.spec-price-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
color: #fa2c19;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.price-symbol {
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.price-value {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.spec-stock-jd {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.spec-choosed-jd {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.spec-list {
|
||||
flex: 1;
|
||||
.close-btn-jd {
|
||||
font-size: 48rpx;
|
||||
color: #999;
|
||||
position: absolute;
|
||||
right: -10rpx;
|
||||
top: -10rpx;
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
.spec-item {
|
||||
.spec-list-jd {
|
||||
flex: 1;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.spec-group {
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.group-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 24rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.group-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.spec-tag {
|
||||
background-color: #f6f6f6;
|
||||
padding: 16rpx 32rpx;
|
||||
border-radius: 40rpx;
|
||||
margin-right: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border: 2rpx solid #f6f6f6;
|
||||
}
|
||||
|
||||
.spec-tag.active {
|
||||
background-color: #fcedeb;
|
||||
border-color: #fa2c19;
|
||||
}
|
||||
|
||||
.spec-tag.active .tag-text {
|
||||
color: #fa2c19;
|
||||
}
|
||||
|
||||
.tag-text {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.spec-quantity-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.quantity-selector-jd {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-color: #f6f6f6;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.q-btn {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 25rpx 0;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.spec-item.active {
|
||||
background-color: #fff3e0;
|
||||
.q-btn-text {
|
||||
font-size: 36rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.spec-name {
|
||||
flex: 1;
|
||||
.q-input {
|
||||
width: 80rpx;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.spec-price {
|
||||
font-size: 26rpx;
|
||||
color: #ff5000;
|
||||
margin-right: 20rpx;
|
||||
.spec-footer-jd {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 20rpx 0 10rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.spec-stock {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
width: 100rpx;
|
||||
text-align: right;
|
||||
.footer-btn {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
border-radius: 40rpx;
|
||||
margin: 0 10rpx;
|
||||
border: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.footer-btn.cart {
|
||||
background: linear-gradient(90deg, #ffba0d, #ffc30d);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.footer-btn.buy {
|
||||
background: linear-gradient(90deg, #f2140c, #f2270c);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 功能主治样式 */
|
||||
|
||||
@@ -48,13 +48,10 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 主内容区域 -->
|
||||
<scroll-view
|
||||
<!-- 主内容区域:改为普通 view,由页面整体滚动 -->
|
||||
<view
|
||||
v-else
|
||||
direction="vertical"
|
||||
class="main-content"
|
||||
:style="{ height: scrollHeight + 'px' }"
|
||||
@scrolltolower="loadMore"
|
||||
>
|
||||
<!-- 初始状态(无搜索词) -->
|
||||
<view v-if="searchKeyword == '' && showResults == false">
|
||||
@@ -233,12 +230,13 @@
|
||||
|
||||
<!-- 底部安全区域 -->
|
||||
<view class="safe-area"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
|
||||
import { supabaseService } from '@/utils/supabaseService.uts'
|
||||
import type { Product } from '@/utils/supabaseService.uts'
|
||||
|
||||
@@ -251,6 +249,7 @@ const loading = ref(false)
|
||||
const hasMore = ref(true)
|
||||
const isError = ref(false) // 错误状态控制
|
||||
const autoFocus = ref(true)
|
||||
|
||||
const activeSort = ref('default') // 当前排序方式: default, sales, price
|
||||
const priceSortAsc = ref(false) // 价格排序是否为升序
|
||||
|
||||
@@ -474,6 +473,8 @@ const performSearch = async (): Promise<void> => {
|
||||
return
|
||||
}
|
||||
|
||||
console.log('Search execution started for keyword:', keyword)
|
||||
|
||||
let sortBy = 'sales'
|
||||
let ascending = false
|
||||
if (activeSort.value === 'price') {
|
||||
@@ -484,7 +485,9 @@ const performSearch = async (): Promise<void> => {
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('Calling searchProducts with params:', keyword, currentPage.value, sortBy, ascending)
|
||||
const prodResp = await supabaseService.searchProducts(keyword, currentPage.value, 20, sortBy, ascending)
|
||||
console.log('searchProducts response received:', prodResp.data != null ? prodResp.data.length : 0, 'items')
|
||||
|
||||
let shopList: Array<ShopResultType> = []
|
||||
if (currentPage.value === 1 && activeSort.value === 'default') {
|
||||
@@ -539,7 +542,7 @@ const performSearch = async (): Promise<void> => {
|
||||
|
||||
hasMore.value = prodResp.hasmore
|
||||
} catch(e) {
|
||||
console.error('Search failed', e)
|
||||
console.error('Search failed detailed error:', e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
@@ -691,19 +694,18 @@ const loadMore = async (): Promise<void> => {
|
||||
} else if (activeSort.value === 'default') {
|
||||
sortBy = 'default'
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await supabaseService.searchProducts(keyword, currentPage.value, 20, sortBy, ascending)
|
||||
const respData = response.data != null ? response.data : []
|
||||
for (let i: number = 0; i < respData.length; i++) {
|
||||
const p = respData[i] as UTSJSONObject
|
||||
const p = respData[i] as Product
|
||||
let tag = ''
|
||||
const tagsRaw = p.get('tags')
|
||||
const tagsRaw = p.tags
|
||||
if (tagsRaw != null) {
|
||||
try {
|
||||
const tagsStr = p.getString('tags')
|
||||
const tagsStr = p.tags
|
||||
if (tagsStr != null) {
|
||||
const tags = JSON.parse(tagsStr)
|
||||
const tags = JSON.parse(tagsStr as string)
|
||||
if (Array.isArray(tags) && tags.length > 0) {
|
||||
const firstTag = tags[0]
|
||||
tag = firstTag != null ? (firstTag as string) : ''
|
||||
@@ -713,14 +715,14 @@ const loadMore = async (): Promise<void> => {
|
||||
}
|
||||
|
||||
const searchItem: SearchResultType = {
|
||||
id: p.getString('id') ?? '',
|
||||
name: p.getString('name') ?? '',
|
||||
image: p.getString('main_image_url') ?? '/static/default.jpg',
|
||||
price: p.getNumber('base_price') ?? 0,
|
||||
specification: p.getString('specification') ?? '标准规格',
|
||||
id: p.id ?? '',
|
||||
name: p.name ?? '',
|
||||
image: p.main_image_url ?? '/static/default.jpg',
|
||||
price: p.base_price ?? 0,
|
||||
specification: p.specification ?? '标准规格',
|
||||
tag: tag,
|
||||
sales: p.getNumber('sale_count') ?? 0,
|
||||
merchant_id: p.getString('merchant_id') ?? ''
|
||||
sales: p.sale_count ?? 0,
|
||||
merchant_id: p.merchant_id ?? ''
|
||||
}
|
||||
searchResults.value.push(searchItem)
|
||||
}
|
||||
@@ -733,6 +735,12 @@ const loadMore = async (): Promise<void> => {
|
||||
}
|
||||
}
|
||||
|
||||
onReachBottom(() => {
|
||||
if (showResults.value) {
|
||||
loadMore()
|
||||
}
|
||||
})
|
||||
|
||||
const refreshGuessList = () => {
|
||||
uni.showLoading({ title: '刷新中' })
|
||||
setTimeout(() => {
|
||||
@@ -835,6 +843,7 @@ const goBack = () => {
|
||||
background-color: #f5f5f5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh; /* 确保背景色覆盖全屏 */
|
||||
}
|
||||
|
||||
/* 店铺搜索结果 */
|
||||
@@ -913,6 +922,7 @@ const goBack = () => {
|
||||
/* #ifdef APP-PLUS */
|
||||
padding-top: 0; /* 在App端由style动态控制 */
|
||||
/* #endif */
|
||||
flex-shrink: 0; /* 禁止头部被压缩 */
|
||||
}
|
||||
|
||||
.search-bar-container {
|
||||
@@ -920,7 +930,7 @@ const goBack = () => {
|
||||
flex-direction: row; /* UVUE 必须显式设置 row */
|
||||
align-items: center;
|
||||
padding: 10px 16px;
|
||||
width: 100%; /* 确保占满宽度 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
@@ -932,6 +942,7 @@ const goBack = () => {
|
||||
width: 32px; /* 固定宽度防止压缩 */
|
||||
height: 32px;
|
||||
margin-right: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
@@ -1194,16 +1205,30 @@ const goBack = () => {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
width: 48%;
|
||||
width: 48%; /* 手机端 2列 */
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
/* 猜测列表响应式,参照 index.uvue 的 hot-products */
|
||||
@media screen and (min-width: 769px) {
|
||||
.guess-item {
|
||||
width: 32%; /* 平板 3列 */
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1025px) {
|
||||
.guess-item {
|
||||
width: 23%; /* 电脑 4列 */
|
||||
}
|
||||
}
|
||||
|
||||
.guess-img {
|
||||
width: 100%;
|
||||
height: 170px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 8px;
|
||||
background: #f5f5f5;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.guess-name {
|
||||
@@ -1272,110 +1297,86 @@ const goBack = () => {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 搜索结果 */
|
||||
.search-results {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.results-header {
|
||||
display: flex;
|
||||
flex-direction: row; /* UVUE 显式设置 row */
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
flex-wrap: wrap; /* 允许换行以适应小屏 */
|
||||
padding: 10px 12px;
|
||||
background-color: #fff;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.results-title {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.filter-tabs {
|
||||
display: flex;
|
||||
flex-direction: row; /* UVUE 显式设置 row */
|
||||
flex: 1; /* 自适应填充剩余空间 */
|
||||
justify-content: flex-end; /* 靠右对齐 */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.filter-tab {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
padding: 4px 8px; /* 增加点击区域 */
|
||||
margin-left: 16px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 20px;
|
||||
border: 1px solid #e0e0e0;
|
||||
transition: all 0.2s ease;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.filter-tab.active {
|
||||
color: #4CAF50;
|
||||
font-weight: bold; /* REPLACED 500 */
|
||||
background: #ff5000;
|
||||
color: white;
|
||||
border-color: #ff5000;
|
||||
}
|
||||
|
||||
.filter-tab:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 搜索结果列表 */
|
||||
.search-results {
|
||||
padding-bottom: 20px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start; /* 核心修复:确保内容不居中缩进 */
|
||||
}
|
||||
|
||||
.results-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 12px;
|
||||
background-color: #fff;
|
||||
margin-bottom: 2px;
|
||||
width: 100%; /* 核心修复:确保标题栏撑满宽度 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.results-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
/* 响应式布局 */
|
||||
/* 平板设备 (768px以上) */
|
||||
@media screen and (min-width: 768px) {
|
||||
.results-list {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.result-item {
|
||||
width: 32%;
|
||||
}
|
||||
|
||||
.guess-item {
|
||||
width: 24%;
|
||||
}
|
||||
}
|
||||
|
||||
/* 桌面设备 (1024px以上) */
|
||||
@media screen and (min-width: 1024px) {
|
||||
.results-list {
|
||||
padding: 0 24px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.result-item {
|
||||
width: 19%;
|
||||
}
|
||||
|
||||
.guess-item {
|
||||
width: 16%;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
.guess-grid {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* 大屏幕 (1440px以上) */
|
||||
@media screen and (min-width: 1440px) {
|
||||
.result-item {
|
||||
width: 16%;
|
||||
}
|
||||
|
||||
.guess-item {
|
||||
width: 12%;
|
||||
}
|
||||
justify-content: flex-start;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
margin-top: 5px;
|
||||
background-color: #fff; /* 为列表添加背景色 */
|
||||
}
|
||||
|
||||
.result-item {
|
||||
@@ -1384,16 +1385,43 @@ const goBack = () => {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
/* width: calc(50% - 20px); 手机端一行2个 */
|
||||
width: 48%;
|
||||
margin-bottom: 12px;
|
||||
margin-right: 2%;
|
||||
border: 1px solid #f0f0f0; /* 添加微弱边框增加层次感 */
|
||||
}
|
||||
|
||||
/* 电脑端响应式覆盖 - 强制拉伸宽度 */
|
||||
@media screen and (min-width: 1025px) {
|
||||
.main-content {
|
||||
width: 1200px; /* 改为固定宽度或更大百分比 */
|
||||
max-width: 95%;
|
||||
margin: 0 auto;
|
||||
padding: 20px 32px;
|
||||
}
|
||||
|
||||
.result-item {
|
||||
width: 23%; /* 4列布局 */
|
||||
margin-right: 2%;
|
||||
}
|
||||
}
|
||||
|
||||
/* 大桌面端 (1400px以上) */
|
||||
@media screen and (min-width: 1400px) {
|
||||
.result-item {
|
||||
width: 23%; /* 保持一行4个,或者根据需要调整为 18% (一行5个) */
|
||||
}
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 100%;
|
||||
height: 170px;
|
||||
height: 170px; /* 与主页一致 */
|
||||
/* aspect-ratio: 1 / 1; */
|
||||
object-fit: cover;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 8px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
|
||||
@@ -45,9 +45,17 @@
|
||||
|
||||
<!-- 商品列表 -->
|
||||
<view class="product-section">
|
||||
<view class="section-title">全部商品</view>
|
||||
<view class="product-grid">
|
||||
<view v-for="product in products" :key="product.id" class="product-item" @click="goToProduct(product.id)">
|
||||
<view class="results-header">
|
||||
<text class="results-title">全部商品</text>
|
||||
<view class="filter-tabs">
|
||||
<text class="filter-tab active">综合</text>
|
||||
<text class="filter-tab">销量</text>
|
||||
<text class="filter-tab">价格</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="results-list">
|
||||
<view v-for="product in products" :key="product.id" class="result-item" @click="goToProduct(product.id)">
|
||||
<image :src="product.images[0]" class="product-image" mode="aspectFill" />
|
||||
<text class="product-name" :lines="2">{{ product.name }}</text>
|
||||
<view class="product-bottom">
|
||||
@@ -529,63 +537,63 @@ const goToProduct = (id: string) => {
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center; /* 使 PC 端内容居中 */
|
||||
}
|
||||
|
||||
.shop-banner {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
height: 200px; /* PC 端稍微加高一点 */
|
||||
height: 150px;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.shop-info-card {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
padding: 0 15px;
|
||||
margin-top: -30px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.shop-logo {
|
||||
width: 80px; /* PC 端稍微加大 */
|
||||
height: 80px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 8px;
|
||||
border: 2px solid #fff;
|
||||
background-color: #fff;
|
||||
margin-right: 15px;
|
||||
margin-right: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.shop-basic-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 30px;
|
||||
padding-top: 35px;
|
||||
}
|
||||
|
||||
.shop-name {
|
||||
font-size: 22px; /* PC 端字体加大 */
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 6px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.shop-stats {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
font-size: 14px;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
margin-right: 15px;
|
||||
background-color: #f0f0f0;
|
||||
padding: 4px 10px;
|
||||
margin-right: 8px;
|
||||
background-color: #f5f5f5;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@@ -593,22 +601,23 @@ const goToProduct = (id: string) => {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding-top: 30px;
|
||||
padding-top: 40px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
border-radius: 20px;
|
||||
margin-left: 15px;
|
||||
border-radius: 17px;
|
||||
margin-left: 8px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px 24px; /* PC 端按钮加大 */
|
||||
padding: 4px 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.chat-btn {
|
||||
@@ -623,6 +632,7 @@ const goToProduct = (id: string) => {
|
||||
.follow-btn {
|
||||
background-color: #ff5000;
|
||||
border: 1px solid #ff5000;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.follow-btn .action-text {
|
||||
@@ -634,12 +644,70 @@ const goToProduct = (id: string) => {
|
||||
}
|
||||
|
||||
.shop-desc {
|
||||
color: #666;
|
||||
padding: 15px 15px 0;
|
||||
line-height: 1.6;
|
||||
color: #999;
|
||||
padding: 10px 15px 0;
|
||||
line-height: 1.5;
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
box-sizing: border-box;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* PC 端响应式覆盖 */
|
||||
@media screen and (min-width: 1025px) {
|
||||
.shop-header {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.shop-banner {
|
||||
height: 300px;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.shop-info-card {
|
||||
max-width: 1200px;
|
||||
margin-top: -40px;
|
||||
}
|
||||
|
||||
.shop-logo {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.shop-basic-info {
|
||||
padding-top: 45px;
|
||||
}
|
||||
|
||||
.shop-name {
|
||||
font-size: 24px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.shop-stats .stat-item {
|
||||
font-size: 14px;
|
||||
padding: 6px 15px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.shop-actions {
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 8px 24px;
|
||||
margin-left: 15px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.shop-desc {
|
||||
max-width: 1200px;
|
||||
font-size: 14px;
|
||||
padding: 15px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Coupon Styles */
|
||||
@@ -708,67 +776,121 @@ const goToProduct = (id: string) => {
|
||||
}
|
||||
|
||||
.product-section {
|
||||
padding: 20px;
|
||||
padding: 20px 0;
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
.results-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 12px;
|
||||
background-color: #fff;
|
||||
margin-bottom: 2px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.results-title {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20px;
|
||||
padding-left: 10px;
|
||||
border-left: 5px solid #ff5000;
|
||||
}
|
||||
|
||||
.product-grid {
|
||||
.filter-tabs {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.filter-tab {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
padding: 8px 12px;
|
||||
border-radius: 20px;
|
||||
border: 1px solid #e0e0e0;
|
||||
transition: all 0.2s ease;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.filter-tab.active {
|
||||
background: #ff5000;
|
||||
color: white;
|
||||
border-color: #ff5000;
|
||||
}
|
||||
|
||||
.results-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
margin-top: 5px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.product-item {
|
||||
.result-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
width: calc(50% - 10px); /* 默认两列 */
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s;
|
||||
width: 48% !important;
|
||||
margin-bottom: 12px;
|
||||
margin-right: 0 !important;
|
||||
border: 1px solid #f0f0f0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.product-item:nth-child(2n) {
|
||||
margin-right: 0;
|
||||
.result-item:nth-child(2n-1) {
|
||||
margin-right: 4% !important;
|
||||
}
|
||||
|
||||
.product-item:hover {
|
||||
.result-item:nth-child(2n) {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
.result-item:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background: #f5f5f5;
|
||||
height: 170px;
|
||||
object-fit: cover;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
margin: 10px 0;
|
||||
margin-bottom: 5px;
|
||||
line-height: 1.4;
|
||||
height: 40px;
|
||||
height: 36px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding: 0 10px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.product-bottom {
|
||||
@@ -776,20 +898,20 @@ const goToProduct = (id: string) => {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 10px 12px;
|
||||
padding: 0 8px 8px;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
font-size: 18px;
|
||||
font-size: 15px;
|
||||
color: #ff5000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.product-add-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-color: #ff5000;
|
||||
border-radius: 14px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -797,50 +919,50 @@ const goToProduct = (id: string) => {
|
||||
|
||||
.add-icon {
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* PC/Tablet Responsive */
|
||||
@media (min-width: 768px) {
|
||||
.product-item {
|
||||
width: calc(33.33% - 14px) !important;
|
||||
/* 电脑端响应式覆盖 */
|
||||
@media screen and (min-width: 1025px) {
|
||||
.product-section {
|
||||
max-width: 95%;
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.product-item:nth-child(2n) {
|
||||
margin-right: 20px !important;
|
||||
|
||||
.result-item {
|
||||
width: 23%;
|
||||
margin-right: 2% !important;
|
||||
}
|
||||
.product-item:nth-child(3n) {
|
||||
|
||||
.result-item:nth-child(2n) {
|
||||
margin-right: 2% !important;
|
||||
}
|
||||
|
||||
.result-item:nth-child(4n) {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.product-item {
|
||||
width: calc(20% - 16px) !important; /* 五列 */
|
||||
/* 大桌面端 (1400px以上) */
|
||||
@media screen and (min-width: 1400px) {
|
||||
.result-item {
|
||||
width: 23.5%;
|
||||
}
|
||||
.product-item:nth-child(3n) {
|
||||
margin-right: 20px !important;
|
||||
}
|
||||
.product-item:nth-child(5n) {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
.shop-banner {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1025px) {
|
||||
.shop-banner {
|
||||
height: 300px; /* 大屏加宽 Banner */
|
||||
border-radius: 0 0 20px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1440px) {
|
||||
.product-item {
|
||||
width: calc(16.66% - 17px) !important; /* 六列 */
|
||||
}
|
||||
.product-item:nth-child(5n) {
|
||||
margin-right: 20px !important;
|
||||
}
|
||||
.product-item:nth-child(6n) {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
BIN
unpackage/cache/.app-android/class/META-INF/main-1773191396189.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773191396189.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773191936555.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773191936555.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773191962345.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773191962345.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773196067746.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773196067746.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773197281880.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773197281880.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773198208558.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773198208558.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773198782428.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773198782428.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773198998094.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773198998094.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199076148.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199076148.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199117854.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199117854.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199500843.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199500843.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199524286.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199524286.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199823963.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199823963.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199831000.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773199831000.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773200592338.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773200592338.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773200681834.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773200681834.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773201132136.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773201132136.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773201228015.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773201228015.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773201308050.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773201308050.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773202296724.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773202296724.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773202381515.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773202381515.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773202874761.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773202874761.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773202925066.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773202925066.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773202973847.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773202973847.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773203035094.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773203035094.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773203076853.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773203076853.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773204252846.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773204252846.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773204409747.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773204409747.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773204524929.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773204524929.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773210699992.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773210699992.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773210962407.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773210962407.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773211123576.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773211123576.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773212988763.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773212988763.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773213350753.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773213350753.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773213561653.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773213561653.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773213789176.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773213789176.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773214056990.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773214056990.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773217116351.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773217116351.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773217332418.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773217332418.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773217387501.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773217387501.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773218115231.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773218115231.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219025088.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219025088.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219362288.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219362288.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219516607.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219516607.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219626839.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219626839.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219694888.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219694888.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219718609.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219718609.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219780770.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219780770.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219842554.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773219842554.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773220091263.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773220091263.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773220151965.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773220151965.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773220245855.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773220245855.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/META-INF/main-1773220305997.kotlin_module
vendored
Normal file
BIN
unpackage/cache/.app-android/class/META-INF/main-1773220305997.kotlin_module
vendored
Normal file
Binary file not shown.
BIN
unpackage/cache/.app-android/class/ktClasss.ser
vendored
BIN
unpackage/cache/.app-android/class/ktClasss.ser
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user