Commit c09bf9d9c11fabd1112bdcaaafe6279b818f777f

Authored by fengwotao
1 parent 5e6df27d

feat(src/packages): 优化封装上传图片组件,移除重复代码

  1 +import TKUpload from './index.vue';
  2 +
  3 +export { TKUpload };
... ...
  1 +<template>
  2 + <n-upload
  3 + v-model:file-list="fileList"
  4 + :show-file-list="true"
  5 + :customRequest="customRequest"
  6 + :onBeforeUpload="beforeUploadHandle"
  7 + :onRemove="remove"
  8 + >
  9 + <n-upload-dragger>
  10 + <img v-if="uploadImageUrl" class="upload-show" :src="uploadImageUrl" alt="上传的图片" />
  11 + <div class="upload-img" v-show="!uploadImageUrl">
  12 + <img src="@/assets/images/canvas/noImage.png" />
  13 + <n-text class="upload-desc" depth="3">
  14 + 上传文件需小于 {{ uploadSizeFormat.size }}M ,格式为 {{ uploadSizeFormat.format }} 的文件
  15 + </n-text>
  16 + </div>
  17 + </n-upload-dragger>
  18 + </n-upload>
  19 +</template>
  20 +
  21 +<script lang="ts" setup name="TKUpload">
  22 +import { ref, PropType, nextTick } from 'vue'
  23 +import type { UploadCustomRequestOptions, UploadFileInfo } from 'naive-ui'
  24 +import { fetchRouteParamsLocation } from '@/utils'
  25 +import { uploadFile } from '@/api/external/contentSave/content'
  26 +import { FileTypeEnum } from '@/enums/external/fileTypeEnum'
  27 +
  28 +interface uploadSizeFormatIF {
  29 + size: number
  30 + format: string
  31 +}
  32 +
  33 +const props = defineProps({
  34 + uploadImageUrl: {
  35 + type: String as PropType<string>,
  36 + default: ''
  37 + },
  38 + uploadSizeFormat: {
  39 + type: Object as PropType<uploadSizeFormatIF>,
  40 + default: () => ({
  41 + size: 5,
  42 + format: 'png/jpg/jpeg/gif'
  43 + })
  44 + }
  45 +})
  46 +
  47 +const emit = defineEmits(['sendFile', 'removeFile'])
  48 +
  49 +const fileList = ref<UploadFileInfo[]>()
  50 +
  51 +// 自定义上传操作
  52 +const customRequest = (options: UploadCustomRequestOptions) => {
  53 + const { file } = options
  54 + nextTick(async () => {
  55 + if (file.file) {
  56 + const newNameFile = new File([file.file], `${fetchRouteParamsLocation()}_index_upload.png`, {
  57 + type: file.file.type
  58 + })
  59 + let uploadParams = new FormData()
  60 + uploadParams.append('file', newNameFile)
  61 + const uploadRes = await uploadFile(uploadParams)
  62 + if (!uploadRes) return
  63 + emit('sendFile', uploadRes?.fileStaticUri)
  64 + window['$message'].success('上传文件成功!')
  65 + } else {
  66 + window['$message'].error('上传文件失败,请稍后重试!')
  67 + }
  68 + })
  69 +}
  70 +
  71 +// 文件上传前置处理
  72 +const beforeUploadHandle = (file: UploadFileInfo) => {
  73 + fileList.value = []
  74 + const type = file.file?.type
  75 + const size = file.file?.size as number
  76 + const typeSuffix = type?.split('/')?.at(-1)?.toUpperCase() as keyof typeof FileTypeEnum
  77 + if (size > 1024 * 1024 * props.uploadSizeFormat.size) {
  78 + window['$message'].warning(`文件超出 ${props.uploadSizeFormat.size}M限制,请重新上传!`)
  79 + return false
  80 + }
  81 + if (!FileTypeEnum[typeSuffix]) {
  82 + window['$message'].warning('文件格式不符合,请重新上传!')
  83 + return false
  84 + }
  85 + return true
  86 +}
  87 +
  88 +//单个点击删除
  89 +const remove = () => {
  90 + fileList.value = []
  91 + emit('removeFile', true)
  92 +}
  93 +</script>
  94 +
  95 +<style lang="scss" scoped>
  96 +$uploadHeight: 193px;
  97 +@include deep() {
  98 + .n-card__content {
  99 + padding: 0;
  100 + overflow: hidden;
  101 + }
  102 + .n-upload-dragger {
  103 + padding: 5px;
  104 + }
  105 +}
  106 +.upload-show {
  107 + width: -webkit-fill-available;
  108 + height: $uploadHeight;
  109 + border-radius: 5px;
  110 +}
  111 +.upload-img {
  112 + display: flex;
  113 + flex-direction: column;
  114 + align-items: center;
  115 + img {
  116 + height: 150px;
  117 + }
  118 + .upload-desc {
  119 + padding: 10px 0;
  120 + }
  121 +}
  122 +</style>
