hejianhao
2026-08-20 ad13f20070707e26b2f6f5ea7660c8a535de0344
feat0806: APP项目介绍密码验证
1个文件已添加
3个文件已修改
116 ■■■■■ 已修改文件
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/home/controller/AppHomeLiveCourseController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/ProjectIntroductionPasswordService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/pages/good/good.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/pages/good/service.js 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/home/controller/AppHomeLiveCourseController.java
@@ -5,6 +5,7 @@
import com.tcm.training.admin.common.ApiResponse;
import com.tcm.training.admin.live.dto.LiveCoursePasswordVerifyRequest;
import com.tcm.training.admin.live.service.LiveCourseAppService;
import com.tcm.training.admin.live.service.ProjectIntroductionPasswordService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@@ -27,13 +28,17 @@
    private final LiveCourseAppService liveCourseAppService;
    private final ProjectIntroductionPasswordService projectIntroductionPasswordService;
    /**
     * 注入首页养生直播服务。
     */
    public AppHomeLiveCourseController(AppHomeLiveCourseService appHomeLiveCourseService,
                                       LiveCourseAppService liveCourseAppService) {
                                       LiveCourseAppService liveCourseAppService,
                                       ProjectIntroductionPasswordService projectIntroductionPasswordService) {
        this.appHomeLiveCourseService = appHomeLiveCourseService;
        this.liveCourseAppService = liveCourseAppService;
        this.projectIntroductionPasswordService = projectIntroductionPasswordService;
    }
    /**
@@ -51,4 +56,12 @@
    public ApiResponse<Boolean> verifyPassword(@Valid @RequestBody LiveCoursePasswordVerifyRequest req) {
        return ApiResponse.ok(liveCourseAppService.verifyPassword(req));
    }
    /**
     * 检查项目介绍是否启用密码访问。
     */
    @GetMapping("/project-introduction/password-enabled")
    public ApiResponse<Boolean> isProjectIntroductionPasswordEnabled() {
        return ApiResponse.ok(projectIntroductionPasswordService.isPasswordEnabled());
    }
}
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/ProjectIntroductionPasswordService.java
@@ -108,4 +108,17 @@
                && !config.getPassword().isEmpty()
                && passwordEncoder.matches(inputPassword, config.getPassword());
    }
    /**
     * 检查项目介绍是否启用密码访问
     */
    public boolean isPasswordEnabled() {
        ProjectIntroductionPassword config = passwordMapper.selectOne(
                new LambdaQueryWrapper<ProjectIntroductionPassword>()
                        .eq(ProjectIntroductionPassword::getPasswordEnabled, 1)
                        .orderByAsc(ProjectIntroductionPassword::getId)
                        .last("limit 1")
        );
        return config != null;
    }
}
traditionalApp/pages/good/good.vue
@@ -17,7 +17,9 @@
                    @confirm="handleConfirm"
                />
            </view>
            <view class="confirm-btn" :class="{ disabled: !password }" @tap="handleConfirm">确认</view>
            <view class="confirm-btn" :class="{ disabled: !password || submitting }" @tap="handleConfirm">
                {{ submitting ? '验证中...' : '确认' }}
            </view>
        </view>
        <view v-else class="entry-content">
@@ -33,40 +35,76 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
/** 项目中心访问密码,后续改为接口读取后台配置。 */
const PROJECT_CENTER_PASSWORD = '123456'
import { verifyProjectIntroductionPassword, checkProjectIntroductionPasswordEnabled } from './service.js'
const statusBarHeight = ref(0)
const password = ref('')
const autoFocus = ref(true)
const unlocked = ref(false)
const submitting = ref(false)
const loading = ref(true)
onMounted(() => {
onMounted(async () => {
    console.log('项目中心页面加载')
    uni.getSystemInfo({
        success: (res) => {
            statusBarHeight.value = res.statusBarHeight || 0
        }
    })
    // 检查是否启用密码
    try {
        console.log('开始检查密码启用状态...')
        const isPasswordEnabled = await checkProjectIntroductionPasswordEnabled()
        console.log('密码启用状态:', isPasswordEnabled)
        if (!isPasswordEnabled) {
            // 未启用密码,直接解锁
            unlocked.value = true
            autoFocus.value = false
            console.log('密码未启用,直接解锁')
        } else {
            console.log('密码已启用,显示密码输入界面')
        }
    } catch (error) {
        console.error('检查密码状态失败:', error)
    } finally {
        loading.value = false
    }
})
/**
 * 校验项目中心密码,通过后展示三个入口。
 */
function handleConfirm() {
async function handleConfirm() {
    if (!password.value) {
        return
    }
    if (password.value !== PROJECT_CENTER_PASSWORD) {
        uni.showToast({
            title: '密码错误,请重新输入',
            icon: 'none'
        })
    if (submitting.value) {
        return
    }
    unlocked.value = true
    password.value = ''
    autoFocus.value = false
    submitting.value = true
    try {
        const isValid = await verifyProjectIntroductionPassword(password.value)
        if (isValid) {
            unlocked.value = true
            password.value = ''
            autoFocus.value = false
        } else {
            uni.showToast({
                title: '密码错误,请重新输入',
                icon: 'none'
            })
            password.value = ''
        }
    } catch (error) {
        uni.showToast({
            title: '验证失败,请重试',
            icon: 'none'
        })
    } finally {
        submitting.value = false
    }
}
/**
traditionalApp/pages/good/service.js
New file
@@ -0,0 +1,22 @@
import { publicPost, publicGet } from '@/utils/public-request.js'
/**
 * 检查项目介绍是否启用密码访问。
 */
export const checkProjectIntroductionPasswordEnabled = async () => {
    const res = await publicGet('/api/app/home/project-introduction/password-enabled')
    // 返回格式:{ code: 200, data: true/false }
    return res?.data === true
}
/**
 * 校验项目介绍访问密码。
 */
export const verifyProjectIntroductionPassword = async (password) => {
    const res = await publicPost('/api/app/home/live-courses/password/verify', {
        type: 2,
        password,
    })
    // 返回格式:{ code: 200, data: true/false }
    return res?.data === true
}