update
This commit is contained in:
@@ -21,6 +21,14 @@ async function banUser() {
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<n-flex>
|
<n-flex>
|
||||||
|
<n-button
|
||||||
|
size="small"
|
||||||
|
type="info"
|
||||||
|
secondary
|
||||||
|
@click="$router.push({ name: 'ai', query: { username: props.user.username, duration: 'months:2' } })"
|
||||||
|
>
|
||||||
|
智能分析
|
||||||
|
</n-button>
|
||||||
<n-button
|
<n-button
|
||||||
size="small"
|
size="small"
|
||||||
type="error"
|
type="error"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<n-flex align="center">
|
<n-flex align="center">
|
||||||
<n-input
|
<n-input
|
||||||
v-if="userStore.isSuperAdmin"
|
v-if="userStore.isSuperAdmin"
|
||||||
v-model:value="aiStore.targetUsername"
|
v-model:value="urlUsername"
|
||||||
placeholder="查看指定用户"
|
placeholder="查看指定用户"
|
||||||
clearable
|
clearable
|
||||||
style="width: 140px"
|
style="width: 140px"
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<n-select
|
<n-select
|
||||||
style="width: 140px"
|
style="width: 140px"
|
||||||
:options="options"
|
:options="options"
|
||||||
v-model:value="aiStore.duration"
|
v-model:value="urlDuration"
|
||||||
/>
|
/>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
@@ -63,6 +63,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useBreakpoints } from "shared/composables/breakpoints"
|
import { useBreakpoints } from "shared/composables/breakpoints"
|
||||||
import { formatISO, sub, type Duration } from "date-fns"
|
import { formatISO, sub, type Duration } from "date-fns"
|
||||||
|
import { useRouteQuery } from "@vueuse/router"
|
||||||
import TagsRadarChart from "./components/TagsRadarChart.vue"
|
import TagsRadarChart from "./components/TagsRadarChart.vue"
|
||||||
import DifficultyGradeChart from "./components/DifficultyGradeChart.vue"
|
import DifficultyGradeChart from "./components/DifficultyGradeChart.vue"
|
||||||
import TimeActivityHeatmap from "./components/TimeActivityHeatmap.vue"
|
import TimeActivityHeatmap from "./components/TimeActivityHeatmap.vue"
|
||||||
@@ -80,42 +81,41 @@ import { DURATION_OPTIONS } from "utils/constants"
|
|||||||
|
|
||||||
const aiStore = useAIStore()
|
const aiStore = useAIStore()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const { isDesktop } = useBreakpoints()
|
const { isDesktop } = useBreakpoints()
|
||||||
|
|
||||||
const options = [...DURATION_OPTIONS]
|
const options = [...DURATION_OPTIONS]
|
||||||
|
|
||||||
|
const urlUsername = useRouteQuery<string>("username", "")
|
||||||
|
const urlDuration = useRouteQuery<string>("duration", "months:6")
|
||||||
|
|
||||||
|
// Initialize store synchronously from URL params before watch fires
|
||||||
|
aiStore.targetUsername = urlUsername.value
|
||||||
|
aiStore.duration = urlDuration.value
|
||||||
|
|
||||||
const subOptions = computed<Duration>(() => {
|
const subOptions = computed<Duration>(() => {
|
||||||
let dur = options.find((it) => it.value === aiStore.duration) ?? options[0]
|
let dur = options.find((it) => it.value === aiStore.duration) ?? options[0]
|
||||||
const x = dur.value!.toString().split(":")
|
const x = dur.value!.toString().split(":")
|
||||||
const unit = x[0]
|
return { [x[0]]: parseInt(x[1]) } as Duration
|
||||||
const n = x[1]
|
|
||||||
return { [unit]: parseInt(n) } as Duration
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const start = computed(() => {
|
const start = computed(() => formatISO(sub(new Date(), subOptions.value)))
|
||||||
const current = new Date()
|
const end = computed(() => formatISO(new Date()))
|
||||||
return formatISO(sub(current, subOptions.value))
|
|
||||||
})
|
|
||||||
|
|
||||||
const end = computed(() => {
|
|
||||||
return formatISO(new Date())
|
|
||||||
})
|
|
||||||
|
|
||||||
function onUsernameChange() {
|
function onUsernameChange() {
|
||||||
|
aiStore.targetUsername = urlUsername.value
|
||||||
aiStore.fetchHeatmapData()
|
aiStore.fetchHeatmapData()
|
||||||
aiStore.fetchAnalysisData(start.value, end.value, aiStore.duration)
|
aiStore.fetchAnalysisData(start.value, end.value, aiStore.duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取热力图数据(仅一次)
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
aiStore.fetchHeatmapData()
|
aiStore.fetchHeatmapData()
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => aiStore.duration,
|
() => urlDuration.value,
|
||||||
() => {
|
(val) => {
|
||||||
aiStore.fetchAnalysisData(start.value, end.value, aiStore.duration)
|
aiStore.duration = val
|
||||||
|
aiStore.fetchAnalysisData(start.value, end.value, val)
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import { NH2, NH3 } from "naive-ui"
|
|||||||
import { getProfile } from "shared/api"
|
import { getProfile } from "shared/api"
|
||||||
import { useBreakpoints } from "shared/composables/breakpoints"
|
import { useBreakpoints } from "shared/composables/breakpoints"
|
||||||
import { durationToDays, parseTime } from "utils/functions"
|
import { durationToDays, parseTime } from "utils/functions"
|
||||||
import { Profile, UserBadge as UserBadgeType } from "utils/types"
|
import type { Profile, UserBadge as UserBadgeType } from "utils/types"
|
||||||
import { getMetrics, getUserBadges } from "../api"
|
import { getMetrics, getUserBadges } from "../api"
|
||||||
import GroupedUserBadge from "shared/components/GroupedUserBadge.vue"
|
import GroupedUserBadge from "shared/components/GroupedUserBadge.vue"
|
||||||
|
import { useUserStore } from "shared/store/user"
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const userStore = useUserStore()
|
||||||
const profile = ref<Profile | null>(null)
|
const profile = ref<Profile | null>(null)
|
||||||
const problems = ref<string[]>([])
|
const problems = ref<string[]>([])
|
||||||
const firstSubmissionAt = ref("")
|
const firstSubmissionAt = ref("")
|
||||||
@@ -204,6 +206,15 @@ onMounted(init)
|
|||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
<h2>{{ profile.user.username }}</h2>
|
<h2>{{ profile.user.username }}</h2>
|
||||||
|
<n-button
|
||||||
|
v-if="userStore.isSuperAdmin"
|
||||||
|
type="info"
|
||||||
|
secondary
|
||||||
|
size="small"
|
||||||
|
@click="router.push({ name: 'ai', query: { username: profile.user.username, duration: 'months:1' } })"
|
||||||
|
>
|
||||||
|
智能分析
|
||||||
|
</n-button>
|
||||||
<p class="desc">{{ profile.mood }}</p>
|
<p class="desc">{{ profile.mood }}</p>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user