... ...
  1 +// 文件上传时的格式映射
  2 +export enum FileTypeEnum {
  3 + // 文档
  4 + TXT = 'text/plain',
  5 + JSON = 'application/json',
  6 + // 图片
  7 + PNG = 'image/png',
  8 + JPEG = 'image/jpeg',
  9 + JPG = 'image/jpg',
  10 + GIF = 'image/gif',
  11 +}
... ...
... ... @@ -2,24 +2,11 @@
2 2 <collapse-item name="属性" :expanded="true">
3 3 <setting-item-box name="上传图片" :alone="true">
4 4 <setting-item>
5   - <n-card class="upload-box">
6   - <n-upload
7   - :show-file-list="false"
8   - v-model:file-list="uploadFileListRef"
9   - :customRequest="customRequest"
10   - :onBeforeUpload="beforeUploadHandle"
11   - >
12   - <n-upload-dragger>
13   - <img v-if="optionData.dataset" class="upload-show" :src="optionData.dataset" alt="背景" />
14   - <div class="upload-img" v-show="!optionData.dataset">
15   - <img src="@/assets/images/canvas/noImage.png" />
16   - <n-text class="upload-desc" depth="3">
17   - 图片需小于 {{ backgroundImageSize }}M ,格式为 png/jpg/gif 的文件
18   - </n-text>
19   - </div>
20   - </n-upload-dragger>
21   - </n-upload>
22   - </n-card>
  5 + <TKUpload
  6 + :uploadImageUrl="props.optionData.dataset"
  7 + @sendFile="handleSendFile"
  8 + @removeFile="handleRemoveFile"
  9 + />
23 10 </setting-item>
24 11 </setting-item-box>
25 12 <setting-item-box name="样式">
... ... @@ -39,14 +26,10 @@
39 26 </template>
40 27
41 28 <script setup lang="ts">
42   -import { PropType, ref, nextTick } from 'vue'
  29 +import { PropType } from 'vue'
43 30 import { option } from './config'
44 31 import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
45   -import { FileTypeEnum } from '@/enums/fileTypeEnum'
46   -import { uploadFile } from '@/api/external/contentSave/content'
47   -import { UploadCustomRequestOptions } from 'naive-ui'
48   -import { backgroundImageSize } from '@/settings/designSetting'
49   -import { fetchRouteParamsLocation } from '@/utils'
  32 +import { TKUpload } from '@/components/external/Common/TKUpload'
