feat: 添加 H5 基础 URL 和匿名访问支持

- 在 `AndroidScreenSaverCatalogVO` 中新增 `h5BaseUrl` 字段
- 更新 `vite.config.ts`,设置基础路径为 `/H5/`
- 更新 `main.tsx`,设置 `BrowserRouter` 的 `basename` 为 `/H5`
- 在 `AndroidMeetingController` 的 `config` 方法上添加 `@Anonymous` 注解
- 在 `AndroidScreen
dev_na
chenhao 2026-06-09 18:09:17 +08:00
parent 1cce0aeabb
commit 82dc485dcf
7 changed files with 47 additions and 12 deletions

View File

@ -1,29 +1,55 @@
package com.imeeting.common;
/**
* Key
*/
public final class SysParamKeys {
private SysParamKeys() {}
/** 登录验证码开关。 */
public static final String CAPTCHA_ENABLED = "security.captcha.enabled";
/** AI 会议总结使用的系统提示词。 */
public static final String MEETING_SUMMARY_SYSTEM_PROMPT = "meeting.summary.system_prompt";
/** 离线会议音频上传大小上限,单位 MB。 */
public static final String MEETING_OFFLINE_AUDIO_MAX_SIZE_MB = "meeting.offline_audio.max_size_mb";
/** 是否允许创建离线会议。 */
public static final String MEETING_CREATE_OFFLINE_ENABLED = "meeting.create.offline_enabled";
/** 是否允许创建实时会议。 */
public static final String MEETING_CREATE_REALTIME_ENABLED = "meeting.create.realtime_enabled";
/** ASR 任务最大并发数。 */
public static final String MEETING_ASR_MAX_CONCURRENT = "meeting.asr.max_concurrent";
/** 会议暂停最大时长,单位秒。 */
public static final String MEETING_MAX_PAUSE_DURATION = "meeting.max_pause_duration";
/** 单场会议最大时长,单位分钟。 */
public static final String MEETING_MAX_MEETING_DURATION = "meeting.max_meeting_duration";
/** 会议音频传输丢包率配置值。 */
public static final String MEETING_PACKET_LOSS_RATE = "meeting.packet_loss_rate";
/** 安卓端是否启用音频分片上传。 */
public static final String MEETING_ANDROID_AUDIO_CHUNK_UPLOAD_ENABLED = "meeting.android.audio.chunk_upload_enabled";
/** 安卓端音频分片上传时每片时长,单位秒。 */
public static final String MEETING_ANDROID_AUDIO_CHUNK_DURATION_SECONDS = "meeting.android.audio.chunk_duration_seconds";
/** 会议积分功能总开关。 */
public static final String MEETING_POINTS_ENABLED = "meeting.points.enabled";
/** 积分计费单位时长,单位分钟。 */
public static final String MEETING_POINTS_UNIT_MINUTES = "meeting.points.unit_minutes";
/** 每个计费单位消耗的积分数。 */
public static final String MEETING_POINTS_COST_PER_UNIT = "meeting.points.cost_per_unit";
/** 积分拆分时分配给 ASR 的比例。 */
public static final String MEETING_POINTS_ASR_RATIO = "meeting.points.asr_ratio";
/** 积分拆分时分配给 LLM 的比例。 */
public static final String MEETING_POINTS_LLM_RATIO = "meeting.points.llm_ratio";
/** 新建积分账户时的初始积分余额。 */
public static final String MEETING_POINTS_INITIAL_BALANCE = "meeting.points.initial_balance";
/** 会议积分账户模式,如公共账户或个人账户。 */
public static final String MEETING_POINTS_ACCOUNT_MODE = "meeting.points.account_mode";
/** 临时授权默认下发数量。 */
public static final String LICENSE_TEMP_DEFAULT_COUNT = "license.temp.default.count";
/** 临时授权默认有效期,单位月。 */
public static final String LICENSE_TEMP_DEFAULT_EXPIRE_MONTHS = "license.temp.default.expire.months";
/** 默认授权对应的产品编码。 */
public static final String LICENSE_DEFAULT_PRODUCT_CODE = "license.default.product.code";
/** 和风天气接口基础地址。 */
public static final String DEVICE_WEATHER_QWEATHER_BASE_URL = "device.weather.qweather.base_url";
/** 和风天气接口访问 Key。 */
public static final String DEVICE_WEATHER_QWEATHER_KEY = "device.weather.qweather.key";
}

View File

@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "Android认证接口")
@RestController
@RequestMapping("/api/android/auth")

View File

@ -373,6 +373,7 @@ public class AndroidMeetingController {
@GetMapping("/config")
@Log(value = "获取会议配置", type = "Android会议管理")
@Operation(summary = "获取会议配置")
@Anonymous
public ApiResponse<AndroidMeetingConfigVo> config(HttpServletRequest request) {
AndroidRequestLogHelper.logRequest(log, "Android会议", "获取会议配置接口");
AndroidAuthContext authContext = androidAuthService.authenticateHttp(request);

View File

@ -17,6 +17,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -31,7 +33,8 @@ public class AndroidScreenSaverController {
private final AndroidAuthService androidAuthService;
private final ScreenSaverService screenSaverService;
private final TaskSecurityContextRunner taskSecurityContextRunner;
@Value("${imeeting.h5.base-url:}")
private String h5BaseUrl;
@Operation(summary = "获取当前生效屏保")
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(
@ -47,6 +50,7 @@ public class AndroidScreenSaverController {
ScreenSaverSelectionResult selection = querySelection(authContext);
AndroidScreenSaverCatalogVO vo = new AndroidScreenSaverCatalogVO();
vo.setRefreshIntervalSec(300);
vo.setH5BaseUrl(StringUtils.hasText(h5BaseUrl) ? h5BaseUrl.trim() : null);
vo.setPlayMode("SEQUENTIAL");
vo.setDisplayDurationSec(selection.getDisplayDurationSec());
vo.setSourceScope(selection.getSourceScope());

View File

@ -18,4 +18,6 @@ public class AndroidScreenSaverCatalogVO {
private String sourceScope;
@Schema(description = "屏保图片项列表")
private List<AndroidScreenSaverItemVO> items;
@Schema(description = "H5 地址")
private String h5BaseUrl;
}

View File

@ -24,7 +24,7 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
>
<AntdApp>
<PlatformConfigProvider>
<BrowserRouter>
<BrowserRouter basename="/H5">
<App />
</BrowserRouter>
</PlatformConfigProvider>

View File

@ -3,6 +3,7 @@ import react from "@vitejs/plugin-react";
import { fileURLToPath, URL } from "node:url";
export default defineConfig({
base: "/H5/",
plugins: [react()],
resolve: {
alias: {