添加服务类商品修改完成

This commit is contained in:
yuanteng 2024-12-08 10:40:37 +08:00
parent fef1b41ee0
commit 5151f9efdf
10 changed files with 1136 additions and 2124 deletions

2823
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"axios": "^1.7.2",
"element-plus": "^2.7.5",
"element-plus": "^2.9.0",
"mitt": "^3.0.1",
"pinia": "^2.2.4",
"pinia-plugin-persistedstate": "^4.1.2",
@ -26,6 +26,7 @@
"@types/node": "^20.17.6",
"@vitejs/plugin-vue": "^5.0.4",
"@vue/tsconfig": "^0.5.1",
"less": "^4.2.1",
"npm-run-all2": "^6.1.2",
"sass": "^1.77.5",
"typescript": "~5.4.0",

View File

@ -1,10 +1,14 @@
<template>
<RouterView v-if="isRouterActive"></RouterView>
<el-config-provider :locale="zhCn">
<RouterView v-if="isRouterActive"></RouterView>
</el-config-provider>
</template>
<script setup lang="ts">
//
import { provide , nextTick , ref } from 'vue'
import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn' //ElemenetPlus
const isRouterActive = ref(true)
provide('reload', () => {
isRouterActive.value = false

View File

@ -12,7 +12,7 @@
<div style="height: 80px; color: white; font-weight: bold;
display: flex; align-items: center; justify-content: center">
<img src="../../assets/logo.png" alt="" style="height: 30px">
<span style="margin-left: 5px" v-show="isShow">珑水阁管理系统</span>
<span style="margin-left: 5px" v-show="isShow">泷水月阁管理系统</span>
</div>
<el-sub-menu index="1">

View File

@ -0,0 +1,219 @@
<template>
<el-calendar class="calbox">
<template #date-cell="{ data }">
<div @click="dateForm(data)">
<p :class="data.isSelected ? 'is-selected' : ''">
{{ data.day.split('-').slice(1).join('-') }}
{{ data.isSelected ? '✔️' : '' }}
</p>
</div>
</template>
</el-calendar>
<el-drawer v-model="drawer" :title="'当前选择的日期是:' + periodObj.specificDate" :with-header="true" @open="drawerOpen" @closed="drawerClean">
<div style="margin-bottom: 20px;">选择当天时间段和人数</div>
<div class="timebox" v-for="(item,index) in periodObj.timePeriodAddRequestList">
<span>选择时间段</span>
<el-time-picker
v-model="timePickArr[index]"
format='HH:mm'
is-range="true"
range-separator="到"
start-placeholder="开始"
end-placeholder="结束"
value-format="HH:mm"
:style="{ width: '236px' }"
@change="saveTime(index)"
/>
<div>
<span>最小人数:</span>
<el-select v-model="periodObj.timePeriodAddRequestList[index].minNumber" style="width: 100px" @change="minNum(index)">
<el-option v-for="item in minArr" :label="item" :value="item" />
</el-select>
<span>最大人数:</span>
<el-select v-model="periodObj.timePeriodAddRequestList[index].maxNumber" style="width: 100px" @change="maxNum(index)">
<el-option v-for="item in maxArr" :label="item" :value="item" />
</el-select>
<el-button circle @click="addList(index)"><el-icon>
<Plus />
</el-icon></el-button>
<el-button circle @click="subList(index)" v-if="index > 0"><el-icon>
<Minus />
</el-icon></el-button>
</div>
</div>
<el-checkbox v-model="isBook" label="这天可预约" style="margin-left: 10px;"/>
<el-button type="success" round @click="saveInfo">保存</el-button>
<el-button type="danger" round @click="closeForm">取消</el-button>
<el-button type="primary" round @click="resetForm">重置</el-button>
</el-drawer>
<el-button type="success" round @click="emittValue" style="margin-left: 100px;">保存</el-button>
</template>
<script setup lang="ts">
import { ref , onMounted , defineEmits} from 'vue'
import { ElMessage } from 'element-plus';
const Selectdate = ref('')
const drawer = ref(false)
const periodObj : any = ref(
{
specificDate: '',
isAvailable: 0,
timePeriodAddRequestList: [
{
timeSlot: '',
minNumber: 0,
maxNumber: 0
}
]
}
)
const periodMap = new Map() //map
const timePickMap = new Map() //
const count = ref(0) //
const timePickArr : any = ref([])
const minArr : any = ref([])
const maxArr : any = ref([])
const isTrue = ref(false) //
const isBook = ref(true)
const appointmentDateAddRequestList :any = ref([]) //
const emit = defineEmits(['calendar-Info'])
onMounted(()=>{
for(let i = 0;i <=50 ; i++) { //
minArr.value[i] = 5+i
maxArr.value[i] = 6+i
}
})
const dateForm =(object : any)=>{ //
Selectdate.value = object.day
periodObj.value.specificDate = object.day
drawer.value = true
}
const closeForm =()=>{ //
drawer.value = false
}
const addList =(index: number)=>{ //
count.value += 1
if(count.value <= 15 && judgeNull(periodObj.value.timePeriodAddRequestList)) {
periodObj.value.timePeriodAddRequestList.push(
{
timeSlot: '',
minNumber: 0,
maxNumber: 0
}
)
timePickArr.value.push([])
} else {
ElMessage({
type:'warning',
message:'请填写完前一段日期后再添加,我知道测试想要干什么!'
})
}
// console.log(index,'--->',periodObj.value);
}
const subList =(index: number)=>{
if(index != 0) {
periodObj.value.timePeriodAddRequestList.splice(index,1)
}
}
const saveTime =(index : number)=>{ //periodObj
try{
periodObj.value.timePeriodAddRequestList[index].timeSlot = timePickArr.value[index][0]+'-'+timePickArr.value[index][1]
} catch {
periodObj.value.timePeriodAddRequestList[index].timeSlot = ''
}
}
const saveInfo =()=>{ //
//
if(!judgeNull(periodObj.value.timePeriodAddRequestList)) {
ElMessage({
type:'warning',
message:'请填写完整时间段和人数!'
})
return;
}
isBook ? periodObj.value.isAvailable = 1 : periodObj.value.isAvailable = 0
periodMap.set(periodObj.value.specificDate,periodObj.value)
timePickMap.set(periodObj.value.specificDate,timePickArr.value)
drawer.value = false
console.log('periodObj--->',periodObj.value);
}
const drawerClean =()=>{ //
periodObj.value = {
specificDate: Selectdate.value,
isAvailable: 0,
timePeriodAddRequestList: [
{
timeSlot: '',
minNumber: 0,
maxNumber: 0
}
]
}
timePickArr.value = []
count.value = 0;
}
const drawerOpen =()=>{ //
isTrue.value = periodMap.has(periodObj.value.specificDate) //
if(isTrue.value) {
periodObj.value = periodMap.get(periodObj.value.specificDate)
timePickArr.value= timePickMap.get(periodObj.value.specificDate)
}
}
const resetForm =()=>{ //
drawerClean() //
if(isTrue.value) { //map
periodMap.delete(periodObj.value.specificDate)
timePickMap.delete(periodObj.value.specificDate)
}
}
const emittValue =()=>{ //
appointmentDateAddRequestList.value.splice(0,appointmentDateAddRequestList.value.length) //
periodMap.forEach(mapFun)
emit('calendar-Info',appointmentDateAddRequestList.value)
}
const mapFun =(value:any ,key:any ,map:any)=>{ //map
if(periodMap.has(key)) {
appointmentDateAddRequestList.value.push(value)
}
console.log(appointmentDateAddRequestList.value);
}
const judgeNull =(List : any)=>{ //
console.log('List--->',List);
if (List.some((item:any) => item.timeSlot==='' || item.minNumber === 0 || item.maxNumber === 0)) {
return false;
}
return true;
}
const minNum =(index : number)=>{ //
if(periodObj.value.timePeriodAddRequestList[index].minNumber > periodObj.value.timePeriodAddRequestList[index].maxNumber && periodObj.value.timePeriodAddRequestList[index].maxNumber != 0) {
ElMessage({
type: 'warning',
message: '最小人数不能大于最大人数'
})
periodObj.value.timePeriodAddRequestList[index].minNumber = 0
return;
}
}
const maxNum =(index : number)=>{
if(periodObj.value.timePeriodAddRequestList[index].maxNumber < periodObj.value.timePeriodAddRequestList[index].minNumber) {
ElMessage({
type: 'warning',
message: '最大人数不能小于最小人数'
})
periodObj.value.timePeriodAddRequestList[index].maxNumber = 0
return;
}
}
</script>
<style scoped>
.calbox {
width: 550px;
height: 280px;
font-size: 12px;
--el-calendar-cell-width: 30px;
}
.timebox {
margin-bottom: 20px;
}
</style>

View File

@ -52,16 +52,26 @@
const Login = async ()=>{
if(username.value === '' || password.value === '') {
ElMessage.error('检查账号或密码是否成功填写')
return;
}
const res: any = await myAxios.post("/user/login",{
userAccount: username.value,
userPassword: password.value
})
console.log(res.data.code)
console.log(res.data)
if(res.data.code === 1 && res ?.data) {
//pinia
await store.getLoginUser(res.data.data)
//
await router.replace('/PersonalCenter')
} else {
ElMessage({
type: 'warning',
message: res.data.message
})
return; //
}
}
</script>

View File

@ -42,29 +42,13 @@
</div>
</div>
<el-form-item label="课程简介" prop="intro">
<el-input v-model="form.intro" type="textarea" style="width: 600px;" />
<el-input v-model="form.intro" type="textarea" style="width: 500px;" />
</el-form-item>
<!-- 使用弹窗 -->
<div class="midBox">
<el-form-item label="产品类别" prop="type">
<el-select v-model="form.type" disabled style="width: 110px;" />
</el-form-item>
<el-form-item label="节日限定" prop="type">
<el-select v-model="festivalValue" style="width: 110px;" placeholder="请选择" @change="setFestival">
<el-option
v-for="item in festivalList"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
</div>
<el-form-item label="商品标签" prop="label">
<el-input v-model="form.label" type="textarea" placeholder="使用英文;分隔符分开" style="width: 600px;" />
<el-input v-model="form.label" type="textarea" placeholder="使用英文;分隔符分开" style="width: 500px;" />
</el-form-item>
<el-form-item label="商品详细描述" prop="introDetail">
<el-input v-model="form.introDetail" type="textarea" placeholder="产品尺寸,服务等" style="width: 600px;" />
<el-input v-model="form.introDetail" type="textarea" placeholder="产品尺寸,服务等" style="width: 500px;" />
</el-form-item>
<div class="totalButton">
<el-form-item>
@ -77,7 +61,8 @@
</el-form>
</div>
<div class="timeTable">
<appointTime @time-Info="getInfo"></appointTime>
<!-- <appointTime @time-Info="getInfo"></appointTime> -->
<calendarUtil @calendar-info="getInfo"></calendarUtil>
</div>
</div>
@ -88,7 +73,7 @@ import { ref, onMounted, inject, toRaw } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { ElMessage, type UploadFile, type UploadProps, genFileId, type UploadRawFile } from 'element-plus';
import myAxios from "@/api/myAxios";
import appointTime from '@/layout/components/appointTime.vue';
import calendarUtil from '@/layout/components/calendarUtil.vue';
const fileSimple = ref() //
const uploadedFiles = ref<UploadFile[]>([]);//
const uploadedDescription = ref<UploadFile[]>([]);//
@ -97,22 +82,16 @@ const form = ref({
name: '',
price: '', //
intro: '',//
type: '服务类',//
label: '',//
introDetail: '',//
goodImg: '', //url
detailImg: '', //url
festivalOrder: 0,
inventory: 1,
appointmentDateAddRequestList: [] //
})
const festivalList = ['非限定','端午节','元宵节','元旦']
//
const reload: any = inject("reload")
const uploadProductImg: any = ref() //ref
const uploadProductDetail: any = ref() //ref
const timeInfo = ref([]) //
const festivalValue = ref('')
onMounted(() => {
// console.log(myDate.getHours()); //
})
@ -133,15 +112,12 @@ const onSubmit = async () => {
console.log(form.value);
const res = await myAxios.post('/goods/add/service', {
name: form.value.name,
type: form.value.type,
price: form.value.price,
goodImg: form.value.goodImg,
intro: form.value.intro,
introDetail: form.value.introDetail,
detailImg: form.value.detailImg,
label: form.value.label,
inventory: form.value.inventory,
festivalOrder: form.value.festivalOrder,
appointmentDateAddRequestList: toRaw(form.value.appointmentDateAddRequestList)
})
console.log(res.data);
@ -199,11 +175,6 @@ const getInfo =(info:any)=>{
// timeInfo.value = info
form.value.appointmentDateAddRequestList = info
}
const setFestival =(info:any)=>{
console.log(info);
form.value.festivalOrder = festivalList.findIndex(value=>value == info)
console.log(form.value.festivalOrder);
}
</script>
<style scoped>
@ -212,7 +183,7 @@ const setFestival =(info:any)=>{
}
.fromBox {
width: 750px;
width: 700px;
height: 750px;
}

View File

@ -43,21 +43,13 @@
<el-table-column prop="name" label="课程名称"></el-table-column>
<el-table-column prop="price" label="单次价格" width="100"></el-table-column>
<el-table-column label="展开时间段" type="expand" width="80">
<template #default="props">
<template #default="{ $index }">
<!-- 放后端传来的预约时间 -->
<el-table :data="props.row.appointmentDateVOS" :header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }">
<el-table :data="appointmentDateArr[$index]" :header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }">
<el-table-column label="日期" prop="specificDate" />
<el-table-column label="人数范围" prop="numberRange" />
<el-table-column label="时间段" prop="timeSlot"/>
<el-table-column label="此段课程人数" prop=""/>
<el-table-column label="操作">
<el-button size="small" @click="">
编辑
</el-button>
<el-button size="small" @click="" type="danger">
删除
</el-button>
</el-table-column>
</el-table>
</template>
</el-table-column>
@ -100,6 +92,14 @@
:small="null" :disabled="null" :background="null" layout="total, sizes, prev, pager, next, jumper"
:total="total" />
</div>
<!-- <el-calendar @input="abc">
<template #date-cell="{ data }">
<p :class="data.isSelected ? 'is-selected' : ''">
{{ data.day.split('-').slice(1).join('-') }}
{{ data.isSelected ? '✔️' : '' }}
</p>
</template>
</el-calendar> -->
<!-- 编辑/详情表单 -->
<!-- <el-dialog v-model="DialogVisible" :title="title">
<el-form label-width="100px" :disabled="disabled">
@ -199,7 +199,7 @@ const searchParams: any = ref({ //封装分页
sortOrder: "descend" //
})
const tableData : any= ref([]);
const appointmentDateArr = ref([])
const appointmentDateArr : any = ref([])
const disabled = ref(true)
const title = ref('') //
const productName = ref('');
@ -227,7 +227,12 @@ const getProductList = async () => {
if (res.data.code === 1) {
tableData.value = res.data.data.records;
total.value = parseInt(res.data.data.total) //
console.log('时间--->',tableData.value);
appointmentDateArr.value.splice(0,total.value)
console.log(tableData.value);
tableData.value.forEach((val : any) => {
appointmentDateArr.value.push(val.appointmentDateVOS)
})
console.log('时间--->',appointmentDateArr.value);
} else {
ElMessage({
message: '获取数据失败',
@ -358,6 +363,10 @@ const delBatch = async ()=>{
}
}
const handleSelectionChange =()=>{}
const abc =(index : any)=>{
console.log(index);
}
</script>
<style scoped>

View File

@ -1,87 +1,47 @@
<template>
<div class="date-picker">
<div class="father">
<div v-for="(item, index) in dayList" :key="index">
<div class="inner">
{{ index + 1 }}
</div>
<!-- 时间段部分 -->
<div class="time-picker">
<div v-for="(item, row) in timeList[index]" :key="row" class="box">
<span> {{ row+1 }} 个时间段</span>
<el-time-select
v-model="timeList[index][row].startTime"
style="width: 150px"
:max-time="timeList[index][row].endTime"
placeholder="Start time"
size="default"
start="08:30"
step="00:15"
end="18:30" />
<el-time-select
v-model="timeList[index][row].endTime"
style="width: 150px"
:min-time="timeList[index][row].startTime"
placeholder="End time"
size="default"
start="08:30"
step="00:15"
end="18:30" />
<el-button circle @click="addList(index, row)"><el-icon><Plus /></el-icon></el-button>
<el-button circle @click="subList(index, row)" v-if="row + 1 > 1"><el-icon><Minus /></el-icon></el-button>
</div>
</div>
</div>
</div>
<div class="demo-range">
<el-time-picker
v-model="value1"
is-range
range-separator="To"
start-placeholder="Start time"
end-placeholder="End time"
@change="abc"
/>
<el-time-picker
v-model="value2"
is-range
arrow-control
range-separator="To"
start-placeholder="Start time"
end-placeholder="End time"
/>
</div>
</template>
<script setup lang="ts">
<script lang="ts" setup>
import { ref } from 'vue'
import { Plus } from '@element-plus/icons-vue';
const dayList = ref([0,1,2,3]) //
const timeList = ref([
[
{
startTime: '',
endTime: ''
}
],
[
{
startTime: '',
endTime: ''
}
],
[
{
startTime: '',
endTime: ''
}
],
[
{
startTime: '',
endTime: ''
}
]
const value1 = ref<[Date, Date]>([
new Date(2016, 9, 10, 8, 40),
new Date(2016, 9, 10, 9, 40),
])
const numberRange = ref([])
const addList = (index: any, row: any) => {
if ( timeList.value[index].length < 6) {
timeList.value[index].push({
startTime:'',
endTime:''
})
}
}
const subList = (index: number, row: number) => {
console.log(index,row);
timeList.value[index].splice(row, 1)
const value2 = ref<[Date, Date]>([
new Date(2016, 9, 10, 8, 40),
new Date(2016, 9, 10, 9, 40),
])
const abc=()=>{
console.log(value1.value);
}
</script>
<style lang="scss" scoped>
<style>
.demo-range .el-date-editor {
margin: 8px;
}
.demo-range .el-range-separator {
box-sizing: content-box;
}
</style>

View File

@ -7,6 +7,11 @@
{
"path": "./tsconfig.app.json"
}
]
],
"compilerOptions": {
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true
}
}