feat(商户信息修改)

This commit is contained in:
Ankkaya 2024-09-14 18:15:03 +08:00
parent 250f08c074
commit 6f0d928fb2
11 changed files with 1418 additions and 41 deletions

View File

@ -0,0 +1,290 @@
<template>
<view>
<view v-if="isShow" class="time_mask" :class="{'uni-timer-mask-show':timeMaskShow}" @tap="close"></view>
<view v-if="isShow" class="yx_time_slot" :class="{'fadelogIn1':timeMaskShow}">
<view class="time_top_box">
<view class="time_close" @click="close">取消</view>
<view class="time_text">{{title}}</view>
<view class="time_comfirm" @click="confirm">确认</view>
</view>
<view class="typelist">
<view class="typeobj" :class="{'typeobj_hover':typeIndex==index}" v-for="(item,index) in typeList" :key="index" @click="handleType(index)">
<view class="text">{{item}}</view>
<view class="line"></view>
</view>
</view>
<!-- 时间选择 -->
<view class="yx_timer_sel">
<swiper class="sel_swiper" :current="typeIndex" @change="swiperChange">
<swiper-item>
<view>
<picker-view :value="startvalue" :indicator-style="indicatorStyle" @change="bindstartChange" class="sel_swiper-item">
<picker-view-column>
<view class="item" v-for="(item,index) in timeHour" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="item" v-for="(item,index) in timeMin" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</swiper-item>
<swiper-item>
<view>
<picker-view :value="endvalue" :indicator-style="indicatorStyle" @change="bindendChange" class="sel_swiper-item">
<picker-view-column>
<view class="item" v-for="(item,index) in timeHour" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="item" v-for="(item,index) in timeMin" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</swiper-item>
</swiper>
</view>
</view>
</view>
</template>
<script>
export default {
name:"time_slot",
props: {
title: {
type: String,
default: () => {
return "选择时间段";
}
},
},
data() {
return {
timeMaskShow:false,//
isShow:false,//
typeList:["开始时间","结束时间"],
typeIndex:0,//
startvalue:[14,0],//14 00
endvalue:[15,0],//15 00
indicatorStyle: 'height: 50px;',
// timeList:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],
timeHour:[],
timeMin:[],//
};
},
mounted() {
//
let timeHour = []
let timeMin = []
for (let i = 0; i < 24; i++) {
timeHour.push(this.formatNumber(i))
}
for (let i = 0; i < 60; i++) {
timeMin.push(this.formatNumber(i))
}
this.timeHour = timeHour
this.timeMin = timeMin
},
methods: {
swiperChange(event) {
this.typeIndex = event.detail.current
},
//
formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
},
//
bindstartChange(e){
console.log(e)
this.startvalue = e.detail.value
},
//
bindendChange(e){
console.log(e)
this.endvalue = e.detail.value
},
/**
* 关闭弹窗
*/
close() {
this.timeMaskShow = false
this.$nextTick(() => {
setTimeout(() => {
this.isShow = false
this.$emit('close')
}, 300)
})
},
/**
* 确认按钮
*/
confirm() {
if(this.typeIndex==0){
this.endvalue = [this.startvalue[0]+1,0]
this.typeIndex = 1
}else{
if(this.startvalue[0]<this.endvalue[0] || (this.startvalue[0]==this.endvalue[0]&&this.startvalue[1]<this.endvalue[1])){
var obj = {
start:{
hour:this.timeHour[this.startvalue[0]],
min:this.timeMin[this.startvalue[1]]
},
end:{
hour:this.timeHour[this.endvalue[0]],
min:this.timeMin[this.endvalue[1]]
}
}
this.$emit('confirm',obj)
this.close()
}else{
uni.showToast({
icon:"error",
title:"结束时间要大于开始时间"
})
}
}
},
/**
* 打开日历弹窗
*/
open() {
this.typeIndex = 0
this.isShow = true
this.$nextTick(() => {
setTimeout(() => {
this.timeMaskShow = true
}, 50)
})
},
//
handleType(index){
if(index!=this.typeIndex){
if(index==1){
this.endvalue = [this.startvalue[0]+1,0]
}
this.typeIndex = index
}
}
}
};
</script>
<style lang="scss" scoped>
.time_mask {
position: fixed;
bottom: 0;
top: 0;
left: 0;
right: 0;
background-color: $uni-bg-color-mask;
transition-property: opacity;
transition-duration: 0.3s;
opacity: 0;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.yx_time_slot{
background-color: #FFFFFF;
width: 100%;
height: 750rpx;
position: fixed;
bottom: calc(var(--window-bottom));
left: 0;
right: 0;
z-index: 99;
transition-property: transform;
transition-duration: 0.3s;
transform: translateY(460px);
border-top-left-radius: 20px;
border-top-right-radius: 20px;
.time_top_box{
width: 100%;
height: 80rpx;
display: flex;
align-items: center;
justify-content: space-between;
.time_close,.time_comfirm{
width: 100rpx;
color: #6666;
font-size: 28rpx;
font-weight: 400;
text-align: center;
}
.time_comfirm{
color: #ff3000;
}
.time_text{
flex: 1;
font-size: 30rpx;
font-weight: 800;
text-align: center;
}
}
}
.uni-timer-mask-show{
opacity: 1;
}
/* 从下往上弹窗动画 */
.fadelogIn1 {
// -webkit-animation: fadelogIn 0.5s;
// animation: fadelogIn 0.5s;
transform: translateY(0);
}
.typelist{
width: 100%;
height: 70rpx;
display: flex;
align-items: center;
.typeobj{
width: 158rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.text{
height: 65rpx;
line-height: 65rpx;
font-size: 28rpx;
color: #333333;
}
.line{
width: 1rpx;
height: 5rpx;
}
}
.typeobj_hover{
.text{
font-weight: 600;
}
.line{
width: 88rpx;
transition: width .5s;
background-color: #4360F7;
}
}
}
.yx_timer_sel{
width: 100%;
margin-top: 38rpx;
.sel_swiper{
// width: 80%;
// margin: 0 auto;
height: 500rpx;
}
.sel_swiper-item{
height: 500rpx;
.item {
height: 50px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
}
}
</style>

View File

@ -108,6 +108,24 @@
{
"root": "pages/user",
"pages": [
{
"path": "info/detail",
"style": {
"navigationBarTitleText": "个人信息"
},
"meta": {
"auth": true
}
},
{
"path": "info/index",
"style": {
"navigationBarTitleText": "修改信息"
},
"meta": {
"auth": true
}
},
{
"path": "wallet/money",
"style": {

View File

@ -10,9 +10,9 @@
<view class="description ss-font-26">{{ userInfo.mobile }}</view>
</view>
</view>
<!-- <view>
<text style="color: #fff; font-size: 20px" class="cicon-settings-o"></text>
</view> -->
<view @click="handleNav">
<text style="color: #fff; font-size: 20px" class="cicon-settings-o"></text>
</view>
</view>
<view class="statistic ss-m-t-24">
@ -102,6 +102,10 @@ function navService(item) {
peach.$router.go(item.path)
}
function handleNav() {
peach.$router.go('/pages/user/info/detail')
}
function logOut() {
uni.showModal({
title: '提示',

175
pages/user/info/detail.vue Normal file
View File

@ -0,0 +1,175 @@
<template>
<pb-layout title="个人信息" navbar="normal" class="merchant-success" :bgStyle="{ backgroundColor: '#fff' }">
<view class="info">
<view class="details">
<template v-for="item in Object.keys(list)">
<view class="item" v-if="res?.id">
<view>
{{ list[item] }}
</view>
<view v-if="!res[item]?.includes('http')">
{{ res[item] }}
</view>
<p-uploader
v-else
v-model:url="res[item]"
fileMediatype="image"
limit="1"
readonly
:imageStyles="{ width: '168rpx', height: '168rpx' }"
/>
</view>
</template>
</view>
<view class="footer-box">
<button class="ss-reset-button back-btn shadow" @tap="navBack">返回首页</button>
<button class="ss-reset-button save-btn shadow" @tap="navToEdit">修改信息</button>
</view>
</view>
</pb-layout>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import UserApi from '@/peach/api/member/user'
import peach from '@/peach'
const list = ref({
name: '店铺名称',
logo: '门店LOGO',
timezone: '营业时间',
tradeImg: '营业执照',
address: '详细地址',
contactName: '联系人',
contactPhone: '联系电话',
idCard: '身份证号',
idCardFront: '身份证正面',
idCardBack: '身份证反面',
alipayLogonId: '支付宝账号',
payee: '收款人姓名',
bankName: '银行名称',
bankBranchName: '开户行',
bankNo: '银行卡号',
bankOpenContact: '开户人',
bankCardFront: '银行卡正面',
bankCardBack: '银行卡反面',
})
const res = ref(null)
//
function getMerchantInfo() {
UserApi.getUserDetail().then((data) => {
data.data.address = data.data.address.replace(/\//g, '')
data.data.timezone =
formatNumber(data.data.openingTime[0]) +
':' +
formatNumber(data.data.openingTime[1]) +
'~' +
formatNumber(data.data.closingTime[0]) +
':' +
formatNumber(data.data.closingTime[1])
res.value = data.data
})
}
//
function formatNumber(num) {
return num < 10 ? '0' + num : num
}
function navToEdit() {
peach.$router.go('/pages/user/info/index')
}
function navBack() {
peach.$router.back()
}
onLoad(() => {
getMerchantInfo()
})
</script>
<style lang="scss" scoped>
.merchant-success {
.top {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
padding: 0 80rpx 40rpx;
margin-bottom: 40rpx;
background-color: #fff;
.note {
color: #999;
font-size: 28rpx;
}
.submit-btn {
height: 80rpx;
width: 100px;
border-radius: 40rpx;
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
color: $white;
}
}
.info {
background-color: #fff;
padding: 40rpx;
margin-bottom: 40rpx;
.title {
font-weight: 700;
font-size: 17px;
margin-bottom: 20px;
}
.details {
display: flex;
flex-direction: column;
gap: 10px;
.item {
display: flex;
align-items: flex-start;
font-size: 14px;
color: #333;
view:nth-child(2n) {
font-size: 14px;
color: #999;
}
view:nth-child(2n + 1) {
width: 100px;
}
}
}
}
.footer-box {
margin-top: 25px;
display: flex;
justify-content: space-around;
gap: 20px;
.save-btn {
width: 50%;
height: 80rpx;
border-radius: 40rpx;
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
color: $white;
}
.back-btn {
width: 50%;
border-radius: 40rpx;
border: 1px solid #000;
}
}
}
</style>

441
pages/user/info/index.vue Normal file
View File

@ -0,0 +1,441 @@
<!-- 商家入驻 -->
<template>
<pb-layout title="修改信息" navbar="inner" :bgStyle="{ color: 'rgb(245,28,19)' }" color="#fff">
<view class="page-bg" :style="[{ marginTop: '-' + Number(statusBarHeight + 88) + 'rpx' }]"> </view>
<view class="apply-form">
<uni-forms ref="formRef" v-model="formData" :rules="rules" label-position="top" label-width="160">
<uni-forms-item label="店铺名称" name="name" required>
<uni-easyinput type="text" v-model="formData.name" placeholder="请输入店铺名称" />
</uni-forms-item>
<uni-forms-item label="门店LOGO" name="logo" required>
<p-uploader
v-model:url="formData.logo"
fileMediatype="image"
limit="1"
mode="grid"
:imageStyles="{ width: '168rpx', height: '168rpx' }"
/>
</uni-forms-item>
<uni-forms-item label="营业时间" name="timezone" required @tap="showTime">
<uni-easyinput
v-model="formData.timezone"
disabled
:styles="{ disableColor: '#fff', color: '#333', borderColor: '#dcdfd6 !important' }"
placeholder="请选择营业时间"
>
<template v-slot:right>
<uni-icons type="right" />
</template>
</uni-easyinput>
</uni-forms-item>
<uni-forms-item label="营业执照" name="tradeImg" required>
<p-uploader
v-model:url="formData.tradeImg"
fileMediatype="image"
limit="1"
mode="grid"
:imageStyles="{ width: '168rpx', height: '168rpx' }"
/>
</uni-forms-item>
<uni-forms-item name="areaName" label="省市区" @tap="regionPickerRef.onOpen()" required>
<uni-easyinput
v-model="formData.areaName"
disabled
:styles="{ disableColor: '#fff', color: '#333', borderColor: '#dcdfd6 !important' }"
placeholder="请选择省市区"
>
<template v-slot:right>
<uni-icons type="right" />
</template>
</uni-easyinput>
</uni-forms-item>
<uni-forms-item name="detailAddress" label="详细地址" required>
<uni-easyinput type="textarea" v-model="formData.detailAddress" placeholder="请输入详细地址" clearable />
</uni-forms-item>
<uni-forms-item name="contactName" label="联系人" required>
<uni-easyinput type="text" v-model="formData.contactName" placeholder="请输入联系人" clearable />
</uni-forms-item>
<uni-forms-item label="联系电话" name="contactPhone" required>
<uni-easyinput type="number" v-model="formData.contactPhone" placeholder="请输入联系电话" />
</uni-forms-item>
<uni-forms-item label="身份证号" name="idCard" required>
<uni-easyinput type="idcard" v-model="formData.idCard" placeholder="请输入省份证号" />
</uni-forms-item>
<uni-forms-item label="身份证正面" name="idCardFront" required>
<p-uploader
v-model:url="formData.idCardFront"
fileMediatype="image"
limit="1"
mode="grid"
:imageStyles="{ width: '168rpx', height: '168rpx' }"
/>
</uni-forms-item>
<uni-forms-item label="身份证反面" name="idCardBack" required>
<p-uploader
v-model:url="formData.idCardBack"
fileMediatype="image"
limit="1"
mode="grid"
:imageStyles="{ width: '168rpx', height: '168rpx' }"
/>
</uni-forms-item>
<uni-forms-item label="支付宝账号" name="alipayLogonId" required>
<uni-easyinput type="text" v-model="formData.alipayLogonId" placeholder="请输入支付宝账号" />
</uni-forms-item>
<uni-forms-item label="收款人姓名" name="payee" required>
<uni-easyinput type="text" v-model="formData.payee" placeholder="请输入收款人姓名" />
</uni-forms-item>
<uni-forms-item label="银行名称" name="bankName" required>
<uni-easyinput type="text" v-model="formData.bankName" placeholder="请输入银行名称" />
</uni-forms-item>
<uni-forms-item label="开户行" name="bankBranchName" required>
<uni-easyinput type="text" v-model="formData.bankBranchName" placeholder="请输入开户行" />
</uni-forms-item>
<uni-forms-item label="银行卡号" name="bankNo" required>
<uni-easyinput type="number" v-model="formData.bankNo" placeholder="请输入银行卡号" />
</uni-forms-item>
<uni-forms-item label="开户人" name="bankOpenContact" required>
<uni-easyinput type="text" v-model="formData.bankOpenContact" placeholder="请输入开户人姓名" />
</uni-forms-item>
<uni-forms-item label="银行卡正面" name="bankCardFront" required>
<p-uploader
v-model:url="formData.bankCardFront"
fileMediatype="image"
limit="1"
mode="grid"
:imageStyles="{ width: '168rpx', height: '168rpx' }"
/>
</uni-forms-item>
<uni-forms-item label="银行卡反面" name="bankCardBack" required>
<p-uploader
v-model:url="formData.bankCardBack"
fileMediatype="image"
limit="1"
mode="grid"
:imageStyles="{ width: '168rpx', height: '168rpx' }"
/>
</uni-forms-item>
</uni-forms>
<view class="footer-box">
<button class="ss-reset-button save-btn ui-Shadow-Main" @tap="onSubmit">修改</button>
</view>
</view>
<!-- 省市区弹窗 -->
<p-region-picker ref="regionPickerRef" @confirm="onRegionConfirm" />
</pb-layout>
<!-- 时间弹窗 -->
<timeSlot ref="timeSlotRef" :title="'选择时间段'" @confirm="confirmTime"></timeSlot>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import sheep from '@/peach'
import $store from '@/peach/store'
import UserApi from '@/peach/api/member/user'
import { mobile, idCard, bankName, bankCode } from '@/peach/validate/form'
import timeSlot from '@/components/wanghexu-timeslot/wanghexu-timeslot.vue'
import _ from 'lodash'
const userStore = $store('user')
const formData = ref({
name: '',
logo: '',
timezone: '',
tradeImg: '',
idCard: '',
idCardFront: '',
idCardBack: '',
contactPhone: '',
areaName: '',
detailAddress: '',
contactName: '',
bankNo: '',
bankName: '',
bankBranchName: '',
bankCardFront: '',
bankCardBack: '',
bankOpenContact: '',
})
const regionPickerRef = ref(null)
const rules = {
name: {
rules: [
{
required: true,
errorMessage: '请输入店铺名称',
},
],
},
logo: {
rules: [
{
required: true,
errorMessage: '请上传店铺LOGO',
},
],
},
timezone: {
rules: [
{
required: true,
errorMessage: '请选择营业时间',
},
],
},
tradeImg: {
rules: [
{
required: true,
errorMessage: '请上传营业执照',
},
],
},
idCard: idCard,
idCardFront: {
rules: [
{
required: true,
errorMessage: '请上传身份证正面',
},
],
},
idCardBack: {
rules: [
{
required: true,
errorMessage: '请上传身份证反面',
},
],
},
alipayLogonId: {
rules: [
{
required: true,
errorMessage: '请输入支付宝账号',
},
],
},
payee: {
rules: [
{
required: true,
errorMessage: '请输入收款人姓名',
},
],
},
areaName: {
rules: [
{
required: true,
errorMessage: '请选择省市区',
},
],
},
contactName: {
rules: [
{
required: true,
errorMessage: '请输入联系人',
},
],
},
detailAddress: {
rules: [
{
required: true,
errorMessage: '请输入详细地址',
},
],
},
contactPhone: mobile,
bankNo: bankCode,
bankName: bankName,
bankBranchName: {
rules: [
{
required: true,
errorMessage: '请输入开户行名称',
},
],
},
bankCardFront: {
rules: [
{
required: true,
errorMessage: '请上传银行卡正面',
},
],
},
bankCardBack: {
rules: [
{
required: true,
errorMessage: '请上传银行卡反面',
},
],
},
bankOpenContact: {
rules: [
{
required: true,
errorMessage: '请输入开户人姓名',
},
],
},
}
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2
const timeSlotRef = ref(null)
const formRef = ref(null)
function onSubmit() {
formRef.value
.validate()
.then(async (res) => {
let tempObj = { ...res }
tempObj.id = formData.value.id
tempObj.memberUserId = userStore.userInfo.id
tempObj.address = tempObj.areaName.replace(/ /g, '/') + '/' + tempObj.detailAddress
tempObj.openingTime = tempObj.timezone.split('~')[0]
tempObj.closingTime = tempObj.timezone.split('~')[1]
delete tempObj.areaName
delete tempObj.detailAddress
delete tempObj.timezone
await UserApi.editUserInfo(tempObj)
peach.$router.go('/pages/user/info/detail', {
redirect: true,
})
})
.catch((err) => {
console.log('err', err)
})
}
//
function showTime() {
timeSlotRef.value.open()
}
//
function confirmTime(time) {
formData.value.timezone = time.start.hour + ':' + time.start.min + '~' + time.end.hour + ':' + time.end.min
}
//
function onRegionConfirm(e) {
formData.value.areaName = `${e.province_name}/${e.city_name}/${e.district_name}`
}
//
function getMerchantInfo() {
UserApi.getUserDetail().then((data) => {
formData.value = data.data
let index = data.data.address.lastIndexOf('/')
formData.value.areaName = data.data.address.substring(0, index)
formData.value.detailAddress = data.data.address.substring(index + 1)
formData.value.timezone =
data.data.openingTime[0].toString().padStart(2, '0') +
':' +
data.data.openingTime[1].toString().padStart(2, '0') +
'~' +
data.data.closingTime[0].toString().padStart(2, '0') +
':' +
data.data.closingTime[1].toString().padStart(2, '0')
})
}
//
async function getAreaList() {
let res = await UserApi.getAreaList()
uni.setStorageSync('areaData', res.data)
}
onLoad(async () => {
getMerchantInfo()
await getAreaList()
})
</script>
<style lang="scss" scoped>
.page-bg {
width: 100%;
height: 458rpx;
background: url('/static/merchant3.jpg') no-repeat;
background-size: 100% 100%;
}
.apply-form {
margin: -100rpx 16px;
padding: 20rpx;
background: #fff;
border-radius: 16rpx;
margin-bottom: 40px;
padding-bottom: 40rpx;
box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.04);
.shake {
animation: shake 0.05s linear 4 alternate;
}
@keyframes shake {
from {
transform: translateX(-10rpx);
}
to {
transform: translateX(10rpx);
}
}
:deep() {
.uni-easyinput__content-input {
font-size: 28rpx !important;
color: #333333 !important;
line-height: normal !important;
padding-left: 10px !important;
}
.uni-easyinput__placeholder-class {
font-size: 14px;
}
.is-disabled {
color: #333333;
}
}
.footer-box {
.save-btn {
height: 80rpx;
border-radius: 40rpx;
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
color: $white;
}
}
.agreement-box {
margin: -10px auto 10px;
.protocol-check {
transform: scale(0.7);
}
.agreement-text {
font-size: 26rpx;
font-weight: 500;
color: #999999;
.tcp-text {
color: var(--ui-BG-Main);
}
}
}
}
</style>

View File

@ -1,46 +1,71 @@
import request from '@/peach/request'
const UserUtil = {
// 获取用户信息
getUserInfo: () => {
return request({
url: '/particulars/member/get',
method: 'GET',
})
},
// 获取用户信息
getUserInfo: () => {
return request({
url: '/particulars/member/get',
method: 'GET',
})
},
// 获取钱包
getWalletInfo: () => {
return request({
url: '/pay/wallet/get',
method: 'GET',
})
},
// 获取钱包
getWalletInfo: () => {
return request({
url: '/pay/wallet/get',
method: 'GET',
})
},
// 首页统计
getHomeStatistics: () => {
return request({
url: '/statistics/index/get-count',
method: 'GET',
})
},
// 首页统计
getHomeStatistics: () => {
return request({
url: '/statistics/index/get-count',
method: 'GET',
})
},
/**
* @author Ankkaya
* @description 用户列表
* @param {String} mobile - 手机号
* @param {String} nickname - 用户昵称
* @param {Number} pageNo - 页码
* @param {Number} pageSize - 每页条数
* @returns {Type}
*/
getUserList: (data) => {
return request({
url: '/particulars/point/page-member',
method: 'GET',
params: data,
})
},
/**
* @author Ankkaya
* @description 用户列表
* @param {String} mobile - 手机号
* @param {String} nickname - 用户昵称
* @param {Number} pageNo - 页码
* @param {Number} pageSize - 每页条数
* @returns {Type}
*/
getUserList: (data) => {
return request({
url: '/particulars/point/page-member',
method: 'GET',
params: data,
})
},
// 用户详情
getUserDetail: () => {
return request({
url: '/shop/particulars/get',
method: 'GET',
})
},
// 修改用户信息
editUserInfo: (data) => {
return request({
url: '/shop/particulars/update',
method: 'PUT',
data,
})
},
// 区域列表
getAreaList: () => {
return request({
url: '/system/area/tree',
method: 'GET',
})
},
}
export default UserUtil

View File

@ -137,6 +137,19 @@ const GoodsApi = {
},
})
},
// 更改商品状态
changeProductStatus: (data) => {
return request({
url: '/product/spu/update-status',
method: 'PUT',
data,
custom: {
successMsg: '操作成功',
showSuccess: true,
},
})
},
}
export default GoodsApi

View File

@ -1,7 +1,12 @@
<template>
<view class="ss-goods-wrap">
<view v-if="size === 'lg'" class="lg-goods-card ss-flex ss-col-stretch" :style="[elStyles]" @click="onClick">
<image class="lg-img-box" :src="peach.$url.cdn(data.image || data.picUrl)" mode="aspectFill"></image>
<image
:class="['lg-img-box', data.status === 0 ? 'down' : '']"
:src="peach.$url.cdn(data.image || data.picUrl)"
mode="aspectFill"
></image>
<view v-if="data.status === 0" class="down-text">商品已下架</view>
<view class="lg-goods-content ss-flex-1 ss-flex-col ss-row-between ss-p-b-10 ss-p-t-20">
<view>
<view
@ -50,6 +55,9 @@
<view class="ss-flex ss-row-around" :style="btnStyles">
<button class="ss-reset-button btn-group" @click="clickGoods('detail')">详情</button>
<button class="ss-reset-button btn-group" @click="clickGoods('edit')">编辑</button>
<button class="ss-reset-button btn-group" @click="clickGoods('inventory')">
{{ data.status === 0 ? '上架' : '下架' }}
</button>
<button class="ss-reset-button btn-group btn-del" @click="clickGoods('del')">删除</button>
</view>
</view>
@ -180,12 +188,34 @@ function clickGoods(mark) {
}
},
})
} else if (mark === 'inventory') {
uni.showModal({
title: '提示',
content: `是否${props.data.status === 1 ? '下架' : '上架'}该商品?`,
success: async (res) => {
if (res.confirm)
await GoodsApi.changeProductStatus({
id: props.data.id,
status: props.data.status === 1 ? 0 : 1,
})
emits('refresh')
},
})
}
}
</script>
<style lang="scss" scoped>
.ss-goods-wrap {
.down {
filter: opacity(0.3);
}
.down-text {
position: absolute;
left: 75rpx;
top: 130rpx;
font-weight: 600;
}
.lg-goods-card {
overflow: hidden;
position: relative;

View File

@ -0,0 +1,252 @@
<!-- 省市区选择弹窗 -->
<template>
<uni-popup type="bottom" ref="pickerPopupRef" background-color="#fff">
<view class="ui-region-picker">
<p-toolbar
:cancelColor="cancelColor"
:confirmColor="confirmColor"
:cancelText="cancelText"
:confirmText="confirmText"
title="选择区域"
@cancel="onCancel"
@confirm="onConfirm('confirm')"
/>
<view class="ui-picker-body">
<picker-view
:value="state.currentIndex"
@change="change"
class="ui-picker-view"
@pickstart="pickstart"
@pickend="pickend"
>
<picker-view-column>
<view class="ui-column-item" v-for="province in provinceList" :key="province.id">
<view :style="getSizeByNameLength(province.name)">{{ province.name }}</view>
</view>
</picker-view-column>
<picker-view-column>
<view class="ui-column-item" v-for="city in cityList" :key="city.id">
<view :style="getSizeByNameLength(city.name)">{{ city.name }}</view>
</view>
</picker-view-column>
<picker-view-column>
<view class="ui-column-item" v-for="district in districtList" :key="district.id">
<view :style="getSizeByNameLength(district.name)">{{ district.name }}</view>
</view>
</picker-view-column>
</picker-view>
</view>
</view>
</uni-popup>
</template>
<script setup>
/**
* picker picker弹出选择器
* @property {Object} params 需要显示的参
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配默认false
* @property {Boolean} show-time-tag 时间模式时是否显示后面的年月日中文提示
* @property {String} cancel-color 取消按钮的颜色
* @property {String} confirm-color 确认按钮的颜色
* @property {String} confirm-text 确认按钮的文字
* @property {String} cancel-text 取消按钮的文字
* @property {String} default-region 默认选中的地区
* @property {String} default-code 默认选中的地区
* @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker默认true
* @property {String Number} z-index 弹出时的z-index值默认1075
* @property {Array} default-selector 数组形式其中每一项表示选择了range对应项中的第几个
* @property {String} range-key 当range参数的元素为对象时指定Object中的哪个key的值作为选择器显示内容
* @event {Function} confirm 点击确定按钮返回当前选择的值
* @event {Function} cancel 点击取消按钮返回当前选择的值
*/
import { computed, reactive, defineExpose, ref } from 'vue'
const props = defineProps({
// ""
cancelColor: {
type: String,
default: '#6666',
},
// ""
confirmColor: {
type: String,
default: 'var(--ui-BG-Main)',
},
//
cancelText: {
type: String,
default: '取消',
},
//
confirmText: {
type: String,
default: '确认',
},
})
const areaData = uni.getStorageSync('areaData')
const pickerPopupRef = ref(null)
const getSizeByNameLength = (name) => {
let length = name.length
if (length <= 7) return ''
if (length < 9) {
return 'font-size:28rpx'
} else {
return 'font-size: 24rpx'
}
}
const state = reactive({
currentIndex: [0, 0, 0],
moving: false, //
})
const emits = defineEmits(['confirm', 'cancel', 'change'])
const provinceList = areaData
const cityList = computed(() => {
return areaData[state.currentIndex[0]]?.children
})
const districtList = computed(() => {
return cityList.value[state.currentIndex[1]]?.children
})
//
const pickstart = () => {
// #ifdef MP-WEIXIN
state.moving = true
// #endif
}
//
const pickend = () => {
// #ifdef MP-WEIXIN
state.moving = false
// #endif
}
const onCancel = () => {
pickerPopupRef.value.close()
emits('cancel')
}
function onOpen() {
pickerPopupRef.value.open()
}
// picker
const change = (e) => {
if (state.currentIndex[0] === e.detail.value[0] && state.currentIndex[1] === e.detail.value[1]) {
//
state.currentIndex[2] = e.detail.value[2]
return
} else {
//
if (state.currentIndex[0] !== e.detail.value[0]) {
e.detail.value[1] = 0
}
e.detail.value[2] = 0
state.currentIndex = e.detail.value
}
emits('change', state.currentIndex)
}
//
const onConfirm = (event = null) => {
// #ifdef MP-WEIXIN
if (state.moving) return
// #endif
let index = state.currentIndex
let province = provinceList[index[0]]
let city = cityList.value[index[1]]
let district = districtList.value[index[2]]
let result = {
province_name: province.name,
province_id: province.id,
city_name: city.name,
city_id: city.id,
district_name: district.name,
district_id: district.id,
}
pickerPopupRef.value.close()
if (event) emits(event, result)
}
defineExpose({
onOpen,
})
</script>
<style lang="scss" scoped>
.ui-region-picker {
position: relative;
z-index: 999;
}
.ui-picker-view {
height: 100%;
box-sizing: border-box;
}
.ui-picker-header {
width: 100%;
height: 90rpx;
padding: 0 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
font-size: 30rpx;
background: #fff;
position: relative;
}
.ui-picker-header::after {
content: '';
position: absolute;
border-bottom: 1rpx solid #eaeef1;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
bottom: 0;
right: 0;
left: 0;
}
.ui-picker__title {
color: #333;
}
.ui-picker-body {
width: 100%;
height: 500rpx;
overflow: hidden;
background-color: #fff;
}
.ui-column-item {
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: #333;
padding: 0 8rpx;
}
.ui-btn-picker {
padding: 16rpx;
box-sizing: border-box;
text-align: center;
text-decoration: none;
}
.ui-opacity {
opacity: 0.5;
}
.ui-btn-picker--primary {
color: blue;
}
.ui-btn-picker--tips {
color: red;
}
</style>

View File

@ -0,0 +1,129 @@
<template>
<view class="p-toolbar" @touchmove.stop.prevent="noop" v-if="show">
<view class="p-toolbar__cancel__wrapper" hover-class="p-hover-class">
<text
class="p-toolbar__wrapper__cancel"
@tap="cancel"
:style="{
color: cancelColor,
}"
>
{{ cancelText }}
</text>
</view>
<text class="p-toolbar__title u-line-1" v-if="title">{{ title }}</text>
<view class="p-toolbar__confirm__wrapper" hover-class="p-hover-class">
<text
class="p-toolbar__wrapper__confirm"
@tap="confirm"
:style="{
color: confirmColor,
}"
>
{{ confirmText }}
</text>
</view>
</view>
</template>
<script>
/**
* Toolbar 工具条
* @description
* @tutorial https://www.uviewui.com/components/toolbar.html
* @property {Boolean} show 是否展示工具条默认 true
* @property {String} cancelText 取消按钮的文字默认 '取消'
* @property {String} confirmText 确认按钮的文字默认 '确认'
* @property {String} cancelColor 取消按钮的颜色默认 '#909193'
* @property {String} confirmColor 确认按钮的颜色默认 '#3c9cff'
* @property {String} title 标题文字
* @event {Function}
* @example
*/
export default {
name: 'SuToolbar',
props: {
//
show: {
type: Boolean,
default: true,
},
//
cancelText: {
type: String,
default: '取消',
},
//
confirmText: {
type: String,
default: '确认',
},
//
cancelColor: {
type: String,
default: '#909193',
},
//
confirmColor: {
type: String,
default: '#3c9cff',
},
//
title: {
type: String,
default: '',
},
},
methods: {
//
cancel() {
this.$emit('cancel')
},
//
confirm() {
this.$emit('confirm')
},
//
preventEvent(e) {
e && typeof e.stopPropagation === 'function' && e.stopPropagation()
},
//
noop(e) {
this.preventEvent(e)
},
},
}
</script>
<style lang="scss" scoped>
.p-toolbar {
height: 42px;
@include flex;
justify-content: space-between;
align-items: center;
&__wrapper {
&__cancel {
color: #111111;
font-size: 15px;
padding: 0 15px;
}
}
&__title {
color: #000000;
padding: 0 60rpx;
font-size: 16px;
flex: 1;
text-align: center;
}
&__wrapper {
&__confirm {
color: #ffffff;
font-size: 15px;
padding: 0 15px;
}
}
}
</style>

BIN
static/merchant3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB