✨ improve api
This commit is contained in:
18
src/api/auth/index.ts
Normal file
18
src/api/auth/index.ts
Normal 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",
|
||||
});
|
||||
};
|
@@ -10,6 +10,7 @@ export const shareImageUploadApi = (formData) => {
|
||||
ignoreToken: false,
|
||||
signature: false,
|
||||
},
|
||||
name: 'upload-share-image',
|
||||
});
|
||||
};
|
||||
/**
|
||||
|
@@ -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"],
|
||||
});
|
||||
};
|
||||
|
@@ -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');
|
||||
|
@@ -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
|
||||
|
@@ -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">
|
||||
|
@@ -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);
|
||||
|
@@ -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 {
|
||||
|
Reference in New Issue
Block a user