improve api

This commit is contained in:
2025-03-06 00:07:21 +08:00
parent b77217f724
commit a20ea6c76b
8 changed files with 159 additions and 126 deletions

18
src/api/auth/index.ts Normal file
View File

@@ -0,0 +1,18 @@
import {service} from "@/utils/alova/service.ts";
/**
* 获取分享统计信息
*/
export const checkSecuritySettingApi = () => {
return service.Post('/api/auth/user/check/security/setting', {}, {
cacheFor: {
expire: 60 * 60 * 24 * 7,
mode: "restore",
},
meta: {
ignoreToken: false,
signature: false,
},
name: "check-security-setting",
});
};

View File

@@ -10,6 +10,7 @@ export const shareImageUploadApi = (formData) => {
ignoreToken: false,
signature: false,
},
name: 'upload-share-image',
});
};
/**

View File

@@ -561,3 +561,37 @@ export const addStorageConfigApi = (params: any) => {
name: "add-storage-config",
});
};
/**
* 获取用户上传信息
*/
export const getUserUploadInfoApi = () => {
return service.Post('/api/auth/storage/user/upload/info', {}, {
cacheFor: {
expire: 60 * 60 * 24 * 7,
mode: "restore",
},
meta: {
ignoreToken: false,
signature: false,
},
name: "get-user-upload-info",
hitSource: ["upload-file", "delete-images"],
});
};
/**
* 获取分享统计信息
*/
export const getShareStatisticsInfoApi = () => {
return service.Post('/api/auth/storage/share/recent/info', {}, {
cacheFor: {
expire: 60 * 60 * 24 * 7,
mode: "restore",
},
meta: {
ignoreToken: false,
signature: false,
},
name: "get-share-statistics-info",
hitSource: ["upload-file", "upload-share-image"],
});
};

View File

@@ -116,7 +116,7 @@ import {NSFWJS} from "nsfwjs";
import {initNSFWJs, predictNSFW} from "@/utils/tfjs/nsfw.ts";
import {message} from "ant-design-vue";
import i18n from "@/locales";
import {bytesToSize} from "@/utils/imageUtils/bytesToSize.ts";
import bytesToSize from "@/utils/imageUtils/bytesToSize.ts";
import {cocoSsdPredict} from "@/utils/tfjs/mobilenet.ts";
dayjs.locale('zh-cn');

View File

