改了实体类商品的部分约束
This commit is contained in:
parent
e63fe5da2c
commit
29d4228b4b
16
src/App.vue
16
src/App.vue
|
@ -6,17 +6,27 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
// 引入组件刷新功能
|
||||
import { provide , nextTick , ref } from 'vue'
|
||||
import { provide , nextTick , ref , onMounted } from 'vue'
|
||||
import { ElConfigProvider } from 'element-plus'
|
||||
import router from './router';
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn' //引入ElemenetPlus中文
|
||||
import myAxios from './api/myAxios';
|
||||
const isRouterActive = ref(true)
|
||||
provide('reload', () => {
|
||||
provide('reload', () => { //页面刷新
|
||||
isRouterActive.value = false
|
||||
nextTick(() => {
|
||||
isRouterActive.value = true
|
||||
})
|
||||
})
|
||||
|
||||
onMounted(()=>{
|
||||
checkLoginState()
|
||||
})
|
||||
const checkLoginState = async ()=>{ //监测登陆状态
|
||||
const res = await myAxios.get('/user/get/login')
|
||||
if(res.data.code != 1) {
|
||||
router.push('/')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
import { ElMessage } from 'element-plus';
|
||||
|
||||
const isNotValid = (val) => {
|
||||
const timeRegex = /^([0-1]?[0-9]|2[0-3]):([0-5]?[0-9])-(?:[0-1]?[0-9]|2[0-3]):([0-5]?[0-9])$/;
|
||||
const rangeRegex = /^\(\d+,\d+\)$/
|
||||
return timeRegex.test(val.timeSlot) && rangeRegex.test(val.numberRange)
|
||||
}
|
||||
|
||||
const isValidPlus = (val) => {
|
||||
const timeRegex = /^([0-1]?[0-9]|2[0-3]):([0-5]?[0-9])-(?:[0-1]?[0-9]|2[0-3]):([0-5]?[0-9])$/;
|
||||
const rangeRegex = /^\(\d+,\d+\)$/
|
||||
if(val.timeSlot === '' && val.numberRange === '') return false
|
||||
if(timeRegex.test(val.timeSlot) && rangeRegex.test(val.numberRange)) return false
|
||||
return true
|
||||
}
|
||||
|
||||
export const transfer = (val, arr, isAvailableArr) => {
|
||||
console.log('这是val:', val)
|
||||
for (var i = 0; i < val.length; i ++ ) {
|
||||
for (var j = 0; j < val[i].length; j ++ ) {
|
||||
arr[i][j].timeSlot = val[i][j].startTime + "-" + val[i][j].endTime
|
||||
arr[i][j].numberRange = "(" + val[i][j].minNumValue + "," + val[i][j].maxNumValue + ")"
|
||||
}
|
||||
}
|
||||
console.log('这是arr:', arr)
|
||||
for (var i = 0; i < 4; i ++ ) {
|
||||
for (var j = 0; j < 6; j ++ ) {
|
||||
if(isValidPlus(arr[i][j])) {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: '请检查表单数据是否完整填写'
|
||||
})
|
||||
return ;
|
||||
}
|
||||
}
|
||||
}
|
||||
let newArr = new Array(4)
|
||||
for (var i = 0; i < 4; i ++ ) {
|
||||
newArr[i] = {
|
||||
timeSlot:'',
|
||||
numberRange: '',
|
||||
isAvailable: false
|
||||
}
|
||||
}
|
||||
|
||||
let timeSlotArr = []
|
||||
let numberRangeArr = []
|
||||
let cnt = 0
|
||||
let k = 0
|
||||
for (var i = 0; i < val.length; i ++ ) {
|
||||
for (var j = 0; j < val[i].length; j ++ ) {
|
||||
if(isNotValid(arr[i][j])) {
|
||||
timeSlotArr.push(arr[i][j].timeSlot)
|
||||
numberRangeArr.push(arr[i][j].numberRange)
|
||||
}
|
||||
}
|
||||
if(val[i].length == 0){
|
||||
newArr[i].timeSlot = "00:00-00:00"
|
||||
newArr[i].numberRange = "(0,0)"
|
||||
newArr[i].isAvailable = 0
|
||||
k ++
|
||||
cnt ++
|
||||
}else{
|
||||
newArr[i].timeSlot = timeSlotArr.join(';')
|
||||
newArr[i].numberRange = numberRangeArr.join(';')
|
||||
newArr[i].isAvailable = isAvailableArr[i] ? 1 : 0
|
||||
if(!isAvailableArr[i]) k ++
|
||||
}
|
||||
if(cnt == 4) {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: '至少得有一个预约时间段'
|
||||
})
|
||||
return ;
|
||||
}
|
||||
if(k == 4) {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: '至少有一天可以预约'
|
||||
})
|
||||
return ;
|
||||
}
|
||||
timeSlotArr = []
|
||||
numberRangeArr = []
|
||||
}
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '时间段保存成功'
|
||||
})
|
||||
// console.log(newArr)
|
||||
return newArr
|
||||
}
|
26
src/utils/entityProduct/FormRules.ts
Normal file
26
src/utils/entityProduct/FormRules.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { saveBtn, invInput } from './globalVar';
|
||||
|
||||
export const validateName = (rule: any, value: any, callback: any) => { //商品名称的校验规则
|
||||
if (value === '') {
|
||||
callback(new Error('请输入商品名称'))
|
||||
} else if (value.length < 2) {
|
||||
callback(new Error('商品名称不能小于两位'))
|
||||
saveBtn.value = true
|
||||
} else { saveBtn.value = false }
|
||||
}
|
||||
export const validateIntro = (rule: any, value: any, callback: any) => { //商品简介的校验规则
|
||||
if (value === '') {
|
||||
callback(new Error('请输入商品简介'))
|
||||
} else if (value.length < 20) {
|
||||
callback(new Error('商品简介不能少于20字'))
|
||||
saveBtn.value = true
|
||||
} else { saveBtn.value = false }
|
||||
}
|
||||
export const validateDetail = (rule: any, value: any, callback: any) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请输入商品详情'))
|
||||
} else if (value.length < 80) {
|
||||
callback(new Error('商品详情不能少于80字'))
|
||||
saveBtn.value = true
|
||||
} else { saveBtn.value = false }
|
||||
}
|
5
src/utils/entityProduct/globalVar.ts
Normal file
5
src/utils/entityProduct/globalVar.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { ref } from "vue";
|
||||
|
||||
export const saveBtn = ref(false) //提交按钮状态
|
||||
export const invInput = ref(false) //库存按钮
|
||||
|
70
src/utils/entityProduct/picUpload.ts
Normal file
70
src/utils/entityProduct/picUpload.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import { ref } from 'vue';
|
||||
import myAxios from '@/api/myAxios';
|
||||
import { type UploadFile, type UploadProps, genFileId, type UploadRawFile, type FormInstance, type FormRules } from 'element-plus';
|
||||
import { WarnInfo } from '../messageInfo';
|
||||
|
||||
export const productImgMap = new Map() //商品图片数组
|
||||
export const productImgArr: any = ref([])
|
||||
export const fileSimple = ref() //单个文件
|
||||
export const form : any = ref({ //添加实体类商品的表单
|
||||
name: '', //商品名称
|
||||
price: '', //商品价格
|
||||
intro: '',//产品简介
|
||||
festivalName: '', //节日名称
|
||||
type: '',//类别
|
||||
label: '',//商品标签
|
||||
introDetail: '',//详情描述
|
||||
goodImg: '', //商品图片url
|
||||
detailImg: '', //图文详情url
|
||||
inventory: '' //库存
|
||||
})
|
||||
|
||||
//图片上传请求 此请求只要选择了图片,就会默认上传
|
||||
export const handleChange = async (file: any, flag: number) => { //12.18改
|
||||
fileSimple.value = file
|
||||
let formData = new FormData() //这一步很重要 创建一个FormData对象
|
||||
formData.append("file", fileSimple.value.raw) //fileSimple.value.raw 才是文件主体 将其以文件的格式插入formData
|
||||
const res = await myAxios({ //编写请求,与以前的请求不同,这一次要指定好头部类型和文件类型
|
||||
url: '/file/upload/server/not_login',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'content-Type': 'multipart/form-data'
|
||||
},
|
||||
data: {
|
||||
biz: "test",
|
||||
// 取出formData对象中的file
|
||||
file: formData.get("file")
|
||||
}
|
||||
})
|
||||
if (res.data.code === 1) {
|
||||
if (flag === 0) {
|
||||
productImgArr.value.splice(0, productImgArr.value.length) //一并删除数组中存放的图片Url地址
|
||||
productImgMap.set(fileSimple.value.uid, res.data.data)
|
||||
productImgMap.forEach(loopMap) //将图片url插入到数组中
|
||||
form.value.goodImg = formatString()
|
||||
} else {
|
||||
form.value.detailImg = res.data.data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const formatString = () => { //拼接图片URL,方便传给后端
|
||||
var str = ''
|
||||
str = productImgArr.value.join(';')
|
||||
return str
|
||||
}
|
||||
|
||||
const loopMap = (value: any, key: any, map: any) => { //循环商品图片Map集合函数,用于给请求的字段赋值
|
||||
productImgArr.value.push(value)
|
||||
}
|
||||
|
||||
export const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //uploadFile表示当前删除的图片,uploadFiles是还剩余的图片信息
|
||||
productImgMap.delete(uploadFile.uid)
|
||||
productImgArr.value.splice(0, productImgArr.value.length) //一并删除数组中存放的图片Url地址
|
||||
productImgMap.forEach(loopMap)
|
||||
form.value.goodImg = formatString()
|
||||
}
|
||||
|
||||
export const Exceed_ProductImg: UploadProps['onExceed'] = (files) => { //覆盖商品照片 'onExceed'当文件个数超过限制时,做出的判断
|
||||
WarnInfo('最多只能上传七张图片!')
|
||||
}
|
|
@ -43,7 +43,7 @@
|
|||
</el-form-item>
|
||||
<div>
|
||||
<el-form-item label="库存" prop="inventory">
|
||||
<el-input-number v-model="form.inventory" min="0" :precision="0" :step="1" />
|
||||
<el-input-number v-model="form.inventory" min="0" :precision="0" :step="1" :disabled="invInput" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -52,10 +52,13 @@
|
|||
<el-input v-model="form.festivalName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产品类别" prop="type" style="width: 240px;">
|
||||
<el-select v-model="typeList.value" placeholder="请选择" @change="(event: any) => loadForm(event, 1)">
|
||||
<el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value1" />
|
||||
<el-select v-model="form.type" placeholder="请选择" @change="(event: any) => loadForm(event)" :disabled="typeSelect">
|
||||
<el-option v-for="item in typeList" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div>
|
||||
<el-checkbox v-model="isqualify" label="定制商品" size="large" border style="margin-left: 10px;" @change="customTag" />
|
||||
</div>
|
||||
</div>
|
||||
<el-form-item label="商品标签" prop="label">
|
||||
<div v-for="(item, index) in labelList" :key="index">
|
||||
|
@ -83,148 +86,63 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref, onMounted, inject, reactive } from 'vue';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import { type UploadFile, type UploadProps, genFileId, type UploadRawFile, type FormInstance, type FormRules } from 'element-plus';
|
||||
import { SuccessInfo, WarnInfo, CommInfo } from '@/utils/messageInfo';
|
||||
import { type UploadProps, genFileId, type UploadRawFile, type FormInstance, type FormRules } from 'element-plus';
|
||||
import { SuccessInfo, WarnInfo, CommInfo } from '@/utils/messageInfo'; //封装ElMessage提示
|
||||
import myAxios from "@/api/myAxios";
|
||||
const fileSimple = ref() //单个文件
|
||||
const productImgMap = new Map() //商品图片数组
|
||||
// const uploadedFiles = ref<UploadFile[]>([]);//商品图片数组
|
||||
// const uploadedDescription = ref<UploadFile[]>([]);//商品图文描述数组
|
||||
const productImgArr : any = ref([])
|
||||
import { saveBtn, invInput } from '@/utils/entityProduct/globalVar';
|
||||
import { validateName, validateIntro, validateDetail } from '@/utils/entityProduct/FormRules';
|
||||
import { handleChange, handleRemove, form, Exceed_ProductImg } from '@/utils/entityProduct/picUpload';
|
||||
const resetFormData = ref()
|
||||
const form = ref({
|
||||
name: '', //商品名称
|
||||
price: '', //商品价格
|
||||
intro: '',//产品简介
|
||||
festivalName: '', //节日名称
|
||||
type: '',//类别
|
||||
label: '',//商品标签
|
||||
introDetail: '',//详情描述
|
||||
goodImg: '', //商品图片url
|
||||
detailImg: '', //图文详情url
|
||||
inventory: '' //库存
|
||||
})
|
||||
//导入组件刷新
|
||||
const reload: any = inject("reload")
|
||||
const typeList: any = ref([
|
||||
{
|
||||
value1: '',
|
||||
label: ''
|
||||
}
|
||||
])
|
||||
const reload: any = inject("reload") //导入组件刷新
|
||||
const typeList: any = ref([])
|
||||
const uploadProductImg: any = ref() //图片上传的ref绑定
|
||||
const uploadProductDetail: any = ref() //图片上传的ref绑定
|
||||
const saveBtn = ref(false) //按钮状态
|
||||
const labelList = ref([''])
|
||||
const isqualify : any = ref(false)
|
||||
const typeSelect : any = ref(false) //类别下拉选项栏的禁用状态
|
||||
onMounted(() => {
|
||||
getTypeList() //加载类别列表,渲染在产品列表的select选项里面
|
||||
})
|
||||
const getTypeList = async () => { //获取类别列表作为可选项
|
||||
const res = await myAxios.post('/category/list', {}) //获取商品列表
|
||||
for (let key in res.data.data) { //循环赋值
|
||||
typeList.value[key] = {
|
||||
value1: res.data.data[key].typeName,
|
||||
label: res.data.data[key].typeName
|
||||
const res = await myAxios.post('/category/list/web', {}) //获取商品列表
|
||||
for(let key in res.data.data) {
|
||||
typeList.value.push(res.data.data[key].typeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //uploadFile表示当前删除的图片,uploadFiles是还剩余的图片信息
|
||||
productImgMap.delete(uploadFile.uid)
|
||||
productImgArr.value.splice(0,productImgArr.value.length) //一并删除数组中存放的图片Url地址
|
||||
console.log('typeList---->',typeList.value);
|
||||
}
|
||||
//提交表单
|
||||
const onSubmit = async () => {
|
||||
const values = Object.values(form.value );
|
||||
// 使用some()方法来检查是否有任何值为空
|
||||
console.log('表单--->',values);
|
||||
if (values.some((value: any) => value === null || value === undefined || value === '' || value === 0)) {
|
||||
WarnInfo('请检查表单数据是否完整填写')
|
||||
return; //空返回结束函数
|
||||
}
|
||||
const res = await myAxios.post('/goods/add', { ...form.value })
|
||||
console.log(res.data);
|
||||
// console.log(res.data);
|
||||
if (res.data.code === 1) {
|
||||
SuccessInfo('提交成功')
|
||||
form.value = {} //12.18改
|
||||
reload() //上传完后重置表单
|
||||
} else {
|
||||
WarnInfo('服务错误')
|
||||
return;
|
||||
}
|
||||
}
|
||||
//图片上传请求 此请求只要选择了图片,就会默认上传
|
||||
const handleChange = async (file: any, flag: number) => {
|
||||
fileSimple.value = file
|
||||
let formData = new FormData() //这一步很重要 创建一个FormData对象
|
||||
formData.append("file", fileSimple.value.raw) //fileSimple.value.raw 才是文件主体 将其以文件的格式插入formData
|
||||
const res = await myAxios({ //编写请求,与以前的请求不同,这一次要指定好头部类型和文件类型
|
||||
url: '/file/upload/server/not_login',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'content-Type': 'multipart/form-data'
|
||||
},
|
||||
data: {
|
||||
biz: "test",
|
||||
// 取出formData对象中的file
|
||||
file: formData.get("file")
|
||||
}
|
||||
})
|
||||
if (res.data.code === 1) {
|
||||
//三元运算 当flag为0时,赋值给商品图片 flag为1时,赋值给详情图片
|
||||
// flag ? form.value.detailImg = res.data.data : 0
|
||||
if(flag === 0) {
|
||||
productImgMap.set(fileSimple.value.uid,res.data.data)
|
||||
productImgMap.forEach(loopMap) //将图片url插入到数组中
|
||||
form.value.goodImg = formatString()
|
||||
} else {
|
||||
form.value.detailImg = res.data.data
|
||||
}
|
||||
// console.log('str--->',formatString());
|
||||
}
|
||||
}
|
||||
//将 商品类别 赋值到表格里
|
||||
const loadForm = (value: any, flag: number) => {
|
||||
flag ? form.value.type = value : form.value.festivalName = value //三元运算符 flag=1 是关于"商品类别"选项的值 flag=0 是关于“是否为节日限定”选项的值
|
||||
const loadForm = (value: any) => {
|
||||
form.value.type = value //三元运算符 flag=1 是关于"商品类别"选项的值 flag=0 是关于“是否为节日限定”选项的值
|
||||
}
|
||||
//清除表单
|
||||
const resetForm = () => {
|
||||
resetFormData.value.resetFields()
|
||||
}
|
||||
const Exceed_ProductImg: UploadProps['onExceed'] = (files) => { //覆盖商品照片 'onExceed'当文件个数超过限制时,做出的判断
|
||||
uploadProductImg.value!.clearFiles() //清空已上传的文件列表
|
||||
const file = files[0] as UploadRawFile
|
||||
file.uid = genFileId()
|
||||
uploadProductImg.value!.handleStart(file) //手动选择文件
|
||||
}
|
||||
const Exceed_ProductDetail: UploadProps['onExceed'] = (files) => { //覆盖商品详情图片
|
||||
uploadProductDetail.value!.clearFiles() //清空已上传的文件列表
|
||||
const file = files[0] as UploadRawFile
|
||||
file.uid = genFileId()
|
||||
uploadProductDetail.value!.handleStart(file) //手动选择文件
|
||||
}
|
||||
const validateName = (rule: any, value: any, callback: any) => { //商品名称的校验规则
|
||||
if (value === '') {
|
||||
callback(new Error('请输入商品名称'))
|
||||
} else if (value.length < 2) {
|
||||
callback(new Error('商品名称不能小于两位'))
|
||||
saveBtn.value = true
|
||||
} else { saveBtn.value = false }
|
||||
}
|
||||
const validateIntro = (rule: any, value: any, callback: any) => { //商品简介的校验规则
|
||||
if (value === '') {
|
||||
callback(new Error('请输入商品简介'))
|
||||
} else if (value.length < 20) {
|
||||
callback(new Error('商品简介不能少于20字'))
|
||||
saveBtn.value = true
|
||||
} else { saveBtn.value = false }
|
||||
}
|
||||
const validateDetail = (rule: any, value: any, callback: any) => {
|
||||
if(value === '') {
|
||||
callback(new Error('请输入商品详情'))
|
||||
} else if(value.length < 80) {
|
||||
callback(new Error('商品详情不能少于80字'))
|
||||
saveBtn.value = true
|
||||
} else { saveBtn.value = false }
|
||||
}
|
||||
const rules = reactive<FormRules<typeof form>>({ //表单校验规则
|
||||
name: [{ validator: validateName, trigger: 'blur' }],
|
||||
intro: [{ validator: validateIntro, trigger: 'blur' }],
|
||||
|
@ -246,14 +164,18 @@ const addLabelList = () => { //格式化商品标签
|
|||
} else return;
|
||||
form.value.label = string
|
||||
}
|
||||
const loopMap = (value :any , key :any ,map :any) => { //循环商品图片Map集合函数,用于给请求的字段赋值
|
||||
productImgArr.value.push(value)
|
||||
const customTag = (e:any)=>{ //点击定制
|
||||
if(e) {
|
||||
form.value.inventory = 1
|
||||
invInput.value = true
|
||||
typeSelect.value = true
|
||||
form.value.type = '定制'
|
||||
} else {
|
||||
form.value.inventory = 0
|
||||
invInput.value = false
|
||||
typeSelect.value = false
|
||||
form.value.type = ''
|
||||
}
|
||||
const formatString =()=>{
|
||||
var str = ''
|
||||
str = productImgArr.value.join(';')
|
||||
// console.log(str);
|
||||
return str
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -263,20 +185,25 @@ const formatString =()=>{
|
|||
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.fromBox {
|
||||
width: 700px;
|
||||
height: 750px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.NamePrice {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.IntroInven {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.festivalBox {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.btnBox {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
|
|
@ -2,20 +2,16 @@
|
|||
<!-- 修改前请注释以前的 -->
|
||||
<!-- 搜索 -->
|
||||
<div>
|
||||
<el-input style="width: 200px; height: 30px; margin-right: 10px;" suffix-icon="Search" placeholder="请输入商品名称"
|
||||
<el-input style="width: 240px; margin-right: 10px;" suffix-icon="Search" placeholder="请输入商品名称"
|
||||
v-model="productName"></el-input>
|
||||
<el-form-item label="商品类型" style="width: 200px; margin-right: 10px;display: inline-block">
|
||||
<el-select v-model="editForm.type" @change="(event: any) => searchByType(event)" placeholder="请选择">
|
||||
<el-button class="ml-5" type="primary" @click="onSearch(productName)" style="height: 25px; margin-right: 10px;">搜索</el-button>
|
||||
<el-select v-model="editForm.type" @change="(event: any) => searchByType(event)" placeholder="商品类别" style="width: 240px; margin-right: 10px;">
|
||||
<el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value1"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品状态" style="width: 200px;margin-right: 10px;display: inline-block">
|
||||
<el-select v-model="state" placeholder="请选择" @change="(event: any) => searchByState(event)">
|
||||
<el-select v-model="state" placeholder="商品状态" @change="(event: any) => searchByState(event)" style="width: 240px; margin-right: 10px;">
|
||||
<el-option label="已上架" value="1" />
|
||||
<el-option label="已下架" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-button class="ml-5" type="primary" @click="onSearch(productName)" style="height: 25px;">搜索</el-button>
|
||||
<el-button type="warning" @click="reset" style="height:25px">重置</el-button>
|
||||
</div>
|
||||
<div style="margin: 15px 0">
|
||||
|
@ -41,12 +37,18 @@
|
|||
<el-table-column prop="goodImg" label="商品图片">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<img :src="scope.row.goodImg" alt="" style="height: 50px;">
|
||||
<img :src="scope.row.goodImg.split(';')[0]" alt="" style="height: 50px;">
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="商品名称"></el-table-column>
|
||||
<el-table-column prop="price" label="商品价格" width="180"></el-table-column>
|
||||
<el-table-column prop="price" label="商品价格" width="180">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
{{ scope.row.price }} 元
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="type" label="商品类型"></el-table-column>
|
||||
<el-table-column prop="inventory" label="商品数量"></el-table-column>
|
||||
<el-table-column label="商品状态">
|
||||
|
@ -95,10 +97,8 @@
|
|||
<el-input v-model="editForm.id" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品图片">
|
||||
<div v-if="editForm.goodImg">
|
||||
<img :src="editForm.goodImg" alt="商品图标" class="thumbnail" style="width: 100px; height: 100px;" />
|
||||
</div>
|
||||
<el-upload
|
||||
v-model:file-list="ImgArr"
|
||||
ref="uploadProductImg"
|
||||
action="#"
|
||||
list-type="picture-card"
|
||||
|
@ -107,7 +107,7 @@
|
|||
:on-remove="handleRemove"
|
||||
@change="(event: any) => handleChange(event, 0)"
|
||||
:on-exceed="Exceed_ProductImg"
|
||||
limit="1" >
|
||||
limit="7" >
|
||||
<el-icon>
|
||||
<Plus/>
|
||||
</el-icon>
|
||||
|
@ -116,8 +116,9 @@
|
|||
<el-form-item label="商品名称">
|
||||
<el-input v-model="editForm.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品价格">
|
||||
<el-input v-model="editForm.price"></el-input>
|
||||
<el-form-item label="产品价格" prop="price">
|
||||
<el-input-number v-model="editForm.price" min="0.01" :precision="2" :step="0.5" />
|
||||
<p>元</p>
|
||||
</el-form-item>
|
||||
<el-form-item label="产品类别" prop="type">
|
||||
<el-select v-model="editForm.type" @change="(event: any) => loadForm(event, 1)">
|
||||
|
@ -175,9 +176,11 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ElMessage , type UploadProps , genFileId ,type UploadRawFile } from 'element-plus';
|
||||
import { ElMessage , type UploadProps , genFileId ,type UploadRawFile ,type UploadUserFile } from 'element-plus';
|
||||
import { ref, onMounted, inject } from 'vue';
|
||||
import myAxios from "@/api/myAxios";
|
||||
import { handleChange, handleRemove, Exceed_ProductImg} from '@/utils/entityProduct/picUpload';
|
||||
// import { handleChange, handleRemove, form, Exceed_ProductImg } from '@/utils/entityProduct/picUpload';
|
||||
const total = ref(0); //总页数
|
||||
const idList = ref([]);
|
||||
const searchParams: any = ref({ //封装分页
|
||||
|
@ -186,14 +189,14 @@ const searchParams: any = ref({ //封装分页
|
|||
sortField: "id", //根据ID分类
|
||||
sortOrder: "descend" //降序
|
||||
})
|
||||
const fileSimple = ref()
|
||||
const disabled = ref(true)
|
||||
//表单变量
|
||||
const title = ref('') //表单名字
|
||||
const productName = ref('');
|
||||
const DialogVisible = ref(false);
|
||||
const state = ref(''); //根据商品上架状态select栏
|
||||
const tableData : any= ref([]);
|
||||
const editForm : any = ref({});
|
||||
const tableData : any= ref([]); //实体类商品表格
|
||||
const editForm : any = ref({}); //编辑后的实体类商品表格
|
||||
const reload : any = inject("reload") //页面重新刷新
|
||||
const uploadProductImg : any = ref() //图片上传的ref绑定
|
||||
const uploadProductDetail : any = ref() //图片上传的ref绑定
|
||||
|
@ -203,6 +206,7 @@ const typeList: any = ref([
|
|||
label: ''
|
||||
}
|
||||
])
|
||||
const ImgArr: any = ref<UploadUserFile[]>([]) //图片数组
|
||||
onMounted(() => { //页面加载时获取商品列表和分类页表
|
||||
getProductList()
|
||||
getTypeList()
|
||||
|
@ -210,7 +214,7 @@ onMounted(() => { //页面加载时获取商品列表和分类页表
|
|||
const getProductList = async () => {
|
||||
try {
|
||||
const res = await myAxios.post('/goods/list/page', { ...searchParams.value });
|
||||
// console.log(res.data)
|
||||
console.log('res--->',res.data)
|
||||
if (res.data.code === 1) {
|
||||
tableData.value = res.data.data.records;
|
||||
total.value = parseInt(res.data.data.total) //总数据量,用于分页
|
||||
|
@ -271,15 +275,20 @@ const deleteProduct = async (index: number) => {
|
|||
}
|
||||
getTypeList()
|
||||
}
|
||||
//选中发生的方法--->将其赋值给批量删除的数组
|
||||
//详情或编辑
|
||||
const ReviseOrView = (index: number, row: any , flag : number) => {
|
||||
//flag值不同显示不同内容 disabled开启和关闭
|
||||
ImgArr.value.splice(0,ImgArr.value.length)
|
||||
var tempArr = row.goodImg.split(';')
|
||||
tempArr.forEach((item: any)=>{
|
||||
ImgArr.value.push({
|
||||
url: item
|
||||
})
|
||||
})
|
||||
flag ? (title.value = "编辑商品" , disabled.value = false) : (title.value = "商品详情" , disabled.value = true)
|
||||
DialogVisible.value = true;
|
||||
editForm.value = row;
|
||||
};
|
||||
//下架商品(待优化,有问题,逻辑有问题)
|
||||
//下架商品
|
||||
const handleOff = async (index: number, row: any) => {
|
||||
row.isShelves ? row.isShelves = 0 : row.isShelves = 1 //三元运算符 改变那一行的上架值
|
||||
editForm.value = row;
|
||||
|
@ -305,16 +314,6 @@ const handleCurrentChange = (Current: any) => {
|
|||
const reset = () => {
|
||||
reload()
|
||||
};
|
||||
//上传图片移除 --逻辑上移除
|
||||
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
|
||||
console.log(uploadFile, uploadFiles)
|
||||
}
|
||||
const Exceed_ProductImg: UploadProps['onExceed'] = (files , flag) => { //覆盖商品照片
|
||||
uploadProductImg.value!.clearFiles()
|
||||
const file = files[0] as UploadRawFile
|
||||
file.uid = genFileId()
|
||||
uploadProductImg.value!.handleStart(file)
|
||||
}
|
||||
const Exceed_ProductDetail: UploadProps['onExceed'] = (files) => { //覆盖商品详情图片
|
||||
uploadProductDetail.value!.clearFiles()
|
||||
const file = files[0] as UploadRawFile
|
||||
|
@ -325,27 +324,6 @@ const Exceed_ProductDetail: UploadProps['onExceed'] = (files) => { //覆盖商
|
|||
const loadForm = (value: any, flag: number) => {
|
||||
flag ? editForm.value.type = value : editForm.value.festivalOrder = value //三元运算符 flag=1 是关于"商品类别"选项的值 flag=0 是关于“是否为节日限定”选项的值
|
||||
}
|
||||
//图片上传请求 此请求只要选择了图片,就会默认上传
|
||||
const handleChange = async (file: any, flag: number) => {
|
||||
fileSimple.value = file
|
||||
let formData = new FormData() //这一步很重要 创建一个FormData对象
|
||||
formData.append("file", fileSimple.value.raw) //fileSimple.value.raw 才是文件主体 将其以文件的格式插入formData
|
||||
const res = await myAxios({ //编写请求,与以前的请求不同,这一次要指定好头部类型和文件类型
|
||||
url: '/file/upload/server/not_login',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'content-Type': 'multipart/form-data'
|
||||
},
|
||||
data: {
|
||||
biz: "test",
|
||||
file: formData.get("file") // 取出formData对象中的file
|
||||
}
|
||||
})
|
||||
if (res.data.code === 1) {
|
||||
//三元运算 当flag为0时,赋值给商品图片 flag为1时,赋值给详情图片
|
||||
flag ? editForm.value.detailImg = res.data.data : editForm.value.goodImg = res.data.data
|
||||
}
|
||||
}
|
||||
const onSearch = (data : String)=>{ //搜索按钮方法
|
||||
searchParams.value.name = data
|
||||
searchParams.value.current = 1
|
||||
|
|
|
@ -89,7 +89,7 @@ onMounted(() => {
|
|||
})
|
||||
//获取类别列表
|
||||
const getTypeList = async () => {
|
||||
const res = await myAxios.post('/category/list')
|
||||
const res = await myAxios.post('/category/list/web')
|
||||
// console.log(res.data.data)
|
||||
if (res.data.code === 1) {
|
||||
tableData.value = res.data.data
|
||||
|
|
|
@ -1,104 +1,69 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="ruleFormRef"
|
||||
style="max-width: 600px"
|
||||
:model="ruleForm"
|
||||
status-icon
|
||||
:rules="rules"
|
||||
label-width="auto"
|
||||
class="demo-ruleForm"
|
||||
<el-upload
|
||||
v-model:file-list="fileList"
|
||||
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
|
||||
list-type="picture-card"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
>
|
||||
<el-form-item label="Password" prop="pass">
|
||||
<el-input v-model="ruleForm.pass" type="password" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="Confirm" prop="checkPass">
|
||||
<el-input
|
||||
v-model="ruleForm.checkPass"
|
||||
type="password"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Age" prop="age">
|
||||
<el-input v-model.number="ruleForm.age" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitForm(ruleFormRef)">
|
||||
Submit
|
||||
</el-button>
|
||||
<el-button @click="resetForm(ruleFormRef)">Reset</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
|
||||
<el-dialog v-model="dialogVisible">
|
||||
<img w-full :src="dialogImageUrl" alt="Preview Image" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import { ref } from 'vue'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
|
||||
const ruleFormRef = ref<FormInstance>() //表单实例
|
||||
import type { UploadProps, UploadUserFile } from 'element-plus'
|
||||
|
||||
const checkAge = (rule: any, value: any, callback: any) => {
|
||||
if (!value) {
|
||||
return callback(new Error('Please input the age'))
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (!Number.isInteger(value)) {
|
||||
callback(new Error('Please input digits'))
|
||||
} else {
|
||||
if (value < 18) {
|
||||
callback(new Error('Age must be greater than 18'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}, 1000)
|
||||
const fileList = ref<UploadUserFile[]>([
|
||||
{
|
||||
name: 'food.jpeg',
|
||||
url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
|
||||
},
|
||||
{
|
||||
name: 'plant-1.png',
|
||||
url: '/images/plant-1.png',
|
||||
},
|
||||
{
|
||||
name: 'food.jpeg',
|
||||
url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
|
||||
},
|
||||
{
|
||||
name: 'plant-2.png',
|
||||
url: '/images/plant-2.png',
|
||||
},
|
||||
{
|
||||
name: 'food.jpeg',
|
||||
url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
|
||||
},
|
||||
{
|
||||
name: 'figure-1.png',
|
||||
url: '/images/figure-1.png',
|
||||
},
|
||||
{
|
||||
name: 'food.jpeg',
|
||||
url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
|
||||
},
|
||||
{
|
||||
name: 'figure-2.png',
|
||||
url: '/images/figure-2.png',
|
||||
},
|
||||
])
|
||||
|
||||
const dialogImageUrl = ref('')
|
||||
const dialogVisible = ref(false)
|
||||
|
||||
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
|
||||
console.log(uploadFile, uploadFiles)
|
||||
}
|
||||
|
||||
const validatePass = (rule: any, value: any, callback: any) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请输入密码'))
|
||||
} else {
|
||||
if (ruleForm.checkPass !== '') { //ruleForm就是当前这个表单
|
||||
if (!ruleFormRef.value) return
|
||||
ruleFormRef.value.validateField('checkPass') //具体检验的某个字段,再检验一次
|
||||
}
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validatePass2 = (rule: any, value: any, callback: any) => {
|
||||
if (value === '') {
|
||||
callback(new Error('Please input the password again'))
|
||||
} else if (value !== ruleForm.pass) {
|
||||
callback(new Error("Two inputs don't match!"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const ruleForm = reactive({
|
||||
pass: '',
|
||||
checkPass: '',
|
||||
age: '',
|
||||
})
|
||||
|
||||
const rules = reactive<FormRules<typeof ruleForm>>({ //表单校验规则,需要检验的就放进来
|
||||
pass: [{ validator: validatePass, trigger: 'blur' }],
|
||||
checkPass: [{ validator: validatePass2, trigger: 'blur' }],
|
||||
age: [{ validator: checkAge, trigger: 'blur' }],
|
||||
})
|
||||
|
||||
const submitForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
console.log('submit!')
|
||||
} else {
|
||||
console.log('error submit!')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields()
|
||||
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
|
||||
dialogImageUrl.value = uploadFile.url!
|
||||
dialogVisible.value = true
|
||||
}
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user