consumer模块完成度95%,完成部署消费者端(外网可访问consumer.meitizs.com),消费者小程序能正常运行在微信开发者工具上
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
<!-- 评价页面 -->
|
||||
<template>
|
||||
<view class="review-page">
|
||||
<!-- 顶部栏 -->
|
||||
<!-- 顶部栏:已移除“发表评价”文字 -->
|
||||
<view class="review-header">
|
||||
<text class="back-btn" @click="goBack">‹</text>
|
||||
<text class="header-title">评价商品</text>
|
||||
<view class="header-back" @click="goBack">
|
||||
<image class="back-icon" src="/static/icons/back.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="header-title-placeholder"></view>
|
||||
<view class="header-right"></view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="review-content" direction="vertical">
|
||||
@@ -145,7 +148,6 @@
|
||||
<script setup lang="uts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import supa from '@/components/supadb/aksupainstance.uts'
|
||||
import { supabaseService } from '@/utils/supabaseService.uts'
|
||||
|
||||
type OrderType = {
|
||||
@@ -195,72 +197,58 @@ const isSubmitting = ref<boolean>(false)
|
||||
|
||||
const loadOrderData = async (): Promise<void> => {
|
||||
try {
|
||||
const orderRes = await supa
|
||||
.from('ml_orders')
|
||||
.select('*')
|
||||
.eq('id', orderId.value)
|
||||
.single()
|
||||
.execute()
|
||||
|
||||
if (orderRes.error != null) {
|
||||
console.error('加载订单失败:', orderRes.error)
|
||||
return
|
||||
}
|
||||
|
||||
if (orderRes.data != null) {
|
||||
const orderData = orderRes.data as UTSJSONObject
|
||||
order.value = {
|
||||
id: orderData.getString('id') ?? '',
|
||||
order_no: orderData.getString('order_no') ?? '',
|
||||
created_at: orderData.getString('created_at') ?? '',
|
||||
merchant_id: orderData.getString('merchant_id') ?? ''
|
||||
} as OrderType
|
||||
}
|
||||
|
||||
const itemsRes = await supa
|
||||
.from('ml_order_items')
|
||||
.select(`
|
||||
*,
|
||||
product:product_id(images)
|
||||
`)
|
||||
.eq('order_id', orderId.value)
|
||||
.execute()
|
||||
|
||||
if (itemsRes.error != null) {
|
||||
console.error('加载订单商品失败:', itemsRes.error)
|
||||
return
|
||||
}
|
||||
|
||||
const rawData = itemsRes.data
|
||||
let itemsArray: Array<any> = []
|
||||
if (rawData != null) {
|
||||
itemsArray = rawData as Array<any>
|
||||
}
|
||||
console.log('[loadOrderData] 开始加载订单数据, orderId:', orderId.value)
|
||||
|
||||
const processedItems: Array<OrderItemType> = []
|
||||
for (let i: number = 0; i < itemsArray.length; i++) {
|
||||
const item = itemsArray[i] as UTSJSONObject
|
||||
const productObjRaw = item.get('product')
|
||||
const productObj = (productObjRaw != null) ? (productObjRaw as UTSJSONObject) : null
|
||||
const imagesArrRaw = (productObj != null) ? productObj.get('images') : null
|
||||
const imagesArr = (imagesArrRaw != null) ? (imagesArrRaw as Array<string>) : []
|
||||
const firstImage = (imagesArr.length > 0) ? imagesArr[0] : '/static/default-product.png'
|
||||
const skuSpecRaw = item.get('sku_specifications')
|
||||
const skuSpec = (skuSpecRaw != null) ? (skuSpecRaw as any) : null
|
||||
const processedItem: OrderItemType = {
|
||||
id: (item.getNumber('id') ?? 0) as number,
|
||||
order_id: (item.getNumber('order_id') ?? 0) as number,
|
||||
product_id: (item.getNumber('product_id') ?? 0) as number,
|
||||
product_name: item.getString('product_name') ?? '',
|
||||
price: (item.getNumber('price') ?? 0) as number,
|
||||
quantity: (item.getNumber('quantity') ?? 1) as number,
|
||||
sku_specifications: skuSpec,
|
||||
product_image: firstImage
|
||||
}
|
||||
processedItems.push(processedItem)
|
||||
// 使用 supabaseService 获取订单详情
|
||||
const orderDetailRaw = await supabaseService.getOrderDetail(orderId.value)
|
||||
console.log('[loadOrderData] orderDetailRaw:', JSON.stringify(orderDetailRaw))
|
||||
|
||||
if (orderDetailRaw == null) {
|
||||
console.error('加载订单失败: 未找到订单')
|
||||
uni.showToast({ title: '订单不存在', icon: 'none' })
|
||||
return
|
||||
}
|
||||
orderItems.value = processedItems
|
||||
|
||||
// 转换为 UTSJSONObject
|
||||
const orderDetail = JSON.parse(JSON.stringify(orderDetailRaw)) as UTSJSONObject
|
||||
|
||||
// 解析订单基本信息
|
||||
order.value = {
|
||||
id: orderDetail.getString('id') ?? '',
|
||||
order_no: orderDetail.getString('order_no') ?? '',
|
||||
created_at: orderDetail.getString('created_at') ?? '',
|
||||
merchant_id: orderDetail.getString('merchant_id') ?? ''
|
||||
} as OrderType
|
||||
|
||||
// 解析订单商品
|
||||
const itemsRaw = orderDetail.get('ml_order_items')
|
||||
console.log('[loadOrderData] itemsRaw:', JSON.stringify(itemsRaw))
|
||||
|
||||
if (itemsRaw != null) {
|
||||
const itemsList = itemsRaw as any[]
|
||||
const processedItems: Array<OrderItemType> = []
|
||||
|
||||
for (let i: number = 0; i < itemsList.length; i++) {
|
||||
const itemStr = JSON.stringify(itemsList[i])
|
||||
const item = JSON.parse(itemStr) as UTSJSONObject
|
||||
const skuSpec = item.get('sku_specifications')
|
||||
|
||||
processedItems.push({
|
||||
id: (item.getNumber('id') ?? 0) as number,
|
||||
order_id: (item.getNumber('order_id') ?? 0) as number,
|
||||
product_id: (item.getNumber('product_id') ?? 0) as number,
|
||||
product_name: item.getString('product_name') ?? '',
|
||||
price: (item.getNumber('price') ?? 0) as number,
|
||||
quantity: (item.getNumber('quantity') ?? 1) as number,
|
||||
sku_specifications: skuSpec,
|
||||
product_image: item.getString('product_image') ?? item.getString('image_url') ?? '/static/default-product.png'
|
||||
} as OrderItemType)
|
||||
}
|
||||
orderItems.value = processedItems
|
||||
console.log('[loadOrderData] processedItems count:', processedItems.length)
|
||||
}
|
||||
|
||||
// 初始化评价数据
|
||||
const count = orderItems.value.length
|
||||
const newRatings: Array<number> = []
|
||||
const newContents: Array<string> = []
|
||||
@@ -274,23 +262,25 @@ const loadOrderData = async (): Promise<void> => {
|
||||
contents.value = newContents
|
||||
images.value = newImages
|
||||
|
||||
const orderObj = order.value as UTSJSONObject
|
||||
const merchantId = orderObj.getString('merchant_id')
|
||||
if (merchantId != null && merchantId !== '') {
|
||||
const merchantRes = await supa
|
||||
.from('ml_shops')
|
||||
.select('id, shop_name, rating')
|
||||
.eq('id', merchantId)
|
||||
.single()
|
||||
.execute()
|
||||
|
||||
if (merchantRes.error == null && merchantRes.data != null) {
|
||||
merchant.value = merchantRes.data as MerchantType
|
||||
// 获取商家信息
|
||||
const orderObj = order.value
|
||||
if (orderObj != null) {
|
||||
const merchantId = orderObj.merchant_id
|
||||
if (merchantId != '') {
|
||||
const shopInfo = await supabaseService.getShopByMerchantId(merchantId)
|
||||
if (shopInfo != null) {
|
||||
merchant.value = {
|
||||
id: shopInfo.id,
|
||||
shop_name: shopInfo.shop_name,
|
||||
rating: shopInfo.rating_avg ?? 5
|
||||
} as MerchantType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error('加载订单数据异常:', err)
|
||||
uni.showToast({ title: '加载失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,10 +312,19 @@ const formatTime = (timeStr?: string): string => {
|
||||
|
||||
const getSpecText = (specs: any | null): string => {
|
||||
if (specs == null) return ''
|
||||
if (specs instanceof UTSJSONObject) {
|
||||
return '规格信息'
|
||||
if (typeof specs === 'string') return specs as string
|
||||
|
||||
try {
|
||||
const specObj = JSON.parse(JSON.stringify(specs)) as UTSJSONObject
|
||||
const jsonStr = JSON.stringify(specObj)
|
||||
if (jsonStr == '{}' || jsonStr == 'null') return ''
|
||||
|
||||
// 简单解析:直接返回 JSON 字符串(去除大括号)
|
||||
const cleanStr = jsonStr.replace(/^\{|\}$/g, '').replace(/"/g, '').replace(/:/g, ': ').replace(/,/g, '; ')
|
||||
return cleanStr
|
||||
} catch (e) {
|
||||
return ''
|
||||
}
|
||||
return specs as string
|
||||
}
|
||||
|
||||
// 获取评分文本
|
||||
@@ -548,23 +547,37 @@ const goBack = (): void => {
|
||||
|
||||
.review-header {
|
||||
background-color: #ffffff;
|
||||
padding: 15px;
|
||||
padding: 10px 15px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.header-back {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
font-size: 24px;
|
||||
color: #333333;
|
||||
padding: 5px;
|
||||
margin-right: 15px;
|
||||
.back-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
.header-title-placeholder {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 44px;
|
||||
}
|
||||
|
||||
.review-content {
|
||||
@@ -632,39 +645,46 @@ const goBack = (): void => {
|
||||
|
||||
.rating-section {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 20px;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.rating-label {
|
||||
font-size: 14px;
|
||||
font-size: 15px;
|
||||
color: #333333;
|
||||
margin-right: 15px;
|
||||
font-weight: 500;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.rating-stars {
|
||||
display: flex;
|
||||
/* gap: 10px; removed */
|
||||
}
|
||||
|
||||
.rating-stars.small {
|
||||
/* gap: 5px; removed */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.star-icon {
|
||||
font-size: 24px;
|
||||
color: #cccccc;
|
||||
margin-right: 10px;
|
||||
font-size: 26px;
|
||||
margin-right: 8px;
|
||||
color: #e0e0e0;
|
||||
transition: transform 0.1s ease;
|
||||
}
|
||||
|
||||
.star-icon.active {
|
||||
color: #ff5000;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.rating-text {
|
||||
margin-left: 15px;
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
color: #999999;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.rating-stars.small {
|
||||
/* gap: 5px; removed */
|
||||
}
|
||||
|
||||
.content-section {
|
||||
@@ -783,28 +803,49 @@ const goBack = (): void => {
|
||||
|
||||
.merchant-section {
|
||||
background-color: #ffffff;
|
||||
padding: 15px;
|
||||
margin-bottom: 10px;
|
||||
padding: 20px 15px;
|
||||
margin-top: 15px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
/* display: block; removed */
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 20px;
|
||||
padding-left: 10px;
|
||||
border-left: 4px solid #ff5000;
|
||||
}
|
||||
|
||||
.merchant-rating {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 20px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.rating-item {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
color: #666666;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.merchant-rating .rating-stars.small {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.merchant-rating .rating-stars.small .star-icon {
|
||||
font-size: 20px;
|
||||
margin-right: 5px;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.merchant-rating .rating-stars.small .star-icon.active {
|
||||
color: #ff5000;
|
||||
}
|
||||
|
||||
.tips-section {
|
||||
|
||||
Reference in New Issue
Block a user