feat(api-keys): 优化隐私协议同意逻辑及样式

- 修正api-keys样式导入路径,改为developer路径
- 在开发者申请页面增加服务协议和隐私政策勾选框
- 提交时校验协议是否已勾选,未勾选时提示用户
- 优化申请页面协议区域样式及交互
- 在用户验证页面添加隐私政策同意勾选框
- 提交用户验证表单时检查协议同意状态
- 增加打开服务协议和隐私政策的链接跳转
- 更新项目配置,增加passport/webview路由配置
- 修复createTicket函数中日期格式正则表达式问题
This commit is contained in:
2026-04-13 02:40:27 +08:00
parent ffab0ec25c
commit f2d6b029f1
5 changed files with 93 additions and 17 deletions

View File

@@ -4,12 +4,19 @@
"condition": { "condition": {
"miniprogram": { "miniprogram": {
"list": [ "list": [
{
"name": "passport/webview/index",
"pathName": "passport/webview/index",
"query": "url=https%3A%2F%2Fwebsopy.websoft.top%2Fdeveloper",
"scene": null,
"launchMode": "default"
},
{ {
"name": "passport/login", "name": "passport/login",
"pathName": "passport/login", "pathName": "passport/login",
"query": "", "query": "",
"scene": null, "launchMode": "default",
"launchMode": "default" "scene": null
}, },
{ {
"name": "passport/invite/index", "name": "passport/invite/index",

View File

@@ -187,7 +187,7 @@ export async function listTicketReply(ticketId: string): Promise<TicketReply[]>
export async function createTicket(data: Partial<Ticket>): Promise<Ticket> { export async function createTicket(data: Partial<Ticket>): Promise<Ticket> {
const newTicket: Ticket = { const newTicket: Ticket = {
id: String(Date.now()), id: String(Date.now()),
ticketNo: `TK${new Date().toISOString().replace(/[-:T]/g, '').slice(0, 12)}`, ticketNo: `TK${new Date().toISOString().replace(/[\-:T]/g, '').slice(0, 12)}`,
title: data.title || '', title: data.title || '',
content: data.content || '', content: data.content || '',
type: data.type || 'technical', type: data.type || 'technical',

View File

@@ -31,6 +31,7 @@ const DeveloperApplyPage: React.FC = () => {
experience: '', experience: '',
}) })
const [submitting, setSubmitting] = useState(false) const [submitting, setSubmitting] = useState(false)
const [agreementChecked, setAgreementChecked] = useState(false)
// 加载申请记录 // 加载申请记录
const loadData = async (pageNum: number = 1, isRefresh = false) => { const loadData = async (pageNum: number = 1, isRefresh = false) => {
@@ -77,6 +78,15 @@ const DeveloperApplyPage: React.FC = () => {
return return
} }
// 检查隐私协议是否同意
if (!agreementChecked) {
Taro.showToast({
title: '请先同意服务协议和隐私政策',
icon: 'none'
});
return false;
}
setSubmitting(true) setSubmitting(true)
try { try {
await createApply({ await createApply({
@@ -203,9 +213,26 @@ const DeveloperApplyPage: React.FC = () => {
</View> </View>
<View className="apply-page__agreement"> <View className="apply-page__agreement">
<Text className="apply-page__agreement-text"> <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<View
</Text> style={{
width: '18px', height: '18px', borderRadius: '4px',
border: agreementChecked ? 'none' : '1px solid #ccc',
background: agreementChecked ? '#3b82f6' : 'transparent',
display: 'flex', alignItems: 'center', justifyContent: 'center',
marginRight: '8px'
}}
onClick={() => setAgreementChecked(!agreementChecked)}
>
{agreementChecked && <Text style={{ color: '#fff', fontSize: '12px' }}></Text>}
</View>
<Text className="apply-page__agreement-text" style={{ fontSize: '12px' }}>
<Text style={{ color: '#3b82f6' }} onClick={() => Taro.navigateTo({ url: '/passport/webview/index?url=' + encodeURIComponent('https://websopy.websoft.top/agreement') })}></Text>
<Text style={{ color: '#3b82f6' }} onClick={() => Taro.navigateTo({ url: '/passport/webview/index?url=' + encodeURIComponent('https://websopy.websoft.top/privacy') })}></Text>
</Text>
</View>
</View> </View>
<Button <Button

View File

@@ -1,2 +1,2 @@
// 复用 app/api-keys/index.scss 的样式 // 复用 developer/app/api-keys/index.scss 的样式
@import '../../app/api-keys/index'; @import '../../developer/app/api-keys/index';

View File

@@ -8,6 +8,7 @@ import {
Button, Button,
Input, Input,
Radio, Radio,
Checkbox,
} from '@nutui/nutui-react-taro' } from '@nutui/nutui-react-taro'
import {UserVerify} from "@/api/system/userVerify/model"; import {UserVerify} from "@/api/system/userVerify/model";
import {addUserVerify, myUserVerify, updateUserVerify} from "@/api/system/userVerify"; import {addUserVerify, myUserVerify, updateUserVerify} from "@/api/system/userVerify";
@@ -16,6 +17,7 @@ import {uploadFile} from "@/api/system/file";
function Index() { function Index() {
const [isUpdate, setIsUpdate] = useState<boolean>(false) const [isUpdate, setIsUpdate] = useState<boolean>(false)
const [submitText, setSubmitText] = useState<string>('提交') const [submitText, setSubmitText] = useState<string>('提交')
const [privacyAgreed, setPrivacyAgreed] = useState<boolean>(false)
const [FormData, setFormData] = useState<UserVerify>({ const [FormData, setFormData] = useState<UserVerify>({
userId: undefined, userId: undefined,
@@ -49,10 +51,29 @@ function Index() {
}) })
} }
// 打开协议页面
const openAgreement = (type: 'service' | 'privacy') => {
const urlMap = {
service: 'https://websopy.websoft.top/agreement',
privacy: 'https://websopy.websoft.top/privacy',
};
const targetUrl = encodeURIComponent(urlMap[type]);
Taro.navigateTo({ url: `/passport/webview/index?url=${targetUrl}` });
};
// 提交表单 // 提交表单
const submitSucceed = (values: any) => { const submitSucceed = (values: any) => {
console.log('提交表单', values); console.log('提交表单', values);
if (FormData.status != 2 && FormData.status != undefined) return false; if (FormData.status != 2 && FormData.status != undefined) return false;
// 检查隐私协议是否同意
if (!privacyAgreed) {
Taro.showToast({
title: '请先同意隐私政策和服务协议',
icon: 'none'
});
return false;
}
if (FormData.type == 0) { if (FormData.type == 0) {
if (!FormData.sfz1 || !FormData.sfz2) { if (!FormData.sfz1 || !FormData.sfz2) {
Taro.showToast({ Taro.showToast({
@@ -158,17 +179,38 @@ function Index() {
onFinishFailed={(errors) => submitFailed(errors)} onFinishFailed={(errors) => submitFailed(errors)}
footer={ footer={
FormData.status != 1 && FormData.status != 0 && ( FormData.status != 1 && FormData.status != 0 && (
<div <div style={{ width: '100%' }}>
style={{ {/* 隐私协议勾选 */}
<div style={{
display: 'flex', display: 'flex',
alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
width: '100%' marginBottom: '16px',
}} fontSize: '12px'
> }}>
<Button nativeType="submit" block type={'info'} <Checkbox
disabled={FormData.status != 2 && FormData.status != undefined}> checked={privacyAgreed}
{submitText} onChange={(value) => setPrivacyAgreed(value)}
</Button> />
<span style={{ color: '#666', marginLeft: '8px' }}>
<span style={{ color: '#3b82f6' }} onClick={() => openAgreement('service')}></span>
<span style={{ color: '#3b82f6' }} onClick={() => openAgreement('privacy')}></span>
</span>
</div>
<div
style={{
display: 'flex',
justifyContent: 'center',
width: '100%'
}}
>
<Button nativeType="submit" block type={'info'}
disabled={FormData.status != 2 && FormData.status != undefined}>
{submitText}
</Button>
</div>
</div> </div>
) )
} }