diff --git a/web/src/assets/css/main.less b/web/src/assets/css/main.less index 926485a6..0ae8cc30 100644 --- a/web/src/assets/css/main.less +++ b/web/src/assets/css/main.less @@ -1,6 +1,6 @@ :root { // 如果要变更中间栏的大小,修改此处即可 - --content-main: 910px; + --content-main: 820px; } .app-container { diff --git a/web/src/components/auth.vue b/web/src/components/auth.vue index 9916c7ee..8ee6a4d9 100644 --- a/web/src/components/auth.vue +++ b/web/src/components/auth.vue @@ -175,11 +175,31 @@ const registerForm = reactive({ password: '', repassword: '', }); +const forbiddenUsernames = [ + 'aimo', 'zhaizhai', 'admin', 'test', 'service', 'user', + 'tw', 'hk', 'zhongguo', 'china', 'chinese', 'taiwan', + 'xianggang', 'fuck', 'suck' +]; + const registerRule = { - username: { - required: true, - message: '请输入账户名', - }, + username: [ + { + required: true, + message: '请输入账户名', + }, + { + validator: (rule: FormItemRule, value: any) => { + const lowercaseValue = value.toLowerCase(); // 转换为小写 + const isForbidden = forbiddenUsernames.some(keyword => lowercaseValue.includes(keyword)); + if (isForbidden) { + return Promise.reject('用户名已被注册'); + } else { + return Promise.resolve(); + } + }, + trigger: 'blur', + }, + ], password: { required: true, message: '请输入密码', diff --git a/web/src/components/compose-comment.vue b/web/src/components/compose-comment.vue index 71dfbb66..03a12dc1 100644 --- a/web/src/components/compose-comment.vue +++ b/web/src/components/compose-comment.vue @@ -279,15 +279,88 @@ const beforeUpload = async (data: any) => { window.$message.warning('图片大小不能超过10MB'); return false; } - + if(uploadType.value === 'public/image') { + const compressedFile = await compressionFile(data.file.file); + data.file.file = compressedFile; + } return true; }; + +/** + * 图片压缩方法 + * @param {Object} file 图片文件 + * @param {String} type 想压缩成的文件类型 + * @param {Number} quality 压缩质量参数 + * @returns 压缩后的新图片 + */ + const compressionFile = async ( + file: Blob, + type: string = 'image/jpeg', + quality: number = 0.4, + maxWidth: number = 1920, // 设置压缩后的最大宽度 + maxHeight: number = 1920 // 设置压缩后的最大高度 + ) => { + const fileName = file.name; + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d') as CanvasRenderingContext2D; + + const base64 = await fileToDataURL(file); + const img = await dataURLToImage(base64); + + // 计算新的宽度和高度,以实现像素压缩 + let newWidth = img.width; + let newHeight = img.height; + if (img.width > maxWidth) { + newWidth = maxWidth; + newHeight = (img.height * maxWidth) / img.width; + } + if (newHeight > maxHeight) { + newHeight = maxHeight; + newWidth = (img.width * maxHeight) / img.height; + } + + canvas.width = newWidth; + canvas.height = newHeight; + + context.clearRect(0, 0, newWidth, newHeight); + context.drawImage(img, 0, 0, newWidth, newHeight); + + const blob = (await canvasToFile(canvas, type, quality)) as Blob; + + // quality:0.5可根据实际情况计算 + const newFile = new File([blob], fileName, {type}); + + return newFile; +} +const fileToDataURL = (file: Blob): Promise => { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.onloadend = (e) => resolve((e.target as FileReader).result); + reader.readAsDataURL(file); + }); +} + +const dataURLToImage = (dataURL: string): Promise => { + return new Promise((resolve) => { + const img = new Image(); + img.onload = () => resolve(img); + img.src = dataURL; + }); +} + +const canvasToFile = (canvas: HTMLCanvasElement, type: string, quality: number): Promise => { + return new Promise((resolve) => + canvas.toBlob((blob) => resolve(blob), type, quality) + ); +} + const finishUpload = ({ file, event }: any): any => { try { let data = JSON.parse(event.target?.response); if (data.code === 0) { if (uploadType.value === 'public/image') { + imageContents.value.push({ id: file.id, content: data.data.content, diff --git a/web/src/components/compose.vue b/web/src/components/compose.vue index 45e4441a..49963152 100644 --- a/web/src/components/compose.vue +++ b/web/src/components/compose.vue @@ -440,6 +440,11 @@ const beforeUpload = async (data: any) => { return false; } + if(uploadType.value === 'public/image') { + const compressedFile = await compressionFile(data.file.file); + data.file.file = compressedFile; + } + // 视频类型校验 if ( uploadType.value === 'public/video' && @@ -471,6 +476,75 @@ const beforeUpload = async (data: any) => { return true; }; + +/** + * 图片压缩方法 + * @param {Object} file 图片文件 + * @param {String} type 想压缩成的文件类型 + * @param {Number} quality 压缩质量参数 + * @returns 压缩后的新图片 + */ +const compressionFile = async ( + file: Blob, + type: string = 'image/jpeg', + quality: number = 0.4, + maxWidth: number = 1920, // 设置压缩后的最大宽度 + maxHeight: number = 1920 // 设置压缩后的最大高度 + ) => { + const fileName = file.name; + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d') as CanvasRenderingContext2D; + + const base64 = await fileToDataURL(file); + const img = await dataURLToImage(base64); + + // 计算新的宽度和高度,以实现像素压缩 + let newWidth = img.width; + let newHeight = img.height; + if (img.width > maxWidth) { + newWidth = maxWidth; + newHeight = (img.height * maxWidth) / img.width; + } + if (newHeight > maxHeight) { + newHeight = maxHeight; + newWidth = (img.width * maxHeight) / img.height; + } + + canvas.width = newWidth; + canvas.height = newHeight; + + context.clearRect(0, 0, newWidth, newHeight); + context.drawImage(img, 0, 0, newWidth, newHeight); + + const blob = (await canvasToFile(canvas, type, quality)) as Blob; + + // quality:0.5可根据实际情况计算 + const newFile = new File([blob], fileName, {type}); + + return newFile; +} +const fileToDataURL = (file: Blob): Promise => { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.onloadend = (e) => resolve((e.target as FileReader).result); + reader.readAsDataURL(file); + }); +} + +const dataURLToImage = (dataURL: string): Promise => { + return new Promise((resolve) => { + const img = new Image(); + img.onload = () => resolve(img); + img.src = dataURL; + }); +} + +const canvasToFile = (canvas: HTMLCanvasElement, type: string, quality: number): Promise => { + return new Promise((resolve) => + canvas.toBlob((blob) => resolve(blob), type, quality) + ); +} + const finishUpload = ({ file, event }: any): any => { try { let data = JSON.parse(event.target?.response);