增加支付结果页,搜索页,地址编辑页,收货地址页,活动商品页等页面

master
wyy 2 years ago
parent 30648951bc
commit 1277f51bf9

@ -0,0 +1,67 @@
.prod-items {
width: 43%;
background: #fff;
margin-bottom: 40rpx;
box-sizing: border-box;
.hot-imagecont {
border-radius: 8rpx;
text-align: center;
font-size: 0;
}
.hot-text {
margin-top: 20rpx;
.prod-info {
font-size: 20rpx;
color: #777;
padding: 0 20rpx;
margin-top: 8rpx;
}
.prod-text-info {
position: relative;
height: 50rpx;
line-height: 70rpx;
font-family: Arial;
.price {
color: #eb2444;
padding-left: 20rpx;
}
}
}
}
prod {
&:nth-child(2n-1) {
.prod-items {
padding: 20rpx 10rpx 10rpx 20rpx;
}
}
&:nth-child(2n) {
.prod-items {
padding: 20rpx 20rpx 10rpx 10rpx;
}
}
}
.hot-imagecont {
.hotsaleimg {
width: 100%;
height: 345rpx;
}
}
.hot-text {
.hotprod-text {
height: 76rpx;
font-size: 28rpx;
display: -webkit-box;
word-break: break-all;
padding: 0 20rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
color: #000;
}
}
.deadline-price {
font-size: 22rpx;
margin-right: 5rpx;
}

@ -0,0 +1,73 @@
<template>
<view
class="prod-items"
:data-prodid="item.prodId"
@tap="toProdPage"
>
<view class="hot-imagecont">
<image
:src="item.pic"
class="hotsaleimg"
/>
</view>
<view class="hot-text">
<view class="hotprod-text">
{{ item.prodName }}
</view>
<view
v-if="sts===6"
class="prod-info"
>
{{ item.prodCommNumber }}评价 {{ item.positiveRating }}%好评
</view>
<view class="prod-text-info">
<view class="price">
<text
v-if="sts===2"
class="deadline-price"
>
限时价
</text>
<text class="symbol">
</text>
<text class="big-num">
{{ wxs.parsePrice(item.price)[0] }}
</text>
<text class="small-num">
.{{ wxs.parsePrice(item.price)[1] }}
</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
const wxs = number()
// eslint-disable-next-line no-unused-vars
const props = defineProps({
item: {
type: Object,
default: () => {
return null
}
},
sts: {
type: Number,
default: () => {
return 2
}
}
})
const toProdPage = (e) => {
const prodid = e.currentTarget.dataset.prodid
uni.navigateTo({
url: '/pages/prod/prod?prodid=' + prodid
})
}
</script>
<style scoped lang="scss">
@use './production.scss';
</style>

