Files
fuintadmin/src/views/book/components/bookForm.vue

377 lines
11 KiB
Vue
Raw Normal View History

2026-01-27 14:08:40 +08:00
<template>
<!-- 添加或修改对话框 -->
<el-dialog
:title="title"
:visible.sync="showDialog"
class="common-dialog"
width="840px"
:before-close="handleCLose"
@close="handleCLose"
destroy-on-close
>
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-row>
<el-col :span="24">
<el-form-item label="预约名称" prop="name">
<el-input
v-model="form.name"
placeholder="请输入预约名称"
maxlength="200"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="所属店铺" prop="storeId">
<el-select
v-model="form.storeId"
style="width: 260px"
placeholder="所属店铺,空则为全部店铺"
>
<el-option
:key="0"
label="全部店铺"
v-if="!this.$store.getters.storeId"
:value="0"
/>
<el-option
v-for="storeInfo in storeList"
:key="storeInfo.id"
:label="storeInfo.name"
:value="storeInfo.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="所属分类" prop="cateId">
<el-select
v-model="form.cateId"
style="width: 260px"
placeholder="所属分类"
>
<el-option :key="0" label="无" :value="0" />
<el-option
v-for="cate in cateList"
:key="cate.id"
:label="cate.name"
:value="cate.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="9">
<el-form-item label="封面图片" prop="logo">
<el-upload
:action="uploadAction"
list-type="picture-card"
:class="{ hide: hideUpload }"
:file-list="uploadFiles"
:auto-upload="true"
:show-file-list="false"
:headers="uploadHeader"
:on-success="handleUploadSuccess"
>
<img
v-if="this.form.logo"
2026-02-18 16:33:16 +08:00
:src="getImageUrl(this.form.logo)"
2026-01-27 14:08:40 +08:00
class="list-img"
/>
<i v-if="!this.form.logo" class="el-icon-plus"></i>
</el-upload>
</el-form-item>
</el-col>
<p class="form-tips">提示点击图片修改建议尺寸200 x 140</p>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="可预约日期" prop="dates">
<el-date-picker
type="dates"
v-model="dates"
value-format="yyyy-MM-dd"
style="width: 500px"
placeholder="选择一个或多个日期空则表示未来7天每天都可预约"
>
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="可预约时段" prop="dates">
2026-02-18 16:33:16 +08:00
<div class="time-item">
2026-01-27 14:08:40 +08:00
<el-time-select
placeholder="起始时间"
2026-02-18 16:33:16 +08:00
v-model="timeRange.startTime"
2026-01-27 14:08:40 +08:00
:picker-options="{
start: '00:00',
2026-02-18 16:33:16 +08:00
step: '00:30',
2026-01-27 14:08:40 +08:00
end: '23:59',
}"
>
</el-time-select>
-
<el-time-select
placeholder="结束时间"
2026-02-18 16:33:16 +08:00
v-model="timeRange.endTime"
2026-01-27 14:08:40 +08:00
:picker-options="{
2026-02-18 16:33:16 +08:00
start: '00:00',
step: '00:30',
2026-01-27 14:08:40 +08:00
end: '23:59',
}"
>
</el-time-select>
-
<el-input-number
style="width: 120px"
2026-02-18 16:33:16 +08:00
v-model="timeRange.num"
:min="1"
/>
<span class="unit"></span>
</div>
<div class="form-tips">提示只需设置一个可预约时间范围例如 10:00-22:00</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="预约费用" prop="priceRules">
<div class="add-item">
<el-button
type="primary"
size="mini"
icon="el-icon-plus"
@click="addPriceRule()"
>添加费用</el-button
>
</div>
<div class="time-item" v-for="(rule, index) in priceRules" :key="index">
<el-input-number
style="width: 140px"
v-model="rule.hours"
2026-01-27 14:08:40 +08:00
:min="0"
2026-02-18 16:33:16 +08:00
:precision="1"
controls-position="right"
2026-01-27 14:08:40 +08:00
/>
2026-02-18 16:33:16 +08:00
<span class="unit">小时</span>
<el-input-number
style="width: 140px; margin-left: 10px"
v-model="rule.price"
:min="0"
:precision="2"
controls-position="right"
/>
<span class="unit"></span>
2026-01-27 14:08:40 +08:00
<span
class="remove-item el-icon-remove"
2026-02-18 16:33:16 +08:00
@click="removePriceRule(index)"
2026-01-27 14:08:40 +08:00
></span>
</div>
2026-02-18 16:33:16 +08:00
<div class="form-tips">提示可配置任意时长与费用 1小时/52小时/87小时/13</div>
2026-01-27 14:08:40 +08:00
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="排序" prop="sort">
<el-input-number v-model="form.sort" :min="0" />
<div class="form-tips">提示数值越小排列越靠前</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="备注信息">
<el-input
v-model="form.description"
type="textarea"
placeholder="请输入内容"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio key="A" label="A" value="A">启用</el-radio>
<el-radio key="N" label="N" value="N">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="doSubmit">确定</el-button>
<el-button @click="handleCLose">取消</el-button>
</div>
</el-dialog>
</template>
<script>
import { saveBook } from '@/api/book'
import { getToken } from '@/utils/auth'
2026-02-18 16:33:16 +08:00
import { getUploadFileName } from '@/utils/upload'
2026-01-27 14:08:40 +08:00
export default {
name: 'bookForm',
props: {
showDialog: {
type: [Boolean],
default: () => false,
},
title: {
type: [String],
default: () => '',
},
form: {
type: [Object],
default: () => null,
},
imagePath: {
type: [String],
default: () => '',
},
storeList: {
type: [Array],
default: () => [],
},
cateList: {
type: [Array],
default: () => [],
},
},
watch: {
showDialog(value) {
if (value) {
if (this.form.serviceDates) {
this.dates = this.form.serviceDates.split(',')
} else {
this.dates = []
}
if (this.form.serviceTimes) {
const times = this.form.serviceTimes.split(',')
2026-02-18 16:33:16 +08:00
const first = times[0].split('-')
if (first && first.length >= 2) {
this.timeRange = {
startTime: first[0],
endTime: first[1],
num: first[2] ? Number(first[2]) : 1,
2026-01-27 14:08:40 +08:00
}
}
} else if (this.form.id) {
2026-02-18 16:33:16 +08:00
this.timeRange = { startTime: '', endTime: '', num: 1 }
2026-01-27 14:08:40 +08:00
} else {
2026-02-18 16:33:16 +08:00
this.timeRange = { startTime: '10:00', endTime: '22:00', num: 1 }
}
if (this.form.priceRules) {
try {
const parsed = JSON.parse(this.form.priceRules)
this.priceRules = Array.isArray(parsed) ? parsed : []
} catch (e) {
this.priceRules = []
}
} else {
this.priceRules = []
2026-01-27 14:08:40 +08:00
}
}
},
},
data() {
return {
loading: false,
dates: [],
2026-02-18 16:33:16 +08:00
timeRange: { startTime: '10:00', endTime: '22:00', num: 1 },
priceRules: [],
2026-01-27 14:08:40 +08:00
total: 0,
// 上传地址
uploadAction: process.env.VUE_APP_SERVER_URL + 'backendApi/file/upload',
// 隐藏上传
hideUpload: false,
// 上传文件列表
uploadFiles: [],
uploadHeader: { 'Access-Token': getToken() },
rules: {
name: [
{ required: true, message: '名称不能为空', trigger: 'blur' },
{
min: 2,
max: 200,
message: '名称长度必须介于2 和 200 之间',
trigger: 'blur',
},
],
logo: [{ required: true, message: '请上传图片', trigger: 'blur' }],
},
}
},
methods: {
2026-02-18 16:33:16 +08:00
getImageUrl(path) {
if (!path) return ''
if (/^https?:\/\//i.test(path)) return path
return (this.imagePath || '') + path
},
addPriceRule() {
this.priceRules.push({ hours: 1, price: 0 })
},
removePriceRule(index) {
this.priceRules.splice(index, 1)
},
2026-01-27 14:08:40 +08:00
// 提交
doSubmit() {
const app = this
let param = app.form
2026-02-18 16:33:16 +08:00
param.times = [
{
startTime: app.timeRange.startTime,
endTime: app.timeRange.endTime,
num: app.timeRange.num,
},
]
2026-01-27 14:08:40 +08:00
if (app.dates && app.dates.length > 0) {
param.dates = app.dates.toString()
} else {
param.dates = ''
}
2026-02-18 16:33:16 +08:00
param.priceRules = app.priceRules && app.priceRules.length > 0 ? JSON.stringify(app.priceRules) : ''
2026-01-27 14:08:40 +08:00
saveBook(param).then((response) => {
if (response) {
app.$modal.msgSuccess('提交成功!')
app.$emit('updateList', false)
app.$emit('closeDialog', 'bookDialog')
}
})
},
// 关闭对话框
handleCLose() {
this.$emit('closeDialog', 'bookDialog')
},
// 上传成功回调
2026-02-18 16:33:16 +08:00
handleUploadSuccess(res) {
const fileName = getUploadFileName(res)
if (!fileName) return
this.form.logo = fileName
2026-01-27 14:08:40 +08:00
},
},
}
</script>
<style scoped>
.common-dialog >>> .el-upload--picture-card {
width: 60px;
height: 50px;
line-height: 60px;
}
.time-item {
margin-bottom: 2px;
}
.remove-item {
margin-left: 2px;
color: red;
cursor: pointer;
}
</style>