🎨 organize code structure

This commit is contained in:
landaiqing
2024-09-26 12:00:48 +08:00
parent 96ae754efd
commit 4f42d1c5b4
7 changed files with 219 additions and 223 deletions

23
components.d.ts vendored
View File

@@ -19,6 +19,7 @@ declare module 'vue' {
AForm: typeof import('ant-design-vue/es')['Form'] AForm: typeof import('ant-design-vue/es')['Form']
AFormItem: typeof import('ant-design-vue/es')['FormItem'] AFormItem: typeof import('ant-design-vue/es')['FormItem']
AImage: typeof import('ant-design-vue/es')['Image'] AImage: typeof import('ant-design-vue/es')['Image']
AImagePreviewGroup: typeof import('ant-design-vue/es')['ImagePreviewGroup']
AInput: typeof import('ant-design-vue/es')['Input'] AInput: typeof import('ant-design-vue/es')['Input']
AInputPassword: typeof import('ant-design-vue/es')['InputPassword'] AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
AMenu: typeof import('ant-design-vue/es')['Menu'] AMenu: typeof import('ant-design-vue/es')['Menu']
@@ -35,17 +36,17 @@ declare module 'vue' {
ATextarea: typeof import('ant-design-vue/es')['Textarea'] ATextarea: typeof import('ant-design-vue/es')['Textarea']
ATooltip: typeof import('ant-design-vue/es')['Tooltip'] ATooltip: typeof import('ant-design-vue/es')['Tooltip']
AUpload: typeof import('ant-design-vue/es')['Upload'] AUpload: typeof import('ant-design-vue/es')['Upload']
BoxDog: typeof import('./src/Components/BoxDog/BoxDog.vue')['default'] BoxDog: typeof import('./src/components/BoxDog/BoxDog.vue')['default']
Card3D: typeof import('./src/Components/Card3D/Card3D.vue')['default'] Card3D: typeof import('./src/components/Card3D/Card3D.vue')['default']
CloseCircleOutlined: typeof import('@ant-design/icons-vue')['CloseCircleOutlined'] CloseCircleOutlined: typeof import('@ant-design/icons-vue')['CloseCircleOutlined']
Clouds: typeof import('./src/Components/Clouds/Clouds.vue')['default'] Clouds: typeof import('./src/components/Clouds/Clouds.vue')['default']
CommentInput: typeof import('./src/Components/CommentReply/Components/CommentInput/CommentInput.vue')['default'] CommentInput: typeof import('./src/components/CommentReply/Components/CommentInput/CommentInput.vue')['default']
CommentList: typeof import('./src/Components/CommentReply/Components/CommentList/CommentList.vue')['default'] CommentList: typeof import('./src/components/CommentReply/Components/CommentList/CommentList.vue')['default']
CommentReply: typeof import('./src/Components/CommentReply/index.vue')['default'] CommentReply: typeof import('./src/components/CommentReply/index.vue')['default']
CopyOutlined: typeof import('@ant-design/icons-vue')['CopyOutlined'] CopyOutlined: typeof import('@ant-design/icons-vue')['CopyOutlined']
DeleteOutlined: typeof import('@ant-design/icons-vue')['DeleteOutlined'] DeleteOutlined: typeof import('@ant-design/icons-vue')['DeleteOutlined']
DynamicTitle: typeof import('./src/Components/DynamicTitle/DynamicTitle.vue')['default'] DynamicTitle: typeof import('./src/components/DynamicTitle/DynamicTitle.vue')['default']
EffectsCard: typeof import('./src/Components/EffectsCard/EffectsCard.vue')['default'] EffectsCard: typeof import('./src/components/EffectsCard/EffectsCard.vue')['default']
EyeOutlined: typeof import('@ant-design/icons-vue')['EyeOutlined'] EyeOutlined: typeof import('@ant-design/icons-vue')['EyeOutlined']
ForgetPage: typeof import('./src/views/Forget/ForgetPage.vue')['default'] ForgetPage: typeof import('./src/views/Forget/ForgetPage.vue')['default']
GithubOutlined: typeof import('@ant-design/icons-vue')['GithubOutlined'] GithubOutlined: typeof import('@ant-design/icons-vue')['GithubOutlined']
@@ -58,9 +59,9 @@ declare module 'vue' {
QqOutlined: typeof import('@ant-design/icons-vue')['QqOutlined'] QqOutlined: typeof import('@ant-design/icons-vue')['QqOutlined']
QRLogin: typeof import('./src/views/QRLogin/QRLogin.vue')['default'] QRLogin: typeof import('./src/views/QRLogin/QRLogin.vue')['default']
QRLoginFooter: typeof import('./src/views/QRLogin/QRLoginFooter.vue')['default'] QRLoginFooter: typeof import('./src/views/QRLogin/QRLoginFooter.vue')['default']
ReplyInput: typeof import('./src/Components/CommentReply/Components/ReplyInput/ReplyInput.vue')['default'] ReplyInput: typeof import('./src/components/CommentReply/Components/ReplyInput/ReplyInput.vue')['default']
ReplyList: typeof import('./src/Components/CommentReply/Components/ReplyList/ReplyList.vue')['default'] ReplyList: typeof import('./src/components/CommentReply/Components/ReplyList/ReplyList.vue')['default']
ReplyReply: typeof import('./src/Components/CommentReply/Components/ReplyReplyInput/ReplyReply.vue')['default'] ReplyReply: typeof import('./src/components/CommentReply/Components/ReplyReplyInput/ReplyReply.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
SafetyOutlined: typeof import('@ant-design/icons-vue')['SafetyOutlined'] SafetyOutlined: typeof import('@ant-design/icons-vue')['SafetyOutlined']

View File

@@ -35,21 +35,22 @@
method="post" method="post"
:directory="false" :directory="false"
:show-upload-list="false" :show-upload-list="false"
:custom-request="customUploadRequest" :custom-request="comment.customUploadRequest"
:before-upload="beforeUpload" :before-upload="comment.beforeUpload"
:disabled="imageList.length >= 3" :disabled="comment.imageList.length >= 3"
> >
<ABadge :count="imageList.length"> <ABadge :count="comment.imageList.length">
<AButton type="text" size="small" :icon="h(PictureOutlined)" <AButton type="text" size="small" :icon="h(PictureOutlined)"
class="comment-action-icon"> class="comment-action-icon">
{{ t('comment.picture') }} {{ t('comment.picture') }}
</AButton> </AButton>
</ABadge> </ABadge>
</AUpload> </AUpload>
<template v-if="imageList.length > 0"> <template v-if="comment.imageList.length > 0">
<ABadge style="margin-left: 10px;" v-for="(item, index) in imageList" :key="index"> <AImagePreviewGroup>
<ABadge style="margin-left: 10px;" v-for="(item, index) in comment.imageList" :key="index">
<template #count> <template #count>
<CloseCircleOutlined @click="removeBase64Image(index)" style="color: #f5222d"/> <CloseCircleOutlined @click="comment.removeBase64Image(index)" style="color: #f5222d"/>
</template> </template>
<AAvatar shape="square" size="small"> <AAvatar shape="square" size="small">
<template #icon> <template #icon>
@@ -57,6 +58,7 @@
</template> </template>
</AAvatar> </AAvatar>
</ABadge> </ABadge>
</AImagePreviewGroup>
</template> </template>
</AFlex> </AFlex>
</AFlex> </AFlex>
@@ -90,15 +92,14 @@ import useStore from "@/store";
import {message} from "ant-design-vue"; import {message} from "ant-design-vue";
import {commentSubmitApi} from "@/api/comment"; import {commentSubmitApi} from "@/api/comment";
import {useDebounceFn, useThrottleFn} from "@vueuse/core"; import {useDebounceFn, useThrottleFn} from "@vueuse/core";
import imageCompression from "browser-image-compression";
import {useRouter} from "vue-router"; import {useRouter} from "vue-router";
const {t} = useI18n(); const {t} = useI18n();
const showCommentActions = ref<boolean>(false); const showCommentActions = ref<boolean>(false);
const commentContent = ref<string>(""); const commentContent = ref<string>("");
const fileList = ref<any[]>([]);
const imageList = ref<any[]>([]);
const user = useStore().user; const user = useStore().user;
const commentTextAreaPlaceholder = ref<string>(t('comment.placeholder')); const commentTextAreaPlaceholder = ref<string>(t('comment.placeholder'));
const topicId = ref<string>("123"); const topicId = ref<string>("123");
@@ -146,7 +147,7 @@ async function commentSubmit(point: any) {
message.error(t('comment.commentContentNotEmpty')); message.error(t('comment.commentContentNotEmpty'));
return; return;
} }
if (imageList.value.length > 3) { if (comment.imageList.length > 3) {
message.error(t('comment.maxImageCount')); message.error(t('comment.maxImageCount'));
return; return;
} }
@@ -156,7 +157,7 @@ async function commentSubmit(point: any) {
user_id: user.user.uid, user_id: user.user.uid,
topic_id: topicId.value, topic_id: topicId.value,
content: content, content: content,
images: imageList.value, images: comment.imageList,
author: user.user.uid, author: user.user.uid,
point: [point.x, point.y], point: [point.x, point.y],
key: comment.slideCaptchaData.key, key: comment.slideCaptchaData.key,
@@ -165,8 +166,7 @@ async function commentSubmit(point: any) {
if (result.code === 200 && result.success) { if (result.code === 200 && result.success) {
message.success(t('comment.commentSuccess')); message.success(t('comment.commentSuccess'));
commentContent.value = ""; commentContent.value = "";
fileList.value = []; await comment.clearFileList();
imageList.value = [];
showSubmitCaptcha.value = false; showSubmitCaptcha.value = false;
await getCommentList(); await getCommentList();
} else { } else {
@@ -188,47 +188,6 @@ async function getCommentList(page: number = 1, size: number = 5, hot: boolean =
await comment.getCommentList(params); await comment.getCommentList(params);
} }
// 压缩图片配置
const options = {
maxSizeMB: 0.4,
maxWidthOrHeight: 750,
maxIteration: 2
};
/**
* 上传文件前置
* @param file
*/
async function beforeUpload(file: any) {
if (!window.FileReader) return false; // 判断是否支持FileReader
const compressedFile = await imageCompression(file, options);
const reader = new FileReader();
reader.readAsDataURL(compressedFile); // 文件转换
reader.onloadend = async function () {
if (fileList.value.length >= 5) {
message.error(t('comment.maxImageCount'));
return false;
}
fileList.value.push(reader.result);
};
return true;
}
/**
* 自定义上传图片请求
*/
async function customUploadRequest() {
imageList.value = fileList.value;
}
/**
* 移除图片
* @param index
*/
async function removeBase64Image(index: number) {
fileList.value.splice(index, 1);
imageList.value.splice(index, 1);
}
const getSlideCaptchaDataThrottled = useThrottleFn(comment.getSlideCaptchaData, 1000); const getSlideCaptchaDataThrottled = useThrottleFn(comment.getSlideCaptchaData, 1000);

View File

@@ -49,6 +49,7 @@
<div class="reply-text" v-html="item.content"> <div class="reply-text" v-html="item.content">
</div> </div>
<AFlex :vertical="false" align="center" class="reply-images" v-if="item.images"> <AFlex :vertical="false" align="center" class="reply-images" v-if="item.images">
<AImagePreviewGroup>
<AAvatar shape="square" size="large" <AAvatar shape="square" size="large"
v-for="(image, index) in item.images" :key="index"> v-for="(image, index) in item.images" :key="index">
<template #icon> <template #icon>
@@ -59,6 +60,7 @@
</AImage> </AImage>
</template> </template>
</AAvatar> </AAvatar>
</AImagePreviewGroup>
</AFlex> </AFlex>
<AFlex :vertical="false" justify="space-between" align="center"> <AFlex :vertical="false" justify="space-between" align="center">
<!--评论操作按钮 --> <!--评论操作按钮 -->

View File

@@ -48,21 +48,22 @@
method="post" method="post"
:directory="false" :directory="false"
:show-upload-list="false" :show-upload-list="false"
:custom-request="customUploadRequest" :custom-request="comment.customUploadRequest"
:before-upload="beforeUpload" :before-upload="comment.beforeUpload"
:disabled="imageList.length >= 3" :disabled="comment.imageList.length >= 3"
> >
<ABadge :count="imageList.length"> <ABadge :count="comment.imageList.length">
<AButton type="text" size="small" :icon="h(PictureOutlined)" <AButton type="text" size="small" :icon="h(PictureOutlined)"
class="comment-action-icon-reply"> class="comment-action-icon-reply">
{{ t('comment.picture') }} {{ t('comment.picture') }}
</AButton> </AButton>
</ABadge> </ABadge>
</AUpload> </AUpload>
<template v-if="imageList.length > 0"> <template v-if="comment.imageList.length > 0">
<ABadge style="margin-left: 10px;" v-for="(item, index) in imageList" :key="index"> <AImagePreviewGroup>
<ABadge style="margin-left: 10px;" v-for="(item, index) in comment.imageList" :key="index">
<template #count> <template #count>
<CloseCircleOutlined @click="removeBase64Image(index)" style="color: #f5222d"/> <CloseCircleOutlined @click="comment.removeBase64Image(index)" style="color: #f5222d"/>
</template> </template>
<AAvatar shape="square" size="small"> <AAvatar shape="square" size="small">
<template #icon> <template #icon>
@@ -70,6 +71,7 @@
</template> </template>
</AAvatar> </AAvatar>
</ABadge> </ABadge>
</AImagePreviewGroup>
</template> </template>
</AFlex> </AFlex>
</AFlex> </AFlex>
@@ -98,7 +100,6 @@
import {h, ref} from "vue"; import {h, ref} from "vue";
import {message} from "ant-design-vue"; import {message} from "ant-design-vue";
import imageCompression from "browser-image-compression";
import {CloseOutlined, PictureOutlined, SmileOutlined} from "@ant-design/icons-vue"; import {CloseOutlined, PictureOutlined, SmileOutlined} from "@ant-design/icons-vue";
import EMOJI from "@/constant/emoji.ts"; import EMOJI from "@/constant/emoji.ts";
import {useI18n} from "vue-i18n"; import {useI18n} from "vue-i18n";
@@ -110,8 +111,6 @@ const {t} = useI18n();
const comment = useStore().comment; const comment = useStore().comment;
const user = useStore().user; const user = useStore().user;
const commentTextAreaPlaceholder = ref<string>(t('comment.placeholder')); const commentTextAreaPlaceholder = ref<string>(t('comment.placeholder'));
const fileList = ref<any[]>([]);
const imageList = ref<any[]>([]);
const replyContent = ref<string>(""); const replyContent = ref<string>("");
const topicId = ref<string>("123"); const topicId = ref<string>("123");
const showSubmitCaptcha = ref<boolean>(false); const showSubmitCaptcha = ref<boolean>(false);
@@ -141,47 +140,6 @@ async function insertEmojiToReplyContent(emoji: string) {
replyContent.value += emoji; replyContent.value += emoji;
} }
// 压缩图片配置
const options = {
maxSizeMB: 0.4,
maxWidthOrHeight: 750,
maxIteration: 2
};
/**
* 上传文件前置
* @param file
*/
async function beforeUpload(file: any) {
if (!window.FileReader) return false; // 判断是否支持FileReader
const compressedFile = await imageCompression(file, options);
const reader = new FileReader();
reader.readAsDataURL(compressedFile); // 文件转换
reader.onloadend = async function () {
if (fileList.value.length >= 5) {
message.error(t('comment.maxImageCount'));
return false;
}
fileList.value.push(reader.result);
};
return true;
}
/**
* 自定义上传图片请求
*/
async function customUploadRequest() {
imageList.value = fileList.value;
}
/**
* 移除图片
* @param index
*/
async function removeBase64Image(index: number) {
fileList.value.splice(index, 1);
imageList.value.splice(index, 1);
}
/** /**
* 回复提交 throttled * 回复提交 throttled
@@ -196,7 +154,7 @@ async function replySubmit(point: any) {
message.error(t('comment.commentContentNotEmpty')); message.error(t('comment.commentContentNotEmpty'));
return; return;
} }
if (imageList.value.length > 3) { if (comment.imageList.length > 3) {
message.error(t('comment.maxImageCount')); message.error(t('comment.maxImageCount'));
return; return;
} }
@@ -216,7 +174,7 @@ async function replySubmit(point: any) {
user_id: user.user.uid, user_id: user.user.uid,
topic_id: topicId.value, topic_id: topicId.value,
content: content, content: content,
images: imageList.value, images: comment.imageList,
author: user.user.uid, author: user.user.uid,
reply_id: props.item.id, reply_id: props.item.id,
reply_user: props.item.user_id, reply_user: props.item.user_id,
@@ -226,8 +184,7 @@ async function replySubmit(point: any) {
const result: any = await replySubmitApi(replyParams); const result: any = await replySubmitApi(replyParams);
if (result.code === 200 && result.success) { if (result.code === 200 && result.success) {
replyContent.value = ""; replyContent.value = "";
fileList.value = []; await comment.clearFileList();
imageList.value = [];
showSubmitCaptcha.value = false; showSubmitCaptcha.value = false;
await getReplyList(); await getReplyList();
comment.closeReplyInput(); comment.closeReplyInput();

View File

@@ -28,6 +28,7 @@
<div class="reply-text-child" v-html="child.content"> <div class="reply-text-child" v-html="child.content">
</div> </div>
<AFlex :vertical="false" align="center" class="reply-images" v-if="child.images"> <AFlex :vertical="false" align="center" class="reply-images" v-if="child.images">
<AImagePreviewGroup>
<AAvatar shape="square" size="large" <AAvatar shape="square" size="large"
v-for="(image, index) in child.images" :key="index"> v-for="(image, index) in child.images" :key="index">
<template #icon> <template #icon>
@@ -38,6 +39,7 @@
</AImage> </AImage>
</template> </template>
</AAvatar> </AAvatar>
</AImagePreviewGroup>
</AFlex> </AFlex>
<AFlex :vertical="false" justify="space-between" align="center"> <AFlex :vertical="false" justify="space-between" align="center">
<!--评论操作按钮 --> <!--评论操作按钮 -->
@@ -141,7 +143,6 @@ const props = defineProps({
} }
}); });
/** /**
* 格式化时间 * 格式化时间
* @param dateString * @param dateString
@@ -169,6 +170,7 @@ function formatTimeAgo(dateString: string) {
return `${seconds} 秒前`; return `${seconds} 秒前`;
} }
const commentLikeThrottled = useThrottleFn(commentLike, 1000); const commentLikeThrottled = useThrottleFn(commentLike, 1000);
/** /**

View File

@@ -51,22 +51,23 @@
method="post" method="post"
:directory="false" :directory="false"
:show-upload-list="false" :show-upload-list="false"
:custom-request="customUploadRequest" :custom-request="comment.customUploadRequest"
:before-upload="beforeUpload" :before-upload="comment.beforeUpload"
:disabled="imageList.length >= 3" :disabled="comment.imageList.length >= 3"
> >
<ABadge :count="imageList.length"> <ABadge :count="comment.imageList.length">
<AButton type="text" size="small" :icon="h(PictureOutlined)" <AButton type="text" size="small" :icon="h(PictureOutlined)"
class="comment-action-icon-reply-child"> class="comment-action-icon-reply-child">
{{ t('comment.picture') }} {{ t('comment.picture') }}
</AButton> </AButton>
</ABadge> </ABadge>
</AUpload> </AUpload>
<template v-if="imageList.length > 0"> <template v-if="comment.imageList.length > 0">
<ABadge style="margin-left: 10px;" v-for="(item, index) in imageList" <AImagePreviewGroup>
<ABadge style="margin-left: 10px;" v-for="(item, index) in comment.imageList"
:key="index"> :key="index">
<template #count> <template #count>
<CloseCircleOutlined @click="removeBase64Image(index)" <CloseCircleOutlined @click="comment.removeBase64Image(index)"
style="color: #f5222d"/> style="color: #f5222d"/>
</template> </template>
<AAvatar shape="square" size="small"> <AAvatar shape="square" size="small">
@@ -75,6 +76,7 @@
</template> </template>
</AAvatar> </AAvatar>
</ABadge> </ABadge>
</AImagePreviewGroup>
</template> </template>
</AFlex> </AFlex>
</AFlex> </AFlex>
@@ -110,14 +112,12 @@ import {message} from "ant-design-vue";
import {replyReplySubmitApi} from "@/api/comment"; import {replyReplySubmitApi} from "@/api/comment";
import {ReplyCommentParams} from "@/types/comment"; import {ReplyCommentParams} from "@/types/comment";
import {useThrottleFn} from "@vueuse/core"; import {useThrottleFn} from "@vueuse/core";
import imageCompression from "browser-image-compression";
const {t} = useI18n(); const {t} = useI18n();
const commentTextAreaPlaceholder = ref<string>(t('comment.placeholder')); const commentTextAreaPlaceholder = ref<string>(t('comment.placeholder'));
const comment = useStore().comment; const comment = useStore().comment;
const replyReplyContent = ref<string>(""); const replyReplyContent = ref<string>("");
const fileList = ref<any[]>([]);
const imageList = ref<any[]>([]);
const user = useStore().user; const user = useStore().user;
const topicId = ref<string>("123"); const topicId = ref<string>("123");
const showSubmitCaptcha = ref<boolean>(false); const showSubmitCaptcha = ref<boolean>(false);
@@ -153,48 +153,6 @@ async function insertEmojiToReplyReplyContent(emoji: string) {
} }
// 压缩图片配置
const options = {
maxSizeMB: 0.4,
maxWidthOrHeight: 750,
maxIteration: 2
};
/**
* 上传文件前置
* @param file
*/
async function beforeUpload(file: any) {
if (!window.FileReader) return false; // 判断是否支持FileReader
const compressedFile = await imageCompression(file, options);
const reader = new FileReader();
reader.readAsDataURL(compressedFile); // 文件转换
reader.onloadend = async function () {
if (fileList.value.length >= 5) {
message.error(t('comment.maxImageCount'));
return false;
}
fileList.value.push(reader.result);
};
return true;
}
/**
* 自定义上传图片请求
*/
async function customUploadRequest() {
imageList.value = fileList.value;
}
/**
* 移除图片
* @param index
*/
async function removeBase64Image(index: number) {
fileList.value.splice(index, 1);
imageList.value.splice(index, 1);
}
/** /**
* 回复提交 throttled * 回复提交 throttled
*/ */
@@ -208,7 +166,7 @@ async function replyReplySubmit(point: any) {
message.error(t('comment.commentContentNotEmpty')); message.error(t('comment.commentContentNotEmpty'));
return; return;
} }
if (imageList.value.length > 3) { if (comment.imageList.length > 3) {
message.error(t('comment.maxImageCount')); message.error(t('comment.maxImageCount'));
return; return;
} }
@@ -218,7 +176,7 @@ async function replyReplySubmit(point: any) {
user_id: user.user.uid, user_id: user.user.uid,
topic_id: topicId.value, topic_id: topicId.value,
content: content, content: content,
images: imageList.value, images: comment.imageList,
author: user.user.uid, author: user.user.uid,
reply_to: props.child.id, reply_to: props.child.id,
reply_id: props.item.id, reply_id: props.item.id,
@@ -230,8 +188,7 @@ async function replyReplySubmit(point: any) {
if (result.code === 200 && result.success) { if (result.code === 200 && result.success) {
replyReplyContent.value = ""; replyReplyContent.value = "";
fileList.value = []; await comment.clearFileList();
imageList.value = [];
showSubmitCaptcha.value = false; showSubmitCaptcha.value = false;
await getReplyList(); await getReplyList();
comment.closeReplyInput(); comment.closeReplyInput();

View File

@@ -4,7 +4,7 @@ import {Comment} from "@/types/comment";
import {cancelCommentLikeApi, commentLikeApi, commentListApi, replyListApi} from "@/api/comment"; import {cancelCommentLikeApi, commentLikeApi, commentListApi, replyListApi} from "@/api/comment";
import {message} from "ant-design-vue"; import {message} from "ant-design-vue";
import {getSlideCaptchaDataApi} from "@/api/captcha"; import {getSlideCaptchaDataApi} from "@/api/captcha";
import imageCompression from "browser-image-compression";
export const useCommentStore = defineStore( export const useCommentStore = defineStore(
'comment', 'comment',
@@ -25,6 +25,8 @@ export const useCommentStore = defineStore(
thumbX: 0, thumbX: 0,
thumbY: 0 thumbY: 0
}); });
const fileList = ref<any[]>([]);
const imageList = ref<any[]>([]);
/** /**
* 获取评论列表 * 获取评论列表
@@ -147,6 +149,115 @@ export const useCommentStore = defineStore(
return false; return false;
} }
/**
* 清空文件列表
*/
async function clearFileList() {
fileList.value = [];
imageList.value = [];
}
/**
* 上传文件前置
* @param file
*/
async function beforeUpload(file: any) {
// 压缩图片配置
const options = {
maxSizeMB: 0.4,
maxWidthOrHeight: 750,
maxIteration: 2
};
if (!window.FileReader) return false; // 判断是否支持FileReader
const compressedFile = await imageCompression(file, options);
const reader = new FileReader();
reader.readAsDataURL(compressedFile); // 文件转换
reader.onloadend = async function () {
if (fileList.value.length < 3) {
const img: HTMLImageElement = document.createElement('img');
img.src = reader.result as string;
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
const ctx = canvas.getContext('2d');
if (!ctx) {
console.error('Failed to get canvas context');
return;
}
ctx.drawImage(img, 0, 0);
ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
ctx.textBaseline = 'middle';
// 动态设置字体大小,假设字体大小为画布高度的 5%
const fontSize = canvas.height * 0.05; // 可以根据需要调整比例
ctx.font = `${fontSize}px Microsoft Yahei`;
// 计算文本的宽度和高度,以便将其放置在右下角
const text = 'schisandra';
const textWidth = ctx.measureText(text).width;
const textHeight = fontSize; // 字体大小
// 设置文本的位置到右下角
const x: number = canvas.width - textWidth - 5; // 距离右边缘 5 像素
const y: number = canvas.height - textHeight / 2 - 5; // 距离下边缘 5 像素
ctx.fillText('schisandra', x, y);
fileList.value.push(canvas.toDataURL());
};
} else {
return false;
}
};
return true;
}
/**
* 自定义上传图片请求
*/
async function customUploadRequest() {
imageList.value = fileList.value;
}
/**
* 移除图片
* @param index
*/
async function removeBase64Image(index: number) {
fileList.value.splice(index, 1);
imageList.value.splice(index, 1);
}
/**
* 格式化时间
* @param dateString
*/
function formatTimeAgo(dateString: string) {
const now: any = new Date();
const date: any = new Date(dateString);
const seconds = Math.floor((now - date) / 1000);
const intervals = [
{label: '年', seconds: 31536000},
{label: '个月', seconds: 2592000},
{label: '天', seconds: 86400},
{label: '小时', seconds: 3600},
{label: '分钟', seconds: 60}
];
for (const interval of intervals) {
const count = Math.floor(seconds / interval.seconds);
if (count > 0) {
return `${count} ${interval.label}`;
}
}
return `${seconds} 秒前`;
}
return { return {
commentList, commentList,
commentLoading, commentLoading,
@@ -156,6 +267,8 @@ export const useCommentStore = defineStore(
replyLoading, replyLoading,
slideCaptchaData, slideCaptchaData,
commentMap, commentMap,
fileList,
imageList,
getCommentList, getCommentList,
handleShowReplyInput, handleShowReplyInput,
closeReplyInput, closeReplyInput,
@@ -164,6 +277,11 @@ export const useCommentStore = defineStore(
commentLike, commentLike,
cancelCommentLike, cancelCommentLike,
getSlideCaptchaData, getSlideCaptchaData,
beforeUpload,
customUploadRequest,
removeBase64Image,
clearFileList,
formatTimeAgo,
}; };
}, },
{ {