@@ -1,4 +1,4 @@
export function bytesToSize(bytes: number, decimals = 2): string {
export default function bytesToSize(bytes: number, decimals = 2): string {
if (bytes === 0) return '0 Bytes';
const k = 1024;
@@ -9,7 +9,3 @@ export function bytesToSize(bytes: number, decimals = 2): string {
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
// 使用示例
// console.log(bytesToSize(1024)); // 输出: 1 KB
// console.log(bytesToSize(123456789)); // 输出: 117.74 MB

View File

@@ -26,7 +26,7 @@
<AAvatar size="default" :src="accountSecurity"/>
<span style="font-size: 20px; font-weight: bold;color: #333">账号安全</span>
</div>
<div class="account-setting-home-content-section">
<div class="account-setting-home-content-section" v-if="securityStatus">
<AFlex :vertical="false" align="center" justify="space-between" :gap="50">
<div class="account-setting-home-content-section-item">
<div class="account-setting-home-content-section-item-avatar">
@@ -36,8 +36,10 @@
<span style="font-size: 18px; font-weight: bold;color: #333;margin-top: 10px">我的邮箱</span>
<span style="font-size: 14px; color: #666;">绑定邮箱后即可使用邮箱登录</span>
<AFlex :vertical="false" align="center" justify="space-between" gap="large">
<AButton type="primary" size="small" :disabled="true">已绑定邮箱</AButton>
<AButton type="link" size="small">更改邮箱</AButton>
<AButton type="primary" size="small" :disabled="securityStatus.bind_email">
{{ securityStatus.bind_email ? "已绑定邮箱" : "绑定邮箱" }}
</AButton>
<AButton type="link" size="small">{{ securityStatus.bind_email ? "修改邮箱" : "绑定邮箱" }}</AButton>
</AFlex>
</div>
</div>
@@ -64,8 +66,10 @@
<span style="font-size: 18px; font-weight: bold;color: #333;margin-top: 10px">我的密保</span>
<span style="font-size: 14px; color: #666;">设置密保账号更安全</span>
<AFlex :vertical="false" align="center" justify="space-between" gap="large">
<AButton type="primary" size="small" :disabled="true">已绑定密保</AButton>
<AButton type="link" size="small">查看并设置</AButton>
<AButton type="primary" size="small" :disabled="securityStatus.set_password">
{{ securityStatus.set_password ? "已设置密保" : "设置密保" }}
</AButton>
<AButton type="link" size="small">{{ securityStatus.set_password ? "修改密保" : "设置密保" }}</AButton>
</AFlex>
</div>
</div>
@@ -77,8 +81,10 @@
<span style="font-size: 18px; font-weight: bold;color: #333;margin-top: 10px">三方登录</span>
<span style="font-size: 14px; color: #666;">绑定三方账号安全登录</span>
<AFlex :vertical="false" align="center" justify="space-between" gap="large">
<AButton type="primary" size="small" :disabled="true">已绑定三方账号</AButton>
<AButton type="link" size="small">取消绑定</AButton>
<AButton type="primary" size="small" :disabled="securityStatus.bind_wechet">
{{ securityStatus.bind_wechet ? "已绑定" : "绑定" }}
</AButton>
<AButton type="link" size="small">{{ securityStatus.bind_wechet ? "管理" : "" }}</AButton>
</AFlex>
</div>
</div>
@@ -95,9 +101,24 @@ import emailSecurity from "@/assets/svgs/email_security.svg";
import phoneSecurity from "@/assets/svgs/phone_security.svg";
import passwordSecurity from "@/assets/svgs/password_security.svg";
import loginSecurity from "@/assets/svgs/login_security.svg";
import {checkSecuritySettingApi} from "@/api/auth";
const userStore = useStore().user;
const securityStatus = ref<any>();
async function checkStatus() {
const res: any = await checkSecuritySettingApi();
console.log(res);
if (res && res.code === 200) {
securityStatus.value = res.data;
}
}
onMounted(() => {
checkStatus();
});
</script>
<style scoped lang="scss">

View File

@@ -5,8 +5,32 @@
</template>
<script setup lang="ts">
import * as echarts from 'echarts';
import {getShareStatisticsInfoApi} from "@/api/storage";
interface DataItem {
date: string;
visit_count: number;
visitor_count: number;
publish_count: number;
}
const chartRef = ref<any>(null);
const dates = ref<string[]>([]);
const visitCounts = ref<number[]>([]);
const visitorCounts = ref<number[]>([]);
const publishCounts = ref<number[]>([]);
async function getData() {
const res: any = await getShareStatisticsInfoApi();
if (res && res.code === 200) {
const data: DataItem[] = res.data.records;
dates.value = data.map((item: DataItem) => item.date);
visitCounts.value = data.map((item: DataItem) => item.visit_count);
visitorCounts.value = data.map((item: DataItem) => item.visitor_count);
publishCounts.value = data.map((item: DataItem) => item.publish_count);
}
}
onMounted(async () => {
await nextTick();
const chartInstance = echarts.init(chartRef.value);
@@ -16,10 +40,8 @@ onMounted(async () => {
backgroundColor: "#fff",
title: {
text: "最近七天分享统计",
textStyle: {
fontSize: 12,
fontWeight: 400,
},
fontSize: 12,
fontWeight: 400,
left: "center",
top: "5%",
},
@@ -29,9 +51,8 @@ onMounted(async () => {
right: "5%",
itemWidth: 6,
itemGap: 20,
textStyle: {
color: "#556677",
},
color: "#556677",
},
tooltip: {
trigger: "axis",
@@ -49,9 +70,7 @@ onMounted(async () => {
},
},
backgroundColor: "#fff",
textStyle: {
color: "#5c6c7c",
},
color: "#5c6c7c",
padding: [10, 10],
extraCssText: "box-shadow: 1px 0 2px 0 rgba(163,163,163,0.5)",
},
@@ -61,7 +80,7 @@ onMounted(async () => {
xAxis: [
{
type: "category",
data: ["2025-3-5", "2025-3-6", "2025-3-7", "2025-3-8", "2025-3-9", "2025-3-10", "2025-3-11"],
data: dates.value,
axisLine: {
lineStyle: {
color: "#DCE2E8",
@@ -72,9 +91,7 @@ onMounted(async () => {
},
axisLabel: {
interval: 0,
textStyle: {
color: "#556677",
},
color: "#556677",
// 默认x轴字体大小
fontSize: 12,
// margin:文字到x轴的距离
@@ -153,9 +170,7 @@ onMounted(async () => {
},
},
axisLabel: {
textStyle: {
color: "#556677",
},
color: "#556677",
},
splitLine: {
show: false,
@@ -168,9 +183,7 @@ onMounted(async () => {
show: false,
},
axisLabel: {
textStyle: {
color: "#556677",
},
color: "#556677",
formatter: "{value}",
},
axisLine: {
@@ -188,7 +201,7 @@ onMounted(async () => {
{
name: "浏览次数",
type: "line",
data: [10, 10, 30, 12, 15, 3, 7],
data: visitCounts.value,
symbolSize: 1,
symbol: "circle",
smooth: true,
@@ -211,16 +224,14 @@ onMounted(async () => {
shadowOffsetY: 20,
},
itemStyle: {
normal: {
color: colorList[0],
borderColor: colorList[0],
},
color: colorList[0],
borderColor: colorList[0],
},
},
{
name: "浏览人数",
type: "line",
data: [5, 12, 11, 14, 25, 16, 10],
data: visitorCounts.value,
symbolSize: 1,
symbol: "circle",
smooth: true,
@@ -243,16 +254,14 @@ onMounted(async () => {
shadowOffsetY: 20,
},
itemStyle: {
normal: {
color: colorList[1],
borderColor: colorList[1],
},
color: colorList[1],
borderColor: colorList[1],
},
},
{
name: "发布次数",
type: "line",
data: [150, 120, 170, 140, 500, 160, 110],
data: publishCounts.value,
symbolSize: 1,
yAxisIndex: 1,
symbol: "circle",
@@ -275,10 +284,8 @@ onMounted(async () => {
shadowOffsetY: 20,
},
itemStyle: {
normal: {
color: colorList[2],
borderColor: colorList[2],
},
color: colorList[2],
borderColor: colorList[2],
},
},
],
@@ -286,6 +293,11 @@ onMounted(async () => {
chartInstance.setOption(option);
});
onBeforeMount(() => {
getData();
});
onBeforeUnmount(() => {
if (chartRef.value) {
const chartInstance = echarts.getInstanceByDom(chartRef.value);

View File

@@ -1,7 +1,7 @@
<template>
<div class="user-center-home">
<div class="user-center-home-left">
<div class="user-center-home-left-top">
<div class="user-center-home-left-top" v-if="chartData">
<div class="user-center-home-left-top-card"
style="background: linear-gradient(102.74deg, rgb(66, 230, 171) -7.03%, rgb(103, 235, 187) 97.7%);">
<div class="user-center-home-left-top-card-top">
@@ -10,12 +10,12 @@
</div>
<div class="user-center-home-left-top-card-top-name">
<span style="font-size: 2.8vh;color: rgba(255, 255, 255, 0.6); font-weight: bold;">图片总数</span>
<span style="font-size: 3.8vh;font-weight: bold;color: #ffffff">50</span>
<span style="font-size: 3.8vh;font-weight: bold;color: #ffffff">{{ chartData.image_count }}</span>
</div>
</div>
<div class="user-center-home-left-top-card-bottom">
<span style="font-size: 2.3vh;color: rgba(255, 255, 255, 0.6); font-weight: bold;">今日上传</span>
<span style="font-size: 3vh;font-weight: bold;color: #ffffff">+10</span>
<span style="font-size: 3vh;font-weight: bold;color: #ffffff">+{{ chartData.today_upload_count }}</span>
</div>
</div>
<div class="user-center-home-left-top-card"
@@ -26,12 +26,12 @@
</div>
<div class="user-center-home-left-top-card-top-name">
<span style="font-size: 2.8vh;color: rgba(255, 255, 255, 0.6); font-weight: bold;">分享总数</span>
<span style="font-size: 3.8vh;font-weight: bold;color: white">50</span>
<span style="font-size: 3.8vh;font-weight: bold;color: white">{{ chartData.share_count }}</span>
</div>
</div>
<div class="user-center-home-left-top-card-bottom">
<span style="font-size: 2.3vh;color: rgba(255, 255, 255, 0.6); font-weight: bold;">今日上传</span>
<span style="font-size: 2.8vh;font-weight: bold;color: white">+10</span>
<span style="font-size: 2.8vh;font-weight: bold;color: white">+{{ chartData.today_share_count }}</span>
</div>
</div>
<div class="user-center-home-left-top-card"
@@ -42,18 +42,24 @@
</div>
<div class="user-center-home-left-top-card-top-name">
<span style="font-size: 2.8vh;color: rgba(255, 255, 255, 0.6); font-weight: bold;">文件总量</span>
<span style="font-size: 3.8vh;font-weight: bold;color: white">50</span>
<span
style="font-size: 3.8vh;font-weight: bold;color: white">{{
bytesToSize(chartData.file_size_count)
}}</span>
</div>
</div>
<div class="user-center-home-left-top-card-bottom">
<span style="font-size: 2.3vh;color: rgba(255, 255, 255, 0.6);font-weight: bold;">今日上传</span>
<span style="font-size: 2.8vh;font-weight: bold;color: white">+10</span>
<span
style="font-size: 2.8vh;font-weight: bold;color: white">+{{
bytesToSize(chartData.today_file_size_count)
}}</span>
</div>
</div>
</div>
<div class="user-center-home-left-bottom">
<div class="user-center-home-left-bottom" v-if="chartData">
<span style="font-size: 16px; font-weight: bold; margin-left: 20px;">文件上传热力图</span>
<HeatmapPro :contributions="timeValue" :width="'100%'" :height="'100%'"/>
<HeatmapPro :contributions="chartData.heatmap"/>
</div>
</div>
<div class="user-center-home-right">
@@ -69,76 +75,21 @@ import HeatmapPro from "@/components/HeatmapPro/HeatmapPro.vue";
import imageIcon from "@/assets/svgs/image-icon.svg";
import shareIcon from "@/assets/svgs/share-icon.svg";
import fileSize from "@/assets/svgs/file-size.svg";
import {getUserUploadInfoApi} from "@/api/storage";
import bytesToSize from "@/utils/imageUtils/bytesToSize";
const timeValue = [
{date: "2024-08-02", count: 1},
{date: "2024-08-03", count: 2},
{date: "2024-08-04", count: 3},
{date: "2024-08-05", count: 4},
{date: "2024-08-06", count: 5},
{date: "2024-08-07", count: 6},
{date: "2024-08-08", count: 5},
{date: "2024-08-15", count: 8},
{date: "2024-08-22", count: 3},
{date: "2024-08-29", count: 4},
{date: "2024-09-05", count: 6},
{date: "2024-09-28", count: 6},
{date: "2024-09-22", count: 6},
{date: "2024-09-23", count: 6},
{date: "2024-09-24", count: 6},
{date: "2024-10-04", count: 6},
{date: "2024-10-02", count: 6},
{date: "2024-10-10", count: 6},
{date: "2024-10-11", count: 6},
{date: "2024-10-17", count: 6},
{date: "2024-10-19", count: 6},
{date: "2024-10-23", count: 6},
{date: "2024-10-27", count: 6},
{date: "2024-10-28", count: 6},
{date: "2024-10-29", count: 6},
{date: "2024-11-22", count: 6},
{date: "2024-11-30", count: 6},
{date: "2024-12-08", count: 6},
{date: "2024-12-16", count: 6},
{date: "2024-12-24", count: 6},
{date: "2025-01-01", count: 6},
{date: "2025-01-09", count: 6},
{date: "2025-01-16", count: 6},
{date: "2025-01-22", count: 6},
{date: "2025-01-28", count: 6},
{date: "2025-02-03", count: 6},
{date: "2025-02-09", count: 6},
{date: "2025-02-15", count: 6},
{date: "2025-02-21", count: 6},
{date: "2025-03-21", count: 6},
{date: "2025-03-22", count: 6},
{date: "2025-03-23", count: 6},
{date: "2025-03-24", count: 6},
{date: "2025-03-25", count: 6},
{date: "2025-03-26", count: 6},
{date: "2025-03-27", count: 6},
{date: "2025-03-28", count: 6},
{date: "2025-03-31", count: 6},
{date: "2025-04-03", count: 6},
{date: "2025-04-07", count: 6},
{date: "2025-04-04", count: 6},
{date: "2025-04-10", count: 6},
{date: "2025-04-11", count: 6},
{date: "2025-04-14", count: 6},
{date: "2025-04-17", count: 6},
{date: "2025-04-18", count: 6},
{date: "2025-04-21", count: 6},
{date: "2025-04-24", count: 6},
{date: "2025-04-25", count: 6},
{date: "2025-04-28", count: 6},
{date: "2025-05-01", count: 6},
{date: "2025-05-02", count: 6},
{date: "2025-05-05", count: 6},
{date: "2025-05-08", count: 6},
{date: "2025-05-09", count: 6},
{date: "2025-05-12", count: 6},
{date: "2025-05-15", count: 6},
];
const chartData = ref<any>();
async function getData() {
const res: any = await getUserUploadInfoApi();
if (res && res.code === 200) {
chartData.value = res.data;
}
}
onMounted(() => {
getData();
});
</script>
<style scoped lang="scss">
.user-center-home {