这次真的不一样了,修改了CSS样式,在前端就做了图片压缩,10m图片瞬间变为800k以下,新增活动管理、轮播图管理

This commit is contained in:
yuanteng 2025-03-20 21:04:28 +08:00
parent 4ee1cfa3a9
commit 2bd3a67a7d
45 changed files with 2182 additions and 1613 deletions

View File

@ -15,7 +15,7 @@
<style>
html,body,#app{
height:100%;
margin: 0px;
padding: 0px;
width: 100%;
position: relative;
}
</style>

53
package-lock.json generated
View File

@ -201,6 +201,15 @@
"regenerator-runtime": "^0.14.0"
}
},
"@babel/runtime-corejs3": {
"version": "7.26.10",
"resolved": "https://registry.npmmirror.com/@babel/runtime-corejs3/-/runtime-corejs3-7.26.10.tgz",
"integrity": "sha512-uITFQYO68pMEYR46AHgQoyBg7KPPJDAbGn4jUTIRgCFJIp88MIBUianVOplhZDEec07bp9zIyr4Kp0FCyQzmWg==",
"requires": {
"core-js-pure": "^3.30.2",
"regenerator-runtime": "^0.14.0"
}
},
"@babel/standalone": {
"version": "7.26.1",
"resolved": "https://registry.npmmirror.com/@babel/standalone/-/standalone-7.26.1.tgz",
@ -1322,6 +1331,11 @@
"resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="
},
"blueimp-canvas-to-blob": {
"version": "3.29.0",
"resolved": "https://registry.npmmirror.com/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz",
"integrity": "sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg=="
},
"brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
@ -1434,6 +1448,15 @@
"resolved": "https://registry.npmmirror.com/compatx/-/compatx-0.1.8.tgz",
"integrity": "sha512-jcbsEAR81Bt5s1qOFymBufmCbXCXbk0Ql+K5ouj6gCyx2yHlu6AgmGIi9HxfKixpUDO5bCFJUHQ5uM6ecbTebw=="
},
"compressorjs": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/compressorjs/-/compressorjs-1.2.1.tgz",
"integrity": "sha512-+geIjeRnPhQ+LLvvA7wxBQE5ddeLU7pJ3FsKFWirDw6veY3s9iLxAQEw7lXGHnhCJvBujEQWuNnGzZcvCvdkLQ==",
"requires": {
"blueimp-canvas-to-blob": "^3.29.0",
"is-blob": "^2.1.0"
}
},
"compute-scroll-into-view": {
"version": "1.0.20",
"resolved": "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz",
@ -1469,6 +1492,11 @@
"is-what": "^3.14.1"
}
},
"core-js-pure": {
"version": "3.41.0",
"resolved": "https://registry.npmmirror.com/core-js-pure/-/core-js-pure-3.41.0.tgz",
"integrity": "sha512-71Gzp96T9YPk63aUvE5Q5qP+DryB4ZloUZPSOebGM88VNw8VNfvdA7z6kGA8iGOTEzAomsRidp4jXSmUIJsL+Q=="
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -1934,6 +1962,11 @@
"binary-extensions": "^2.0.0"
}
},
"is-blob": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/is-blob/-/is-blob-2.1.0.tgz",
"integrity": "sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw=="
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
@ -2385,6 +2418,11 @@
"mimic-fn": "^4.0.0"
}
},
"pako": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/pako/-/pako-2.1.0.tgz",
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
},
"parse-node-version": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz",
@ -2644,6 +2682,16 @@
"integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
"dev": true
},
"shrinkpng": {
"version": "1.2.0-beta.1",
"resolved": "https://registry.npmmirror.com/shrinkpng/-/shrinkpng-1.2.0-beta.1.tgz",
"integrity": "sha512-14B3Na+thQHyXkz1cMXKcMQ/mYBCJFWck1Z5z3NzmQqF5x712vuM9WWt2g/2V6/+ZYUA40FQLyNl6Q9TcffdEw==",
"requires": {
"@babel/runtime-corejs3": "^7.18.3",
"pako": "^2.0.4",
"uzip": "^0.20201231.0"
}
},
"signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz",
@ -2876,6 +2924,11 @@
"picocolors": "^1.1.0"
}
},
"uzip": {
"version": "0.20201231.0",
"resolved": "https://registry.npmmirror.com/uzip/-/uzip-0.20201231.0.tgz",
"integrity": "sha512-OZeJfZP+R0z9D6TmBgLq2LHzSSptGMGDGigGiEe0pr8UBe/7fdflgHlHBNDASTXB5jnFuxHpNaJywSg8YFeGng=="
},
"vite": {
"version": "5.4.10",
"resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.10.tgz",

View File

@ -15,12 +15,14 @@
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.7.2",
"compressorjs": "^1.2.1",
"dayjs": "^1.11.13",
"element-plus": "^2.9.0",
"mitt": "^3.0.1",
"pinia": "^2.0.35",
"pinia-plugin-persistedstate": "^4.1.2",
"querystring": "^0.2.1",
"shrinkpng": "^1.2.0-beta.1",
"vue": "^3.2.31",
"vue-router": "^4.3.3"
},

View File

@ -33,15 +33,14 @@ const checkLoginState = async ()=>{ //监测登陆状态
<style scoped>
html{
padding:0;
margin: 0;
}
body{
html {
padding: 0;
margin: 0;
overflow: auto;
width: 100%;
min-width: 1200px;
}
body {
padding: 0;
margin: 0;
}
</style>

View File

@ -1,13 +1,12 @@
<template>
<el-container >
<div class="layout">
<el-container style="height: 100%">
<!-- 侧边栏-->
<Aside/>
<!-- 主体-->
<el-container>
<!-- 头部-->
<el-header style="font-size: 12px; border-bottom:2px solid #ccc; line-height: 60px; height: 70px;">
<el-header style="font-size: 12px; border-bottom:2px solid #ccc; line-height: 60px; height: 70px;min-width: 500px;">
<Header/>
</el-header>
<!-- 身体-->
@ -17,6 +16,7 @@
</el-main>
</el-container>
</el-container>
</div>
</template>
<script setup lang="ts">
@ -29,5 +29,9 @@ import Header from "@/layout/components/Header.vue";
</script>
<style>
.layout {
height: 100%;
overflow-x: hidden;
}
</style>

View File

@ -1,6 +1,5 @@
<template>
<el-aside :width="sideWidth + 'px'" style="max-height: 200vh; min-height: 100vh; position: sticky; bottom: 0; left: 0; height: auto; background-color: rgb(170, 113, 81); box-shadow: rgba(0, 21, 155, 0.35) 2px 0 6px" >
<el-aside :style="AsideObj">
<el-aside :style="AsideObj" >
<el-menu
background-color="rgb(170, 113, 81)"
:collapse="isCollapse"
@ -10,6 +9,7 @@
:default-active="currentRoute"
active-text-color="#ffd04b"
unique-opened
style="height: 100%;overflow-y: scroll;overflow-y: auto;"
>
<div style="height: 80px; color: white; font-weight: bold;
display: flex; align-items: center; justify-content: center">
@ -62,7 +62,6 @@
</template>
</el-menu>
</el-aside>
</el-aside>
</template>
<script setup>
@ -183,13 +182,4 @@ const menuRoutes = computed(() => {
</script>
<style scoped>
.is-active {
color: #ffd04b;
}
.no-active {
color: #ffffff;
}
.el-menu--horizontal {
--el-menu-horizontal-height: 2000px;
}
</style>

View File

@ -16,7 +16,7 @@
<div style="position: absolute; right: 40px; display: flex; justify-content: center; align-items: center;">
<el-avatar style="margin-right: 10px">
<img :src="userInfo.userAvatar" alt="">
<img :src="downloadUrl + userInfo.userAvatar" alt="">
</el-avatar>
<el-dropdown style="cursor: pointer;" size="default">
@ -35,13 +35,15 @@
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { ref } from 'vue'
import emitter from '@/utils/emitter'
import { useRouter } from "vue-router";
import myAxios from '@/api/myAxios';
import { userStore } from '@/store/userStore';
import { ElMessage } from 'element-plus';
import Breadcrumb from './Breadcrumb.vue';
import { downloadUrl } from '@/utils/formatImgUpload'
const router = useRouter();
const offset = ref(20)
const showLog = ref(false)

View File

@ -2,7 +2,7 @@
<div style="border: 1px solid #ccc">
<Toolbar style="border-bottom: 1px solid #ccc; width: 400px;" :editor="editorRef" :defaultConfig="toolbarConfig"
:mode="mode" />
<Editor style="height: 500px; overflow-y: hidden; width: 400px;" v-model="context" :value="disableRich" :defaultConfig="editorConfig"
<Editor style="height: 500px; overflow-y: hidden; width: 400px;" v-model="valueHtml" :defaultConfig="editorConfig"
:mode="mode" @onChange="handleChange" @onCreated="handleCreated" />
</div>
</template>
@ -39,7 +39,7 @@ const editorConfig = {
}
editorConfig.readOnly = props.disableRich //
editorConfig.autoFocus = false
editorConfig.MENU_CONF['uploadImage'] = {
async customUpload(file, insertFn) {
const res = await myAxios({
@ -54,7 +54,7 @@ editorConfig.MENU_CONF['uploadImage'] = {
}
})
console.log('图片上传返回值--->',res.data)
const downloadUrl = 'http://123.249.108.160:8888/api/file/downloadFile?objectKey=';
const downloadUrl = 'https://www.carboner.cn:8888/api/file/downloadFile?objectKey=';
insertFn(downloadUrl + res.data.data, res.alt, res.href)
}
}
@ -69,7 +69,8 @@ const handleCreated = (editor) => {
editorRef.value = editor // editor
}
const handleChange = (editor) => { //emit
emit('richTextContent', props.context)
// console.log(valueHtml.value)
emit('richTextContent', valueHtml.value)
// emit('disableChange',props.disable)
// console.log('html',editor.getHtml());
}

View File

@ -202,7 +202,7 @@ export const constantRoute = [
}
},
{
path: '/ManagementCenter',
path: '/OutfitManagementCenter',
name: '写真产品中心',
component: () => import("@/views/CostumeAppointments/ManagementCenter.vue"),
meta: {
@ -241,6 +241,48 @@ export const constantRoute = [
}
]
},
//活动资讯管理
{
path: '/activityMessage',
redirect: '/AddMessage',
component: () => import("@/layout/Manage.vue"),
meta: {
title: '活动资讯管理',
icon: '',
hidden: false
},
children: [
{
path: '/AddMessage',
name: '添加活动资讯',
component: () => import("@/views/ActivityMessageManagement/AddMessage.vue"),
meta: {
title: '添加活动资讯',
icon: 'Edit',
hidden: false
}
},
{
path: '/MessageCenter',
name: '活动资讯中心',
component: () => import("@/views/ActivityMessageManagement/MessageCenter.vue"),
meta: {
title: '活动资讯中心',
icon: '',
hidden: false
}
},
{
path: '/SingleMessageDetail/:id/:flag',
name: '资讯详情',
component: () => import("@/views/ActivityMessageManagement/SingleMessageDetail.vue"),
meta: {
title: '资讯详情',
hidden: true
}
}
]
},
// 优惠卷信息
{
path: '/coupon',
@ -328,6 +370,15 @@ export const constantRoute = [
icon: 'User',
hidden: false
}
},
{
path: '/SingleUserDetail/:id/:flag',
name: '用户详情',
component: () => import("@/views/User/SingleUserDetail.vue"),
meta: {
title: '用户详情',
hidden: true
}
}
]
},

View File

@ -1,110 +0,0 @@
import { ref } from 'vue';
import myAxios from '@/api/myAxios';
import { type UploadFile, type UploadProps,type UploadUserFile} from 'element-plus';
import { WarnInfo } from '../messageInfo';
export const productImgMap = new Map() //商品图片集合
export const productImgArr: any = ref([]) //商品图片数组
export const ImgArr: any = ref<UploadUserFile[]>([]) //给商品中心页面编辑商品使用
export const fileSimple = ref() //单个文件
export const form : any = ref({ //添加实体类商品的表单
name: '', //商品名称
price: '', //商品价格
intro: '',//产品简介
festivalName: '', //节日名称
type: '',//类别
label: '',//商品标签
// introDetail: '',//详情描述
goodImg: '', //商品图片url
// detailImg: '', //图文详情url
inventory: '', //库存
richText: ''
})
export const editForm: any = ref({}) //编辑后的实体类商品表格
//图片上传请求 此请求只要选择了图片,就会默认上传
export 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/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
// 取出formData对象中的file
file: formData.get("file")
}
})
// console.log('图片上传的结果--->',res.data)
if (res.data.code === 1) {
if ( flag === 2 ) {
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 if(flag === 0 && ImgArr != null) {
dealImgArr(ImgArr.value) //先处理
productImgMap.set(fileSimple.value.uid,res.data.data)
productImgMap.forEach(loopMap) //将图片url插入到数组中
pushImgArr(productImgArr.value)
editForm.value.goodImg = formatString()
productImgMap.clear() //清除所有的键防止bug
}
}
}
const formatString = () => { //拼接图片URL,方便传给后端
var str = ''
str = productImgArr.value.join(';')
return str
}
const loopMap = (value: any, key: any, map: any) => { //循环商品图片Map集合函数,用于给请求的字段赋值
productImgArr.value.push(value)
}
const pushImgArr = (arr: any) =>{
ImgArr.value.splice(0, ImgArr.value.length) //先清空,防止之前的
arr.forEach((item:any)=>{
ImgArr.value.push({
url: item
})
})
console.log('处理完之后的图片数组--->',ImgArr.value);
}
const dealImgArr = (obj: any) =>{ //处理商品图片数组对象
productImgArr.value.splice(0, productImgArr.value.length) //防止数组越界
console.log('商品图片对象--->',obj);
obj.forEach((item: any)=>{
if(item.status === 'success') {
productImgArr.value.push(item.url) //赋值给商品图片数组
}
})
ImgArr.value.splice(0,ImgArr.value.length)
}
//针对添加商品的删除图片
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('最多只能上传七张图片!')
}
//针对的是商品中心编辑按钮的删除
export const removePic : UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //uploadFile表示当前删除的图片uploadFiles是还剩余的图片信息
ImgArr.value = ImgArr.value.filter((item:any)=>{
return uploadFile.url !== item.url
})
console.log(ImgArr.value);
dealImgArr(ImgArr.value)
pushImgArr(productImgArr.value)
editForm.value.goodImg = formatString()
}

View File

@ -0,0 +1,4 @@
//上传链接
export const uploadUrl : string = 'http://localhost:9092/api/file/uploadFile'
// export const uploadUrl = 'https://www.carboner.cn:8888/api/file/uploadFile'
export const downloadUrl : string = 'https://www.carboner.cn:8888/api/file/downloadFile?objectKey='

View File

@ -0,0 +1,116 @@
<template>
<!-- 批量图片上传 -->
<el-upload
v-model:file-list="ImgList"
action="#"
list-type="picture-card"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-exceed="ExceedImg"
:http-request="compressImage"
limit="7"
v-loading="loading"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-dialog v-model="dialogVisible">
<el-image :src="dialogImageUrl"/>
</el-dialog>
</template>
<script lang="ts" setup>
import myAxios from '@/api/myAxios'
import { ref,defineEmits,watch } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import type { UploadProps } from 'element-plus'
import { uploadUrl } from '@/utils/formatImgUpload'
import { WarnInfo } from "@/utils/messageInfo";
import Compressor from "compressorjs";
const goodImgStr = ref('') //
const goodImgArr= ref<String[]>([]) //objectKey
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const loading = ref(false)
const ImgList: any = ref([])
const emit = defineEmits<Emits>() //
interface Emits {
(event: 'update:goodImgArr' , newVal: string): void
}
const compressImage =(file: any)=> { //
// console.log('compressImage',file)
return new Promise((resolve, reject) => {
new Compressor(file.file, {
quality: 0.3, //
success(result) {
console.log('res--->',result)
//
const compressedFile = new File([result], file.file.name, { type: result.type });
//
console.log("Compressed file:", compressedFile);
//
customUpload(compressedFile)
// resolve(compressedFile);
},
error(err) {
reject("压缩失败");
console.log("Compressor error:", err.message);
}
});
});
}
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //
// console.log(uploadFile)
// let deleteObjKey = uploadFile.url?.substring(downloadUrl.length)
// console.log('--->',deleteObjKey)
goodImgArr.value = goodImgArr.value.filter((item)=>{ //
return !item.includes(replaceSpecialChars(uploadFile.name))
})
goodImgStr.value = goodImgArr.value.join(';')
}
const replaceSpecialChars = (input : any) => { //(+&)线
// 使线
return input.replace(/[^a-zA-Z0-9\u4e00-\u9fa5.]/g, '_');
}
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!
dialogVisible.value = true
}
const ExceedImg: UploadProps['onExceed'] = (files) => { // 'onExceed'
WarnInfo('最多只能上传七张图片!')
}
//
const customUpload = async (file:any) => {
loading.value = true
const res = await myAxios({
url: uploadUrl,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: {
biz: "test",
file: file
}
})
// console.log('--->',res.data)
if(res.data.code === 1) {
goodImgStr.value = ''
goodImgArr.value.push(res.data.data)
goodImgStr.value = goodImgArr.value.join(';')
loading.value = false
}
}
watch(goodImgStr, (newVal:any) => {
emit('update:goodImgArr', newVal)
// console.log('--->',newVal)
})
</script>

View File

@ -0,0 +1,103 @@
<template>
<!-- 批量图片上传 -->
<el-upload
v-model:file-list="ImgList"
action="#"
list-type="picture-card"
:http-request="compressImage"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-exceed="ExceedImg"
limit="1"
v-loading="loading"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-dialog v-model="dialogVisible">
<el-image :src="dialogImageUrl"/>
</el-dialog>
</template>
<script lang="ts" setup>
import myAxios from '@/api/myAxios'
import { ref,defineEmits,watch } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import type { UploadProps } from 'element-plus'
import { uploadUrl } from '@/utils/formatImgUpload'
import { WarnInfo } from "@/utils/messageInfo";
import Compressor from "compressorjs";
const goodImgStr = ref('') //
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const loading = ref(false)
const ImgList: any = ref([])
const emit = defineEmits<Emits>() //
interface Emits {
(event: 'update:goodImgArr' , newVal: string): void
}
const compressImage =(file: any)=> { //
// console.log('compressImage',file)
return new Promise((resolve, reject) => {
new Compressor(file.file, {
quality: 0.3, //
success(result) {
console.log('res--->',result)
//
const compressedFile = new File([result], file.file.name, { type: result.type });
//
// console.log("Compressed file:", compressedFile);
//
customUpload(compressedFile)
// resolve(compressedFile);
},
error(err) {
reject("压缩失败");
console.log("Compressor error:", err.message);
}
});
});
}
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //
goodImgStr.value = ''
}
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!
dialogVisible.value = true
}
const ExceedImg: UploadProps['onExceed'] = (files) => { // 'onExceed'
WarnInfo('请删掉后再上传')
}
//
const customUpload = async (file:any) => {
loading.value = true
const res = await myAxios({
url: uploadUrl,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: {
biz: "test",
file: file
}
})
console.log('图片上传--->',res)
if(res.data.code === 1) {
goodImgStr.value = res.data.data
loading.value = false
}
}
watch(goodImgStr, (newVal:any) => {
emit('update:goodImgArr', newVal)
})
</script>

