mirror of
https://github.com/MCSManager/MCSManager.git
synced 2025-01-12 14:54:34 +08:00
Feat: upload image
This commit is contained in:
parent
64dc34e6eb
commit
f390de613e
@ -167,10 +167,8 @@ export const uploadAddress = useDefineApi<
|
||||
export const uploadFile = useDefineApi<
|
||||
{
|
||||
data: FormData;
|
||||
url: string;
|
||||
onUploadProgress: Function;
|
||||
},
|
||||
{}
|
||||
any
|
||||
>({
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "multipart/form-data" }
|
||||
|
@ -191,10 +191,8 @@ export const uploadInstanceFile = useDefineApi<
|
||||
code: string;
|
||||
};
|
||||
data: FormData;
|
||||
url: string;
|
||||
onUploadProgress: Function;
|
||||
},
|
||||
{}
|
||||
any
|
||||
>({
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "multipart/form-data" }
|
||||
|
@ -22,3 +22,14 @@ export const resetLayoutConfig = useDefineApi<any, void>({
|
||||
url: "/api/overview/layout",
|
||||
method: "DELETE"
|
||||
});
|
||||
|
||||
export const uploadFile = useDefineApi<
|
||||
{
|
||||
data: FormData;
|
||||
},
|
||||
string
|
||||
>({
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
url: "/api/overview/upload_assets"
|
||||
});
|
||||
|
@ -1,33 +1,60 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { $t as t } from "@/lang/i18n";
|
||||
import { useAppToolsStore } from "@/stores/useAppToolsStore";
|
||||
import { t } from "@/lang/i18n";
|
||||
import { useLayoutContainerStore } from "@/stores/useLayoutContainerStore";
|
||||
import CardPanel from "@/components/CardPanel.vue";
|
||||
import type { LayoutCard } from "@/types/index";
|
||||
import { Empty } from "ant-design-vue";
|
||||
import { Empty, message, type UploadProps } from "ant-design-vue";
|
||||
import { UploadOutlined } from "@ant-design/icons-vue";
|
||||
import { useLayoutCardTools } from "@/hooks/useCardTools";
|
||||
import { uploadFile } from "@/services/apis/layout";
|
||||
import { useAppStateStore } from "@/stores/useAppStateStore";
|
||||
|
||||
const props = defineProps<{
|
||||
card: LayoutCard;
|
||||
}>();
|
||||
|
||||
const { getMetaValue, setMetaValue } = useLayoutCardTools(props.card);
|
||||
|
||||
const { containerState } = useLayoutContainerStore();
|
||||
const { isAdmin } = useAppStateStore();
|
||||
const imgSrc = ref(getMetaValue("image", ""));
|
||||
const { openInputDialog } = useAppToolsStore();
|
||||
const open = ref(false);
|
||||
const activeKey = ref("upload");
|
||||
const percentComplete = ref(0);
|
||||
|
||||
const { state, execute } = uploadFile();
|
||||
const beforeUpload: UploadProps["beforeUpload"] = async (file) => {
|
||||
const uploadFormData = new FormData();
|
||||
uploadFormData.append("file", file);
|
||||
await execute({
|
||||
data: uploadFormData,
|
||||
timeout: 60 * 60 * 1000,
|
||||
onUploadProgress: (progressEvent: any) => {
|
||||
percentComplete.value = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||||
}
|
||||
});
|
||||
if (state.value) {
|
||||
imgSrc.value = `${window.location.origin}/upload_files/${state.value}`;
|
||||
setMetaValue("image", imgSrc.value);
|
||||
percentComplete.value = 0;
|
||||
message.success(t("TXT_CODE_773f36a0"));
|
||||
open.value = false;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const save = async () => {
|
||||
setMetaValue("image", imgSrc.value);
|
||||
open.value = false;
|
||||
};
|
||||
|
||||
const editImgSrc = async () => {
|
||||
try {
|
||||
imgSrc.value = (await openInputDialog(t("TXT_CODE_c8a51b2e"))) as string;
|
||||
setMetaValue("image", imgSrc.value);
|
||||
} catch (error) {}
|
||||
open.value = true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div style="width: 100%; position: relative">
|
||||
<div style="width: 100%; height: 100%; position: relative">
|
||||
<div v-if="imgSrc !== '' && containerState.isDesignMode" class="mask">
|
||||
<a-button type="primary" @click="editImgSrc()">
|
||||
{{ t("TXT_CODE_fd13f431") }}
|
||||
@ -40,13 +67,66 @@ const editImgSrc = async () => {
|
||||
<template #description>
|
||||
<span>{{ t("TXT_CODE_635d051") }}</span>
|
||||
</template>
|
||||
<a-button type="primary" @click="editImgSrc()">
|
||||
<a-button
|
||||
:disabled="!containerState.isDesignMode || !isAdmin"
|
||||
type="primary"
|
||||
@click="editImgSrc()"
|
||||
>
|
||||
{{ t("TXT_CODE_589e091c") }}
|
||||
</a-button>
|
||||
</a-empty>
|
||||
</template>
|
||||
</CardPanel>
|
||||
</div>
|
||||
<a-modal v-model:open="open" :title="null" :closable="false" :destroy-on-close="true">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="upload" :tab="t('TXT_CODE_e00c858c')">
|
||||
<a-progress
|
||||
v-if="percentComplete > 0"
|
||||
:stroke-color="{
|
||||
'0%': '#49b3ff',
|
||||
'100%': '#25f5b9'
|
||||
}"
|
||||
:percent="percentComplete"
|
||||
class="mb-20"
|
||||
/>
|
||||
|
||||
<a-upload
|
||||
:max-count="1"
|
||||
:disabled="percentComplete > 0"
|
||||
:show-upload-list="false"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<a-button type="primary" :loading="percentComplete > 0">
|
||||
<upload-outlined v-if="percentComplete === 0" />
|
||||
{{
|
||||
percentComplete > 0
|
||||
? t("TXT_CODE_b625dbf0") + percentComplete + "%"
|
||||
: t("TXT_CODE_e00c858c")
|
||||
}}
|
||||
</a-button>
|
||||
</a-upload>
|
||||
<a-typography class="mt-20">
|
||||
<a-typography-title :level="5">{{ t("温馨提示") }}</a-typography-title>
|
||||
<a-typography-paragraph>
|
||||
<ol>
|
||||
<li>{{ t("上传后将自动保存") }}</li>
|
||||
<li>{{ t("你可以通过 “重置布局” 来清空你上传的所有文件") }}</li>
|
||||
</ol>
|
||||
</a-typography-paragraph>
|
||||
</a-typography>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="url" :tab="t('网络URL')" force-render>
|
||||
<a-input v-model:value.lazy.trim="imgSrc" autofocus :placeholder="t('TXT_CODE_c8a51b2e')" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<template #footer>
|
||||
<a-button @click="open = false">{{ t("关闭") }}</a-button>
|
||||
<a-button v-if="activeKey === 'url'" type="primary" @click="save">
|
||||
{{ t("保存") }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
@ -14,7 +14,10 @@ export default defineConfig({
|
||||
target: "http://localhost:23333",
|
||||
changeOrigin: true,
|
||||
ws: true
|
||||
// rewrite: (path) => path.replace(/^\/api/, "")
|
||||
},
|
||||
"/upload_files": {
|
||||
target: "http://localhost:23333",
|
||||
changeOrigin: true
|
||||
},
|
||||
"/socket.io": {
|
||||
target: "ws://localhost:23333",
|
||||
|
@ -169,7 +169,7 @@ _ / / / / /___ ____/ /_ / / / / /_/ /_ / / / /_/ /_ /_/ // __/ /
|
||||
const koaStaticOptions = {
|
||||
maxAge: 10 * 24 * 60 * 60 //Cache for ten days. Changed files will not be load from cache.
|
||||
};
|
||||
app.use(koaStatic(path.join(BASE_PATH, "public"), koaStaticOptions));
|
||||
app.use(koaStatic(path.join(process.cwd(), "public"), koaStaticOptions));
|
||||
|
||||
// Websocket routing (useless for now)
|
||||
// import SocketService from "./app/service/socket_service";
|
||||
|
Loading…
Reference in New Issue
Block a user