Files
cashier_app/pageMarket/packagePopularize/addGoods.vue
2025-12-22 09:23:55 +08:00

1171 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<u-form ref="formRef" :model="form" :rules="rules" label-position="top">
<view class="card">
<u-form-item prop="useShops">
<view class="switch-wrap">
<view class="top">
<text class="t">可用门店</text>
</view>
<view class="info">
<view class="ipt" v-if="isMainShop()">
<my-shop-select-w v-model:useType="form.useShopType" v-model:selShops="form.useShops"></my-shop-select-w>
</view>
<view class="ipt" v-else>
<u-radio-group v-model="form.useShopType">
<u-radio label="仅本店" name="only"></u-radio>
</u-radio-group>
</view>
</view>
</view>
</u-form-item>
</view>
<view class="card">
<u-form-item prop="packageName">
<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.packageName"></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-textarea placeholder="请输入" :maxlength="50" v-model="form.description"></u-textarea>
</view>
</view>
</view>
</u-form-item>
</view>
<view class="card">
<u-form-item prop="images">
<view class="switch-wrap">
<view class="top column">
<text class="t">套餐图片</text>
<text class="tips">*建议优先选择jpg格式并且最好控制在500kb内</text>
</view>
<view class="info">
<my-upload-imgs v-model="form.images"></my-upload-imgs>
</view>
</view>
</u-form-item>
</view>
<view class="card">
<u-form-item prop="originPrice">
<view class="switch-wrap">
<view class="top">
<text class="t">原价</text>
</view>
<view class="info">
<view class="ipt">
<u-input v-model="form.originPrice" placeholder="请输入" @change="originalPriceInput">
<template #suffix>
<text></text>
</template>
</u-input>
</view>
</view>
</view>
</u-form-item>
<u-form-item prop="price">
<view class="switch-wrap">
<view class="top">
<text class="t">价格</text>
</view>
<view class="info">
<view class="ipt">
<u-input v-model="form.price" placeholder="请输入" @change="groupPriceInput">
<template #suffix>
<text></text>
</template>
</u-input>
</view>
</view>
</view>
</u-form-item>
</view>
<view class="card">
<u-form-item prop="packageContent">
<view class="switch-wrap">
<view class="top">
<text class="t">选择商品</text>
</view>
<view class="info">
<view class="package-wrap">
<view class="list">
<view class="item" v-for="(item, index) in form.packageContent" :key="index">
<view class="header">
<text class="t">{{ index + 1 }}组菜品</text>
<view class="del" @click="form.packageContent.splice(index, 1)">
<u-icon name="minus-circle-fill" color="red" size="14"></u-icon>
<text class="t">删除套餐组</text>
</view>
</view>
<view class="input-wrap">
<view class="ipt">
<u-input v-model="item.name" :maxlength="20" placeholder="请输入菜品组名"></u-input>
</view>
<view class="btn" @click="showGoodsDialogHandle(index)">
<u-icon name="plus-circle-fill" color="#318AFE"></u-icon>
<text class="t">导入商品</text>
</view>
<view class="btn" @click="addGoodsHandle(item)">
<u-icon name="plus" color="#318AFE"></u-icon>
<text class="t">添加商品</text>
</view>
</view>
<view class="table-wrap">
<view class="tab-head">
<view class="tr">
<view class="td">
<text class="t">名称</text>
</view>
<view class="td">
<text class="t">价格</text>
</view>
<view class="td">
<text class="t">数量</text>
</view>
<view class="td">
<text class="t">操作</text>
</view>
</view>
</view>
<view class="tb-body">
<view class="tr" v-for="(val, i) in item.packageProducts" :key="i">
<view class="td">
<u-input v-model="val.name" placeholder="商品名称"></u-input>
</view>
<view class="td">
<u-input
v-model="val.price"
placeholder="价格"
:maxlength="8"
@change="
(e) =>
mySetTimeout(() => {
val.price = filterNumberInput(e);
}, 50)
"
></u-input>
</view>
<view class="td">
<u-input
v-model="val.num"
placeholder="数量"
:maxlength="8"
@change="
(e) =>
mySetTimeout(() => {
val.num = filterNumberInput(e, 1);
}, 50)
"
></u-input>
</view>
<view class="td">
<text class="del" @click="item.packageProducts.splice(i, 1)">删除</text>
</view>
</view>
</view>
<view class="empty" v-if="item.packageProducts.length == 0">
<text class="t">请添加商品</text>
</view>
</view>
<view class="select_num_wrap">
<view class="label">
<text class="t">套餐{{ item.packageProducts.length }}{{ item.num }}</text>
</view>
<view class="ipt">
<u-input
v-model="item.num"
placeholder="请输入"
:maxlength="8"
@change="
(e) =>
mySetTimeout(() => {
item.num = filterNumberInput(e, 1);
}, 50)
"
></u-input>
</view>
</view>
</view>
</view>
<view class="package-wrap-btn" @click="addGroupHandle">
<view class="btn">
<u-icon name="plus" color="#318AFE"></u-icon>
<text class="t">添加菜品组</text>
</view>
</view>
</view>
</view>
</view>
</u-form-item>
</view>
<view class="card">
<u-form-item prop="useWeeks">
<view class="switch-wrap">
<view class="top column">
<text class="t">可用周期</text>
</view>
<view class="info">
<view class="ipt">
<my-week-sel v-model="form.useWeeks"></my-week-sel>
</view>
</view>
</view>
</u-form-item>
<u-form-item prop="useTimes">
<view class="switch-wrap">
<view class="top column">
<text class="t">指定时间段</text>
</view>
<view class="info">
<view class="ipt">
<my-hour-area :showType="false" v-model:startValue="startValue" v-model:endValue="endValue"></my-hour-area>
</view>
</view>
</view>
</u-form-item>
</view>
<view class="card">
<u-form-item>
<view class="switch-wrap">
<view class="top">
<text class="t">其他使用说明</text>
</view>
<view class="info">
<view class="ipt">
<u-textarea placeholder="请输入" :maxlength="50" v-model="form.otherDesc"></u-textarea>
</view>
</view>
</view>
</u-form-item>
</view>
<view class="card">
<u-form-item prop="tieredDiscount">
<view class="switch-wrap">
<view class="top">
<view class="two">
<text class="t">分享优惠阶梯</text>
<view class="tips">如果没有分享裂变需求可以不设置最多三级</view>
</view>
<view>
<u-button type="primary" :disabled="!form.price" v-if="form.tieredDiscount.length < 3" @click="addStepHandle">
{{ form.price ? '添加方案' : '请添加价格' }}
</u-button>
</view>
</view>
<view class="info">
<view class="step-wrap">
<view class="table-wrap">
<view class="tab-head">
<view class="tr">
<view class="td">
<text class="t">分享人数</text>
</view>
<view class="td">
<text class="t">价格</text>
</view>
<view class="td">
<text class="t">操作</text>
</view>
</view>
</view>
<view class="tb-body">
<view class="tr" v-for="(val, i) in form.tieredDiscount" :key="i">
<view class="td">
<text class="t">{{ val.peopleNum }}</text>
</view>
<view class="td">
<text class="t">{{ val.price }}</text>
</view>
<view class="td">
<text class="edit" @click="editorStepFormHandle(i)">编辑</text>
<text class="del" @click="form.tieredDiscount.splice(i, 1)">删除</text>
</view>
</view>
</view>
<view class="empty" v-if="form.tieredDiscount.length == 0">
<text class="t">请添加阶梯</text>
</view>
</view>
</view>
</view>
</view>
</u-form-item>
</view>
<view class="card">
<u-form-item prop="expireHours">
<view class="switch-wrap">
<view class="top column">
<text class="t">分享期限小时</text>
</view>
<view class="info">
<view class="ipt">
<u-input v-model="form.expireHours" placeholder="最小不低于1小时最大不超过72小时" @change="groupTimeoutHourInput"></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.onlineStatus" :active-value="1" :inactive-value="0"></u-switch>
</view>
</view>
</u-form-item>
</view>
<view class="card">
<u-form-item>
<view class="switch-wrap">
<view class="top column">
<text class="t">商品详情</text>
<text class="tips">*建议优先选择jpg格式并且最好控制在500kb内</text>
</view>
<view class="info">
<my-upload-imgs v-model="form.detailImages"></my-upload-imgs>
</view>
</view>
</u-form-item>
</view>
</u-form>
<my-footer-btn showCancel type="horizontal" @confirm="submitHandle" @cancel="backHandle"></my-footer-btn>
<u-popup :show="showStepDialog" mode="center" closeable :safe-area-inset-bottom="false" @close="stepDialogReset">
<view class="add-step-wrap">
<view class="title">
<text class="t">
{{ stepFormType == 'add' ? '添加阶梯' : '编辑阶梯' }}
</text>
</view>
<view class="content">
<u-form ref="stepFormRef" :model="stepForm" :rules="stepFormRules" :label-width="0">
<u-form-item prop="peopleNum">
<view class="switch-wrap">
<view class="top column">
<text class="t">分享人数</text>
</view>
<view class="info">
<view class="ipt">
<u-input
v-model="stepForm.peopleNum"
placeholder="请输入分享人数"
:maxlength="8"
@change="
(e) =>
mySetTimeout(() => {
stepForm.peopleNum = filterNumberInput(e, 1);
}, 50)
"
>
<template #suffix>
<text></text>
</template>
</u-input>
</view>
</view>
</view>
</u-form-item>
<u-form-item prop="price">
<view class="switch-wrap">
<view class="top column">
<text class="t">价格</text>
</view>
<view class="info">
<view class="ipt">
<u-input
v-model="stepForm.price"
placeholder="请输入价格"
:maxlength="8"
@change="
(e) =>
mySetTimeout(() => {
stepForm.price = filterNumberInput(e);
}, 50)
"
>
<template #suffix>
<text></text>
</template>
</u-input>
</view>
</view>
</view>
</u-form-item>
</u-form>
</view>
<view class="footer-btn-wrap">
<view class="btn">
<u-button style="width: 100%" @click="showStepDialog = false">取消</u-button>
</view>
<view class="btn">
<u-button type="primary" style="width: 100%" @click="stepFormSubmitHandle">确定</u-button>
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script setup>
import _ from 'lodash';
import { ref } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import { filterNumberInput } from '@/utils/index.js';
import { packageAddEdit } from '@/http/api/ware.js';
import { isMainShop } from '@/store/account.js';
// 封装全局定时器,适配多端
const mySetTimeout = (fn, delay) => {
if (typeof uni !== 'undefined') {
return setTimeout(fn, delay); // 小程序
} else {
return window.setTimeout(fn, delay); // H5
}
};
const type = ref('add'); // add添加商品 editor编辑商品
const formRef = ref(null);
const startValue = ref('');
const endValue = ref('');
const form = ref({
id: '',
useShopType: 'only', // only-仅本店 all全部 /custom 指定
useShops: [], // 可用门店指定门店时存储门店ID逗号分隔
packageName: '', // 套餐名称
description: '', // 商品描述
images: [], // 商品图片(多个用逗号分隔)
originPrice: '', // 原价
price: '', // 售价
packageContent: [], // 套餐内容
useTimes: '', // 可用时段08:00~21:30
useWeeks: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'], // 可用周期: [周一,周二]
otherDesc: '', // 其他描述
tieredDiscount: [], // 阶梯优惠
expireHours: '', // 分享期限小时不低于1小时最大72小时
onlineStatus: 1, // 上架状态0下架 1上架
detailImages: [] // 商品详情图片(多个用逗号分隔)
});
const rules = ref({
useShops: [
{
trigger: ['change'],
message: '请选择可用门店',
validator: (rule, value, callback) => {
if (form.value.useShopType == 'custom' && form.value.useShops.length == 0) {
return false;
} else {
return true;
}
}
}
],
packageName: [
{
required: true,
trigger: ['blur'],
message: '请输入',
validator: (rule, value, callback) => {
if (form.value.packageName === '') {
return false;
} else {
return true;
}
}
}
],
images: [
{
required: true,
trigger: ['blur'],
message: '请选择商品图片',
validator: (rule, value, callback) => {
if (form.value.images.length == 0) {
return false;
} else {
return true;
}
}
}
],
originPrice: [
{
required: true,
trigger: ['blur'],
message: '请输入',
validator: (rule, value, callback) => {
if (form.value.originPrice === '') {
return false;
} else {
return true;
}
}
}
],
price: [
{
required: true,
trigger: ['blur'],
message: '请输入',
validator: (rule, value, callback) => {
if (form.value.price === '') {
return false;
} else {
return true;
}
}
}
],
packageContent: [
{
required: true,
message: '请检查',
trigger: ['blur'],
validator: (rule, value, callback) => {
if (form.value.packageContent.length == 0) {
uni.showToast({
title: `请添加菜品组`,
icon: 'none'
});
return false;
} else {
let checkPass = true;
let errorMsg = '';
for (const [groupIndex, item] of form.value.packageContent.entries()) {
// 1. 校验菜品组名
if (item.name === '') {
errorMsg = `请输入第${groupIndex + 1}组的菜品组名`;
checkPass = false;
break; // 终止循环,只提示第一个错误
}
// 2. 校验该组是否添加商品
if (item.packageProducts.length === 0) {
errorMsg = `请给第${groupIndex + 1}组添加商品`;
checkPass = false;
break;
}
// 3. 校验组内商品(嵌套 entries() 获取商品索引)
let productError = false;
for (const [productIndex, val] of item.packageProducts.entries()) {
// 3.1 商品名称为空
if (val.name === '') {
errorMsg = `请输入第${groupIndex + 1}组菜品的第${productIndex + 1}项的商品名称`;
productError = true;
break;
}
// 3.2 商品价格为空
if (val.price === '') {
errorMsg = `请输入第${groupIndex + 1}组菜品的第${productIndex + 1}项的商品价格`;
productError = true;
break;
}
}
// 商品校验失败,终止整体循环
if (productError) {
checkPass = false;
break;
}
if (item.num === '') {
errorMsg = `请给第${groupIndex + 1}组输入几选几`;
checkPass = false;
break;
}
if (item.num > item.packageProducts.length) {
errorMsg = `${groupIndex + 1}组几选几输入有误,最大${item.packageProducts.length}`;
checkPass = false;
break;
}
}
if (!checkPass) {
uni.showToast({
title: errorMsg,
icon: 'none'
});
}
return checkPass;
}
}
}
],
useWeeks: [
{
required: true,
trigger: ['blur'],
message: '请选择可用周期',
validator: (rule, value, callback) => {
if (form.value.useWeeks.length === 0) {
return false;
} else {
return true;
}
}
}
],
useTimes: [
{
required: true,
trigger: ['blur'],
message: '请选择指定时间段',
validator: (rule, value, callback) => {
if (form.value.useTimes === '') {
return false;
} else {
return true;
}
}
}
],
expireHours: [
{
trigger: ['blur'],
validator: (rule, value, callback) => {
if (form.value.tieredDiscount.length && form.value.expireHours === '') {
return callback(new Error('请输入分享期限'));
} else if (form.value.expireHours > 72) {
return callback(new Error('最大不超过72小时'));
} else {
return true;
}
}
}
]
});
// 套餐组对象
const packageContentItem = ref({
name: '',
num: 1,
packageProducts: []
});
// 套餐组商品对象
const packageProductsItem = ref({
name: '',
price: '',
num: 1
});
// 添加套餐组
function addGroupHandle() {
form.value.packageContent.push(_.cloneDeep(packageContentItem.value));
}
// 添加商品
function addGoodsHandle(item) {
item.packageProducts.push(_.cloneDeep(packageProductsItem.value));
}
// 显示导入商品弹窗
const portGoodsIndex = ref(0);
function showGoodsDialogHandle(index) {
portGoodsIndex.value = index;
uni.navigateTo({
url: '/pageMarket/packagePopularize/selectGoods'
});
}
// 选择的商品
function selectProduceHandle() {
let obj = uni.getStorageSync('packageSelectGoods');
if (obj && obj.name) {
let data = _.cloneDeep(packageProductsItem.value);
data.name = obj.name;
data.price = obj.price;
form.value.packageContent[portGoodsIndex.value].packageProducts.push(data);
}
}
// ============= 添加阶梯 start
const addStepIndex = ref(0);
const showStepDialog = ref(false);
const stepFormRef = ref(null);
const stepForm = ref({
peopleNum: '',
price: ''
});
const stepFormType = ref('add');
const stepFormRules = ref({
peopleNum: [
{
required: true,
validator: (rule, value, callback) => {
if (addStepIndex.value == 1 && +stepForm.value.peopleNum <= +form.value.tieredDiscount[0].peopleNum) {
return callback(new Error('二阶段价格分享人数不可小于一阶段分享人数'));
} else if (addStepIndex.value == 2 && +stepForm.value.peopleNum <= +form.value.tieredDiscount[1].peopleNum) {
return callback(new Error('三阶段价格分享人数不可小于二阶段分享人数'));
} else {
return callback();
}
},
trigger: ['blur']
}
],
price: [
{
required: true,
validator: (rule, value, callback) => {
// 1. 空值校验(优先处理)
if (stepForm.value.price.trim() === '') {
return callback(new Error('请输入价格'));
}
// 统一转数值(避免字符串比较问题)
const currentPrice = +stepForm.value.price;
const originPrice = +form.value.price;
// 解构阶梯价格(转数值)
const [firstPrice, secondPrice, thirdPrice] = form.value.tieredDiscount.map((item) => +item.price);
// 2. 新增模式(原有逻辑不变)
if (stepFormType.value === 'add') {
if (addStepIndex.value === 0 && currentPrice > originPrice) {
return callback(new Error(`一阶段价格不可大于商品售价¥${originPrice}`));
} else if (addStepIndex.value === 1 && currentPrice >= firstPrice) {
return callback(new Error('二阶段价格不可大于等于一阶段价格'));
} else if (addStepIndex.value === 2 && currentPrice >= secondPrice) {
return callback(new Error('三阶段价格不可大于等于二阶段价格'));
} else {
return callback(); // 校验通过
}
}
// 3. 编辑模式(新增逻辑:瞻前顾后)
else if (stepFormType.value === 'editor') {
// 编辑第一阶段
if (addStepIndex.value === 0) {
// 规则:不大于原价 + 不小于第二阶段(若第二阶段存在)
if (currentPrice > originPrice) {
return callback(new Error(`一阶段价格不可大于商品售价¥${form.value.originPrice}`));
} else if (secondPrice && currentPrice <= secondPrice) {
// 第二阶段有值时,第一阶段需大于第二阶段
return callback(new Error('一阶段价格不可小于等于二阶段价格'));
} else {
return callback();
}
}
// 编辑第二阶段
else if (addStepIndex.value === 1) {
// 规则:不小于第一阶段 + 不大于第三阶段(若第三阶段存在)
const errors = [];
if (currentPrice >= firstPrice) {
errors.push('二阶段价格不可大于等于一阶段价格');
}
if (thirdPrice && currentPrice <= thirdPrice) {
// 第三阶段有值时,第二阶段需大于第三阶段
errors.push('二阶段价格不可小于等于三阶段价格');
}
if (errors.length > 0) {
return callback(new Error(errors.join('')));
} else {
return callback();
}
}
// 编辑第三阶段
else if (addStepIndex.value === 2) {
// 规则:仅校验不大于等于第二阶段(和新增一致)
if (currentPrice >= secondPrice) {
return callback(new Error('三阶段价格不可大于等于二阶段价格'));
} else {
return callback();
}
}
}
// 兜底:无匹配模式时校验通过
else {
return callback();
}
},
trigger: ['blur']
}
]
});
// 显示添加阶梯
function addStepHandle() {
stepFormType.value = 'add';
showStepDialog.value = true;
addStepIndex.value = form.value.tieredDiscount.length;
}
// 编辑优惠阶梯
function editorStepFormHandle(index) {
stepFormType.value = 'editor';
showStepDialog.value = true;
addStepIndex.value = index;
stepForm.value.peopleNum = form.value.tieredDiscount[index].peopleNum;
stepForm.value.price = form.value.tieredDiscount[index].price;
}
// 关闭dialog后初始化stepForm
function stepDialogReset() {
stepForm.value.peopleNum = '';
stepForm.value.price = '';
stepFormRef.value.resetFields();
}
// 确认添加阶段
function stepFormSubmitHandle() {
stepFormRef.value
.validate()
.then(() => {
console.log('stepFormType.value', stepFormType.value);
console.log('addStepIndex.value', addStepIndex.value);
if (stepFormType.value == 'add') {
form.value.tieredDiscount.push(_.cloneDeep(stepForm.value));
} else {
form.value.tieredDiscount[addStepIndex.value] = _.cloneDeep(stepForm.value);
}
showStepDialog.value = false;
})
.catch(() => {});
}
// ============= 添加阶梯end
// 原价
function originalPriceInput(e) {
setTimeout(() => {
form.value.originPrice = filterNumberInput(e);
}, 50);
}
// 拼团价
function groupPriceInput(e) {
setTimeout(() => {
form.value.price = filterNumberInput(e);
}, 50);
}
// 成团期限
function groupTimeoutHourInput(e) {
setTimeout(() => {
form.value.expireHours = filterNumberInput(e, 1);
}, 50);
}
// 保存商品
function submitHandle() {
if (startValue.value && endValue.value) {
form.value.useTimes = `${startValue.value}~${endValue.value}`;
}
console.log(form.value);
formRef.value
.validate()
.then(async () => {
try {
uni.showLoading({
title: '保存中...',
mask: true
});
const data = { ...form.value };
if (form.value.useShops.length) {
data.useShops = form.value.useShops.join(',');
} else {
data.useShops = '';
}
await packageAddEdit(data);
setTimeout(() => {
uni.showToast({
title: '保存成功',
icon: 'none'
});
}, 300);
setTimeout(() => {
uni.navigateBack();
}, 1000);
} catch (error) {
console.log(error);
}
uni.hideLoading();
})
.catch(() => {});
}
function backHandle() {
uni.navigateBack();
}
// 从本地获取商品信息
function getLocalGoods() {
let packageGoods = uni.getStorageSync('packageGoods');
if (packageGoods && packageGoods.id) {
form.value = packageGoods;
if (form.value.useShops !== '') {
form.value.useShops = form.value.useShops.split(',');
} else {
form.value.useShops = [];
}
if (packageGoods.useTimes !== '') {
let times = packageGoods.useTimes.split('~');
startValue.value = times[0];
endValue.value = times[1];
}
}
}
onShow(() => {
// 从本地获取选择的商品
selectProduceHandle();
});
onLoad((options) => {
uni.setStorageSync('packageSelectGoods', '');
if (options.type && options.type == 'editor') {
type.value = options.type;
uni.setNavigationBarTitle({
title: '编辑商品'
});
getLocalGoods();
} else {
type.value = 'add';
}
});
</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;
&.column {
align-items: flex-start;
flex-direction: column;
}
.two {
display: flex;
flex-direction: column;
padding-right: 28upx;
}
.t {
font-size: 32upx;
color: #333;
font-weight: bold;
}
.tips {
font-size: 24upx;
color: #666;
}
}
.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;
}
.package-wrap {
flex: 1;
.list {
.item {
border: 1px solid #ececec;
border-radius: 12upx;
padding: 20upx;
&:not(:first-child) {
margin-top: 28upx;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 20upx;
.t {
font-size: 28upx;
color: #333;
}
.del {
display: flex;
align-items: center;
gap: 12upx;
}
}
.input-wrap {
display: flex;
gap: 20upx;
padding-bottom: 20upx;
.btn {
display: flex;
align-items: center;
gap: 12upx;
.t {
color: #318afe;
}
}
}
.table-wrap {
padding-bottom: 20upx;
margin-bottom: 20upx;
.tab-head {
background-color: #f8f8f8;
}
.tr {
display: flex;
gap: 12upx;
padding: 20upx;
border-bottom: 1px solid #ececec;
.td {
flex: 1;
&:nth-child(1) {
flex: 2;
}
&:last-child {
flex: 0.5;
display: flex;
align-items: center;
justify-content: flex-end;
}
.t {
font-size: 28upx;
color: #333;
}
.del {
color: red;
font-size: 28upx;
}
}
}
}
.select_num_wrap {
padding-bottom: 28upx;
.label {
padding-bottom: 20upx;
.t {
color: #333;
font-size: 32upx;
}
}
}
}
}
.package-wrap-btn {
display: flex;
justify-content: center;
padding-top: 28upx;
.btn {
display: flex;
gap: 8upx;
align-items: center;
.t {
font-size: 28upx;
color: #318afe;
font-weight: bold;
}
}
}
}
.step-wrap {
flex: 1;
.table-wrap {
padding-bottom: 20upx;
margin-bottom: 20upx;
.tab-head {
background-color: #f8f8f8;
}
.tr {
display: flex;
gap: 12upx;
padding: 20upx;
border-bottom: 1px solid #ececec;
.td {
flex: 1;
display: flex;
gap: 20upx;
align-items: center;
&:last-child {
flex: 0.6;
}
.t {
font-size: 28upx;
color: #333;
}
.edit {
color: #318afe;
font-size: 28upx;
}
.del {
color: red;
font-size: 28upx;
}
}
}
}
}
}
}
.empty {
padding: 28upx 0;
display: flex;
justify-content: center;
.t {
font-size: 28upx;
color: #999;
}
}
.add-step-wrap {
width: 80vw;
.title {
padding: 28upx;
.t {
font-size: 32upx;
font-weight: bold;
}
}
.content {
padding: 0 28upx 28upx;
}
.footer-btn-wrap {
display: flex;
padding: 0 28upx 28upx;
gap: 28upx;
.btn {
flex: 1;
}
}
}
</style>