chore: point miniapp API to deployed hera service

This commit is contained in:
zhouzhibo committed 2026-10-17 22:58:40 +08:00
1 parent 5be2ca6b50
commit bc7bbc52c8
5 files changed
+39 -7

No files matched your search

+8 -2
View File
@@ -16,14 +16,20 @@ npm install
npm run dev:weapp npm run dev:weapp
``` ```
后端默认请求 `http://127.0.0.1:8080`,可通过构建环境变量 `HERA_API_BASE_URL` 指定测试地址: 后端默认请求 `http://101.43.139.56/hera`,例如登录接口完整路径为
`http://101.43.139.56/hera/api/auth/wx-login`。可通过构建环境变量 `HERA_API_BASE_URL` 覆盖:
```bash ```bash
HERA_API_BASE_URL=https://your-test-api.example.com npm run build:weapp # 改回本机后端测试
HERA_API_BASE_URL=http://127.0.0.1:8080 npm run build:weapp
``` ```
H5 真实接口模式不要携带 `?preview=1`;该参数仅用于只读素材预览,不登录、不保存或上传。 H5 真实接口模式不要携带 `?preview=1`;该参数仅用于只读素材预览,不登录、不保存或上传。
微信注册需在微信开发者工具/小程序中完成,H5 不生成假微信登录凭证。 微信注册需在微信开发者工具/小程序中完成,H5 不生成假微信登录凭证。
头像上传也使用同一个 API 前缀;头像展示若后端返回绝对 URL,前端保留该 URL,服务器需将
`TENCENT_COS_PUBLIC_BASE_URL` 配置为对应的文件签名入口(例如 `http://101.43.139.56/hera/file/`),
不要指向开发机 `127.0.0.1`,也不要将 `/file/access` 直接代理为 COS 对象路径。
HTTP/IP 地址用于当前联调部署;正式微信发布前需配置 HTTPS 合法域名。
资料及头像联调、接口和验收说明见 [账号联调说明](docs/account-backend-integration.md)。 资料及头像联调、接口和验收说明见 [账号联调说明](docs/account-backend-integration.md)。
微信构建后自动执行 WXSS 兼容检查(也可单独运行 `npm run check:wxss`)。 微信构建后自动执行 WXSS 兼容检查(也可单独运行 `npm run check:wxss`)。
+1 -1
View File
@@ -13,7 +13,7 @@ export default defineConfig(async () => ({
outputRoot: process.env.TARO_ENV === 'h5' ? 'dist-h5' : 'dist', outputRoot: process.env.TARO_ENV === 'h5' ? 'dist-h5' : 'dist',
plugins: ['@tarojs/plugin-framework-react'], plugins: ['@tarojs/plugin-framework-react'],
defineConstants: { defineConstants: {
API_BASE_URL: JSON.stringify((process.env.HERA_API_BASE_URL || 'http://127.0.0.1:8080').replace(/\/+$/, '')) API_BASE_URL: JSON.stringify((process.env.HERA_API_BASE_URL || 'http://101.43.139.56/hera').replace(/\/+$/, ''))
}, },
copy: { copy: {
patterns: [], patterns: [],
+9 -1
View File
@@ -9,6 +9,14 @@
- 登录凭证失效后清除本地会话;失效头像链接通过资料接口刷新,不在前端签名 COS 文件。 - 登录凭证失效后清除本地会话;失效头像链接通过资料接口刷新,不在前端签名 COS 文件。
- 天宫绑定等已有隔离 Mock 未改成真实后端业务。本次没有提交或推送代码。 - 天宫绑定等已有隔离 Mock 未改成真实后端业务。本次没有提交或推送代码。
## 当前默认部署地址
- 前端默认 API 基址已改为 `http://101.43.139.56/hera`,登录、资料和头像上传均复用该前缀。
- 本地后端服务地址没有改变,但前端如需改回本机,构建前需设置 `HERA_API_BASE_URL=http://127.0.0.1:8080`;该设置在构建时生效。
- 只读探测远端 `/hera/api/user/profile` 当前返回 404,尚不能据此确认服务已经部署可用。服务器需要正确处理 `/hera` 代理或应用上下文路径;部署后未登录访问资料接口应返回 401,而不是 404。
- 服务器头像文件入口需独立配置 `TENCENT_COS_PUBLIC_BASE_URL`,例如 `http://101.43.139.56/hera/file/`,并转发到后端签名控制器。前端不改写后端返回的绝对头像 URL,不会把本地入口自动变成公网入口。
- HTTP/IP 地址为当前联调部署地址,正式小程序发布需配置 HTTPS 合法域名;本次未修改远程服务器、后端配置或存储权限。
## 本地入口与启动 ## 本地入口与启动
- 前端:`http://127.0.0.1:4173/#/pages/my/index`,真实模式不带 `preview=1`。 - 前端:`http://127.0.0.1:4173/#/pages/my/index`,真实模式不带 `preview=1`。
@@ -48,7 +56,7 @@
## 已验证与边界 ## 已验证与边界
- 前端自动测试 58 项通过(包含日主五行入口图标、隔离头像演示、编辑页样式作用域及 WXSS 兼容回归测试),TypeScript 检查、H5 和微信构建通过。13 个产物 WXSS 均通过本机微信开发者工具自带 `wcsc` 的原生编译检查;这不替代真实登录/上传验收。 - 前端自动测试 59 项通过(包含远端 API 前缀与本地覆盖、日主五行入口图标、隔离头像演示、编辑页样式作用域及 WXSS 兼容回归测试),TypeScript 检查、H5 和微信构建通过。13 个产物 WXSS 均通过本机微信开发者工具自带 `wcsc` 的原生编译检查;这不替代真实登录/上传验收。
- 后端干净构建默认执行的 17 项单元/隔离测试通过:注册/资料/头像控制器链路、账号 CRUD、仅当前表启动、头像限额与格式、401、文件访问、COS 和 Redis 配置测试。4 项需要显式启用的外部集成测试在默认构建中跳过。业务写入测试使用隔离 H2,微信客户端及实际 COS 上传使用测试替身,不代表已向真实 COS 上传成功。另有 1 项当前配置数据库的只读 Mapper 集成检查通过,不读取真实账号记录或写入数据库。 - 后端干净构建默认执行的 17 项单元/隔离测试通过:注册/资料/头像控制器链路、账号 CRUD、仅当前表启动、头像限额与格式、401、文件访问、COS 和 Redis 配置测试。4 项需要显式启用的外部集成测试在默认构建中跳过。业务写入测试使用隔离 H2,微信客户端及实际 COS 上传使用测试替身,不代表已向真实 COS 上传成功。另有 1 项当前配置数据库的只读 Mapper 集成检查通过,不读取真实账号记录或写入数据库。
- 已运行的本地后端:无登录和无效凭证请求均返回 401;资料 PUT 跨域预检返回 200 并允许 Authorization、Content-Type。前端入口 HTTP 200。 - 已运行的本地后端:无登录和无效凭证请求均返回 401;资料 PUT 跨域预检返回 200 并允许 Authorization、Content-Type。前端入口 HTTP 200。
- 真实联调阶段浏览器验收曾被额度限制阻止;后续用户要求的 H5 已登录演示已在浏览器验证:从相册选择项目测试图片、保存、我的/首页/重新进入编辑页均成功加载同一本地头像。截图保存在 `/private/tmp/hera-avatar-demo-my.png`。这不是实际 COS 上传证据;真实微信授权、真实账号写入和实际 COS 上传/展示仍须完成上述开发者工具验收。 - 真实联调阶段浏览器验收曾被额度限制阻止;后续用户要求的 H5 已登录演示已在浏览器验证:从相册选择项目测试图片、保存、我的/首页/重新进入编辑页均成功加载同一本地头像。截图保存在 `/private/tmp/hera-avatar-demo-my.png`。这不是实际 COS 上传证据;真实微信授权、真实账号写入和实际 COS 上传/展示仍须完成上述开发者工具验收。
+20 -2
View File
@@ -28,7 +28,7 @@ test('编辑页所有编译样式均限定页面,默认头像不复用我的
assert.doesNotMatch(source, /className='water-mascot'/) assert.doesNotMatch(source, /className='water-mascot'/)
}) })
function setup(token = 'test-session') { function setup(token = 'test-session', baseUrl) {
let profile = { ...fullProfile } let profile = { ...fullProfile }
const storage = { token } const storage = { token }
const calls = [], routes = [] const calls = [], routes = []
@@ -57,6 +57,7 @@ function setup(token = 'test-session') {
vm.runInNewContext(ts.transpileModule(fs.readFileSync(path.join(root, `src/${name}.ts`), 'utf8'), { vm.runInNewContext(ts.transpileModule(fs.readFileSync(path.join(root, `src/${name}.ts`), 'utf8'), {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019 } compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019 }
}).outputText, { exports, process: { env: { TARO_ENV: 'h5' } }, window: { location: { search: '' } }, URLSearchParams, }).outputText, { exports, process: { env: { TARO_ENV: 'h5' } }, window: { location: { search: '' } }, URLSearchParams,
...(baseUrl === undefined ? {} : { API_BASE_URL: baseUrl }),
require: id => id === '@tarojs/taro' ? taro : load(path.posix.normalize(path.posix.join(path.posix.dirname(name), id))) }) require: id => id === '@tarojs/taro' ? taro : load(path.posix.normalize(path.posix.join(path.posix.dirname(name), id))) })
return exports return exports
} }
@@ -86,7 +87,7 @@ test('头像经专用COS后端接口上传,Bearer字段正确,禁止H5跨域
ctx.service.subscribeProfile(profile => updates.push(profile)) ctx.service.subscribeProfile(profile => updates.push(profile))
const profile = await ctx.service.api.uploadAvatar('blob:local-avatar') const profile = await ctx.service.api.uploadAvatar('blob:local-avatar')
const upload = ctx.calls[0] const upload = ctx.calls[0]
assert.equal(upload.url, 'http://127.0.0.1:8080/api/user/avatar') assert.equal(upload.url, 'http://101.43.139.56/hera/api/user/avatar')
assert.equal(upload.name, 'file') assert.equal(upload.name, 'file')
assert.equal(upload.filePath, 'blob:local-avatar') assert.equal(upload.filePath, 'blob:local-avatar')
assert.equal(upload.header.Authorization, 'Bearer test-session') assert.equal(upload.header.Authorization, 'Bearer test-session')
@@ -98,6 +99,23 @@ test('头像经专用COS后端接口上传,Bearer字段正确,禁止H5跨域
assert.equal(ctx.calls.length, 1) assert.equal(ctx.calls.length, 1)
}) })
test('默认部署地址为远端hera前缀,登录资料上传与相对文件路径一致且允许本地覆盖', async () => {
const ctx = setup()
await ctx.service.api.profile()
await ctx.service.api.wxLogin('stub-code')
assert.equal(ctx.calls[0].url, 'http://101.43.139.56/hera/api/user/profile')
assert.equal(ctx.calls[1].url, 'http://101.43.139.56/hera/api/auth/wx-login')
assert.equal(ctx.service.resolveAssetUrl('/file/access?token=test-only'), 'http://101.43.139.56/hera/file/access?token=test-only')
assert.equal(ctx.service.resolveAssetUrl('https://files.example.test/image.png'), 'https://files.example.test/image.png')
const local = setup('local-session', 'http://127.0.0.1:8080/')
await local.service.api.profile()
await local.service.api.uploadAvatar('blob:test-only')
assert.equal(local.calls[0].url, 'http://127.0.0.1:8080/api/user/profile')
assert.equal(local.calls[1].url, 'http://127.0.0.1:8080/api/user/avatar')
const config = fs.readFileSync(path.join(root, 'config/index.ts'), 'utf8')
assert.match(config, /process\.env\.HERA_API_BASE_URL \|\| 'http:\/\/101\.43\.139\.56\/hera'/)
})
test('上传失败不覆盖已有头像;HTML 401也清理会话', async () => { test('上传失败不覆盖已有头像;HTML 401也清理会话', async () => {
const ctx = setup() const ctx = setup()
await ctx.service.api.profile() await ctx.service.api.profile()
+1 -1
View File
@@ -3,7 +3,7 @@ import { frontendPreviewProfile, isFrontendPreview } from './frontendPreview'
import { createResourceCache } from '../utils/resourceCache' import { createResourceCache } from '../utils/resourceCache'
import { getAvatarDemoProfile, isAvatarDemo, saveAvatarDemoImage, updateAvatarDemoProfile } from './avatarDemo' import { getAvatarDemoProfile, isAvatarDemo, saveAvatarDemoImage, updateAvatarDemoProfile } from './avatarDemo'
export const BASE_URL = typeof API_BASE_URL === 'undefined' ? 'http://127.0.0.1:8080' : API_BASE_URL export const BASE_URL = (typeof API_BASE_URL === 'undefined' ? 'http://101.43.139.56/hera' : API_BASE_URL).replace(/\/+$/, '')
const profileCache = createResourceCache<UserProfile>(30000) const profileCache = createResourceCache<UserProfile>(30000)
const profileListeners = new Set<(profile: UserProfile | null) => void>() const profileListeners = new Set<(profile: UserProfile | null) => void>()
export const getToken = (): string => Taro.getStorageSync('token') || '' export const getToken = (): string => Taro.getStorageSync('token') || ''