feat:更新上传图片和视频组件
This commit is contained in:
1
.env.development
Normal file
1
.env.development
Normal file
@@ -0,0 +1 @@
|
||||
VITE_API_ALIST_PATH=/local/test
|
||||
1
.env.production
Normal file
1
.env.production
Normal file
@@ -0,0 +1 @@
|
||||
VITE_API_ALIST_PATH=/local
|
||||
@@ -12,8 +12,8 @@
|
||||
<el-card class="record-card">
|
||||
<span class="record-content">完成人:{{ item.person }}</span>
|
||||
<el-image v-if="item.imageUrl"
|
||||
:src="AListPath + item.imageUrl"
|
||||
:preview-src-list="[AListPath + item.imageUrl]"
|
||||
:src="AListUrl + item.imageUrl"
|
||||
:preview-src-list="[AListUrl + item.imageUrl]"
|
||||
fit="contain" alt="暂无图片" class="record-image"/>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFoodStore } from '@/store/food.ts'
|
||||
import { AListPath } from '@/utils'
|
||||
import { AListUrl } from '@/utils'
|
||||
import { SvgIcon } from 'vue3-common'
|
||||
|
||||
const foodStore = useFoodStore()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="life-record-card card-item">
|
||||
<el-image v-if="props.foodItem?.recordList.length > 0"
|
||||
:src="AListPath + props.foodItem?.recordList[0].imageUrl"
|
||||
:src="AListUrl + props.foodItem?.recordList[0].imageUrl"
|
||||
:preview-src-list="previewImageList"
|
||||
:initial-index="0"
|
||||
show-progress
|
||||
@@ -68,7 +68,7 @@ import { IFoodRecipe } from '@/types/food.ts'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { formatDate } from 'vue3-common/utils/dateUtil'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import { AListPath } from '@/utils'
|
||||
import { AListUrl } from '@/utils'
|
||||
|
||||
const router = useRouter()
|
||||
const foodStore = useFoodStore()
|
||||
@@ -90,7 +90,7 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
const previewImageList = computed(() => {
|
||||
return props.foodItem?.recordList.map((item) => `${AListPath}${item.imageUrl}`)
|
||||
return props.foodItem?.recordList.map((item) => `${AListUrl}${item.imageUrl}`)
|
||||
})
|
||||
|
||||
const editFoodRecipeClick = async () => {
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
<!-- 单媒体内容(图片优先于视频) -->
|
||||
<el-image
|
||||
v-if="props.item?.imageUrl"
|
||||
:src="AListPath + props.item?.imageUrl"
|
||||
:preview-src-list="[AListPath + props.item?.imageUrl]"
|
||||
:src="AListUrl + props.item?.imageUrl"
|
||||
:preview-src-list="[AListUrl + props.item?.imageUrl]"
|
||||
fit="contain"
|
||||
class="media-content"/>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
v-if="props.item?.videoUrl"
|
||||
controls
|
||||
class="media-content">
|
||||
<source :src="AListPath + props.item?.videoUrl" type="video/mp4">
|
||||
<source :src="AListUrl + props.item?.videoUrl" type="video/mp4">
|
||||
</video>
|
||||
|
||||
<!-- 展开/收起按钮 -->
|
||||
@@ -76,7 +76,7 @@ import { deepCopyObject } from 'vue3-common/utils/dataUtil'
|
||||
import { useJournalStore } from '@/store/journal.ts'
|
||||
import { useAppStore } from '@/store/app.ts'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { AListPath } from '@/utils'
|
||||
import { AListUrl } from '@/utils'
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="life-record-card card-item">
|
||||
<el-image :src="AListPath + props.productItem?.imageUrl"
|
||||
:preview-src-list="[AListPath + props.productItem?.imageUrl]"
|
||||
<el-image :src="AListUrl + props.productItem?.imageUrl"
|
||||
:preview-src-list="[AListUrl + props.productItem?.imageUrl]"
|
||||
fit="contain" alt="暂无成果">
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
@@ -42,11 +42,6 @@
|
||||
<i class="fa-solid fa-chart-line" style="color: #FFA500"></i>
|
||||
{{ props.productItem.averagePrice }}元/天
|
||||
</div>
|
||||
|
||||
<div class="info-item">
|
||||
<i class="fa-solid fa-location-dot"></i>
|
||||
{{ props.productItem.channel }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-list">
|
||||
<div class="info-item">
|
||||
@@ -70,7 +65,7 @@ import { defineProps, onMounted, PropType } from 'vue'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import { IProduct } from '@/types/product.ts'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { AListPath } from '@/utils'
|
||||
import { AListUrl } from '@/utils'
|
||||
|
||||
const productStore = useProductStore()
|
||||
const router = useRouter()
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
<el-card class="record-card">
|
||||
<span class="record-content">旅行人:{{ item.persons.join('-') }}</span>
|
||||
<el-image v-for="(image, index) in item.imageList" :key="index"
|
||||
:src="AListPath + image"
|
||||
:preview-src-list="[AListPath + image]"
|
||||
:src="AListUrl + image"
|
||||
:preview-src-list="[AListUrl + image]"
|
||||
fit="contain" alt="暂无图片" class="record-image"/>
|
||||
|
||||
<video v-for="(video, index) in item.videoList"
|
||||
:key="index" controls style="width: 60%;min-height: 200px;">
|
||||
<source :src="AListPath + video" type="video/mp4">
|
||||
<source :src="AListUrl + video" type="video/mp4">
|
||||
您的浏览器不支持 HTML5 视频
|
||||
</video>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<script setup lang="ts">
|
||||
import { SvgIcon } from 'vue3-common'
|
||||
import { useTravelStore } from '@/store/travel.ts'
|
||||
import { AListPath } from '@/utils'
|
||||
import { AListUrl } from '@/utils'
|
||||
|
||||
const travelStore = useTravelStore()
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<el-carousel v-if="props.travelItem?.recordList.length > 0"
|
||||
arrow="always" @change="changeTravelEvent">
|
||||
<el-carousel-item v-for="(item, index) in props.travelItem?.recordList" :key="index">
|
||||
<el-image :src="AListPath + item.imageList[0]"
|
||||
<el-image :src="AListUrl + item.imageList[0]"
|
||||
fit="contain" alt="暂无图片">
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
@@ -70,7 +70,7 @@ import { useRouter } from 'vue-router'
|
||||
import { formatDate } from 'vue3-common/utils/dateUtil'
|
||||
import { ITravelSpot } from '@/types/travel.ts'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import { AListPath } from '@/utils'
|
||||
import { AListUrl } from '@/utils'
|
||||
import { parsePerson } from '@/utils/home/travelUtil.ts'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { ElLoading, ElMessage, UploadRawFile, UploadRequestOptions } from 'element-plus'
|
||||
import { getFileExtension, getFileHashName, validateImage } from '@/utils/home/file.ts'
|
||||
import { ElLoading, ElMessage } from 'element-plus'
|
||||
import type { UploadRawFile, UploadRequestOptions } from 'element-plus'
|
||||
import { getFileExtension, getFileHashName, validateImage, compressOptions, validateVideo } from '@/utils/file.ts'
|
||||
import { compressImage } from 'vue3-common/utils/fileUtil'
|
||||
import { compressOptions } from '@/utils'
|
||||
import { uploadAListFileApi } from '@/apis/file.ts'
|
||||
import { AListPath } from '@/utils'
|
||||
|
||||
export const beforeUploadImage = (rawFile: UploadRawFile): boolean => {
|
||||
const maxFileMax = 1024 * 1024 * 10
|
||||
@@ -23,7 +24,27 @@ export const beforeUploadImage = (rawFile: UploadRawFile): boolean => {
|
||||
return true
|
||||
}
|
||||
|
||||
export const httpRequestFile = async (basePath: string, options: UploadRequestOptions) => {
|
||||
export const beforeUploadVideo = (rawFile: UploadRawFile): boolean => {
|
||||
const maxFileMax = 1024 * 1024 * 200
|
||||
const fileType = rawFile.type
|
||||
const fileName = rawFile.name
|
||||
const fileExtension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase()
|
||||
|
||||
if (!validateVideo(fileType, fileExtension)) {
|
||||
ElMessage.error('请上传视频')
|
||||
return false
|
||||
}
|
||||
|
||||
if (rawFile.size > maxFileMax) {
|
||||
ElMessage.error('请上传200M以内的文件!')
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
export const httpRequestFile = async (basePath: string,
|
||||
options: UploadRequestOptions, isCompress = true) => {
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '文件上传中 请等待',
|
||||
@@ -31,11 +52,15 @@ export const httpRequestFile = async (basePath: string, options: UploadRequestOp
|
||||
})
|
||||
|
||||
try {
|
||||
const filePath = `/local/${basePath}/${getFileHashName(options.file.name)}.${getFileExtension(options.file.name)}`
|
||||
const compressFile = await compressImage(options.file, compressOptions)
|
||||
|
||||
const filePath = `${AListPath}/${basePath}/${getFileHashName(options.file)}.${getFileExtension(options.file.name)}`
|
||||
const data = new FormData()
|
||||
|
||||
if (isCompress) {
|
||||
const compressFile = await compressImage(options.file, compressOptions)
|
||||
data.append('file', compressFile)
|
||||
} else {
|
||||
data.append('file', options.file)
|
||||
}
|
||||
data.append('filePath', filePath)
|
||||
|
||||
const result = await uploadAListFileApi(data)
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { hashSHA256 } from 'vue3-common/utils/cryptoUtil'
|
||||
|
||||
export const getFileHashName = (name: string) => {
|
||||
return hashSHA256(name)
|
||||
export const getFileHashName = (file: File) => {
|
||||
return hashSHA256(`${file.name}_${file.lastModified}`)
|
||||
}
|
||||
|
||||
export const getFileExtension = (name: string) => {
|
||||
return name.substring(name.lastIndexOf('.') + 1).toLowerCase()
|
||||
}
|
||||
|
||||
export const getFilePath = (basePath: string, name: string) => {
|
||||
return `/local/${basePath}/${getFileHashName(name)}.${getFileExtension(name)}`
|
||||
export const compressOptions = {
|
||||
quality: 0.7,
|
||||
maxHeight: 800,
|
||||
maxWidth: 600
|
||||
}
|
||||
|
||||
export const validateExcel = (fileType: string, fileExtension: string): boolean => {
|
||||
@@ -29,6 +31,8 @@ export const validateExcel = (fileType: string, fileExtension: string): boolean
|
||||
|
||||
export const acceptImageTypes = '.jpg,.jpeg,.png,.gif,.webp,.bmp,.JPG,.JPEG,.PNG,.GIF,.WEBP,.BMP'
|
||||
|
||||
export const acceptVideoTypes = '.mp4,.mov,.avi,.wmv,.flv,.webm,.mpeg,.mpg,.m4v,.3gp,.3g2,.mkv,.ts,.mts,.m2ts'
|
||||
|
||||
export const validateImage = (fileType: string, fileExtension: string): boolean => {
|
||||
// 常见的图片 MIME 类型
|
||||
const imageMimeTypes = [
|
||||
17
src/utils/home/journalUtil.ts
Normal file
17
src/utils/home/journalUtil.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export const journalCategoryTypeList = ['生活', '工作', '其他']
|
||||
|
||||
export const journalWeatherTypeList = [{
|
||||
value: 'sunny',
|
||||
label: '晴'
|
||||
}, {
|
||||
value: 'rainy',
|
||||
label: '雨'
|
||||
}, {
|
||||
value: 'snowy',
|
||||
label: '雪'
|
||||
}, {
|
||||
value: 'cloudy',
|
||||
label: '阴'
|
||||
}]
|
||||
|
||||
export const journalMoodTypeList = ['😀', '🙁', '😡']
|
||||
@@ -28,13 +28,9 @@ export const fileServiceUrl = '/home-api/file'
|
||||
*/
|
||||
export const serviceFileRootPath = '/home-api/'
|
||||
|
||||
export const AListPath = '/alist-api/'
|
||||
export const AListUrl = '/alist-api/'
|
||||
|
||||
export const compressOptions = {
|
||||
quality: 0.7,
|
||||
maxHeight: 800,
|
||||
maxWidth: 600
|
||||
}
|
||||
export const AListPath = import.meta.env.VITE_API_ALIST_PATH
|
||||
|
||||
/**
|
||||
* 获取assets静态资源
|
||||
|
||||
@@ -71,11 +71,11 @@ import { ref, reactive, onMounted } from 'vue'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import { ElMessage, ElMessageBox, FormRules, UploadProps, UploadRawFile, UploadRequestOptions, UploadUserFile } from 'element-plus'
|
||||
import { foodRecordRules } from '@/utils/element/elRules.ts'
|
||||
import { AListPath } from '@/utils'
|
||||
import { AListUrl } from '@/utils'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import { useAppStore } from '@/store/app.ts'
|
||||
import { beforeUploadImage, httpRequestFile } from '@/utils/element/elUpload.ts'
|
||||
import { acceptImageTypes } from '@/utils/home/file.ts'
|
||||
import { acceptImageTypes } from '@/utils/file.ts'
|
||||
|
||||
const rules = reactive<FormRules>(foodRecordRules)
|
||||
|
||||
@@ -97,7 +97,7 @@ const initImageFileList = () => {
|
||||
if (imageUrl) {
|
||||
imageFileList.value.push({
|
||||
name: 'image',
|
||||
url: `${AListPath}${imageUrl}`
|
||||
url: `${AListUrl}${imageUrl}`
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -107,11 +107,11 @@ const beforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||
}
|
||||
|
||||
const httpRequest: UploadProps['httpRequest'] = async (options: UploadRequestOptions): Promise<any> => {
|
||||
await httpRequestFile(foodStore.foodImagePath, options)
|
||||
return await httpRequestFile(foodStore.foodImagePath, options)
|
||||
}
|
||||
|
||||
const handleSuccess = (response: string) => {
|
||||
foodStore.currentFoodRecord.imageUrl = `p/${response}`
|
||||
foodStore.currentFoodRecord.imageUrl = `p${response}`
|
||||
}
|
||||
|
||||
const handleExceed: UploadProps['onExceed'] = () => {
|
||||
@@ -133,6 +133,7 @@ const confirmClick = () => {
|
||||
formRef.value.validate().then(() => {
|
||||
foodStore.handleFoodRecordApi(foodStore.currentFoodRecord)
|
||||
history.back()
|
||||
appStore.isShowMobileBack = false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<el-radio-group v-model="journalStore.currentJournal.category"
|
||||
placeholder="请选择分类" clearable>
|
||||
<el-radio
|
||||
v-for="(item, index) in categoryTypeList"
|
||||
v-for="(item, index) in journalCategoryTypeList"
|
||||
:key="index" :label="item" :value="item"
|
||||
/>
|
||||
</el-radio-group>
|
||||
@@ -46,7 +46,7 @@
|
||||
<el-radio-group v-model="journalStore.currentJournal.weather"
|
||||
placeholder="请选择天气" clearable>
|
||||
<el-radio
|
||||
v-for="(item, index) in weatherTypeList"
|
||||
v-for="(item, index) in journalWeatherTypeList"
|
||||
:key="index" :value="item.value"
|
||||
>
|
||||
<template #default>
|
||||
@@ -60,27 +60,53 @@
|
||||
<el-radio-group v-model="journalStore.currentJournal.mood"
|
||||
placeholder="请选择心情" clearable>
|
||||
<el-radio
|
||||
v-for="(item, index) in moodTypeList"
|
||||
v-for="(item, index) in journalMoodTypeList"
|
||||
:key="index" :value="item" :label="item"
|
||||
/>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="图片">
|
||||
<upload-image v-model="journalStore.currentJournal.imageUrl"
|
||||
:service-url="fileServiceUrl"
|
||||
:image-limit="1"
|
||||
:service-file-root-path="serviceFileRootPath"
|
||||
:image-path="journalStore.journalImagePath"/>
|
||||
<el-upload
|
||||
v-model:file-list="imageFileList"
|
||||
list-type="picture-card"
|
||||
:accept="acceptImageTypes"
|
||||
:limit="1"
|
||||
:before-upload="beforeImageUpload"
|
||||
:http-request="httpImageRequest"
|
||||
:on-success="handleImageSuccess"
|
||||
:on-exceed="handleImageExceed"
|
||||
:before-remove="beforeRemove"
|
||||
:on-remove="handleImageRemove"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
请上传小于10M的图片
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="视频">
|
||||
<upload-video v-model="journalStore.currentJournal.videoUrl"
|
||||
:service-url="fileServiceUrl"
|
||||
:image-limit="1"
|
||||
:service-file-root-path="serviceFileRootPath"
|
||||
:video-path="journalStore.journalVideoPath"
|
||||
style="width: 100%;"/>
|
||||
<el-upload
|
||||
v-model:file-list="videoFileList"
|
||||
:accept="acceptVideoTypes"
|
||||
:limit="1"
|
||||
:before-upload="beforeVideoUpload"
|
||||
:http-request="httpVideoRequest"
|
||||
:on-success="handleVideoSuccess"
|
||||
:on-exceed="handleVideoExceed"
|
||||
:before-remove="beforeRemove"
|
||||
:on-remove="handleVideoRemove"
|
||||
>
|
||||
<el-button type="primary">点击上传</el-button>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
请上传小于200M的视频
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@@ -95,43 +121,97 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Location } from '@element-plus/icons-vue'
|
||||
import { Location, Plus } from '@element-plus/icons-vue'
|
||||
import { useJournalStore } from '@/store/journal.ts'
|
||||
import { useAppStore } from '@/store/app.ts'
|
||||
import { FormRules } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox, FormRules, UploadProps, UploadRawFile, UploadRequestOptions, UploadUserFile } from 'element-plus'
|
||||
import { journalRules } from '@/utils/element/elRules.ts'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import { fileServiceUrl, serviceFileRootPath } from '@/utils'
|
||||
import { UploadImage, UploadVideo, SvgIcon } from 'vue3-common'
|
||||
import { AListUrl } from '@/utils'
|
||||
import { SvgIcon } from 'vue3-common'
|
||||
import { acceptImageTypes, acceptVideoTypes } from '@/utils/file.ts'
|
||||
import { beforeUploadImage, beforeUploadVideo, httpRequestFile } from '@/utils/element/elUpload.ts'
|
||||
import { journalCategoryTypeList, journalMoodTypeList, journalWeatherTypeList } from '@/utils/home/journalUtil.ts'
|
||||
|
||||
const formRef = ref()
|
||||
const rules = reactive<FormRules>(journalRules)
|
||||
const journalStore = useJournalStore()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const categoryTypeList = ['生活', '工作', '其他']
|
||||
|
||||
const weatherTypeList = [{
|
||||
value: 'sunny',
|
||||
label: '晴'
|
||||
}, {
|
||||
value: 'rainy',
|
||||
label: '雨'
|
||||
}, {
|
||||
value: 'snowy',
|
||||
label: '雪'
|
||||
}, {
|
||||
value: 'cloudy',
|
||||
label: '阴'
|
||||
}]
|
||||
|
||||
const moodTypeList = ['😀', '🙁', '😡']
|
||||
const imageFileList = ref<UploadUserFile[]>([])
|
||||
const videoFileList = ref<UploadUserFile[]>([])
|
||||
|
||||
onMounted(async () => {
|
||||
appStore.isShowMobileBack = true
|
||||
|
||||
initFileList()
|
||||
})
|
||||
|
||||
const initFileList = () => {
|
||||
imageFileList.value = []
|
||||
videoFileList.value = []
|
||||
|
||||
const { imageUrl, videoUrl } = journalStore.currentJournal
|
||||
if (imageUrl) {
|
||||
imageFileList.value.push({
|
||||
name: 'image',
|
||||
url: `${AListUrl}${imageUrl}`
|
||||
})
|
||||
}
|
||||
|
||||
if (videoUrl) {
|
||||
videoFileList.value.push({
|
||||
name: 'video',
|
||||
url: `${AListUrl}${videoUrl}`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const beforeImageUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||
return beforeUploadImage(rawFile)
|
||||
}
|
||||
|
||||
const httpImageRequest: UploadProps['httpRequest'] = async (options: UploadRequestOptions): Promise<any> => {
|
||||
return await httpRequestFile(journalStore.journalImagePath, options)
|
||||
}
|
||||
|
||||
const handleImageSuccess = (response: string) => {
|
||||
journalStore.currentJournal.imageUrl = `p${response}`
|
||||
}
|
||||
|
||||
const handleImageExceed: UploadProps['onExceed'] = () => {
|
||||
ElMessage.warning('最多上传1张图片')
|
||||
}
|
||||
|
||||
const handleImageRemove: UploadProps['onRemove'] = () => {
|
||||
journalStore.currentJournal.imageUrl = ''
|
||||
}
|
||||
|
||||
const beforeRemove: UploadProps['beforeRemove'] = () => {
|
||||
return ElMessageBox.confirm('确认删除该文件?').then(() => true, () => false)
|
||||
}
|
||||
|
||||
const beforeVideoUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||
return beforeUploadVideo(rawFile)
|
||||
}
|
||||
|
||||
const httpVideoRequest: UploadProps['httpRequest'] = async (options: UploadRequestOptions): Promise<any> => {
|
||||
return await httpRequestFile(journalStore.journalImagePath, options, false)
|
||||
}
|
||||
|
||||
const handleVideoSuccess = (response: string) => {
|
||||
journalStore.currentJournal.videoUrl = `p${response}`
|
||||
}
|
||||
|
||||
const handleVideoExceed: UploadProps['onExceed'] = () => {
|
||||
ElMessage.warning('最多上传1个视频')
|
||||
}
|
||||
|
||||
const handleVideoRemove: UploadProps['onRemove'] = () => {
|
||||
journalStore.currentJournal.videoUrl = ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击确认按钮
|
||||
*/
|
||||
|
||||
@@ -47,19 +47,25 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="图片">
|
||||
<upload-image v-model="ledgerStore.currentLedgerRecord.imageUrl"
|
||||
:image-limit="1"
|
||||
:service-url="fileServiceUrl"
|
||||
:service-file-root-path="serviceFileRootPath"
|
||||
:image-path="ledgerStore.ledgerImagePath"/>
|
||||
|
||||
<el-image
|
||||
v-if="ledgerStore.currentLedgerRecord.imageUrl"
|
||||
:src="serviceFileRootPath + ledgerStore.currentLedgerRecord.imageUrl"
|
||||
:preview-src-list="[serviceFileRootPath + ledgerStore.currentLedgerRecord.imageUrl]"
|
||||
show-progress
|
||||
fit="cover"
|
||||
/>
|
||||
<el-upload
|
||||
v-model:file-list="imageFileList"
|
||||
list-type="picture-card"
|
||||
:accept="acceptImageTypes"
|
||||
:limit="1"
|
||||
:before-upload="beforeUpload"
|
||||
:http-request="httpRequest"
|
||||
:on-success="handleSuccess"
|
||||
:on-exceed="handleExceed"
|
||||
:before-remove="beforeRemove"
|
||||
:on-remove="handleRemove"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
请上传小于10M的图片
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注">
|
||||
@@ -80,25 +86,66 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { UploadImage } from 'vue3-common'
|
||||
import { AmountInput } from 'vue3-common'
|
||||
import { useLedgerStore } from '@/store/ledger.ts'
|
||||
import { useAppStore } from '@/store/app.ts'
|
||||
import { FormRules } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox, FormRules, UploadProps, UploadRawFile, UploadRequestOptions, UploadUserFile } from 'element-plus'
|
||||
import { ledgerRules } from '@/utils/element/elRules.ts'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import { fileServiceUrl, serviceFileRootPath } from '@/utils'
|
||||
import { AListUrl } from '@/utils'
|
||||
import { acceptImageTypes } from '@/utils/file.ts'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import { beforeUploadImage, httpRequestFile } from '@/utils/element/elUpload.ts'
|
||||
|
||||
const formRef = ref()
|
||||
const rules = reactive<FormRules>(ledgerRules)
|
||||
const imageFileList = ref<UploadUserFile[]>([])
|
||||
|
||||
const ledgerStore = useLedgerStore()
|
||||
const appStore = useAppStore()
|
||||
|
||||
onMounted(async () => {
|
||||
appStore.isShowMobileBack = true
|
||||
|
||||
initImageFileList()
|
||||
})
|
||||
|
||||
const initImageFileList = () => {
|
||||
imageFileList.value = []
|
||||
const { imageUrl } = ledgerStore.currentLedgerRecord
|
||||
if (imageUrl) {
|
||||
imageFileList.value.push({
|
||||
name: 'image',
|
||||
url: `${AListUrl}${imageUrl}`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||
return beforeUploadImage(rawFile)
|
||||
}
|
||||
|
||||
const httpRequest: UploadProps['httpRequest'] = async (options: UploadRequestOptions): Promise<any> => {
|
||||
return await httpRequestFile(ledgerStore.ledgerImagePath, options)
|
||||
}
|
||||
|
||||
const handleSuccess = (response: string) => {
|
||||
ledgerStore.currentLedgerRecord.imageUrl = `p${response}`
|
||||
}
|
||||
|
||||
const handleExceed: UploadProps['onExceed'] = () => {
|
||||
ElMessage.warning('最多上传1张图片')
|
||||
}
|
||||
|
||||
const handleRemove: UploadProps['onRemove'] = () => {
|
||||
ledgerStore.currentLedgerRecord.imageUrl = ''
|
||||
}
|
||||
|
||||
const beforeRemove: UploadProps['beforeRemove'] = () => {
|
||||
return ElMessageBox.confirm('确认删除该文件?').then(() => true, () => false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击确认按钮
|
||||
*/
|
||||
|
||||
@@ -61,11 +61,25 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="物品图片">
|
||||
<upload-image v-model="productStore.currentProduct.imageUrl"
|
||||
:image-limit="1"
|
||||
:service-url="fileServiceUrl"
|
||||
:service-file-root-path="serviceFileRootPath"
|
||||
:image-path="productStore.productImagePath"/>
|
||||
<el-upload
|
||||
v-model:file-list="imageFileList"
|
||||
list-type="picture-card"
|
||||
:accept="acceptImageTypes"
|
||||
:limit="1"
|
||||
:before-upload="beforeUpload"
|
||||
:http-request="httpRequest"
|
||||
:on-success="handleSuccess"
|
||||
:on-exceed="handleExceed"
|
||||
:before-remove="beforeRemove"
|
||||
:on-remove="handleRemove"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
请上传小于10M的图片
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@@ -77,23 +91,64 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { UploadImage } from 'vue3-common'
|
||||
import { useProductStore } from '@/store/product.ts'
|
||||
import { useAppStore } from '@/store/app.ts'
|
||||
import { FormRules } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox, FormRules, UploadProps, UploadRawFile, UploadRequestOptions, UploadUserFile } from 'element-plus'
|
||||
import { productRules } from '@/utils/element/elRules.ts'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { fileServiceUrl, serviceFileRootPath } from '@/utils'
|
||||
import { AListUrl } from '@/utils'
|
||||
import { acceptImageTypes } from '@/utils/file.ts'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import { beforeUploadImage, httpRequestFile } from '@/utils/element/elUpload.ts'
|
||||
|
||||
const formRef = ref()
|
||||
const rules = reactive<FormRules>(productRules)
|
||||
const productStore = useProductStore()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const imageFileList = ref<UploadUserFile[]>([])
|
||||
|
||||
onMounted(async () => {
|
||||
appStore.isShowMobileBack = true
|
||||
|
||||
initImageFileList()
|
||||
})
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
|
||||
return beforeUploadImage(rawFile)
|
||||
}
|
||||
|
||||
const httpRequest: UploadProps['httpRequest'] = async (options: UploadRequestOptions): Promise<any> => {
|
||||
return await httpRequestFile(productStore.productImagePath, options)
|
||||
}
|
||||
|
||||
const handleSuccess = (response: string) => {
|
||||
productStore.currentProduct.imageUrl = `p${response}`
|
||||
}
|
||||
|
||||
const handleExceed: UploadProps['onExceed'] = () => {
|
||||
ElMessage.warning('最多上传1张图片')
|
||||
}
|
||||
|
||||
const handleRemove: UploadProps['onRemove'] = () => {
|
||||
productStore.currentProduct.imageUrl = ''
|
||||
}
|
||||
|
||||
const beforeRemove: UploadProps['beforeRemove'] = () => {
|
||||
return ElMessageBox.confirm('确认删除该文件?').then(() => true, () => false)
|
||||
}
|
||||
|
||||
const initImageFileList = () => {
|
||||
imageFileList.value = []
|
||||
const { imageUrl } = productStore.currentProduct
|
||||
if (imageUrl) {
|
||||
imageFileList.value.push({
|
||||
name: 'image',
|
||||
url: `${AListUrl}${imageUrl}`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击确认按钮
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user