评论需要添加功能,提交订单有问题

This commit is contained in:
bobobobo
2025-12-26 02:15:32 +08:00
parent 1aab94bbc3
commit bb02cb22c0
32 changed files with 2844 additions and 117 deletions

View File

@@ -1,13 +1,29 @@
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { reactive, ref } from 'vue'
import { PHONE_REGEX } from '@/utils/validate'
import {
addUserAddress,
updateUserAddress,
getUserAddressDetail
} from '@/api'
import { navigateBack } from '@/utils/router'
const props = defineProps({
type: {
type: String,
default: 'add'
}
})
const formRef = ref(null)
const formData = reactive({
id: '',
name: '',
phone: '',
address: '',
/** 省市区选择 */
selectAddress: '',
/** 门牌号 */
houseNum: '',
/** 是否默认地址 */
defaultAddress: false
})
@@ -27,26 +43,60 @@
errorMessage: '手机号不能为空'
},
{
format: 'number',
errorMessage: '手机号只能输入数字'
validateFunction: (rule, value, data, callback) => {
if (!PHONE_REGEX.test(value)) {
callback('手机号格式不正确')
return false
}
return true
}
}
]
},
selectAddress: {
houseNum: {
rules: [
{
required: true,
errorMessage: '所在地区不能为空'
errorMessage: '门牌号不能为空'
}
]
}
}
const submitForm = () => {
formRef.value.validate().then(res => {
console.log(res, '校验通过')
formRef.value.validate().then(async () => {
const data = {
houseNum: formData.houseNum,
name: formData.name,
phone: formData.phone,
address: formData.address,
defaultAddress: formData.defaultAddress ? 1 : 0
}
// updateUserAddress
if (props.type === 'edit') {
await updateUserAddress({ id: formData.id, ...data })
} else {
await addUserAddress(data)
}
navigateBack()
})
}
const getData = async id => {
const { data } = await getUserAddressDetail(id)
formData.id = data.id
formData.name = data.name
formData.phone = data.phone
formData.houseNum = data.houseNum
formData.address = data.address
formData.defaultAddress = data.defaultAddress == 1
}
onLoad(e => {
if (props.type === 'edit') {
getData(e.id)
}
})
</script>
<template>
@@ -75,6 +125,7 @@
:rules="rules"
:modelValue="formData"
label-width="150rpx"
class="address-form"
>
<uni-forms-item label="收件人" required name="name">
<uni-easyinput
@@ -88,10 +139,10 @@
placeholder="请输入手机号"
/>
</uni-forms-item>
<uni-forms-item label="所在地区" required name="selectAddress">
<uni-forms-item label="门牌号" required name="houseNum">
<uni-easyinput
v-model="formData.selectAddress"
placeholder="请选择地区"
v-model="formData.houseNum"
placeholder="请输入门牌号"
/>
</uni-forms-item>
<uni-forms-item label="详细地址" name="address">
@@ -163,5 +214,11 @@
}
}
}
.address-form {
:deep(.uni-easyinput__content) {
border-radius: 34rpx;
}
}
}
</style>

View File

@@ -1,7 +1,11 @@
<script setup></script>
<script setup>
import EditBox from './add.vue'
</script>
<template>
<view class="address-edit">修改地址</view>
<view class="address-edit">
<EditBox type="edit"></EditBox>
</view>
</template>
<style lang="scss" scoped></style>

View File

