Commit bc8af96a authored by chenqikuai's avatar chenqikuai

feat:专辑管理页面开发

parent e53264dc
...@@ -22,3 +22,4 @@ dist-ssr ...@@ -22,3 +22,4 @@ dist-ssr
*.njsproj *.njsproj
*.sln *.sln
*.sw? *.sw?
src/Test
\ No newline at end of file
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<body> <body>
<div id="app"></div> <div id="app"></div>
<script src="//at.alicdn.com/t/font_2990811_5ef22ofxikf.js"></script> <script src="//at.alicdn.com/t/font_2990811_5ef22ofxikf.js"></script>
<script src="//at.alicdn.com/t/font_2543933_vessc0ufp5.js"></script> <script src="//at.alicdn.com/t/font_2543933_zn6d44hoqhc.js"></script>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>
......
<template>
<div class="empty">
<slot></slot>
</div>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss">
.empty {
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #ababab;
line-height: 22px;
}
</style>
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
'is-required': isRequried && label, 'is-required': isRequried && label,
}" }"
style="margin-bottom: 12px" style="margin-bottom: 12px"
v-if="label || $slots.label"
> >
<label for="powerOfAttorney" class="el-form-item__label relative"> <label for="powerOfAttorney" class="el-form-item__label relative">
<slot name="label"> <slot name="label">
......
...@@ -6,7 +6,6 @@ export const showTip = ( ...@@ -6,7 +6,6 @@ export const showTip = (
handleCancel?: () => void, handleCancel?: () => void,
hightwords = "" hightwords = ""
) => { ) => {
console.log("show");
globalState.syMessageBoxConfig = { globalState.syMessageBoxConfig = {
visible: true, visible: true,
tip, tip,
......
import png from "@/assets/img/png.png";
import { iSelectBox, iUploadBox } from "./types";
export const boxConfig = {
uploadPicture: {
type: "upload",
accept: ".jpg,.png,.gif,.avi,.wmv,.mpeg",
icon: {
tag: "img",
url: png as string,
style: {
marginTop: "38px",
marginBottom: "7px",
},
},
requiredMsg: "藏品限JPG/PNG/GIF大小在20M以内",
requiredMsgStyle: {
marginBottom: "5px",
},
maxSize: 20 * 1024 ** 2,
btnTxt: "上传图片",
choosedFileIconName: "icontupian2",
} as iUploadBox,
selectAlbum: {
type: "select",
icon: {
tag: "icon",
iconName: "iconwenjian",
style: {
marginTop: "49px",
marginBottom: "19px",
},
},
btnTxt: "选择专辑",
choosedFileIconName: "iconyasuobao",
} as iSelectBox,
uploadAlbum: {
type: "upload",
accept: ".zip,.rar",
icon: {
tag: "icon",
iconName: "iconwenjian",
style: {
marginTop: "41px",
marginBottom: "5px",
},
},
requiredMsg: "支持ZIP/RAR格式,文件大小不超过5G",
requiredMsgStyle: {
marginBottom: "7px",
},
maxSize: 5 * 1024 ** 3,
btnTxt: "上传文件",
choosedFileIconName: "iconyasuobao",
} as iUploadBox,
};
<template>
<UploadBgBox>
<input
v-if="TheBox.type === 'upload'"
type="file"
:accept="TheBox.accept"
ref="inputRef"
class="hidden"
@change="handleFileInputChange"
/>
<Icon
v-if="TheBox.icon.tag === 'icon'"
:icon-name="TheBox.icon.iconName"
style="font-size: 51px"
:style="TheBox.icon.style"
class="mx-auto"
></Icon>
<img
v-else-if="TheBox.icon.tag === 'img'"
:src="TheBox.icon.url"
class="mx-auto select-none"
draggable="false"
:style="TheBox.icon.style"
alt=""
/>
<div
v-if="TheBox.type === 'upload'"
class="uploadTip"
:style="TheBox.requiredMsgStyle"
>
{{ TheBox.requiredMsg }}
</div>
<syButton
mode="uploadBtn"
@click="handleClickBtn"
:style="TheBox.btnStyle"
>{{ TheBox.btnTxt }}</syButton
>
<div
v-if="file && file.name"
class="flex w-full items-center justify-center"
>
<Icon :icon-name="TheBox.choosedFileIconName" class="mr-1"></Icon>
<span
style="
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #353535;
"
>{{ file.name }}</span
>
<Icon
@click="onClear"
icon-name="iconshanchu"
class="cursor-pointer"
style="font-size: 8px; margin-left: 14px"
></Icon>
</div>
</UploadBgBox>
</template>
<script setup lang="ts">
/**
* @description: 处理各种类型的文件上传或专辑选择的触发
* 提供基本的样式,可以配置关键点的样式
*/
import Icon from "@/components/Icon/index.vue";
import UploadBgBox from "./UploadBgBox.vue";
import { syButton } from "cqk-sy-ui";
import { computed, ref, watch } from "vue";
import { boxConfig } from "./constants";
import { fileTypeChecked } from "../../utils/file";
import { ElMessage, useFormItem } from "element-plus";
const props = defineProps<{
type: "uploadPicture" | "uploadAlbum" | "selectAlbum";
file: File | any;
}>();
const inputRef = ref<HTMLInputElement | null>();
const { formItem } = useFormItem();
const emit = defineEmits(["clear", "clickCenterBtn", "upload"]);
const TheBox = computed(() => {
return boxConfig[props.type];
});
const handleClickBtn = () => {
if (TheBox.value.type === "upload") {
inputRef.value?.click();
} else {
emit("clickCenterBtn");
}
};
const handleFileInputChange = (e: Event) => {
if (TheBox.value.type === "select") return;
const files = (e.target as HTMLInputElement).files;
if (!files || files?.length === 0) return;
const file = files[0];
if (!fileTypeChecked(file, inputRef.value!.accept)) {
ElMessage.error("请上传指定类型的文件");
return;
}
if (file.size >= TheBox.value.maxSize) {
ElMessage.error("请上传指定大小的文件");
return;
}
emit("upload", file);
(e.target as HTMLInputElement).value = "";
};
const onClear = () => {
emit("clear");
};
watch(
() => props.file,
() => {
formItem?.validate("change");
}
);
</script>
<style lang="scss" scoped>
.uploadTip {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #353535;
line-height: 17px;
}
</style>
import { StyleValue } from "vue";
export type tTypeOfUpload = "uploadPicture" | "uploadAlbum" | "selectAlbum";
export interface iImgTypeOfIcon {
tag: "img";
url: string;
}
export interface iSvgTypeOfIcon {
tag: "icon";
iconName: string;
}
export interface iBox {
icon: (iImgTypeOfIcon | iSvgTypeOfIcon) & {
style?: StyleValue;
};
btnTxt: string;
btnStyle?: StyleValue;
choosedFileIconName: string;
}
export interface iUploadBox extends iBox {
type: "upload";
accept: string;
requiredMsg: string;
requiredMsgStyle?: StyleValue;
maxSize: number;
}
export interface iSelectBox extends iBox {
type: "select";
}
...@@ -73,7 +73,7 @@ const menuList = [ ...@@ -73,7 +73,7 @@ const menuList = [
type: "menuItem", type: "menuItem",
name: "藏品管理", name: "藏品管理",
path: "/collectionManagement", path: "/collectionManagement",
otherActivePath: [], otherActivePath: ["/albumManagement"],
icon: { icon: {
active: { iconName: "iconzichan21", props: { color: "#3A3A3A" } }, active: { iconName: "iconzichan21", props: { color: "#3A3A3A" } },
notActive: { iconName: "iconzichan21", props: { color: "#959595" } }, notActive: { iconName: "iconzichan21", props: { color: "#959595" } },
......
<template> <template>
<div class="title"> <div class="title">
<slot></slot> <div class="cursor-pointer">
<slot></slot>
</div>
<div v-if="!$slots.title && title">
<div class="flex">
<div v-for="(t, i) in title" :key="i" class="flex items-center">
<div
:class="{
grayTitle: i !== title.length - 1,
}"
class="cursor-pointer"
@click="$router.push({ name: t.routerName })"
>
{{ t.name }}
</div>
<Icon
icon-name="iconjinru"
v-if="i !== title.length - 1"
class="mx-2"
></Icon>
</div>
</div>
</div>
</div> </div>
</template> </template>
<script setup lang="ts"></script> <script setup lang="ts">
import { useSlots } from "vue";
import Icon from "./Icon/index.vue";
defineProps<{
title?: {
name: string;
routerName: string;
}[];
}>();
</script>
<style lang="scss" scoped> <style lang="scss" scoped>
.title { .title {
...@@ -15,4 +46,7 @@ ...@@ -15,4 +46,7 @@
line-height: 33px; line-height: 33px;
letter-spacing: 1px; letter-spacing: 1px;
} }
.grayTitle {
color: #959595;
}
</style> </style>
...@@ -65,6 +65,11 @@ const routes = [ ...@@ -65,6 +65,11 @@ const routes = [
import("@/views/Collection/CollectionManagement/index.vue"), import("@/views/Collection/CollectionManagement/index.vue"),
}, },
{ {
path: "/albumManagement",
name: "albumManagement",
component: () => import("@/views/Collection/AlbumManagement/index.vue"),
},
{
path: "/passManage", path: "/passManage",
name: "passManage", name: "passManage",
component: () => component: () =>
......
<template>
<div class="albumItem transition-all flow-root">
<div class="albumBanner mx-auto"></div>
<div class="flex items-center justify-between" style="padding: 7px 17px">
<div>
<div class="name">
{{ name }}
</div>
<div class="time">
{{ formatTime(time) }}
</div>
</div>
<slot name="bottomR">
<syMoreOperate
:list="operateList"
@click-item="clickItem"
teleport
:margin-left="-47"
>
<template #default="{ show }">
<div
:style="{ backgroundColor: show ? '#e0e0e0' : '' }"
style="border-radius: 4px"
class="transition-all"
>
<Icon
icon-name="iconbianzu7-copy"
style="font-size: 23px"
class="cursor-pointer"
></Icon>
</div>
</template>
</syMoreOperate>
</slot>
</div>
</div>
</template>
<script setup lang="ts">
import { formatTime, syMoreOperate } from "cqk-sy-ui";
import Icon from "@/components/Icon/index.vue";
const props = defineProps<{
name: string;
time: number;
}>();
const emit = defineEmits<{
(e: "rename", id: any): void;
(e: "delete", id: any): void;
}>();
const operateList = [
{ name: "重命名", value: "rename" },
{ name: "删除", value: "delete" },
];
const clickItem = (item: string) => {
if (item === "rename") {
emit("rename", {
name: props.name,
id: "1lk2j31",
});
} else if (item === "delete") {
emit("delete", {
name: props.name,
id: "adsfjalksdj",
});
}
};
</script>
<style lang="scss" scoped>
.albumItem {
width: 295px;
height: 238px;
border-radius: 10px;
&:hover {
background: #efefef;
}
.albumBanner {
width: 263px;
height: 149px;
margin-top: 18px;
background-color: lightpink;
border-radius: 10px;
}
.name {
font-size: 16px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #353535;
}
.time {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #353535;
}
}
</style>
<template>
<div class="flex flex-wrap">
<AlbumItem
class="flex-shrink-0"
name="alksdf"
:time="new Date().getTime()"
v-for="n in list"
@rename="renameAlbum"
@delete="deleteAlbum"
>
</AlbumItem>
<RenameDialog
v-model:visible="renameShow"
:old-name="oldName"
placeholder="请输入专辑名"
:confirm-rename="confirmRename"
></RenameDialog>
</div>
</template>
<script setup lang="ts">
import { showTip } from "@/components/GlobalMount/api";
import { ElMessage } from "element-plus";
import AlbumItem from "./AlbumItem.vue";
import { ref } from "vue";
import RenameDialog from "./RenameDialog.vue";
const props = defineProps<{
list: any[];
}>();
const renameShow = ref(false);
const oldName = ref("");
const currentId = ref("");
const renameAlbum = (albumMsg: any) => {
renameShow.value = true;
oldName.value = albumMsg.name;
currentId.value = albumMsg.id;
};
const deleteAlbum = (item: any) => {
showTip(
"确认删除此专辑及专辑内全部内容吗?删除后无法找回,请谨慎操作。",
() => {
ElMessage.success("删除成功");
}
);
};
const confirmRename = async (name: string) => {
if (name === oldName.value) {
return true;
}
const res = await fetch(`/api/album/rename`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
id: currentId.value,
name,
}),
});
const data = await res.json();
if (data.code === 0) {
ElMessage.success("重命名成功");
return true;
} else {
ElMessage.error(data.msg);
return false;
}
};
</script>
<style></style>
<template>
<syCommonDialog
:visible="visible"
type="element"
:elementDialogProps="{
title: '重命名',
}"
:btnConfig="{
type: 'noBorder',
btns: [{
name: '取消',
disabled: false,
loading: false,
type: 'default' as const,
},
{
name: '确定',
disabled: false,
loading: false,
type: 'primary' as const,
}
],
btnFunctions: [{
name: '取消',
async click(){
return true;
},
}, {
name: '确定',
click:async () => {
if(model.name === '') {
return false;
}
confirmRename(model.name);
},
}]
}"
showMask
@closePopup="$emit('update:visible', false)"
>
<ElForm :rules="rules" :model="model">
<CustomizeFormItem prop="name">
<syDialogInput
style="width: 100%"
v-model:value="model.name"
:placeholder="placeholder"
maxLength="30"
></syDialogInput>
</CustomizeFormItem>
</ElForm>
</syCommonDialog>
</template>
<script setup lang="ts">
import { syCommonDialog, syDialogInput } from "cqk-sy-ui";
import { reactive, watch } from "vue";
import { ElForm } from "element-plus";
import CustomizeFormItem from "@/components/Form/CustomizeFormItem.vue";
const props = defineProps<{
oldName: string;
visible: boolean;
placeholder?: string;
confirmRename: (name: string) => Promise<boolean>;
}>();
defineEmits<{ (e: "update:visible", visible: boolean): void }>();
const rules = {
name: [
{
required: true,
message: "请输入专辑名",
},
],
};
const model = reactive({
name: "",
});
watch(
() => props.visible,
(newV) => {
if (newV) {
model.name = props.oldName;
}
}
);
</script>
<style></style>
<template>
<syCommonDialog
:visible="visible"
type="element"
:elementDialogProps="{
title: '创建专辑',
}"
showMask
elementDialogSize="medium"
@closePopup="$emit('update:visible', false)"
>
<ElForm :rules="rules" :model="model" ref="formRef">
<CustomizeFormItem prop="name">
<syDialogInput
style="width: 100%"
v-model:value="model.name"
placeholder="请输入专辑名称"
maxLength="30"
></syDialogInput>
</CustomizeFormItem>
<CustomizeFormItem prop="file">
<HandleAllKindsOfType
type="uploadAlbum"
:file="model.file"
@upload="upload"
@clear="clear"
></HandleAllKindsOfType>
</CustomizeFormItem>
</ElForm>
<div class="tip" style="margin-bottom: 50px">
提示:系统根据您的文件名生成数字产品编号,一旦上传无法修改。
</div>
<syButton
mode="elementBtn"
type="primary"
style="height: 40px"
class="w-full"
:disabled="confirmDisabled"
@click="handleClickConfirm"
>确定</syButton
>
</syCommonDialog>
</template>
<script setup lang="ts">
import { computed, reactive, ref, watch } from "vue";
import { syCommonDialog, syDialogInput, syButton } from "cqk-sy-ui";
import { ElForm, FormInstance } from "element-plus";
import CustomizeFormItem from "@/components/Form/CustomizeFormItem.vue";
import HandleAllKindsOfType from "@/components/HandleAllKindsOfType/index.vue";
const props = defineProps<{
visible: boolean;
}>();
const emit = defineEmits<{ (e: "update:visible", visible: boolean): void }>();
const formRef = ref<null | FormInstance>();
const rules = {
name: [
{
required: true,
message: "请输入专辑名",
},
],
file: [
{
required: true,
message: "请上传专辑",
trigger: "change",
},
],
};
const model = reactive({
name: "",
file: undefined as File | undefined,
});
const confirmDisabled = computed(() => {
return !model.name || !model.file;
});
const upload = (f: File) => {
model.file = f;
};
const clear = () => {
model.file = undefined;
};
const handleClickConfirm = () => {
formRef.value?.validate(async (valid) => {
if (!valid) return;
emit("update:visible", false);
});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
formRef.value?.resetFields();
}
}
);
</script>
<style scoped>
.tip {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #565656;
line-height: 17px;
}
</style>
<template>
<LayoutVue>
<div class="flex flex-col w-full h-full">
<div class="flex items-center">
<Search placeholder="搜索" v-model="searchStr"></Search>
<Avatar
class="ml-7"
@click="() => $router.push('/userCenter')"
></Avatar>
</div>
<div class="flex items-center justify-between" style="margin-top: 26px">
<Title
:title="[
{
name: '藏品管理',
routerName: 'collectionManagement',
},
{
name: '专辑管理',
routerName: 'albumManagement',
},
]"
></Title>
<div class="flex items-center">
<syButton
style="width: 113px"
mode="elementBtn"
size="large"
@click="createAlbumShow = true"
type="primary"
>
创建</syButton
>
</div>
</div>
<div class="flex-grow overflow-hidden relative" style="margin-top: 50px">
<Empty
v-if="!loading && tableData.length === 0"
class="absolute top-1/3 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
>
没有找到匹配结果,尝试其他关键词搜索
</Empty>
<div class="h-full overflow-auto" @scroll="scroll">
<syScrollBar @scrollToEnd="scrollToEnd" ref="syScrollBarRef">
<AlbumList :list="tableData"></AlbumList>
</syScrollBar>
</div>
</div>
<CreateAlbumDialog v-model:visible="createAlbumShow"></CreateAlbumDialog>
</div>
</LayoutVue>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import { syButton, syScrollBar } from "cqk-sy-ui";
import LayoutVue from "@/components/Layout.vue";
import Search from "@/components/Search/index.vue";
import Avatar from "@/components/Avatar/index.vue";
import Title from "@/components/Title.vue";
import { useTableData } from "@/components/Table/hooks";
import { watchDebounced } from "@vueuse/core";
import AlbumList from "./Album/AlbumList.vue";
import CreateAlbumDialog from "./CreateAlbumDialog/index.vue";
import Empty from "../../../components/Empty/index.vue";
const searchStr = ref("");
const createAlbumShow = ref(false);
const syScrollBarRef = ref<InstanceType<typeof syScrollBar>>();
const scroll = (e: Event) => {
const target = e.target as HTMLElement;
console.log(
"scroll",
target.scrollTop,
target.scrollHeight,
target.clientHeight
);
if (target.scrollTop + target.clientHeight >= target.scrollHeight) {
fetchNextPage();
}
};
const fetchTableData = ({
page,
page_size,
}: {
page: number;
page_size: number;
}) => {
/* 请求所需要的参数 */
page;
page_size;
// 当前状态
return new Promise<any>((r) => {
setTimeout(() => {
r({
total: 100,
data: "1"
.repeat(0)
.split("")
.map((i, index) => ({
name: index + (page - 1) * page_size + "____" + searchStr.value,
address: searchStr.value,
status: 2,
})),
});
}, 1);
});
};
const {
fetchNextPage: fetchNextPage,
tableData: tableData,
loading: loading,
refetch: refetch,
} = useTableData({
fetchData: fetchTableData,
});
watchDebounced(
searchStr,
(newV) => {
(syScrollBarRef.value as any).scrollTo(0, 0);
refetch();
},
{ debounce: 500 }
);
const scrollToEnd = () => {
console.log("toend");
fetchNextPage();
};
</script>
<style lang="scss" scoped></style>
...@@ -31,7 +31,13 @@ ...@@ -31,7 +31,13 @@
style="width: 113px" style="width: 113px"
mode="elementBtn" mode="elementBtn"
size="large" size="large"
@click="() => {}" @click="
() => {
$router.push({
name: 'albumManagement',
});
}
"
type="default" type="default"
> >
<Icon <Icon
......
<template> <template>
<UploadBox v-if="activedMenu === eCollectionType.picture"> <HandleAllKindsOfType
<input v-if="activedMenu === eCollectionType.picture"
type="file" type="uploadPicture"
name="" :file="fileData"
id="" @clear="
ref="pictureInputRef" () => {
class="hidden" clearCollectionMsg();
accept=".jpg,.png,.gif" }
@change="handlePictureChange" "
/> @upload="upload"
<img ></HandleAllKindsOfType>
src="@/assets/img/png.png" <HandleAllKindsOfType
class="mx-auto select-none" v-else-if="activedMenu === eCollectionType.album"
draggable="false" type="selectAlbum"
style="margin-top: 40px" :file="fileData"
alt="" @clear="
/> () => {
<div class="uploadTip" style="margin-bottom: 5px; margin-top: 4px"> clearCollectionMsg();
藏品限JPG/PNG/GIF大小在20M以内 }
</div> "
<syButton @click-center-btn="handleClickCenterBtn"
mode="uploadBtn" ></HandleAllKindsOfType>
@click="() => {
($refs as any).pictureInputRef.click();
}"
>上传藏品</syButton
>
<div v-if="fileData.name" class="flex w-full items-center">
<Icon1 icon-name="icontupian2" class="mr-1"></Icon1>
<span
style="
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #353535;
"
>{{ fileData.name }}</span
>
<Icon1
@click="
() => {
clearCollectionMsg();
formItem?.validate('blur');
}
"
icon-name="iconshanchu"
class="cursor-pointer"
style="font-size: 8px; margin-left: 14px"
></Icon1>
</div>
</UploadBox>
<UploadBox v-else>
<input type="file" name="" id="" ref="albumInputRef" class="hidden" />
<Icon1
icon-name="iconwenjian"
style="font-size: 51px; margin-top: 49px; margin-bottom: 17px"
class="mx-auto"
></Icon1>
<syButton mode="uploadBtn" @click="$emit('selectAlbum')">选择专辑</syButton>
<div
v-if="fileData.name"
class="flex w-full items-center"
style="margin-top: 8px"
>
<Icon1 icon-name="iconyasuobao" class="mr-1"></Icon1>
<span
style="
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #353535;
"
>{{ fileData.name }}</span
>
<Icon1
@click="
() => {
clearCollectionMsg();
formItem?.validate('blur');
}
"
icon-name="iconshanchu"
class="cursor-pointer"
style="font-size: 8px; margin-left: 14px"
></Icon1>
</div>
</UploadBox>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import UploadBox from "../UploadBox.vue";
import Icon1 from "@/components/Icon/index.vue";
import { eCollectionType } from "../types"; import { eCollectionType } from "../types";
import { fileTypeChecked, getFileName } from "../../../../utils/file"; import { getFileName } from "../../../../utils/file";
import { nextTick, ref } from "vue"; import HandleAllKindsOfType from "@/components/HandleAllKindsOfType/index.vue";
import { ElMessage, useFormItem } from "element-plus";
import { syButton } from "cqk-sy-ui";
const pictureInputRef = ref<HTMLInputElement>();
const props = defineProps<{ const props = defineProps<{
activedMenu: eCollectionType; activedMenu: eCollectionType;
...@@ -105,29 +34,15 @@ const props = defineProps<{ ...@@ -105,29 +34,15 @@ const props = defineProps<{
clearCollectionMsg: any; clearCollectionMsg: any;
}>(); }>();
const { formItem } = useFormItem();
const emit = defineEmits(["uploadCollection", "selectAlbum"]); const emit = defineEmits(["uploadCollection", "selectAlbum"]);
function handlePictureChange(e: Event) { const upload = (file: File) => {
const files = (e.target as HTMLInputElement).files;
if (!files || files?.length === 0) return;
const file = files[0];
if (!fileTypeChecked(file, pictureInputRef.value!.accept)) {
ElMessage.error("请上传指定类型的文件");
return;
}
if (file.size >= 20 * 1024 * 1024) {
ElMessage.error("请上传20M以内文件");
return;
}
emit("uploadCollection", { emit("uploadCollection", {
file,
formData: { formData: {
amount: 1, amount: 1,
type: "nft", type: "nft",
name: getFileName(file.name), name: getFileName(file.name),
fileData: file,
}, },
proof: { proof: {
id: "123", id: "123",
...@@ -137,18 +52,11 @@ function handlePictureChange(e: Event) { ...@@ -137,18 +52,11 @@ function handlePictureChange(e: Event) {
detail: "alskdf", detail: "alskdf",
}, },
}); });
nextTick(() => { };
formItem?.validate("blur");
}); const handleClickCenterBtn = () => {
(e.target as HTMLInputElement).value = ""; emit("selectAlbum");
} };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss"></style>
.uploadTip {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #353535;
}
</style>
...@@ -30,21 +30,18 @@ ...@@ -30,21 +30,18 @@
<CustomizeFormItem prop="fileData"> <CustomizeFormItem prop="fileData">
<UploadBoxFormControl <UploadBoxFormControl
:activedMenu="activedMenu" :activedMenu="activedMenu"
:fileData="fileData" :fileData="formData.fileData"
:clearCollectionMsg="clearCollectionMsg" :clearCollectionMsg="clearCollectionMsg"
@select-album="visibleOfAlbumDialog = true" @select-album="visibleOfAlbumDialog = true"
@uploadCollection=" @uploadCollection="
({ file, formData: fd, proof }) => { ({ formData: fd, proof }) => {
formData = fd;
uploadStatus = UploadStatusType.SUCCESS; uploadStatus = UploadStatusType.SUCCESS;
fileData = file; fee = feeCalcu(fd.fileData.size);
formData = {
...formData,
...fd,
fileData: file,
};
fee = feeCalcu(file.size);
checkProof(proof); checkProof(proof);
($refs as any).elFormRef.validate('name'); $nextTick(()=>{
($refs as any).elFormRef.validateField('name');
})
} }
" "
></UploadBoxFormControl> ></UploadBoxFormControl>
...@@ -52,7 +49,11 @@ ...@@ -52,7 +49,11 @@
<CustomizeFormItem <CustomizeFormItem
label="藏品名称" label="藏品名称"
prop="name" prop="name"
v-if="activedMenu === eCollectionType.picture && fileData.name" v-if="
activedMenu === eCollectionType.picture &&
formData.fileData &&
formData.fileData.name
"
> >
<syDialogInput <syDialogInput
class="w-full" class="w-full"
...@@ -60,7 +61,11 @@ ...@@ -60,7 +61,11 @@
placeholder="请输入藏品名称" placeholder="请输入藏品名称"
></syDialogInput> ></syDialogInput>
</CustomizeFormItem> </CustomizeFormItem>
<CustomizeFormItem label="发行类型" prop="type" v-if="fileData.name"> <CustomizeFormItem
label="发行类型"
prop="type"
v-if="formData && formData.fileData && formData.fileData.name"
>
<sy-select <sy-select
v-model="formData.type" v-model="formData.type"
placeholder="请选择资产类型" placeholder="请选择资产类型"
...@@ -69,7 +74,11 @@ ...@@ -69,7 +74,11 @@
<sy-option key="NFT" label="NFT" value="1"></sy-option> <sy-option key="NFT" label="NFT" value="1"></sy-option>
</sy-select> </sy-select>
</CustomizeFormItem> </CustomizeFormItem>
<CustomizeFormItem label="发行数量" prop="amount" v-if="fileData.name"> <CustomizeFormItem
label="发行数量"
prop="amount"
v-if="formData.fileData?.name"
>
<syDialogInput <syDialogInput
class="w-full" class="w-full"
type="number" type="number"
...@@ -169,7 +178,6 @@ import { ...@@ -169,7 +178,6 @@ import {
ElDialog, ElDialog,
} from "element-plus"; } from "element-plus";
import { $ajax } from "@/service"; import { $ajax } from "@/service";
import UploadBox from "./UploadBox.vue";
import UploadBoxFormControl from "./UploadBoxFormControl/index.vue"; import UploadBoxFormControl from "./UploadBoxFormControl/index.vue";
let service = null as any; let service = null as any;
...@@ -202,7 +210,6 @@ const proofInfo = { ...@@ -202,7 +210,6 @@ const proofInfo = {
type ProofInfoType = typeof proofInfo; type ProofInfoType = typeof proofInfo;
import { eCollectionType } from "./types"; import { eCollectionType } from "./types";
import { fileTypeChecked, getFileName } from "@/utils/file";
import Icon1 from "@/components/Icon/index.vue"; import Icon1 from "@/components/Icon/index.vue";
import CustomizeFormItem from "@/components/Form/CustomizeFormItem.vue"; import CustomizeFormItem from "@/components/Form/CustomizeFormItem.vue";
import DialogOfSelectAlbum from "./DialogOfSelectAlbum/index.vue"; import DialogOfSelectAlbum from "./DialogOfSelectAlbum/index.vue";
...@@ -230,7 +237,6 @@ export default defineComponent({ ...@@ -230,7 +237,6 @@ export default defineComponent({
syOption, syOption,
syRadio, syRadio,
syMenu, syMenu,
UploadBox,
Icon1, Icon1,
CustomizeFormItem, CustomizeFormItem,
DialogOfSelectAlbum, DialogOfSelectAlbum,
...@@ -254,7 +260,7 @@ export default defineComponent({ ...@@ -254,7 +260,7 @@ export default defineComponent({
uploadProcessCount: 0, uploadProcessCount: 0,
UploadStatusType, UploadStatusType,
uploadStatus: 1, uploadStatus: 1,
fileData: {} as any, // fileData: {} as any,
fee: 1, fee: 1,
chainSelected: 1, chainSelected: 1,
chainSelectAction: [ chainSelectAction: [
...@@ -293,6 +299,7 @@ export default defineComponent({ ...@@ -293,6 +299,7 @@ export default defineComponent({
fileData: [ fileData: [
{ {
validator: (rule: any, value: any, callback: any) => { validator: (rule: any, value: any, callback: any) => {
console.log(value, "show value in validator");
if (value) { if (value) {
callback && callback(); callback && callback();
} else { } else {
...@@ -304,6 +311,7 @@ export default defineComponent({ ...@@ -304,6 +311,7 @@ export default defineComponent({
); );
} }
}, },
trigger: "change",
}, },
], ],
}, },
...@@ -356,7 +364,7 @@ export default defineComponent({ ...@@ -356,7 +364,7 @@ export default defineComponent({
methods: { methods: {
handleSelectAlbum(album: any) { handleSelectAlbum(album: any) {
console.log(album, "show album message"); console.log(album, "show album message");
this.fileData = { this.formData.fileData = {
name: "flkajsdf.zip", name: "flkajsdf.zip",
}; };
this.formData.amount = 1000; this.formData.amount = 1000;
...@@ -377,37 +385,9 @@ export default defineComponent({ ...@@ -377,37 +385,9 @@ export default defineComponent({
this.formData.name = ""; this.formData.name = "";
this.formData.type = ""; this.formData.type = "";
this.formData.fileData = null; this.formData.fileData = null;
this.fileData = {};
this.relationProof = {} as ProofInfoType; this.relationProof = {} as ProofInfoType;
this.uploadStatus = UploadStatusType.INIT; this.uploadStatus = UploadStatusType.INIT;
}, },
handlePictureChange(e: Event) {
const files = (e.target as HTMLInputElement).files;
if (!files || files?.length === 0) return;
const file = files[0];
if (!fileTypeChecked(file, (this.$refs as any).pictureInputRef!.accept)) {
ElMessage.error("请上传指定类型的文件");
return;
}
if (file.size >= 20 * 1024 * 1024) {
ElMessage.error("请上传20M以内文件");
return;
}
this.fileData = file;
this.formData.amount = 1;
this.formData.type = "nft";
this.formData.name = getFileName(file.name);
this.uploadStatus = UploadStatusType.SUCCESS;
this.fee = this.feeCalcu(file.size);
this.checkProof({
id: "123",
user_id: 2,
name: "testProofName",
hash: "lkajsdf",
detail: "alskdf",
} as ProofInfoType);
(e.target as HTMLInputElement).value = "";
},
log: console.log, log: console.log,
/**删除溯源 */ /**删除溯源 */
deleteAdd() { deleteAdd() {
...@@ -526,11 +506,14 @@ export default defineComponent({ ...@@ -526,11 +506,14 @@ export default defineComponent({
if (!isValid) return; if (!isValid) return;
this.inSubmit = true; this.inSubmit = true;
/**如果有文件,则先文件上链 */ /**如果有文件,则先文件上链 */
if (this.fileData.name) { if (this.formData.fileData.name) {
const fd = new FormData(); const fd = new FormData();
fd.append("file_type", this.uploadFileType(this.fileData.name)); fd.append(
"file_type",
this.uploadFileType(this.formData.fileData.name)
);
fd.append("chain_type", this.chainSelected.toString()); fd.append("chain_type", this.chainSelected.toString());
fd.append("file_data", this.fileData); fd.append("file_data", this.formData.fileData);
const res = await $ajax({ const res = await $ajax({
type: "post", type: "post",
url: GO_URLS.uploadChain, url: GO_URLS.uploadChain,
...@@ -555,8 +538,8 @@ export default defineComponent({ ...@@ -555,8 +538,8 @@ export default defineComponent({
{ proof_id: this.relationProof.id }, { proof_id: this.relationProof.id },
{ file_type: "", file_url: "" } { file_type: "", file_url: "" }
); );
if (this.fileData.name) { if (this.formData.fileData.name) {
params.file_type = this.uploadFileType(this.fileData.name); params.file_type = this.uploadFileType(this.formData.fileData.name);
params.file_url = this.fileUrl; params.file_url = this.fileUrl;
} }
const res = await $ajax({ const res = await $ajax({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment