feat: 积分页面不足展示

This commit is contained in:
tim
2025-08-17 02:19:21 +08:00
parent cf3b6d8fc7
commit 0b6d4f9709
2 changed files with 34 additions and 1 deletions

View File

@@ -119,6 +119,8 @@ public class SecurityConfig {
.requestMatchers(HttpMethod.GET, "/api/reaction-types").permitAll() .requestMatchers(HttpMethod.GET, "/api/reaction-types").permitAll()
.requestMatchers(HttpMethod.GET, "/api/activities/**").permitAll() .requestMatchers(HttpMethod.GET, "/api/activities/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/sitemap.xml").permitAll() .requestMatchers(HttpMethod.GET, "/api/sitemap.xml").permitAll()
.requestMatchers(HttpMethod.GET, "/api/point-goods").permitAll()
.requestMatchers(HttpMethod.POST, "/api/point-goods").permitAll()
.requestMatchers(HttpMethod.POST, "/api/categories/**").hasAuthority("ADMIN") .requestMatchers(HttpMethod.POST, "/api/categories/**").hasAuthority("ADMIN")
.requestMatchers(HttpMethod.POST, "/api/tags/**").authenticated() .requestMatchers(HttpMethod.POST, "/api/tags/**").authenticated()
.requestMatchers(HttpMethod.DELETE, "/api/categories/**").hasAuthority("ADMIN") .requestMatchers(HttpMethod.DELETE, "/api/categories/**").hasAuthority("ADMIN")
@@ -151,6 +153,7 @@ public class SecurityConfig {
uri.startsWith("/api/search") || uri.startsWith("/api/users") || uri.startsWith("/api/search") || uri.startsWith("/api/users") ||
uri.startsWith("/api/reaction-types") || uri.startsWith("/api/config") || uri.startsWith("/api/reaction-types") || uri.startsWith("/api/config") ||
uri.startsWith("/api/activities") || uri.startsWith("/api/push/public-key") || uri.startsWith("/api/activities") || uri.startsWith("/api/push/public-key") ||
uri.startsWith("/api/point-goods") ||
uri.startsWith("/api/sitemap.xml") || uri.startsWith("/api/medals")); uri.startsWith("/api/sitemap.xml") || uri.startsWith("/api/medals"));
if (authHeader != null && authHeader.startsWith("Bearer ")) { if (authHeader != null && authHeader.startsWith("Bearer ")) {

View File

@@ -7,6 +7,10 @@
</div> </div>
</section> </section>
<div class="loading-points-container" v-if="isLoading">
<l-hatch size="28" stroke="4" speed="3.5" color="var(--primary-color)"></l-hatch>
</div>
<div class="point-info"> <div class="point-info">
<p v-if="authState.loggedIn && point !== null"> <p v-if="authState.loggedIn && point !== null">
<span><i class="fas fa-coins coin-icon"></i></span>我的积分<span class="point-value">{{ <span><i class="fas fa-coins coin-icon"></i></span>我的积分<span class="point-value">{{
@@ -23,7 +27,13 @@
<i class="fas fa-coins"></i> <i class="fas fa-coins"></i>
{{ good.cost }} 积分 {{ good.cost }} 积分
</div> </div>
<div class="goods-item-button" @click="openRedeem(good)">兑换</div> <div
class="goods-item-button"
:class="{ disabled: !authState.loggedIn || point === null || point < good.cost }"
@click="openRedeem(good)"
>
兑换
</div>
</div> </div>
</section> </section>
<RedeemPopup <RedeemPopup
@@ -46,6 +56,7 @@ const config = useRuntimeConfig()
const API_BASE_URL = config.public.apiBaseUrl const API_BASE_URL = config.public.apiBaseUrl
const point = ref(null) const point = ref(null)
const isLoading = ref(false)
const pointRules = [ const pointRules = [
'发帖:每天前两次,每次 30 积分', '发帖:每天前两次,每次 30 积分',
@@ -61,11 +72,13 @@ const loading = ref(false)
const selectedGood = ref(null) const selectedGood = ref(null)
onMounted(async () => { onMounted(async () => {
isLoading.value = true
if (authState.loggedIn) { if (authState.loggedIn) {
const user = await fetchCurrentUser() const user = await fetchCurrentUser()
point.value = user ? user.point : null point.value = user ? user.point : null
} }
await loadGoods() await loadGoods()
isLoading.value = false
}) })
const loadGoods = async () => { const loadGoods = async () => {
@@ -76,6 +89,10 @@ const loadGoods = async () => {
} }
const openRedeem = (good) => { const openRedeem = (good) => {
if (!authState.loggedIn || point.value === null || point.value < good.cost) {
toast.error('积分不足')
return
}
selectedGood.value = good selectedGood.value = good
dialogVisible.value = true dialogVisible.value = true
} }
@@ -117,6 +134,13 @@ const submitRedeem = async () => {
margin: 0 auto; margin: 0 auto;
} }
.loading-points-container {
margin-top: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.point-info { .point-info {
font-size: 18px; font-size: 18px;
} }
@@ -184,6 +208,12 @@ const submitRedeem = async () => {
background-color: var(--primary-color-hover); background-color: var(--primary-color-hover);
} }
.goods-item-button.disabled,
.goods-item-button.disabled:hover {
background-color: var(--primary-color-disabled);
cursor: not-allowed;
}
.section-title { .section-title {
font-size: 18px; font-size: 18px;
font-weight: bold; font-weight: bold;