mirror of
https://github.com/keven1024/015.git
synced 2026-05-26 07:08:02 +00:00
feat(front): refactor sharing logic by introducing useAppShare composable for file and text sharing
This commit is contained in:
@@ -1,75 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { Button } from '@/components/ui/button';
|
||||
import FilePreviewView from '@/components/FilePreviewView.vue';
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { toast } from 'vue-sonner'
|
||||
import { useQuery } from '@tanstack/vue-query';
|
||||
import { Button } from "@/components/ui/button";
|
||||
import FilePreviewView from "@/components/FilePreviewView.vue";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
import { toast } from "vue-sonner";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import useAppShare from "@/composables/useShare";
|
||||
const props = defineProps<{
|
||||
data: { file: File, config: any, handle_type: string, file_id: string }
|
||||
}>()
|
||||
data: { file: File; config: any; handle_type: string; file_id: string };
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'change', key: string): void
|
||||
}>()
|
||||
(e: "change", key: string): void;
|
||||
}>();
|
||||
const { createFileShare } = useAppShare();
|
||||
const { data } = useQuery({
|
||||
queryKey: ['create-share', props?.data?.file_id],
|
||||
queryFn: async () => {
|
||||
const { file_id, config, file } = props?.data || {}
|
||||
const { name } = file || {}
|
||||
const data = await $fetch<{
|
||||
code: number
|
||||
data: {
|
||||
id?: string
|
||||
}
|
||||
}>(`/api/share`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
type: 'file',
|
||||
config,
|
||||
data: file_id,
|
||||
file_name: name
|
||||
}
|
||||
})
|
||||
return data?.data
|
||||
}
|
||||
})
|
||||
queryKey: ["create-share", props?.data?.file_id],
|
||||
queryFn: async () => {
|
||||
const { file_id, config, file } = props?.data || {};
|
||||
const { name } = file || {};
|
||||
const data = await createFileShare({
|
||||
file_id,
|
||||
config,
|
||||
file_name: name,
|
||||
});
|
||||
return data?.data;
|
||||
},
|
||||
});
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig();
|
||||
const url = computed(() => {
|
||||
const { id } = data?.value || {}
|
||||
return `${appConfig?.value?.site_url}/s/${id}`
|
||||
})
|
||||
const { id } = data?.value || {};
|
||||
return `${appConfig?.value?.site_url}/s/${id}`;
|
||||
});
|
||||
|
||||
const { copy } = useClipboard()
|
||||
const { copy } = useClipboard();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-3">
|
||||
<h2 class="text-lg">上传成功</h2>
|
||||
<div class="flex flex-col gap-3 items-center">
|
||||
<div class="flex flex-col h-30 items-center">
|
||||
<FilePreviewView :value="props?.data?.file" />
|
||||
</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<Input v-model="url" class="bg-white/70" />
|
||||
<Button
|
||||
variant="outline"
|
||||
class="bg-white/70"
|
||||
size="icon"
|
||||
@click="
|
||||
() => {
|
||||
copy(url);
|
||||
toast.success('复制成功');
|
||||
}
|
||||
"
|
||||
>
|
||||
<LucideCopy />
|
||||
</Button>
|
||||
|
||||
<div class="flex flex-col gap-3">
|
||||
<h2 class="text-lg">上传成功</h2>
|
||||
<div class="flex flex-col gap-3 items-center">
|
||||
<div class="flex flex-col h-30 items-center">
|
||||
<FilePreviewView :value="props?.data?.file" />
|
||||
</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<Input v-model="url" class="bg-white/70" />
|
||||
<Button variant="outline" class="bg-white/70" size="icon" @click="() => {
|
||||
copy(url)
|
||||
toast.success('复制成功')
|
||||
}">
|
||||
<LucideCopy />
|
||||
</Button>
|
||||
|
||||
<Button variant="outline" class="bg-white/70" size="icon">
|
||||
<LucideQrCode />
|
||||
</Button>
|
||||
</div>
|
||||
<Button variant="ghost" class="hover:bg-white/50 w-40" @click="() => {
|
||||
emit('change', 'input')
|
||||
}">
|
||||
确定
|
||||
</Button>
|
||||
</div>
|
||||
<Button variant="outline" class="bg-white/70" size="icon">
|
||||
<LucideQrCode />
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
class="hover:bg-white/50 w-40"
|
||||
@click="
|
||||
() => {
|
||||
emit('change', 'input');
|
||||
}
|
||||
"
|
||||
>
|
||||
确定
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,44 +1,45 @@
|
||||
<script lang="ts" setup>
|
||||
import FileShareResult from '@/components/Result/FileShareResult.vue'
|
||||
import TextShareResult from '@/components/Result/TextShareResult.vue'
|
||||
import FileShareResult from "@/components/Result/FileShareResult.vue";
|
||||
import TextShareResult from "@/components/Result/TextShareResult.vue";
|
||||
import ImageCompressResult from "@/components/Result/ImageCompressResult.vue";
|
||||
|
||||
type basehandleData = { config: any, handle_type: string }
|
||||
type basehandleData = { config: any; handle_type: string };
|
||||
|
||||
type filehandleData = { file: File, file_id: string } & basehandleData
|
||||
type texthandleData = { text: string } & basehandleData
|
||||
type filehandleData = { file: File; file_id: string } & basehandleData;
|
||||
type texthandleData = { text: string } & basehandleData;
|
||||
|
||||
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: 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>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
@@ -1,70 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { toast } from 'vue-sonner'
|
||||
import { useQuery } from '@tanstack/vue-query';
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
import { toast } from "vue-sonner";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import useAppShare from "@/composables/useShare";
|
||||
|
||||
const props = defineProps<{
|
||||
data: { text: string, config: any, handle_type: string }
|
||||
}>()
|
||||
data: { text: string; config: any; handle_type: string };
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'change', key: string): void
|
||||
}>()
|
||||
(e: "change", key: string): void;
|
||||
}>();
|
||||
|
||||
const { createTextShare } = useAppShare();
|
||||
const { data } = useQuery({
|
||||
queryKey: ['create-share', props?.data?.text],
|
||||
queryFn: async () => {
|
||||
const { config, text } = props?.data || {}
|
||||
const data = await $fetch<{
|
||||
code: number
|
||||
data: {
|
||||
id?: string
|
||||
}
|
||||
}>(`/api/share`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
type: 'text',
|
||||
config,
|
||||
data: text,
|
||||
}
|
||||
})
|
||||
return data?.data
|
||||
}
|
||||
})
|
||||
const appConfig = useAppConfig()
|
||||
queryKey: ["create-share", props?.data?.text],
|
||||
queryFn: async () => {
|
||||
const { config, text } = props?.data || {};
|
||||
const data = await createTextShare({
|
||||
text,
|
||||
config,
|
||||
});
|
||||
return data?.data;
|
||||
},
|
||||
});
|
||||
const appConfig = useAppConfig();
|
||||
const url = computed(() => {
|
||||
const { id } = data?.value || {}
|
||||
return `${appConfig?.value?.site_url}/s/${id}`
|
||||
})
|
||||
const { id } = data?.value || {};
|
||||
return `${appConfig?.value?.site_url}/s/${id}`;
|
||||
});
|
||||
|
||||
const { copy } = useClipboard()
|
||||
const { copy } = useClipboard();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex flex-row justify-between">
|
||||
<h2 class="text-lg">分享成功</h2>
|
||||
<div class="flex flex-row gap-2 basis-1/2">
|
||||
<Button variant="outline" class="bg-white/70" size="icon" @click="() => {
|
||||
emit('change', 'input')
|
||||
}">
|
||||
<LucideHome />
|
||||
</Button>
|
||||
<Input v-model="url" class="bg-white/70" />
|
||||
<Button variant="outline" class="bg-white/70" size="icon" @click="() => {
|
||||
copy(url)
|
||||
toast.success('复制成功')
|
||||
}">
|
||||
<LucideCopy />
|
||||
</Button>
|
||||
<Button variant="outline" class="bg-white/70" size="icon">
|
||||
<LucideQrCode />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="prose rounded-md bg-white/70 p-3 w-full max-w-full" v-html="props?.data?.text" />
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex flex-row justify-between">
|
||||
<h2 class="text-lg">分享成功</h2>
|
||||
<div class="flex flex-row gap-2 basis-1/2">
|
||||
<Button
|
||||
variant="outline"
|
||||
class="bg-white/70"
|
||||
size="icon"
|
||||
@click="
|
||||
() => {
|
||||
emit('change', 'input');
|
||||
}
|
||||
"
|
||||
>
|
||||
<LucideHome />
|
||||
</Button>
|
||||
<Input v-model="url" class="bg-white/70" />
|
||||
<Button
|
||||
variant="outline"
|
||||
class="bg-white/70"
|
||||
size="icon"
|
||||
@click="
|
||||
() => {
|
||||
copy(url);
|
||||
toast.success('复制成功');
|
||||
}
|
||||
"
|
||||
>
|
||||
<LucideCopy />
|
||||
</Button>
|
||||
<Button variant="outline" class="bg-white/70" size="icon">
|
||||
<LucideQrCode />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<div
|
||||
class="prose rounded-md bg-white/70 p-3 w-full max-w-full"
|
||||
v-html="props?.data?.text"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
72
front/composables/useShare.ts
Normal file
72
front/composables/useShare.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
const downloadFile = async (share_id: string) => {
|
||||
const data = await $fetch<{
|
||||
code: number;
|
||||
data: {
|
||||
token?: string;
|
||||
};
|
||||
}>(`/api/download`, {
|
||||
method: "POST",
|
||||
body: {
|
||||
share_id,
|
||||
},
|
||||
});
|
||||
const { token } = data?.data || {};
|
||||
if (!token) {
|
||||
return;
|
||||
}
|
||||
(window as any)?.open(`/api/download?token=${token}`);
|
||||
};
|
||||
|
||||
const createShare = async (data: any) => {
|
||||
return await $fetch<{
|
||||
code: number;
|
||||
data: {
|
||||
id?: string;
|
||||
};
|
||||
}>(`/api/share`, {
|
||||
method: "POST",
|
||||
body: data,
|
||||
});
|
||||
};
|
||||
|
||||
const createFileShare = async (data: {
|
||||
file_id: string;
|
||||
config: {
|
||||
download_nums: number;
|
||||
expire_time: number;
|
||||
has_pickup_code?: boolean;
|
||||
has_password?: boolean;
|
||||
pickup_code?: string;
|
||||
password?: string;
|
||||
notify_email?: string;
|
||||
};
|
||||
file_name: string;
|
||||
}) => {
|
||||
const { file_id, config, file_name } = data || {};
|
||||
return await createShare({
|
||||
type: "file",
|
||||
data: file_id,
|
||||
config,
|
||||
file_name,
|
||||
});
|
||||
};
|
||||
|
||||
const createTextShare = async (data: { text: string; config: any }) => {
|
||||
const { text, config } = data || {};
|
||||
return await createShare({
|
||||
type: "text",
|
||||
data: text,
|
||||
config,
|
||||
});
|
||||
};
|
||||
|
||||
const useAppShare = () => {
|
||||
return {
|
||||
downloadFile,
|
||||
createShare,
|
||||
createFileShare,
|
||||
createTextShare,
|
||||
};
|
||||
};
|
||||
|
||||
export default useAppShare;
|
||||
Reference in New Issue
Block a user