Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/components/utils/Footer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@
</svg>
<span>我的</span>
</router-link> -->
<router-link to="/my">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 12a5 5 0 100-10 5 5 0 000 10zm-7 9a7 7 0 0114 0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path>
</svg>
<span>{{ $t('footer.my') }}</span>
</router-link>
<router-link to="/f">
<svg fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path
Expand Down
10 changes: 10 additions & 0 deletions src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@ export default {
blackHole: 'Schwarzes Loch',
friends: 'Freunde',
notifications: 'Benachrichtigungen',
my: 'Mein',
},

myPage: {
publishedExperiment: 'Veröffentlichte Experimente',
publishedDiscussion: 'Veröffentlichte Diskussionen',
favoriteExperiment: 'Favorisierte Experimente',
favoriteDiscussion: 'Favorisierte Diskussionen',
supportedExperiment: 'Unterstützte Experimente',
supportedDiscussion: 'Unterstützte Diskussionen',
},
ui: {
messages: {
Expand Down
10 changes: 10 additions & 0 deletions src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ export default {
blackHole: 'Black Hole',
friends: 'Friends',
notifications: 'Notifications',
my: 'My',
},

myPage: {
publishedExperiment: 'Published Experiments',
publishedDiscussion: 'Published Discussions',
favoriteExperiment: 'Favorite Experiments',
favoriteDiscussion: 'Favorite Discussions',
supportedExperiment: 'Supported Experiments',
supportedDiscussion: 'Supported Discussions',
},
ui: {
messages: {
Expand Down
10 changes: 10 additions & 0 deletions src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@ export default {
blackHole: 'Trou noir',
friends: 'Amis',
notifications: 'Notifications',
my: 'Moi',
},

myPage: {
publishedExperiment: 'Expériences publiées',
publishedDiscussion: 'Discussions publiées',
favoriteExperiment: 'Expériences favorites',
favoriteDiscussion: 'Discussions favorites',
supportedExperiment: 'Expériences soutenues',
supportedDiscussion: 'Discussions soutenues',
},
ui: {
messages: {
Expand Down
10 changes: 10 additions & 0 deletions src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@ export default {
blackHole: 'ブラックホール',
friends: '友人',
notifications: '通知',
my: 'マイ',
},

myPage: {
publishedExperiment: '公開済み実験',
publishedDiscussion: '公開済み議論',
favoriteExperiment: 'お気に入り実験',
favoriteDiscussion: 'お気に入り議論',
supportedExperiment: '支持した実験',
supportedDiscussion: '支持した議論',
},
ui: {
messages: {
Expand Down
10 changes: 10 additions & 0 deletions src/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ export default {
blackHole: '黑洞',
friends: '好友',
notifications: '通知',
my: '我的',
},

myPage: {
publishedExperiment: '已发布实验',
publishedDiscussion: '已发布讨论',
favoriteExperiment: '收藏实验',
favoriteDiscussion: '收藏讨论',
supportedExperiment: '支持的实验',
supportedDiscussion: '支持的讨论',
},
ui: {
messages: {
Expand Down
6 changes: 6 additions & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ const routes: RouteRecordRaw[] = [
component: () => import('../views/Friends.vue'),
meta: { keepAlive: true },
},
{
path: '/my',
name: 'my',
component: () => import('../views/My.vue'),
meta: { keepAlive: true },
},
{
path: '/l/:config',
name: 'list',
Expand Down
121 changes: 121 additions & 0 deletions src/views/My.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<template>
<div id="my-page">
<Header>
<div class="my-page__title">{{ $t('footer.my') }}</div>
</Header>
<main>
<div v-show="isLoading" class="loading"></div>
<div v-show="!isLoading" class="block-container">
<n-grid :x-gap="12" :y-gap="12" :cols="blockItemsPerRow">
<n-gi v-for="block in blocks" :key="block.Header">
<div class="my-page__block">
<Block :block="block" :maxProjectsPerBlock="maxProjectsPerBlock" />
</div>
</n-gi>
</n-grid>
</div>
</main>
</div>
<Footer></Footer>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { NGrid, NGi } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { getData } from '@api/getData'
import { checkLogin } from '@services/utils'
import { showLoginModel } from '@popup/index'
import { useResponsive } from '../layout/useResponsive'
import Header from '../components/utils/Header.vue'
import Footer from '../components/utils/Footer.vue'
import Block from '../components/blocks/Block.vue'
import type { ListBlock, Summary } from '@services/../pl-serve-type-main/type/main'

const { t } = useI18n()
const isLoading = ref(true)
const blocks = ref<ListBlock[]>([])
const { blockItemsPerRow, maxProjectsPerBlock } = useResponsive()

function createBlock(header: string, summaries: Summary[]): ListBlock {
return {
$type: 'Quantum.Models.Contents.ListBlock, Quantum Models',
Header: header,
Summaries: summaries,
DefaultLink: null,
DefaultText: null,
FetchAmount: 0,
FetchConfiguration: null,
FetchSource: '',
Locations: null,
Permission: null,
TargetLink: '',
Type: 0,
}
}

async function querySummaries(category: 'Experiment' | 'Discussion', special: 'Favorite' | 'Support' | null) {
const response = await getData('/Contents/QueryExperiments', {
Query: {
Category: category,
Languages: [],
Tags: [],
Take: 24,
Sort: 0,
Skip: 0,
Days: 0,
Special: special,
UserID: null,
ExcludeLanguages: null,
ExcludeTags: null,
ModelTags: null,
ModelID: null,
ParentID: null,
From: null,
ShowAnnouncement: false,
},
})

return response.Data?.$values ?? []
}

onMounted(async () => {
if (!checkLogin(false)) {
showLoginModel()
isLoading.value = false
return
Comment on lines +82 to +86
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Refresh data after login when page is cached

This page only loads data in onMounted, but the route is marked keepAlive, so when an unauthenticated user opens /my, the component returns early and stays cached with empty blocks; after completing login and returning to /my, onMounted will not run again and the page remains empty until a full reload. Please trigger the same load flow on activation or on userLogin so cached instances recover.

Useful? React with 👍 / 👎.

}

const [publishedExp, publishedDiscussion, favoriteExp, favoriteDiscussion, supportExp, supportDiscussion] =
await Promise.all([
querySummaries('Experiment', null),
querySummaries('Discussion', null),
querySummaries('Experiment', 'Favorite'),
querySummaries('Discussion', 'Favorite'),
querySummaries('Experiment', 'Support'),
querySummaries('Discussion', 'Support'),
])
Comment on lines +89 to +97
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Guard parallel queries so loading state always clears

The six requests are awaited with Promise.all without any error handling, and getData can throw on transport failures (see src/services/api/getData.ts catch path). If one request rejects, isLoading is never set to false and the page stays in a perpetual loading state with an unhandled rejection. Wrap the load in try/finally (and optionally handle per-block failures) so the UI can recover.

Useful? React with 👍 / 👎.


blocks.value = [
createBlock(t('myPage.publishedExperiment'), publishedExp),
createBlock(t('myPage.publishedDiscussion'), publishedDiscussion),
createBlock(t('myPage.favoriteExperiment'), favoriteExp),
createBlock(t('myPage.favoriteDiscussion'), favoriteDiscussion),
createBlock(t('myPage.supportedExperiment'), supportExp),
createBlock(t('myPage.supportedDiscussion'), supportDiscussion),
]

isLoading.value = false
})
</script>

<style scoped>
.my-page__title {
font-size: 20px;
font-weight: 600;
}

.my-page__block {
height: 100%;
}
</style>