feat:七牛云上传
This commit is contained in:
1 parent
13497eb22d
commit
79194fb502
5 files changed
+309
-10
No files matched your search
@@ -0,0 +1,282 @@
|
||||
<template>
|
||||
<div class="upload-box">
|
||||
<el-upload v-model:file-list="fileList" list-type="picture-card" multiple :accept="fileType.join(',')"
|
||||
:class="['upload', 'no-border', self_disabled ? 'disabled' : '']" :drag="true" :disabled="self_disabled"
|
||||
:before-upload="beforeUpload" :on-preview="handlePictureCardPreview" :on-error="uploadError"
|
||||
:on-remove="handleRemove" :on-success="uploadSuccess" :http-request="handleHttpUpload">
|
||||
<el-icon>
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</el-upload>
|
||||
|
||||
<el-dialog v-model="dialogVisible">
|
||||
<img class="m-auto" w-full :src="dialogImageUrl" alt="Preview Image" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue"
|
||||
import { Plus } from "@element-plus/icons-vue"
|
||||
import { ElUpload, ElDialog, UploadRequestOptions, ElNotification, UploadFile, UploadProps, formContextKey } from "element-plus"
|
||||
import request from "/@/utils/request"
|
||||
|
||||
interface UploadFileProps {
|
||||
disabled?: boolean
|
||||
fileType?: string[]
|
||||
fileSize?: number
|
||||
height?: string
|
||||
width?: string
|
||||
borderRadius?: string
|
||||
}
|
||||
const props = withDefaults(defineProps<UploadFileProps>(), {
|
||||
disabled: false,
|
||||
fileType: () => ["image/jpeg", "image/png", "image/gif"],
|
||||
fileSize: 5,
|
||||
height: "150px",
|
||||
width: "150px",
|
||||
borderRadius: "8px",
|
||||
})
|
||||
|
||||
const imageUrls = defineModel("modelValue", { default: "" })
|
||||
|
||||
const imageBaseUrl = import.meta.env.VITE_IMAGE_BASE_PATH
|
||||
const dialogVisible = ref(false)
|
||||
const fileList = ref<any>([])
|
||||
const dialogImageUrl = ref("")
|
||||
// 获取 el-form 组件上下文
|
||||
const formContext = inject(formContextKey, void 0)
|
||||
|
||||
// 自定义上传方法
|
||||
const handleHttpUpload = async (options: UploadRequestOptions) => {
|
||||
let formData = new FormData()
|
||||
formData.append("file", options.file)
|
||||
try {
|
||||
const res = await request({
|
||||
url: "/admin/sys-file/qn/upload",
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
data: formData,
|
||||
})
|
||||
if (res.code == 0) {
|
||||
return res
|
||||
}
|
||||
} catch (error) {
|
||||
options.onError(error as any)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 文件上传之前判断
|
||||
* @param rawFile 选择的文件
|
||||
* */
|
||||
const beforeUpload: UploadProps["beforeUpload"] = (rawFile) => {
|
||||
const imgSize = rawFile.size / 1024 / 1024 < props.fileSize
|
||||
const imgType = props.fileType.includes(rawFile.type)
|
||||
if (!imgType)
|
||||
ElNotification({
|
||||
title: "温馨提示",
|
||||
message: "上传图片不符合所需的格式!",
|
||||
type: "warning",
|
||||
})
|
||||
if (!imgSize)
|
||||
setTimeout(() => {
|
||||
ElNotification({
|
||||
title: "温馨提示",
|
||||
message: `上传图片大小不能超过 ${props.fileSize}M!`,
|
||||
type: "warning",
|
||||
})
|
||||
}, 0)
|
||||
return imgType && imgSize
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 图片上传成功
|
||||
* */
|
||||
const uploadSuccess = (response: any, uploadFile: UploadFile, uploadFiles: any) => {
|
||||
console.log("success", uploadFiles)
|
||||
|
||||
const urls = uploadFiles
|
||||
.map((item: any) => {
|
||||
// 处理新上传和已有的图片URL
|
||||
return item.response ? item.response.data.url : item.fileUrl
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join(",")
|
||||
imageUrls.value = urls
|
||||
|
||||
console.log("fileList.value", fileList.value)
|
||||
console.log("urls", urls)
|
||||
|
||||
ElNotification({
|
||||
title: "温馨提示",
|
||||
message: "图片上传成功!",
|
||||
type: "success",
|
||||
})
|
||||
}
|
||||
|
||||
// 预览
|
||||
const handlePictureCardPreview = (uploadFile: any) => {
|
||||
dialogImageUrl.value = uploadFile.url
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 移除
|
||||
const handleRemove = (uploadFile: any, uploadFiles: any[]) => {
|
||||
const urls = uploadFiles
|
||||
.map((item) => {
|
||||
return item.response ? item.response.data.url : item.fileUrl
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join(",")
|
||||
imageUrls.value = urls
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 图片上传错误
|
||||
* */
|
||||
const uploadError = () => {
|
||||
ElNotification({
|
||||
title: "温馨提示",
|
||||
message: "图片上传失败,请您重新上传!",
|
||||
type: "error",
|
||||
})
|
||||
}
|
||||
|
||||
// 判断是否禁用上传和删除
|
||||
const self_disabled = computed(() => {
|
||||
return props.disabled || formContext?.disabled
|
||||
})
|
||||
|
||||
watch(
|
||||
() => imageUrls.value,
|
||||
(newValue) => {
|
||||
if (!newValue || Object.prototype.toString.call(newValue) !== "[object String]") {
|
||||
fileList.value = []
|
||||
return
|
||||
}
|
||||
|
||||
if (!newValue.match(/x-oss-process/g)) {
|
||||
fileList.value = newValue
|
||||
.split(",")
|
||||
.map((item: string) => {
|
||||
const url = item.startsWith("http") ? item : imageBaseUrl + item
|
||||
return {
|
||||
name: item.split("/").pop() || "",
|
||||
url: url,
|
||||
fileUrl: item,
|
||||
}
|
||||
})
|
||||
.filter((item) => item.url)
|
||||
|
||||
console.log("fileList.value", fileList.value)
|
||||
} else {
|
||||
fileList.value = newValue
|
||||
.split("?")
|
||||
.filter(
|
||||
(item) =>
|
||||
item.endsWith(".jpg") || item.endsWith(".png") || item.endsWith(".gif") || item.endsWith(".jpeg") || item.endsWith(".webp"),
|
||||
)
|
||||
.map((item: string) => {
|
||||
const url = item.startsWith("http") ? item : imageBaseUrl + item
|
||||
return {
|
||||
name: item.split("/").pop() || "",
|
||||
url: url,
|
||||
fileUrl: item,
|
||||
}
|
||||
})
|
||||
.filter((item) => item.url)
|
||||
|
||||
console.log("fileList.value", fileList.value)
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.is-error {
|
||||
.upload {
|
||||
|
||||
:deep(.el-upload),
|
||||
:deep(.el-upload-dragger) {
|
||||
border: 1px dashed var(--el-color-danger) !important;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.disabled) {
|
||||
|
||||
.el-upload,
|
||||
.el-upload-dragger {
|
||||
cursor: not-allowed !important;
|
||||
background: var(--el-disabled-bg-color);
|
||||
border: 1px dashed var(--el-border-color-darker) !important;
|
||||
|
||||
&:hover {
|
||||
border: 1px dashed var(--el-border-color-darker) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-box {
|
||||
overflow: hidden;
|
||||
|
||||
.no-border {
|
||||
:deep(.el-upload) {
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.upload) {
|
||||
.el-upload {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: v-bind(width);
|
||||
height: v-bind(height);
|
||||
overflow: hidden;
|
||||
border: 1px dashed var(--el-border-color-darker);
|
||||
border-radius: v-bind(borderRadius);
|
||||
transition: var(--el-transition-duration-fast);
|
||||
|
||||
&:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
|
||||
.upload-handle {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.el-upload-dragger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: transparent;
|
||||
border: 1px dashed var(--el-border-color-darker);
|
||||
border-radius: v-bind(borderRadius);
|
||||
|
||||
&:hover {
|
||||
border: 1px dashed var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.el-upload-dragger.is-dragover {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
border: 2px dashed var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -6,6 +6,8 @@ import UploadExcel from "/@/components/Upload/Excel.vue"
|
||||
import UploadFile from "/@/components/Upload/index.vue"
|
||||
import UploadImg from "/@/components/Upload/Image.vue"
|
||||
import UploadImgs from "/@/components/Upload/Images.vue"
|
||||
import UploadQnImgs from "/@/components/Upload/qnImages.vue"
|
||||
|
||||
import DelWrap from "/@/components/DelWrap/index.vue"
|
||||
import Editor from "/@/components/Editor/index.vue"
|
||||
import Tip from "/@/components/Tip/index.vue"
|
||||
@@ -67,6 +69,7 @@ export default {
|
||||
app.component("UploadFile", UploadFile)
|
||||
app.component("UploadImg", UploadImg)
|
||||
app.component("UploadImgs", UploadImgs)
|
||||
app.component("UploadQnImgs", UploadQnImgs)
|
||||
app.component("Editor", Editor)
|
||||
app.component("Tip", Tip)
|
||||
app.component("DelWrap", DelWrap)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<el-dialog :title="form.id ? '编辑' : '新增'" width="40%" v-model="visible" :close-on-click-modal="false" draggable>
|
||||
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="120px" v-loading="loading">
|
||||
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="120px"
|
||||
v-loading="loading">
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="商品名" prop="name">
|
||||
@@ -14,12 +15,12 @@
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="商品封面图片" prop="cover">
|
||||
<upload-imgs v-model="form.cover" :disabled="form.skuType == '0'" />
|
||||
<upload-qn-imgs v-model="form.cover" :disabled="form.skuType == '0'" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="商品识别图片" prop="pic">
|
||||
<upload-imgs v-model="form.pic" :disabled="form.skuType == '0'" />
|
||||
<upload-qn-imgs v-model="form.pic" :disabled="form.skuType == '0'" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
@@ -149,7 +150,7 @@ const openDialog = (id: string) => {
|
||||
|
||||
// 提交
|
||||
const onSubmit = async () => {
|
||||
const valid = await dataFormRef.value.validate().catch(() => {})
|
||||
const valid = await dataFormRef.value.validate().catch(() => { })
|
||||
if (!valid) return false
|
||||
|
||||
try {
|
||||
|
||||
@@ -14,12 +14,9 @@ const loading = ref(false)
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
// 是否生成环境
|
||||
if (import.meta.env.VITE_ENV === "prod") {
|
||||
openPlanUrl("https://stgl.pj.gov.cn/cockpit/#/canteen")
|
||||
} else {
|
||||
openPlanUrl("http://localhost:5173/#/canteen")
|
||||
}
|
||||
const isDev = import.meta.env.MODE === "development"
|
||||
const url = isDev ? "http://localhost:5173/#/canteen" : "https://stgl.pj.gov.cn/cockpit/#/canteen"
|
||||
openPlanUrl(url)
|
||||
loading.value = true
|
||||
router.back()
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -42,6 +42,19 @@
|
||||
</el-form-item>
|
||||
<!-- **************************** end 营养分析 end **************************** -->
|
||||
|
||||
|
||||
<!-- **************************** start 今日菜品复购排行 start **************************** -->
|
||||
<el-divider class="my-12">今日菜品复购排行</el-divider>
|
||||
<el-form-item prop="nutritionSetting.repurchaseTopExcludeCategoryIds">
|
||||
<template #label>
|
||||
<div class="flex items-center gap-1">
|
||||
<span>需要排除的菜品分类</span>
|
||||
</div>
|
||||
</template>
|
||||
<select-ctcg v-model="form.nutritionSetting.repurchaseTopExcludeCategoryIds" multiple
|
||||
placeholder="请选择需要排除的菜品分类" />
|
||||
</el-form-item>
|
||||
<!-- **************************** end 今日菜品复购排行 end **************************** -->
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
@@ -66,6 +79,8 @@ const form = reactive<any>({
|
||||
scCategoryIds: [],
|
||||
// 主食菜品分类
|
||||
zsCategoryIds: [],
|
||||
// 复购排行需要排除的菜品分类
|
||||
repurchaseTopExcludeCategoryIds: [],
|
||||
},
|
||||
})
|
||||
|
||||
@@ -91,6 +106,7 @@ async function getSetting() {
|
||||
hcCategoryIds: [],
|
||||
scCategoryIds: [],
|
||||
zsCategoryIds: [],
|
||||
repurchaseTopExcludeCategoryIds: [],
|
||||
}
|
||||
}
|
||||
if (data) {
|
||||
|
||||
Reference in new issue
Block a user