diff --git a/backend/src/main/java/com/openisle/controller/AdminPointController.java b/backend/src/main/java/com/openisle/controller/AdminPointController.java deleted file mode 100644 index 5352391aa..000000000 --- a/backend/src/main/java/com/openisle/controller/AdminPointController.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.openisle.controller; - -import com.openisle.dto.AdminGrantPointRequest; -import com.openisle.service.PointService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import java.util.Map; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/api/admin/points") -@RequiredArgsConstructor -public class AdminPointController { - - private final PointService pointService; - - @PostMapping("/grant") - @SecurityRequirement(name = "JWT") - @Operation(summary = "Grant points", description = "Grant points to a user as administrator") - @ApiResponse(responseCode = "200", description = "Points granted") - public Map grant( - @RequestBody AdminGrantPointRequest request, - Authentication auth - ) { - String username = request.getUsername(); - int balance = pointService.grantPointByAdmin(auth.getName(), username, request.getAmount()); - return Map.of("username", username.trim(), "point", balance); - } -} diff --git a/backend/src/main/java/com/openisle/dto/AdminGrantPointRequest.java b/backend/src/main/java/com/openisle/dto/AdminGrantPointRequest.java deleted file mode 100644 index c4503f0db..000000000 --- a/backend/src/main/java/com/openisle/dto/AdminGrantPointRequest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.openisle.dto; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class AdminGrantPointRequest { - - private String username; - private int amount; -} diff --git a/backend/src/main/java/com/openisle/model/PointHistoryType.java b/backend/src/main/java/com/openisle/model/PointHistoryType.java index ed71dc461..689f73c9c 100644 --- a/backend/src/main/java/com/openisle/model/PointHistoryType.java +++ b/backend/src/main/java/com/openisle/model/PointHistoryType.java @@ -13,5 +13,4 @@ public enum PointHistoryType { REDEEM, LOTTERY_JOIN, LOTTERY_REWARD, - ADMIN_GRANT, } diff --git a/backend/src/main/java/com/openisle/service/PointService.java b/backend/src/main/java/com/openisle/service/PointService.java index 029cab314..0a8349a53 100644 --- a/backend/src/main/java/com/openisle/service/PointService.java +++ b/backend/src/main/java/com/openisle/service/PointService.java @@ -43,22 +43,6 @@ public class PointService { return addPoint(user, 500, PointHistoryType.FEATURE, post, null, null); } - public int grantPointByAdmin(String adminName, String targetUsername, int amount) { - if (amount <= 0) { - throw new FieldException("amount", "积分必须为正数"); - } - if (targetUsername == null || targetUsername.isBlank()) { - throw new FieldException("username", "用户名不能为空"); - } - String normalizedUsername = targetUsername.trim(); - User admin = userRepository.findByUsername(adminName).orElseThrow(); - User target = userRepository - .findByUsername(normalizedUsername) - .orElseThrow(() -> new FieldException("username", "用户不存在")); - addPoint(target, amount, PointHistoryType.ADMIN_GRANT, null, null, admin); - return target.getPoint(); - } - public void processLotteryJoin(User participant, LotteryPost post) { int cost = post.getPointCost(); if (cost > 0) { diff --git a/frontend_nuxt/pages/about/index.vue b/frontend_nuxt/pages/about/index.vue index be77273b6..5d669c2de 100644 --- a/frontend_nuxt/pages/about/index.vue +++ b/frontend_nuxt/pages/about/index.vue @@ -71,16 +71,6 @@ export default { label: '隐私政策', file: 'https://openisle-1307107697.cos.ap-guangzhou.myqcloud.com/assert/about/privacy.md', }, - { - key: 'points', - label: '积分说明', - content: `# 积分说明 - -- 积分可用于兑换商品、参与抽奖等社区玩法。 -- 管理员可以通过后台新增的积分模块为用户发放奖励积分。 -- 每次发放都会记录在积分历史中,方便你查看积分来源。 -`, - }, { key: 'api', label: 'API与调试', @@ -98,21 +88,11 @@ export default { return `${token.value.slice(0, 20)}...${token.value.slice(-10)}` }) - const loadContent = async (tab) => { - if (!tab || tab.key === 'api') return - if (tab.content) { - isFetching.value = false - content.value = tab.content - return - } - if (!tab.file) { - isFetching.value = false - content.value = '' - return - } + const loadContent = async (file) => { + if (!file) return try { isFetching.value = true - const res = await fetch(tab.file) + const res = await fetch(file) if (res.ok) { content.value = await res.text() } else { @@ -130,15 +110,15 @@ export default { if (initTab && tabs.find((t) => t.key === initTab)) { selectedTab.value = initTab const tab = tabs.find((t) => t.key === initTab) - if (tab) loadContent(tab) + if (tab && tab.file) loadContent(tab.file) } else { - loadContent(tabs[0]) + loadContent(tabs[0].file) } }) watch(selectedTab, (name) => { const tab = tabs.find((t) => t.key === name) - if (tab) loadContent(tab) + if (tab && tab.file) loadContent(tab.file) router.replace({ query: { ...route.query, tab: name } }) }) @@ -147,8 +127,6 @@ export default { (name) => { if (name && name !== selectedTab.value && tabs.find((t) => t.key === name)) { selectedTab.value = name - const tab = tabs.find((t) => t.key === name) - if (tab) loadContent(tab) } }, ) diff --git a/frontend_nuxt/pages/points.vue b/frontend_nuxt/pages/points.vue index 203faaa4e..1aace6a27 100644 --- a/frontend_nuxt/pages/points.vue +++ b/frontend_nuxt/pages/points.vue @@ -184,16 +184,6 @@ }} 参与,获得 {{ item.amount }} 积分 - - 你目前的积分是 {{ item.balance }} @@ -239,7 +229,6 @@ const pointRules = [ '评论被点赞:每次 10 积分', '邀请好友加入可获得 500 积分/次,注意需要使用邀请链接注册', '文章被收录至精选:每次 500 积分', - '管理员赠送:特殊活动可由管理员手动赠送积分', ] const goods = ref([]) @@ -261,7 +250,6 @@ const iconMap = { LOTTERY_REWARD: 'fireworks', POST_LIKE_CANCELLED: 'clear-icon', COMMENT_LIKE_CANCELLED: 'clear-icon', - ADMIN_GRANT: 'paper-money-two', } const loadTrend = async () => { diff --git a/frontend_nuxt/pages/settings.vue b/frontend_nuxt/pages/settings.vue index 15347d98f..6da7c4fbe 100644 --- a/frontend_nuxt/pages/settings.vue +++ b/frontend_nuxt/pages/settings.vue @@ -65,35 +65,6 @@
注册模式
-
-
发放积分
-
- - - -
-
{{ grantError }}
-
积分会立即发放给目标用户,并记录在积分历史中
-
保存中...
@@ -131,10 +102,6 @@ const registerMode = ref('DIRECT') const isLoadingPage = ref(false) const isSaving = ref(false) const frosted = ref(true) -const grantUsername = ref('') -const grantAmount = ref('') -const grantError = ref('') -const isGrantingPoints = ref(false) onMounted(async () => { isLoadingPage.value = true @@ -217,55 +184,6 @@ const loadAdminConfig = async () => { // ignore } } - -const grantPoint = async () => { - if (isGrantingPoints.value) return - const username = grantUsername.value.trim() - if (!username) { - grantError.value = '用户名不能为空' - toast.error(grantError.value) - return - } - const amount = Number(grantAmount.value) - if (!Number.isInteger(amount) || amount <= 0) { - grantError.value = '积分数量必须为正整数' - toast.error(grantError.value) - return - } - isGrantingPoints.value = true - try { - const token = getToken() - const res = await fetch(`${API_BASE_URL}/api/admin/points/grant`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${token}`, - }, - body: JSON.stringify({ username, amount }), - }) - let data = null - try { - data = await res.json() - } catch (e) { - // ignore body parse errors - } - if (res.ok) { - toast.success(`已为 ${username} 发放 ${amount} 积分`) - grantUsername.value = '' - grantAmount.value = '' - grantError.value = '' - } else { - const message = data?.error || '发放失败' - grantError.value = message - toast.error(message) - } - } catch (e) { - grantError.value = '发放失败,请稍后再试' - toast.error(grantError.value) - } finally { - isGrantingPoints.value = false - } -} const save = async () => { isSaving.value = true @@ -405,51 +323,6 @@ const save = async () => { max-width: 200px; } -.grant-row { - max-width: 100%; -} - -.grant-form { - display: flex; - flex-wrap: wrap; - gap: 10px; - align-items: center; -} - -.grant-input { - flex: 1 1 180px; -} - -.grant-input.amount { - max-width: 140px; -} - -.grant-button { - background-color: var(--primary-color); - color: #fff; - border: none; - border-radius: 8px; - padding: 8px 16px; - cursor: pointer; - transition: background-color 0.2s ease-in-out; -} - -.grant-button.disabled, -.grant-button:disabled { - cursor: not-allowed; - background-color: var(--primary-color-disabled); -} - -.grant-button:not(.disabled):hover { - background-color: var(--primary-color-hover); -} - -.grant-error-message { - color: red; - font-size: 14px; - margin-top: 8px; -} - .switch-row { flex-direction: row; align-items: center;