50 33
51 34 const props = defineProps({
52 35 optionData: {
... ... @@ -55,48 +38,12 @@ const props = defineProps({
55 38 }
56 39 })
57 40
58   -const uploadFileListRef = ref()
59   -
60   -// 上传图片前置处理
61   -// eslint-disable-next-line @typescript-eslint/ban-ts-comment
62   -//@ts-ignore
63   -const beforeUploadHandle = async ({ file }) => {
64   - uploadFileListRef.value = []
65   - const type = file.file.type
66   - const size = file.file.size
67   -
68   - if (size > 1024 * 1024 * backgroundImageSize) {
69   - window['$message'].warning(`图片超出 ${backgroundImageSize}M 限制,请重新上传!`)
70   - return false
71   - }
72   - if (type !== FileTypeEnum.PNG && type !== FileTypeEnum.JPEG && type !== FileTypeEnum.GIF) {
73   - window['$message'].warning('文件格式不符合,请重新上传!')
74   - return false
75   - }
76   - return true
  41 +const handleSendFile = (file: string) => {
  42 + if (!file) return
  43 + props.optionData.dataset = file
77 44 }
78 45
79   -// 自定义上传操作
80   -const customRequest = (options: UploadCustomRequestOptions) => {
81   - const { file } = options
82   - nextTick(async () => {
83   - if (file.file) {
84   - // 修改名称
85   - const newNameFile = new File([file.file], `${fetchRouteParamsLocation()}_index_background.png`, {
86   - type: file.file.type
87   - })
88   - let uploadParams = new FormData()
89   - uploadParams.append('file', newNameFile)
90   - const uploadRes = await uploadFile(uploadParams)
91   - if (uploadRes) {
92   - props.optionData.dataset = uploadRes?.fileStaticUri
93   - window['$message'].success('添加图片成功!')
94   - }
95   - } else {
96   - window['$message'].error('添加图片失败,请稍后重试!')
97   - }
98   - })
99   -}
  46 +const handleRemoveFile = (status: boolean) => (status ? (props.optionData.dataset = '') : null)
100 47
101 48 // 适应类型
102 49 const fitList = [
... ... @@ -122,35 +69,3 @@ const fitList = [
122 69 }
123 70 ]
124 71 </script>
125   -<style lang="scss" scoped>
126   -$uploadHeight: 193px;
127   -.upload-box {
128   - cursor: pointer;
129   - margin-bottom: 20px;
130   - @include deep() {
131   - .n-card__content {
132   - padding: 0;
133   - overflow: hidden;
134   - }
135   - .n-upload-dragger {
136   - padding: 5px;
137   - }
138   - }
139   - .upload-show {
140   - width: -webkit-fill-available;
141   - height: $uploadHeight;
142   - border-radius: 5px;
143   - }
144   - .upload-img {
145   - display: flex;
146   - flex-direction: column;
147   - align-items: center;
148   - img {
149   - height: 150px;
150   - }
151   - .upload-desc {
152   - padding: 10px 0;
153   - }
154   - }
155   -}
156   -</style>
... ...
... ... @@ -58,9 +58,7 @@ const isRtspProtocol = (url: string) => {
58 58 const getVideoTypeByUrl = (url = '') => {
59 59 try {
60 60 const { protocol, pathname } = new URL(url)
61   -
62 61 if (protocol.startsWith('rtsp:')) return VideoPlayerType.flv
63   -
64 62 const reg = /[^.]\w*$/
65 63 const mathValue = pathname.match(reg) || []
66 64 const ext = (mathValue[0] as keyof typeof VideoPlayerType) || 'webm'
... ... @@ -112,11 +110,9 @@ const { getResult } = useFingerprint()
112 110 async function getSource() {
113 111 fingerprintResult.value = await getResult()
114 112 let src = props.sourceSrc || ''
115   -
116 113 if (isRtspProtocol(props.sourceSrc!)) {
117 114 src = getOpenFlvPlayUrl(src, unref(fingerprintResult)?.visitorId || '')
118 115 }
119   -
120 116 return [
121 117 {
122 118 type: getVideoTypeByUrl(props.sourceSrc),
... ...
... ... @@ -2,29 +2,12 @@
2 2 <CollapseItem name="播放器配置" :expanded="true">
3 3 <setting-item-box name="上传图片" :alone="true">
4 4 <setting-item>
5   - <n-card class="upload-box">
6   - <n-upload
7   - :show-file-list="false"
8   - v-model:file-list="uploadFileListRef"
9   - :customRequest="customRequest"
10   - :onBeforeUpload="beforeUploadHandle"
11   - >
12   - <n-upload-dragger>
13   - <img v-if="optionData.poster" class="upload-show" :src="optionData.poster" alt="背景" />
14   - <div class="upload-img" v-show="!optionData.poster">
15   - <img src="@/assets/images/canvas/noImage.png" />
16   - <n-text class="upload-desc" depth="3">
17   - 图片需小于 {{ backgroundImageSize }}M ,格式为 png/jpg/gif 的文件
18   - </n-text>
19   - </div>
20   - </n-upload-dragger>
21   - </n-upload>
22   - </n-card>
  5 + <TKUpload :uploadImageUrl="optionData.poster" @sendFile="handleSendFile" @removeFile="handleRemoveFile" />
23 6 </setting-item>
24 7 </setting-item-box>
25 8 <setting-item-box name="源类型" :alone="true">
26 9 <setting-item>
27   - <n-radio-group @change="handleChecked" v-model:value="optionData.sourceType" name="radiogroup">
  10 + <n-radio-group @update:value="handleChecked" v-model:value="optionData.sourceType" name="radiogroup">
28 11 <n-space>
29 12 <n-radio v-for="(item, index) in sourceTypes" :key="item.value" :value="item.value">
30 13 {{ item.label }}
... ... @@ -55,7 +38,12 @@
55 38 </setting-item-box>
56 39 <setting-item-box v-if="optionData.sourceType === sourceTypeEnum.PLATFORM" name="视频" :alone="true">
57 40 <setting-item>
58   - <n-select @update:value="handleSelect" v-model:value="optionData.dataset" :options="videoOptions" />
  41 + <n-select
  42 + @update:value="handleSelect"
  43 + v-model:value="optionData.dataset"
  44 + :options="videoOptions"
  45 + placeholder="请选择视频地址"
  46 + />
59 47 </setting-item>
60 48 </setting-item-box>
61 49 <setting-item-box name="自动播放">
... ... @@ -67,15 +55,21 @@
67 55 </template>
68 56
69 57 <script setup lang="ts">
70   -import { PropType, ref, nextTick, onMounted } from 'vue'
  58 +import { PropType, ref, onMounted } from 'vue'
71 59 import { option, sourceTypeEnum } from './config'
72 60 import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
73   -import { FileTypeEnum } from '@/enums/fileTypeEnum'
74   -import { uploadFile } from '@/api/external/contentSave/content'
75   -import { UploadCustomRequestOptions, NTreeSelect } from 'naive-ui'
76   -import { backgroundImageSize } from '@/settings/designSetting'
77   -import { fetchRouteParamsLocation } from '@/utils'
  61 +import { NTreeSelect } from 'naive-ui'
78 62 import { getOrganizationList, getVideoList, getVideoUrl } from '@/api/external/common/index'
  63 +import { TKUpload } from '@/components/external/Common/TKUpload'
  64 +
  65 +interface videoListIF {
  66 + name: string
  67 + accessMode: number
  68 + id: string
  69 + videoUrl: string
  70 + label: string
  71 + value: string
  72 +}
79 73
80 74 const props = defineProps({
81 75 optionData: {
... ... @@ -84,8 +78,6 @@ const props = defineProps({
84 78 }
85 79 })
86 80
87   -const uploadFileListRef = ref()
88   -
89 81 const sourceTypes = [
90 82 {
91 83 value: 'custom',
... ... @@ -99,7 +91,7 @@ const sourceTypes = [
99 91
100 92 const originationOption = ref([])
101 93
102   -const videoOptions = ref([])
  94 +const videoOptions = ref<videoListIF[]>([])
103 95
104 96 const getOriginationList = async () => {
105 97 const res = await getOrganizationList()
... ... @@ -113,7 +105,8 @@ const handleUpdateTreeValue = (value: string) => {
113 105
114 106 const getVideoLists = async (organizationId: string) => {
115 107 const res = await getVideoList({ organizationId })
116   - videoOptions.value = res?.data?.map((item: any) => ({
  108 + if (!res) return
  109 + videoOptions.value = res?.data?.map((item: videoListIF) => ({
117 110 label: item.name,
118 111 value: item.accessMode === 1 ? item.id : item.videoUrl,
119 112 id: item.id,
... ... @@ -128,16 +121,16 @@ const getVideoUrlById = async (id: string) => {
128 121 props.optionData.url = url
129 122 }
130 123
131   -const handleChecked = ({ target }: any) => {
  124 +const handleChecked = (value: string) => {
132 125 props.optionData.dataset = ''
133   - const { value } = target
134 126 if (value === sourceTypeEnum.PLATFORM) {
135 127 getOriginationList()
136 128 }
137 129 }
138 130
139   -const handleSelect = (value: string, e: any) => {
  131 +const handleSelect = (_: string, e: videoListIF) => {
140 132 const { accessMode, id } = e
  133 + //1表示,需要从服务端调取接口换取播放的地址,0则不需要
141 134 if (accessMode === 1) {
142 135 getVideoUrlById(id)
143 136 } else {
... ... @@ -154,76 +147,10 @@ onMounted(() => {
154 147 }
155 148 })
156 149
157   -// 上传图片前置处理
158   -// eslint-disable-next-line @typescript-eslint/ban-ts-comment
159   -//@ts-ignore
160   -const beforeUploadHandle = async ({ file }) => {
161   - uploadFileListRef.value = []
162   - const type = file.file.type
163   - const size = file.file.size
164   -
165   - if (size > 1024 * 1024 * backgroundImageSize) {
166   - window['$message'].warning(`图片超出 ${backgroundImageSize}M 限制,请重新上传!`)
167   - return false
168   - }
169   - if (type !== FileTypeEnum.PNG && type !== FileTypeEnum.JPEG && type !== FileTypeEnum.GIF) {
170   - window['$message'].warning('文件格式不符合,请重新上传!')
171   - return false
172   - }
173   - return true
  150 +const handleSendFile = (file: string) => {
  151 + if (!file) return
  152 + props.optionData.poster = file
174 153 }
175 154
176   -// 自定义上传操作
177   -const customRequest = (options: UploadCustomRequestOptions) => {
178   - const { file } = options
179   - nextTick(async () => {
180   - if (file.file) {
181   - // 修改名称
182   - const newNameFile = new File([file.file], `${fetchRouteParamsLocation()}_index_background.png`, {
183   - type: file.file.type
184   - })
185   - let uploadParams = new FormData()
186   - uploadParams.append('file', newNameFile)
187   - const uploadRes = await uploadFile(uploadParams)
188   - if (uploadRes) {
189   - props.optionData.poster = uploadRes?.fileStaticUri
190   - window['$message'].success('添加图片成功!')
191   - }
192   - } else {
193   - window['$message'].error('添加图片失败,请稍后重试!')
194   - }
195   - })
196   -}
  155 +const handleRemoveFile = (status: boolean) => (status ? (props.optionData.poster = '') : null)
197 156 </script>
198   -<style lang="scss" scoped>
199   -$uploadHeight: 193px;
200   -.upload-box {
201   - cursor: pointer;
202   - margin-bottom: 20px;
203   - @include deep() {
204   - .n-card__content {
205   - padding: 0;
206   - overflow: hidden;
207   - }
208   - .n-upload-dragger {
209   - padding: 5px;
210   - }
211   - }
212   - .upload-show {
213   - width: -webkit-fill-available;
214   - height: $uploadHeight;
215   - border-radius: 5px;
216   - }
217   - .upload-img {
218   - display: flex;
219   - flex-direction: column;
220   - align-items: center;
221   - img {
222   - height: 150px;
223   - }
224   - .upload-desc {
225   - padding: 10px 0;
226   - }
227   - }
228   -}
229   -</style>
... ...