@@ -1,7 +1,198 @@
<script setup></script>
<script setup>
import { navigateTo } from '@/utils/router'
import { onShow } from '@dcloudio/uni-app'
import { getUserAddress, updateUserAddress, deleteUserAddress } from '@/api'
import { ref } from 'vue'
import { useUI } from '@/utils/use-ui'
const { showDialog, showToast } = useUI()
const listData = ref([])
const getData = async () => {
const res = await getUserAddress({ pageNum: 1, pageSize: 99 })
listData.value = res.rows
}
const onAdd = () => {
navigateTo('/pages/address/add')
}
const onGo = id => {
navigateTo('/pages/address/edit', { id })
}
const onDefault = async item => {
const show = await showDialog('提示', '确定要设为默认地址吗?')
if (show) {
const data = {
id: item.id,
houseNum: item.houseNum,
name: item.name,
phone: item.phone,
address: item.address,
defaultAddress: 1
}
await updateUserAddress(data)
await showToast('设置成功', 'success')
getData()
}
}
const onDelete = async item => {
const show = await showDialog('提示', '确定要删除吗?')
if (show) {
await deleteUserAddress(item.id)
await showToast('删除成功', 'success')
getData()
}
}
onShow(() => {
getData()
})
</script>
<template>
<view class="address-index">地址列表</view>
<view class="address-index">
<nav-bar isTopBg isPlaceholder title="我的地址">
<template #right>
<text class="top-right-name" @click="onAdd">添加地址</text>
</template>
</nav-bar>
<view class="address-list">
<uni-swipe-action>
<uni-swipe-action-item v-for="item in listData" :key="item.id">
<view class="card-box" @click="onGo(item.id)">
<view class="left-box">
<text class="address">{{ item.address }}</text>
<text class="name">{{ item.houseNum }}</text>
<view class="bottom">
<text>{{ item.name }}</text>
<text>{{ item.phone }}</text>
<text
v-if="item.defaultAddress == 1"
class="default-text"
>
默认地址
</text>
</view>
</view>
<uni-icons type="compose" size="20"></uni-icons>
</view>
<template v-slot:right>
<view class="swipe-box">
<view
v-if="item.defaultAddress == 0"
class="btn-box"
@click="onDefault(item)"
>
<uni-icons
type="checkbox"
size="18"
color="#ffffff"
></uni-icons>
<text class="iocn-name">设为默认</text>
</view>
<view class="btn-box" @click="onDelete(item)">
<uni-icons
type="trash"
size="18"
color="#ffffff"
></uni-icons>
<text class="iocn-name">删除</text>
</view>
</view>
</template>
</uni-swipe-action-item>
</uni-swipe-action>
</view>
</view>
</template>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.top-right-name {
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 28rpx;
color: #00d993;
text-align: center;
font-style: normal;
text-transform: none;
}
.address-list {
// padding: 32rpx;
.card-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 22rpx;
border-bottom: 2rpx solid #f4f4f4;
// margin-bottom: 22rpx;
// padding-bottom: 22rpx;
.left-box {
display: flex;
flex-direction: column;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-style: normal;
text-transform: none;
.address {
font-size: 24rpx;
color: #999999;
}
.name {
font-size: 32rpx;
color: #333333;
margin: 10rpx 0;
}
.bottom {
display: flex;
align-items: center;
text + text {
margin-left: 26rpx;
}
text {
font-size: 24rpx;
color: #999999;
}
.default-text {
font-size: 24rpx;
background: #00d993;
color: #ffffff;
padding: 2rpx 6rpx;
border-radius: 8rpx;
}
}
}
}
.swipe-box {
display: flex;
.btn-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: rgb(47, 194, 17);
width: 130rpx;
.iocn-name {
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 28rpx;
color: #fff;
text-align: left;
font-style: normal;
text-transform: none;
}
// 最后一个
&:last-child {
background: rgb(206, 59, 22);
}
}
}
}
</style>

View File

@@ -1,31 +1,20 @@
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { onMounted, ref } from 'vue'
import { onLoad, onUnload } from '@dcloudio/uni-app'
import { ref } from 'vue'
import { reLaunch } from '@/utils/router'
const cb = v => {
console.log(v)
}
// export default {
// data() {
// return {
// title: 'Hello'
// }
// },
// onLoad() {
// },
// methods: {
// }
// }
const indexGo = ref(null)
onLoad(() => {
// 3秒后跳转
setTimeout(() => {
indexGo.value = setTimeout(() => {
reLaunch('/pages/news-list/news-list')
}, 3000)
})
onUnload(() => {
clearTimeout(indexGo.value)
})
const title = ref('这个是启动页')
</script>

186
pages/mall/comment.vue Normal file
View File

@@ -0,0 +1,186 @@
<script setup>
import { ref, reactive } from 'vue'
const topNav = ref([
{ name: '全部', id: '1' },
{ name: '好评(54)', id: '2' },
{ name: '差评(43)', id: '3' },
{ name: '有图(23)', id: '4' }
])
const formData = reactive({
type: '1'
})
</script>
<template>
<view class="comment-box">
<view class="top-options">
<view
v-for="(item, index) in topNav"
:key="index"
:class="{ active: item.id === formData.type }"
class="text"
@click="onTop(item.id)"
>
{{ item.name }}
</view>
</view>
<!-- 卡片位置 -->
<view class="card-box">
<image
src="/static/images/public/random1.png"
mode="scaleToFill"
class="avatar"
></image>
<!-- 右边 -->
<view class="right-box">
<text class="name">名字</text>
<view class="rate-box">
<view class="date">
<text>2022-2-2</text>
<text>重庆市</text>
</view>
<view class="star">
<view class="like">
<uni-icons
type="hand-up"
size="16"
color="#74747480"
></uni-icons>
22
</view>
<uni-icons
type="chat"
size="16"
color="#74747480"
></uni-icons>
</view>
</view>
<text class="content">
视频讲的真好全面升级讲的真的全面老师 徒弟吗
</text>
<view class="img-box">
<image
v-for="item in 5"
src="/static/images/public/random1.png"
mode="scaleToFill"
class="bottom-img"
></image>
</view>
<view class="bottom-content">
<view class="name-box">
<text>名字</text>
<text>内容</text>
</view>
<text class="expand">共三条回复></text>
</view>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
@import './styles/public.scss';
.comment-box {
padding: 32rpx 24rpx;
.card-box {
margin-top: 36rpx;
display: flex;
.avatar {
width: 64rpx;
height: 64rpx;
flex-shrink: 0;
margin-right: 16rpx;
}
.right-box {
width: 100%;
display: flex;
flex-direction: column;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
text-align: left;
font-style: normal;
text-transform: none;
.name {
font-size: 28rpx;
color: #333333;
}
.rate-box {
display: flex;
align-items: center;
justify-content: space-between;
margin: 10rpx 0 20rpx;
.date {
font-weight: 400;
font-size: 24rpx;
color: #74747480;
text {
&:first-child {
margin-right: 20rpx;
}
}
}
.star {
display: flex;
align-items: center;
.like {
display: flex;
align-items: center;
font-weight: 400;
font-size: 22rpx;
color: #74747480;
margin-right: 86rpx;
}
}
}
.content {
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
.img-box {
margin-top: 16rpx;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 16rpx;
.bottom-img {
width: 128rpx;
height: 128rpx;
}
}
.bottom-content {
margin-top: 32rpx;
background: #f9f9f9;
border-radius: 8rpx;
padding: 0 16rpx 16rpx;
font-family: PingFang SC, PingFang SC;
font-style: normal;
text-transform: none;
.name-box {
margin-top: 16rpx;
text {
font-weight: 400;
font-size: 28rpx;
color: #333333;
&:last-child {
font-weight: 500;
font-size: 28rpx;
color: #999999;
}
}
}
.expand {
display: block;
margin-top: 14rpx;
font-weight: 400;
font-size: 24rpx;
color: #00d993;
}
}
}
}
}
</style>

View File

@@ -1,5 +1,5 @@
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { getProductDetail } from '@/api/mall'
import { reactive, ref } from 'vue'
import { formatRMB } from '@/utils'
@@ -24,16 +24,33 @@
/** 可选数量 */
maxNum: 1
})
/** 顶部地址信息 */
const topRessData = reactive({
name: '',
houseNum: '',
id: '',
phone: '',
state: false,
loading: true
})
/** 获取用户地址 */
const userRess = async () => {
const res = await getUserAddress()
console.log(res)
topRessData.loading = true
const res = await getUserAddress({ pageNum: 1, pageSize: 99 }, false)
const data = res.rows.find(v => v.defaultAddress == 1)
console.log(data, '地址数据===')
topRessData.state = !data?.id
topRessData.name = data?.name || ''
topRessData.houseNum = data?.houseNum || ''
topRessData.id = data?.id || ''
topRessData.phone = data?.phone || ''
topRessData.loading = false
}
/** 用户地址跳转 */
const onRess = () => {
navigateTo('/pages/address/add')
navigateTo('/pages/address/index')
}
const getData = async productId => {
@@ -46,6 +63,7 @@
formData.spec = id
priceData.value = price
formData.total = price
console.log('111111111111111111111')
}
/** 数量切换 */
@@ -63,10 +81,20 @@
}
// 提交订单
const onConfirm = () => {}
const onConfirm = () => {
const data = {
addressId: topRessData.id,
productId: viewData.value.id,
quantity: formData.num
}
console.log(data, '提交订单')
}
onShow(() => {
userRess()
})
onLoad(async e => {
await userRess()
await getData(e.productId)
})
</script>
@@ -75,16 +103,16 @@
<view class="mall-confirm-order">
<!-- 地址 -->
<view class="address-box" @click="onRess">
<view class="left-name">
<text class="adres">重庆沙坪坝龙湖光年4号楼3009</text>
<text v-if="topRessData.state" class="wu-adres">
暂无收货/默认地址(点击添加)
</text>
<view v-else class="left-name">
<text class="adres">{{ topRessData.houseNum }}</text>
<view class="bottom-name">
<text>名字</text>
<text>137******</text>
<text>{{ topRessData.name }}</text>
<text>{{ topRessData.phone }}</text>
</view>
</view>
<!-- <text class="wu-adres">
暂无收货地址(点击添加)
</text> -->
<image
src="/static/images/public/right-arrow.png"
mode="heightFix"

