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