新增积分锁客页面,基础设置,商品设置,兑换记录
This commit is contained in:
415
pageMarket/points/addProduct.vue
Normal file
415
pageMarket/points/addProduct.vue
Normal file
@@ -0,0 +1,415 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<u-form ref="formRef" :model="form" :rules="rules" label-position="top">
|
||||
<view class="card">
|
||||
<u-form-item>
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">商品类型</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<u-radio-group v-model="form.goodsCategory">
|
||||
<u-radio label="优惠券" name="优惠券"></u-radio>
|
||||
<u-radio label="其它商品" name="其它商品"></u-radio>
|
||||
</u-radio-group>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item prop="couponId" v-if="includesString(form.goodsCategory, '优惠券')">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">选择优惠券</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="ipt">
|
||||
<my-select-coupon v-model="form.couponId"></my-select-coupon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item prop="goodsName">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">商品名称</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="ipt">
|
||||
<u-input placeholder="请输入" :maxlength="30" v-model="form.goodsName"></u-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item prop="goodsImageUrl" v-if="includesString(form.goodsCategory, '其它商品')">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">商品图片</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<my-upload-img v-model="form.goodsImageUrl"></my-upload-img>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item prop="requiredPoints">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">所需积分</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="ipt">
|
||||
<u-input placeholder="请输入" :maxlength="8" v-model="form.requiredPoints" @change="requiredPointsInput">
|
||||
<template #suffix>
|
||||
<text>积分</text>
|
||||
</template>
|
||||
</u-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item>
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">额外价格</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="ipt">
|
||||
<u-input placeholder="请输入" :maxlength="8" v-model="form.extraPrice" @change="extraPriceInput">
|
||||
<template #suffix>
|
||||
<text>元</text>
|
||||
</template>
|
||||
</u-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item prop="quantity">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">数量</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="ipt">
|
||||
<u-input placeholder="请输入" :maxlength="8" v-model="form.quantity" @change="quantityInput"></u-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item>
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">排序值</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="ipt">
|
||||
<u-input placeholder="请输入" :maxlength="8" v-model="form.sort" @change="sortInput"></u-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item prop="limitQuota">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">每人限购</text>
|
||||
<u-switch v-model="isLimitQuota" :active-value="1" :inactive-value="0" @change="isLimitQuotaChange"></u-switch>
|
||||
</view>
|
||||
<view class="info" v-if="isLimitQuota == 1">
|
||||
<view class="ipt">
|
||||
<u-input placeholder="请输入限购数量" :maxlength="8" v-model="form.limitQuota" @change="limitQuotaInput"></u-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item prop="limitQuota">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">发放方式</text>
|
||||
<text class="intro">
|
||||
<template class="tips" v-if="includesString(form.goodsCategory, '优惠券')">系统发放</template>
|
||||
<template class="tips" v-if="includesString(form.goodsCategory, '其它商品')">需要用户到店内领取核销</template>
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="card" v-if="includesString(form.goodsCategory, '其它商品')">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">商品图片</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<my-upload-imgs v-model="imgs"></my-upload-imgs>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="card">
|
||||
<u-form-item prop="limitQuota">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">是否上架</text>
|
||||
<u-switch v-model="form.status" :active-value="1" :inactive-value="0"></u-switch>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
</view>
|
||||
</u-form>
|
||||
<my-footer-btn type="horizontal" showCancel @confirm="submitHandle"></my-footer-btn>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { pointsGoodsPost, pointsGoodsDetail } from '@/http/api/market/point.js';
|
||||
import { includesString, filterNumberInput } from '@/utils/index.js';
|
||||
|
||||
const formRef = ref(null);
|
||||
const isLimitQuota = ref(0);
|
||||
const imgs = ref([]);
|
||||
const form = ref({
|
||||
id: '',
|
||||
goodsCategory: '优惠券', // 商品类型 优惠券 其它商品
|
||||
couponId: '', // 优惠券id
|
||||
goodsName: '', // 商品名称/优惠券名称
|
||||
goodsImageUrl: '', // 商品图片URL
|
||||
requiredPoints: '', // 所需积分
|
||||
extraPrice: '', // 额外价格
|
||||
quantity: '', // 数量
|
||||
sort: 0,
|
||||
status: 1, // 是否上架 1-是 0-否
|
||||
receiveType: '', // 领取方式 店内自取、系统发放
|
||||
limitQuota: '', // 限购数量
|
||||
goodsDescription: '' // 商品详情
|
||||
});
|
||||
|
||||
function isLimitQuotaChange() {
|
||||
form.value.limitQuota = '';
|
||||
}
|
||||
|
||||
const rules = ref({
|
||||
couponId: [
|
||||
{
|
||||
required: true,
|
||||
trigger: ['blur'],
|
||||
message: '请选择优惠券',
|
||||
validator: (rule, value, callback) => {
|
||||
if (form.value.couponId === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
goodsName: [
|
||||
{
|
||||
required: true,
|
||||
trigger: ['blur'],
|
||||
message: '请输入',
|
||||
validator: (rule, value, callback) => {
|
||||
if (form.value.goodsName === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
goodsImageUrl: [
|
||||
{
|
||||
required: true,
|
||||
trigger: ['change'],
|
||||
message: '请上传商品封面图',
|
||||
validator: (rule, value, callback) => {
|
||||
if (form.value.goodsImageUrl === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
requiredPoints: [
|
||||
{
|
||||
required: true,
|
||||
trigger: ['blur'],
|
||||
message: '请输入',
|
||||
validator: (rule, value, callback) => {
|
||||
if (form.value.requiredPoints < 0 || form.value.requiredPoints === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
quantity: [
|
||||
{
|
||||
required: true,
|
||||
trigger: ['blur'],
|
||||
message: '请输入',
|
||||
validator: (rule, value, callback) => {
|
||||
if (form.value.quantity < 0 || form.value.quantity === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
limitQuota: [
|
||||
{
|
||||
trigger: ['blur'],
|
||||
message: '请输入限购数量',
|
||||
validator: (rule, value, callback) => {
|
||||
if (isLimitQuota.value == 1 && form.value.limitQuota === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
function requiredPointsInput(e) {
|
||||
setTimeout(() => {
|
||||
form.value.requiredPoints = filterNumberInput(e, 1);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function extraPriceInput(e) {
|
||||
setTimeout(() => {
|
||||
form.value.extraPrice = filterNumberInput(e);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function quantityInput(e) {
|
||||
setTimeout(() => {
|
||||
form.value.quantity = filterNumberInput(e, 1);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function sortInput(e) {
|
||||
setTimeout(() => {
|
||||
form.value.sort = filterNumberInput(e, 1);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function limitQuotaInput(e) {
|
||||
setTimeout(() => {
|
||||
form.value.limitQuota = filterNumberInput(e, 1);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
// 提交
|
||||
function submitHandle() {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '保存中...',
|
||||
mask: true
|
||||
});
|
||||
const data = { ...form.value };
|
||||
if (imgs.value.length > 0) {
|
||||
data.goodsDescription = JSON.stringify(imgs.value);
|
||||
}
|
||||
await pointsGoodsPost(data);
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'none'
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1000);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
uni.hideLoading();
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
// 积分:商品:详情
|
||||
async function pointsGoodsDetailAjax() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中...',
|
||||
mask: true
|
||||
});
|
||||
const obj = await pointsGoodsDetail(form.value.id);
|
||||
form.value = obj;
|
||||
if (obj.goodsDescription !== '') {
|
||||
imgs.value = JSON.parse(obj.goodsDescription);
|
||||
}
|
||||
if (obj.limitQuota !== '' && obj.limitQuota !== null) {
|
||||
isLimitQuota.value = 1;
|
||||
} else {
|
||||
isLimitQuota.value = 0;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
uni.hideLoading();
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.id) {
|
||||
form.value.id = options.id;
|
||||
uni.setNavigationBarTitle({
|
||||
title: '编辑商品'
|
||||
});
|
||||
pointsGoodsDetailAjax();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
padding: 28upx;
|
||||
}
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 20px;
|
||||
padding: 28upx;
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 28upx;
|
||||
}
|
||||
}
|
||||
.switch-wrap {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
.top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.t {
|
||||
font-size: 32upx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
padding-top: 16upx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16upx;
|
||||
.i {
|
||||
font-size: 28upx;
|
||||
color: #666;
|
||||
}
|
||||
.ipt {
|
||||
flex: 1;
|
||||
}
|
||||
.t {
|
||||
font-size: 24upx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
142
pageMarket/points/components/coupon-icon.vue
Normal file
142
pageMarket/points/components/coupon-icon.vue
Normal file
@@ -0,0 +1,142 @@
|
||||
<!-- 优惠券图标 -->
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="icon icon1" v-if="props.item[props.typeKey] == 1">
|
||||
<view class="top">
|
||||
<text class="i">¥</text>
|
||||
<text class="num">{{ props.item.discountAmount }}</text>
|
||||
</view>
|
||||
<view class="intro">
|
||||
<text class="t">满{{ props.item.fullAmount }}可用</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="icon icon2" v-if="props.item[props.typeKey] == 2">
|
||||
<view class="top">
|
||||
<text class="i">{{ props.item.discountNum }}件</text>
|
||||
<text class="num">商品兑换</text>
|
||||
</view>
|
||||
<view class="intro">
|
||||
<text class="t">满{{ props.item.fullAmount }}可用</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="icon icon3" v-if="props.item[props.typeKey] == 3">
|
||||
<view class="top">
|
||||
<text class="num">{{ props.item.discountRate / 10 }}折</text>
|
||||
</view>
|
||||
<view class="intro">
|
||||
<text class="t">满{{ props.item.fullAmount }}可用</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="icon icon2" v-if="props.item[props.typeKey] == 4">
|
||||
<view class="top">
|
||||
<text class="i">第二件</text>
|
||||
<text class="num">半价券</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="icon icon2" v-if="props.item[props.typeKey] == 6">
|
||||
<view class="top">
|
||||
<text class="i">买一送</text>
|
||||
<text class="num">一券</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
typeKey: {
|
||||
type: String,
|
||||
default: 'type'
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$color: #ff1c1c;
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&.icon1 {
|
||||
.top {
|
||||
.i {
|
||||
color: $color;
|
||||
font-size: 24upx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.num {
|
||||
color: $color;
|
||||
font-size: 72upx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.icon2 {
|
||||
.top {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.i {
|
||||
color: $color;
|
||||
font-size: 34upx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.num {
|
||||
color: $color;
|
||||
font-size: 34upx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.icon3 {
|
||||
.top {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.i {
|
||||
color: $color;
|
||||
font-size: 34upx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.num {
|
||||
color: $color;
|
||||
font-size: 52upx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.intro {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.t {
|
||||
font-size: 22upx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
326
pageMarket/points/components/productPage.vue
Normal file
326
pageMarket/points/components/productPage.vue
Normal file
@@ -0,0 +1,326 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="list">
|
||||
<view class="item" v-for="item in listData.list" :key="item.id">
|
||||
<view class="top">
|
||||
<text class="t">排序值:{{ item.sort }}</text>
|
||||
<view class="quantity" @click="showEdtorQuantityHandle(item)">
|
||||
<text class="t">库存:{{ item.quantity }}</text>
|
||||
<u-icon name="edit-pen" color="#999"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-wrap">
|
||||
<view class="left">
|
||||
<view class="icon" v-if="includesString(item.goodsCategory, '其它商品')">
|
||||
<image class="img" :src="item.goodsImageUrl" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="icon border" v-if="includesString(item.goodsCategory, '优惠券')">
|
||||
<couponIcon :item="item.couponInfo" typeKey="couponType" />
|
||||
</view>
|
||||
<view class="info-wrap">
|
||||
<text class="name">{{ item.goodsName }}</text>
|
||||
<text class="num">{{ item.requiredPoints }}积分 + {{ item.extraPrice || 0 }}元</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="status-wrap">
|
||||
<u-switch v-model="item.status" :active-value="1" :inactive-value="0" @change="statusChange($event, item)"></u-switch>
|
||||
<text class="t">
|
||||
<template v-if="item.status == 0">上架</template>
|
||||
<template v-if="item.status == 1">下架</template>
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="footer-wrap">
|
||||
<view class="btn">
|
||||
<u-button shape="circle" @click="delHandle(item)">删除</u-button>
|
||||
</view>
|
||||
<view class="btn">
|
||||
<u-button type="primary" shape="circle" @click="toEditor(item)">编辑</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-loadmore :status="listData.status"></u-loadmore>
|
||||
<u-popup :show="showEdtorQuantity" mode="center" :safeAreaInsetBottom="false" @close="showEdtorQuantity = false">
|
||||
<view class="quantity-wrap">
|
||||
<view class="title">
|
||||
<text class="t">修改库存</text>
|
||||
</view>
|
||||
<view class="form-content">
|
||||
<u-form :model="quantityItem" :rules="quantityFormRules">
|
||||
<u-form-item label="数量">
|
||||
<u-input v-model="quantityItem.quantity" placeholder="请输入数量" @change="quantityInput" clearable></u-input>
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
<view class="quantity-footer">
|
||||
<view class="btn">
|
||||
<u-button style="width: 100%" shape="circle" @click="showEdtorQuantity = false">取消</u-button>
|
||||
</view>
|
||||
<view class="btn">
|
||||
<u-button type="primary" style="width: 100%" shape="circle" @click="submitQuntity">确认</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, reactive } from 'vue';
|
||||
import { onReachBottom } from '@dcloudio/uni-app';
|
||||
import { pointsGoodsPage, pointsGoodsPost, pointsGoodsDel } from '@/http/api/market/point.js';
|
||||
import { filterNumberInput, includesString } from '@/utils/index.js';
|
||||
import couponIcon from './coupon-icon.vue';
|
||||
|
||||
const listData = reactive({
|
||||
page: 1,
|
||||
size: 10,
|
||||
status: 'loading',
|
||||
list: []
|
||||
});
|
||||
|
||||
function reachBottom() {
|
||||
if (listData.status != 'nomore') {
|
||||
listData.page++;
|
||||
pointsGoodsPageAjax();
|
||||
}
|
||||
}
|
||||
|
||||
// 积分:商品:列表
|
||||
async function pointsGoodsPageAjax(page = listData.page) {
|
||||
try {
|
||||
const res = await pointsGoodsPage({
|
||||
page: page,
|
||||
size: listData.size
|
||||
});
|
||||
|
||||
if (listData.page == 1) {
|
||||
listData.list = res.records;
|
||||
} else {
|
||||
listData.list.push(...res.records);
|
||||
}
|
||||
|
||||
if (res.pageNumber >= res.totalPage) {
|
||||
listData.status = 'nomore';
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 状态修改
|
||||
function statusChange(e, item) {
|
||||
pointsGoodsPostAjax(item);
|
||||
}
|
||||
|
||||
// 积分:商品:新增/修改
|
||||
async function pointsGoodsPostAjax(item) {
|
||||
try {
|
||||
await pointsGoodsPost(item);
|
||||
pointsGoodsPageAjax();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示修改库存
|
||||
const quantityItem = ref({});
|
||||
const showEdtorQuantity = ref(false);
|
||||
const quantityFormRules = ref({
|
||||
quantity: [
|
||||
{
|
||||
required: true,
|
||||
trigger: ['blur'],
|
||||
message: '请输入',
|
||||
validator: (rule, value, callback) => {
|
||||
if (quantityItem.value.quantity < 0 || quantityItem.value.quantity === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
function quantityInput(e) {
|
||||
setTimeout(() => {
|
||||
quantityItem.value.quantity = filterNumberInput(e, 1);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function showEdtorQuantityHandle(item) {
|
||||
quantityItem.value = { ...item };
|
||||
showEdtorQuantity.value = true;
|
||||
}
|
||||
|
||||
// 提交库存修改
|
||||
async function submitQuntity() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '保存中...',
|
||||
mask: true
|
||||
});
|
||||
await pointsGoodsPost(quantityItem.value);
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'none'
|
||||
});
|
||||
pointsGoodsPageAjax();
|
||||
showEdtorQuantity.value = false;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
uni.hideLoading();
|
||||
}
|
||||
|
||||
// 删除
|
||||
function delHandle(item) {
|
||||
uni.showModal({
|
||||
title: '注意',
|
||||
content: `确认要删除${item.goodsName}商品吗?`,
|
||||
success: async (res) => {
|
||||
try {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({
|
||||
title: '删除中...',
|
||||
mask: true
|
||||
});
|
||||
await pointsGoodsDel(item.id);
|
||||
uni.showToast({
|
||||
title: '已删除',
|
||||
icon: 'none'
|
||||
});
|
||||
let index = listData.list.findIndex((val) => val.id == item.id);
|
||||
listData.list.splice(index, 1);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
uni.hideLoading();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function toEditor(item) {
|
||||
uni.navigateTo({
|
||||
url: `/pageMarket/points/addProduct?id=${item.id}`
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
reachBottom,
|
||||
pointsGoodsPageAjax
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
pointsGoodsPageAjax();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.list {
|
||||
padding-bottom: 28upx;
|
||||
.item {
|
||||
border-radius: 16upx;
|
||||
background-color: #fff;
|
||||
padding: 28upx;
|
||||
&:not(:first-child) {
|
||||
margin-top: 28upx;
|
||||
}
|
||||
.top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 44upx;
|
||||
.t {
|
||||
font-size: 24upx;
|
||||
color: #666;
|
||||
}
|
||||
.quantity {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4upx;
|
||||
}
|
||||
}
|
||||
.goods-wrap {
|
||||
display: flex;
|
||||
padding: 28upx 0;
|
||||
.left {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon {
|
||||
$size: 180upx;
|
||||
width: $size;
|
||||
height: $size;
|
||||
&.border {
|
||||
border: 1px solid #ececec;
|
||||
border-radius: 16upx;
|
||||
padding: 16upx;
|
||||
}
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 16upx;
|
||||
}
|
||||
}
|
||||
.info-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 28upx;
|
||||
padding-left: 20upx;
|
||||
.name {
|
||||
font-size: 28upx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
.status-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4upx;
|
||||
.t {
|
||||
font-size: 24upx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-wrap {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 28upx;
|
||||
.btn {
|
||||
width: 140upx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.quantity-wrap {
|
||||
width: 80vw;
|
||||
.title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 28upx;
|
||||
.t {
|
||||
font-size: 32upx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
.form-content {
|
||||
padding: 0 28upx;
|
||||
}
|
||||
.quantity-footer {
|
||||
display: flex;
|
||||
gap: 28upx;
|
||||
padding: 28upx;
|
||||
.btn {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
414
pageMarket/points/components/record.vue
Normal file
414
pageMarket/points/components/record.vue
Normal file
@@ -0,0 +1,414 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="tab-wrap" :style="{ top: `${top}px` }">
|
||||
<view class="item" :class="{ active: tabsActive == index }" v-for="(item, index) in tabs" :key="index" @click="changeTabHandle(index)">
|
||||
<text class="t">{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list">
|
||||
<view class="item" v-for="item in listData.list" :key="item.id">
|
||||
<view class="top">
|
||||
<text class="t">{{ item.orderNo }}</text>
|
||||
<u-tag :type="statusFilter(item.status).type" plain plainFill>{{ item.status }}</u-tag>
|
||||
</view>
|
||||
<view class="row">
|
||||
<text class="name">用户:{{ item.nickName }} {{ item.phone }}</text>
|
||||
</view>
|
||||
<view class="goods-wrap">
|
||||
<view class="left">
|
||||
<view class="icon" v-if="includesString(item.goodsCategory, '其它商品')">
|
||||
<image class="img" :src="item.goodsImageUrl" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="icon border" v-if="includesString(item.goodsCategory, '优惠券')">
|
||||
<couponIcon :item="item.couponInfo" typeKey="couponType" />
|
||||
</view>
|
||||
<view class="info-wrap">
|
||||
<text class="name">{{ item.pointsGoodsName }}</text>
|
||||
<text class="num">x{{ item.number }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="status-wrap">
|
||||
<text class="t">{{ item.spendPoints }}积分 + {{ item.extraPaymentAmount }}元</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="row">
|
||||
<text class="t">下单时间:{{ item.createTime }}</text>
|
||||
</view>
|
||||
<view class="row" v-if="item.checkoutTime">
|
||||
<text class="t">核销时间:{{ item.checkoutTime }}</text>
|
||||
</view>
|
||||
<view class="footer-wrap" v-if="includesString(item.status, '退款中') || includesString(item.status, '待核销')">
|
||||
<view class="btn" v-if="includesString(item.status, '退款中')">
|
||||
<u-button type="error" shape="circle" @click="refundCostHandle(item)">审核</u-button>
|
||||
</view>
|
||||
<view class="btn" v-if="includesString(item.status, '待核销')">
|
||||
<u-button type="primary" shape="circle" @click="checkoutHandle(item)">核销</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-loadmore :status="listData.status"></u-loadmore>
|
||||
<u-popup :show="showRefundPopup" :round="20" mode="bottom" closeable @close="showRefundPopup = false">
|
||||
<view class="refund-popup-content">
|
||||
<view class="refund-popup-title">
|
||||
<text class="t">退款审核</text>
|
||||
</view>
|
||||
<view class="form">
|
||||
<u-form :model="refundForm" label-width="70" label-position="left">
|
||||
<u-form-item label="是否同意">
|
||||
<u-radio-group v-model="refundForm.type">
|
||||
<u-radio label="同意" :name="1" :customStyle="{ marginRight: '15px' }"></u-radio>
|
||||
<u-radio label="驳回" :name="0"></u-radio>
|
||||
</u-radio-group>
|
||||
</u-form-item>
|
||||
<u-form-item label="驳回原因" v-if="refundForm.type === 0">
|
||||
<u-textarea type="textarea" v-model="refundForm.reason" placeholder="请输入驳回原因"></u-textarea>
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
<view class="dialog-footer">
|
||||
<view class="btn">
|
||||
<u-button @click="showRefundPopup = false" shape="circle" style="width: 100%">取消</u-button>
|
||||
</view>
|
||||
<div class="btn">
|
||||
<u-button type="primary" shape="circle" @click="returnCostConfirmHandle" :loading="refundLoading" style="width: 100%">确认</u-button>
|
||||
</div>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { goodsRecordPage, goodsRecordCkecout, goodsRecordAgreeRefund, goodsRecordRejectRefund } from '@/http/api/market/point.js';
|
||||
import { includesString } from '@/utils/index.js';
|
||||
import couponIcon from './coupon-icon.vue';
|
||||
|
||||
const props = defineProps({
|
||||
top: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
});
|
||||
|
||||
const tabsActive = ref(0);
|
||||
|
||||
const tabs = ref([
|
||||
{
|
||||
value: '',
|
||||
label: '全部'
|
||||
},
|
||||
{
|
||||
value: '待核销',
|
||||
label: '待核销'
|
||||
},
|
||||
{
|
||||
value: '已完成',
|
||||
label: '已完成'
|
||||
},
|
||||
{
|
||||
value: '退款中',
|
||||
label: '售后'
|
||||
}
|
||||
]);
|
||||
|
||||
const statusList = ref([
|
||||
{
|
||||
label: '待支付',
|
||||
type: 'info'
|
||||
},
|
||||
{
|
||||
label: '待核销',
|
||||
type: 'warning'
|
||||
},
|
||||
{
|
||||
label: '已完成',
|
||||
type: 'info'
|
||||
},
|
||||
{
|
||||
label: '退款中',
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
label: '已退款',
|
||||
type: 'info'
|
||||
}
|
||||
]);
|
||||
|
||||
function statusFilter(status) {
|
||||
const obj = statusList.value.find((item) => item.label == status);
|
||||
if (obj) {
|
||||
return obj;
|
||||
} else {
|
||||
return {
|
||||
label: status,
|
||||
type: 'info'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 切换tab
|
||||
function changeTabHandle(index) {
|
||||
tabsActive.value = index;
|
||||
listData.status = 'loading';
|
||||
listData.page = 1;
|
||||
listData.list = [];
|
||||
goodsRecordPageAjax();
|
||||
}
|
||||
|
||||
const listData = reactive({
|
||||
page: 1,
|
||||
size: 10,
|
||||
status: 'loading',
|
||||
list: []
|
||||
});
|
||||
|
||||
function reachBottom() {
|
||||
if (listData.status != 'nomore') {
|
||||
listData.page++;
|
||||
goodsRecordPageAjax();
|
||||
}
|
||||
}
|
||||
|
||||
// 确认核销
|
||||
function checkoutHandle(item) {
|
||||
uni.showModal({
|
||||
title: '注意',
|
||||
content: `确认要核销吗?`,
|
||||
success: async (res) => {
|
||||
try {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({
|
||||
title: '核销中...',
|
||||
mask: true
|
||||
});
|
||||
await goodsRecordCkecout(item.couponCode);
|
||||
goodsRecordPageAjax();
|
||||
uni.showToast({
|
||||
title: '已核销',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
uni.hideLoading();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const refundLoading = ref(false);
|
||||
const showRefundPopup = ref(false);
|
||||
const refundForm = ref({
|
||||
type: 1,
|
||||
recordId: '',
|
||||
orderNo: '',
|
||||
reason: ''
|
||||
});
|
||||
|
||||
// 显示退款操作
|
||||
function refundCostHandle(row) {
|
||||
refundForm.value.recordId = row.id;
|
||||
refundForm.value.orderNo = row.orderNo;
|
||||
showRefundPopup.value = true;
|
||||
}
|
||||
|
||||
// 退款操作
|
||||
async function returnCostConfirmHandle() {
|
||||
try {
|
||||
refundLoading.value = true;
|
||||
if (refundForm.value.type == 1) {
|
||||
// 同意
|
||||
await goodsRecordAgreeRefund(refundForm.value);
|
||||
} else {
|
||||
// 驳回
|
||||
await goodsRecordRejectRefund(refundForm.value);
|
||||
}
|
||||
showRefundPopup.value = false;
|
||||
uni.showToast({
|
||||
title: '操作成功',
|
||||
icon: 'none'
|
||||
});
|
||||
goodsRecordPageAjax();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
setTimeout(() => {
|
||||
refundLoading.value = false;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// 积分:积分商品:兑换记录
|
||||
async function goodsRecordPageAjax(page = listData.page) {
|
||||
try {
|
||||
const res = await goodsRecordPage({
|
||||
page: page,
|
||||
size: listData.size,
|
||||
status: tabs.value[tabsActive.value].value
|
||||
});
|
||||
|
||||
if (listData.page == 1) {
|
||||
listData.list = res.records;
|
||||
} else {
|
||||
listData.list.push(...res.records);
|
||||
}
|
||||
|
||||
if (res.pageNumber >= res.totalPage) {
|
||||
listData.status = 'nomore';
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
reachBottom,
|
||||
goodsRecordPageAjax
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
goodsRecordPageAjax();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
padding-top: 50px;
|
||||
}
|
||||
.tab-wrap {
|
||||
$color: #318afe;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
z-index: 999;
|
||||
.item {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-bottom: 1px solid #fff;
|
||||
.t {
|
||||
font-size: 28upx;
|
||||
color: #333;
|
||||
}
|
||||
&.active {
|
||||
border-bottom-color: $color;
|
||||
.t {
|
||||
color: $color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.list {
|
||||
padding-bottom: 28upx;
|
||||
.item {
|
||||
background-color: #fff;
|
||||
border-radius: 20upx;
|
||||
padding: 28upx;
|
||||
&:not(:first-child) {
|
||||
margin-top: 28upx;
|
||||
}
|
||||
.top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.t {
|
||||
font-size: 28upx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.row {
|
||||
.name {
|
||||
font-size: 28upx;
|
||||
color: #333;
|
||||
}
|
||||
.t {
|
||||
font-size: 24upx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.goods-wrap {
|
||||
display: flex;
|
||||
padding: 28upx 0;
|
||||
.left {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon {
|
||||
$size: 180upx;
|
||||
width: $size;
|
||||
height: $size;
|
||||
&.border {
|
||||
border: 1px solid #ececec;
|
||||
border-radius: 16upx;
|
||||
padding: 16upx;
|
||||
}
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 16upx;
|
||||
}
|
||||
}
|
||||
.info-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 28upx;
|
||||
padding-left: 20upx;
|
||||
.name {
|
||||
font-size: 28upx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
.status-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.t {
|
||||
font-size: 32upx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer-wrap {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 28upx;
|
||||
padding-top: 28upx;
|
||||
.btn {
|
||||
width: 180upx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.refund-popup-content {
|
||||
padding: 0 28upx;
|
||||
.refund-popup-title {
|
||||
padding: 28upx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.t {
|
||||
font-size: 32upx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.form {
|
||||
padding: 28upx;
|
||||
}
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
gap: 28upx;
|
||||
.btn {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
290
pageMarket/points/components/setting.vue
Normal file
290
pageMarket/points/components/setting.vue
Normal file
@@ -0,0 +1,290 @@
|
||||
<template>
|
||||
<view class="form">
|
||||
<u-form ref="formRef" :model="form" :rules="rules" label-width="200px" label-position="top">
|
||||
<view class="card">
|
||||
<u-form-item>
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">开启积分</text>
|
||||
<u-switch v-model="form.enableRewards" :active-value="1" :inactive-value="0"></u-switch>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text class="t">开启后,所有用户可通过消费获得积分及可用积分抵扣支付</text>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="card">
|
||||
<u-form-item prop="consumeAmount">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">消费送积分</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text class="i">每消费</text>
|
||||
<view class="ipt">
|
||||
<u-input placeholder="请输入" :maxlength="8" v-model="form.consumeAmount" @change="consumeAmountInput">
|
||||
<template #suffix>
|
||||
<text>元</text>
|
||||
</template>
|
||||
</u-input>
|
||||
</view>
|
||||
<text class="i">获得1积分</text>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item prop="minPaymentAmount">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">可抵扣门槛</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="ipt">
|
||||
<u-input placeholder="请输入" :maxlength="8" v-model="form.minPaymentAmount" @change="minPaymentAmountInput">
|
||||
<template #suffix>
|
||||
<text>元</text>
|
||||
</template>
|
||||
</u-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item prop="maxDeductionRatio">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">最高抵扣比例</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="ipt">
|
||||
<u-input placeholder="请输入" :maxlength="8" v-model="form.maxDeductionRatio" @change="maxDeductionRatioInput">
|
||||
<template #suffix>
|
||||
<text>%</text>
|
||||
</template>
|
||||
</u-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item prop="equivalentPoints">
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">抵扣积分比例</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text class="i">1元等于</text>
|
||||
<view class="ipt">
|
||||
<u-input placeholder="请输入" :maxlength="8" v-model="form.equivalentPoints" @change="equivalentPointsInput">
|
||||
<template #suffix>
|
||||
<text>积分</text>
|
||||
</template>
|
||||
</u-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="card">
|
||||
<u-form-item>
|
||||
<view class="switch-wrap">
|
||||
<view class="top">
|
||||
<text class="t">开启积分商城</text>
|
||||
<u-switch v-model="form.enablePointsMall" :active-value="1" :inactive-value="0"></u-switch>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
</view>
|
||||
</u-form>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { filterNumberInput } from '@/utils/index.js';
|
||||
import { pointsConfigPost, pointsConfigGet } from '@/http/api/market/point.js';
|
||||
|
||||
const formRef = ref(null);
|
||||
const form = ref({
|
||||
enableRewards: 0,
|
||||
consumeAmount: '', // 每消费xx元赠送1积分
|
||||
minPaymentAmount: '', // 下单实付抵扣门槛
|
||||
maxDeductionRatio: 100, // 下单最高抵扣比例
|
||||
equivalentPoints: '', // 下单抵扣积分比例 1元=?积分
|
||||
enablePointsMall: 0 // 开启积分商城
|
||||
});
|
||||
|
||||
const rules = ref({
|
||||
consumeAmount: [
|
||||
{
|
||||
required: true,
|
||||
trigger: ['blur'],
|
||||
message: '请输入',
|
||||
validator: (rule, value, callback) => {
|
||||
if (form.value.consumeAmount < 0 || form.value.consumeAmount === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
minPaymentAmount: [
|
||||
{
|
||||
required: true,
|
||||
trigger: ['blur'],
|
||||
message: '请输入',
|
||||
validator: (rule, value, callback) => {
|
||||
if (form.value.minPaymentAmount < 0 || form.value.minPaymentAmount === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
maxDeductionRatio: [
|
||||
{
|
||||
required: true,
|
||||
trigger: ['blur'],
|
||||
message: '请输入',
|
||||
validator: (rule, value, callback) => {
|
||||
if (form.value.maxDeductionRatio < 0 || form.value.maxDeductionRatio === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
equivalentPoints: [
|
||||
{
|
||||
required: true,
|
||||
trigger: ['blur'],
|
||||
message: '请输入',
|
||||
validator: (rule, value, callback) => {
|
||||
if (form.value.equivalentPoints < 0 || form.value.equivalentPoints === '') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
function consumeAmountInput(e) {
|
||||
setTimeout(() => {
|
||||
form.value.consumeAmount = filterNumberInput(e);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function minPaymentAmountInput(e) {
|
||||
setTimeout(() => {
|
||||
form.value.minPaymentAmount = filterNumberInput(e);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function maxDeductionRatioInput(e) {
|
||||
setTimeout(() => {
|
||||
form.value.maxDeductionRatio = filterNumberInput(e, 1);
|
||||
if (form.value.maxDeductionRatio > 100) {
|
||||
form.value.maxDeductionRatio = 100;
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function equivalentPointsInput(e) {
|
||||
setTimeout(() => {
|
||||
form.value.equivalentPoints = filterNumberInput(e, 1);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
// 提交
|
||||
function submitHandle() {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '保存中...',
|
||||
mask: true
|
||||
});
|
||||
await pointsConfigPost(form.value);
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'none'
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
uni.hideLoading();
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
// 获取配置
|
||||
async function pointsConfigGetAjax() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中...',
|
||||
mask: true
|
||||
});
|
||||
const res = await pointsConfigGet();
|
||||
form.value = res;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
setTimeout(() => {
|
||||
uni.hideLoading();
|
||||
}, 300);
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
submitHandle
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
pointsConfigGetAjax();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 20px;
|
||||
padding: 28upx;
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 28upx;
|
||||
}
|
||||
}
|
||||
.switch-wrap {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
.top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.t {
|
||||
font-size: 32upx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
padding-top: 16upx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16upx;
|
||||
.i {
|
||||
font-size: 28upx;
|
||||
color: #666;
|
||||
}
|
||||
.ipt {
|
||||
flex: 1;
|
||||
}
|
||||
.t {
|
||||
font-size: 24upx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
155
pageMarket/points/index.vue
Normal file
155
pageMarket/points/index.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<my-header-card
|
||||
:options="{
|
||||
name: '积分锁客',
|
||||
intro: '下单可获得积分,再次下单可使用积分抵扣',
|
||||
icon: 'https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/4/11e5482336a94c2a91a10e2bf289126e.png'
|
||||
}"
|
||||
@load="(e) => (headHeight = e.height)"
|
||||
></my-header-card>
|
||||
<view class="content">
|
||||
<setting ref="settingRef" name="setting" key="setting" v-if="tabsActive == 0" />
|
||||
<productPage ref="productPageRef" name="productPage" key="productPage" v-if="tabsActive == 1" />
|
||||
<record ref="recordRef" name="record" key="record" :top="headHeight + 54" v-if="tabsActive == 2" />
|
||||
</view>
|
||||
<view class="tab-wrap" :style="{ top: `${headHeight}px` }">
|
||||
<view class="tab-list">
|
||||
<view class="item" v-for="(item, index) in tabs" :class="{ active: tabsActive == index }" :key="item.value" @click="tabClickHandle(item, index)">
|
||||
<text class="t">{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<my-footer-btn type="horizontal" showCancel @confirm="settingRef.submitHandle()" @cancel="backHandle" v-if="tabsActive == 0"></my-footer-btn>
|
||||
<my-footer-btn confirmText="添加商品" type="horizontal" @confirm="toAddProduct" v-if="tabsActive == 1"></my-footer-btn>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app';
|
||||
import setting from './components/setting.vue';
|
||||
import productPage from './components/productPage.vue';
|
||||
import record from './components/record.vue';
|
||||
|
||||
const settingRef = ref(null);
|
||||
const productPageRef = ref(null);
|
||||
const recordRef = ref(null);
|
||||
|
||||
const headHeight = ref(0);
|
||||
const tabsActive = ref(2);
|
||||
const tabs = ref([
|
||||
{
|
||||
value: 1,
|
||||
label: '基础设置'
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: '商品设置'
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
label: '兑换记录'
|
||||
},
|
||||
{
|
||||
value: 4,
|
||||
label: '用户积分'
|
||||
}
|
||||
]);
|
||||
|
||||
function tabClickHandle(item, index) {
|
||||
tabsActive.value = index;
|
||||
}
|
||||
|
||||
function backHandle() {
|
||||
uni.navigateBack();
|
||||
}
|
||||
|
||||
function toAddProduct() {
|
||||
uni.navigateTo({
|
||||
url: '/pageMarket/points/addProduct'
|
||||
});
|
||||
}
|
||||
|
||||
onReachBottom(() => {
|
||||
switch (tabsActive.value) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
productPageRef.value.reachBottom();
|
||||
break;
|
||||
case 2:
|
||||
recordRef.value.reachBottom();
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
switch (tabsActive.value) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
productPageRef.value.pointsGoodsPageAjax(1);
|
||||
break;
|
||||
case 2:
|
||||
recordRef.value.goodsRecordPageAjax(1);
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="scss">
|
||||
$bgColor: #e6f0ff;
|
||||
$primarColor: #318afe;
|
||||
.content {
|
||||
padding: calc(54px + 28upx) 28upx 28upx;
|
||||
}
|
||||
.tab-wrap {
|
||||
height: 54px;
|
||||
padding: 10px 14px;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
z-index: 999;
|
||||
.tab-list {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
background-color: $bgColor;
|
||||
padding: 6upx;
|
||||
border-radius: 12upx;
|
||||
.item {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8upx;
|
||||
.t {
|
||||
color: $primarColor;
|
||||
font-size: 28upx;
|
||||
}
|
||||
&.active {
|
||||
background-color: $primarColor;
|
||||
.t {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user