@ -38,15 +38,31 @@
"path": "pages/sub-category/sub-category"
},
{
"path": "pages/accountLogin/accountLogin"
"path": "pages/search-page/search-page",
"style": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "搜索",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
}
},
{
"path": "pages/register/register"
"path": "pages/delivery-address/delivery-address",
"style": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "收货地址",
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/prod/prod",
"path": "pages/editAddress/editAddress",
"style": {
"navigationBarTitleText": "商品详情"
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "编辑收货地址",
"navigationBarTextStyle": "black"
}
},
{
@ -67,6 +83,24 @@
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/submit-order/submit-order",
"style": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "提交订单",
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/express-delivery/express-delivery",
"style": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "物流查询",
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/pay-result/pay-result",
"style": {
@ -75,6 +109,51 @@
"navigationBarTitleText": "支付结果",
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/search-prod-show/search-prod-show",
"style": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "搜索结果",
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/prod/prod",
"style": {
"navigationBarTitleText": "商品详情"
}
},
{
"path": "pages/prod-classify/prod-classify",
"style": {
"onReachBottomDistance": 0
}
},
{
"path": "pages/recent-news/recent-news",
"style": {
"backgroundTextStyle": "light",
"navigationBarTitleText": "最新公告",
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#fafafa"
}
},
{
"path": "pages/news-detail/news-detail",
"style": {
"backgroundTextStyle": "light",
"navigationBarTitleText": "最新公告",
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#fafafa"
}
},
{
"path": "pages/accountLogin/accountLogin"
},
{
"path": "pages/register/register"
}
],
"tabBar": {

@ -1,15 +1,11 @@
.container {
width: 100%;
background: #f4f4f4;
padding-bottom: 118rpx;
min-height: calc(100vh - 118rpx);
}
container {
.prod-list {
padding-bottom: 118rpx;
width: 100%;
background: #f8f8f8;
}
}
.prod-list {
.prod-block {
background: #fff;
margin-top: 15rpx;
@ -267,7 +263,8 @@ container {
}
}
}
checkbox {
:deep(checkbox) {
.uni-checkbox-input,
.wx-checkbox-input {
border-radius: 50%;
width: 35rpx;

@ -105,12 +105,12 @@
class="cart-footer"
>
<view class="btn all">
<label @tap="onSelAll">
<checkbox
:checked="allChecked"
color="#f7d731;"
@tap="onSelAll"
/>
全选</label>
全选
</view>
<view
class="btn del"
@ -221,8 +221,7 @@ const toFirmOrder = () => {
* 全选
*/
const onSelAll = () => {
let allCheckedParam = allChecked.value
allCheckedParam = !allCheckedParam //
const allCheckedParam = !allChecked.value //
const shopCartItemDiscountsParam = shopCartItemDiscounts.value
for (let i = 0; i < shopCartItemDiscountsParam.length; i++) {
const cItems = shopCartItemDiscountsParam[i].shopCartItems

@ -7,8 +7,7 @@
position: fixed;
display: flex;
overflow: hidden;
margin-top: 100rpx;
height: calc(100% - 100rpx);
height: 100%;
}
.search-bar {
width: 100%;

@ -7,7 +7,7 @@
@tap="toSearchPage"
>
<image
src="/static/images/icon/search.png"
src="@/static/images/icon/search.png"
class="search-img"
/>
<text class="sear-input">

@ -0,0 +1,93 @@
.container {
background-color: #f4f4f4;
border-top: 2rpx solid #e9eaec;
min-height: 100vh;
}
.main {
margin-top: 20rpx;
padding-bottom: 150rpx;
}
.address {
margin-bottom: 15rpx;
width: 100%;
background-color: #fff;
border-bottom: 2rpx solid #e9eaec;
.personal {
position: relative;
padding: 20rpx 30rpx;
border-bottom: 3rpx dashed #e9eaec;
.info-tit {
.name {
margin-right: 30rpx;
font-size: 32rpx;
display: inline-block;
}
.tel {
font-size: 30rpx;
}
image {
position: absolute;
right: 30rpx;
top: 46rpx;
width: 40rpx;
height: 40rpx;
margin-left: 50rpx;
vertical-align: middle;
}
}
}
.select-btn {
padding: 15rpx 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
.box {
font-size: 26rpx;
}
}
}
.personal {
.addr {
font-size: 26rpx;
margin: 10rpx 0;
margin-top: 20rpx;
.addr-get {
display: inline-block;
color: #999;
width: 100%;
word-break: break-word;
}
}
}
.footer {
position: fixed;
bottom: 0;
width: 100%;
height: 100rpx;
line-height: 100rpx;
text-align: center;
background-color: #fff;
box-shadow: 0 -1rpx 8rpx rgba(0, 0, 0, 0.05);
text {
font-size: 32rpx;
color: #eb2444;
}
}
.empty {
.img {
text-align: center;
margin-top: 130rpx;
image {
width: 100rpx;
height: 100rpx;
display: block;
margin: auto;
}
}
.txt {
margin-top: 30rpx;
font-size: 24rpx;
text-align: center;
color: #999;
}
}

@ -0,0 +1,160 @@
<template>
<view class="container">
<view class="main">
<view
v-if="addressList.length===0"
class="empty"
>
<view class="img">
<image src="http://jiales.gz-yami.com/addr.png" />
</view>
<view class="txt">
您还没有收货地址
</view>
</view>
<radio-group class="radio-group">
<block
v-for="(item, index) in addressList"
:key="index"
>
<view class="address">
<view
class="personal"
@tap="selAddrToOrder(item)"
>
<view class="info-tit">
<text class="name">
{{ item.receiver }}
</text>
<text class="tel">
{{ item.mobile }}
</text>
<image
src="@/static/images/icon/revise.png"
:data-addrid="item.addrId"
@tap.stop="toEditAddress"
/>
</view>
<view class="addr">
<text class="addr-get">
{{ item.province }}{{ item.city }}{{ item.area }}{{ item.addr }}
</text>
</view>
</view>
<view
class="select-btn"
:data-addrid="item.addrId"
@tap="onDefaultAddr"
>
<view class="box">
<radio
:value="item.prodId"
:checked="item.commonAddr==1"
color="#eb2444"
:data-addrid="item.addrId"
@tap="onDefaultAddr"
/>
设为默认地址
</view>
</view>
</view>
</block>
</radio-group>
</view>
<view
class="footer"
@tap="onAddAddr"
>
<text>新增收货地址</text>
</view>
</view>
</template>
<script setup>
const order = ref(-1)
onLoad((option) => {
if (option.order) {
order.value = option.order
}
})
const addressList = ref([])
/**
* 加载地址列表
*/
onShow(() => {
onGetList()
})
/**
* 获取收获列表接口
*/
const onGetList = () => {
uni.showLoading()
http.request({
url: '/p/address/list',
method: 'GET'
})
.then(({ data }) => {
addressList.value = data
uni.hideLoading()
})
}
/**
* 新增收货地址
*/
const onAddAddr = () => {
uni.navigateTo({
url: '/pages/editAddress/editAddress'
})
}
/**
* 设置为默认地址
*/
const onDefaultAddr = (e) => {
const addrId = e.currentTarget.dataset.addrid
uni.showLoading()
http.request({
url: '/p/address/defaultAddr/' + addrId,
method: 'PUT',
data: {
addrId
}
})
.then(() => {
uni.hideLoading()
})
}
/**
* 修改地址
*/
const toEditAddress = (e) => {
const addrId = e.currentTarget.dataset.addrid
uni.navigateTo({
url: '/pages/editAddress/editAddress?addrId=' + addrId
})
}
/**
* 选择地址 跳转回提交订单页
*/
const selAddrToOrder = (item) => {
if (order.value == 0) {
const pages = getCurrentPages() //
const prevPage = pages[pages.length - 2] //
prevPage.item = item //
prevPage.selAddress = 'yes'
//
uni.navigateBack({
delta: 1
})
}
}
</script>
<style scoped lang="scss">
@use './delivery-address.scss';
</style>

@ -0,0 +1,158 @@
.container {
background: #fff;
}
.input-box {
margin-bottom: 50rpx;
background: #fff;
padding: 0 20rpx;
.section {
display: flex;
align-items: center;
width: 100%;
font-size: 28rpx;
padding: 30rpx 0;
line-height: 48rpx;
height: 100%;
box-sizing: border-box;
border-bottom: 2rpx solid #e5e5e5;
text {
width: 20%;
color: #333;
}
input {
width: 70%;
padding: 0 20rpx;
color: #333;
}
picker {
width: 70%;
padding: 0 30rpx;
}
.pca {
width: 70%;
padding: 0 20rpx;
}
.arrow {
width: 28rpx;
height: 28rpx;
image {
width: 100%;
height: 100%;
vertical-align: top;
}
}
}
}
.btn-box {
padding: 5px 10px;
width: 100%;
text-align: center;
margin: auto;
text {
font-size: 30rpx;
}
.clear.btn {
width: 60%;
height: 80rpx;
line-height: 80rpx;
margin: auto;
text-align: center;
border: 1rpx solid #eb2444;
border-radius: 50rpx;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 1px 0 rgba(255, 255, 255, 0.3);
margin-top: 40rpx;
color: #eb2444;
background-color: #f8f0f1b6;
}
.keep {
color: #fff;
background-color: #eb2444;
}
}
.keep.btn {
width: 60%;
height: 80rpx;
line-height: 80rpx;
margin: auto;
text-align: center;
border: 1rpx solid #eb2444;
border-radius: 50rpx;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 1px 0 rgba(255, 255, 255, 0.3);
}
.infoText {
margin-top: 20rpx;
text-align: center;
width: 100%;
justify-content: center;
}
picker-view {
background-color: white;
padding: 0;
width: 100%;
height: 380rpx;
bottom: 0;
position: fixed;
text {
color: #999;
display: inline-flex;
position: fixed;
margin-top: 20rpx;
height: 50rpx;
text-align: center;
line-height: 50rpx;
font-size: 34rpx;
font-family: Arial, Helvetica, sans-serif;
}
}
picker-view-column {
view {
vertical-align: middle;
font-size: 28rpx;
line-height: 28rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
}
.animation-element-wrapper {
display: flex;
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.6);
z-index: 999;
}
.animation-element {
display: flex;
position: fixed;
width: 100%;
height: 470rpx;
bottom: 0;
background-color: rgba(255, 255, 255, 1);
}
.animation-button {
top: 20rpx;
width: 290rpx;
height: 100rpx;
align-items: center;
}
.left-bt {
left: 30rpx;
}
.right-bt {
right: 20rpx;
top: 20rpx;
position: absolute;
width: 80rpx !important;
}
.line {
display: block;
position: fixed;
height: 2rpx;
width: 100%;
margin-top: 89rpx;
background-color: #eee;
}

@ -0,0 +1,435 @@
<template>
<view class="container">
<!--input列表 -->
<view class="input-box">
<view class="section">
<text> </text>
<input
placeholder="姓名"
type="text"
maxlength="15"
:value="receiver"
@input="onReceiverInput"
>
</view>
<view class="section">
<text>手机号码</text>
<input
placeholder="11位手机号码"
type="number"
maxlength="11"
:value="mobile"
@input="onMobileInput"
>
</view>
<view
class="section"
@tap="translate"
>
<text>所在地区</text>
<view class="pca">
{{ province }} {{ city }} {{ area }}
</view>
<view
class="animation-element-wrapper"
:animation="animation"
:style="'visibility:' + (show ? 'visible':'hidden')"
@tap.stop="hiddenFloatView"
>
<view
class="animation-element"
@tap.stop="nono"
>
<text
class="right-bt"
@tap.stop="hiddenFloatView"
>
确定
</text>
<view class="line" />
<picker-view
indicator-style="height: 50rpx;"
:value="valArr"
@change="bindChange"
@tap.stop="nono"
>
<!---->
<picker-view-column>
<view
v-for="(item, indexs) in provArray"
:key="indexs"
>
{{ item.areaName }}
</view>
</picker-view-column>
<!--地级市-->
<picker-view-column>
<view
v-for="(item, indexss) in cityArray"
:key="indexss"
>
{{ item.areaName }}
</view>
</picker-view-column>
<!--区县-->
<picker-view-column>
<view
v-for="(item, indexsss) in areaArray"
:key="indexsss"
>
{{ item.areaName }}
</view>
</picker-view-column>
</picker-view>
</view>
</view>
<view class="arrow">
<image src="@/static/images/icon/more.png" />
</view>
</view>
<view class="section">
<text>详细地址</text>
<input
placeholder="如楼号/单元/门牌号"
type="text"
:value="addr"
@input="onAddrInput"
>
</view>
</view>
<!-- end input列表 -->
<!-- 功能按钮 -->
<view class="btn-box">
<view
class="keep btn"
@tap="onSaveAddr"
>
<text>保存收货地址</text>
</view>
<view
v-if="addrId!=0"
class="clear btn"
@tap="onDeleteAddr"
>
<text>删除收货地址</text>
</view>
</view>
<!-- end 功能按钮 -->
</view>
</template>
<script setup>
const addrId = ref(0)
const city = ref('')
const area = ref('')
const provinceId = ref(0)
const cityId = ref(0)
const areaId = ref(0)
const receiver = ref('')
const mobile = ref('')
const addr = ref('')
const province = ref('')
onLoad((options) => {
if (options.addrId) {
uni.showLoading()
http.request({
url: '/p/address/addrInfo/' + options.addrId,
method: 'GET'
})
.then(({ data }) => {
province.value = data.province
city.value = data.city
area.value = data.area
provinceId.value = data.provinceId
cityId.value = data.cityId
areaId.value = data.areaId
receiver.value = data.receiver
mobile.value = data.mobile
addr.value = data.addr
addrId.value = options.addrId
initCityData(data.provinceId, data.cityId, data.areaId)
uni.hideLoading()
})
} else {
initCityData(provinceId.value, cityId.value, areaId.value)
}
})
const provArray = ref([])
const valArr = ref([0, 0, 0])
const initCityData = (provinceId, cityId, areaId) => {
uni.showLoading()
http.request({
url: '/p/area/listByPid',
method: 'GET',
data: {
pid: 0
}
})
.then(({ data }) => {
provArray.value = data
if (provinceId) {
for (const index in data) {
if (data[index].areaId === provinceId) {
valArr.value = [parseInt(index), valArr.value[1], valArr.value[2]]
}
}
}
getCityArray(provinceId || data[0].areaId, cityId, areaId)
uni.hideLoading()
})
}
let indexArr = [18, 0, 0]
const areaArray = ref([])
const cityArray = ref([])
/**
* 滑动事件
*/
const bindChange = (e) => {
// column
const val = e.detail.value
// column
if (indexArr[0] != val[0]) {
val[1] = 0
val[2] = 0 //
//
getCityArray(provArray.value[val[0]].areaId)
} else {
// column
if (indexArr[1] != val[1]) {
val[2] = 0 //
getAreaArray(cityArray.value[val[1]].areaId) //
}
}
indexArr = val
valArr.value = [val[0], val[1], val[2]]
province.value = provArray.value[valArr.value[0]].areaName
city.value = cityArray.value[valArr.value[1]].areaName
area.value = areaArray.value[valArr.value[2]].areaName
provinceId.value = provArray.value[valArr.value[0]].areaId
cityId.value = cityArray.value[valArr.value[1]].areaId
areaId.value = areaArray.value[valArr.value[2]].areaId
}
let t = 0
let moveY = 200
const show = ref('')
/**
* 移动按钮点击事件
*/
const translate = () => {
if (t == 0) {
moveY = 0
show.value = true
t = 1
} else {
moveY = 200
show.value = false
t = 0
}
animationEvents(moveY, show.value)
}
/**
* 隐藏弹窗浮层
*/
const hiddenFloatView = () => {
moveY = 200
show.value = false
t = 0
animationEvents(moveY, show.value)
}
const animation = ref('')
/**
* 动画事件
*/
const animationEvents = (moveY, showParam) => {
animation.value = uni.createAnimation({
transformOrigin: '50% 50%',
duration: 400,
timingFunction: 'ease',
delay: 0
})
animation.value.translateY(moveY + 'vh').step()
animation.value = animation.value.export()
show.value = showParam
}
/**
* 根据省份ID获取 城市数据
*/
const getCityArray = (provinceId, cityId, areaId) => {
http.request({
url: '/p/area/listByPid',
method: 'GET',
data: {
pid: provinceId
}
})
.then(({ data }) => {
cityArray.value = data
if (cityId) {
for (const index in data) {
if (data[index].areaId == cityId) {
valArr.value = [valArr.value[0], parseInt(index), valArr.value[2]]
}
}
}
getAreaArray(cityId || data[0].areaId, areaId)
uni.hideLoading()
})
}
/**
* 根据城市ID获取 区数据
*/
const getAreaArray = (cityId, areaId) => {
http.request({
url: '/p/area/listByPid',
method: 'GET',
data: {
pid: cityId
}
}).then(({ data }) => {
areaArray.value = data
if (areaId) {
for (const _index in data) {
if (data[_index].areaId == areaId) {
valArr.value = [valArr.value[0], valArr.value[1], parseInt(_index)]
}
}
indexArr = valArr.value
} else {
province.value = provArray.value[valArr.value[0]].areaName
city.value = cityArray.value[valArr.value[1]].areaName
area.value = areaArray.value[valArr.value[2]].areaName
provinceId.value = provArray.value[valArr.value[0]].areaId
cityId.value = cityArray.value[valArr.value[1]].areaId
areaId.value = areaArray.value[valArr.value[2]].areaId
}
uni.hideLoading()
})
}
/**
* 保存地址
*/
const onSaveAddr = () => {
const receiverParam = receiver.value
const mobileParam = mobile.value
const addrParam = addr.value
if (!receiverParam.trim()) {
receiver.value = ''
uni.showToast({
title: '请输入收货人姓名',
icon: 'none'
})
return
}
if (!mobileParam) {
uni.showToast({
title: '请输入手机号码',
icon: 'none'
})
return
}
if (mobileParam.length != 11) {
uni.showToast({
title: '请输入正确的手机号码',
icon: 'none'
})
return
}
if (!addrParam.trim()) {
receiver.value = ''
uni.showToast({
title: '请输入详细地址',
icon: 'none'
})
return
}
uni.showLoading()
let url = '/p/address/addAddr'
let method = 'POST'
if (addrId.value != 0) {
url = '/p/address/updateAddr'
method = 'PUT'
} //
http.request({
url,
method,
data: {
receiver: receiver.value,
mobile: mobile.value,
addr: addr.value,
province: province.value,
provinceId: provinceId.value,
city: city.value,
cityId: cityId.value,
areaId: areaId.value,
area: area.value,
userType: 0,
addrId: addrId.value
}
})
.then(() => {
uni.hideLoading()
uni.navigateBack({
delta: 1
})
})
}
const onReceiverInput = (e) => {
receiver.value = e.detail.value
}
const onMobileInput = (e) => {
mobile.value = e.detail.value
}
const onAddrInput = (e) => {
addr.value = e.detail.value
}
/**
* 删除配送地址
*/
const onDeleteAddr = () => {
uni.showModal({
title: '',
content: '确定要删除此收货地址吗?',
confirmColor: '#eb2444',
success (res) {
if (res.confirm) {
const addrIdParam = addrId.value
uni.showLoading()
http.request({
url: '/p/address/deleteAddr/' + addrIdParam,
method: 'DELETE'
})
.then(() => {
uni.hideLoading()
uni.navigateBack({
delta: 1
})
})
}
}
})
}
</script>
<style scoped lang="scss">
@use './editAddress.scss';
</style>

@ -0,0 +1,175 @@
page {
background: #f7f8fa;
}
.container {
height: 100%;
}
.padding20 {
padding-top: 88rpx;
}
.f-fl {
float: left;
}
.f-fr {
float: right;
}
.navWrap {
position: fixed;
top: 0;
left: 0;
z-index: 1;
overflow: hidden;
background-color: #fafafa;
border-bottom: 2rpx solid #f4f4f4;
height: 92rpx;
}
.nav {
display: flex;
flex-flow: row nowrap;
}
.nav-slider {
left: 0;
bottom: 0;
height: 4rpx;
background-color: #b4282d;
transition: transform 0.3s;
transition: transform 0.3s, -webkit-transform 0.3s;
box-sizing: border-box;
}
.nav-item {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
float: left;
height: 88rpx;
padding: 0 16rpx;
font-size: 28rpx;
text {
box-sizing: border-box;
color: #333;
padding: 27rpx 16rpx 23rpx;
line-height: 34rpx;
}
}
.nav-item.active {
text {
color: #b4282d;
}
}
.u-icon {
vertical-align: middle;
}
.deliveryInfo {
height: 198rpx;
width: 100%;
vertical-align: middle;
padding-left: 30rpx;
background-size: cover;
display: table;
position: relative;
box-sizing: border-box;
.companyname {
line-height: 1;
margin-left: 136rpx;
font-size: 28rpx;
.key {
color: #666;
}
}
.expno {
line-height: 1;
margin-left: 136rpx;
font-size: 28rpx;
margin-top: 16rpx;
.key {
color: #666;
}
}
}
.icon-express {
width: 104rpx;
height: 104rpx;
background-size: 100% 100%;
position: absolute;
top: 48rpx;
left: 30rpx;
}
.infoWarp {
display: table-cell;
vertical-align: middle;
}
.deliveryDetail {
margin-top: 20rpx;
padding-top: 40rpx;
background-color: #fff;
min-height: 670rpx;
}
.detailItem {
border-left: 1px dashed #f4f4f4;
margin-left: 42rpx;
position: relative;
margin-bottom: 2rpx;
}
.dot {
image {
width: 35rpx;
height: 35rpx;
background-size: 100%;
position: absolute;
top: 40rpx;
left: -18rpx;
}
}
.lastest {
.dot {
image {
top: -2rpx;
}
}
.detail {
.desc {
color: #105c3e;
margin-top: 0;
}
.time {
color: #105c3e;
}
border-top: 0;
}
}
.detail {
.desc {
font-size: 24rpx;
line-height: 30rpx;
margin-top: 40rpx;
}
.time {
font-size: 24rpx;
line-height: 30rpx;
color: #999;
margin-top: 15rpx;
margin-bottom: 39rpx;
}
border-top: 1px solid #f4f4f4;
margin-left: 28rpx;
overflow: hidden;
padding-right: 30rpx;
}
.deliveryTip {
height: 80rpx;
background-color: #fff8d8;
padding-left: 30rpx;
color: #f48f18;
font-size: 28rpx;
line-height: 80rpx;
margin-bottom: 20rpx;
}
.empty-space {
margin-top: 20rpx;
background: #fff;
font-size: 28rpx;
color: #333;
padding: 20rpx 0;
text-align: center;
}

@ -0,0 +1,93 @@
<template>
<!-- 物流信息 -->
<view class="container">
<view class="wrapper">
<view
class="deliveryInfo"
style="background:url(http://jiales.gz-yami.com/delivery-bg.png) center center no-repeat #fff;"
>
<view
class="icon-express"
style="background:url(http://jiales.gz-yami.com/delivery-car.png) no-repeat;background-size:100% 100%;"
/>
<view class="infoWarp">
<view class="companyname">
<text class="key">
物流公司
</text>
<text class="value">
{{ companyName }}
</text>
</view>
<view class="expno">
<text class="key">
运单编号
</text>
<text class="value">
{{ dvyFlowId }}
</text>
</view>
</view>
</view>
<view
v-if="dvyData.length"
class="deliveryDetail"
>
<block
v-for="(item, index) in dvyData"
:key="index"
>
<view :class="'detailItem ' + (index==0?'lastest':'')">
<view class="dot">
<image src="@/static/images/icon/delive-dot.png" />
<image src="@/static/images/icon/dot.png" />
</view>
<view class="detail">
<view class="desc">
{{ item.context }}
</view>
<view class="time">
{{ item.time }}
</view>
</view>
</view>
</block>
</view>
<view
v-else
class="empty-space"
>
暂无配送信息
</view>
</view>
</view>
</template>
<script setup>
const companyName = ref('')
const dvyFlowId = ref('')
const dvyData = ref([])
/**
* 生命周期函数--监听页面加载
*/
onLoad((options) => {
uni.showLoading()
http.request({
url: '/delivery/check',
method: 'GET',
data: {
orderNumber: options.orderNum
}
})
.then(({ data }) => {
companyName.value = data.companyName
dvyFlowId.value = data.dvyFlowId
dvyData.value = data.data
uni.hideLoading()
})
})
</script>
<style scoped lang="scss">
@use './express-delivery.scss';
</style>

@ -0,0 +1,27 @@
.news-detail {
padding: 20rpx;
.news-detail-title {
font-size: 32rpx;
font-weight: bold;
line-height: 50rpx;
padding: 20rpx;
}
.news-detail-text {
font-size: 28rpx;
line-height: 46rpx;
text-align: justify;
text-justify: inter-ideograph;
margin-top: 20rpx;
}
}
.content {
> {
> {
>img {
display: block;
width: 100%;
height: auto;
}
}
}
}

@ -0,0 +1,41 @@
<template>
<view class="container">
<view class="news-detail">
<view class="news-detail-title">
{{ news.title }}
</view>
<rich-text
class="content"
:nodes="news.content"
/>
</view>
</view>
</template>
<script setup>
const news = ref({
title: '',
content: '',
id: null
})
/**
* 生命周期函数--监听页面加载
*/
onLoad((options) => {
//
http.request({
url: '/shop/notice/info/' + options.id,
method: 'GET'
})
.then(({ data }) => {
data.content = data.content.replace(/width=/gi, 'sss=')
data.content = data.content.replace(/height=/gi, 'sss=')
data.content = data.content.replace(/ \/>/gi, ' style="max-width:100% !important;display:block;" />')
news.value = data
})
})
</script>
<style scoped lang="scss">
@use './news-detail.scss';
</style>

@ -0,0 +1,30 @@
.container {
background: #fff;
margin: 7px;
}
.line-fix {
width: 100%;
height: 2rpx;
background: #e1e1e1;
position: fixed;
top: 0;
}
.tit-background {
width: 100%;
height: 20rpx;
background: #f4f4f4;
}
.prod-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
/* 空 */
.empty {
display: block;
width: 100%;
font-size: 26rpx;
color: #999;
margin-top: 20vh;
text-align: center;
}

@ -0,0 +1,232 @@
<template>
<view class="container">
<view>
<block
v-for="(item, index) in prodList"
:key="index"
>
<production :item="item" />
</block>
<view
v-if="!prodList.length"
class="empty"
>
暂无数据
</view>
</view>
</view>
</template>
<script setup>
const sts = ref(0)
const title = ref('')
const current = ref(1)
const size = ref(10)
const pages = ref(0)
const tagid = ref(0)
/**
* 生命周期函数--监听页面加载
*/
onLoad((options) => {
current.value = 1
pages.value = 0
sts.value = options.sts
title.value = options.title ? options.title : ''
if (options.tagid) {
tagid.value = options.tagid
}
if (sts.value == 0) {
if (options.tagid == 1) {
uni.setNavigationBarTitle({
title: '每日上新'
})
} else if (options.tagid == 2) {
uni.setNavigationBarTitle({
title: '商城热卖'
})
} else if (options.tagid == 3) {
uni.setNavigationBarTitle({
title: '更多宝贝'
})
}
} else if (sts.value == 1) {
uni.setNavigationBarTitle({
title: '新品推荐'
})
} else if (sts.value == 2) {
uni.setNavigationBarTitle({
title: '限时特惠'
})
} else if (sts.value == 3) {
uni.setNavigationBarTitle({
title: '每日疯抢'
})
} else if (sts.value == 4) {
uni.setNavigationBarTitle({
title: '优惠券活动商品'
})
} else if (sts.value == 5) {
uni.setNavigationBarTitle({
title: '我的收藏商品'
})
} else {
uni.setNavigationBarTitle({
title: title.value
})
}
loadProdData(options)
})
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom(() => {
if (current.value < pages.value) {
current.value = current.value + 1
loadProdData()
}
})
/**
* 加载商品数据
*/
const loadProdData = (options) => {
const stsParam = sts.value
if (stsParam == 0) {
//
getTagProd()
} else if (stsParam == 1) {
//
const url = '/prod/lastedProdPage'
getActProd(url)
} else if (stsParam == 2) {
//
const url = '/prod/discountProdList'
getActProd(url)
} else if (stsParam == 3) {
//
const url = '/prod/moreBuyProdList'
getActProd(url)
} else if (stsParam == 4) {
//
getProdByCouponId(options.tagid)
} else if (stsParam == 5) {
//
getCollectionProd()
}
}
const prodList = ref([])
const getActProd = (url) => {
uni.showLoading()
http.request({
url,
method: 'GET',
data: {
current: current.value,
size: size.value
}
})
.then(({ data }) => {
let list
if (data.current === 1) {
list = data.records
} else {
list = prodList.value
list = list.concat(data.records)
}
prodList.value = list
pages.value = data.pages
uni.hideLoading()
})
}
/**
* 获取我的收藏商品
*/
const getCollectionProd = () => {
uni.showLoading()
http.request({
url: '/p/user/collection/prods',
method: 'GET',
data: {
current: current.value,
size: size.value
}
})
.then(({ data }) => {
let list
if (data.current == 1) {
list = data.records
} else {
list = prodList.value
list = list.concat(data.records)
}
prodList.value = list
pages.value = data.pages
uni.hideLoading()
})
}
/**
* 获取标签列表
*/
const getTagProd = () => {
uni.showLoading()
http.request({
url: '/prod/prodListByTagId',
method: 'GET',
data: {
tagId: tagid.value,
current: current.value,
size: size.value
}
})
.then(({ data }) => {
let list
if (data.current === 1) {
list = data.records
} else {
list = prodList.value.concat(data.records)
}
prodList.value = list
pages.value = data.pages
uni.hideLoading()
})
}
/**
* 获取优惠券商品列表
*/
const getProdByCouponId = (id) => {
uni.showLoading()
http.request({
url: '/coupon/prodListByCouponId',
method: 'GET',
data: {
couponId: id,
current: current.value,
size: size.value
}
})
.then(({ data }) => {
let list
if (data.current === 1) {
list = data.records
} else {
list = prodList.value.concat(data.records)
}
prodList.value = list
pages.value = data.pages
uni.hideLoading()
})
}
</script>
<style scoped lang="scss">
@use './prod-classify.scss';
</style>

@ -0,0 +1,34 @@
.recent-news {
background: #fff;
.news-item {
padding: 20rpx 20rpx 0 20rpx;
position: relative;
&::after {
content: " ";
width: 100%;
height: 2rpx;
background-color: #e1e1e1;
left: 20rpx;
display: block;
position: absolute;
}
.news-item-title {
font-size: 28rpx;
text-align: left;
}
.news-item-date {
font-size: 24rpx;
color: #999;
text-align: right;
margin-top: 10rpx;
margin-bottom: 20rpx;
}
}
.empty {
display: block;
padding-top: 200rpx;
color: #999;
font-size: 26rpx;
text-align: center;
}
}

@ -0,0 +1,60 @@
<template>
<view class="container">
<view class="recent-news">
<block
v-for="(item, index) in news"
:key="index"
>
<view
class="news-item"
:data-id="item.id"
@tap="toNewsDetail"
>
<view class="news-item-title">
{{ item.title }}
</view>
<view class="news-item-date">
{{ item.publishTime }}
</view>
</view>
</block>
<view
v-if="!news || !news.length"
class="empty"
>
暂无数据
</view>
</view>
</view>
</template>
<script setup>
const news = ref([])
/**
* 生命周期函数--监听页面显示
*/
onShow(() => {
//
http.request({
url: '/shop/notice/noticeList',
method: 'GET'
})
.then(({ data }) => {
news.value = data.records
})
})
/**
* 跳转公告详情页
* @param e
*/
const toNewsDetail = (e) => {
uni.navigateTo({
url: '/pages/news-detail/news-detail?id=' + e.currentTarget.dataset.id
})
}
</script>
<style scoped lang="scss">
@use './recent-news.scss';
</style>

@ -0,0 +1,119 @@
.search-bar {
width: 100%;
position: fixed;
top: 0;
left: 0;
color: #777;
background: #fff;
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.07);
z-index: 3;
.search-box {
position: relative;
height: 60rpx;
background: #f7f7f7;
z-index: 999;
width: 80%;
margin-left: 70rpx;
border-radius: 50rpx;
margin: 20rpx 0 20rpx 20rpx;
.search-img {
width: 32rpx;
height: 32rpx;
position: absolute;
left: 20rpx;
top: 14rpx;
display: block;
}
}
.search-hint {
font-size: 28rpx;
position: absolute;
right: 30rpx;
top: 31rpx;
color: #eb2444;
}
}
.sear-input {
height: 60rpx;
border-radius: 50rpx;
border: 0;
margin: 0 30rpx 0 64rpx;
line-height: 48rpx;
vertical-align: top;
background: #f7f7f7;
font-size: 28rpx;
}
.search-display {
background: #fff;
padding: 20rpx;
margin-top: 100rpx;
.title-text {
padding: 30rpx 0;
font-size: 30rpx;
color: #666;
}
}
.hot-search {
.hot-search-tags {
overflow: hidden;
font-size: 26rpx;
text-align: center;
padding-bottom: 30rpx;
.tags {
display: block;
max-width: 100%;
overflow: hidden;
float: left;
border-radius: 50rpx;
white-space: nowrap;
text-overflow: ellipsis;
background-color: #f2f2f2;
box-sizing: border-box;
margin-right: 20rpx;
margin-bottom: 20rpx;
padding: 10rpx 30rpx;
}
}
}
.history-search {
.title-text.history-line {
position: relative;
border-top: 2rpx solid #e1e1e1;
}
.his-search-tags {
overflow: hidden;
font-size: 26rpx;
text-align: center;
display: inline-block;
.tags {
max-width: 300rpx;
overflow: hidden;
float: left;
border-radius: 50rpx;
white-space: nowrap;
text-overflow: ellipsis;
background-color: #f2f2f2;
box-sizing: border-box;
margin-right: 20rpx;
margin-bottom: 20rpx;
padding: 10rpx 30rpx;
}
}
}
.clear-history {
image {
width: 32rpx;
height: 32rpx;
position: absolute;
right: 10rpx;
top: 30rpx;
}
}
.search-tit-empty {
display: block;
margin: 0 auto;
text-align: center;
width: 100%;
font-size: 24rpx;
color: #aaa;
}

@ -0,0 +1,183 @@
<template>
<view class="container">
<!-- 搜索框 -->
<view class="search-bar">
<view class="search-box">
<input
placeholder="输入关键字搜索"
class="sear-input"
confirm-type="search"
:value="prodName"
@confirm="toSearchProdPage"
@input="getSearchContent"
>
<image
src="@/static/images/icon/search.png"
class="search-img"
/>
</view>
<text
class="search-hint"
@tap="goBackIndex"
>
取消
</text>
</view>
<view class="search-display">
<!-- 热门搜索 -->
<view class="hot-search">
<view class="title-text">
热门搜索
</view>
<view
v-if="hotSearchList && hotSearchList.length"
class="hot-search-tags"
>
<block
v-for="(item, index) in hotSearchList"
:key="index"
>
<text
class="tags"
:data-name="item.content"
@tap="onHistSearch"
>
{{ item.title }}
</text>
</block>
</view>
<view
v-else
class="search-tit-empty"
>
暂无数据
</view>
</view>
<!-- 搜索历史 -->
<view
v-if="recentSearch && recentSearch.length"
class="history-search"
>
<view class="title-text history-line">
搜索历史
<view class="clear-history">
<image
src="@/static/images/icon/clear-his.png"
@tap="clearSearch"
/>
</view>
</view>
<block
v-for="(item, index) in recentSearch"
:key="index"
>
<view class="his-search-tags">
<text
class="tags"
:data-name="item"
@tap="onHistSearch"
>
{{ item }}
</text>
</view>
</block>
</view>
</view>
</view>
</template>
<script setup>
const hotSearchList = ref([])
/**
* 生命周期函数--监听页面显示
*/
onShow(() => {
http.request({
url: '/search/hotSearchByShopId',
method: 'GET',
data: {
number: 10,
shopId: 1,
sort: 1
}
})
.then(({ data }) => {
hotSearchList.value = data
})
//
getRecentSearch()
})
const prodName = ref('')
/**
* 生命周期函数--监听页面隐藏
*/
onHide(() => {
prodName.value = ''
})
const recentSearch = ref([])
/**
* 获取历史搜索
*/
const getRecentSearch = () => {
recentSearch.value = uni.getStorageSync('recentSearch')
}
/**
* 搜索提交
*/
const toSearchProdPage = () => {
if (prodName.value.trim()) {
//
let recentSearchStorage = uni.getStorageSync('recentSearch') || []
recentSearchStorage = recentSearchStorage.filter(item => item !== prodName.value)
recentSearchStorage.unshift(prodName.value)
if (recentSearchStorage.length > 10) {
recentSearchStorage.pop()
}
uni.setStorageSync('recentSearch', recentSearchStorage) //
uni.navigateTo({
url: '/pages/search-prod-show/search-prod-show?prodName=' + prodName.value
})
}
}
/**
* 清空搜索历史
*/
const clearSearch = () => {
uni.removeStorageSync('recentSearch')
getRecentSearch()
}
/**
* 返回首页
*/
const goBackIndex = () => {
uni.navigateBack({
url: '/pages/search-page/search-page'
})
}
/**
* 输入商品名获取数据 || 绑定输入值
*/
const getSearchContent = (e) => {
prodName.value = e.detail.value
}
/**
* 点击搜素历史
*/
const onHistSearch = (e) => {
prodName.value = e.currentTarget.dataset.name
toSearchProdPage()
}
</script>
<style scoped lang="scss">
@use './search-page.scss';
</style>

@ -0,0 +1,186 @@
.container {
background: #f4f4f4;
.empty {
text-align: center;
color: #999;
font-size: 26rpx;
}
.empty.empty-top {
margin-top: 300rpx;
}
}
.fixed-box {
position: fixed;
width: 100%;
top: 0;
z-index: 999;
background: #fff;
.tabs {
width: 100%;
height: 80rpx;
line-height: 80rpx;
padding: 10rpx 0;
z-index: 999;
background: #fff;
&::after {
content: '';
background-color: #e1e1e1;
left: 0;
height: 1px;
transform-origin: 50% 100% 0;
bottom: 0;
position: absolute;
display: block;
width: 100%;
}
.tab-item {
display: inline-block;
width: 33.33%;
text-align: center;
font-size: 28rpx;
}
.tab-item.on {
color: #eb2444;
}
}
}
.search-bar {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
color: #777;
background: #fff;
z-index: 3;
padding: 0 30rpx;
box-sizing: border-box;
margin: 30rpx 0;
.search-box {
position: relative;
height: 60rpx;
background: #f7f7f7;
z-index: 999;
width: 80%;
border-radius: 50rpx;
margin-right: 30rpx;
flex: 1;
.search-img {
width: 32rpx;
height: 32rpx;
position: absolute;
left: 20rpx;
top: 14rpx;
display: block;
}
}
.search-hint {
font-size: 28rpx;
position: absolute;
right: 30rpx;
top: 31rpx;
color: #eb2444;
}
.search-list-img {
width: 40rpx;
height: 40rpx;
font-size: 0;
image {
width: 100%;
height: 100%;
}
}
}
.sear-input {
height: 60rpx;
border-radius: 50rpx;
border: 0;
margin: 0 30rpx 0 64rpx;
line-height: 48rpx;
vertical-align: top;
background: #f7f7f7;
font-size: 28rpx;
}
.prod-show {
background: #fff;
.prod-items {
float: left;
background: #fff;
padding-bottom: 20rpx;
box-sizing: border-box;
}
}
.prod-items {
margin: 0 20rpx;
}
.hotsale-item-cont {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.prod-list {
padding-top: 150rpx;
min-height: calc(100vh - 150rpx);
.cont-item {
padding: 0 20rpx 20rpx 20rpx;
.show-item {
.more-prod-pic {
text-align: center;
width: 170rpx;
height: 170rpx;
font-size: 0;
.more-pic {
width: 100%;
height: 100%;
vertical-align: middle;
}
}
position: relative;
display: flex;
justify-content: start;
padding: 20rpx;
border-radius: 20rpx;
background: #fff;
margin-bottom: 20rpx;
box-shadow: 0 16rpx 32rpx 0 rgba(7, 17, 27, 0.05);
.prod-text-right {
margin-left: 20rpx;
width: 75%;
.cate-prod-info {
font-size: 22rpx;
color: #999;
margin: 10rpx 0 20rpx 0;
}
.go-to-buy {
font-size: 26rpx;
background: #eb2444;
color: #fff;
border-radius: 50rpx;
width: 150rpx;
text-align: center;
padding: 8rpx 3rpx;
position: absolute;
right: 20rpx;
bottom: 20rpx;
}
.prod-text.more {
margin: 0;
height: 78rpx;
font-size: 28rpx;
display: -webkit-box;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
color: #000;
}
.prod-price.more {
font-size: 28rpx;
color: #eb2444;
font-family: arial;
}
}
}
}
}

@ -0,0 +1,223 @@
<template>
<view class="container">
<!-- 搜索框 -->
<view class="fixed-box">
<view class="search-bar">
<view class="search-box">
<input
placeholder="输入关键字搜索"
class="sear-input"
:value="prodName"
confirm-type="search"
@input="getSearchContent"
@confirm="toSearchConfirm"
>
<image
src="@/static/images/icon/search.png"
class="search-img"
/>
</view>
<view
class="search-list-img"
@tap="changeShowType"
>
<image
v-if="showType==1"
src="@/static/images/icon/search-col.png"
/>
<image
v-if="showType==2"
src="@/static/images/icon/search-col2.png"
/>
</view>
</view>
<view class="tabs">
<text
:class="'tab-item complete ' + (sts==0?'on':'')"
data-sts="0"
@tap="onStsTap"
>
综合
</text>
<text
:class="'tab-item ' + (sts==1?'on':'')"
data-sts="1"
@tap="onStsTap"
>
销量
</text>
<text
:class="'tab-item ' + (sts==2?'on':'')"
data-sts="2"
@tap="onStsTap"
>
价格
</text>
</view>
</view>
<!-- 商品列表 -->
<view class="prod-list">
<!-- 横向列表 -->
<view
v-if="showType==1"
class="prod-show"
>
<view class="hotsale-item-cont">
<block
v-for="(item, index) in searchProdList"
:key="index"
>
<production
:item="item"
sts="6"
/>
</block>
</view>
</view>
<!-- 纵向列表 -->
<view
v-if="showType==2"
class="cont-item"
>
<block
v-for="(item, index) in searchProdList"
:key="index"
>
<view
class="show-item"
:data-prodid="item.prodId"
@tap="toProdPage"
>
<view class="more-prod-pic">
<image
:src="item.pic"
class="more-pic"
/>
</view>
<view class="prod-text-right">
<view class="prod-text more">
{{ item.prodName }}
</view>
<view class="cate-prod-info">
{{ item.praiseNumber }}评价 {{ item.positiveRating }}%好评
</view>
<view class="prod-price more">
<text class="symbol">
</text>
<text class="big-num">
{{ wxs.parsePrice(item.price)[0] }}
</text>
<text class="small-num">
.{{ wxs.parsePrice(item.price)[1] }}
</text>
</view>
</view>
</view>
</block>
</view>
<!-- 空占位 -->
<view
v-if="!searchProdList.length"
:class="['empty',showType==1? 'empty-top':'']"
>
暂无结果
</view>
</view>
</view>
</template>
<script setup>
const wxs = number()
const prodName = ref('')
/**
* 生命周期函数--监听页面加载
*/
onLoad((options) => {
prodName.value = options.prodName
})
/**
* 生命周期函数--监听页面显示
*/
onShow(() => {
toLoadData()
})
const showType = ref(2)
const changeShowType = () => {
if (showType.value == 1) {
showType.value = 2
} else {
showType.value = 1
}
}
/**
* 输入商品获取数据
* @param e
*/
const getSearchContent = (e) => {
prodName.value = e.detail.value
}
const sts = ref(0)
const searchProdList = ref([])
/**
* 请求热门搜索商品接口
*/
const toLoadData = () => {
http.request({
url: '/search/searchProdPage',
method: 'GET',
data: {
current: 1,
prodName: prodName.value,
size: 10,
sort: sts.value
}
})
.then(({ data }) => {
searchProdList.value = data.records
})
}
/**
* 当前搜索页二次搜索商品
*/
const toSearchConfirm = (e) => {
if (e.detail.value) {
let recentSearch = uni.getStorageSync('recentSearch') || []
recentSearch = recentSearch.filter(item => item !== prodName.value)
recentSearch.unshift(prodName.value)
if (recentSearch.length > 10) {
recentSearch.pop()
}
uni.setStorageSync('recentSearch', recentSearch)
}
uni.redirectTo({
url: '/pages/search-prod-show/search-prod-show?prodName=' + e.detail.value
})
}
/**
* 状态点击事件
*/
const onStsTap = (e) => {
sts.value = e.currentTarget.dataset.sts
toLoadData()
}
const toProdPage = (e) => {
uni.navigateTo({
url: '/pages/prod/prod?prodid=' + e.currentTarget.dataset.prodid
})
}
</script>
<style scoped lang="scss">
@use './search-prod-show.scss';
</style>

@ -19,7 +19,7 @@
}
}
.prod-item {
margin-top: 100rpx;
height: calc(100vh - 100rpx);
}
.on {
border-bottom: 4rpx solid #e43130;
@ -105,5 +105,5 @@
.empty-wrap {
color: #aaa;
text-align: center;
margin-top: 400rpx;
padding-top: 400rpx;
}

@ -22,10 +22,8 @@
</block>
</scroll-view>
<!-- 商品列表 -->
<view
v-if="prodList.length"
class="prod-item"
>
<view class="prod-item">
<block v-if="prodList.length">
<block
v-for="(prod, key) in prodList"
:key="key"
@ -64,7 +62,7 @@
</view>
</view>
</block>
</view>
</block>
<view
v-else
class="empty-wrap"
@ -72,6 +70,7 @@
暂无商品数据~
</view>
</view>
</view>
</template>
<script setup>

@ -0,0 +1,433 @@
.container {
background: #f4f4f4;
}
.submit-order {
margin-bottom: 100rpx;
padding-bottom: 160rpx;
.delivery-addr {
position: relative;
background: #fff;
.addr-icon {
width: 32rpx;
height: 32rpx;
display: block;
position: absolute;
left: 30rpx;
top: 24rpx;
image {
width: 100%;
height: 100%;
}
}
.user-info {
padding-top: 20rpx;
line-height: 48rpx;
word-wrap: break-word;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
.item {
font-size: 30rpx;
margin-right: 30rpx;
vertical-align: top;
display: inline-block;
}
}
.addr {
font-size: 26rpx;
line-height: 36rpx;
color: #999;
width: 90%;
padding-bottom: 20rpx;
margin-top: 15rpx;
word-wrap: break-word;
}
.arrow {
width: 15rpx;
height: 15rpx;
border-top: 2rpx solid #777;
border-right: 2rpx solid #777;
transform: rotate(45deg);
position: absolute;
right: 30rpx;
top: 60rpx;
}
.arrow.empty {
top: 39rpx;
}
}
}
.delivery-addr {
.addr-bg {
.add-addr {
.plus-sign {
color: #eb2444;
border: 2rpx solid #eb2444;
padding: 0rpx 6rpx;
margin-right: 10rpx;
}
font-size: 28rpx;
color: #666;
display: flex;
align-items: center;
padding: 30rpx 0;
}
padding: 0 30rpx;
}
.addr-bg.whole {
padding: 0 39rpx 0 77rpx;
}
}
.addr-bg {
.add-addr {
.plus-sign-img {
width: 32rpx;
height: 32rpx;
font-size: 0;
margin-right: 10rpx;
image {
width: 100%;
height: 100%;
}
}
}
}
.prod-item {
background-color: #fff;
margin-top: 15rpx;
font-size: 28rpx;
.item-cont {
.prod-pic {
image {
width: 180rpx;
height: 180rpx;
width: 100%;
height: 100%;
}
font-size: 0;
display: block;
width: 160rpx;
height: 160rpx;
overflow: hidden;
background: #fff;
margin-right: 16rpx;
}
display: flex;
align-items: center;
padding: 30rpx;
border-bottom: 2rpx solid #f1f1f1;
.prod-info {
margin-left: 10rpx;
font-size: 28rpx;
width: 100%;
position: relative;
height: 160rpx;
-webkit-flex: 1;
-ms-flex: 1;
-webkit-box-flex: 1;
-moz-box-flex: 1;
flex: 1;
.prodname {
font-size: 28rpx;
line-height: 40rpx;
max-height: 86rpx;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
word-break: break-all;
}
.prod-info-cont {
color: #999;
line-height: 40rpx;
margin-top: 10rpx;
font-size: 22rpx;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
word-break: break-all;
}
}
}
.order-num {
padding: 20rpx 30rpx;
display: flex;
justify-content: space-between;
font-size: 28rpx;
.clear-btn {
width: 32rpx;
height: 32rpx;
font-size: 0;
vertical-align: top;
margin-top: 6rpx;
margin-left: 42rpx;
position: relative;
&::after {
content: " ";
display: block;
position: absolute;
left: -10px;
top: 1px;
width: 1px;
height: 12px;
background: #ddd;
}
.clear-list-btn {
width: 100%;
height: 100%;
vertical-align: middle;
}
}
}
.total-num {
text-align: right;
padding: 20rpx 30rpx;
font-size: 28rpx;
.prodprice {
display: inline-block;
color: #333;
}
.prodcount {
margin-right: 20rpx;
}
}
.price-nums {
.prodprice {
position: absolute;
bottom: 0;
}
.prodcount {
position: absolute;
bottom: 5rpx;
right: 0;
color: #999;
font-family: verdana;
}
}
}
.order-state {
display: flex;
align-items: center;
}
.order-msg {
background: #fff;
margin-top: 15rpx;
padding: 0 30rpx;
font-size: 28rpx;
.msg-item {
border-top: 2rpx solid #f1f1f1;
&:first-child {
border: 0;
}
.item {
position: relative;
display: flex;
padding: 16rpx 0;
align-items: center;
.item-tit {
line-height: 48rpx;
}
.item-txt {
-webkit-box-flex: 1;
-moz-box-flex: 1;
flex: 1;
font-family: arial;
max-height: 48rpx;
overflow: hidden;
line-height: 48rpx;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
word-break: break-all;
}
.item-txt.price {
padding: 0;
text-align: right;
}
input {
flex: 1;
}
.coupon-btn {
display: block;
margin: 0 30rpx;
line-height: 28rpx;
color: #999;
}
.arrow {
width: 15rpx;
height: 15rpx;
border-top: 2rpx solid #999;
border-right: 2rpx solid #999;
transform: rotate(45deg);
position: absolute;
right: 0rpx;
}
}
.item.payment {
border-top: 2rpx solid #f1f1f1;
color: #eb2444;
}
.item.coupon {
border-bottom: 2rpx solid #e1e1e1;
}
}
}
.submit-order-footer {
position: fixed;
bottom: 0;
width: 100%;
max-width: 750rpx;
background: #fff;
margin: auto;
display: -webkit-flex;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: flex;
font-size: 26rpx;
box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.05);
.sub-order {
flex: 1;
margin: 0 30rpx;
line-height: 100rpx;
display: block;
text-align: left;
font-size: 28rpx;
.item-txt {
.price {
display: inline;
color: #eb2444;
font-size: 28rpx;
}
}
}
.footer-box {
padding: 0 10rpx;
width: 200rpx;
background: #eb2444;
text-align: center;
line-height: 100rpx;
color: #fff;
}
}
.clearfix {
&:after {
content: " ";
display: table;
clear: both;
}
}
.popup-hide {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 999;
background-color: rgba(0, 0, 0, 0.3);
}
.popup-box {
position: absolute;
bottom: 0;
width: 100%;
height: 80%;
overflow: hidden;
background-color: #fff;
}
.popup-tit {
position: relative;
height: 46px;
line-height: 46px;
padding-left: 10px;
font-size: 16px;
color: #333;
font-weight: bold;
}
.close {
color: #aaa;
border-radius: 12px;
line-height: 20px;
text-align: center;
height: 20px;
width: 20px;
font-size: 18px;
padding: 1px;
top: 10px;
right: 10px;
position: absolute;
&::before {
content: "\2716";
}
}
.coupon-tabs {
display: flex;
font-size: 14px;
justify-content: space-around;
border-bottom: 1px solid #f2f2f2;
}
.coupon-tab {
padding: 10px 0;
}
.coupon-tab.on {
border-bottom: 2px solid #eb2444;
font-weight: 600;
}
.popup-cnt {
height: calc(100% - 88px);
overflow: auto;
padding: 0 10px;
background: #f4f4f4;
}
.coupon-ok {
position: fixed;
bottom: 0;
width: 100%;
height: 60px;
line-height: 50px;
font-size: 14px;
text-align: center;
box-shadow: 0px -1px 1px #ddd;
background: rgba(255, 255, 255, 0.9);
text {
border-radius: 20px;
display: inline-block;
height: 20px;
line-height: 20px;
width: 450rpx;
padding: 7px;
background: -o-linear-gradient(right, #f45c43, #eb2444);
background: linear-gradient(right, #f45c43, #eb2444);
background: -webkit-linear-gradient(right, #f45c43, #eb2444);
color: #fff;
box-shadow: -1px 3px 3px #aaa;
}
}
.botm-empty {
height: 60px;
}
checkbox {
.wx-checkbox-input {
border-radius: 50%;
width: 35rpx;
height: 35rpx;
}
.wx-checkbox-input.wx-checkbox-input-checked {
background: #eb2444;
border-color: #eb2444;
&::before {
text-align: center;
font-size: 22rpx;
color: #fff;
background: transparent;
transform: translate(-50%, -50%) scale(1);
-webkit-transform: translate(-50%, -50%) scale(1);
}
}
}

@ -0,0 +1,527 @@
<template>
<view>
<view class="container">
<view class="submit-order">
<!-- 收货地址 -->
<view
class="delivery-addr "
@tap="toAddrListPage"
>
<view
v-if="!userAddr"
class="addr-bg "
>
<view class="add-addr">
<view class="plus-sign-img">
<image src="@/static/images/icon/plus-sign.png" />
</view>
<text>新增收货地址</text>
</view>
<view class="arrow empty" />
</view>
<view
v-if="userAddr"
class="addr-bg whole"
>
<view class="addr-icon">
<image src="@/static/images/icon/addr.png" />
</view>
<view class="user-info">
<text class="item">
{{ userAddr.receiver }}
</text>
<text class="item">
{{ userAddr.mobile }}
</text>
</view>
<view class="addr">
{{ userAddr.province }}{{ userAddr.city }}{{ userAddr.area }}{{ userAddr.addr }}
</view>
<view class="arrow" />
</view>
</view>
<!-- 商品详情 -->
<view class="prod-item">
<block
v-for="(item, index) in orderItems"
:key="index"
>
<view
class="item-cont"
:data-ordernum="item.primaryOrderNo"
@tap="toOrderDetailPage"
>
<view class="prod-pic">
<image :src="item.pic" />
</view>
<view class="prod-info">
<view class="prodname">
{{ item.prodName }}
</view>
<view class="prod-info-cont">
{{ item.skuName }}
</view>
<view class="price-nums">
<text class="prodprice">
<text class="symbol">
</text>
<text class="big-num">
{{ wxs.parsePrice(item.price)[0] }}
</text>
<text class="small-num">
.{{ wxs.parsePrice(item.price)[1] }}
</text>
</text>
<text class="prodcount">
x{{ item.prodCount }}
</text>
</view>
</view>
</view>
</block>
<view class="total-num">
<text class="prodcount">
{{ totalCount }}件商品
</text>
<view class="prodprice">
合计
<text class="symbol">
</text>
<text class="big-num">
{{ wxs.parsePrice(total)[0] }}
</text>
<text class="small-num">
.{{ wxs.parsePrice(total)[1] }}
</text>
</view>
</view>
</view>
<!-- 订单详情 -->
<view class="order-msg">
<view class="msg-item">
<view
class="item coupon"
@tap="showCouponPopup"
>
<text class="item-tit">
优惠券
</text>
<text
v-if="!coupons.canUseCoupons"
class="item-txt"
>
暂无可用
</text>
<text class="coupon-btn">
{{ coupons.totalLength ? coupons.totalLength : 0 }}
</text>
<text class="arrow" />
</view>
<view class="item">
<text>买家留言</text>
<input
v-model="remarks"
placeholder="给卖家留言"
>
</view>
</view>
</view>
<view class="order-msg">
<view class="msg-item">
<view class="item">
<view class="item-tit">
订单总额
</view>
<view class="item-txt price">
<text class="symbol">
</text>
<text class="big-num">
{{ wxs.parsePrice(total)[0] }}
</text>
<text class="small-num">
.{{ wxs.parsePrice(total)[1] }}
</text>
</view>
</view>
<view class="item">
<view class="item-tit">
运费
</view>
<view class="item-txt price">
<text class="symbol">
</text>
<text class="big-num">
{{ wxs.parsePrice(transfee)[0] }}
</text>
<text class="small-num">
.{{ wxs.parsePrice(transfee)[1] }}
</text>
</view>
</view>
<view class="item">
<view class="item-tit">
优惠金额
</view>
<view class="item-txt price">
<text class="symbol">
-
</text>
<text class="big-num">
{{ wxs.parsePrice(shopReduce)[0] }}
</text>
<text class="small-num">
.{{ wxs.parsePrice(shopReduce)[1] }}
</text>
</view>
</view>
<view class="item payment">
<view class="item-txt price">
小计
<text class="symbol">
</text>
<text class="big-num">
{{ wxs.parsePrice(actualTotal)[0] }}
</text>
<text class="small-num">
.{{ wxs.parsePrice(actualTotal)[1] }}
</text>
</view>
</view>
</view>
</view>
</view>
<!-- 底部栏 -->
<view class="submit-order-footer">
<view class="sub-order">
<view class="item-txt">
合计
<view class="price">
<text class="symbol">
</text>
<text class="big-num">
{{ wxs.parsePrice(actualTotal)[0] }}
</text>
<text class="small-num">
.{{ wxs.parsePrice(actualTotal)[1] }}
</text>
</view>
</view>
</view>
<view
class="footer-box"
@tap="toPay"
>
提交订单
</view>
</view>
</view>
<!-- 选择优惠券弹窗 -->
<view
v-if="popupShow"
class="popup-hide"
>
<view class="popup-box">
<view class="popup-tit">
<text>优惠券</text>
<text
class="close"
@tap="closePopup"
/>
</view>
<view class="coupon-tabs">
<view
:class="'coupon-tab ' + (couponSts==1?'on':'')"
data-sts="1"
@tap="changeCouponSts"
>
可用优惠券({{ coupons.canUseCoupons.length ? coupons.canUseCoupons.length : 0 }})
</view>
<view
:class="'coupon-tab ' + (couponSts==2?'on':'')"
data-sts="2"
@tap="changeCouponSts"
>
不可用优惠券({{ coupons.unCanUseCoupons.length ? coupons.unCanUseCoupons.length : 0 }})
</view>
</view>
<view class="popup-cnt">
<block v-if="couponSts == 1">
<view
v-for="(item, index) in coupons.canUseCoupons"
:key="index"
>
<coupon
:item="item"
order="true"
can-use="true"
@check-coupon="checkCoupon"
/>
</view>
</block>
<block v-if="couponSts == 2">
<view
v-for="(item, index) in coupons.unCanUseCoupons"
:key="index"
>
<coupon
:item="item"
order="true"
can-use="false"
/>
</view>
</block>
<view class="botm-empty" />
</view>
<view
v-if="couponSts==1"
class="coupon-ok"
>
<text @tap="choosedCoupon">
确定
</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
const wxs = number()
let orderEntry = '0' // 0 1
/**
* 生命周期函数--监听页面加载
*/
onLoad((options) => {
orderEntry = options.orderEntry
})
const userAddr = ref(null)
/**
* 生命周期函数--监听页面显示
*/
onShow(() => {
const pages = getCurrentPages()
const currPage = pages[pages.length - 1]
if (currPage.selAddress === 'yes') {
//
userAddr.value = currPage.item
}
//
loadOrderData()
})
let couponIds = []
const coupons = ref({})
const total = ref(0)
const actualTotal = ref(0)
const orderItems = ref([])
const totalCount = ref(0)
const transfee = ref(0)
const shopReduce = ref('')
/**
* 加载订单数据
*/
const loadOrderData = () => {
let addrId = 0
if (userAddr.value != null) {
addrId = userAddr.value.addrId
}
uni.showLoading({
mask: true
})
http.request({
url: '/p/order/confirm',
method: 'POST',
data: {
addrId,
orderItem: orderEntry === '1' ? JSON.parse(uni.getStorageSync('orderItem')) : undefined,
basketIds: orderEntry === '0' ? JSON.parse(uni.getStorageSync('basketIds')) : undefined,
couponIds,
userChangeCoupon: 1
}
})
.then(({ data }) => {
uni.hideLoading()
let orderItems = []
data.shopCartOrders[0].shopCartItemDiscounts?.forEach(itemDiscount => {
orderItems = orderItems.value?.concat(itemDiscount.shopCartItems)
})
if (data.shopCartOrders[0].coupons) {
const canUseCoupons = []
const unCanUseCoupons = []
data.shopCartOrders[0].coupons?.forEach(coupon => {
if (coupon.canUse) {
canUseCoupons.push(coupon)
} else {
unCanUseCoupons.push(coupon)
}
})
coupons.value = {
totalLength: data.shopCartOrders[0].coupons.length,
canUseCoupons,
unCanUseCoupons
}
}
orderItems.value = orderItems
actualTotal.value = data.actualTotal
total.value = data.total
totalCount.value = data.totalCount
userAddr.value = data.userAddr
transfee.value = data.shopCartOrders[0].transfee
shopReduce.value = data.shopCartOrders[0].shopReduce
})
.catch(err => {
uni.hideLoading()
chooseCouponErrHandle(err)
})
}
/**
* 优惠券选择出错处理方法
*/
const chooseCouponErrHandle = (res) => {
//
if (res.statusCode == 601) {
uni.showToast({
title: res.data,
icon: 'none',
duration: 3000,
success: () => {
couponIds = []
}
})
setTimeout(() => {
loadOrderData()
}, 2500)
}
}
/**
* 提交订单
*/
const toPay = () => {
if (!userAddr.value) {
uni.showToast({
title: '请选择地址',
icon: 'none'
})
return
}
submitOrder()
}
const remarks = ref('')
const submitOrder = () => {
uni.showLoading({
mask: true
})
http.request({
url: '/p/order/submit',
method: 'POST',
data: {
orderShopParam: [{
remarks: remarks.value,
shopId: 1
}]
}
})
.then(({ data }) => {
uni.hideLoading()
normalPay(data.orderNumbers)
})
}
/**
* 模拟支付直接提交成功
* @param orderNumbers
*/
const normalPay = (orderNumbers) => {
uni.showLoading({
mask: true
})
http.request({
url: '/p/order/normalPay',
method: 'POST',
data: {
orderNumbers
}
})
.then(({ data }) => {
uni.hideLoading()
if (data) {
uni.showToast({
title: '模拟支付成功',
icon: 'none'
})
setTimeout(() => {
uni.navigateTo({
url: '/pages/pay-result/pay-result?sts=1&orderNumbers=' + orderNumbers
})
}, 1200)
} else {
uni.showToast({
title: '支付失败!',
icon: 'none'
})
}
})
}
const couponSts = ref(1)
const changeCouponSts = (e) => {
couponSts.value = e.currentTarget.dataset.sts
}
const popupShow = ref(false)
const showCouponPopup = () => {
popupShow.value = true
}
const closePopup = () => {
popupShow.value = false
}
/**
* 去地址页面
*/
const toAddrListPage = () => {
uni.navigateTo({
url: '/pages/delivery-address/delivery-address?order=0'
})
}
/**
* 确定选择好的优惠券
*/
const choosedCoupon = () => {
loadOrderData()
popupShow.value = false
}
/**
* 优惠券子组件发过来
*/
const checkCoupon = (e) => {
const index = couponIds.indexOf(e.detail.couponId)
if (index === -1) {
couponIds.push(e.detail.couponId)
} else {
couponIds.splice(index, 1)
}
}
</script>
<style scoped lang="scss">
@use './submit-order.scss';
</style>

@ -133,6 +133,12 @@ const http = {
}
})
},
onRequestFail: (params, responseData) => {
console.error('============== 请求异常 ==============')
console.log('接口地址: ', params.url)
console.log('异常信息: ', responseData)
console.error('============== 请求异常 end ==========')
},
/**
* 登录成功后执行
* @param {Object} result 登录成功返回的数据

Loading…
Cancel
Save