View File

@ -0,0 +1,148 @@
<template>
<el-upload
v-model:file-list="ImgList"
action="#"
list-type="picture-card"
:http-request="compressImage"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-exceed="ExceedImg"
limit="7"
v-loading="loading"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-dialog v-model="dialogVisible">
<el-image :src="dialogImageUrl"/>
</el-dialog>
</template>
<script lang="ts" setup>
import myAxios from '@/api/myAxios'
import { ref,defineEmits,defineProps,watch,onUpdated } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import type { UploadProps } from 'element-plus'
import { uploadUrl, downloadUrl } from '@/utils/formatImgUpload'
import { WarnInfo } from "@/utils/messageInfo";
import Compressor from "compressorjs";
const goodImgStr = ref('') //
const goodImgArr= ref<String[]>([]) //objectKey
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const loading = ref(false)
const emit = defineEmits<Emits>()
const props = defineProps<Props>() //props
const previwUrl = ref('')
const flag = ref(0)
interface Emits {
(event: 'update:goodImgArr' , newVal: string): void
}
interface Props {
ImgUrlList: string;
}
onUpdated(()=>{ //
if(flag.value === 0){
formatImgUrlList()
}
})
const compressImage =(file: any)=> { //
// console.log('compressImage',file)
return new Promise((resolve, reject) => {
new Compressor(file.file, {
quality: 0.3, //
success(result) {
console.log('res--->',result)
//
const compressedFile = new File([result], file.file.name, { type: result.type });
//
// console.log("Compressed file:", compressedFile);
//
customUpload(compressedFile)
// resolve(compressedFile);
},
error(err) {
reject("压缩失败");
console.log("Compressor error:", err.message);
}
});
});
}
const formatImgUrlList = () => { //
flag.value = 1
goodImgArr.value = previwUrl.value.split(';')
// console.log('--->',goodImgArr.value)
goodImgArr.value.forEach(item => { //
ImgList.value.push({
url: downloadUrl + item
})
})
goodImgStr.value = goodImgArr.value.join(';') //objectKey
}
const ImgList: any = ref([])
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //
console.log(uploadFile)
let deleteObjKey = uploadFile.url?.substring(downloadUrl.length)
// console.log('--->',deleteObjKey)
goodImgArr.value = goodImgArr.value.filter(item => item !== deleteObjKey)
goodImgArr.value = goodImgArr.value.filter((item)=>{
return !item.includes(replaceSpecialChars(uploadFile.name))
})
goodImgStr.value = goodImgArr.value.join(';')
}
const replaceSpecialChars = (input : any) => { //(+&)线
// 使线
return input.replace(/[^a-zA-Z0-9\u4e00-\u9fa5.]/g, '_');
}
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!
dialogVisible.value = true
}
const ExceedImg: UploadProps['onExceed'] = (files) => { // 'onExceed'
WarnInfo('最多只能上传七张图片!')
}
//
const customUpload = async (file:any) => {
loading.value = true
const res = await myAxios({
url: uploadUrl,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: {
biz: "test",
file: file
}
})
// console.log('--->',res.data)
if(res.data.code === 1) {
goodImgArr.value.push(res.data.data)
goodImgStr.value = goodImgArr.value.join(';') //goodImgStr
loading.value = false
}
}
watch(()=> props.ImgUrlList, (newVal) => {
previwUrl.value = newVal
})
watch(goodImgStr, (newVal:any) => {
emit('update:goodImgArr', newVal)
// console.log('goodImgStr: ', goodImgStr.value)
})
</script>

View File

@ -0,0 +1,149 @@
<template>
<el-upload
v-model:file-list="ImgList"
action="#"
list-type="picture-card"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-exceed="ExceedImg"
:http-request="compressImage"
limit="1"
v-loading="loading"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-dialog v-model="dialogVisible">
<el-image :src="dialogImageUrl"/>
</el-dialog>
</template>
<script lang="ts" setup>
import myAxios from '@/api/myAxios'
import { ref,defineEmits,defineProps,watch,onUpdated } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import type { UploadProps } from 'element-plus'
import { uploadUrl, downloadUrl } from '@/utils/formatImgUpload'
import { WarnInfo } from "@/utils/messageInfo";
import Compressor from "compressorjs";
const goodImgStr = ref('') //
const goodImgArr= ref<String[]>([]) //objectKey
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const loading = ref(false)
const emit = defineEmits<Emits>()
const props = defineProps<Props>() //props
const previwUrl = ref('')
const flag = ref(0)
interface Emits {
(event: 'update:goodImgArr' , newVal: string): void
}
interface Props {
ImgUrlList: string;
}
onUpdated(()=>{ //
if(flag.value === 0) {
formatImgUrlList()
}
})
const compressImage =(file: any)=> { //
// console.log('compressImage',file)
return new Promise((resolve, reject) => {
new Compressor(file.file, {
quality: 0.3, //
success(result) {
console.log('res--->',result)
//
const compressedFile = new File([result], file.file.name, { type: result.type });
//
// console.log("Compressed file:", compressedFile);
//
customUpload(compressedFile)
// resolve(compressedFile);
},
error(err) {
reject("压缩失败");
console.log("Compressor error:", err.message);
}
});
});
}
const formatImgUrlList = () => { //
flag.value = 1
goodImgArr.value = previwUrl.value.split(';')
console.log('分号隔开的数组--->',goodImgArr.value)
goodImgArr.value.forEach(item => { //
ImgList.value.push({
url: downloadUrl + item
})
})
goodImgStr.value = goodImgArr.value.join(';') //objectKey
}
const ImgList: any = ref([])
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //
console.log(uploadFile)
let deleteObjKey = uploadFile.url?.substring(downloadUrl.length)
goodImgArr.value = goodImgArr.value.filter(item => item !== deleteObjKey)
goodImgArr.value = goodImgArr.value.filter((item)=>{
return !item.includes(replaceSpecialChars(uploadFile.name))
})
goodImgStr.value = goodImgArr.value.join(';')
}
const replaceSpecialChars = (input : any) => { //(+&)线
// 使线
return input.replace(/[^a-zA-Z0-9\u4e00-\u9fa5.]/g, '_');
}
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!
dialogVisible.value = true
}
const ExceedImg: UploadProps['onExceed'] = (files) => { // 'onExceed'
WarnInfo('请删除之前的再上传')
}
//
const customUpload = async (file:any) => {
loading.value = true
const res = await myAxios({
url: uploadUrl,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: {
biz: "test",
file: file
}
})
// console.log('--->',res.data)
if(res.data.code === 1) {
goodImgArr.value.push(res.data.data)
goodImgStr.value = goodImgArr.value.join(';') //goodImgStr
loading.value = false
}
}
watch(()=> props.ImgUrlList, (newVal) => {
previwUrl.value = ''
previwUrl.value = newVal
// formatImgUrlList()
// console.log('previewUrl--->', previwUrl.value)
})
watch(goodImgStr, (newVal:any) => {
emit('update:goodImgArr', newVal)
// console.log('goodImgStr: ', goodImgStr.value)
})
</script>

View File

@ -0,0 +1,123 @@
<template>
<div class="flexCard">
<!-- 表单 ref prop绑定 用于重置表单 -->
<el-card class="form-container" shadow="never" >
<div class="form">
<el-form ref="resetFormData" :model="form" label-width="auto" size="large" >
<div>
<el-form-item label="添加活动图片">
<ImgSingleUpload @update:goodImgArr="form.image = $event"/>
</el-form-item>
</div>
<el-form-item label="资讯标题">
<el-input v-model="form.title" maxlength="12" minlength="2" show-word-limit style="width: 260px;" />
</el-form-item>
<el-form-item label="文章发布时间">
<el-date-picker
v-model="form.publishTime"
type="date"
placeholder="选择发布日期"
value-format="YYYY-MM-DD"
:disabled-date="disabledDate"
size="large"
/>
</el-form-item>
<el-form-item label="公众号链接">
<el-input v-model="form.url" show-word-limit style="width: 260px;" />
</el-form-item>
<div class="btnBox">
<el-form-item>
<el-button type="primary" @click="onSubmit" :disabled="saveBtn">保存</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetForm">重置</el-button>
</el-form-item>
</div>
</el-form>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, inject } from 'vue';
import { SuccessInfo, WarnInfo, CommInfo } from '@/utils/messageInfo'; //ElMessage
import myAxios from "@/api/myAxios";
import { saveBtn, invInput } from '@/utils/entityProduct/globalVar';
import ImgSingleUpload from "@/utils/imgUpload/ImgSingleUpload.vue";
const resetFormData = ref()
const reload: any = inject("reload") //
const form : any = ref({ //
title: '',
image: '',
publishTime: '',
url: '',
})
onMounted(() => {
})
const disabledDate = (time : any ) => {
// console.log('time---->',time.getTime())
return time.getTime() > Date.now()
}
//
const onSubmit = async () => {
console.log('表单--->',form.value)
const values = Object.values(form.value );
// 使some()
if (values.some((value: any) => value === null || value === undefined || value === '' )) {
WarnInfo('请检查表单数据是否完整填写')
return; //
}
const res = await myAxios.post('/article/add', {
title: form.value.title,
image: form.value.image,
publishTime: form.value.publishTime.replace(/(.+?)\-(.+?)\-(.+)/,"$1年$2月$3日"),
url: form.value.url
})
if (res.data.code === 1) {
SuccessInfo('提交成功')
form.value = {} //12.18
reload() //
} else {
WarnInfo('服务错误')
return;
}
}
//
const resetForm = () => {
resetFormData.value.resetFields()
}
</script>
<style scoped>
.flexCard {
display: flex;
height: 100%;
min-width: 800px;
margin: 0 auto;
}
.form-container {
width: 700px;
margin: 0 auto;
}
.form {
/* width: 500px; */
margin: 0 auto;
}
.btnBox {
display: flex;
justify-content: space-around;
}
</style>

View File

@ -0,0 +1,178 @@
<template>
<!-- 修改前请注释以前的 -->
<!-- 搜索 -->
<div class="table_page">
<div>
<el-input style="width: 240px; margin-right: 10px;" suffix-icon="Search" placeholder="资讯名称" size="default"
v-model="productName"></el-input>
<el-button type="primary" @click="" style="margin-right: 10px;" size="default">
搜索
</el-button>
<el-button type="warning" @click="reset" size="default">重置</el-button>
</div>
<!-- 批量删除 -->
<!-- <div style="margin: 15px 0">-->
<!-- <el-popconfirm class="ml-5" confirm-button-text='确定' cancel-button-text='取消' icon="InfoFilled" icon-color="red"-->
<!-- title="您确定批量删除这些数据吗?" @confirm="delBatch" width=180>-->
<!-- <template #reference>-->
<!-- <el-button style="height: 25px" class="ml-5" type="danger">批量删除-->
<!-- <el-icon style="margin-left: 5px;">-->
<!-- <Remove/>-->
<!-- </el-icon>-->
<!-- </el-button>-->
<!-- </template>-->
<!-- </el-popconfirm>-->
<!-- </div>-->
<!-- 数据展示 -->
<el-table :data="tableData" border stripe header-cell-class-name="headerBg"
:cell-style="{ 'text-align': 'center', 'font-size': '16px' }" @selection-change="handleSelectionChange"
@select="selectChange"
:header-cell-style="{ 'text-align': 'center' }">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="id" label="编号" width="80">
<template #default="{ $index }">
{{ $index + 1 }}
</template>
</el-table-column>
<el-table-column prop="title" label="标题"></el-table-column>
<el-table-column prop="image" label="预览图" width="200">
<template #default="scope">
<div>
<img :src="downloadUrl + scope.row.image" alt="" style="height: 50px;">
</div>
</template>
</el-table-column>
<el-table-column prop="publishTime" label="发布时间" width="150"></el-table-column>
<el-table-column label="操作" width="230px">
<template #default="scope">
<el-button size="small" @click="ReviseOrView(scope.row , 0)">
详情
</el-button>
<el-button size="small" @click="ReviseOrView(scope.row, 1)">
编辑
</el-button>
<el-popconfirm class="ml-5" confirm-button-text='确定' cancel-button-text='取消' icon="InfoFilled"
icon-color="red"
title="是否确认删除" @confirm="deleteMessage(scope.row.id)" width=180>
<template #reference>
<el-button class="ml-5" type="danger">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!-- 分页器 -->
<div style="padding: 10px 0">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
:current-page="searchParams.current" :page-size="searchParams.pageSize" :page-sizes="[5, 10, 15, 20]"
:small="null" :disabled="null" :background="null" layout="total, sizes, prev, pager, next, jumper"
:total="total"/>
</div>
</div>
</template>
<script setup lang="ts">
import { ElMessage } from 'element-plus';
import {ref, onMounted, inject} from 'vue';
import myAxios from "@/api/myAxios";
import { useRouter } from "vue-router";
import {downloadUrl} from '@/utils/formatImgUpload'
const router = useRouter(); //
const total = ref(0); //
const idList = ref<Number[]>([]);
const searchParams: any = ref({ //
current: 1, //
pageSize: 5, //
sortField: "id", //ID
sortOrder: "descend" //
})
const productName = ref('');
const tableData: any = ref([]); //
const reload: any = inject("reload") //
onMounted(() => { //
getMessageList()
})
const getMessageList = async () => {
try {
const res = await myAxios.post('/article/query/web', {...searchParams.value});
console.log('资讯表格--->', res.data)
if (res.data.code === 1) {
tableData.value = res.data.data.records;
total.value = parseInt(res.data.data.total) //
} else {
ElMessage({
message: '获取数据失败',
});
return;
}
} catch (error) {
ElMessage({
message: '发生错误',
});
}
}
//
const deleteMessage = async (index: number) => {
console.log(typeof index)
const res = await myAxios.post('/article/delete', {id: index})
console.log(res)
if (res.data.code === 1) {
ElMessage({
type: 'success',
message: '删除成功',
})
await getMessageList()
}
}
//
const ReviseOrView = ( row: any, flag: number) => {
router.push({
name: '资讯详情',
params: {
id: row.id,
flag: flag
}
})
}
//
const handleSizeChange = (newSize: any) => {
searchParams.value.pageSize = newSize //
getMessageList()
}
//
const handleCurrentChange = (Current: any) => {
searchParams.value.current = Current
getMessageList()
}
//
const reset = () => {
reload()
};
const handleSelectionChange = () => {
}
const selectChange = (selection: any, row: any) => { //selctionrow
idList.value.splice(0, idList.value.length) //
selection.forEach((item: any) => {
idList.value.push(item.id)
})
// console.log('idList--->',idList.value);
}
//
const onSearch = (value: string) => {}
</script>
<style scoped>
.table_page {
min-width: 800px;
}
</style>

View File

@ -0,0 +1,139 @@
<template>
<div class="flexCard">
<!-- 表单 ref prop绑定 用于重置表单 -->
<el-card class="form-container" shadow="never" >
<div class="form">
<el-form ref="resetFormData" :model="form" label-width="auto" size="large" :disabled="disabled">
<div>
<el-form-item label="添加活动图片">
<PreviewSingleImgUpload :ImgUrlList="form.image" @update:goodImgArr="form.image = $event"/>
</el-form-item>
</div>
<el-form-item label="资讯标题">
<el-input v-model="form.title" maxlength="30" minlength="2" show-word-limit style="width: 260px;" />
</el-form-item>
<el-form-item label="文章发布时间">
<el-date-picker
v-model="form.publishTime"
type="date"
placeholder="选择发布日期"
value-format="YYYY-MM-DD"
:disabled-date="disabledDate"
size="large"
/>
</el-form-item>
<el-form-item label="公众号链接">
<el-input v-model="form.url" style="width: 260px;" />
</el-form-item>
<div class="btnBox">
<el-form-item>
<el-button type="primary" @click="onSubmit" :disabled="saveBtn">保存</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetForm">重置</el-button>
</el-form-item>
</div>
</el-form>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { SuccessInfo, WarnInfo, CommInfo } from '@/utils/messageInfo'; //ElMessage
import myAxios from "@/api/myAxios";
import { saveBtn } from '@/utils/entityProduct/globalVar';
import { useRoute, useRouter } from "vue-router";
import PreviewSingleImgUpload from "@/utils/imgUpload/PreviewSingleImgUpload.vue";
const route = useRoute();
const resetFormData = ref()
const form : any = ref({ //
title: '',
image: '',
publishTime: '',
url: '',
})
const disabled = ref(true)
const router = useRouter();
onMounted(() => {
getMessageInfo()
if(route.params.flag === '1') {
disabled.value = false
}
})
const getMessageInfo = async () =>{
const res = await myAxios.post('/article/query/id', { id: route.params.id });
console.log('后端返回的信息--->',res.data)
if(res.data.code === 1) {
form.value = res.data.data
} else {
WarnInfo('服务错误')
}
}
const disabledDate = (time : any ) => {
// console.log('time---->',time.getTime())
return time.getTime() > Date.now()
}
//
const onSubmit = async () => {
// console.log('--->',form.value)
const values = Object.values(form.value );
// 使some()
if (values.some((value: any) => value === null || value === undefined || value === '' )) {
WarnInfo('请检查表单数据是否完整填写')
return; //
}
const res = await myAxios.post('/article/update', {
id: form.value.id,
title: form.value.title,
image: form.value.image,
publishTime: form.value.publishTime.replace(/(.+?)\-(.+?)\-(.+)/,"$1年$2月$3日"),
url: form.value.url
})
if (res.data.code === 1) {
SuccessInfo('提交成功')
router.replace('/MessageCenter')
} else {
WarnInfo('服务错误')
return;
}
}
//
const resetForm = () => {
resetFormData.value.resetFields()
}
</script>
<style scoped>
.flexCard {
display: flex;
height: 100%;
min-width: 800px;
margin: 0 auto;
}
.form-container {
width: 700px;
margin: 0 auto;
}
.form {
/* width: 500px; */
margin: 0 auto;
}
.btnBox {
display: flex;
justify-content: space-around;
}
</style>

