mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-03-16 00:50:47 +08:00
feat: menu add category & tags
This commit is contained in:
@@ -29,22 +29,13 @@
|
|||||||
<i :class="categoryOpen ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i>
|
<i :class="categoryOpen ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="categoryOpen" class="section-items">
|
<div v-if="categoryOpen" class="section-items">
|
||||||
<div
|
<div v-if="isLoadingCategory" class="menu-loading-container">
|
||||||
v-for="c in categories"
|
<l-hatch size="28" stroke="4" speed="3.5" color="var(--primary-color)"></l-hatch>
|
||||||
:key="c.id"
|
</div>
|
||||||
class="section-item"
|
<div v-else v-for="c in categories" :key="c.id" class="section-item" @click="gotoCategory(c)">
|
||||||
@click="gotoCategory(c)"
|
|
||||||
>
|
|
||||||
<template v-if="c.smallIcon || c.icon">
|
<template v-if="c.smallIcon || c.icon">
|
||||||
<img
|
<img v-if="isImageIcon(c.smallIcon || c.icon)" :src="c.smallIcon || c.icon" class="section-item-icon" />
|
||||||
v-if="isImageIcon(c.smallIcon || c.icon)"
|
<i v-else :class="['section-item-icon', c.smallIcon || c.icon]"></i>
|
||||||
:src="c.smallIcon || c.icon"
|
|
||||||
class="section-item-icon"
|
|
||||||
/>
|
|
||||||
<i
|
|
||||||
v-else
|
|
||||||
:class="['section-item-icon', c.smallIcon || c.icon]"
|
|
||||||
></i>
|
|
||||||
</template>
|
</template>
|
||||||
<span class="section-item-text">{{ c.name }}</span>
|
<span class="section-item-text">{{ c.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -57,24 +48,13 @@
|
|||||||
<i :class="tagOpen ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i>
|
<i :class="tagOpen ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="tagOpen" class="section-items">
|
<div v-if="tagOpen" class="section-items">
|
||||||
<div
|
<div v-if="isLoadingTag" class="menu-loading-container">
|
||||||
v-for="t in tags"
|
<l-hatch size="28" stroke="4" speed="3.5" color="var(--primary-color)"></l-hatch>
|
||||||
:key="t.id"
|
</div>
|
||||||
class="section-item"
|
<div v-else v-for="t in tags" :key="t.id" class="section-item" @click="gotoTag(t)">
|
||||||
@click="gotoTag(t)"
|
<img v-if="isImageIcon(t.smallIcon || t.icon)" :src="t.smallIcon || t.icon" class="section-item-icon" />
|
||||||
>
|
<i v-else class="section-item-icon fas fa-hashtag"></i>
|
||||||
<template v-if="t.smallIcon || t.icon">
|
<span class="section-item-text">{{ t.name }} ({{ t.count }})</span>
|
||||||
<img
|
|
||||||
v-if="isImageIcon(t.smallIcon || t.icon)"
|
|
||||||
:src="t.smallIcon || t.icon"
|
|
||||||
class="section-item-icon"
|
|
||||||
/>
|
|
||||||
<i
|
|
||||||
v-else
|
|
||||||
:class="['section-item-icon', t.smallIcon || t.icon]"
|
|
||||||
></i>
|
|
||||||
</template>
|
|
||||||
<span class="section-item-text">{{ t.name }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,6 +74,9 @@ import { authState } from '../utils/auth'
|
|||||||
import { fetchUnreadCount } from '../utils/notification'
|
import { fetchUnreadCount } from '../utils/notification'
|
||||||
import { watch } from 'vue'
|
import { watch } from 'vue'
|
||||||
import { API_BASE_URL } from '../main'
|
import { API_BASE_URL } from '../main'
|
||||||
|
import { hatch } from 'ldrs'
|
||||||
|
hatch.register()
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MenuComponent',
|
name: 'MenuComponent',
|
||||||
props: {
|
props: {
|
||||||
@@ -108,7 +91,9 @@ export default {
|
|||||||
categories: [],
|
categories: [],
|
||||||
tags: [],
|
tags: [],
|
||||||
categoryOpen: true,
|
categoryOpen: true,
|
||||||
tagOpen: true
|
tagOpen: true,
|
||||||
|
isLoadingCategory: false,
|
||||||
|
isLoadingTag: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -140,18 +125,31 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API_BASE_URL}/api/categories`)
|
this.isLoadingCategory = true
|
||||||
if (res.ok) {
|
fetch(`${API_BASE_URL}/api/categories`).then(
|
||||||
const data = await res.json()
|
res => {
|
||||||
this.categories = data.slice(0, 10)
|
if (res.ok) {
|
||||||
}
|
res.json().then(data => {
|
||||||
|
this.categories = data.slice(0, 10)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.isLoadingCategory = false
|
||||||
|
}
|
||||||
|
)
|
||||||
} catch { /* ignore */ }
|
} catch { /* ignore */ }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const r = await fetch(`${API_BASE_URL}/api/tags?limit=10`)
|
this.isLoadingTag = true
|
||||||
if (r.ok) {
|
fetch(`${API_BASE_URL}/api/tags?limit=10`).then(
|
||||||
this.tags = await r.json()
|
res => {
|
||||||
}
|
if (res.ok) {
|
||||||
|
res.json().then(data => {
|
||||||
|
this.tags = data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.isLoadingTag = false
|
||||||
|
}
|
||||||
|
)
|
||||||
} catch { /* ignore */ }
|
} catch { /* ignore */ }
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -188,7 +186,6 @@ export default {
|
|||||||
border-right: 1px solid var(--menu-border-color);
|
border-right: 1px solid var(--menu-border-color);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-item-container {
|
.menu-item-container {
|
||||||
@@ -226,6 +223,7 @@ export default {
|
|||||||
height: 18px;
|
height: 18px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unread {
|
.unread {
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
@@ -239,11 +237,13 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.menu-footer {
|
.menu-footer {
|
||||||
|
position: fixed;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-footer-btn {
|
.menu-footer-btn {
|
||||||
@@ -256,7 +256,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.menu-section {
|
.menu-section {
|
||||||
margin: 10px 0;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-header {
|
.section-header {
|
||||||
@@ -264,6 +264,7 @@ export default {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
opacity: 0.5;
|
||||||
padding: 4px 10px;
|
padding: 4px 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -297,6 +298,13 @@ export default {
|
|||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-loading-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
.slide-enter-active, .slide-leave-active {
|
.slide-enter-active, .slide-leave-active {
|
||||||
transition:
|
transition:
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class SecurityConfig {
|
|||||||
public CorsConfigurationSource corsConfigurationSource() {
|
public CorsConfigurationSource corsConfigurationSource() {
|
||||||
CorsConfiguration cfg = new CorsConfiguration();
|
CorsConfiguration cfg = new CorsConfiguration();
|
||||||
cfg.setAllowedOrigins(List.of(
|
cfg.setAllowedOrigins(List.of(
|
||||||
"http://127.0.0.1", // 前端调试地址
|
"http://127.0.0.1:8080", // 前端调试地址
|
||||||
// "http://129.204.254.110", // 前端调试地址
|
// "http://129.204.254.110", // 前端调试地址
|
||||||
"https://www.open-isle.com", // 生产域名
|
"https://www.open-isle.com", // 生产域名
|
||||||
"689d7858-openisle.cjt807916.workers.dev" // cloudflare 部署域名
|
"689d7858-openisle.cjt807916.workers.dev" // cloudflare 部署域名
|
||||||
|
|||||||
Reference in New Issue
Block a user