View File

@@ -1,16 +1,28 @@
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { getProductDetail } from '@/api/mall'
import { getProductDetail, getProductCommentList } from '@/api/mall'
import { ref, computed } from 'vue'
import { navigateTo } from '@/utils/router'
const viewData = ref({})
const productId = ref('')
/** 评论数量 */
const commentNum = ref(0)
const getData = async productId => {
const res = await getProductDetail(productId)
viewData.value = res.data
}
/** 评论数量获取 */
const getComment = async productId => {
const res = await getProductCommentList({
productId,
pageNum: 1,
pageSize: 1
})
commentNum.value = res.total
}
/** 拼单人数 */
const getPeople = computed(() => {
if (!viewData.value.groupActivities?.length) return 0
@@ -31,9 +43,10 @@
})
}
onLoad(e => {
onLoad(async e => {
productId.value = e.productId
getData(e.productId)
await getData(e.productId)
await getComment(e.productId)
})
</script>
@@ -106,6 +119,22 @@
<button>去拼单</button>
</view>-->
<!-- 评论入口 -->
<view
class="comment-box"
@click="navigateTo('/pages/mall/comment', { productId })"
>
<text class="comment-name">评论({{ commentNum }})</text>
<view class="right-box">
<text>查看全部</text>
<image
src="/static/images/public/right-arrow.png"
mode="heightFix"
class="right-img"
></image>
</view>
</view>
<!-- 商品详情 -->
<view class="detail-content">
<text class="title">商品详情</text>
@@ -233,8 +262,8 @@
}
.detail-content {
border-top: 2rpx solid #f9f9f9;
padding-top: 46rpx;
margin-top: 46rpx;
padding-top: 20rpx;
margin-top: 20rpx;
.title {
margin-bottom: 16rpx;
font-weight: 500;
@@ -246,5 +275,33 @@
width: 100%;
}
}
.comment-box {
border-top: 2rpx solid #f9f9f9;
padding-top: 20rpx;
margin-top: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-style: normal;
text-transform: none;
.comment-name {
font-size: 28rpx;
color: #333333;
}
.right-box {
display: flex;
align-items: center;
text {
font-size: 28rpx;
color: #999999;
margin-right: 8rpx;
}
.right-img {
height: 32rpx;
}
}
}
}
</style>

View File

@@ -84,42 +84,10 @@
</template>
<style lang="scss" scoped>
@import './styles/public.scss';
.mall-list {
.top-box {
padding: 24rpx;
.top-options {
overflow: hidden;
margin-top: 32rpx;
margin-bottom: 8rpx;
display: flex;
flex-direction: row;
white-space: nowrap; /* 重要:防止换行 */
-webkit-overflow-scrolling: touch; /* iOS 平滑滚动 */
.text + .text {
margin-left: 16rpx;
}
.text {
flex-shrink: 0;
padding: 8rpx 16rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 28rpx;
color: #999999;
text-align: center;
font-style: normal;
text-transform: none;
background: #f4f4f4;
border-radius: 64rpx;
box-sizing: border-box;
}
.active {
padding: 6rpx 14rpx;
border-radius: 64rpx;
border: 2rpx solid #00d993;
color: #00d993;
}
}
}
.card-list {

View File

@@ -78,11 +78,10 @@
color: #333333;
display: -webkit-box;
display: box;
-webkit-box-orient: vertical;
box-orient: vertical;
-webkit-line-clamp: 2;
line-clamp: 2; /* 添加标准属性 */
line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;

View File

@@ -0,0 +1,33 @@
.top-options {
overflow: hidden;
margin-top: 32rpx;
margin-bottom: 8rpx;
display: flex;
flex-direction: row;
white-space: nowrap; /* 重要:防止换行 */
-webkit-overflow-scrolling: touch; /* iOS 平滑滚动 */
.text + .text {
margin-left: 16rpx;
}
.text {
flex-shrink: 0;
padding: 8rpx 16rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 28rpx;
color: #999999;
text-align: center;
font-style: normal;
text-transform: none;
background: #f4f4f4;
border-radius: 64rpx;
box-sizing: border-box;
}
.active {
padding: 6rpx 14rpx;
border-radius: 64rpx;
border: 2rpx solid #00d993;
color: #00d993;
}
}