1315 lines
29 KiB
Vue
1315 lines
29 KiB
Vue
<template>
|
||
<view class="add-service">
|
||
<view class="fixed-header">
|
||
<view class="tip" v-if="formData.back_text && formData.state == 4">
|
||
<image
|
||
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/390d9d12-3c30-4639-9ac3-7b604b606b6d.png"
|
||
class="tip-icon"></image>
|
||
<text>{{ formData.back_text }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 表单区域 -->
|
||
<view class="form-container">
|
||
<!-- 动态表单区域 -->
|
||
<dynamic-form :fields="formFields" v-model="formData" ref="dynamicForm" />
|
||
</view>
|
||
|
||
<!-- 底部按钮 -->
|
||
<view class="bottom-buttons">
|
||
<button class="btn-draft" @click="saveDraft" v-if="!state || state == 0">
|
||
存草稿
|
||
</button>
|
||
<button class="btn-submit" @click="submitForm">提交</button>
|
||
</view>
|
||
|
||
<!-- 获取权限提示匡内容 -->
|
||
<view class="permission" :class="{ transform: isShowPer && nowQer === 'xc' }">
|
||
<view class="per-tit">美融融plus 对储存空间/照片权限申请说明</view>
|
||
<view class="per-cont">便于您使用该功能上传您的照片/图片/视频以及用于更换头像、发布商品等场景中读取相册和文件内容。</view>
|
||
</view>
|
||
<view class="permission" :class="{ transform: isShowPer && nowQer === 'xj' }">
|
||
<view class="per-tit">美融融plus 对相机拍摄权限申请说明</view>
|
||
<view class="per-cont">便于您使用该功能上传您的照片/图片/视频以及用于更换头像、发布商品等场景中所需内容。</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import request from "../../utils/request";
|
||
import CircleProgress from "@/components/circle-progress/circle-progress.vue";
|
||
import DynamicForm from "@/components/dynamic-form/dynamic-form.vue";
|
||
import sparkMD5 from "spark-md5"; // 引入MD5计算库
|
||
import {
|
||
debounce
|
||
} from "@/utils/debounce.js";
|
||
import AliOssUploader from "../../components/ali-oss-uploader/ali-oss-uploader.vue";
|
||
import permissionUtils from "../../utils/per";
|
||
import locationService from "../../utils/locationService";
|
||
import _public from "../../utils/public";
|
||
|
||
export default {
|
||
components: {
|
||
CircleProgress,
|
||
AliOssUploader,
|
||
DynamicForm,
|
||
},
|
||
data() {
|
||
return {
|
||
formFields: [], // 动态表单字段配置
|
||
showReminderPopup: false,
|
||
artisanType: getApp().globalData.artisanType,
|
||
nowQer: "xc",
|
||
progress: 0,
|
||
isShow: false,
|
||
state: null,
|
||
isShowPer: false,
|
||
formData: {
|
||
publish_user_id: null,
|
||
server_kind: getApp().globalData.artisanType,
|
||
title: "",
|
||
server_price: "",
|
||
line_price: '',
|
||
server_time: "",
|
||
first_class_id: "",
|
||
second_class_id: "",
|
||
detail: [],
|
||
process: [],
|
||
video: "",
|
||
photo: [],
|
||
graphic_details: "",
|
||
sj_see: null, // 1代表商家端不可见 2代表商家端可见
|
||
// 新增的五个独立字段
|
||
efficacy: "",
|
||
crowd: "",
|
||
product: "",
|
||
scope: "",
|
||
prompt: "",
|
||
},
|
||
ratio: null,
|
||
// 服务简介部分
|
||
detailForm: {
|
||
effect: "",
|
||
crowd: "",
|
||
product: "",
|
||
scope: "",
|
||
tips: "",
|
||
},
|
||
detailOtherList: [],
|
||
|
||
imagesList: [], // 临时图片地址
|
||
addDetailList: [],
|
||
showProgress: false,
|
||
publish_user_id: null,
|
||
isAdd: false,
|
||
isDraft: false,
|
||
};
|
||
},
|
||
onShow() {
|
||
},
|
||
onLoad(options) {
|
||
// 监听图文详情编辑回调(在onLoad注册,确保navigateBack时能收到事件)
|
||
uni.$on("updateGraphicDetails", (data) => {
|
||
// 替换整个formData对象引用,确保dynamic-form的watch.value能触发
|
||
this.formData = Object.assign({}, this.formData, {
|
||
graphic_details: JSON.stringify(data)
|
||
});
|
||
});
|
||
this.state = options.state || "";
|
||
// 接收分类参数
|
||
if (options.first_class_id) {
|
||
this.formData.first_class_id = options.first_class_id;
|
||
}
|
||
if (options.second_class_id) {
|
||
this.formData.second_class_id = options.second_class_id;
|
||
}
|
||
if (options.id) {
|
||
this.formData.id = options.id;
|
||
this.getInit();
|
||
}
|
||
// 获取模板
|
||
this.getTemplate();
|
||
// 判断是否显示上门提醒弹窗
|
||
const notShow = uni.getStorageSync('addServiceReminderNotShow');
|
||
this.getUserInfo();
|
||
},
|
||
onUnload() {
|
||
uni.$off("updateGraphicDetails");
|
||
},
|
||
computed: {
|
||
showShopPrice() {
|
||
return (
|
||
this.artisanType == 1 &&
|
||
this.formData.sj_see == 2 &&
|
||
this.formData.server_price &&
|
||
this.formData.first_class_id
|
||
);
|
||
},
|
||
shopPrice() {
|
||
return _public.roundUpToTwoDecimals(
|
||
this.formData.server_price,
|
||
this.ratio
|
||
);
|
||
},
|
||
},
|
||
methods: {
|
||
// 字段类型映射:接口类型 -> dynamic-form类型
|
||
mapFieldType(fieldType) {
|
||
const typeMap = {
|
||
'text': 'text',
|
||
'number': 'number',
|
||
'image_multi': 'image_multi',
|
||
'video': 'video',
|
||
'richtext_editor': 'richtext_editor',
|
||
'select': 'select',
|
||
'single_select': 'single_select',
|
||
'multi_select': 'multi_select',
|
||
'textarea': 'textarea',
|
||
};
|
||
return typeMap[fieldType] || 'text';
|
||
},
|
||
|
||
// 将接口config_data转换为dynamic-form需要的分组格式
|
||
transformConfigToFields(configData) {
|
||
const groups = [];
|
||
let customFieldIndex = 0;
|
||
|
||
// 1. 处理presetFields(预设字段)- 每个字段独立一组
|
||
if (configData.presetFields && Array.isArray(configData.presetFields)) {
|
||
configData.presetFields.forEach((preset) => {
|
||
if (!preset.enabled) return;
|
||
|
||
const field = {
|
||
key: preset.key,
|
||
type: this.mapFieldType(preset.fieldType),
|
||
label: preset.title,
|
||
is_required: preset.required,
|
||
placeholder: preset.placeholder || `请输入${preset.title}`,
|
||
};
|
||
|
||
if (preset.showHint && preset.hint) {
|
||
field.tip = preset.hint;
|
||
}
|
||
|
||
if (preset.key === 'line_price' || preset.key === 'server_price') {
|
||
field.tips = '(元)';
|
||
field.tip = preset.key === 'line_price' ? '服务的基础定价,未参与任何优惠的价格' : '服务参与单品优惠后的价格';
|
||
} else if (preset.key === 'server_time') {
|
||
field.placeholder = '请输入服务时长';
|
||
field.tips = '分钟';
|
||
}
|
||
|
||
if (preset.maxCount) {
|
||
field.maxCount = preset.maxCount;
|
||
}
|
||
if (preset.maxLength && preset.fieldType === 'text') {
|
||
field.maxLength = preset.maxLength;
|
||
}
|
||
if (preset.maxFileSize) {
|
||
field.maxFileSize = preset.maxFileSize;
|
||
}
|
||
|
||
field._hasOriginalKey = !!preset.key;
|
||
groups.push({ type: 'single', field });
|
||
});
|
||
}
|
||
|
||
// 2. 处理sections(区段)- 整个section为一组
|
||
if (configData.sections && Array.isArray(configData.sections)) {
|
||
configData.sections.forEach((section) => {
|
||
const sectionFields = [];
|
||
if (section.fields && Array.isArray(section.fields)) {
|
||
section.fields.forEach((sectionField) => {
|
||
const fieldKey = sectionField.key || `custom_${sectionField.id || customFieldIndex++}`;
|
||
|
||
const field = {
|
||
key: fieldKey,
|
||
type: this.mapFieldType(sectionField.fieldType),
|
||
label: sectionField.title,
|
||
is_required: sectionField.required,
|
||
placeholder: sectionField.placeholder || `请输入${sectionField.title}`,
|
||
};
|
||
|
||
if (sectionField.key === 'server_time') {
|
||
field.placeholder = '请输入服务时长';
|
||
field.tips = '分钟';
|
||
}
|
||
|
||
if (sectionField.options && Array.isArray(sectionField.options) && sectionField.options.length > 0) {
|
||
field.options = sectionField.options;
|
||
}
|
||
|
||
if (sectionField.maxCount && (sectionField.fieldType === 'multi_select' || sectionField.fieldType === 'image_multi')) {
|
||
field.maxCount = sectionField.maxCount;
|
||
}
|
||
|
||
if (sectionField.maxLength && (sectionField.fieldType === 'text' || sectionField.fieldType === 'textarea')) {
|
||
field.maxLength = sectionField.maxLength;
|
||
}
|
||
|
||
if (sectionField.maxLength && sectionField.fieldType === 'number') {
|
||
field.maxLength = sectionField.maxLength;
|
||
}
|
||
|
||
if (sectionField.maxFileSize) {
|
||
field.maxFileSize = sectionField.maxFileSize;
|
||
}
|
||
|
||
field._hasOriginalKey = !!sectionField.key;
|
||
field._original = {
|
||
id: sectionField.id,
|
||
sectionId: section.id,
|
||
sectionType: section.sectionType,
|
||
userDefined: sectionField.userDefined,
|
||
};
|
||
|
||
sectionFields.push(field);
|
||
});
|
||
}
|
||
|
||
groups.push({
|
||
type: 'section',
|
||
sectionTitle: section.sectionTitle || '',
|
||
fields: sectionFields,
|
||
});
|
||
});
|
||
}
|
||
|
||
return groups;
|
||
},
|
||
|
||
// 获取服务模板
|
||
async getTemplate() {
|
||
try {
|
||
const res = await request.post("/sj/servers/getTemplate", {
|
||
first_class_id: this.formData.first_class_id,
|
||
});
|
||
console.log("模板接口返回数据:", res);
|
||
if (res.data && res.data.config_data) {
|
||
// 使用接口返回的config_data转换为表单字段
|
||
// config_data 可能是字符串,需要解析
|
||
const configData = typeof res.data.config_data === 'string'
|
||
? JSON.parse(res.data.config_data)
|
||
: res.data.config_data;
|
||
console.log("解析后的config_data:", configData);
|
||
console.log("presetFields类型:", typeof configData.presetFields, Array.isArray(configData.presetFields));
|
||
const fields = this.transformConfigToFields(configData);
|
||
console.log("转换后的fields数组:", fields, "长度:", fields.length);
|
||
this.formFields = fields;
|
||
} else if (res.data && res.data.fields && res.data.fields.length > 0) {
|
||
// 兼容旧格式
|
||
this.formFields = res.data.fields;
|
||
}
|
||
} catch (e) {
|
||
console.error("获取模板失败", e);
|
||
}
|
||
// 初始化表单数据
|
||
const initialData = {};
|
||
this.formFields.forEach((field) => {
|
||
if (field.default_value !== undefined) {
|
||
initialData[field.key] = field.default_value;
|
||
} else if (field.type === 'multi_select' || field.type === 'image_multi') {
|
||
initialData[field.key] = [];
|
||
} else if (!this.formData[field.key] && this.formData[field.key] !== 0) {
|
||
initialData[field.key] = '';
|
||
}
|
||
});
|
||
this.formData = { ...this.formData, ...initialData };
|
||
},
|
||
inpPrice2(e) {
|
||
let that = this;
|
||
let value = e.detail.value;
|
||
|
||
// 1. 移除非数字和小数点
|
||
value = value.replace(/[^\d.]/g, '');
|
||
|
||
// 2. 确保只有一个小数点
|
||
const parts = value.split('.');
|
||
if (parts.length > 2) {
|
||
value = parts[0] + '.' + parts.slice(1).join('');
|
||
}
|
||
|
||
// 3. 限制小数点后最多一位
|
||
if (parts.length > 1) {
|
||
value = parts[0] + '.' + parts[1].slice(0, 2);
|
||
}
|
||
// 4. 如果以小数点开头,前面补0
|
||
if (value.startsWith('.')) {
|
||
value = '0' + value;
|
||
}
|
||
that.$set(that.formData, 'line_price', value);
|
||
},
|
||
// 服务简介部分
|
||
initDetailForm(detail = []) {
|
||
// 先重置 detailForm 为空
|
||
this.detailForm = {
|
||
effect: "",
|
||
crowd: "",
|
||
product: "",
|
||
scope: "",
|
||
tips: "",
|
||
};
|
||
this.detailOtherList = [];
|
||
|
||
// 优先从后端返回的新字段赋值
|
||
if (this.formData.efficacy) this.detailForm.effect = this.formData.efficacy;
|
||
if (this.formData.crowd) this.detailForm.crowd = this.formData.crowd;
|
||
if (this.formData.product) this.detailForm.product = this.formData.product;
|
||
if (this.formData.scope) this.detailForm.scope = this.formData.scope;
|
||
if (this.formData.prompt) this.detailForm.tips = this.formData.prompt;
|
||
|
||
// 如果新字段都为空,则尝试从旧的 detail 数组中提取(兼容旧数据)
|
||
if (!this.formData.efficacy && !this.formData.crowd && !this.formData.product) {
|
||
(detail || []).forEach((item) => {
|
||
if (item.title === "服务功效") {
|
||
this.detailForm.effect = item.text || "";
|
||
} else if (item.title === "适用人群") {
|
||
this.detailForm.crowd = item.text || "";
|
||
} else if (item.title === "产品清单") {
|
||
this.detailForm.product = item.text || "";
|
||
} else if (item.title === "适用范围" || item.title === "使用范围") {
|
||
this.detailForm.scope = item.text || "";
|
||
} else if (item.title === "温馨提示") {
|
||
this.detailForm.tips = item.text || "";
|
||
} else {
|
||
this.detailOtherList.push({
|
||
title: item.title || "",
|
||
text: item.text || "",
|
||
photo: item.photo || "",
|
||
});
|
||
}
|
||
});
|
||
}
|
||
},
|
||
|
||
syncDetailForm() {
|
||
// 双向同步:如果formData有值(来自dynamic-form),同步到detailForm;否则从detailForm同步到formData
|
||
if (this.formData.efficacy) {
|
||
this.detailForm.effect = this.formData.efficacy;
|
||
} else {
|
||
this.formData.efficacy = (this.detailForm.effect || "").trim();
|
||
}
|
||
if (this.formData.crowd) {
|
||
this.detailForm.crowd = this.formData.crowd;
|
||
} else {
|
||
this.formData.crowd = (this.detailForm.crowd || "").trim();
|
||
}
|
||
if (this.formData.product) {
|
||
this.detailForm.product = this.formData.product;
|
||
} else {
|
||
this.formData.product = (this.detailForm.product || "").trim();
|
||
}
|
||
if (this.formData.scope) {
|
||
this.detailForm.scope = this.formData.scope;
|
||
} else {
|
||
this.formData.scope = (this.detailForm.scope || "").trim();
|
||
}
|
||
if (this.formData.prompt) {
|
||
this.detailForm.tips = this.formData.prompt;
|
||
} else {
|
||
this.formData.prompt = (this.detailForm.tips || "").trim();
|
||
}
|
||
},
|
||
|
||
checkDetailForm() {
|
||
return true;
|
||
},
|
||
|
||
|
||
closeReminderPopup(notShowAgain) {
|
||
console.log('关闭弹窗,不再提示:', notShowAgain);
|
||
if (notShowAgain) {
|
||
uni.setStorageSync('addServiceReminderNotShow', true);
|
||
}
|
||
this.showReminderPopup = false;
|
||
},
|
||
goImgAndText() {
|
||
uni.navigateTo({
|
||
url: `/pages/shop/add-img-text?list=${this.formData.graphic_details}`,
|
||
});
|
||
},
|
||
ckeckisShowPer(value) {
|
||
console.log("ckeckisShowPer==========", value);
|
||
this.isShowPer = value;
|
||
},
|
||
ckecknowQer(value) {
|
||
this.nowQer = value;
|
||
},
|
||
addVideo(value) {
|
||
this.formData.video = value;
|
||
},
|
||
// addImg(arr) {
|
||
// this.formData.photo = this.formData.photo.concat(arr);
|
||
// },
|
||
// deleteImage(index) {
|
||
// this.formData.photo.splice(index, 1)
|
||
// },
|
||
onUploadSuccess(file) {
|
||
console.log("添加的图片", this.formData.photo);
|
||
},
|
||
onUploadError(error) {
|
||
console.error("上传失败:", error);
|
||
uni.showToast({
|
||
title: "上传失败",
|
||
icon: "none",
|
||
});
|
||
},
|
||
onFileDelete(file, index) {
|
||
console.log("删除文件:", this.formData.photo, index);
|
||
},
|
||
uploadVideoSuc(file) {
|
||
this.formData.video = file;
|
||
},
|
||
uploadVideoErr() { },
|
||
uploadVideoDel() {
|
||
this.formData.video = null;
|
||
},
|
||
async getInit() {
|
||
await request
|
||
.post("/sj/servers/detail", {
|
||
id: this.formData.id
|
||
})
|
||
.then((res) => {
|
||
// 直接合并所有字段,避免遗漏
|
||
this.formData = {
|
||
...this.formData,
|
||
...res.data
|
||
};
|
||
// 确保 detail 数组被保留(可能用于兼容)
|
||
this.formData.detail = res.data.detail || [];
|
||
// 调用初始化方法,它会优先使用新字段
|
||
this.initDetailForm(res.data.detail || []);
|
||
});
|
||
},
|
||
getUserInfo() {
|
||
const type = this.artisanType == 1 ? 2 : this.artisanType == 2 ? 3 : 1;
|
||
request
|
||
.post("/user/getuser", {
|
||
type: type,
|
||
})
|
||
.then((result) => {
|
||
this.formData.publish_user_id = result.data.id;
|
||
});
|
||
},
|
||
// 是否在商家端售卖
|
||
changeSale(value) {
|
||
this.formData.sj_see = value;
|
||
},
|
||
// 输入价格
|
||
inpPrice(e) {
|
||
let that = this;
|
||
let value = e.detail.value;
|
||
|
||
// 1. 移除非数字和小数点
|
||
value = value.replace(/[^\d.]/g, "");
|
||
|
||
// 2. 确保只有一个小数点
|
||
const parts = value.split(".");
|
||
if (parts.length > 2) {
|
||
value = parts[0] + "." + parts.slice(1).join("");
|
||
}
|
||
|
||
// 3. 限制小数点后最多一位
|
||
if (parts.length > 1) {
|
||
value = parts[0] + "." + parts[1].slice(0, 2);
|
||
}
|
||
// 4. 如果以小数点开头,前面补0
|
||
if (value.startsWith(".")) {
|
||
value = "0" + value;
|
||
}
|
||
that.$set(that.formData, "server_price", value);
|
||
},
|
||
deleteStep(i) {
|
||
this.formData.process.splice(i, 1);
|
||
},
|
||
addStep() {
|
||
let i = this.formData.process.length + 1;
|
||
let arr = {
|
||
title: "第" + i + "步",
|
||
text: "",
|
||
photo: "",
|
||
};
|
||
this.formData.process.push(arr);
|
||
},
|
||
|
||
// 删除视频
|
||
deleteVideo() {
|
||
this.formData.video = "";
|
||
},
|
||
|
||
// 保存草稿
|
||
saveDraft: debounce(function () {
|
||
if (this.isDraft) return;
|
||
this.syncDetailForm();
|
||
const {
|
||
title,
|
||
server_price,
|
||
line_price,
|
||
server_time,
|
||
first_class_id,
|
||
second_class_id,
|
||
detail,
|
||
process,
|
||
video,
|
||
photo,
|
||
} = this.formData;
|
||
let item = {
|
||
title,
|
||
server_price,
|
||
line_price,
|
||
server_time,
|
||
first_class_id,
|
||
second_class_id,
|
||
detail,
|
||
process,
|
||
video,
|
||
photo,
|
||
};
|
||
// 检查是否所有字段都为空
|
||
const isEmpty = Object.values(item).every((value) => {
|
||
if (Array.isArray(value)) {
|
||
return value.length === 0;
|
||
}
|
||
return !value;
|
||
});
|
||
|
||
if (isEmpty) {
|
||
uni.showToast({
|
||
title: "请至少填写一项内容",
|
||
icon: "none",
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 实现保存草稿逻辑
|
||
this.formData.state = 0;
|
||
let url = null;
|
||
if (!this.formData.id) {
|
||
url = "/user/serveradd";
|
||
} else {
|
||
url = "/user/serverchange";
|
||
}
|
||
request.post(url, this.formData).then((res) => {
|
||
if (res.state == 1) {
|
||
this.isDraft = true;
|
||
const pages = getCurrentPages();
|
||
const prevPage = pages[pages.length - 2]; // 上一个页面
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: "success",
|
||
duration: 1000,
|
||
});
|
||
setTimeout(() => {
|
||
uni.navigateBack({
|
||
delta: 1,
|
||
success: () => {
|
||
prevPage.$vm.currentTab = 3;
|
||
prevPage.$vm.state = 0;
|
||
prevPage.$vm.getServicesList(); // 直接调用上个页面的刷新方法
|
||
},
|
||
});
|
||
}, 500);
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: "none",
|
||
});
|
||
this.isDraft = false;
|
||
}
|
||
});
|
||
}, 500),
|
||
|
||
// 验证动态表单字段
|
||
validateDynamicForm() {
|
||
// 遍历 formGroups(分组结构)按顺序验证必填项
|
||
for (let i = 0; i < this.formFields.length; i++) {
|
||
const group = this.formFields[i];
|
||
const fieldsToCheck = [];
|
||
if (group.type === 'single' && group.field) {
|
||
fieldsToCheck.push(group.field);
|
||
} else if (group.type === 'section' && group.fields) {
|
||
fieldsToCheck.push(...group.fields);
|
||
}
|
||
|
||
for (let j = 0; j < fieldsToCheck.length; j++) {
|
||
const field = fieldsToCheck[j];
|
||
if (!field.is_required) continue;
|
||
|
||
const value = this.formData[field.key];
|
||
const isEmpty = value === undefined || value === null || value === '' ||
|
||
(Array.isArray(value) && value.length === 0);
|
||
|
||
if (isEmpty) {
|
||
// 根据字段类型显示不同的提示语
|
||
const prefix = (field.type === 'image_multi' || field.type === 'video') ? '请上传' : '请输入';
|
||
uni.showToast({
|
||
title: `${prefix}${field.label}`,
|
||
icon: "none",
|
||
});
|
||
return false;
|
||
}
|
||
|
||
// 服务时长特殊验证
|
||
if (field.key === 'server_time') {
|
||
if (value < 10) {
|
||
uni.showToast({
|
||
title: "服务时长最短为10分钟",
|
||
icon: "none",
|
||
});
|
||
return false;
|
||
}
|
||
if (value > 240) {
|
||
uni.showToast({
|
||
title: "服务时长最长为240分钟",
|
||
icon: "none",
|
||
});
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
},
|
||
// 构建提交数据:有key的字段直接作为参数,没有key的字段放入intro数组
|
||
buildSubmitData() {
|
||
const submitData = {};
|
||
const introArr = [];
|
||
|
||
// 添加固定字段
|
||
if (this.formData.id) submitData.id = this.formData.id;
|
||
if (this.formData.first_class_id) submitData.first_class_id = this.formData.first_class_id;
|
||
if (this.formData.second_class_id) submitData.second_class_id = this.formData.second_class_id;
|
||
submitData.server_kind = this.formData.server_kind || getApp().globalData.artisanType;
|
||
|
||
// 遍历分组,按顺序处理字段
|
||
for (let i = 0; i < this.formFields.length; i++) {
|
||
const group = this.formFields[i];
|
||
let fieldsToProcess = [];
|
||
if (group.type === 'single' && group.field) {
|
||
fieldsToProcess.push(group.field);
|
||
} else if (group.type === 'section' && group.fields) {
|
||
fieldsToProcess = group.fields;
|
||
}
|
||
for (let j = 0; j < fieldsToProcess.length; j++) {
|
||
const field = fieldsToProcess[j];
|
||
const value = this.formData[field.key];
|
||
if (value === undefined || value === null || value === '') continue;
|
||
if (Array.isArray(value) && value.length === 0) continue;
|
||
|
||
if (field._hasOriginalKey) {
|
||
// 有key的字段直接作为请求参数
|
||
submitData[field.key] = value;
|
||
} else {
|
||
// 没有key的字段放入intro数组
|
||
introArr.push({
|
||
id: field._original ? field._original.id : field.key,
|
||
title: field.label,
|
||
value: value,
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
if (introArr.length > 0) {
|
||
submitData.intro = JSON.stringify(introArr);
|
||
}
|
||
|
||
return submitData;
|
||
},
|
||
|
||
// 提交表单
|
||
submitForm: debounce(function () {
|
||
if (this.isAdd) return;
|
||
|
||
// 先同步服务简介数据到formData
|
||
this.syncDetailForm();
|
||
|
||
// 验证动态表单字段
|
||
if (!this.validateDynamicForm()) {
|
||
return;
|
||
}
|
||
|
||
if (this.artisanType == 2) {
|
||
delete this.formData.sj_see;
|
||
}
|
||
// 提交表单逻辑
|
||
delete this.formData.state;
|
||
let url = null;
|
||
if (!this.formData.id) {
|
||
url = "/user/serveradd";
|
||
} else {
|
||
url = "/user/serverupdate";
|
||
}
|
||
console.log(this.formData, '-0-0-0-0-0-');
|
||
const submitData = this.buildSubmitData();
|
||
request.post(url, submitData).then((res) => {
|
||
if (res.state == 1) {
|
||
const pages = getCurrentPages();
|
||
const prevPage = pages[pages.length - 2]; // 上一个页面
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: "success",
|
||
duration: 600,
|
||
mask: true,
|
||
});
|
||
this.isAdd = true;
|
||
setTimeout(() => {
|
||
uni.navigateBack({
|
||
delta: 1,
|
||
success: () => {
|
||
prevPage.$vm.currentTab = 1;
|
||
prevPage.$vm.state = 1;
|
||
prevPage.$vm.getServicesList(); // 直接调用上个页面的刷新方法
|
||
},
|
||
});
|
||
}, 500);
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg,
|
||
icon: "none",
|
||
});
|
||
this.isAdd = false;
|
||
}
|
||
});
|
||
}, 500),
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="less">
|
||
.add-service {
|
||
padding: 24rpx 24rpx 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.form-container {
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
.form-item {
|
||
background-color: #fff;
|
||
padding: 24rpx;
|
||
display: flex;
|
||
flex-flow: row nowrap;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
box-sizing: border-box;
|
||
border-radius: 10rpx;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.price-tip {
|
||
width: 100%;
|
||
margin-top: 40rpx;
|
||
|
||
.price-tip-card {
|
||
padding: 8rpx 12rpx;
|
||
background: #FDF0F0;
|
||
border-radius: 8rpx;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #EE4853;
|
||
line-height: 33rpx;
|
||
}
|
||
}
|
||
|
||
.shopsale-box {
|
||
flex-flow: column;
|
||
justify-content: space-between;
|
||
align-items: space-between;
|
||
}
|
||
|
||
.shopsale-change {
|
||
display: flex;
|
||
flex-flow: row nowrap;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-top: 24rpx;
|
||
}
|
||
|
||
.shopsale-option {
|
||
display: flex;
|
||
flex-flow: row nowrap;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.shopsale-option:last-child {
|
||
margin-left: 220rpx;
|
||
}
|
||
|
||
.option-text {
|
||
padding-left: 16rpx;
|
||
}
|
||
|
||
.form-item-up {
|
||
background-color: #fff;
|
||
padding: 24rpx;
|
||
display: flex;
|
||
flex-flow: column nowrap;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
box-sizing: border-box;
|
||
border-radius: 10rpx;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.form-label {
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
.form-input {
|
||
flex: 1;
|
||
height: 40rpx;
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
align-items: center;
|
||
text-align: center;
|
||
}
|
||
|
||
.form-right {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.form-value {
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
margin-right: 16rpx;
|
||
}
|
||
|
||
.placeholder {
|
||
font-weight: 400;
|
||
font-size: 28rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.textarea-item {
|
||
padding-bottom: 30rpx;
|
||
}
|
||
|
||
.form-textarea {
|
||
flex: 1;
|
||
height: 198rpx;
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
line-height: 1.5;
|
||
margin-left: 32rpx;
|
||
}
|
||
|
||
.upload-item {
|
||
padding-bottom: 30rpx;
|
||
}
|
||
|
||
.upload-tip {
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
margin-left: 10rpx;
|
||
}
|
||
|
||
.upload-content {
|
||
margin-top: 20rpx;
|
||
position: relative;
|
||
}
|
||
|
||
.progress-box {
|
||
width: 204rpx;
|
||
height: 204rpx;
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 99;
|
||
display: flex;
|
||
flex-flow: column nowrap;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.progress-text {
|
||
font-size: 42rpx;
|
||
color: #ffffff;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.progress-lable {
|
||
font-size: 28rpx;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.progress-box progress {
|
||
/* width: 204rpx; */
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
}
|
||
|
||
.video-preview,
|
||
.image-preview,
|
||
.upload-btn {
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
margin-right: 10rpx;
|
||
margin-bottom: 20rpx;
|
||
position: relative;
|
||
}
|
||
|
||
.preview-video,
|
||
.preview-image {
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
.upload-btn {
|
||
border: 2rpx dashed #dddddd;
|
||
border-radius: 8rpx;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.plus-icon {
|
||
font-size: 60rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.delete-btn {
|
||
position: absolute;
|
||
top: -20rpx;
|
||
right: -20rpx;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
border-radius: 50%;
|
||
color: #ffffff;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.bottom-buttons {
|
||
/* position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0; */
|
||
height: 100rpx;
|
||
padding: 40rpx 0 64rpx;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
flex-flow: row nowrap;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.btn-draft,
|
||
.btn-submit {
|
||
width: 334rpx;
|
||
height: 76rpx;
|
||
line-height: 76rpx;
|
||
text-align: center;
|
||
font-size: 28rpx;
|
||
border-radius: 40rpx;
|
||
margin: 0 24rpx;
|
||
}
|
||
|
||
.btn-draft {
|
||
background-color: #ffffff;
|
||
color: #e8101e;
|
||
border: 2rpx solid #e8101e;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.btn-submit {
|
||
background-color: #e8101e;
|
||
color: #ffffff;
|
||
width: 705rpx;
|
||
height: 76rpx;
|
||
}
|
||
|
||
.form-step {
|
||
background-color: #fff;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.form-step .form-item {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.step {
|
||
display: flex;
|
||
flex-flow: row nowrap;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 0 24rpx 24rpx;
|
||
}
|
||
|
||
.step-inp {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
margin-left: 38rpx;
|
||
padding: 0 24rpx;
|
||
background-color: rgba(230, 230, 230, 0.5);
|
||
}
|
||
|
||
.step-textarea {
|
||
font-size: 24rpx;
|
||
flex: 1;
|
||
height: 70rpx;
|
||
border-radius: 6rpx;
|
||
margin-left: 38rpx;
|
||
padding: 24rpx;
|
||
background-color: rgba(230, 230, 230, 0.5);
|
||
}
|
||
|
||
/* 选择器触发按钮样式 */
|
||
.picker-trigger {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 24rpx 32rpx;
|
||
background-color: #ffffff;
|
||
border-radius: 12rpx;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.picker-label {
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
.picker-value {
|
||
font-size: 28rpx;
|
||
color: #666666;
|
||
}
|
||
|
||
.picker-arrow {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
margin-left: 16rpx;
|
||
}
|
||
|
||
.delete-icon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
margin-left: 24rpx;
|
||
}
|
||
|
||
.form-detail {
|
||
position: relative;
|
||
}
|
||
|
||
.required::before {
|
||
content: "*";
|
||
color: #ff0000;
|
||
margin-right: 4rpx;
|
||
}
|
||
|
||
.step-inp,
|
||
.form-input {
|
||
height: 60rpx;
|
||
}
|
||
|
||
// 服务简介相关
|
||
.detail-card {
|
||
background: #ffffff;
|
||
border-radius: 20rpx;
|
||
padding: 0 24rpx 8rpx;
|
||
margin-bottom: 24rpx;
|
||
box-sizing: border-box;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.detail-title {
|
||
padding: 24rpx 0 25rpx;
|
||
}
|
||
|
||
.detail-title .form-label {
|
||
font-size: 30rpx;
|
||
font-weight: 500;
|
||
color: #333;
|
||
line-height: 40rpx;
|
||
}
|
||
|
||
.detail-row {
|
||
padding: 0 0 36rpx;
|
||
}
|
||
|
||
.detail-row .form-label {
|
||
display: block;
|
||
margin-bottom: 20rpx;
|
||
line-height: 40rpx;
|
||
}
|
||
|
||
.detail-textarea-wrap {
|
||
position: relative;
|
||
background: #f7f7f7;
|
||
border-radius: 16rpx;
|
||
padding: 24rpx 24rpx 52rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.detail-textarea {
|
||
width: 100%;
|
||
height: 108rpx;
|
||
min-height: 108rpx;
|
||
margin: 0;
|
||
padding: 0;
|
||
background: transparent;
|
||
border: 0;
|
||
font-size: 28rpx;
|
||
line-height: 40rpx;
|
||
color: #333333;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.detail-count {
|
||
position: absolute;
|
||
right: 24rpx;
|
||
bottom: 16rpx;
|
||
font-size: 22rpx;
|
||
color: #999999;
|
||
line-height: 32rpx;
|
||
}
|
||
|
||
/* 平台特定样式 */
|
||
/* #ifdef H5 */
|
||
|
||
.form-input,
|
||
.form-textarea {
|
||
outline: none;
|
||
}
|
||
|
||
.upload-btn {
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* #endif */
|
||
|
||
/* #ifdef APP-PLUS */
|
||
.form-input {
|
||
height: 90rpx;
|
||
}
|
||
|
||
.permission.transform {
|
||
top: calc(var(--status-bar-height) + 88rpx + 30rpx);
|
||
opacity: 1;
|
||
visibility: visible;
|
||
}
|
||
|
||
/* #endif */
|
||
|
||
/* #ifdef MP-WEIXIN */
|
||
.form-input {
|
||
height: 80rpx;
|
||
}
|
||
|
||
.bottom-buttons {
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
}
|
||
|
||
/* #endif */
|
||
.tip {
|
||
padding: 20rpx 30rpx;
|
||
background: #feefec;
|
||
font-weight: 400;
|
||
font-size: 30rpx;
|
||
color: #f31d2f;
|
||
line-height: 42rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
|
||
text-align: center;
|
||
|
||
.tip-icon {
|
||
width: 34rpx;
|
||
height: 34rpx;
|
||
margin-right: 10rpx;
|
||
transform: translateY(6rpx);
|
||
}
|
||
}
|
||
|
||
/* 淡入淡出动画 */
|
||
.fade-enter-active,
|
||
.fade-leave-active {
|
||
transition: opacity 0.3s;
|
||
}
|
||
|
||
.fade-enter,
|
||
.fade-leave-to {
|
||
opacity: 0;
|
||
}
|
||
|
||
.popup-mask2 {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
// z-index: 1000;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.popup-content2 {
|
||
width: 600rpx;
|
||
background-color: #ffffff;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
padding: 40rpx 30rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.popup-title {
|
||
font-size: 36rpx;
|
||
font-weight: 600;
|
||
color: #333333;
|
||
text-align: center;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.popup-message {
|
||
font-size: 30rpx;
|
||
color: #666666;
|
||
text-align: center;
|
||
margin-top: 40rpx;
|
||
margin-bottom: 30rpx;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.popup-buttons {
|
||
display: flex;
|
||
flex-flow: row nowrap;
|
||
justify-content: space-between;
|
||
padding: 20rpx 0 0 0;
|
||
gap: 60rpx;
|
||
}
|
||
|
||
.popup-btn {
|
||
flex: 1;
|
||
height: 80rpx;
|
||
line-height: 80rpx;
|
||
text-align: center;
|
||
font-size: 26rpx;
|
||
border-radius: 40rpx;
|
||
}
|
||
|
||
.popup-btn-know {
|
||
background-color: #e8101e;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.popup-btn-notshow {
|
||
background-color: #ffffff;
|
||
color: #e8101e;
|
||
border: 1rpx #e8101e solid;
|
||
}
|
||
</style> |