View File

@ -7,24 +7,17 @@
<!-- 表单 ref prop绑定 用于重置表单 -->
<el-card class="form-container" shadow="never">
<div class="form">
<el-form ref="resetFormData" :model="form" label-width="auto" size="large" :rules="rules">
<el-form ref="resetFormData" :model="form" size="large" :rules="rules">
<div>
<el-form-item label="添加商品图片">
<!-- 下面的event的作用,传入当前事件对象 -->
<el-upload ref="uploadProductImg" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 2)" :on-exceed="Exceed_ProductImg"
limit="7">
<el-icon>
<Plus />
</el-icon>
</el-upload>
<ImgListUpload @update:goodImgArr="form.goodImg = $event"/>
</el-form-item>
</div>
<div class="NamePrice">
<el-form-item label="产品名称" prop="name">
<el-input v-model="form.name" maxlength="12" minlength="2" show-word-limit style="width: 260px;" />
</el-form-item>
<el-form-item label="产品价格" prop="price">
<el-form-item label="产品价格" prop="price" label-width="100">
<el-input-number v-model="form.price" min="0" :precision="2" :step="0.5" />
<p></p>
</el-form-item>
@ -35,7 +28,7 @@
style="width: 300px;" />
</el-form-item>
<div>
<el-form-item label="库存" prop="inventory">
<el-form-item label="库存" prop="inventory" label-width="80">
<el-input-number v-model="form.inventory" min="0" :precision="0" :step="1" :disabled="invInput" />
</el-form-item>
</div>
@ -46,7 +39,7 @@
<el-option v-for="item in festivalArr" :key="item" :label="item.name" :value="item.name" />
</el-select>
</el-form-item>
<el-form-item label="产品类别" prop="type" style="width: 240px;">
<el-form-item label="产品类别" prop="type" style="width: 240px;" label-width="80">
<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>
@ -60,7 +53,8 @@
<el-input v-model="labelList[index]" type="text" style="width: 150px;" maxlength="5" show-word-limit
@blur="addLabelList" />
</div>
<el-button type="primary" @click="addLabel">添加</el-button>
<el-button type="primary" size="large" @click="addLabel">添加</el-button>
<el-button type="danger" size="large" @click="deleteLabel" v-if="labelList.length > 1">删除</el-button>
</el-form-item>
<el-form-item label="商品图文" prop="richText">
<richTextUtil @richTextContent="getInfo"/>
@ -80,24 +74,38 @@
</template>
<script lang="ts" setup>
import { ref, onMounted, inject, reactive } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import {ref, onMounted, inject, reactive, onBeforeMount} from 'vue';
import { type FormRules } from 'element-plus';
import { SuccessInfo, WarnInfo, CommInfo } from '@/utils/messageInfo'; //ElMessage
import myAxios from "@/api/myAxios";
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';
import richTextUtil from '@/layout/components/richTextUtil.vue';
import ImgListUpload from '@/utils/imgUpload/ImgListUpload.vue'
const resetFormData = ref()
const reload: any = inject("reload") //
const typeList: any = ref([])
const uploadProductImg: any = ref() //ref
const labelList = ref([''])
const isqualify : any = ref(false)
const typeSelect : any = ref(false) //
const previewRichText: any = ref<String>('')
const festivalArr : any = ref([]) //
const form : any = ref({ //
name: '', //
price: 0, //
intro: '',//
festivalName: '', //
type: '',//
label: '',//
goodImg: '', //url
inventory: 0, //
richText: ''
})
onBeforeMount(()=>{
form.value.festivalName = '无'
})
onMounted(() => {
getTypeList() //select
@ -122,9 +130,10 @@ const getTypeList = async () => { //获取类别列表作为可选项
}
//
const onSubmit = async () => {
console.log(form.value)
const values = Object.values(form.value );
// 使some()
if (values.some((value: any) => value === null || value === undefined || value === '' || value === 0)) {
if (values.some((value: any) => value === null || value === undefined || value === '' || value === 0 || value === 'PHA+PGJyPjwvcD4=')) {
WarnInfo('请检查表单数据是否完整填写')
return; //
}
@ -171,6 +180,11 @@ const addLabel = () => { //添加商品标签按钮的方法
labelList.value.push('')
}
}
const deleteLabel = () => { //
labelList.value.pop()
}
const addLabelList = () => { //
var string = ''
if (!labelList.value.some((item: any) => item === '')) {
@ -205,8 +219,8 @@ function encode64(text: string): string {
.flexCard {
display: flex;
height: 100%;
width: 1200px;
overflow-x: auto;
min-width: 800px;
margin: 0 auto;
}
.richTextPreview {
@ -217,7 +231,9 @@ function encode64(text: string): string {
margin-right: 10px;
}
.form-container {
width: 700px;
width: 900px;
height: 800px;
overflow: auto;
/* margin: 0 auto; */
}
.form {
@ -241,4 +257,9 @@ function encode64(text: string): string {
display: flex;
justify-content: space-around;
}
.titleText {
text-align: center;
margin: 0 auto;
}
</style>

View File

@ -11,13 +11,7 @@
<div>
<el-form-item label="添加商品图片">
<!-- 下面的event的作用,传入当前事件对象 -->
<el-upload v-model:file-list="ImgArr" ref="uploadProductImg" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 2)" :on-exceed="Exceed_ProductImg"
limit="7">
<el-icon>
<Plus />
</el-icon>
</el-upload>
<PreviewImgUpload :ImgUrlList="previewImgUrl" @update:goodImgArr="detailFrom.goodImg = $event"/>
</el-form-item>
</div>
<div class="NamePrice">
@ -60,9 +54,10 @@
<el-input v-model="labelList[index]" type="text" style="width: 150px;" maxlength="5" show-word-limit
@blur="addLabelList" />
</div>
<el-button type="primary" @click="addLabel">添加</el-button>
<el-button type="primary" size="large" @click="addLabel">添加</el-button>
<el-button type="danger" size="large" @click="deleteLabel" v-if="labelList.length > 1">删除</el-button>
</el-form-item>
<el-form-item label="商品图文" prop="richText">
<el-form-item label="商品图文" prop="richText" v-loading="loading">
<richTextUtil @richTextContent="getInfo" v-model:disableRich="disabledRichText" v-model:context="previewRichText"/>
</el-form-item>
<div class="btnBox">
@ -80,22 +75,20 @@
</template>
<script lang="ts" setup>
import { ref, onMounted, inject, reactive, onBeforeMount } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { ref, onMounted, reactive, onBeforeMount } from 'vue';
import {type FormRules, type UploadUserFile} from 'element-plus';
import { SuccessInfo, WarnInfo, CommInfo } from '@/utils/messageInfo'; //ElMessage
import myAxios from "@/api/myAxios";
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';
import richTextUtil from '@/layout/components/richTextUtil.vue';
import { useRoute } from "vue-router";
import { useRoute, useRouter} from "vue-router";
import PreviewImgUpload from '@/utils/imgUpload/PreviewImgUpload.vue'
const router = useRouter()
const route = useRoute(); //
const resetFormData = ref()
const reload: any = inject("reload") //
const typeList: any = ref([])
const uploadProductImg: any = ref() //ref
const labelList = ref([''])
const isqualify : any = ref(false)
const typeSelect : any = ref(false) //
@ -107,26 +100,30 @@ const detailFrom : any = ref({
festivalName: '', //
type: '',//
label: '',//
// introDetail: '',//
goodImg: '', //url
// detailImg: '', //url
inventory: '', //
richText: ''
})
const disabledRichText:any = ref(false);
const previewRichText:any = ref('');
const festivalArr : any = ref([]) //
const previewImgUrl = ref('') //
const loading = ref(true)
onBeforeMount(()=>{ //
getProductInfo() //
if(route.params.flag === '0'){
disabledRichText.value = true;
}
})
onMounted(() => {
getTypeList() //select
getProductInfo() //
getFestivalArr()
setTimeout(()=>{ //
loading.value = false
},1500)
})
//
@ -141,11 +138,13 @@ const getFestivalArr = async () => {
const getProductInfo = async () => { //
const res = await myAxios.post('/goods/getById',{ id: route.params.id })
// console.log('--->',res.data.data)
console.log('后端查询商品--->',res.data.data)
if(res.data.code === 1) {
previewImgUrl.value = res.data.data.goodImg
detailFrom.value = res.data.data
previewRichText.value = JSON.parse(JSON.stringify(res.data.data.richText))
previewRichText.value = res.data.data.richText
ImgArr.value.splice(0, ImgArr.value.length)
detailFrom.value.festivalName = res.data.data.festivalName.substring(0,1)
labelList.value = res.data.data.label.split(';')
var tempArr = res.data.data.goodImg.split(';')
tempArr.forEach((item: any) => {
@ -165,9 +164,10 @@ const getTypeList = async () => { //获取类别列表作为可选项
//
const onSubmit = async () => {
console.log('提交前的表格',detailFrom.value)
const values = Object.values(detailFrom.value );
// 使some()
if (values.some((value: any) => value === null || value === undefined || value === '' || value === 0)) {
if (values.some((value: any) => value === null || value === undefined || value === '' || value === 'PHA+PGJyPjwvcD4=')) {
WarnInfo('请检查表单数据是否完整填写')
return; //
}
@ -175,8 +175,7 @@ const onSubmit = async () => {
// console.log(res.data);
if (res.data.code === 1) {
SuccessInfo('提交成功')
// detailFrom.value = {}
// reload() //
await router.replace('/MerchandiseCenter')
} else {
WarnInfo('服务错误')
return;
@ -190,7 +189,7 @@ const loadForm = (value: any) => {
const resetForm = () => {
resetFormData.value.resetFields()
}
const rules = reactive<FormRules<typeof form>>({ //
const rules = reactive<FormRules<typeof detailFrom>>({ //
name: [{ validator: validateName, trigger: 'blur' }],
intro: [{ validator: validateIntro, trigger: 'blur' }],
introDetail: [{ validator: validateDetail, trigger: 'blur' }]
@ -204,7 +203,9 @@ const addLabel = () => { //添加商品标签按钮的方法
labelList.value.push('')
}
}
const deleteLabel = () => { //
labelList.value.pop()
}
const addLabelList = () => { //
var string = ''
if (!labelList.value.some((item: any) => item === '')) {
@ -244,6 +245,7 @@ function encode64(text: string): string {
.flexCard {
display: flex;
height: 100%;
min-width: 800px;
}
.richTextPreview {
@ -255,7 +257,9 @@ function encode64(text: string): string {
}
.form-container {
width: 700px;
width: 900px;
height: 800px;
overflow: auto;
/* margin: 0 auto; */
}
.form {
@ -279,4 +283,9 @@ function encode64(text: string): string {
display: flex;
justify-content: space-around;
}
.titleText {
text-align: center;
margin: 0 auto;
}
</style>

View File

@ -1,6 +1,7 @@
<template>
<!-- 修改前请注释以前的 -->
<!-- 搜索 -->
<div class="table_page">
<div>
<el-input style="width: 240px; margin-right: 10px;" suffix-icon="Search" placeholder="请输入商品名称" size="default"
v-model="productName"></el-input>
@ -44,7 +45,7 @@
<el-table-column prop="goodImg" label="商品图片">
<template #default="scope">
<div>
<img :src="scope.row.goodImg.split(';')[0]" alt="" style="height: 50px;">
<img :src="downloadUrl + scope.row.goodImg.split(';')[0]" alt="" style="height: 50px;">
</div>
</template>
</el-table-column>
@ -95,15 +96,17 @@
:small="null" :disabled="null" :background="null" layout="total, sizes, prev, pager, next, jumper"
:total="total"/>
</div>
</div>
</template>
<script setup lang="ts">
import {ElMessage, type UploadProps, genFileId, type UploadRawFile} from 'element-plus';
import { ElMessage } from 'element-plus';
import {ref, onMounted, inject} from 'vue';
import myAxios from "@/api/myAxios";
import { editForm } from '@/utils/entityProduct/picUpload';
import { useRouter } from "vue-router";
import {downloadUrl} from '@/utils/formatImgUpload'
const editForm = ref({})
const router = useRouter(); //
const total = ref(0); //
const idList = ref<Number[]>([]);
@ -117,7 +120,6 @@ const productName = ref('');
const state = ref(''); //select
const tableData: any = ref([]); //
const reload: any = inject("reload") //
const uploadProductDetail: any = ref() //ref
const typeList: any = ref([
{
value1: '',
@ -251,7 +253,8 @@ const onSearch = (value: string) => {}
</script>
<style scoped>
.headerBg {
background-color: #eee !important;
.table_page {
min-width: 1000px;
overflow: auto;
}
</style>

View File

@ -1,4 +1,5 @@
<template>
<div class="table_page">
<div style="margin-bottom: 10px;">
<el-button type="success" @click="showForm">添加类别</el-button>
</div>
@ -25,9 +26,6 @@
<el-form-item label="类别名">
<el-input v-model="typeForm.typeName" @input="changeInput"/>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="typeForm.typeIntro" @input="changeInput"/>
</el-form-item>
</el-form>
<template #footer #default="{ row, $index }">
<div class="dialog-footer">
@ -46,10 +44,9 @@
<el-table-column prop="typeUrl" label="类别图片" width="300">
<!-- 插槽拿到父组件的值typeUrl -->
<!-- scope 提供了关于当前行的信息 -->
<template #default="scope"><img :src="scope.row.typeUrl" alt="" style="height: 50px;"></template>
<template #default="scope"><img :src="downloadUrl + scope.row.typeUrl" alt="" style="height: 50px;"></template>
</el-table-column>
<el-table-column prop="typeName" label="类别名称" width="150"></el-table-column>
<el-table-column prop="typeIntro" label="备注"></el-table-column>
<el-table-column prop="typeName" label="类别名称"></el-table-column>
<el-table-column prop="operation" label="操作">
<template #default="scope">
<el-button type="success" @click="editShowForm(scope.$index, scope.row)">修改类别</el-button>
@ -64,6 +61,7 @@
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
@ -71,6 +69,7 @@ import {ElMessage, type UploadProps, type UploadUserFile,type UploadFile, genFil
import {ErrorInfo, SuccessInfo} from '@/utils/messageInfo';
import {onMounted, ref} from 'vue'
import myAxios from '@/api/myAxios';
import { downloadUrl } from '@/utils/formatImgUpload'
const fileSimple = ref() //
const selectedItems = ref([])
@ -84,7 +83,6 @@ const typeForm = ref({
id: 0,
typeName: '',
typeUrl: '',
typeIntro: ''
})
//
const tableData = ref([])
@ -133,8 +131,7 @@ const handleChange = async (file: any) => {
}
//
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
// typeForm.value.typeUrl = ''
// console.log(uploadFile, uploadFiles)
typeImg.value.splice(0, typeImg.value.length) //
submitable.value = true //
}
@ -176,8 +173,7 @@ const addOrUpdateType = async () => {
const res = await myAxios.post('/category/add', {
//
typeName: typeForm.value.typeName,
typeUrl: tempImgUrl.value,
typeIntro: typeForm.value.typeIntro
typeUrl: tempImgUrl.value
})
if (res.data.code === 1) {
//
@ -191,8 +187,7 @@ const addOrUpdateType = async () => {
const res = await myAxios.post('/category/update', {
id: typeForm.value.id,
typeName: typeForm.value.typeName,
typeUrl: tempImgUrl.value,
typeIntro: typeForm.value.typeIntro
typeUrl: tempImgUrl.value
})
if (res.data.code === 1) {
//
@ -211,8 +206,7 @@ const resetForm = () => {
typeForm.value = {
id: 0,
typeName: '',
typeUrl: '',
typeIntro: ''
typeUrl: ''
}
};
const handleSelectionChange = (row: any) => {
@ -223,7 +217,7 @@ const editShowForm = (index: number, row: any) => {
tempImgUrl.value = row.typeUrl //
typeImg.value.splice(0, typeImg.value.length) //
typeImg.value.push({
url: row.typeUrl
url: downloadUrl + row.typeUrl
})
dialogVisible.value = true
typeForm.value = JSON.parse(JSON.stringify(row))
@ -247,4 +241,9 @@ const changeInput = () => { //当输入栏变化时解除禁用提交按钮
}
</script>
<style scoped></style>
<style scoped>
.table_page {
min-width: 800px;
overflow: auto;
}
</style>

View File

@ -2,20 +2,13 @@
<div class="flexCard">
<el-card class="richTextPreview" shadow="never">
<div class="titleText">移动端预览</div>
<p v-html="form.richText"></p>
<p v-html="previewRichText"></p>
</el-card>
<!-- 表单 ref prop绑定 用于重置表单 -->
<el-card class="form-FormContainer" shadow="never">
<el-form ref="resetFormData" :model="form" label-width="auto" size="large">
<el-form-item label="添加写真展示图片">
<!-- 下面的event的作用,传入当前事件对象 -->
<el-upload ref="uploadProductImg" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 0)"
:on-exceed="Exceed_ProductImg" limit="1">
<el-icon>
<Plus />
</el-icon>
</el-upload>
<ImgSingleUpload @update:goodImgArr="form.goodImg = $event"/>
</el-form-item>
<el-form-item label="服装名称" prop="name" style="width: 300px;" label-width="70px">
<el-input v-model="form.name" />
@ -50,7 +43,7 @@
</el-form-item>
</div>
<el-form-item label="效果图" label-width="70px">
<richTextUtil @richTextContent="getInfo"/>
<richTextUtil @richTextContent="getRichTextInfo"/>
</el-form-item>
<div class="totalButton">
<el-form-item>
@ -63,21 +56,21 @@
</el-form>
</el-card>
<el-card class="form-RichTextContainer" shadow="never">
<outfitCalendarUtil @calendar-info="getInfo"></outfitCalendarUtil>
<outfitCalendarUtil @calendar-info="getDateInfo"></outfitCalendarUtil>
</el-card>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, inject, toRaw, effect } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { ref, onMounted, inject, toRaw } from 'vue';
import { ElMessage, type UploadProps, genFileId, type UploadRawFile } from 'element-plus';
import myAxios from "@/api/myAxios";
import outfitCalendarUtil from '@/layout/components/outfitCalendarUtil.vue';
import richTextUtil from '@/layout/components/richTextUtil.vue';
import ImgSingleUpload from '@/utils/imgUpload/ImgSingleUpload.vue'
const fileSimple = ref() //
const resetFormData = ref()
const form = ref({
name: '', //
@ -92,11 +85,13 @@ const form = ref({
})
//
const reload: any = inject("reload")
const uploadProductImg: any = ref() //ref
const typeList = ref<String[]>([]) //
const siteList = ref<String[]>(['室外','室内','均可']) //
const minArr = ref<Number[]>([]) //
const maxArr= ref<Number[]>([]) //
const previewRichText = ref('') //
onMounted(() => {
getOutfitKind() //
for(let i = 0;i <=50 ; i++) { //
@ -104,9 +99,7 @@ onMounted(() => {
maxArr.value[i] = 2+i
}
})
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
}
//
const loadCategory = (value: any) => {
form.value.categoryName = value // flag=1 "" flag=0
@ -117,10 +110,11 @@ const loadScene = (value: any) => {
}
//
const onSubmit = async () => {
console.log('提交前的表单---->',form.value)
const values : any = Object.values(form.value);
// 使some()
console.log(form.value.bookingDateAddRequestList)
if (values.some((value:any) => value === null || value === undefined || value === '') || form.value.bookingDateAddRequestList.length == 0) {
if (values.some((value:any) => value === null || value === undefined || value === '' || value === 'PHA+PGJyPjwvcD4=') || form.value.bookingDateAddRequestList.length == 0) {
ElMessage({
type: 'warning',
message: '请检查表单数据是否完整填写'
@ -136,6 +130,7 @@ const onSubmit = async () => {
shotScene: form.value.shotScene,
categoryName: form.value.categoryName,
introImg: form.value.goodImg,
richText: form.value.richText,
bookingDateAddRequestList: toRaw(form.value.bookingDateAddRequestList)
})
console.log(res.data);
@ -150,44 +145,26 @@ const onSubmit = async () => {
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/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
// formDatafile
file: formData.get("file")
}
})
if (res.data.code === 1) {
form.value.goodImg =res.data.data
// flag0 flag1
// flag ? form.value.detailImg = res.data.data : form.value.goodImg = res.data.data
}
}
//
const resetForm = () => {
resetFormData.value.resetFields()
}
const Exceed_ProductImg: UploadProps['onExceed'] = (files) => { //
uploadProductImg.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
uploadProductImg.value!.handleStart(file)
const getRichTextInfo =(info:any)=>{ //
// console.log('info-->',info);
form.value.richText = encode64(info)
previewRichText.value = info
}
const getInfo =(info:any)=>{
console.log('info-->',info);
// timeInfo.value = info
form.value.richText = info
//base64
function encode64(text: string): string {
return btoa(String.fromCharCode(...new TextEncoder().encode(text)))
}
const getDateInfo = ( info:any )=>{ //
console.log('info---->',info)
form.value.bookingDateAddRequestList = info
}
const getOutfitKind = async ()=> { //
@ -218,6 +195,12 @@ const maxNum =()=>{
}
}
const getInfo = (info: any) => { //
// console.log('info', info)
previewRichText.value = info
form.value.richText = info
}
</script>
<style scoped>
@ -257,4 +240,9 @@ const maxNum =()=>{
.numberSelect {
display: flex;
}
.titleText {
text-align: center;
margin: 0 auto;
}
</style>

View File

@ -66,7 +66,7 @@
<el-table-column prop="goodImg" label="服装图片">
<template #default="scope">
<div>
<img :src="scope.row.introImg" alt="" style="height: 50px;">
<img :src="downloadUrl + scope.row.introImg" alt="" style="height: 50px;">
</div>
</template>
</el-table-column>
@ -117,10 +117,10 @@
</el-table-column>
<el-table-column label="操作" width="250px">
<template #default="scope">
<el-button size="small" @click="ReviseOrView(scope.$index, scope.row , 0)">
<el-button size="small" @click="ReviseOrView( scope.row , 0)">
详情
</el-button>
<el-button size="small" @click="ReviseOrView(scope.$index, scope.row, 1)">
<el-button size="small" @click="ReviseOrView(scope.row, 1)">
编辑
</el-button>
<el-button size="small" @click="handleOff(scope.row)">
@ -143,71 +143,6 @@
:small="null" :disabled="null" :background="null" layout="total, sizes, prev, pager, next, jumper"
:total="total" />
</div>
<!-- 编辑/详情表单 -->
<el-dialog v-model="DialogVisible" :title="title">
<el-form label-width="100px" :disabled="disabled">
<el-form-item label="服装编号">
<el-input v-model="editForm.id" disabled></el-input>
</el-form-item>
<el-form-item label="服装图片">
<div v-if="editForm.introImg">
<img :src="editForm.introImg" alt="服装图标" class="thumbnail" style="width: 100px; height: 100px;" />
</div>
<el-upload ref="uploadProductImg" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 0)" :on-exceed="Exceed_ProductImg"
limit="1">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item label="服装名称">
<el-input v-model="editForm.name"></el-input>
</el-form-item>
<el-form-item label="单次价格" prop="price">
<el-input-number v-model="editForm.price" min="0" :precision="2" :step="0.5" />
<p></p>
</el-form-item>
<el-form-item label="服装类别" prop="type" style="width: 240px;">
<el-select v-model="editForm.categoryName" placeholder="请选择" @change="(event: any) => loadCategory(event)">
<el-option v-for="item in typeList" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="拍摄场地" prop="type" style="width: 240px;">
<el-select v-model="editForm.shotScene" placeholder="请选择" @change="(event: any) => loadScene(event)">
<el-option v-for="item in siteList" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="最小人数" prop="type">
<el-select v-model="editForm.minNumber" style="width: 120px;" @change="minNum()">
<el-option v-for="item in minArr" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="最大人数" prop="type">
<el-select v-model="editForm.maxNumber" style="width: 120px;" @change="maxNum()">
<el-option v-for="item in maxArr" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="详情图">
<div v-if="editForm.detailImg">
<img :src="editForm.detailImg" alt="商品图标" class="thumbnail" style="width: 100px; height: 100px;" />
</div>
<el-upload ref="uploadProductDetail" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 1)" :on-exceed="Exceed_ProductDetail"
limit="1">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="DialogVisible = false" :disabled="disabled">取消</el-button>
<el-button type="primary" @click="saveEdit" :disabled="disabled">确认</el-button>
</span>
</template>
</el-dialog>
<!-- 时间段抽屉 -->
<el-drawer v-model="drawer" :title="'当前日期:'+drawerDate.specificDate + '&emsp;服装名称:' + outfitName" direction="ltr"
@closed="closedDrawer">
@ -249,13 +184,14 @@
</template>
<script setup lang="ts">
import { ElMessage , type UploadProps , genFileId ,type UploadRawFile } from 'element-plus';
import {ref, onMounted, inject, toRaw} from 'vue';
import { ElMessage } from 'element-plus';
import {ref, onMounted, inject} from 'vue';
import myAxios from "@/api/myAxios";
import outfitCalendarUtil from '@/layout/components/outfitCalendarUtil.vue';
import emitter from "@/utils/emitter";
import { useRouter } from "vue-router";
import {WarnInfo} from "@/utils/messageInfo";
import { downloadUrl } from '@/utils/formatImgUpload'
const router = useRouter(); //
const total = ref(0); //
@ -268,16 +204,9 @@ const searchParams: any = ref({ //封装分页
})
const tableData : any= ref([]);
const appointmentDateArr : any = ref([])
const disabled = ref(true)
const title = ref('') //
const productName = ref('');
const DialogVisible = ref(false);
const state = ref(''); //select
const editForm : any = ref({});
const reload : any = inject("reload") //
const fileSimple = ref()
const uploadProductImg : any = ref() //ref
const uploadProductDetail : any = ref() //ref
//
const drawer = ref(false) //
const drawerDate : any = ref({}) //
@ -292,7 +221,6 @@ const timeAbleArr = ref( //禁用时间段组件
const outfitName = ref('') //
const addDateVisible = ref(false) //
const typeList = ref<String[]>([]) //
const siteList = ref<String[]>(['室外','室内','均可']) //
onMounted(async () => { //
getOutfitList()
@ -338,34 +266,7 @@ const getOutfitList = async () => {
});
}
}
const saveEdit = async () => { //
console.log('写真信息--->',editForm.value)
const values : any = Object.values(editForm.value);
// 使some()
console.log(editForm.value.bookingDateAddRequestList)
if (values.some((value:any) => value === null || value === undefined || value === '' || value === 0) ) {
ElMessage({
type: 'warning',
message: '请检查表单数据是否完整填写'
})
return; //
}
const res = await myAxios.post('/photoProducts/update',{...editForm.value})
if(res.data.code === 1) {
DialogVisible.value = false
ElMessage({
type: 'success',
message: '更新成功'
})
await getOutfitList()
} else {
ElMessage({
type: 'error',
message: '请检查字段是否正确填写'
})
}
console.log('服装信息更新结果--->',res.data);
}
const searchByState = (event : any) => { ///
searchParams.value.isShelves = event
searchParams.value.current = 1
@ -381,25 +282,20 @@ const deleteProduct = async (index: number) => {
type: 'success',
message: '删除成功',
})
getOutfitList()
await getOutfitList()
await getAllPhotoProducts()
await getSpecialProducts()
}
}
//
const ReviseOrView = (index: number, row: any , flag : number) => {
// router.push({
// name: '',
// params: {
// id: row.id,
// flag: flag
// }
// })
//flag disabled
flag ? (title.value = "编辑服装" , disabled.value = false) : (title.value = "服装详情" , disabled.value = true)
DialogVisible.value = true;
editForm.value = JSON.parse(JSON.stringify(row));
// console.log('--->',editForm.value);
const ReviseOrView = (row: any , flag : number) => {
router.push({
name: '服装详情',
params: {
id: row.id,
flag: flag
}
})
};
const getOutfitKind = async ()=> { //
const res = await myAxios.post('/photoCategory/list',{})
@ -407,14 +303,7 @@ const getOutfitKind = async ()=> { //获取服装类别
typeList.value.push(res.data.data[key].name)
}
}
//
const loadCategory = (value: any) => {
editForm.value.categoryName = value // flag=1 "" flag=0
}
//
const loadScene = (value: any) => {
editForm.value.shotScene = value // flag=1 "" flag=0
}
//()
const handleOff = async (row: any) => {
console.log(row.isShelves);
@ -443,43 +332,7 @@ 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
file.uid = genFileId()
uploadProductDetail.value!.handleStart(file)
}
//
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/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
file: formData.get("file") // formDatafile
}
})
if (res.data.code === 1) {
// flag0 flag1
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
@ -660,26 +513,6 @@ const submitDate = async ()=> { //提交日期方法
appointmentDateAddRequestList.value = []
emitter.emit('clear')
}
const minNum =()=>{ //
if(editForm.value.minNumber > editForm.value.maxNumber && editForm.value.maxNumber != 0) {
ElMessage({
type: 'warning',
message: '最小人数不能大于最大人数'
})
editForm.value.minNumber = 0
return;
}
}
const maxNum =()=>{
if(editForm.value.maxNumber < editForm.value.minNumber) {
ElMessage({
type: 'warning',
message: '最大人数不能小于最小人数'
})
editForm.value.maxNumber = 0
return;
}
}
const typeSelect : any = ref(true) //

View File

@ -1,221 +1,221 @@
<template>
<div class="flexCard">
<div class="flexCard" >
<el-card class="richTextPreview" shadow="never">
<div class="titleText">移动端预览</div>
<p v-html="detailFrom.richText"></p>
<p v-html="previewRichText"></p>
</el-card>
<!-- 表单 ref prop绑定 用于重置表单 -->
<el-card class="form-container" shadow="never">
<div class="form">
<el-form ref="resetFormData" :model="detailFrom" label-width="auto" size="large" :rules="rules" :disabled="true">
<div>
<el-form-item label="添加商品图片">
<!-- 下面的event的作用,传入当前事件对象 -->
<el-upload v-model:file-list="ImgArr" ref="uploadProductImg" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 2)" :on-exceed="Exceed_ProductImg"
limit="7">
<el-icon>
<Plus />
</el-icon>
</el-upload>
<el-card class="form-FormContainer" shadow="never" >
<el-form ref="resetFormData" :model="form" label-width="auto" size="large" :disabled="disabledRichText">
<el-form-item label="添加写真展示图片">
<PreviewSingleImgUpload :ImgUrlList="form.introImg" @update:goodImgArr="form.introImg = $event"/>
</el-form-item>
</div>
<div class="NamePrice">
<el-form-item label="产品名称" prop="name">
<el-input v-model="detailFrom.name" maxlength="12" minlength="2" show-word-limit style="width: 260px;" />
<el-form-item label="服装名称" prop="name" style="width: 300px;" label-width="70px">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="产品价格" prop="price">
<el-input-number v-model="detailFrom.price" min="0" :precision="2" :step="0.5" />
<el-form-item label="价格" prop="price" label-width="70px">
<el-input-number v-model="form.price" min="0" :precision="2" :step="0.5" />
<p></p>
</el-form-item>
</div>
<div class="IntroInven">
<el-form-item label="产品简介" prop="intro">
<el-input v-model="detailFrom.intro" type="textarea" placeholder="产品尺寸,服务等" maxlength="30" show-word-limit
style="width: 300px;" />
<!-- 拍摄场地户外室内均可 -->
<div class="kinds">
<el-form-item label="拍摄场地" prop="type" style="width: 240px;" label-width="70px">
<el-select v-model="form.shotScene" placeholder="请选择" @change="(event: any) => loadScene(event)" >
<el-option v-for="item in siteList" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<div>
<el-form-item label="库存" prop="inventory">
<el-input-number v-model="detailFrom.inventory" min="0" :precision="0" :step="1" :disabled="invInput" />
</el-form-item>
</div>
</div>
<div class="festivalBox">
<el-form-item label="节日名称" prop="festivalName" style="width: 300px;">
<el-input v-model="detailFrom.festivalName" />
</el-form-item>
<el-form-item label="产品类别" prop="type" style="width: 240px;">
<el-select v-model="detailFrom.type" placeholder="请选择" @change="(event: any) => loadForm(event)" :disabled="typeSelect">
<el-form-item label="服装类别" prop="type" style="width: 240px;" label-width="80px">
<el-select v-model="form.categoryName" placeholder="请选择" @change="(event: any) => loadCategory(event)" >
<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">
<el-input v-model="labelList[index]" type="text" style="width: 150px;" maxlength="5" show-word-limit
@blur="addLabelList" />
</div>
<el-button type="primary" @click="addLabel">添加</el-button>
<div class="numberSelect">
<el-form-item label="最小人数" prop="type" style="width: 240px;" label-width="70px">
<el-select v-model="form.minNumber" @change="minNum()">
<el-option v-for="item in minArr" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="商品图文" prop="richText">
<richTextUtil @richTextContent="getInfo" v-model:disable="disabledRichText"/>
<el-form-item label="最大人数" prop="type" style="width: 240px;" label-width="80px">
<el-select v-model="form.maxNumber" @change="maxNum()">
<el-option v-for="item in maxArr" :label="item" :value="item" />
</el-select>
</el-form-item>
<div class="btnBox">
</div>
<el-form-item label="效果图" label-width="70px" v-loading="loading">
<richTextUtil @richTextContent="getInfo" v-model:disableRich="disabledRichText" v-model:context="previewRichText"/>
</el-form-item>
<div class="totalButton">
<el-form-item>
<el-button type="primary" @click="onSubmit" :disabled="saveBtn">更新</el-button>
<el-button type="primary" @click="onSubmit">保存</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetForm">重置</el-button>
</el-form-item>
</div>
</el-form>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, inject, reactive, onBeforeMount } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import {type FormRules, type UploadUserFile} from 'element-plus';
import { SuccessInfo, WarnInfo, CommInfo } from '@/utils/messageInfo'; //ElMessage
<script setup lang="ts">
import { ref, onMounted, onBeforeMount } from 'vue';
import { ElMessage } from 'element-plus';
import myAxios from "@/api/myAxios";
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';
import richTextUtil from '@/layout/components/richTextUtil.vue';
import { useRoute } from "vue-router";
import PreviewSingleImgUpload from "@/utils/imgUpload/PreviewSingleImgUpload.vue";
import {useRoute, useRouter} from "vue-router";
const route = useRoute(); //
const resetFormData = ref()
const reload: any = inject("reload") //
const typeList: any = ref([])
const uploadProductImg: any = ref() //ref
const labelList = ref([''])
const isqualify : any = ref(false)
const typeSelect : any = ref(false) //
const ImgArr: any = ref<UploadUserFile[]>([])
const detailFrom : any = ref({
name: '', //
price: '', //
intro: '',//
categoryName: '', //
goodImg: '', //url
minNumber: 0,
maxNumber: 0,
richText: '',
shotScene: '' //
})
const disabledRichText:any = ref(false);
const form : any = ref({})
//
const typeList = ref<String[]>([]) //
const siteList = ref<String[]>(['室外','室内','均可']) //
const minArr = ref<Number[]>([]) //
const maxArr= ref<Number[]>([]) //
const previewRichText = ref('') //
const disabledRichText = ref(false)
const route = useRoute(); //
const router = useRouter()
const loading = ref(true)
onBeforeMount(()=>{ //
if(route.params.flag === '0'){
disabledRichText.value = true;
onBeforeMount(()=>{
if(route.params.flag === '0') {
disabledRichText.value = true
}
getOutfitInfo()
})
onMounted(() => {
getTypeList() //select
getProductInfo() //
// console.log('id---->',route.params.id)
// console.log('flag---->',typeof (route.params.flag))
getOutfitKind() //
for(let i = 0;i <=50 ; i++) { //
minArr.value[i] = 1+i
maxArr.value[i] = 2+i
}
setTimeout(()=>{
loading.value = false
},1500)
})
const getProductInfo = async () => {
const res = await myAxios.post('/goods/getById',{ id: route.params.id })
console.log('后端查询商品--->',res.data.data)
const getOutfitInfo = async () => {
const res = await myAxios.post('/photoProducts/list/main/id',{ id: route.params.id })
console.log('后端返回的数据---->',res.data)
if(res.data.code === 1) {
detailFrom.value = res.data.data
ImgArr.value.splice(0, ImgArr.value.length)
labelList.value = res.data.data.label.split(';')
var tempArr = res.data.data.goodImg.split(';')
tempArr.forEach((item: any) => {
ImgArr.value.push({
url: item
})
})
form.value = res.data.data
previewRichText.value = res.data.data.richText
}
}
const getTypeList = async () => { //
const res = await myAxios.post('/category/list/web', {}) //
for(let key in res.data.data) {
typeList.value.push(res.data.data[key].typeName)
}
//
const loadCategory = (value: any) => {
form.value.categoryName = value // flag=1 "" flag=0
}
//
const loadScene = (value: any) => {
form.value.shotScene = value // flag=1 "" flag=0
}
//
const onSubmit = async () => {
const values = Object.values(detailFrom.value );
console.log('提交前的表单---->',form.value)
const values : any = Object.values(form.value);
// 使some()
if (values.some((value: any) => value === null || value === undefined || value === '' || value === 0)) {
WarnInfo('请检查表单数据是否完整填写')
if (values.some((value:any) => value === null || value === undefined || value === '' || value === 'PHA+PGJyPjwvcD4=' || value === 0)) {
ElMessage({
type: 'warning',
message: '请检查表单数据是否完整填写'
})
return; //
}
const res = await myAxios.post('/goods/add', { ...detailFrom.value })
// console.log(form.value);
const res = await myAxios.post('/photoProducts/update', {
id: form.value.id,
name: form.value.name,
price: form.value.price,
minNumber: form.value.minNumber,
maxNumber: form.value.maxNumber,
shotScene: form.value.shotScene,
categoryName: form.value.categoryName,
introImg: form.value.introImg,
richText: form.value.richText
})
// console.log(res.data);
if (res.data.code === 1) {
SuccessInfo('提交成功')
detailFrom.value = {} //12.18
reload() //
ElMessage({
type: 'success',
message: "提交成功"
})
router.replace('/OutfitManagementCenter')
} else {
WarnInfo('服务错误')
ElMessage.error("服务错误")
return;
}
}
//
const loadForm = (value: any) => {
detailFrom.value.type = value // flag=1 "" flag=0
}
//
const resetForm = () => {
resetFormData.value.resetFields()
}
const rules = reactive<FormRules<typeof form>>({ //
name: [{ validator: validateName, trigger: 'blur' }],
intro: [{ validator: validateIntro, trigger: 'blur' }],
introDetail: [{ validator: validateDetail, trigger: 'blur' }]
})
const addLabel = () => { //
if (labelList.value[labelList.value.length - 1] === '') {
WarnInfo('请填写完')
return;
}
if (labelList.value.length < 4) {
labelList.value.push('')
const getOutfitKind = async ()=> { //
const res = await myAxios.post('/photoCategory/list',{})
for(let key in res.data.data) {
typeList.value.push(res.data.data[key].name)
}
}
const addLabelList = () => { //
var string = ''
if (!labelList.value.some((item: any) => item === '')) {
string = labelList.value.join(';')
} else return;
detailFrom.value.label = string
}
const customTag = (e:any)=>{ //
if(e) {
detailFrom.value.inventory = 1
invInput.value = true
typeSelect.value = true
detailFrom.value.type = '定制'
} else {
detailFrom.value.inventory = 0
invInput.value = false
typeSelect.value = false
detailFrom.value.type = ''
const minNum =()=>{ //
if(form.value.minNumber > form.value.maxNumber && form.value.maxNumber != 0) {
ElMessage({
type: 'warning',
message: '最小人数不能大于最大人数'
})
form.value.minNumber = 0
return;
}
}
const maxNum =()=>{
if(form.value.maxNumber < form.value.minNumber) {
ElMessage({
type: 'warning',
message: '最大人数不能小于最小人数'
})
form.value.maxNumber = 0
return;
}
}
const getInfo = (info: any) => { //
console.log('info', info)
detailFrom.value.richText = info
previewRichText.value = info
form.value.richText = encode64(info)
}
//base64
function encode64(text: string): string {
return btoa(String.fromCharCode(...new TextEncoder().encode(text)))
}
</script>
<style scoped>
.form-FormContainer {
width: 600px;
height: 800px;
overflow: auto;
/* margin: 0 auto; */
}
.form-RichTextContainer {
width: 550px;
}
.flexCard {
display: flex;
height: 100%;
@ -229,29 +229,22 @@ const getInfo = (info: any) => { //富文本赋值
margin-right: 10px;
}
.form-container {
width: 700px;
/* margin: 0 auto; */
.kinds {
display: flex;
}
.form {
/* width: 500px; */
.totalButton {
display: flex;
justify-content: space-evenly;
/* 盒子里面水平分隔开 */
}
.numberSelect {
display: flex;
}
.titleText {
text-align: center;
margin: 0 auto;
}
.NamePrice {
display: flex;
}
.IntroInven {
display: flex;
}
.festivalBox {
display: flex;
}
.btnBox {
display: flex;
justify-content: space-around;
}
</style>

View File

@ -75,7 +75,7 @@
<el-col :span="6" class="table-cell-title">服装价格</el-col>
</el-row>
<el-row>
<el-col :span="6" class="table-cell-product"><img :src="photoProductsSnapshot.introImg"
<el-col :span="6" class="table-cell-product"><img :src="downloadUrl + photoProductsSnapshot.introImg"
style="height: 70px; width: 70px;" alt=""></el-col>
<el-col :span="6" class="table-cell-product">{{ photoProductsSnapshot.name }}</el-col>
<el-col :span="6" class="table-cell-product">{{ photoProductsSnapshot.categoryName }}</el-col>
@ -94,6 +94,7 @@ import { onMounted, ref } from "vue";
import myAxios from "@/api/myAxios";
import { SuccessInfo, ErrorInfo } from "@/utils/messageInfo";
import { useRoute } from "vue-router";
import { downloadUrl } from '@/utils/formatImgUpload'
const route = useRoute();
const orderObj: any = ref({}) //

View File

@ -40,7 +40,7 @@
<script lang="ts" setup>
import { ref,onMounted} from 'vue'
import {ElMessage, type UploadProps} from "element-plus";
import {ElMessage} from "element-plus";
import myAxios from "@/api/myAxios";

View File

@ -23,7 +23,7 @@
:header-cell-style="{ 'text-align': 'center' }">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="name" label="优惠券名称"></el-table-column>
<el-table-column prop="content" label="简介"></el-table-column>
<!-- <el-table-column prop="content" label="简介"></el-table-column>-->
<el-table-column prop="standardAmount" label="满减价格"></el-table-column>
<el-table-column prop="conditionAmount" label="优惠价格"></el-table-column>
<el-table-column prop="requirePoints" label="兑换积分"></el-table-column>
@ -110,7 +110,7 @@
<script lang="ts" setup>
import {inject, onMounted, ref} from "vue";
import myAxios from "@/api/myAxios";
import {ElMessage, type UploadProps} from "element-plus";
import {ElMessage} from "element-plus";
onMounted(() => {
getCouponsList()

View File

@ -138,6 +138,7 @@ const getDashBoard = async () => {
margin-top: 40px;
margin-left: 120px;
margin-right: 120px;
min-width: 800px;
}
.total-layout {

View File

@ -1,4 +1,5 @@
<template>
<div class="table_page">
<div style="margin-bottom: 20px">
<el-input style="width: 250px; height: 30px; margin-right: 10px; font-size: 14px" suffix-icon="Search"
placeholder="请输入订单编号" v-model="orderNumber"></el-input>
@ -27,7 +28,7 @@
<el-table-column label="商品图片" prop="goodSnapshot.goodImg" width="200">
<template #default="scope">
<div>
<img :src="scope.row.goodSnapshot.goodImg.split(';')[0]" alt="" style="height: 50px;">
<img :src=" downloadUrl + scope.row.goodSnapshot.goodImg.split(';')[0]" alt="" style="height: 50px;">
</div>
</template>
</el-table-column>
@ -49,7 +50,6 @@
<!-- <el-table-column label="优惠券信息" width="50">-->
<!-- <el-table-column prop="couponSnapshot.name" label="优惠卷名称" />-->
<el-table-column prop="couponSnapshot.conditionAmount" label="优惠金额" />
<!-- </el-table-column>-->
<el-table-column prop="totalAmount" label="订单实付金额"></el-table-column>
<el-table-column prop="orderStatus" label="订单状态"></el-table-column>
<el-table-column prop="trackingNumber" label="快递单号"></el-table-column>
@ -82,6 +82,7 @@
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页器 -->
<div style="padding: 10px 0">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
@ -175,6 +176,7 @@ import { onMounted, ref } from "vue";
import myAxios from "@/api/myAxios";
import { ElMessage } from "element-plus";
import {SuccessInfo, ErrorInfo, WarnInfo} from "@/utils/messageInfo";
import { downloadUrl } from '@/utils/formatImgUpload'
const tableData: any = ref([]); //
const total = ref(0);
const title = ref('')
@ -300,10 +302,13 @@ const cancelOrder = async (row: any) => { //取消订单的方法(未支付能
const successfulTransaction = async (oid: any) => {
// console.log('---->',oid)
// loading.value = true
const res = await myAxios.post('',{})
const res = await myAxios.post('/order/update/all/orderStatus',{
id: oid,
orderStatus: '交易完成'
})
if (res.data.code === 1) {
SuccessInfo('订单完成')
getOrderList()
await getOrderList()
loading.value = false
} else {
WarnInfo('更新失败')
@ -325,4 +330,8 @@ const successfulTransaction = async (oid: any) => {
font-family: 'Arial', sans-serif;
/* 设置字体 */
}
.table_page {
min-width: 1000px;
overflow: auto;
}
</style>

View File

@ -1,4 +1,5 @@
<template>
<div class="table_page">
<div style="margin-bottom: 20px;">
<div style="display: flex; justify-content: space-around; align-items: center">
<div>
@ -34,7 +35,7 @@
<el-table-column prop="goodImg" label="商品图片" width="100">
<template #default="scope">
<div>
<img :src="scope.row.goodImg.split(';')[0]" alt="" style="height: 50px;">
<img :src=" downloadUrl + scope.row.goodImg.split(';')[0]" alt="" style="height: 50px;">
</div>
</template>
</el-table-column>
@ -78,8 +79,8 @@
</template>
</el-table-column>
</el-table-column>
</el-table>
</div>
<!-- 分页器 -->
<div style="padding: 10px 0">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
@ -111,11 +112,9 @@
<el-form-item label="预估支付金额" style="width: 250px">
<el-input v-model="editForm.itemTotalAmount" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="订单明细状态" style="width: 250px">
<el-input v-model="editForm.orderItemStatus" autocomplete="off"></el-input>
</el-form-item>
<!-- <div style="display: flex">-->
<!-- <el-form-item label="下单时间" style="width: 300px;">-->
<!-- <el-input v-model="editForm.createTime" autocomplete="off"></el-input>-->
@ -156,7 +155,8 @@ import { SuccessInfo, ErrorInfo } from "@/utils/messageInfo";
import DatePicker from "@/layout/components/DatePicker.vue";
import TimePicker from "@/layout/components/TimePicker.vue";
import emitter from "@/utils/emitter";
import { checkObjectProperties } from "@/layout/js/validUtils";
import { downloadUrl } from '@/utils/formatImgUpload'
const tableData: any = ref([]); //
const totalPage = ref(0);
const title = ref('')
@ -323,4 +323,8 @@ const cancelOrder = async (row: any) => { //取消订单的方法(未支付能
/* 设置字体 */
}
.table_page {
min-width: 1000px;
overflow: auto;
}
</style>

View File

@ -1,4 +1,5 @@
<template>
<div class="table_page">
<div style="margin-bottom: 20px">
<el-input style="width: 250px; height: 30px; margin-right: 10px; font-size: 14px" suffix-icon="Search" placeholder="请输入订单编号"
v-model="orderNumber"></el-input>
@ -26,7 +27,7 @@
<el-table-column label="商品图片" prop="goodSnapshot.goodImg" width="200">
<template #default="scope">
<div>
<img :src="scope.row.goodSnapshot.goodImg.split(';')[0]" alt="" style="height: 50px;">
<img :src="downloadUrl + scope.row.goodSnapshot.goodImg.split(';')[0]" alt="" style="height: 50px;">
</div>
</template>
</el-table-column>
@ -77,6 +78,7 @@
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页器 -->
<div style="padding: 10px 0">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
@ -91,7 +93,8 @@ import { onMounted, ref } from "vue";
import myAxios from "@/api/myAxios";
import { ElMessage } from "element-plus";
import {SuccessInfo, ErrorInfo, WarnInfo} from "@/utils/messageInfo";
import emitter from "@/utils/emitter";
import { downloadUrl } from '@/utils/formatImgUpload'
const tableData: any = ref([]); //
const total = ref(0);
const orderNumber = ref('')
@ -191,4 +194,8 @@ const successfulTransaction = async (oid: any) => { //订单完成方法
font-weight: bold; /* 设置字体加粗 */
font-family: 'Arial', sans-serif; /* 设置字体 */
}
.table_page {
min-width: 1000px;
overflow: auto;
}
</style>

View File

@ -1,11 +1,7 @@
<template>
<div>
<div style="margin: 10px 0">
<el-input style="width: 200px; height: 30px; margin-right: 10px;" suffix-icon="Search" placeholder="请输入图片名称" v-model="simpleList.name"></el-input>
<el-button class="ml-5" type="primary" @click="onSearch" style="height: 25px;">搜索</el-button>
<el-button type="warning" @click="reset" style="height:25px">重置</el-button>
</div>
<div style="margin: 15px 0">
<div class="table_page">
<div style="margin-bottom: 15px">
<el-button type="primary" slot="reference" @click="addCarouse">添加图片</el-button>
<el-popconfirm
confirm-button-text='确定'
cancel-button-text='取消'
@ -16,19 +12,17 @@
width=180
>
<template #reference>
<el-button style="height: 25px" type="danger" slot="reference">批量删除 <el-icon style="margin-left: 5px;"><Remove /></el-icon></el-button>
<el-button type="danger" slot="reference">批量删除 <el-icon style="margin-left: 5px;"><Remove /></el-icon></el-button>
</template>
</el-popconfirm>
</div>
<el-table :data="simpleList" border stripe header-cell-class-name="headerBg" :cell-style="{textAlign: 'center'}"
<el-table :data="tableData" border stripe header-cell-class-name="headerBg" :cell-style="{textAlign: 'center'}"
@selection-change="handleSelectionChange" :header-cell-style="{'text-align': 'center'}">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="id" label="图片序号" width="50"></el-table-column>
<el-table-column prop="imgUrl" label="图片">
<template #default="scope"><img :src="scope.row.imgUrl" alt="" style="height: 50px;"></template>
<el-table-column prop="url" label="图片">
<template #default="scope"><img :src="downloadUrl + scope.row.url" alt="" style="height: 50px;"></template>
</el-table-column>
<el-table-column prop="name" label="商品图片" ></el-table-column>
<el-table-column prop="tips" label="对应商品"></el-table-column>
<el-table-column label="操作">
<template #default="scope">
<el-button type="success" @click="editCarouse(scope.row)">编辑<i class="el-icon-edit"></i></el-button>
@ -38,7 +32,7 @@
icon="el-icon-info"
icon-color="red"
title="您确定删除吗?"
@confirm="deleteCarouse"
@confirm="deleteCarouse(scope.row.id)"
>
<template #reference>
<el-button type="danger">删除</el-button>
@ -47,6 +41,7 @@
</template>
</el-table-column>
</el-table>
</div>
<div style="padding: 10px 0">
<!-- 分页器 -->
<el-pagination
@ -61,10 +56,9 @@
:total="total"
/>
</div>
</div>
<!-- 编辑/详情表单 -->
<el-dialog v-model="DialogVisible" title="轮播图编辑">
<el-form label-width="100px" :disabled="disabled">
<el-dialog v-model="DialogVisible" :title="title" >
<el-form label-width="100px" :disabled="disabled" v-loading="loading">
<el-form-item label="轮播图">
<el-upload
v-model:file-list="carouseImg"
@ -82,51 +76,29 @@
</el-icon>
</el-upload>
</el-form-item>
<el-form-item label="图片名称">
<el-input v-model="editForm.productImg" style="width: 200px;"></el-input>
</el-form-item>
<el-form-item label="对应商品" prop="price">
<el-select v-model="editForm.prdouctName" @change="(event: any) => loadForm(event)" style="width: 120px;">
<el-option v-for="item in goodList" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
</el-form>
<template #footer >
<span class="dialog-footer">
<el-button @click="DialogVisible = false" :disabled="disabled">取消</el-button>
<el-button type="primary" @click="saveEdit" :disabled="disabled">确认</el-button>
<el-button @click="restForm" :disabled="loading">取消</el-button>
<el-button type="primary" @click="saveEdit" :disabled="loading">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { type UploadProps , type UploadUserFile , genFileId ,type UploadRawFile } from 'element-plus';
import { type UploadProps } from 'element-plus';
import myAxios from '@/api/myAxios';
import {ref, onMounted , inject} from 'vue'
import { WarnInfo, SuccessInfo , ErrorInfo, CommInfo } from '@/utils/messageInfo';
const simpleList : any = ref([
{
id: '1', //id
name: '样例1', //
imgUrl: 'https://carbon2.obs.cn-north-4.myhuaweicloud.com:443/feiyi%2Ftest%2F0%2FgGwBQzmm-cxz.png', //
grade: '等级1', //
correspondingGoods: '非遗发簪' //
},
{
id: '2', //id
name: '样例2', //
imgUrl: 'https://carbon2.obs.cn-north-4.myhuaweicloud.com:443/feiyi%2Ftest%2F0%2FgGwBQzmm-cxz.png', //
grade: '等级2', //
correspondingGoods: '非遗螺钿' //
}
])
const goodList = ref([]) //
import {ref, onMounted, inject } from 'vue'
import { WarnInfo, SuccessInfo } from '@/utils/messageInfo';
import { downloadUrl } from '@/utils/formatImgUpload'
const DialogVisible = ref(false); //
const disabled = ref(false)
const editForm : any= ref({})
const uploadImg : any = ref() //ref
const carouseImg: any = ref<UploadUserFile[]>([]) //使
const carouseImg: any = ref([]) //使
const reload : any = inject("reload") //
const tableData = ref([]) //
const total = ref(0) //
const fileSimple = ref() //
@ -135,16 +107,31 @@ const searchParams: any = ref({
//
current: 1,
//
pageSize: 5
pageSize: 5,
//
type: '服务类'
})
//
const reload : any = inject("reload")
const title : any = ref('编辑表单')
const loading = ref(false)
onMounted(() => {
getCourseList()
})
//
const reset =()=>{
reload()
const getCourseList = async () => {
const res = await myAxios.post('/banner/query/web',{
current: searchParams.value.current,
pageSize: searchParams.value.pageSize,
type: searchParams.value.type
})
// console.log('---->',res.data)
if(res.data.code === 1) {
tableData.value = res.data.data.records
total.value = parseInt(res.data.data.total)
}
}
const handleSelectionChange = (val:any)=>{
console.log(val)
}
@ -158,57 +145,109 @@ const handleCurrentChange = (Current:any) => {
searchParams.value.current = Current //
//
};
//
const onSearch = (data : String)=>{
searchParams.value.name = data
searchParams.value.current = 1
//
const restForm =()=> {
DialogVisible.value = false
carouseImg.value.splice(0,1)
editForm.value.url = ''
}
const deleteCarouse = async (index: number,row: any) =>{ //
simpleList.value.splice(index,1)
const deleteCarouse = async (id: number) =>{ //
const res = await myAxios.post('/banner/delete',{ id: id })
if(res.data.code === 1) {
SuccessInfo('删除图片成功')
await getCourseList()
} else {
WarnInfo('服务错误')
}
}
const editCarouse = async (obj: any) =>{
title.value = '编辑轮播图'
carouseImg.value.splice(0,carouseImg.value.length)
carouseImg.value.push({ //
url: obj.imgUrl
url: downloadUrl + obj.url
})
editForm.value = obj
editForm.value = JSON.parse(JSON.stringify(obj))
DialogVisible.value = true
}
const saveEdit = ()=>{ //
const saveEdit = async ()=>{ //
if(editForm.value.url === '') {
WarnInfo('图片不能为空')
return
}
DialogVisible.value = false
if(editForm.value.id == undefined) {
const res = await myAxios.post('/banner/add',{
type: '服务类',
url: editForm.value.url
})
if(res.data.code === 1) {
DialogVisible.value = false
await getCourseList()
reload()
return
}
} else {
const res = await myAxios.post('/banner/update',{ ...editForm.value })
if(res.data.code === 1) {
DialogVisible.value = false
await getCourseList()
reload()
SuccessInfo('更新成功')
return
}
}
WarnInfo('服务错误')
}
const removePic : UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //uploadFileuploadFiles
carouseImg.value.splice(0,1)
editForm.value.url = ''
}
//
const loadForm = (value: any) => {
editForm.value.grade = value
}
const Exceed_ProductImg: UploadProps['onExceed'] = (files) => { // 'onExceed'
WarnInfo('请移除之前的再上传')
}
const handleChange = async (file: any ) => {
loading.value = true
fileSimple.value = file
let formData = new FormData() // FormData
formData.append("file", fileSimple.value.raw) //fileSimple.value.raw formData
// const res = await myAxios({ //
// url: '/file/uploadFile',
// method: 'post',
// headers: {
// 'content-Type': 'multipart/form-data'
// },
// data: {
// biz: "test",
// // formDatafile
// file: formData.get("file")
// }
// })
const res = await myAxios({ //
url: '/file/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
// formDatafile
file: formData.get("file")
}
})
if(res.data.code === 1) {
editForm.value.url = res.data.data
loading.value = false
SuccessInfo('图片上传成功')
}
}
//
const addCarouse = async () => {
restForm()
title.value = '添加轮播图'
DialogVisible.value = true
}
</script>
<style scoped>
.headerBg{
background-color: #eee !important;
.table_page {
min-width: 1000px;
overflow: auto;
}
</style>

View File

@ -1,11 +1,7 @@
<template>
<div>
<div style="margin: 10px 0">
<el-input style="width: 200px; height: 30px; margin-right: 10px;" suffix-icon="Search" placeholder="请输入图片名称" v-model="simpleList.name"></el-input>
<el-button class="ml-5" type="primary" @click="onSearch" style="height: 25px;">搜索</el-button>
<el-button type="warning" @click="reset" style="height:25px">重置</el-button>
</div>
<div style="margin: 15px 0">
<div class="table_page">
<div style="margin-bottom: 15px">
<el-button type="primary" slot="reference" @click="addCarouse">添加图片</el-button>
<el-popconfirm
confirm-button-text='确定'
cancel-button-text='取消'
@ -16,19 +12,17 @@
width=180
>
<template #reference>
<el-button style="height: 25px" type="danger" slot="reference">批量删除 <el-icon style="margin-left: 5px;"><Remove /></el-icon></el-button>
<el-button type="danger" slot="reference">批量删除 <el-icon style="margin-left: 5px;"><Remove /></el-icon></el-button>
</template>
</el-popconfirm>
</div>
<el-table :data="simpleList" border stripe header-cell-class-name="headerBg" :cell-style="{textAlign: 'center'}"
<el-table :data="tableData" border stripe header-cell-class-name="headerBg" :cell-style="{textAlign: 'center'}"
@selection-change="handleSelectionChange" :header-cell-style="{'text-align': 'center'}">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="id" label="图片序号" width="50"></el-table-column>
<el-table-column prop="imgUrl" label="图片">
<template #default="scope"><img :src="scope.row.imgUrl" alt="" style="height: 50px;"></template>
<el-table-column prop="url" label="图片">
<template #default="scope"><img :src="downloadUrl + scope.row.url" alt="" style="height: 50px;"></template>
</el-table-column>
<el-table-column prop="name" label="商品图片" ></el-table-column>
<el-table-column prop="tips" label="对应商品"></el-table-column>
<el-table-column label="操作">
<template #default="scope">
<el-button type="success" @click="editCarouse(scope.row)">编辑<i class="el-icon-edit"></i></el-button>
@ -38,7 +32,7 @@
icon="el-icon-info"
icon-color="red"
title="您确定删除吗?"
@confirm="deleteCarouse"
@confirm="deleteCarouse(scope.row.id)"
>
<template #reference>
<el-button type="danger">删除</el-button>
@ -63,8 +57,8 @@
</div>
</div>
<!-- 编辑/详情表单 -->
<el-dialog v-model="DialogVisible" title="轮播图编辑">
<el-form label-width="100px" :disabled="disabled">
<el-dialog v-model="DialogVisible" :title="title" >
<el-form label-width="100px" :disabled="disabled" v-loading="loading">
<el-form-item label="轮播图">
<el-upload
v-model:file-list="carouseImg"
@ -82,51 +76,29 @@
</el-icon>
</el-upload>
</el-form-item>
<el-form-item label="图片名称">
<el-input v-model="editForm.productImg" style="width: 200px;"></el-input>
</el-form-item>
<el-form-item label="对应商品" prop="price">
<el-select v-model="editForm.prdouctName" @change="(event: any) => loadForm(event)" style="width: 120px;">
<el-option v-for="item in goodList" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
</el-form>
<template #footer >
<span class="dialog-footer">
<el-button @click="DialogVisible = false" :disabled="disabled">取消</el-button>
<el-button type="primary" @click="saveEdit" :disabled="disabled">确认</el-button>
<el-button @click="restForm" :disabled="loading">取消</el-button>
<el-button type="primary" @click="saveEdit" :disabled="loading">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { type UploadProps , type UploadUserFile , genFileId ,type UploadRawFile } from 'element-plus';
import { type UploadProps } from 'element-plus';
import myAxios from '@/api/myAxios';
import {ref, onMounted , inject} from 'vue'
import { WarnInfo, SuccessInfo , ErrorInfo, CommInfo } from '@/utils/messageInfo';
const simpleList : any = ref([
{
id: '1', //id
name: '样例1', //
imgUrl: 'https://carbon2.obs.cn-north-4.myhuaweicloud.com:443/feiyi%2Ftest%2F0%2FgGwBQzmm-cxz.png', //
grade: '等级1', //
correspondingGoods: '非遗发簪' //
},
{
id: '2', //id
name: '样例2', //
imgUrl: 'https://carbon2.obs.cn-north-4.myhuaweicloud.com:443/feiyi%2Ftest%2F0%2FgGwBQzmm-cxz.png', //
grade: '等级2', //
correspondingGoods: '非遗螺钿' //
}
])
const goodList = ref([]) //
import {ref, onMounted, inject } from 'vue'
import { WarnInfo, SuccessInfo } from '@/utils/messageInfo';
import { downloadUrl } from '@/utils/formatImgUpload'
const DialogVisible = ref(false); //
const disabled = ref(false)
const editForm : any= ref({})
const uploadImg : any = ref() //ref
const carouseImg: any = ref<UploadUserFile[]>([]) //使
const carouseImg: any = ref([]) //使
const reload : any = inject("reload") //
const tableData = ref([]) //
const total = ref(0) //
const fileSimple = ref() //
@ -135,16 +107,31 @@ const searchParams: any = ref({
//
current: 1,
//
pageSize: 5
pageSize: 5,
//
type: '实体类'
})
//
const reload : any = inject("reload")
const title : any = ref('编辑表单')
const loading = ref(false)
onMounted(() => {
getCourseList()
})
//
const reset =()=>{
reload()
const getCourseList = async () => {
const res = await myAxios.post('/banner/query/web',{
current: searchParams.value.current,
pageSize: searchParams.value.pageSize,
type: searchParams.value.type
})
console.log('分页后端返回---->',res.data)
if(res.data.code === 1) {
tableData.value = res.data.data.records
total.value = parseInt(res.data.data.total)
}
}
const handleSelectionChange = (val:any)=>{
console.log(val)
}
@ -158,57 +145,109 @@ const handleCurrentChange = (Current:any) => {
searchParams.value.current = Current //
//
};
//
const onSearch = (data : String)=>{
searchParams.value.name = data
searchParams.value.current = 1
//
const restForm =()=> {
DialogVisible.value = false
carouseImg.value.splice(0,1)
editForm.value.url = ''
}
const deleteCarouse = async (index: number,row: any) =>{ //
simpleList.value.splice(index,1)
const deleteCarouse = async (id: number) =>{ //
const res = await myAxios.post('/banner/delete',{ id: id })
if(res.data.code === 1) {
SuccessInfo('删除图片成功')
await getCourseList()
} else {
WarnInfo('服务错误')
}
}
const editCarouse = async (obj: any) =>{
title.value = '编辑轮播图'
carouseImg.value.splice(0,carouseImg.value.length)
carouseImg.value.push({ //
url: obj.imgUrl
url: downloadUrl + obj.url
})
editForm.value = obj
editForm.value = JSON.parse(JSON.stringify(obj))
DialogVisible.value = true
}
const saveEdit = ()=>{ //
const saveEdit = async ()=>{ //
if(editForm.value.url === '') {
WarnInfo('图片不能为空')
return
}
DialogVisible.value = false
if(editForm.value.id == undefined) {
const res = await myAxios.post('/banner/add',{
type: '实体类',
url: editForm.value.url
})
if(res.data.code === 1) {
DialogVisible.value = false
await getCourseList()
reload()
return
}
} else {
const res = await myAxios.post('/banner/update',{ ...editForm.value })
if(res.data.code === 1) {
DialogVisible.value = false
await getCourseList()
reload()
SuccessInfo('更新成功')
return
}
}
WarnInfo('服务错误')
}
const removePic : UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //uploadFileuploadFiles
carouseImg.value.splice(0,1)
editForm.value.url = ''
}
//
const loadForm = (value: any) => {
editForm.value.grade = value
}
const Exceed_ProductImg: UploadProps['onExceed'] = (files) => { // 'onExceed'
WarnInfo('请移除之前的再上传')
}
const handleChange = async (file: any ) => {
loading.value = true
fileSimple.value = file
let formData = new FormData() // FormData
formData.append("file", fileSimple.value.raw) //fileSimple.value.raw formData
// const res = await myAxios({ //
// url: '/file/uploadFile',
// method: 'post',
// headers: {
// 'content-Type': 'multipart/form-data'
// },
// data: {
// biz: "test",
// // formDatafile
// file: formData.get("file")
// }
// })
const res = await myAxios({ //
url: '/file/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
// formDatafile
file: formData.get("file")
}
})
if(res.data.code === 1) {
editForm.value.url = res.data.data
loading.value = false
SuccessInfo('图片上传成功')
}
}
//
const addCarouse = async () => {
restForm()
title.value = '添加轮播图'
DialogVisible.value = true
}
</script>
<style scoped>
.headerBg{
background-color: #eee !important;
.table_page {
min-width: 1000px;
overflow: auto;
}
</style>

View File

@ -6,27 +6,10 @@
<el-form :model="festivalForm" label-width="auto" style="max-width: 600px" v-loading="loading">
<el-form-item label="添加节日缩略图">
<!-- 下面的event的作用,传入当前事件对象 -->
<el-upload
v-model:file-list="festivalImg"
action="#"
ref="uploadProductImg"
list-type="picture-card"
:auto-upload="false"
multiple="true"
:on-remove="handleRemove"
@change="(event: any) => handleChange(event)"
:on-exceed="Exceed_ProductImg"
limit="1">
<el-icon>
<Plus/>
</el-icon>
</el-upload>
<ImgSingleUpload @update:goodImgArr="festivalForm.url = $event"/>
</el-form-item>
<el-form-item label="节日名称">
<!-- <el-input v-model="festivalForm.name" @input="changeInput"/>-->
<el-select v-model="form.festivalName" placeholder="请选择" >
<el-option v-for="item in festivalArr" :key="item" :label="item.name" :value="item.name" />
</el-select>
<el-input v-model="festivalForm.name" @input="changeInput"/>
</el-form-item>
</el-form>
<template #footer #default="{ row, $index }">
@ -38,14 +21,13 @@
</div>
</template>
</el-dialog>
<div class="table_page">
<!-- 数据展示层 -->
<el-table :data="tableData" border style="width: 100%;" :header-cell-style="{ 'text-align': 'center' }"
@selection-change="handleSelectionChange" :cell-style="{ 'text-align': 'center', 'font-size': '16px' }">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="url" label="节日图片">
<!-- 插槽拿到父组件的值typeUrl -->
<!-- scope 提供了关于当前行的信息 -->
<template #default="scope"><img :src="scope.row.url" alt="" style="height: 50px;"></template>
<template #default="scope"><img :src="downloadUrl + scope.row.url" alt="" style="height: 50px;"></template>
</el-table-column>
<el-table-column prop="name" label="节日名称"></el-table-column>
<el-table-column prop="operation" label="操作">
@ -60,22 +42,22 @@
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import {ElMessage, type UploadProps, type UploadUserFile,type UploadFile, genFileId, type UploadRawFile} from 'element-plus';
import {ElMessage, type UploadUserFile} from 'element-plus';
import {ErrorInfo, SuccessInfo, WarnInfo} from '@/utils/messageInfo';
import {onMounted, ref} from 'vue'
import myAxios from '@/api/myAxios';
import {form} from "@/utils/entityProduct/picUpload";
import {downloadUrl} from '@/utils/formatImgUpload'
import ImgSingleUpload from "@/utils/imgUpload/ImgSingleUpload.vue";
const fileSimple = ref() //
const selectedItems = ref([])
const dialogVisible = ref(false)
const submitable = ref(true) //
const loading = ref(false) //
const festivalImg: any = ref<UploadUserFile[]>([]) //
const uploadProductImg: any = ref() //ref
//
const festivalForm = ref({
id: 0,
@ -97,52 +79,14 @@ onMounted(() => {
//
const getFestivalList = async () => {
const res = await myAxios.get('/festival/get')
console.log('表格数据--->',res.data)
if (res.data.code === 1) {
tableData.value = res.data.data
} else {
ElMessage.error('获取类别列表失败,请检查服务')
}
}
//flag
const handleChange = async (file: any) => {
fileSimple.value = file
loading.value = true
let formData = new FormData() // FormData
formData.append("file", fileSimple.value.raw) //fileSimple.value.raw formData
const res = await myAxios({ //
url: '/file/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
file: formData.get("file") // formDatafile
}
})
if (res.data.code === 1) {
loading.value = false
SuccessInfo('上传成功')
submitable.value = false
tempImgUrl.value = res.data.data
} else {
ErrorInfo(res.data.message)
}
}
//
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
// typeForm.value.typeUrl = ''
festivalImg.value.splice(0, festivalImg.value.length) //
submitable.value = true //
}
//
const Exceed_ProductImg: UploadProps['onExceed'] = (files) => { // 'onExceed'
uploadProductImg.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
uploadProductImg.value!.handleStart(file)
}
//
const showForm = async () => {
resetForm()
@ -151,30 +95,33 @@ const showForm = async () => {
dialogVisible.value = true;
flag.value = 0
}
//
const cancel = () => {
dialogVisible.value = false
resetForm()
}
//
const addOrUpdateFestival = async () => {
//
// if (festivalForm.value.name?.indexOf(' ') !== -1 ||
// festivalForm.value.name == '' || tempImgUrl.value == '') {
// ElMessage({
// type: 'warning',
// message: '/'
// })
// return
// }
if (festivalForm.value.name?.indexOf(' ') !== -1 ||
festivalForm.value.name == '') {
ElMessage({
type: 'warning',
message: '不能为空格/空字符串'
})
return
}
//
dialogVisible.value = false;
console.log('添加的类别--->',festivalForm.value)
const res = await myAxios.post('/festival/add', {
name: festivalForm.value.name,
url: '12321234123453124',
url: festivalForm.value.url,
//
})
console.log('后端返回的--->',res.data)
if (res.data.code === 1) {
//
SuccessInfo('添加类别成功')
@ -182,7 +129,6 @@ const addOrUpdateFestival = async () => {
} else {
ElMessage.error('提交失败')
}
await getFestivalList()
}
//
@ -212,4 +158,10 @@ const changeInput = () => { //当输入栏变化时解除禁用提交按钮
}
</script>
<style scoped></style>
<style scoped>
.table_page {
min-width: 1000px;
overflow: auto;
}
</style>

View File

@ -1,6 +1,5 @@
<template>
<!-- 修改前请注释以前的 -->
<!-- 搜索 -->
<div class="table_page">
<div>
<el-input style="width: 240px; margin-right: 10px;" suffix-icon="Search" placeholder="请输入商户单号"
v-model="outTradeNo" size="default"></el-input>
@ -9,9 +8,7 @@
<el-button type="warning" @click="reset" size="default">重置</el-button>
</div>
<div style="margin: 15px 0">
</div>
<!-- 数据展示 -->
<el-table :data="tableData" border stripe header-cell-class-name="headerBg"
:cell-style="{ 'text-align': 'center', 'font-size': '16px' }" @selection-change="handleSelectionChange"
:header-cell-style="{ 'text-align': 'center' }">
@ -30,8 +27,8 @@
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间"></el-table-column>
</el-table>
</div>
<!-- 分页器 -->
<div style="padding: 10px 0">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
@ -39,15 +36,12 @@
:small="null" :disabled="null" :background="null" layout="total, sizes, prev, pager, next, jumper"
:total="total" />
</div>
<!-- 编辑/详情表单 -->
</template>
<script setup lang="ts">
import { ElMessage , type UploadProps , genFileId ,type UploadRawFile } from 'element-plus';
import { ElMessage } from 'element-plus';
import { ref, onMounted, inject } from 'vue';
import myAxios from "@/api/myAxios";
import { handleChange, removePic, handleRemove,Exceed_ProductImg, ImgArr ,editForm} from '@/utils/entityProduct/picUpload';
const total = ref(0); //
const outTradeNo = ref('');
const searchParams: any = ref({ //
@ -82,8 +76,6 @@ const getProductList = async () => {
});
}
}
//
//
@ -111,7 +103,8 @@ const handleSelectionChange =()=>{}
</script>
<style scoped>
.headerBg {
background-color: #eee !important;
.table_page {
min-width: 1000px;
overflow: auto;
}
</style>

View File

@ -2,22 +2,15 @@
<div class="flexCard">
<el-card class="richTextPreview" shadow="never">
<div class="titleText">移动端预览</div>
<p v-html="form.richText"></p>
<p v-html="previewRichText"></p>
</el-card>
<!-- 表单 ref prop绑定 用于重置表单 -->
<el-card class="form-FormContainer" shadow="never">
<el-form ref="resetFormData" :model="form" label-width="auto" size="large">
<el-form-item label="添加课程展示图片">
<!-- 下面的event的作用,传入当前事件对象 -->
<el-upload ref="uploadProductImg" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 0)"
:on-exceed="Exceed_ProductImg" limit="1">
<el-icon>
<Plus />
</el-icon>
</el-upload>
<el-form ref="resetFormData" :model="form" size="large">
<el-form-item label="添加课程展示图片" label-width="auto">
<ImgSingleUpload @update:goodImgArr="form.goodImg = $event"/>
</el-form-item>
<el-form-item label="体验课名称" prop="name" style="width: 250px">
<el-form-item label="体验课名称" prop="name" style="width: 250px" >
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="产品价格" prop="price">
@ -30,8 +23,8 @@
<el-form-item label="商品标签" prop="label">
<el-input v-model="form.label" type="textarea" placeholder="使用英文;分隔符分开" style="width: 250px;" />
</el-form-item>
<el-form-item>
<richTextUtil @richTextContent="getInfo"></richTextUtil>
<el-form-item label="课程详情">
<richTextUtil @richTextContent="getRichTextInfo"></richTextUtil>
</el-form-item>
<div class="totalButton">
<el-form-item>
@ -44,7 +37,7 @@
</el-form>
</el-card>
<el-card class="form-RichTextContainer" shadow="never">
<calendarUtil @calendar-info="getInfo"></calendarUtil>
<calendarUtil @calendar-info="getDateInfo"></calendarUtil>
</el-card>
</div>
@ -52,13 +45,12 @@
<script setup lang="ts">
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 { ElMessage } from 'element-plus';
import myAxios from "@/api/myAxios";
import calendarUtil from '@/layout/components/calendarUtil.vue';
import richTextUtil from '@/layout/components/richTextUtil.vue';
import ImgSingleUpload from '@/utils/imgUpload/ImgSingleUpload.vue'
const fileSimple = ref() //
const resetFormData = ref()
const form = ref({
name: '',
@ -71,19 +63,19 @@ const form = ref({
})
//
const reload: any = inject("reload")
const uploadProductImg: any = ref() //ref
const previewRichText = ref('') //
onMounted(() => {
// console.log(myDate.getHours()); //
})
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
}
//
const onSubmit = async () => {
console.log('上传前--->',form.value)
const values = Object.values(form.value);
// 使some()
console.log(form.value.appointmentDateAddRequestList)
if (values.some(value => value === null || value === undefined || value === '') || form.value.appointmentDateAddRequestList.length == 0 ) {
if (values.some(value => value === null || value === undefined || value === '' || value === 'PHA+PGJyPjwvcD4=') || form.value.appointmentDateAddRequestList.length == 0 ) {
ElMessage({
type: 'warning',
message: '请检查表单数据是否完整填写'
@ -96,7 +88,7 @@ const onSubmit = async () => {
price: form.value.price,
goodImg: form.value.goodImg,
intro: form.value.intro,
richTetx: form.value.richText,
richText: form.value.richText,
label: form.value.label,
appointmentDateAddRequestList: toRaw(form.value.appointmentDateAddRequestList)
})
@ -112,58 +104,49 @@ const onSubmit = async () => {
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/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
// formDatafile
file: formData.get("file")
}
})
if (res.data.code === 1) {
// flag0 flag1
form.value.goodImg = res.data.data
}
}
//
const resetForm = () => {
resetFormData.value.resetFields()
}
const Exceed_ProductImg: UploadProps['onExceed'] = (files) => { //
uploadProductImg.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
uploadProductImg.value!.handleStart(file)
}
const getInfo =(info:any)=>{
console.log('info-->',info);
const getRichTextInfo =(info:any)=>{
// console.log('info-->',info);
form.value.richText = info
form.value.richText = encode64(info)
previewRichText.value = info
}
//base64
function encode64(text: string): string {
return btoa(String.fromCharCode(...new TextEncoder().encode(text)))
}
const getDateInfo =(info: any)=> {
console.log('info-->',info);
form.value.appointmentDateAddRequestList = info
}
</script>
<style scoped>
.form-FormContainer {
width: 450px;
width: 600px;
height: 800px;
overflow: auto;
min-width: 600px;
/* margin: 0 auto; */
}
.form-RichTextContainer {
width: 550px;
min-width: 550px;
}
.flexCard {
display: flex;
height: 100%;
min-width: 1000px;
}
.richTextPreview {
@ -172,6 +155,7 @@ const getInfo =(info:any)=>{
word-break: break-all;
width: 400px;
margin-right: 10px;
min-width: 400px;
}
.totalButton {
@ -179,5 +163,8 @@ const getInfo =(info:any)=>{
justify-content: space-evenly;
/* 盒子里面水平分隔开 */
}
.titleText {
text-align: center;
margin: 0 auto;
}
</style>

View File

@ -1,6 +1,5 @@
<template>
<!-- 修改前请注释以前的 -->
<!-- 搜索 -->
<div class="table_page">
<div style="display: flex; align-items: center">
<el-input style="width: 200px; height: 30px; margin-right: 10px;" suffix-icon="Search" placeholder="请输入课程名称"
v-model="productName"></el-input>
@ -38,7 +37,7 @@
<el-table-column prop="goodImg" label="课程图片">
<template #default="scope">
<div>
<img :src="scope.row.goodImg" alt="" style="height: 50px;">
<img :src="downloadUrl + scope.row.goodImg" alt="" style="height: 50px;">
</div>
</template>
</el-table-column>
@ -114,57 +113,7 @@
:small="null" :disabled="null" :background="null" layout="total, sizes, prev, pager, next, jumper"
:total="total" />
</div>
<!-- 编辑/详情表单 -->
<el-dialog v-model="DialogVisible" :title="title">
<el-form label-width="100px" :disabled="disabled">
<el-form-item label="商品编号">
<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 ref="uploadProductImg" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 0)" :on-exceed="Exceed_ProductImg"
limit="1">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item label="商品名称">
<el-input v-model="editForm.name"></el-input>
</el-form-item>
<el-form-item label="产品价格" prop="price">
<el-input-number v-model="editForm.price" min="0" :precision="2" :step="0.5" />
<p></p>
</el-form-item>
<el-form-item label="商品标签">
<el-input v-model="editForm.label"></el-input>
</el-form-item>
<el-form-item label="商品图文">
<div v-if="editForm.detailImg">
<img :src="editForm.detailImg" alt="商品图标" class="thumbnail" style="width: 100px; height: 100px;" />
</div>
<el-upload ref="uploadProductDetail" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 1)" :on-exceed="Exceed_ProductDetail"
limit="1">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item label="商品描述">
<el-input type="textarea" v-model="editForm.introDetail"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="DialogVisible = false" :disabled="disabled">取消</el-button>
<el-button type="primary" @click="saveEdit" :disabled="disabled">确认</el-button>
</span>
</template>
</el-dialog>
<!-- 时间段抽屉 -->
<el-drawer
v-model="drawer"
@ -228,11 +177,12 @@
<script setup lang="ts">
import { ElMessage , type UploadProps , genFileId ,type UploadRawFile } from 'element-plus';
import {ref, onMounted, inject, toRaw} from 'vue';
import {ref, onMounted, inject} from 'vue';
import myAxios from "@/api/myAxios";
import calendarUtil from '@/layout/components/calendarUtil.vue';
import emitter from "@/utils/emitter";
import { useRouter } from "vue-router";
import { downloadUrl } from '@/utils/formatImgUpload'
const router = useRouter(); //
const total = ref(0); //
@ -245,16 +195,9 @@ const searchParams: any = ref({ //封装分页
})
const tableData : any= ref([]);
const appointmentDateArr : any = ref([])
const disabled = ref(true)
const title = ref('') //
const productName = ref('');
const DialogVisible = ref(false);
const state = ref(''); //select
const editForm : any = ref({});
const reload : any = inject("reload") //
const fileSimple = ref()
const uploadProductImg : any = ref() //ref
const uploadProductDetail : any = ref() //ref
//
const drawer = ref(false) //
const drawerDate : any = ref({}) //
@ -313,22 +256,7 @@ const getProductList = async () => {
});
}
}
const saveEdit = async () => { //
const res = await myAxios.post('/goods/service/single/update',{...editForm.value})
if(res.data.code === 1) {
DialogVisible.value = false
ElMessage({
type: 'success',
message: '更新成功'
})
} else {
ElMessage({
type: 'error',
message: '请检查字段是否正确填写'
})
}
console.log(res.data);
}
const searchByState = (event : any) => { ///
searchParams.value.isShelves = event
searchParams.value.current = 1
@ -356,11 +284,9 @@ const ReviseOrView = (index: number, row: any , flag : number) => {
flag: flag
}
})
//flag disabled
flag ? (title.value = "编辑商品" , disabled.value = false) : (title.value = "商品详情" , disabled.value = true)
editForm.value = JSON.parse(JSON.stringify(row));
};
//()
//
const handleOff = async (row: any) => {
console.log(row.isShelves);
const res = await myAxios.post('/goods/service/shelves',{id: row.id})
@ -385,45 +311,8 @@ 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
file.uid = genFileId()
uploadProductDetail.value!.handleStart(file)
}
//
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/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
file: formData.get("file") // formDatafile
}
})
if (res.data.code === 1) {
// flag0 flag1
flag ? editForm.value.detailImg = res.data.data : editForm.value.goodImg = res.data.data
console.log('res--->',res.data.data)
}
}
const onSearch = (data : String)=>{ //
searchParams.value.name = data
searchParams.value.current = 1
@ -635,7 +524,8 @@ const submitDate = async ()=> { //提交日期方法
</script>
<style scoped>
.headerBg {
background-color: #eee !important;
.table_page {
min-width: 1000px;
overflow: auto;
}
</style>

View File

@ -2,22 +2,16 @@
<div class="flexCard">
<el-card class="richTextPreview" shadow="never">
<div class="titleText">移动端预览</div>
<p v-html="detailFrom.richText"></p>
<p v-html="previewRichText"></p>
</el-card>
<!-- 表单 ref prop绑定 用于重置表单 -->
<el-card class="form-container" shadow="never">
<div class="form">
<el-form ref="resetFormData" :model="detailFrom" label-width="auto" size="large" :rules="rules" :disabled="true">
<el-form ref="resetFormData" :model="detailFrom" label-width="auto" size="large" :disabled="disabledRichText" >
<div>
<el-form-item label="添加商品图片">
<!-- 下面的event的作用,传入当前事件对象 -->
<el-upload v-model:file-list="ImgArr" ref="uploadProductImg" action="#" list-type="picture-card" :auto-upload="false" multiple="true"
:on-remove="handleRemove" @change="(event: any) => handleChange(event, 2)" :on-exceed="Exceed_ProductImg"
limit="7">
<el-icon>
<Plus />
</el-icon>
</el-upload>
<PreviewSingleImgUpload :ImgUrlList="previewImgUrl" @update:goodImgArr="detailFrom.goodImg = $event"/>
</el-form-item>
</div>
<div class="NamePrice">
@ -31,12 +25,12 @@
</div>
<div class="IntroInven">
<el-form-item label="课程简介" prop="intro">
<el-input v-model="detailFrom.intro" type="textarea" placeholder="产品尺寸,服务等" maxlength="30" show-word-limit
<el-input v-model="detailFrom.intro" type="textarea" placeholder="产品尺寸,服务等" maxlength="60" show-word-limit
style="width: 300px;" />
</el-form-item>
</div>
<el-form-item label="课程详情图" prop="richText">
<richTextUtil @richTextContent="getInfo" v-model:disableRich="disabledRichText"/>
<el-form-item label="课程详情图" prop="richText" v-loading="loading">
<richTextUtil @richTextContent="getInfo" v-model:disableRich="disabledRichText" v-model:context="previewRichText"/>
</el-form-item>
<div class="btnBox">
<el-form-item>
@ -53,21 +47,18 @@
</template>
<script lang="ts" setup>
import { ref, onMounted, inject, reactive , onBeforeMount} from 'vue';
import { Plus } from '@element-plus/icons-vue';
import {type FormRules, type UploadUserFile} from 'element-plus';
import { SuccessInfo, WarnInfo, CommInfo } from '@/utils/messageInfo'; //ElMessage
import { ref, onMounted , onBeforeMount} from 'vue';
import { type UploadUserFile} from 'element-plus';
import { SuccessInfo, WarnInfo } from '@/utils/messageInfo'; //ElMessage
import myAxios from "@/api/myAxios";
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';
import { saveBtn } from '@/utils/entityProduct/globalVar';
import richTextUtil from '@/layout/components/richTextUtil.vue';
import { useRoute } from "vue-router";
import { useRoute ,useRouter } from "vue-router";
import PreviewSingleImgUpload from "@/utils/imgUpload/PreviewSingleImgUpload.vue";
const route = useRoute(); //
const resetFormData = ref()
const reload: any = inject("reload") //
const uploadProductImg: any = ref() //ref
const ImgArr: any = ref<UploadUserFile[]>([])
const detailFrom : any = ref({
name: '', //
@ -80,25 +71,32 @@ const detailFrom : any = ref({
inventory: '', //
richText: ''
})
const previewImgUrl = ref('') //
const previewRichText = ref('')
const disabledRichText:any = ref(false);
const loading = ref(true)
const router = useRouter()
onBeforeMount(()=>{
if(route.params.flag === '0'){
disabledRichText.value = true;
}
getServiceInfo() //
})
onMounted(() => {
getServiceInfo() //
// console.log('id---->',route.params.id)
// console.log('flag---->',route.params.flag)
setTimeout(()=>{
loading.value = false
},1500)
})
const getServiceInfo = async () => {
const res = await myAxios.post("/goods/service/list/id",{ id: route.params.id })
console.log('res--->',res.data)
if(res.data.code == 1){
previewImgUrl.value = res.data.data.goodImg
detailFrom.value = res.data.data
previewRichText.value = res.data.data.richText
ImgArr.value.splice(0,ImgArr.value.length)
var tempArr = res.data.data.goodImg.split(';')
tempArr.forEach((item: any) => {
@ -119,12 +117,11 @@ const onSubmit = async () => {
WarnInfo('请检查表单数据是否完整填写')
return; //
}
const res = await myAxios.post('/goods/add', { ...detailFrom.value })
const res = await myAxios.post('/goods/service/single/update', { ...detailFrom.value })
// console.log(res.data);
if (res.data.code === 1) {
SuccessInfo('提交成功')
detailFrom.value = {} //12.18
reload() //
await router.replace('/ProductCenter')
} else {
WarnInfo('服务错误')
return;
@ -135,14 +132,16 @@ const onSubmit = async () => {
const resetForm = () => {
resetFormData.value.resetFields()
}
const rules = reactive<FormRules<typeof form>>({ //
name: [{ validator: validateName, trigger: 'blur' }],
intro: [{ validator: validateIntro, trigger: 'blur' }],
introDetail: [{ validator: validateDetail, trigger: 'blur' }]
})
// const rules = reactive<FormRules<typeof form>>({ //
// name: [{ validator: validateName, trigger: 'blur' }],
// intro: [{ validator: validateIntro, trigger: 'blur' }],
// introDetail: [{ validator: validateDetail, trigger: 'blur' }]
// })
const getInfo = (info: any) => { //
console.log('info', info)
// console.log('info', info)
previewRichText.value = info
detailFrom.value.richText = info
}
</script>
@ -158,11 +157,15 @@ const getInfo = (info: any) => { //富文本赋值
overflow-y: auto;
word-break: break-all;
width: 400px;
min-width: 400px;
margin-right: 10px;
}
.form-container {
width: 700px;
min-width: 700px;
height: 800px;
overflow: auto;
/* margin: 0 auto; */
}
.form {
@ -186,4 +189,9 @@ const getInfo = (info: any) => { //富文本赋值
display: flex;
justify-content: space-around;
}
.titleText {
text-align: center;
margin: 0 auto;
}
</style>

View File

@ -1,15 +1,9 @@
<template>
<div class="detail-container">
<div class="detail-container">
<el-card shadow="hover">
<el-form label-width="100px" :disabled="disabled">
<el-form-item label="头像">
<el-upload v-model:file-list="ImgArr" ref="uploadProductImg" action="#" list-type="picture-card"
:auto-upload="false" multiple="true" :on-remove="removePic" @change="(event: any) => handleChange(event)"
:on-exceed="Exceed_ProductImg" limit="1">
<el-icon>
<Plus />
</el-icon>
</el-upload>
<PreviewSingleImgUpload :ImgUrlList="userForm.userAvatar" @update:goodImgArr="userForm.userAvatar = $event"/>
</el-form-item>
<div style="display: flex;">
<el-form-item label="账号">
@ -23,9 +17,6 @@
<el-form-item label="用户名">
<el-input v-model="userForm.userName" />
</el-form-item>
<el-form-item label="手机号码">
<el-input v-model="userForm.phone" />
</el-form-item>
</div>
<div style="display: flex;">
<el-form-item label="积分">
@ -34,71 +25,40 @@
</div>
</el-form>
<div style="display: flex;">
<el-button @click="changeStatus">{{ btnText }}</el-button>
<el-button type="primary" @click="saveEdit" :disabled="disabled">确认</el-button>
</div>
</el-card>
</div>
</div>
</template>
<script setup lang="ts">
import { ElMessage, type UploadProps, type UploadUserFile,type UploadFile, genFileId, type UploadRawFile } from 'element-plus';
import myAxios from '@/api/myAxios';
import { ref, onMounted } from 'vue'
import { ErrorInfo, SuccessInfo, WarnInfo } from '@/utils/messageInfo';
import { ref, onBeforeMount } from 'vue'
import { SuccessInfo, WarnInfo } from '@/utils/messageInfo';
import { useRoute } from "vue-router";
import PreviewSingleImgUpload from "@/utils/imgUpload/PreviewSingleImgUpload.vue";
const ImgArr: any = ref<UploadUserFile[]>([]) //使
const disabled = ref(true) //
const userForm: any = ref({}) //
const fileSimple = ref() //
const uploadProductImg: any = ref() //ref
const tempAvatar = ref('') //
const btnText = ref('编辑') //
const route = useRoute()
onMounted(()=>{
onBeforeMount(()=>{
if(route.params.flag === '1') {
disabled.value = false
}
getUserInfo()
console.log('用户id---->',route.params.id)
console.log('标识--->',route.params.flag)
})
//
const getUserInfo = async () => {
const res = await myAxios.get('/user/get/web/login')
// console.log(res.data.data)
console.log('后端返回---->',res.data)
if(res.data.code === 1) {
userForm.value = res.data.data
ImgArr.value.push({
url: res.data.data.userAvatar
})
}
//
const Exceed_ProductImg: UploadProps['onExceed'] = (files) => { // 'onExceed'
uploadProductImg.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
uploadProductImg.value!.handleStart(file)
}
//
const handleChange = async (file: any) => {
fileSimple.value = file
let formData = new FormData() // FormData
formData.append("file", fileSimple.value.raw) //fileSimple.value.raw formData
const res = await myAxios({ //
url: '/file/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
file: formData.get("file") // formDatafile
}
})
if (res.data.code === 1) {
tempAvatar.value = res.data.data
}
}
//
const removePic: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //uploadFileuploadFiles
userForm.value.userAvatar = ''
}
const saveEdit = async ()=>{ //
@ -106,7 +66,7 @@ const saveEdit = async ()=>{ //保存用户信息
id: userForm.value.id,
userPassword: userForm.value.userPassword,
userName: userForm.value.userName,
userAvatar: tempAvatar.value,
userAvatar: userForm.value.userAvatar,
phone: userForm.value.phone,
userRole: userForm.value.userRole
})
@ -118,18 +78,6 @@ const saveEdit = async ()=>{ //保存用户信息
WarnInfo('更新失败')
}
}
const changeStatus = async ()=> {
if(btnText.value === '编辑') {
tempAvatar.value = userForm.value.userAvatar
btnText.value = '取消'
disabled.value = false
} else {
btnText.value = '编辑'
disabled.value = true
//
}
}
</script>
@ -138,5 +86,6 @@ const changeStatus = async ()=> {
width: 80%;
padding: 20px 20px 20px 20px;
margin: 20px auto;
min-width: 1000px;
}
</style>

View File

@ -0,0 +1,91 @@
<template>
<div class="detail-container">
<el-card shadow="hover">
<el-form label-width="100px" :disabled="disabled">
<el-form-item label="头像">
<PreviewSingleImgUpload :ImgUrlList="userForm.userAvatar" @update:goodImgArr="userForm.userAvatar = $event"/>
</el-form-item>
<div style="display: flex;">
<el-form-item label="账号">
<el-input v-model="userForm.userAccount"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="userForm.userPassword" type="password" />
</el-form-item>
</div>
<div style="display: flex;">
<el-form-item label="用户名">
<el-input v-model="userForm.userName" />
</el-form-item>
</div>
<div style="display: flex;">
<el-form-item label="积分">
<el-input v-model="userForm.points"></el-input>
</el-form-item>
</div>
</el-form>
<div style="display: flex;">
<el-button type="primary" @click="saveEdit" :disabled="disabled">确认</el-button>
</div>
</el-card>
</div>
</template>
<script setup lang="ts">
import myAxios from '@/api/myAxios';
import { ref, onBeforeMount } from 'vue'
import { SuccessInfo, WarnInfo } from '@/utils/messageInfo';
import { useRoute } from "vue-router";
import PreviewSingleImgUpload from "@/utils/imgUpload/PreviewSingleImgUpload.vue";
const disabled = ref(true) //
const userForm: any = ref({}) //
const tempAvatar = ref('') //
const route = useRoute()
onBeforeMount(()=>{
if(route.params.flag === '1') {
disabled.value = false
}
getUserInfo()
console.log('用户id---->',route.params.id)
console.log('标识--->',route.params.flag)
})
//
const getUserInfo = async () => {
const res = await myAxios.post('/user/query/id',{ id: route.params.id })
console.log('后端返回---->',res.data)
if(res.data.code === 1) {
userForm.value = res.data.data
}
}
const saveEdit = async ()=>{ //
const res = await myAxios.post('/user/update',{
id: userForm.value.id,
userPassword: userForm.value.userPassword,
userName: userForm.value.userName,
userAvatar: userForm.value.userAvatar,
phone: userForm.value.phone,
userRole: userForm.value.userRole
})
console.log('更新信息--->',res.data)
if (res.data.code === 1) {
disabled.value = true
SuccessInfo('更新成功')
} else {
WarnInfo('更新失败')
}
}
</script>
<style scoped>
.detail-container {
width: 80%;
padding: 20px 20px 20px 20px;
margin: 20px auto;
}
</style>

View File

@ -1,61 +0,0 @@
<template>
<el-upload
ref="uploadProductImg"
action="#"
list-type="picture-card"
:auto-upload="false"
multiple="true"
:on-remove="handleRemove"
@change="(event: any) => handleChange(event, 0)"
:on-exceed="Exceed_ProductImg"
limit="1" >
<el-icon>
<Plus />
</el-icon>
</el-upload>
<div>图片url: {{ imgUrl }}</div>
</template>
<script setup lang="ts">
import { ref, onMounted , inject} 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";
const fileSimple = ref() //
const uploadProductImg : any = ref() //ref
const imgUrl = ref('')
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
}
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/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
// formDatafile
file: formData.get("file")
}
})
if (res.data.code === 1) {
// flag0 flag1
imgUrl.value = res.data.data
}
}
const Exceed_ProductImg: UploadProps['onExceed'] = (files) => { //
uploadProductImg.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
uploadProductImg.value!.handleStart(file)
}
</script>
<style scoped>
</style>

View File

@ -15,19 +15,17 @@
</el-table-column>
<el-table-column prop="userName" label="用户昵称"></el-table-column>
<el-table-column prop="userAvatar" label="头像">
<template #default="scope"><img :src="scope.row.userAvatar" alt="" style="height: 50px;"></template>
<template #default="scope"><img :src="downloadUrl + scope.row.userAvatar" alt="" style="height: 50px;"></template>
</el-table-column>
<el-table-column prop="userRole" label="身份">
<template #default="scope">
{{ scope.row.userRole === 'boss' ? '管理员' : '小程序用户' }}
</template>
</el-table-column>
<el-table-column prop="phone" label="手机号"></el-table-column>
<!-- <el-table-column prop="isDelete" label="是否封禁"></el-table-column>-->
<el-table-column label="操作">
<template #default="scope">
<el-button size="small" @click="checkDetail(scope.row)">详情</el-button>
<el-button size="small" type="primary" @click="editUser(scope.row)">编辑</el-button>
<el-button size="small" @click="checkDetail(scope.row,0)">详情</el-button>
<el-button size="small" type="primary" @click="checkDetail(scope.row,1)">编辑</el-button>
</template>
</el-table-column>
</el-table>
@ -37,53 +35,15 @@
@size-change="handleSizeChange" @current-change="handleCurrentChange" :small="null" background
layout="total, sizes, prev, pager, next, jumper" :total="total" />
</div>
<!-- 单个用户表单 -->
<el-dialog v-model="DialogVisible" :title="title">
<el-form label-width="100px" :disabled="disabled">
<el-form-item label="头像">
<el-upload v-model:file-list="ImgArr" ref="uploadProductImg" action="#" list-type="picture-card"
:auto-upload="false" multiple="true" :on-remove="removePic" @change="(event: any) => handleChange(event)"
:on-exceed="Exceed_ProductImg" limit="1">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<div style="display: flex;">
<el-form-item label="账号">
<el-input v-model="userForm.userAccount" style="width: 200px;"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="userForm.userPassword" type="password"/>
</el-form-item>
</div>
<div style="display: flex;">
<el-form-item label="用户名">
<el-input v-model="userForm.userName" />
</el-form-item>
<el-form-item label="手机号码">
<el-input v-model="userForm.phone" />
</el-form-item>
</div>
<div style="display: flex;">
<el-form-item label="积分">
<el-input v-model="userForm.points"></el-input>
</el-form-item>
</div>
</el-form>
<template #footer>
<el-button @click="DialogVisible = false" :disabled="disabled">取消</el-button>
<el-button type="primary" @click="saveEdit" :disabled="disabled">确认</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ElMessage, type UploadProps, type UploadUserFile,type UploadFile, genFileId, type UploadRawFile } from 'element-plus';
import { ElMessage } from 'element-plus';
import myAxios from '@/api/myAxios';
import { downloadUrl } from '@/utils/formatImgUpload'
import { ref, onMounted, inject } from 'vue'
import { ErrorInfo, SuccessInfo, WarnInfo } from '@/utils/messageInfo';
const ImgArr: any = ref<UploadUserFile[]>([]) //使
import { useRouter } from "vue-router";
//
const tableData = ref([])
//
@ -96,13 +56,8 @@ const searchParams: any = ref({
pageSize: 5
})
const reload: any = inject("reload") //
const DialogVisible = ref(false) //
const title = ref('编辑用户') //
const disabled = ref(false) //
const userForm: any = ref({}) //
const fileSimple = ref() //
const uploadProductImg: any = ref() //ref
const tempAvatar = ref('') //
const router = useRouter()
onMounted(() => {
getUserList()
})
@ -111,37 +66,7 @@ const username = ref('')
const reset = () => {
reload()
}
//
const handleChange = async (file: any) => {
fileSimple.value = file
let formData = new FormData() // FormData
formData.append("file", fileSimple.value.raw) //fileSimple.value.raw formData
const res = await myAxios({ //
url: '/file/uploadFile',
method: 'post',
headers: {
'content-Type': 'multipart/form-data'
},
data: {
biz: "test",
file: formData.get("file") // formDatafile
}
})
if (res.data.code === 1) {
tempAvatar.value = res.data.data
}
}
//
const removePic: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //uploadFileuploadFiles
userForm.value.userAvatar = ''
}
//
const Exceed_ProductImg: UploadProps['onExceed'] = (files) => { // 'onExceed'
uploadProductImg.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
uploadProductImg.value!.handleStart(file)
}
//
const getUserList = async () => {
//({...})POST.value,Object
@ -180,46 +105,17 @@ const onSearch = (data: String) => {
searchParams.value.current = 1
getUserList()
}
const checkDetail = (obj: any) => { //
title.value = '查看用户'
ImgArr.value.splice(0, ImgArr.value.length)
ImgArr.value.push({
url: obj.userAvatar
})
disabled.value = true
DialogVisible.value = true
userForm.value = obj
}
const editUser = (obj: any) => { //
userForm.value = JSON.parse(JSON.stringify(obj)) //
tempAvatar.value = userForm.value.userAvatar //
disabled.value = false
title.value = '编辑用户'
ImgArr.value.splice(0, ImgArr.value.length)
ImgArr.value.push({
url: obj.userAvatar
})
DialogVisible.value = true
}
const saveEdit = async () => { //
console.log('编辑后的信息--->', userForm.value);
const res = await myAxios.post('/user/update', {
id: userForm.value.id,
userPassword: userForm.value.userPassword,
userName: userForm.value.userName,
userAvatar: tempAvatar.value,
phone: userForm.value.phone,
userRole: userForm.value.userRole
})
console.log('后端返回--->',res.data)
if(res.data.code === 1) {
SuccessInfo('更新成功')
DialogVisible.value = false
getUserList()
} else {
ErrorInfo('更新失败')
const checkDetail = (obj: any, flag : any) => { //
console.log('用户对象--->',obj)
router.push({
name: '用户详情',
params: {
id: obj.id,
flag: flag
}
})
}
</script>

View File

@ -1,128 +1,94 @@
<template>
<el-container class="layout-container-demo" style="height: 500px">
<el-aside width="200px">
<el-scrollbar>
<el-menu :default-openeds="['1', '3']">
<el-sub-menu index="1">
<template #title>
<el-icon><message /></el-icon>Navigator One
</template>
<el-menu-item-group>
<template #title>Group 1</template>
<el-menu-item index="1-1">Option 1</el-menu-item>
<el-menu-item index="1-2">Option 2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="Group 2">
<el-menu-item index="1-3">Option 3</el-menu-item>
</el-menu-item-group>
<el-sub-menu index="1-4">
<template #title>Option4</template>
<el-menu-item index="1-4-1">Option 4-1</el-menu-item>
</el-sub-menu>
</el-sub-menu>
<el-sub-menu index="2">
<template #title>
<el-icon><icon-menu /></el-icon>Navigator Two
</template>
<el-menu-item-group>
<template #title>Group 1</template>
<el-menu-item index="2-1">Option 1</el-menu-item>
<el-menu-item index="2-2">Option 2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="Group 2">
<el-menu-item index="2-3">Option 3</el-menu-item>
</el-menu-item-group>
<el-sub-menu index="2-4">
<template #title>Option 4</template>
<el-menu-item index="2-4-1">Option 4-1</el-menu-item>
</el-sub-menu>
</el-sub-menu>
<el-sub-menu index="3">
<template #title>
<el-icon><setting /></el-icon>Navigator Three
</template>
<el-menu-item-group>
<template #title>Group 1</template>
<el-menu-item index="3-1">Option 1</el-menu-item>
<el-menu-item index="3-2">Option 2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="Group 2">
<el-menu-item index="3-3">Option 3</el-menu-item>
</el-menu-item-group>
<el-sub-menu index="3-4">
<template #title>Option 4</template>
<el-menu-item index="3-4-1">Option 4-1</el-menu-item>
</el-sub-menu>
</el-sub-menu>
</el-menu>
</el-scrollbar>
</el-aside>
<el-upload
v-model:file-list="ImgList"
:action="uploadUrl"
list-type="picture-card"
:http-request="customUpload"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-exceed="ExceedImg"
limit="7"
v-loading="loading"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-container>
<el-header style="text-align: right; font-size: 12px">
<div class="toolbar">
<el-dropdown>
<el-icon style="margin-right: 8px; margin-top: 1px">
<setting />
</el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>View</el-dropdown-item>
<el-dropdown-item>Add</el-dropdown-item>
<el-dropdown-item>Delete</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<span>Tom</span>
</div>
</el-header>
<el-main>
<el-scrollbar>
<el-table :data="tableData">
<el-table-column prop="date" label="Date" width="140" />
<el-table-column prop="name" label="Name" width="120" />
<el-table-column prop="address" label="Address" />
</el-table>
</el-scrollbar>
</el-main>
</el-container>
</el-container>
<el-dialog v-model="dialogVisible">
<el-image :src="dialogImageUrl"/>
</el-dialog>
<el-button type="primary" @click="submitForm">看看删除后的图片</el-button>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Menu as IconMenu, Message, Setting } from '@element-plus/icons-vue'
import myAxios from '@/api/myAxios'
import { ref, onMounted } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import type { UploadProps, UploadUserFile } from 'element-plus'
import { uploadUrl, downloadUrl } from '@/utils/formatImgUpload'
import { WarnInfo } from "@/utils/messageInfo";
const item = {
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
const goodImgStr = ref('') //
const goodImgArr= ref<String[]>([]) //objectKey
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const loading = ref(false)
onMounted(()=>{
getProductInfo()
})
const getProductInfo = async () => {
const res = await myAxios.post('/goods/getById',{id: 498})
console.log('图片信息--->',res.data.data.goodImg)
goodImgArr.value = res.data.data.goodImg.split(';')
console.log('图片数组---->',goodImgArr.value)
goodImgArr.value.forEach(item => { //
ImgList.value.push({
url: downloadUrl + item
})
})
}
const ImgList: any = ref([])
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { //
console.log(uploadFile, uploadFiles)
let deleteObjKey = uploadFile.url?.substring(downloadUrl.length)
goodImgArr.value = goodImgArr.value.filter(item => item !== deleteObjKey)
}
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!
dialogVisible.value = true
}
const submitForm = ()=>{ //
goodImgStr.value = goodImgArr.value.join(';')
console.log('提交表单的goodImgStr',goodImgStr.value)
}
const ExceedImg: UploadProps['onExceed'] = (files) => { // 'onExceed'
WarnInfo('最多只能上传七张图片!')
}
//
const customUpload = async (e:any) => {
loading.value = true
const res = await myAxios({
url: e.action,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: {
biz: "test",
file: e.file
}
})
console.log('图片上传结果--->',res.data)
if(res.data.code === 1) {
goodImgArr.value.push(res.data.data)
loading.value = false
}
}
const tableData = ref(Array.from({ length: 20 }).fill(item))
</script>
<style scoped>
.layout-container-demo .el-header {
position: relative;
background-color: var(--el-color-primary-light-7);
color: var(--el-text-color-primary);
}
.layout-container-demo .el-aside {
color: var(--el-text-color-primary);
background: var(--el-color-primary-light-8);
}
.layout-container-demo .el-menu {
border-right: none;
}
.layout-container-demo .el-main {
padding: 0;
}
.layout-container-demo .toolbar {
display: inline-flex;
align-items: center;
justify-content: center;
height: 100%;
right: 20px;
}
</style>

View File

@ -1,6 +1,6 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*"],
"include": ["env.d.ts", "src/**/*","src/**/*.ts"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,