From 4f42d1c5b45ac9327c7b71463aefe733ba72584d Mon Sep 17 00:00:00 2001
From: landaiqing <3517283258@qq.com>
Date: Thu, 26 Sep 2024 12:00:48 +0800
Subject: [PATCH] :art: organize code structure
---
components.d.ts | 23 ++--
.../Components/CommentInput/CommentInput.vue | 83 +++---------
.../Components/CommentList/CommentList.vue | 22 ++--
.../Components/ReplyInput/ReplyInput.vue | 81 +++---------
.../Components/ReplyList/ReplyList.vue | 26 ++--
.../Components/ReplyReplyInput/ReplyReply.vue | 87 ++++---------
src/store/modules/commentStore.ts | 120 +++++++++++++++++-
7 files changed, 219 insertions(+), 223 deletions(-)
diff --git a/components.d.ts b/components.d.ts
index e6c7b06..587b1d3 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -19,6 +19,7 @@ declare module 'vue' {
AForm: typeof import('ant-design-vue/es')['Form']
AFormItem: typeof import('ant-design-vue/es')['FormItem']
AImage: typeof import('ant-design-vue/es')['Image']
+ AImagePreviewGroup: typeof import('ant-design-vue/es')['ImagePreviewGroup']
AInput: typeof import('ant-design-vue/es')['Input']
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
AMenu: typeof import('ant-design-vue/es')['Menu']
@@ -35,17 +36,17 @@ declare module 'vue' {
ATextarea: typeof import('ant-design-vue/es')['Textarea']
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
AUpload: typeof import('ant-design-vue/es')['Upload']
- BoxDog: typeof import('./src/Components/BoxDog/BoxDog.vue')['default']
- Card3D: typeof import('./src/Components/Card3D/Card3D.vue')['default']
+ BoxDog: typeof import('./src/components/BoxDog/BoxDog.vue')['default']
+ Card3D: typeof import('./src/components/Card3D/Card3D.vue')['default']
CloseCircleOutlined: typeof import('@ant-design/icons-vue')['CloseCircleOutlined']
- Clouds: typeof import('./src/Components/Clouds/Clouds.vue')['default']
- CommentInput: typeof import('./src/Components/CommentReply/Components/CommentInput/CommentInput.vue')['default']
- CommentList: typeof import('./src/Components/CommentReply/Components/CommentList/CommentList.vue')['default']
- CommentReply: typeof import('./src/Components/CommentReply/index.vue')['default']
+ Clouds: typeof import('./src/components/Clouds/Clouds.vue')['default']
+ CommentInput: typeof import('./src/components/CommentReply/Components/CommentInput/CommentInput.vue')['default']
+ CommentList: typeof import('./src/components/CommentReply/Components/CommentList/CommentList.vue')['default']
+ CommentReply: typeof import('./src/components/CommentReply/index.vue')['default']
CopyOutlined: typeof import('@ant-design/icons-vue')['CopyOutlined']
DeleteOutlined: typeof import('@ant-design/icons-vue')['DeleteOutlined']
- DynamicTitle: typeof import('./src/Components/DynamicTitle/DynamicTitle.vue')['default']
- EffectsCard: typeof import('./src/Components/EffectsCard/EffectsCard.vue')['default']
+ DynamicTitle: typeof import('./src/components/DynamicTitle/DynamicTitle.vue')['default']
+ EffectsCard: typeof import('./src/components/EffectsCard/EffectsCard.vue')['default']
EyeOutlined: typeof import('@ant-design/icons-vue')['EyeOutlined']
ForgetPage: typeof import('./src/views/Forget/ForgetPage.vue')['default']
GithubOutlined: typeof import('@ant-design/icons-vue')['GithubOutlined']
@@ -58,9 +59,9 @@ declare module 'vue' {
QqOutlined: typeof import('@ant-design/icons-vue')['QqOutlined']
QRLogin: typeof import('./src/views/QRLogin/QRLogin.vue')['default']
QRLoginFooter: typeof import('./src/views/QRLogin/QRLoginFooter.vue')['default']
- ReplyInput: typeof import('./src/Components/CommentReply/Components/ReplyInput/ReplyInput.vue')['default']
- ReplyList: typeof import('./src/Components/CommentReply/Components/ReplyList/ReplyList.vue')['default']
- ReplyReply: typeof import('./src/Components/CommentReply/Components/ReplyReplyInput/ReplyReply.vue')['default']
+ ReplyInput: typeof import('./src/components/CommentReply/Components/ReplyInput/ReplyInput.vue')['default']
+ ReplyList: typeof import('./src/components/CommentReply/Components/ReplyList/ReplyList.vue')['default']
+ ReplyReply: typeof import('./src/components/CommentReply/Components/ReplyReplyInput/ReplyReply.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SafetyOutlined: typeof import('@ant-design/icons-vue')['SafetyOutlined']
diff --git a/src/components/CommentReply/Components/CommentInput/CommentInput.vue b/src/components/CommentReply/Components/CommentInput/CommentInput.vue
index 3668eee..6af9f57 100644
--- a/src/components/CommentReply/Components/CommentInput/CommentInput.vue
+++ b/src/components/CommentReply/Components/CommentInput/CommentInput.vue
@@ -35,28 +35,30 @@
method="post"
:directory="false"
:show-upload-list="false"
- :custom-request="customUploadRequest"
- :before-upload="beforeUpload"
- :disabled="imageList.length >= 3"
+ :custom-request="comment.customUploadRequest"
+ :before-upload="comment.beforeUpload"
+ :disabled="comment.imageList.length >= 3"
>
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
+
+
+
+
+
+
+
@@ -90,15 +92,14 @@ import useStore from "@/store";
import {message} from "ant-design-vue";
import {commentSubmitApi} from "@/api/comment";
import {useDebounceFn, useThrottleFn} from "@vueuse/core";
-import imageCompression from "browser-image-compression";
+
import {useRouter} from "vue-router";
const {t} = useI18n();
const showCommentActions = ref(false);
const commentContent = ref("");
-const fileList = ref([]);
-const imageList = ref([]);
+
const user = useStore().user;
const commentTextAreaPlaceholder = ref(t('comment.placeholder'));
const topicId = ref("123");
@@ -146,7 +147,7 @@ async function commentSubmit(point: any) {
message.error(t('comment.commentContentNotEmpty'));
return;
}
- if (imageList.value.length > 3) {
+ if (comment.imageList.length > 3) {
message.error(t('comment.maxImageCount'));
return;
}
@@ -156,7 +157,7 @@ async function commentSubmit(point: any) {
user_id: user.user.uid,
topic_id: topicId.value,
content: content,
- images: imageList.value,
+ images: comment.imageList,
author: user.user.uid,
point: [point.x, point.y],
key: comment.slideCaptchaData.key,
@@ -165,8 +166,7 @@ async function commentSubmit(point: any) {
if (result.code === 200 && result.success) {
message.success(t('comment.commentSuccess'));
commentContent.value = "";
- fileList.value = [];
- imageList.value = [];
+ await comment.clearFileList();
showSubmitCaptcha.value = false;
await getCommentList();
} else {
@@ -188,47 +188,6 @@ async function getCommentList(page: number = 1, size: number = 5, hot: boolean =
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);
diff --git a/src/components/CommentReply/Components/CommentList/CommentList.vue b/src/components/CommentReply/Components/CommentList/CommentList.vue
index 4193df1..ebe43f3 100644
--- a/src/components/CommentReply/Components/CommentList/CommentList.vue
+++ b/src/components/CommentReply/Components/CommentList/CommentList.vue
@@ -49,16 +49,18 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/CommentReply/Components/ReplyInput/ReplyInput.vue b/src/components/CommentReply/Components/ReplyInput/ReplyInput.vue
index a5321cd..27f37f6 100644
--- a/src/components/CommentReply/Components/ReplyInput/ReplyInput.vue
+++ b/src/components/CommentReply/Components/ReplyInput/ReplyInput.vue
@@ -48,28 +48,30 @@
method="post"
:directory="false"
:show-upload-list="false"
- :custom-request="customUploadRequest"
- :before-upload="beforeUpload"
- :disabled="imageList.length >= 3"
+ :custom-request="comment.customUploadRequest"
+ :before-upload="comment.beforeUpload"
+ :disabled="comment.imageList.length >= 3"
>
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
+
+
+
+
+
+
+
@@ -98,7 +100,6 @@
import {h, ref} from "vue";
import {message} from "ant-design-vue";
-import imageCompression from "browser-image-compression";
import {CloseOutlined, PictureOutlined, SmileOutlined} from "@ant-design/icons-vue";
import EMOJI from "@/constant/emoji.ts";
import {useI18n} from "vue-i18n";
@@ -110,8 +111,6 @@ const {t} = useI18n();
const comment = useStore().comment;
const user = useStore().user;
const commentTextAreaPlaceholder = ref(t('comment.placeholder'));
-const fileList = ref([]);
-const imageList = ref([]);
const replyContent = ref("");
const topicId = ref("123");
const showSubmitCaptcha = ref(false);
@@ -141,47 +140,6 @@ async function insertEmojiToReplyContent(emoji: string) {
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
@@ -196,7 +154,7 @@ async function replySubmit(point: any) {
message.error(t('comment.commentContentNotEmpty'));
return;
}
- if (imageList.value.length > 3) {
+ if (comment.imageList.length > 3) {
message.error(t('comment.maxImageCount'));
return;
}
@@ -216,7 +174,7 @@ async function replySubmit(point: any) {
user_id: user.user.uid,
topic_id: topicId.value,
content: content,
- images: imageList.value,
+ images: comment.imageList,
author: user.user.uid,
reply_id: props.item.id,
reply_user: props.item.user_id,
@@ -226,8 +184,7 @@ async function replySubmit(point: any) {
const result: any = await replySubmitApi(replyParams);
if (result.code === 200 && result.success) {
replyContent.value = "";
- fileList.value = [];
- imageList.value = [];
+ await comment.clearFileList();
showSubmitCaptcha.value = false;
await getReplyList();
comment.closeReplyInput();
diff --git a/src/components/CommentReply/Components/ReplyList/ReplyList.vue b/src/components/CommentReply/Components/ReplyList/ReplyList.vue
index a5bf318..fd0c429 100644
--- a/src/components/CommentReply/Components/ReplyList/ReplyList.vue
+++ b/src/components/CommentReply/Components/ReplyList/ReplyList.vue
@@ -28,16 +28,18 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
@@ -141,9 +143,8 @@ const props = defineProps({
}
});
-
/**
- * 格式化时间
+ * 格式化时间
* @param dateString
*/
function formatTimeAgo(dateString: string) {
@@ -169,6 +170,7 @@ function formatTimeAgo(dateString: string) {
return `${seconds} 秒前`;
}
+
const commentLikeThrottled = useThrottleFn(commentLike, 1000);
/**
diff --git a/src/components/CommentReply/Components/ReplyReplyInput/ReplyReply.vue b/src/components/CommentReply/Components/ReplyReplyInput/ReplyReply.vue
index 52e9fc7..eca8ab8 100644
--- a/src/components/CommentReply/Components/ReplyReplyInput/ReplyReply.vue
+++ b/src/components/CommentReply/Components/ReplyReplyInput/ReplyReply.vue
@@ -51,30 +51,32 @@
method="post"
:directory="false"
:show-upload-list="false"
- :custom-request="customUploadRequest"
- :before-upload="beforeUpload"
- :disabled="imageList.length >= 3"
+ :custom-request="comment.customUploadRequest"
+ :before-upload="comment.beforeUpload"
+ :disabled="comment.imageList.length >= 3"
>
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
+
+
+
+
+
+
+
@@ -110,14 +112,12 @@ import {message} from "ant-design-vue";
import {replyReplySubmitApi} from "@/api/comment";
import {ReplyCommentParams} from "@/types/comment";
import {useThrottleFn} from "@vueuse/core";
-import imageCompression from "browser-image-compression";
const {t} = useI18n();
const commentTextAreaPlaceholder = ref(t('comment.placeholder'));
const comment = useStore().comment;
const replyReplyContent = ref("");
-const fileList = ref([]);
-const imageList = ref([]);
+
const user = useStore().user;
const topicId = ref("123");
const showSubmitCaptcha = ref(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
*/
@@ -208,7 +166,7 @@ async function replyReplySubmit(point: any) {
message.error(t('comment.commentContentNotEmpty'));
return;
}
- if (imageList.value.length > 3) {
+ if (comment.imageList.length > 3) {
message.error(t('comment.maxImageCount'));
return;
}
@@ -218,7 +176,7 @@ async function replyReplySubmit(point: any) {
user_id: user.user.uid,
topic_id: topicId.value,
content: content,
- images: imageList.value,
+ images: comment.imageList,
author: user.user.uid,
reply_to: props.child.id,
reply_id: props.item.id,
@@ -230,8 +188,7 @@ async function replyReplySubmit(point: any) {
if (result.code === 200 && result.success) {
replyReplyContent.value = "";
- fileList.value = [];
- imageList.value = [];
+ await comment.clearFileList();
showSubmitCaptcha.value = false;
await getReplyList();
comment.closeReplyInput();
diff --git a/src/store/modules/commentStore.ts b/src/store/modules/commentStore.ts
index 71276f3..3b6376c 100644
--- a/src/store/modules/commentStore.ts
+++ b/src/store/modules/commentStore.ts
@@ -4,7 +4,7 @@ import {Comment} from "@/types/comment";
import {cancelCommentLikeApi, commentLikeApi, commentListApi, replyListApi} from "@/api/comment";
import {message} from "ant-design-vue";
import {getSlideCaptchaDataApi} from "@/api/captcha";
-
+import imageCompression from "browser-image-compression";
export const useCommentStore = defineStore(
'comment',
@@ -25,6 +25,8 @@ export const useCommentStore = defineStore(
thumbX: 0,
thumbY: 0
});
+ const fileList = ref([]);
+ const imageList = ref([]);
/**
* 获取评论列表
@@ -147,6 +149,115 @@ export const useCommentStore = defineStore(
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 {
commentList,
commentLoading,
@@ -156,6 +267,8 @@ export const useCommentStore = defineStore(
replyLoading,
slideCaptchaData,
commentMap,
+ fileList,
+ imageList,
getCommentList,
handleShowReplyInput,
closeReplyInput,
@@ -164,6 +277,11 @@ export const useCommentStore = defineStore(
commentLike,
cancelCommentLike,
getSlideCaptchaData,
+ beforeUpload,
+ customUploadRequest,
+ removeBase64Image,
+ clearFileList,
+ formatTimeAgo,
};
},
{