mrr.sj.front/pages/syr/manHour/addManHour.vue

897 lines
20 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>
<custom-navbar
:title="customTitle"
:showBack="!isClassSelect"
backgroundColor="#FFFFFF"
></custom-navbar>
<class_select
:classId="formData.first_class_id"
:secondClassId="formData.second_class_ids"
@changeClass="(id) => (formData.first_class_id = id)"
@changeSecondClass="(ids) => (formData.second_class_ids = ids)"
@changeTypeText="(typeText) => (serviceType = typeText)"
@closeClassSelect="endSelect"
v-show="isClassSelect"
></class_select>
<view class="add-service" v-show="!isClassSelect">
<!-- 表单区域 -->
<view class="form-container">
<!-- 服务分类 -->
<view class="form-item">
<text class="form-label">分类</text>
<view class="form-right" @click="() => (isClassSelect = true)">
<text
:class="[
'form-value',
formData.first_class_id ? '' : 'placeholder',
]"
>
{{ serviceType || "请选择分类" }}
</text>
<image
src="/static/images/arrow_right.png"
class="arrow-right"
mode="aspectFit"
></image>
</view>
</view>
<!-- 工时名称 -->
<view class="form-item-up">
<text class="form-label">工时名称</text>
<view class="form-input-box">
<input
type="text"
v-model="formData.title"
placeholder="请输入名称(例如到家美甲、美甲师小时工)"
placeholder-class="placeholder"
class="form-input"
/></view>
</view>
<!-- 工时价格 -->
<view class="form-item-up">
<view>
<text class="form-label">工时价格</text>
<text class="redTip">(*以下按照每10分钟的价格)</text>
</view>
<view class="content_box">
<view class="form-input-box small_input">
<input
type="digit"
v-model="formData.price"
placeholder="请输入价格"
placeholder-class="placeholder"
class="form-input"
/></view>
<text class="unit">元/10分钟</text>
</view>
</view>
<!-- 服务价格 -->
<view class="form-item-up">
<text class="form-label">工时描述</text>
<view class="form-input-box">
<textarea
v-model="formData.detail"
placeholder="请输入描述,可个人专业度、作品经历等方面描述。"
placeholder-class="placeholder"
class="form-textarea"
maxlength="-1"
></textarea>
</view>
</view>
<!-- 服务图片 -->
<view class="form-item-up upload-item">
<view>
<text class="form-label">作品展示</text>
<text class="redTip">(*仅可上传9个图片)</text>
</view>
<ali-oss-uploader
v-model="formData.photo"
:max-count="9"
:max-size="5"
:width="'654rpx'"
:type="artisanType + 1"
:user-id="formData.publish_user_id"
button-text="上传图片"
tips="最多上传3张图片每张不超过5MB"
@success="onUploadSuccess"
@error="onUploadError"
@delete="onFileDelete"
@ckeckisShowPer="ckeckisShowPer"
@ckecknowQer="ckecknowQer"
>
</ali-oss-uploader>
</view>
</view>
<!-- 底部按钮 -->
<view class="bottom-buttons">
<button
class="btn-draft"
@click="saveDraft"
v-if="!state || state == 0"
>
存草稿
</button>
<button class="btn-submit" :class="{'btn-submit2':state != 0}" @click="submitForm">提交</button>
</view>
<view class="mask" v-if="isShow" @click="isShow = false"></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
>
</view>
</template>
<script>
import request from "@/utils/request";
import PopupPicker from "@/components/popup-picker/popup-picker.vue";
import CircleProgress from "@/components/circle-progress/circle-progress.vue";
import { debounce } from "@/utils/debounce.js";
import AliOssUploader from "@/components/ali-oss-uploader/ali-oss-uploader.vue";
import _public from "@/utils/public";
import class_select from "./components/class_select.vue";
export default {
components: {
PopupPicker,
CircleProgress,
AliOssUploader,
class_select,
},
data() {
return {
serviceType: "",
isClassSelect: false,
artisanType: getApp().globalData.artisanType,
nowQer: "xc",
progress: 0,
isShow: false,
state: null,
isShowPer: false,
formData: {
first_class_id: undefined,
second_class_ids: [],
photo: [],
},
ratio: null,
serviceTypes: [], // 服务分类
categoryAll: [],
showServiceTypePicker: false,
showCategoryPicker: false,
selectedServiceTypeIndex: 0,
selectedCategoryIndex: 0,
category: "",
imagesList: [], // 临时图片地址
showCategory: false,
showProgress: false,
publish_user_id: null,
isAdd: false,
isDraft: false,
};
},
onLoad(options) {
this.state = options.state || "";
if (options.id) {
this.formData.id = options.id;
this.getInit();
}
},
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
);
},
customTitle() {
if (this.isClassSelect) {
return "选择分类";
}
if (this.formData.id) {
return "编辑工时";
}
return "添加工时";
},
},
methods: {
ckeckisShowPer(value) {
console.log("ckeckisShowPer==========", value);
this.isShowPer = value;
},
ckecknowQer(value) {
this.nowQer = value;
},
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;
},
async getInit() {
request
.post("/syr/workHour/details", { id: this.formData.id })
.then((res) => {
this.formData = {
...res.data,
second_class_ids: res.data.second_class_ids
.split(",")
.map((it) => Number(it)),
photo: res.data.photo ? JSON.parse(res.data.photo) : [],
};
});
},
// 输入价格
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);
},
// 保存草稿
saveDraft: debounce(function () {
if (this.isDraft) return;
const formData = {
...this.formData,
second_class_ids: this.formData.second_class_ids.join(","),
state: 1,
photo: JSON.stringify(this.formData.photo),
};
if (!this.formData.title) {
uni.showToast({
title: "请输入工时名称",
icon: "none",
});
return;
}
if (!formData.price) {
uni.showToast({
title: "请输入工时价格",
icon: "none",
});
return;
}
if (formData.price < 0.1) {
uni.showToast({
title: "工时价格不能小于0.1",
icon: "none",
});
return;
}
if (!this.formData.photo || this.formData.photo.length === 0) {
uni.showToast({
title: "请上传服务图片",
icon: "none",
});
return;
}
// 实现保存草稿逻辑
formData.state = 0;
let url = null;
if (!formData.id) {
url = "/syr/workHour/add";
} else {
url = "/syr/workHour/edit";
}
request.post(url, formData).then((res) => {
if (res.code == 200) {
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),
// 提交表单
submitForm: debounce(function () {
const formData = {
...this.formData,
second_class_ids: this.formData.second_class_ids.join(","),
state: 1,
photo: JSON.stringify(this.formData.photo),
};
console.log(formData);
if (this.isAdd) return;
// 表单验证
if (!formData.first_class_id) {
uni.showToast({
title: "请选择服务分类",
icon: "none",
});
return;
}
if (formData.second_class_ids.length < 1) {
uni.showToast({
title: "请选择服务子类",
icon: "none",
});
return;
}
if (!this.formData.title) {
uni.showToast({
title: "请输入工时名称",
icon: "none",
});
return;
}
if (!formData.price) {
uni.showToast({
title: "请输入工时价格",
icon: "none",
});
return;
}
if (formData.price < 0.1) {
uni.showToast({
title: "工时价格不能小于0.1",
icon: "none",
});
return;
}
if (!this.formData.detail) {
uni.showToast({
title: "请输入工时描述",
icon: "none",
});
return;
}
// }
if (!this.formData.photo || this.formData.photo.length === 0) {
uni.showToast({
title: "请上传服务图片",
icon: "none",
});
return;
}
if (this.artisanType == 2) {
delete this.formData.sj_see;
}
// 提交表单逻辑
delete this.formData.state;
let url = null;
if (!this.formData.id) {
url = "/syr/workHour/add";
} else {
url = "/syr/workHour/edit";
}
this.isAdd = true;
request.post(url, formData).then((res) => {
if (res.code == 200) {
const pages = getCurrentPages();
const prevPage = pages[pages.length - 2]; // 上一个页面
uni.showToast({
title: res.msg,
icon: "success",
duration: 600,
mask: 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),
endSelect(typeText) {
this.isClassSelect = false;
this.serviceType = typeText;
},
},
};
</script>
<style scoped>
.uni-textarea-wrapper .uni-textarea-placeholder {
display: flex;
align-items: center;
}
.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;
}
.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;
gap: 24rpx;
}
.form-label {
font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.form-input {
flex: 1;
height: 40rpx;
font-size: 28rpx;
color: #333333;
margin-left: 32rpx;
}
.form-right {
display: flex;
justify-content: space-between;
align-items: center;
}
.form-value {
font-size: 28rpx;
color: #333333;
margin-right: 11rpx;
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 隐藏溢出 */
text-overflow: ellipsis; /* 溢出显示省略号 */
width: 400rpx; /* 固定宽度(关键) */
text-align: right;
}
.placeholder {
font-weight: 400;
font-size: 28rpx;
color: #CACCCC;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
.textarea-item {
padding-bottom: 30rpx;
}
.form-textarea {
padding: 32rpx 0;
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: 78rpx;
line-height: 78rpx;
text-align: center;
font-size: 28rpx;
border-radius: 78rpx;
}
.btn-submit2 {
width: 698rpx;
}
.btn-draft {
background-color: #ffffff;
color: #E8101E;
border: 2rpx solid #E8101E;
box-sizing: border-box;
}
.btn-submit {
background-color: #E8101E;
color: #ffffff;
}
.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;
}
.detail-cont {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
width: 170rpx;
height: 210rpx;
position: absolute;
top: 50rpx;
right: -24rpx;
background-color: #fff;
padding: 20rpx;
border-radius: 20rpx;
box-shadow: 0 8rpx 16rpx 0 rgba(0, 0, 0, 0.5);
z-index: 999;
}
.detail-item {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
padding: 12rpx 0;
border-bottom: 1rpx solid rgba(230, 230, 230, 0.5);
}
.lable-view {
width: 120rpx;
}
.required::before {
content: "*";
color: #ff0000;
margin-right: 4rpx;
}
.step-inp,
.form-input {
height: 60rpx;
}
.mask {
position: fixed;
top: 0;
right: 0;
left: 0;
width: 100vw;
height: 100vh;
/* background-color: rgba(230, 230, 230, 0.5); */
z-index: 99;
}
/* 平台特定样式 */
/* #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 */
.redTip {
color: #E8101E;
font-size: 24rpx;
margin-left: 10rpx;
}
.content_box {
display: flex;
align-items: center;
gap: 10rpx;
}
.form-input {
width: 100%;
height: 72rpx;
}
.form-input-box {
border-radius: 10rpx;
border: 1rpx solid #e5e5e5;
width: 100%;
}
.unit {
font-size: 32rpx;
color: #333333;
flex: 1;
}
.small_input {
width: 320rpx !important;
}
</style>