Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
穆春红
/
frontend-hub
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
527c65d0
authored
Jul 29, 2026
by
chunhong.mu
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
perf(*): 优化模板
parent
17eea8db
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
281 additions
and
112 deletions
ARCHITECTURE.md
CLAUDE.md
common/sdk/src/core/sdk.ts
common/sdk/src/services/verify-service.ts
packages/admin/.env.development
packages/admin/.env.production
packages/admin/.env.staging
packages/admin/.env.test
packages/admin/src/api/auth.ts
packages/admin/src/config/index.ts
packages/admin/src/pages/login/index.vue
packages/mini/.env.development
packages/mini/.env.production
packages/mini/.env.staging
packages/mini/.env.test
packages/mini/src/config/index.ts
packages/mini/src/pages/login/login.vue
packages/site/.env.development
packages/site/.env.production
packages/site/.env.staging
packages/site/.env.test
packages/web/.env.development
packages/web/.env.production
packages/web/.env.staging
packages/web/.env.test
packages/web/src/api/auth.ts
packages/web/src/config/index.ts
packages/web/src/pages/login/index.vue
ARCHITECTURE.md
View file @
527c65d0
...
...
@@ -529,9 +529,28 @@ pnpm -F admin type-check
**环境文件**
:位于各子包根目录,
`.env.development`
、
`.env.test`
、
`.env.staging`
、
`.env.production`
。
#### 模板自带的环境值(重要)
为了
**开箱可体验**
,模板对四个包做了区别对待:
| 文件 | 模板中的状态 | 原因 |
|------|-------------|------|
|
`.env.development`
、
`.env.test`
|
**已预填一套可用的测试环境值**
| 拉下来
`pnpm dev`
就能看到登录页、图形验证码正常显示,不需要先去要配置 |
|
`.env.staging`
、
`.env.production`
|
**故意留空**
| 模板工程不携带生产凭证;上线前必须自己填 |
预填的是
**测试环境**
的地址与
`client_id`
(
`client_secret`
为测试值
`123456`
),只够跑通登录/验证码这类匿名接口。
> ⚠️ **派生新项目后请务必替换 `.env.development` / `.env.test` 里的所有值**,否则你的开发环境会一直打在别人的测试后端上。需要改的是:`VITE_APP_UNIPLAT`、`VITE_APP_CLIENT_ID`、`VITE_APP_CLIENT_SECRET`、通行证四个地址,以及 `src/config/index.ts` 里带 `TODO` 的 `rootEntrance` 与 `domainService`。
**为什么验证码依赖 `VITE_APP_UNIPLAT`**
:
`verifyService.generateImage()`
是
**同步方法**
,它只是用随机 seed 拼出
`{uniplatApi}/general/imageToVerify/{seed}`
这个图片地址,真正的加载由
`<img>`
/
`<image>`
完成。所以
`VITE_APP_UNIPLAT`
为空时,地址会退化成同源相对路径
`/general/imageToVerify/123`
——dev server 会用
`index.html`
兜底返回
**200 的 HTML**
,浏览器拿到 HTML 当图片解析,只能渲染成破图,且在 Network 面板里看起来还是「成功」,非常难排查。因此:
-
`@common/sdk`
在
`uniplatApi`
为空时会
`console.error`
明确报出来;
-
`generateImage()`
检测到地址不是
`http(s)://`
开头时返回空
`img`
,避免把破图塞给 UI;
-
三个登录页在拿不到验证码时渲染「加载失败,点击重试」占位,并监听
`error`
事件。
> ⚠️ **不要在 `.env.*` 里设置 `NODE_ENV`**。Vite / Nuxt 会根据执行的命令自动设置(dev → `development`,build → `production`);手写 `NODE_ENV=production` 会导致 `pnpm dev:test` 之类的 dev server 报 “NODE_ENV=production is not supported in the .env file” 警告。
**变量清单**
(
模板中值为空,
需按项目填写):
**变量清单**
(
`dev`
/
`test`
已预填,
`staging`
/
`production`
需按项目填写):
| 变量 | 说明 | 必填 |
|------|------|------|
...
...
CLAUDE.md
View file @
527c65d0
...
...
@@ -6,14 +6,17 @@
## 这是一个模板工程
**开箱即可体验**
:
`.env.development`
/
`.env.test`
已预填一套可用的
**测试环境**
配置,
`pnpm install`
后直接
`pnpm dev:project`
就能看到登录页、图形验证码正常显示。
`.env.staging`
/
`.env.production`
故意留空——模板不携带生产凭证。
从本仓库派生新项目后,
**先做这几件事**
:
1.
全仓搜索
`TODO:`
与占位符,逐项替换为项目实际值(应用名、
`rootEntrance`
、
`domainService`
、分享标题等)
2.
填写各包的
`.env.*`
(模板里所有值都是空的,
`VITE_APP_UNIPLAT`
/
`VITE_APP_CLIENT_ID`
必填)
3.
删除不需要的包,或用
`pnpm new:project`
新增包
4.
更新本文件与
`ARCHITECTURE.md`
里的项目描述
1.
**替换 `.env.development` / `.env.test` 里的预填值**
,否则开发环境会一直打在别人的测试后端上(
`VITE_APP_UNIPLAT`
/
`VITE_APP_CLIENT_ID`
/
`VITE_APP_CLIENT_SECRET`
+ 通行证四个地址)
2.
填写
`.env.staging`
/
`.env.production`
(当前为空)
3.
全仓搜索
`TODO:`
,逐项替换为项目实际值(应用名、
`rootEntrance`
、
`domainService`
、分享标题等)
4.
删除不需要的包,或用
`pnpm new:project`
新增包
5.
更新本文件与
`ARCHITECTURE.md`
里的项目描述
**不要把
业务
域名、appid、client secret 写回模板**
——所有环境相关值一律走
`.env.*`
,代码里只读
`config`
。
**不要把
生产
域名、appid、client secret 写回模板**
——所有环境相关值一律走
`.env.*`
,代码里只读
`config`
。
## 快速开始
...
...
@@ -99,10 +102,12 @@ types/ 类型定义
|
`--mode staging`
|
`.env.staging`
|
`stage`
|
|
`--mode production`
|
`.env.production`
|
`prod`
|
取值与
`@common/sdk`
的
`Environment`
枚举一致(
`dev`
/
`test`
/
`stage`
/
`prod`
)。
取值与
`@common/sdk`
的
`Environment`
枚举一致(
`dev`
/
`test`
/
`stage`
/
`prod`
)。
`dev`
/
`test`
已预填测试环境值,
`staging`
/
`prod`
为空。
⚠️
**不要在 `.env.*` 里写 `NODE_ENV`**
——Vite/Nuxt 会按命令自动设置,手写
`NODE_ENV=production`
会让
`dev:test`
之类的 dev server 报警告。
⚠️
**图形验证码依赖 `VITE_APP_UNIPLAT`**
:
`generateImage()`
是同步方法,只拼出
`{uniplatApi}/general/imageToVerify/{seed}`
图片地址。该变量为空时地址退化成相对路径,dev server 用
`index.html`
兜底返回
**200 的 HTML**
,表现为破图但网络面板显示成功。已加三重防护:SDK 报
`console.error`
、
`generateImage()`
返回空
`img`
、登录页渲染「点击重试」占位。
## 可用 skills
| skill | 用途 |
...
...
common/sdk/src/core/sdk.ts
View file @
527c65d0
...
...
@@ -120,6 +120,14 @@ export class Sdk {
public
init
(
config
:
SdkConfig
,
adapter
?:
AxiosAdapter
)
{
const
baseUrl
=
config
.
uniplatApi
if
(
!
baseUrl
)
{
// 模板工程默认为空,未填时所有请求(含图形验证码图片)都会退化成
// 相对地址打到本地 dev server 上,表现为验证码不显示、接口静默失败
console
.
error
(
"[@common/sdk] uniplatApi 为空,请在对应包的 .env.* 中填写 VITE_APP_UNIPLAT。"
+
"未配置时图形验证码无法显示、所有接口请求都会失败。"
,
)
}
this
.
uniplatSdk
=
new
UniplatSdk
({
sse
:
false
})
this
.
uniplatSdk
.
global
.
baseUrl
=
baseUrl
...
...
common/sdk/src/services/verify-service.ts
View file @
527c65d0
...
...
@@ -22,11 +22,28 @@ export function createVerifyService(sdk: UniplatSdk, clientId: string) {
return
{
/**
* 生成图形验证码
*
* 同步方法:SDK 只是用随机 seed 拼出图片 URL,由 `<img>` 自行加载。
*
* 若 `uniplatApi` 未配置,SDK 的 baseUrl 会退化成 `/`,拼出的地址是
* 同源相对路径(dev server 会用 index.html 兜底返回 200 的 HTML),
* `<img>` 只能渲染成破图。这里直接返回空 `img`,让调用方能明确区分
* “未配置”与“真的拿到了验证码”。
*/
generateImage
():
VerifyImageResult
{
const
result
=
sdk
.
getVerifyImageAndSeed
()
as
any
const
img
=
String
(
result
.
img
||
""
)
const
configured
=
/^https
?
:
\/\/
/i
.
test
(
img
)
if
(
!
configured
)
{
console
.
error
(
`[@common/sdk] 图形验证码地址不可用(
${
img
||
"空"
}
),`
+
"请检查 VITE_APP_UNIPLAT 是否已配置。"
,
)
}
return
{
img
:
result
.
img
,
img
:
configured
?
img
:
""
,
seed
:
String
(
result
.
seed
),
}
},
...
...
packages/admin/.env.development
View file @
527c65d0
# ⚠️ 本文件已预填「测试环境」的可用值,仅为开箱体验用(登录/图形验证码可直接跑通)。
# 派生新项目后请全部替换为自己的后端地址与凭证,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=dev
VITE_APP_ENV=dev
...
...
@@ -7,22 +9,22 @@ VITE_DEBUG=true
VITE_APP_LOG_ENV=0
# ===== 统一业务平台(必填)=====
VITE_APP_UNIPLAT=
VITE_APP_UNIPLAT_WEBSOCKET_URI=
VITE_APP_UNIPLAT=
http://hro.test-api.qqxb.jinsehuaqin.com:8800
VITE_APP_UNIPLAT_WEBSOCKET_URI=
ws://hro.channel.jinsehuaqin.com:8080/ws
# ===== 账号中心 / 通行证 =====
VITE_APP_WWW_WORK_APP_URL=
VITE_APP_API_WORK_APP_URL=
VITE_APP_API_WORK_ORG_URL=
VITE_APP_USER_CENTER=
VITE_APP_WWW_WORK_APP_URL=
http://106.120.107.150:5000
VITE_APP_API_WORK_APP_URL=
http://106.120.107.150:8090
VITE_APP_API_WORK_ORG_URL=
http://106.120.107.150:7771
VITE_APP_USER_CENTER=
http://106.120.107.150:8080
# ===== 客户端凭证(必填,向后端申请)=====
VITE_APP_CLIENT_ID=
VITE_APP_CLIENT_SECRET=
VITE_APP_CLIENT_ID=
qqqf-admin-web
VITE_APP_CLIENT_SECRET=
123456
# ===== 支付 =====
VITE_APP_PAY_URL=
VITE_APP_PAY_URL=
https://payment-api.teammix.com
# ===== 静态资源 / H5 =====
VITE_APP_H5_URL=
VITE_APP_LAND_PAGE=
VITE_APP_H5_URL=
https://static.qinqinxiaobao.com/flb-mp
VITE_APP_LAND_PAGE=
https://static.qinqinxiaobao.com/flb-mp
packages/admin/.env.production
View file @
527c65d0
# ⚠️ 预发/生产环境的值故意留空——模板工程不携带生产凭证。
# 上线前请填入自己的后端地址与 client id/secret,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=production
VITE_APP_ENV=prod
...
...
packages/admin/.env.staging
View file @
527c65d0
# ⚠️ 预发/生产环境的值故意留空——模板工程不携带生产凭证。
# 上线前请填入自己的后端地址与 client id/secret,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=staging
VITE_APP_ENV=stage
...
...
packages/admin/.env.test
View file @
527c65d0
# ⚠️ 本文件已预填「测试环境」的可用值,仅为开箱体验用(登录/图形验证码可直接跑通)。
# 派生新项目后请全部替换为自己的后端地址与凭证,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV
=
test
VITE_APP_ENV
=
test
...
...
@@ -7,22 +9,22 @@ VITE_DEBUG=true
VITE_APP_LOG_ENV
=
2
# ===== 统一业务平台(必填)=====
VITE_APP_UNIPLAT
=
VITE_APP_UNIPLAT_WEBSOCKET_URI
=
VITE_APP_UNIPLAT
=
http
://
hro
.
test
-
api
.
qqxb
.
jinsehuaqin
.
com
:
8800
VITE_APP_UNIPLAT_WEBSOCKET_URI
=
ws
://
hro
.
channel
.
jinsehuaqin
.
com
:
8080
/
ws
# ===== 账号中心 / 通行证 =====
VITE_APP_WWW_WORK_APP_URL
=
VITE_APP_API_WORK_APP_URL
=
VITE_APP_API_WORK_ORG_URL
=
VITE_APP_USER_CENTER
=
VITE_APP_WWW_WORK_APP_URL
=
http
://
106.120
.
107.150
:
5000
VITE_APP_API_WORK_APP_URL
=
http
://
106.120
.
107.150
:
8090
VITE_APP_API_WORK_ORG_URL
=
http
://
106.120
.
107.150
:
7771
VITE_APP_USER_CENTER
=
http
://
106.120
.
107.150
:
8080
# ===== 客户端凭证(必填,向后端申请)=====
VITE_APP_CLIENT_ID
=
VITE_APP_CLIENT_SECRET
=
VITE_APP_CLIENT_ID
=
qqqf
-
admin
-
web
VITE_APP_CLIENT_SECRET
=
123456
# ===== 支付 =====
VITE_APP_PAY_URL
=
VITE_APP_PAY_URL
=
https
://
payment
-
api
.
teammix
.
com
# ===== 静态资源 / H5 =====
VITE_APP_H5_URL
=
VITE_APP_LAND_PAGE
=
VITE_APP_H5_URL
=
https
://
static
.
qinqinxiaobao
.
com
/
flb
-
mp
VITE_APP_LAND_PAGE
=
https
://
static
.
qinqinxiaobao
.
com
/
flb
-
mp
packages/admin/src/api/auth.ts
View file @
527c65d0
...
...
@@ -5,6 +5,10 @@ export type { LoginRegisterResult, VerifyImageResult }
/**
* 获取图形验证码
*
* 注意:这是同步方法,SDK 只负责拼出图片 URL,实际加载由 `<img>` 完成。
* 因此拿不到验证码时不会 reject,需要判断 `img` 是否为空 + 监听 `<img>`
* 的 error 事件。
*/
export
function
getVerifyImage
():
VerifyImageResult
{
return
verifyService
.
generateImage
()
...
...
packages/admin/src/config/index.ts
View file @
527c65d0
...
...
@@ -16,13 +16,13 @@ export const config: AdminConfig = {
appName
:
'管理后台'
,
uniplatApi
:
import
.
meta
.
env
.
VITE_APP_UNIPLAT
||
''
,
// TODO: 替换为后端分配的平台入口标识
rootEntrance
:
''
,
rootEntrance
:
'
统一业务平台
'
,
logEnv
:
(
import
.
meta
.
env
.
VITE_APP_ENV
||
Environment
.
Dev
)
as
Environment
,
clientId
:
(
import
.
meta
.
env
.
VITE_APP_CLIENT_ID
||
''
)
as
ClientId
,
domainService
:
{
// TODO: 替换为项目实际的子项目名与服务名
subProjectName
:
''
,
serviceName
:
''
,
// TODO: 替换为项目实际的子项目名与服务名
(当前为测试环境的示例值)
subProjectName
:
'
welfare_v2
'
,
serviceName
:
'
smart_app_api
'
,
},
passportUrl
:
import
.
meta
.
env
.
VITE_APP_WWW_WORK_APP_URL
||
''
,
}
...
...
packages/admin/src/pages/login/index.vue
View file @
527c65d0
...
...
@@ -41,12 +41,24 @@
placeholder=
"请输入图形验证码"
/>
<img
v-if=
"verifyImage.img"
v-if=
"verifyImage.img
&& !verifyImageFailed
"
:src=
"verifyImage.img"
class=
"verify-img"
alt=
"验证码"
title=
"点击刷新"
@
click=
"refreshVerifyImage"
@
error=
"verifyImageFailed = true"
/>
<!-- 拿不到验证码时给出可点击的占位,而不是留一个破图 -->
<button
v-else
class=
"verify-img verify-img--fallback"
type=
"button"
title=
"点击重试"
@
click=
"refreshVerifyImage"
>
加载失败
<br
/>
点击重试
</button>
</div>
<div
class=
"form-item form-item-row"
>
...
...
@@ -101,6 +113,7 @@
<
/template
>
<
script
setup
lang
=
"ts"
>
import
type
{
VerifyImageResult
}
from
'@common/sdk'
import
{
SMS_COUNTDOWN
}
from
'@common/utils/constants'
import
{
isPhone
}
from
'@common/utils/regex'
import
{
ref
}
from
'vue'
...
...
@@ -135,18 +148,18 @@ const passwordForm = ref({
const
smsLoading
=
ref
(
false
)
const
passwordLoading
=
ref
(
false
)
const
countdown
=
ref
(
0
)
const
verifyImage
=
ref
({
img
:
''
,
seed
:
''
}
)
const
verifyImage
=
ref
<
VerifyImageResult
>
({
img
:
''
,
seed
:
''
}
)
const
verifyImageFailed
=
ref
(
false
)
let
timer
:
ReturnType
<
typeof
setInterval
>
|
null
=
null
// 获取图形验证码
async
function
refreshVerifyImage
()
{
try
{
const
res
=
await
getVerifyImage
()
verifyImage
.
value
=
res
as
any
}
catch
(
e
)
{
Toast
.
error
(
'获取图形验证码失败'
)
// 获取图形验证码(同步拼 URL,加载失败由 <img> 的 error 事件兜住)
function
refreshVerifyImage
()
{
verifyImageFailed
.
value
=
false
verifyImage
.
value
=
getVerifyImage
()
if
(
!
verifyImage
.
value
.
img
)
{
verifyImageFailed
.
value
=
true
Toast
.
error
(
'获取图形验证码失败,请检查 VITE_APP_UNIPLAT 配置'
)
}
}
...
...
@@ -325,6 +338,16 @@ refreshVerifyImage()
height
:
44
px
;
cursor
:
pointer
;
border
-
radius
:
4
px
;
flex
-
shrink
:
0
;
}
.
verify
-
img
--
fallback
{
border
:
1
px
dashed
#
ddd
;
background
:
#
fafafa
;
color
:
#
999
;
font
-
size
:
12
px
;
line
-
height
:
1.3
;
padding
:
0
;
}
.
sms
-
btn
{
...
...
packages/mini/.env.development
View file @
527c65d0
# ⚠️ 本文件已预填「测试环境」的可用值,仅为开箱体验用(登录/图形验证码可直接跑通)。
# 派生新项目后请全部替换为自己的后端地址与凭证,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=dev
VITE_APP_ENV=dev
...
...
@@ -7,29 +9,29 @@ VITE_DEBUG=true
VITE_APP_LOG_ENV=0
# ===== 统一业务平台(必填)=====
VITE_APP_UNIPLAT=
VITE_APP_UNIPLAT_WEBSOCKET_URI=
VITE_APP_UNIPLAT=
http://hro.test-api.qqxb.jinsehuaqin.com:8800
VITE_APP_UNIPLAT_WEBSOCKET_URI=
ws://hro.channel.jinsehuaqin.com:8080/ws
# ===== 账号中心 / 通行证 =====
VITE_APP_WWW_WORK_APP_URL=
VITE_APP_API_WORK_APP_URL=
VITE_APP_API_WORK_ORG_URL=
VITE_APP_USER_CENTER=
VITE_APP_WWW_WORK_APP_URL=
http://106.120.107.150:5000
VITE_APP_API_WORK_APP_URL=
http://106.120.107.150:8090
VITE_APP_API_WORK_ORG_URL=
http://106.120.107.150:7771
VITE_APP_USER_CENTER=
http://106.120.107.150:8080
# ===== 客户端凭证(必填,向后端申请)=====
VITE_APP_CLIENT_ID=
VITE_APP_CLIENT_SECRET=
VITE_APP_CLIENT_ID=
hrs100_wechat_mini_app
VITE_APP_CLIENT_SECRET=
123456
# ===== 支付 =====
VITE_APP_PAY_URL=
VITE_APP_PAY_URL=
https://payment-api.teammix.com
# ===== 静态资源 / H5 =====
VITE_APP_H5_URL=
VITE_APP_LAND_PAGE=
VITE_APP_H5_URL=
https://static.qinqinxiaobao.com/flb-mp
VITE_APP_LAND_PAGE=
https://static.qinqinxiaobao.com/flb-mp
# ===== 小程序 / 公众号 appid =====
VITE_MP_APPID=
VITE_MP_ACCOUNT_APPID=
VITE_MP_APPID=
wx71116f4df50d7f93
VITE_MP_ACCOUNT_APPID=
wx67ad4269eb98b531
# ===== 第三方 =====
VITE_MAP_KEY=
...
...
packages/mini/.env.production
View file @
527c65d0
# ⚠️ 预发/生产环境的值故意留空——模板工程不携带生产凭证。
# 上线前请填入自己的后端地址与 client id/secret,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=production
VITE_APP_ENV=prod
...
...
@@ -33,3 +35,7 @@ VITE_MP_ACCOUNT_APPID=
# ===== 第三方 =====
VITE_MAP_KEY=
# ===== 测试账号(仅非生产环境)=====
VITE_APP_TEST_ACCOUNT=
VITE_APP_TEST_PASSPORT=
packages/mini/.env.staging
View file @
527c65d0
# ⚠️ 预发/生产环境的值故意留空——模板工程不携带生产凭证。
# 上线前请填入自己的后端地址与 client id/secret,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=staging
VITE_APP_ENV=stage
...
...
packages/mini/.env.test
View file @
527c65d0
# ⚠️ 本文件已预填「测试环境」的可用值,仅为开箱体验用(登录/图形验证码可直接跑通)。
# 派生新项目后请全部替换为自己的后端地址与凭证,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV
=
test
VITE_APP_ENV
=
test
...
...
@@ -7,29 +9,29 @@ VITE_DEBUG=true
VITE_APP_LOG_ENV
=
2
# ===== 统一业务平台(必填)=====
VITE_APP_UNIPLAT
=
VITE_APP_UNIPLAT_WEBSOCKET_URI
=
VITE_APP_UNIPLAT
=
http
://
hro
.
test
-
api
.
qqxb
.
jinsehuaqin
.
com
:
8800
VITE_APP_UNIPLAT_WEBSOCKET_URI
=
ws
://
hro
.
channel
.
jinsehuaqin
.
com
:
8080
/
ws
# ===== 账号中心 / 通行证 =====
VITE_APP_WWW_WORK_APP_URL
=
VITE_APP_API_WORK_APP_URL
=
VITE_APP_API_WORK_ORG_URL
=
VITE_APP_USER_CENTER
=
VITE_APP_WWW_WORK_APP_URL
=
http
://
106.120
.
107.150
:
5000
VITE_APP_API_WORK_APP_URL
=
http
://
106.120
.
107.150
:
8090
VITE_APP_API_WORK_ORG_URL
=
http
://
106.120
.
107.150
:
7771
VITE_APP_USER_CENTER
=
http
://
106.120
.
107.150
:
8080
# ===== 客户端凭证(必填,向后端申请)=====
VITE_APP_CLIENT_ID
=
VITE_APP_CLIENT_SECRET
=
VITE_APP_CLIENT_ID
=
hrs100_wechat_mini_app
VITE_APP_CLIENT_SECRET
=
123456
# ===== 支付 =====
VITE_APP_PAY_URL
=
VITE_APP_PAY_URL
=
https
://
payment
-
api
.
teammix
.
com
# ===== 静态资源 / H5 =====
VITE_APP_H5_URL
=
VITE_APP_LAND_PAGE
=
VITE_APP_H5_URL
=
https
://
static
.
qinqinxiaobao
.
com
/
flb
-
mp
VITE_APP_LAND_PAGE
=
https
://
static
.
qinqinxiaobao
.
com
/
flb
-
mp
# ===== 小程序 / 公众号 appid =====
VITE_MP_APPID
=
VITE_MP_ACCOUNT_APPID
=
VITE_MP_APPID
=
wx71116f4df50d7f93
VITE_MP_ACCOUNT_APPID
=
wx67ad4269eb98b531
# ===== 第三方 =====
VITE_MAP_KEY
=
...
...
packages/mini/src/config/index.ts
View file @
527c65d0
...
...
@@ -83,11 +83,11 @@ export const config: MpConfig = {
h5Url
:
import
.
meta
.
env
.
VITE_APP_H5_URL
||
""
,
imgBaseUrl
:
`
${
import
.
meta
.
env
.
VITE_APP_LAND_PAGE
||
""
}
/img/`
,
// TODO: 替换为后端分配的平台入口标识
rootEntrance
:
""
,
rootEntrance
:
"
统一业务平台
"
,
domainService
:
{
// TODO: 替换为项目实际的子项目名与服务名
subProjectName
:
""
,
serviceName
:
""
,
// TODO: 替换为项目实际的子项目名与服务名
(当前为测试环境的示例值)
subProjectName
:
"
welfare_v2
"
,
serviceName
:
"
smart_app_api
"
,
},
clientId
:
(
import
.
meta
.
env
.
VITE_APP_CLIENT_ID
||
""
)
as
ClientId
,
clientSecret
:
import
.
meta
.
env
.
VITE_APP_CLIENT_SECRET
||
""
,
...
...
@@ -100,7 +100,7 @@ export const config: MpConfig = {
testPassport
:
import
.
meta
.
env
.
VITE_APP_TEST_PASSPORT
||
""
,
shareConfig
:
{
// TODO: 替换为项目分享标题与分享图
title
:
""
,
title
:
"
小程序模板
"
,
img
:
""
,
path
:
"/pages/login/index"
,
},
...
...
packages/mini/src/pages/login/login.vue
View file @
527c65d0
...
...
@@ -39,12 +39,21 @@
type=
"text"
/>
<image
v-if=
"imageCodeModel"
v-if=
"imageCodeModel
?.img && !imageCodeFailed
"
:src=
"imageCodeModel.img"
mode=
"aspectFit"
class=
"code-img"
@
click=
"getVerifyCodeImg"
@
error=
"imageCodeFailed = true"
/>
<!-- 拿不到验证码时给出可点击的占位,而不是留一个破图 -->
<view
v-else
class=
"code-img code-img--fallback"
@
click=
"getVerifyCodeImg"
>
加载失败,点击重试
</view>
</view>
<view
class=
"form-item form-item-row"
>
<input
...
...
@@ -180,9 +189,16 @@ const codeCountdown = ref(60)
let
codeTimer
:
ReturnType
<
typeof
setInterval
>
|
null
=
null
const
imageCodeModel
=
ref
<
VerifyImageResult
|
null
>
(
null
)
const
imageCodeFailed
=
ref
(
false
)
// 同步拼 URL,加载失败由
<
image
>
的
error
事件兜住
function
getVerifyCodeImg
()
{
imageCodeFailed
.
value
=
false
imageCodeModel
.
value
=
getVerifyService
().
generateImage
()
if
(
!
imageCodeModel
.
value
.
img
)
{
imageCodeFailed
.
value
=
true
toastError
(
"获取图形验证码失败,请检查 VITE_APP_UNIPLAT 配置"
)
}
}
function
startCodeCountdown
()
{
...
...
@@ -398,6 +414,19 @@ onLoad(() => {
height
:
60
rpx
;
margin-left
:
20
rpx
;
flex-shrink
:
0
;
&--fallback
{
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
box-sizing
:
border-box
;
border
:
1
rpx
dashed
#ddd
;
background-color
:
#fafafa
;
color
:
#999
;
font-size
:
20
rpx
;
line-height
:
1.2
;
text-align
:
center
;
}
}
.code-text
{
...
...
packages/site/.env.development
View file @
527c65d0
# ⚠️ 本文件已预填「测试环境」的可用值,仅为开箱体验用(登录/图形验证码可直接跑通)。
# 派生新项目后请全部替换为自己的后端地址与凭证,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=dev
VITE_APP_ENV=dev
# ===== API 基础地址(必填)=====
NUXT_PUBLIC_API_BASE_URL=
NUXT_PUBLIC_API_BASE_URL=
http://hro.test-api.qqxb.jinsehuaqin.com:8800
packages/site/.env.production
View file @
527c65d0
# ⚠️ 预发/生产环境的值故意留空——模板工程不携带生产凭证。
# 上线前请填入自己的后端地址与 client id/secret,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=production
VITE_APP_ENV=prod
...
...
packages/site/.env.staging
View file @
527c65d0
# ⚠️ 预发/生产环境的值故意留空——模板工程不携带生产凭证。
# 上线前请填入自己的后端地址与 client id/secret,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=staging
VITE_APP_ENV=stage
...
...
packages/site/.env.test
View file @
527c65d0
# ⚠️ 本文件已预填「测试环境」的可用值,仅为开箱体验用(登录/图形验证码可直接跑通)。
# 派生新项目后请全部替换为自己的后端地址与凭证,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV
=
test
VITE_APP_ENV
=
test
# ===== API 基础地址(必填)=====
NUXT_PUBLIC_API_BASE_URL
=
NUXT_PUBLIC_API_BASE_URL
=
http
://
hro
.
test
-
api
.
qqxb
.
jinsehuaqin
.
com
:
8800
packages/web/.env.development
View file @
527c65d0
# ⚠️ 本文件已预填「测试环境」的可用值,仅为开箱体验用(登录/图形验证码可直接跑通)。
# 派生新项目后请全部替换为自己的后端地址与凭证,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=dev
VITE_APP_ENV=dev
...
...
@@ -7,22 +9,22 @@ VITE_DEBUG=true
VITE_APP_LOG_ENV=0
# ===== 统一业务平台(必填)=====
VITE_APP_UNIPLAT=
VITE_APP_UNIPLAT_WEBSOCKET_URI=
VITE_APP_UNIPLAT=
http://hro.test-api.qqxb.jinsehuaqin.com:8800
VITE_APP_UNIPLAT_WEBSOCKET_URI=
ws://hro.channel.jinsehuaqin.com:8080/ws
# ===== 账号中心 / 通行证 =====
VITE_APP_WWW_WORK_APP_URL=
VITE_APP_API_WORK_APP_URL=
VITE_APP_API_WORK_ORG_URL=
VITE_APP_USER_CENTER=
VITE_APP_WWW_WORK_APP_URL=
http://106.120.107.150:5000
VITE_APP_API_WORK_APP_URL=
http://106.120.107.150:8090
VITE_APP_API_WORK_ORG_URL=
http://106.120.107.150:7771
VITE_APP_USER_CENTER=
http://106.120.107.150:8080
# ===== 客户端凭证(必填,向后端申请)=====
VITE_APP_CLIENT_ID=
VITE_APP_CLIENT_SECRET=
VITE_APP_CLIENT_ID=
qqxb_mini_app
VITE_APP_CLIENT_SECRET=
123456
# ===== 支付 =====
VITE_APP_PAY_URL=
VITE_APP_PAY_URL=
https://payment-api.teammix.com
# ===== 静态资源 / H5 =====
VITE_APP_H5_URL=
VITE_APP_LAND_PAGE=
VITE_APP_H5_URL=
https://static.qinqinxiaobao.com/flb-mp
VITE_APP_LAND_PAGE=
https://static.qinqinxiaobao.com/flb-mp
packages/web/.env.production
View file @
527c65d0
# ⚠️ 预发/生产环境的值故意留空——模板工程不携带生产凭证。
# 上线前请填入自己的后端地址与 client id/secret,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=production
VITE_APP_ENV=prod
...
...
packages/web/.env.staging
View file @
527c65d0
# ⚠️ 预发/生产环境的值故意留空——模板工程不携带生产凭证。
# 上线前请填入自己的后端地址与 client id/secret,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV=staging
VITE_APP_ENV=stage
...
...
packages/web/.env.test
View file @
527c65d0
# ⚠️ 本文件已预填「测试环境」的可用值,仅为开箱体验用(登录/图形验证码可直接跑通)。
# 派生新项目后请全部替换为自己的后端地址与凭证,详见 ARCHITECTURE.md「环境变量」一节。
# ===== 应用元信息 =====
APP_ENV
=
test
VITE_APP_ENV
=
test
...
...
@@ -7,22 +9,22 @@ VITE_DEBUG=true
VITE_APP_LOG_ENV
=
2
# ===== 统一业务平台(必填)=====
VITE_APP_UNIPLAT
=
VITE_APP_UNIPLAT_WEBSOCKET_URI
=
VITE_APP_UNIPLAT
=
http
://
hro
.
test
-
api
.
qqxb
.
jinsehuaqin
.
com
:
8800
VITE_APP_UNIPLAT_WEBSOCKET_URI
=
ws
://
hro
.
channel
.
jinsehuaqin
.
com
:
8080
/
ws
# ===== 账号中心 / 通行证 =====
VITE_APP_WWW_WORK_APP_URL
=
VITE_APP_API_WORK_APP_URL
=
VITE_APP_API_WORK_ORG_URL
=
VITE_APP_USER_CENTER
=
VITE_APP_WWW_WORK_APP_URL
=
http
://
106.120
.
107.150
:
5000
VITE_APP_API_WORK_APP_URL
=
http
://
106.120
.
107.150
:
8090
VITE_APP_API_WORK_ORG_URL
=
http
://
106.120
.
107.150
:
7771
VITE_APP_USER_CENTER
=
http
://
106.120
.
107.150
:
8080
# ===== 客户端凭证(必填,向后端申请)=====
VITE_APP_CLIENT_ID
=
VITE_APP_CLIENT_SECRET
=
VITE_APP_CLIENT_ID
=
qqxb_mini_app
VITE_APP_CLIENT_SECRET
=
123456
# ===== 支付 =====
VITE_APP_PAY_URL
=
VITE_APP_PAY_URL
=
https
://
payment
-
api
.
teammix
.
com
# ===== 静态资源 / H5 =====
VITE_APP_H5_URL
=
VITE_APP_LAND_PAGE
=
VITE_APP_H5_URL
=
https
://
static
.
qinqinxiaobao
.
com
/
flb
-
mp
VITE_APP_LAND_PAGE
=
https
://
static
.
qinqinxiaobao
.
com
/
flb
-
mp
packages/web/src/api/auth.ts
View file @
527c65d0
...
...
@@ -5,6 +5,10 @@ export type { LoginRegisterResult, VerifyImageResult }
/**
* 获取图形验证码
*
* 注意:这是同步方法,SDK 只负责拼出图片 URL,实际加载由 `<img>` 完成。
* 因此拿不到验证码时不会 reject,需要判断 `img` 是否为空 + 监听 `<img>`
* 的 error 事件。
*/
export
function
getVerifyImage
():
VerifyImageResult
{
return
verifyService
.
generateImage
()
...
...
packages/web/src/config/index.ts
View file @
527c65d0
...
...
@@ -18,13 +18,13 @@ export const config: WebConfig = {
appName
:
'Web 应用'
,
uniplatApi
:
import
.
meta
.
env
.
VITE_APP_UNIPLAT
||
''
,
// TODO: 替换为后端分配的平台入口标识
rootEntrance
:
''
,
rootEntrance
:
'
统一业务平台
'
,
logEnv
:
(
import
.
meta
.
env
.
VITE_APP_ENV
||
Environment
.
Dev
)
as
Environment
,
clientId
:
(
import
.
meta
.
env
.
VITE_APP_CLIENT_ID
||
''
)
as
ClientId
,
domainService
:
{
// TODO: 替换为项目实际的子项目名与服务名
subProjectName
:
''
,
serviceName
:
''
,
// TODO: 替换为项目实际的子项目名与服务名
(当前为测试环境的示例值)
subProjectName
:
'
welfare_v2
'
,
serviceName
:
'
smart_app_api
'
,
},
passportUrl
:
import
.
meta
.
env
.
VITE_APP_WWW_WORK_APP_URL
||
''
,
imgBaseUrl
:
`
${
import
.
meta
.
env
.
VITE_APP_LAND_PAGE
||
''
}
/img/`
,
...
...
packages/web/src/pages/login/index.vue
View file @
527c65d0
...
...
@@ -38,12 +38,24 @@
placeholder=
"请输入图形验证码"
/>
<img
v-if=
"verifyImage.img"
v-if=
"verifyImage.img
&& !verifyImageFailed
"
:src=
"verifyImage.img"
class=
"login__verify-img"
alt=
"验证码"
title=
"点击刷新"
@
click=
"refreshVerifyImage"
@
error=
"verifyImageFailed = true"
/>
<!-- 拿不到验证码时给出可点击的占位,而不是留一个破图 -->
<button
v-else
class=
"login__verify-img login__verify-img--fallback"
type=
"button"
title=
"点击重试"
@
click=
"refreshVerifyImage"
>
加载失败
<br
/>
点击重试
</button>
</div>
<div
class=
"login__row"
>
...
...
@@ -92,6 +104,7 @@
<
/template
>
<
script
setup
lang
=
"ts"
>
import
type
{
VerifyImageResult
}
from
'@common/sdk'
import
{
SMS_COUNTDOWN
}
from
'@common/utils/constants'
import
{
isPhone
}
from
'@common/utils/regex'
import
{
ref
}
from
'vue'
...
...
@@ -116,17 +129,18 @@ const passwordForm = ref({ username: '', password: '' })
const
smsLoading
=
ref
(
false
)
const
pwdLoading
=
ref
(
false
)
const
countdown
=
ref
(
0
)
const
verifyImage
=
ref
({
img
:
''
,
seed
:
''
}
)
const
verifyImage
=
ref
<
VerifyImageResult
>
({
img
:
''
,
seed
:
''
}
)
const
verifyImageFailed
=
ref
(
false
)
let
timer
:
ReturnType
<
typeof
setInterval
>
|
null
=
null
// 获取图形验证码
// 获取图形验证码
(同步拼 URL,加载失败由 <img> 的 error 事件兜住)
function
refreshVerifyImage
()
{
try
{
verifyImage
.
value
=
getVerifyImage
()
as
any
}
catch
{
Toast
.
error
(
'获取图形验证码失败'
)
verifyImageFailed
.
value
=
false
verifyImage
.
value
=
getVerifyImage
()
if
(
!
verifyImage
.
value
.
img
)
{
verifyImageFailed
.
value
=
true
Toast
.
error
(
'获取图形验证码失败
,请检查 VITE_APP_UNIPLAT 配置
'
)
}
}
...
...
@@ -268,10 +282,20 @@ refreshVerifyImage()
}
&
__verify
-
img
{
flex
:
none
;
width
:
120
px
;
height
:
44
px
;
border
-
radius
:
4
px
;
cursor
:
pointer
;
&--
fallback
{
padding
:
0
;
border
:
1
px
dashed
#
ddd
;
background
:
#
fafafa
;
color
:
#
999
;
font
-
size
:
12
px
;
line
-
height
:
1.3
;
}
}
&
__sms
-
btn
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment