mirror of
https://github.com/keven1024/015.git
synced 2026-05-26 07:08:02 +00:00
refactor(front): update file handling components to use typed props for better type safety and maintainability
This commit is contained in:
@@ -15,11 +15,12 @@ import { cx } from 'class-variance-authority'
|
||||
import { isObject } from 'lodash-es'
|
||||
import showDrawer from '@/lib/showDrawer'
|
||||
import FileShareHandle from '@/components/Preprocessing/FileShareHandle.vue'
|
||||
import type { FileShareHandleProps } from '../Preprocessing/types'
|
||||
const { t } = useI18n()
|
||||
const props = defineProps<{
|
||||
hide: () => void
|
||||
file: File[]
|
||||
onFileHandle: ({ type, config }: { type: string; config: any }) => void
|
||||
onFileHandle: (props: FileShareHandleProps) => void
|
||||
}>()
|
||||
|
||||
const isImage = computed(() => props.file.every((r) => r?.type?.startsWith('image/')))
|
||||
|
||||
@@ -14,9 +14,10 @@ import dayjs from 'dayjs'
|
||||
import showDrawer from '~/lib/showDrawer'
|
||||
import FileUploadSpeedInfoView from './FileUploadSpeedInfoView.vue'
|
||||
import getFileChunk from '~/lib/getFileChunk'
|
||||
import type { FileHandleKey } from '~/components/Preprocessing/types'
|
||||
|
||||
const props = defineProps<{
|
||||
data: { file: File[]; config: any; handle_type: string }
|
||||
data: { file: File[]; config: Record<string, any>; handle_type: FileHandleKey }
|
||||
}>()
|
||||
const emit = defineEmits<{
|
||||
(e: 'change', key: string): void
|
||||
|
||||
@@ -3,10 +3,11 @@ import SwitchField from '../Field/SwitchField.vue'
|
||||
import InputField from '../Field/InputField.vue'
|
||||
import SelectField from '../Field/SelectField.vue'
|
||||
import FormButton from '../Field/FormButton.vue'
|
||||
import type { FileShareHandleProps } from './types'
|
||||
const props = defineProps<{
|
||||
hide: () => void
|
||||
file: File[]
|
||||
onFileHandle: ({ type, config }: { type: string; config: any }) => void
|
||||
onFileHandle: (props: FileShareHandleProps) => void
|
||||
}>()
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import SwitchField from '../Field/SwitchField.vue';
|
||||
import InputField from '../Field/InputField.vue';
|
||||
import SelectField from '../Field/SelectField.vue';
|
||||
import FormButton from '../Field/FormButton.vue';
|
||||
import SwitchField from '../Field/SwitchField.vue'
|
||||
import InputField from '../Field/InputField.vue'
|
||||
import SelectField from '../Field/SelectField.vue'
|
||||
import FormButton from '../Field/FormButton.vue'
|
||||
import type { TextShareHandleProps } from './types'
|
||||
const props = defineProps<{
|
||||
hide: () => void
|
||||
text: string
|
||||
onTextHandle: ({ type, config }: { type: string, config: any }) => void
|
||||
onTextHandle: (props: TextShareHandleProps) => void
|
||||
}>()
|
||||
</script>
|
||||
|
||||
@@ -15,51 +16,74 @@ const props = defineProps<{
|
||||
<div class="flex flex-col gap-3">
|
||||
<h2 class="text-lg font-bold">分享选项</h2>
|
||||
<div class="flex flex-row items-center gap-2 text-sm">
|
||||
|
||||
<SelectField name="download_nums" label="浏览次数" :options="[
|
||||
{ label: '1次浏览', value: 1 },
|
||||
{ label: '2次浏览', value: 2 },
|
||||
{ label: '3次浏览', value: 3 },
|
||||
{ label: '5次浏览', value: 5 },
|
||||
{ label: '10次浏览', value: 10 },
|
||||
]" />
|
||||
<SelectField
|
||||
name="download_nums"
|
||||
label="浏览次数"
|
||||
:options="[
|
||||
{ label: '1次浏览', value: 1 },
|
||||
{ label: '2次浏览', value: 2 },
|
||||
{ label: '3次浏览', value: 3 },
|
||||
{ label: '5次浏览', value: 5 },
|
||||
{ label: '10次浏览', value: 10 },
|
||||
]"
|
||||
/>
|
||||
或
|
||||
<SelectField name="expire_time" label="过期时间" :options="[
|
||||
{ label: '5分钟', value: 5 },
|
||||
{ label: '1小时', value: 60 },
|
||||
{ label: '1天', value: 1440 },
|
||||
{ label: '3天', value: 4320 },
|
||||
]" />
|
||||
<SelectField
|
||||
name="expire_time"
|
||||
label="过期时间"
|
||||
:options="[
|
||||
{ label: '5分钟', value: 5 },
|
||||
{ label: '1小时', value: 60 },
|
||||
{ label: '1天', value: 1440 },
|
||||
{ label: '3天', value: 4320 },
|
||||
]"
|
||||
/>
|
||||
后过期
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="flex flex-row gap-3 min-h-9">
|
||||
<SwitchField name="has_pickup_code" label="取件码" :rules="((value: boolean) => {
|
||||
if (!!value) {
|
||||
setFieldValue('has_password', false)
|
||||
}
|
||||
return true
|
||||
})" />
|
||||
<SwitchField
|
||||
name="has_pickup_code"
|
||||
label="取件码"
|
||||
:rules="
|
||||
(value: boolean) => {
|
||||
if (!!value) {
|
||||
setFieldValue('has_password', false)
|
||||
}
|
||||
return true
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-row gap-3 min-h-9">
|
||||
<SwitchField name="has_password" label="密码保护" :rules="((value: boolean) => {
|
||||
if (!!value) {
|
||||
setFieldValue('has_pickup_code', false)
|
||||
}
|
||||
return true
|
||||
})" />
|
||||
<SwitchField
|
||||
name="has_password"
|
||||
label="密码保护"
|
||||
:rules="
|
||||
(value: boolean) => {
|
||||
if (!!value) {
|
||||
setFieldValue('has_pickup_code', false)
|
||||
}
|
||||
return true
|
||||
}
|
||||
"
|
||||
/>
|
||||
<InputField v-if="!!values.has_password" name="password" placeholder="请输入密码" rules="required" />
|
||||
</div>
|
||||
<div class="flex flex-row gap-3 min-h-9">
|
||||
<SwitchField name="has_notify" label="已读通知" />
|
||||
<InputField v-if="!!values.has_notify" name="notify_email" placeholder="请输入邮箱"
|
||||
rules="required" />
|
||||
<InputField v-if="!!values.has_notify" name="notify_email" placeholder="请输入邮箱" rules="required" />
|
||||
</div>
|
||||
</div>
|
||||
<FormButton @click="async (form) => {
|
||||
onTextHandle({ type: 'text-share', config: values })
|
||||
hide()
|
||||
}">提交</FormButton>
|
||||
<FormButton
|
||||
@click="
|
||||
async (form) => {
|
||||
onTextHandle({ type: 'text-share', config: values })
|
||||
hide()
|
||||
}
|
||||
"
|
||||
>提交</FormButton
|
||||
>
|
||||
</div>
|
||||
</VeeForm>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
5
front/components/Preprocessing/types.ts
Normal file
5
front/components/Preprocessing/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export type FileHandleKey = 'file-share' | 'file-image-compress'
|
||||
export type FileShareHandleProps = { type: FileHandleKey; config: Record<string, any> }
|
||||
|
||||
export type TextHandleKey = 'text-share'
|
||||
export type TextShareHandleProps = { type: TextHandleKey; config: Record<string, any> }
|
||||
@@ -14,11 +14,12 @@ import showDrawer from '@/lib/showDrawer'
|
||||
import QrCoreDrawer from '@/components/Drawer/QrCoreDrawer.vue'
|
||||
import { h } from 'vue'
|
||||
import { cx } from 'class-variance-authority'
|
||||
import type { FileHandleKey } from '../Preprocessing/types'
|
||||
dayjs.extend(relativeTime) // 扩展 relativeTime 插件
|
||||
dayjs.locale('zh-cn') // 设置语言为中文
|
||||
|
||||
const props = defineProps<{
|
||||
data: { files: { id: string; file: File }[]; config: any; handle_type: string }
|
||||
data: { files: { id: string; file: File }[]; config: Record<string, any>; handle_type: FileHandleKey }
|
||||
}>()
|
||||
const emit = defineEmits<{
|
||||
(e: 'change', key: string): void
|
||||
@@ -33,7 +34,7 @@ const { data } = useQuery({
|
||||
const { id, file } = item || {}
|
||||
return { id, name: file.name }
|
||||
}),
|
||||
config,
|
||||
config: config as any,
|
||||
})
|
||||
return data?.map((item) => item?.data)
|
||||
},
|
||||
|
||||
@@ -1,45 +1,37 @@
|
||||
<script lang="ts" setup>
|
||||
import FileShareResult from "@/components/Result/FileShareResult.vue";
|
||||
import TextShareResult from "@/components/Result/TextShareResult.vue";
|
||||
import ImageCompressResult from "@/components/Result/ImageCompressResult.vue";
|
||||
import FileShareResult from '@/components/Result/FileShareResult.vue'
|
||||
import TextShareResult from '@/components/Result/TextShareResult.vue'
|
||||
import ImageCompressResult from '@/components/Result/ImageCompressResult.vue'
|
||||
import type { FileHandleKey, TextHandleKey } from '../Preprocessing/types'
|
||||
|
||||
type basehandleData = { config: any; handle_type: string };
|
||||
type basehandleData = { config: Record<string, any> }
|
||||
|
||||
type filehandleData = { file: File; file_id: string } & basehandleData;
|
||||
type texthandleData = { text: string } & basehandleData;
|
||||
type filehandleData = { files: { id: string; file: File }[]; handle_type: FileHandleKey } & basehandleData
|
||||
type texthandleData = { text: string; handle_type: TextHandleKey } & basehandleData
|
||||
type handleKey = 'file-share' | 'text-share' | 'file-image-compress'
|
||||
|
||||
const props = defineProps<{
|
||||
data: filehandleData | texthandleData;
|
||||
}>();
|
||||
data: filehandleData | texthandleData
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "change", key: string): void;
|
||||
}>();
|
||||
(e: 'change', key: string): void
|
||||
}>()
|
||||
|
||||
const handleList = [
|
||||
{ component: FileShareResult, key: "file-share" },
|
||||
{ component: TextShareResult, key: "text-share" },
|
||||
{ component: ImageCompressResult, key: "file-image-compress" },
|
||||
];
|
||||
const handleList: { component: Component<{ data: filehandleData | texthandleData }>; key: handleKey }[] = [
|
||||
{ component: FileShareResult, key: 'file-share' },
|
||||
{ component: TextShareResult, key: 'text-share' },
|
||||
{ component: ImageCompressResult, key: 'file-image-compress' },
|
||||
]
|
||||
|
||||
const activeHandle = computed(() => {
|
||||
return handleList.find((item) => item.key === props?.data?.handle_type);
|
||||
});
|
||||
return handleList.find((item) => item.key === props?.data?.handle_type)
|
||||
})
|
||||
// vue这个ts蠢的没边了,本来想写component: FileShareResult | TextShareResult,结果不行
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<component
|
||||
v-if="'file' in data"
|
||||
:is="activeHandle?.component"
|
||||
:data="data"
|
||||
@change="(key: string) => emit('change', key)"
|
||||
/>
|
||||
<component
|
||||
v-if="'text' in data"
|
||||
:is="activeHandle?.component"
|
||||
:data="data"
|
||||
@change="(key: string) => emit('change', key)"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<component v-if="'file' in data" :is="activeHandle?.component" :data="data" @change="(key: string) => emit('change', key)" />
|
||||
<component v-if="'text' in data" :is="activeHandle?.component" :data="data" @change="(key: string) => emit('change', key)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -9,9 +9,11 @@ import useMyAppConfig from '@/composables/useMyAppConfig'
|
||||
import showDrawer from '@/lib/showDrawer'
|
||||
import QrCoreDrawer from '@/components/Drawer/QrCoreDrawer.vue'
|
||||
import dayjs from 'dayjs'
|
||||
import { h } from 'vue'
|
||||
import type { TextHandleKey } from '../Preprocessing/types'
|
||||
|
||||
const props = defineProps<{
|
||||
data: { text: string; config: any; handle_type: string }
|
||||
data: { text: string; config: Record<string, any>; handle_type: TextHandleKey }
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
||||
Reference in New Issue
Block a user