feat: 解决合并冲突
This commit is contained in:
parent
bc3d82e20e
commit
f0b650de26
3
.gitignore
vendored
3
.gitignore
vendored
@ -23,7 +23,6 @@ node_modules
|
|||||||
package-lock.json
|
package-lock.json
|
||||||
# Added by code-review-graph
|
# Added by code-review-graph
|
||||||
.code-review-graph/
|
.code-review-graph/
|
||||||
<<<<<<< HEAD
|
|
||||||
|
|
||||||
.claude
|
.claude
|
||||||
# 本地重复脚本(不提交仓库)
|
# 本地重复脚本(不提交仓库)
|
||||||
@ -39,8 +38,6 @@ backend/**/*.exe
|
|||||||
|
|
||||||
# 浏览器远程调试临时文件
|
# 浏览器远程调试临时文件
|
||||||
.tmp-browser/
|
.tmp-browser/
|
||||||
=======
|
|
||||||
.claude/
|
.claude/
|
||||||
hookify.*.local.md
|
hookify.*.local.md
|
||||||
.mcp.json
|
.mcp.json
|
||||||
>>>>>>> 0284bd6951fafc8a3862644ede979dc44eb6efe8
|
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
// Config 网关配置
|
// Config 网关配置
|
||||||
type Config struct {
|
type Config struct {
|
||||||
<<<<<<< HEAD
|
|
||||||
Server ServerConfig
|
Server ServerConfig
|
||||||
Dubbo DubboConfig
|
Dubbo DubboConfig
|
||||||
JWT JWTConfig
|
JWT JWTConfig
|
||||||
@ -37,7 +36,6 @@ type LaserCompositorConfig struct {
|
|||||||
type DifyConfig struct {
|
type DifyConfig struct {
|
||||||
APIBase string
|
APIBase string
|
||||||
APIKey string
|
APIKey string
|
||||||
=======
|
|
||||||
Server ServerConfig
|
Server ServerConfig
|
||||||
Dubbo DubboConfig
|
Dubbo DubboConfig
|
||||||
JWT JWTConfig
|
JWT JWTConfig
|
||||||
@ -45,7 +43,6 @@ type DifyConfig struct {
|
|||||||
Redis RedisConfig
|
Redis RedisConfig
|
||||||
WebSocket WebSocketConfig
|
WebSocket WebSocketConfig
|
||||||
Root string
|
Root string
|
||||||
>>>>>>> 0284bd6951fafc8a3862644ede979dc44eb6efe8
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedisConfig Redis 配置
|
// RedisConfig Redis 配置
|
||||||
@ -178,19 +175,8 @@ func Load() *Config {
|
|||||||
Password: getEnv("REDIS_PASSWORD", ""),
|
Password: getEnv("REDIS_PASSWORD", ""),
|
||||||
DB: getEnvInt("REDIS_DB", 0),
|
DB: getEnvInt("REDIS_DB", 0),
|
||||||
},
|
},
|
||||||
<<<<<<< HEAD
|
|
||||||
DB: DBConfig{
|
|
||||||
Host: getEnv("DB_HOST", "localhost"),
|
|
||||||
Port: getEnvInt("DB_PORT", 5432),
|
|
||||||
User: getEnv("DB_USER", "postgres"),
|
|
||||||
Password: getEnv("DB_PASSWORD", ""),
|
|
||||||
DBName: getEnv("DB_NAME", "top-fans"),
|
|
||||||
SSLMode: getEnv("DB_SSLMODE", "disable"),
|
|
||||||
TimeZone: getEnv("DB_TIMEZONE", "Asia/Shanghai"),
|
|
||||||
=======
|
|
||||||
WebSocket: WebSocketConfig{
|
WebSocket: WebSocketConfig{
|
||||||
AIChatPath: getEnv("WS_AI_CHAT_PATH", "/ws/ai-chat"),
|
AIChatPath: getEnv("WS_AI_CHAT_PATH", "/ws/ai-chat"),
|
||||||
>>>>>>> 0284bd6951fafc8a3862644ede979dc44eb6efe8
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,16 +86,13 @@ func SetupRouter(userClient *client.Client, socialClient *client.Client, assetCl
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
segmentCtrl := controller.NewSegmentController()
|
segmentCtrl := controller.NewSegmentController()
|
||||||
|
|
||||||
laserGenCtrl := controller.NewLaserGenerateController(config.Load())
|
laserGenCtrl := controller.NewLaserGenerateController(config.Load())
|
||||||
=======
|
|
||||||
aiChatCtrl, err := controller.NewAIChatController(aiChatClient)
|
aiChatCtrl, err := controller.NewAIChatController(aiChatClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
>>>>>>> 0284bd6951fafc8a3862644ede979dc44eb6efe8
|
|
||||||
|
|
||||||
// API v1 路由组
|
// API v1 路由组
|
||||||
v1 := r.Group("/api/v1")
|
v1 := r.Group("/api/v1")
|
||||||
|
|||||||
@ -318,12 +318,9 @@ services:
|
|||||||
DUBBO_ACTIVITY_SERVICE_URL: tri://activityservice:20005
|
DUBBO_ACTIVITY_SERVICE_URL: tri://activityservice:20005
|
||||||
DUBBO_TASK_SERVICE_URL: tri://taskservice:20006
|
DUBBO_TASK_SERVICE_URL: tri://taskservice:20006
|
||||||
DUBBO_STARBOOK_SERVICE_URL: tri://starbookservice:20007
|
DUBBO_STARBOOK_SERVICE_URL: tri://starbookservice:20007
|
||||||
<<<<<<< HEAD
|
|
||||||
DIFY_API_BASE: ${DIFY_API_BASE:-http://host.docker.internal:8081/v1}
|
DIFY_API_BASE: ${DIFY_API_BASE:-http://host.docker.internal:8081/v1}
|
||||||
DIFY_API_KEY: ${DIFY_API_KEY:-}
|
DIFY_API_KEY: ${DIFY_API_KEY:-}
|
||||||
=======
|
|
||||||
DUBBO_AI_CHAT_SERVICE_URL: tri://aichatservice:20008
|
DUBBO_AI_CHAT_SERVICE_URL: tri://aichatservice:20008
|
||||||
>>>>>>> 0284bd6951fafc8a3862644ede979dc44eb6efe8
|
|
||||||
depends_on:
|
depends_on:
|
||||||
userservice:
|
userservice:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|||||||
@ -446,12 +446,9 @@ services:
|
|||||||
DUBBO_ACTIVITY_SERVICE_URL: tri://activityservice:20004
|
DUBBO_ACTIVITY_SERVICE_URL: tri://activityservice:20004
|
||||||
DUBBO_TASK_SERVICE_URL: tri://taskservice:20006
|
DUBBO_TASK_SERVICE_URL: tri://taskservice:20006
|
||||||
DUBBO_STARBOOK_SERVICE_URL: tri://starbookservice:20005
|
DUBBO_STARBOOK_SERVICE_URL: tri://starbookservice:20005
|
||||||
<<<<<<< HEAD
|
|
||||||
DIFY_API_BASE: ${DIFY_API_BASE:-http://dify-api:8081/v1}
|
DIFY_API_BASE: ${DIFY_API_BASE:-http://dify-api:8081/v1}
|
||||||
DIFY_API_KEY: ${DIFY_API_KEY:-}
|
DIFY_API_KEY: ${DIFY_API_KEY:-}
|
||||||
=======
|
|
||||||
DUBBO_AI_CHAT_SERVICE_URL: tri://aichatservice:20008
|
DUBBO_AI_CHAT_SERVICE_URL: tri://aichatservice:20008
|
||||||
>>>>>>> 0284bd6951fafc8a3862644ede979dc44eb6efe8
|
|
||||||
REDIS_HOST: topfans-redis
|
REDIS_HOST: topfans-redis
|
||||||
REDIS_PORT: 6379
|
REDIS_PORT: 6379
|
||||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
|
REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
|
||||||
|
|||||||
@ -97,7 +97,6 @@ export default {
|
|||||||
this.applyType(val);
|
this.applyType(val);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
<<<<<<< HEAD
|
|
||||||
computed: {
|
computed: {
|
||||||
currentCardList() {
|
currentCardList() {
|
||||||
const categoryName = this.categoryList[this.selectedCategoryIndex].name
|
const categoryName = this.categoryList[this.selectedCategoryIndex].name
|
||||||
@ -240,21 +239,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
=======
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
// 组件创建时立即应用一次 type,避免 mall.vue 在 onLoad 才设置 initialType
|
|
||||||
// 导致首次渲染拿到默认 "" 而 watch 错过的情况
|
|
||||||
this.applyType(this.type);
|
|
||||||
},
|
|
||||||
onLoad(options) {
|
|
||||||
// 作为页面被直接打开时,隐藏右侧分类菜单栏(根据用户需求)
|
|
||||||
this.showMenu = false;
|
|
||||||
// 接收从主Tab(square.vue / CastloveContent.vue)传入的 type,自动定位到对应分类
|
|
||||||
// type 取值:star_card | badge | poster
|
|
||||||
if (options && options.type) {
|
|
||||||
this.applyType(options.type);
|
|
||||||
>>>>>>> 0284bd6951fafc8a3862644ede979dc44eb6efe8
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
src="/static/dashboard/crystal-bg.png"
|
src="/static/dashboard/crystal-bg.png"
|
||||||
mode="aspectFit"
|
mode="aspectFit"
|
||||||
/>
|
/>
|
||||||
<text class="tab-title">水晶相关</text>
|
<text class="tab-title">收益总览</text>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
:class="['tab', activeTab === 'season' ? 'tab-active' : '']"
|
:class="['tab', activeTab === 'season' ? 'tab-active' : '']"
|
||||||
|
|||||||
@ -1,11 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="register-container">
|
<view class="register-container">
|
||||||
<!-- 背景图片层 -->
|
<!-- 背景图片层 -->
|
||||||
<image class="background-image" src="/static/background/login-bg.png" mode="aspectFill"></image>
|
<image
|
||||||
|
class="background-image"
|
||||||
|
src="/static/background/login-bg.png"
|
||||||
|
mode="aspectFill"
|
||||||
|
></image>
|
||||||
<!-- 女孩图片 -->
|
<!-- 女孩图片 -->
|
||||||
<image class="girl-image" src="/static/login/person-photo.png" mode="aspectFit"></image>
|
<image
|
||||||
|
class="girl-image"
|
||||||
|
src="/static/login/person-photo.png"
|
||||||
|
mode="aspectFit"
|
||||||
|
></image>
|
||||||
<!-- 粉色玩偶(遮挡女孩脸的下半部分) -->
|
<!-- 粉色玩偶(遮挡女孩脸的下半部分) -->
|
||||||
<image class="doll-image" src="/static/login/login-character.png" mode="aspectFit"></image>
|
<image
|
||||||
|
class="doll-image"
|
||||||
|
src="/static/login/login-character.png"
|
||||||
|
mode="aspectFit"
|
||||||
|
></image>
|
||||||
<view class="background-overlay"></view>
|
<view class="background-overlay"></view>
|
||||||
|
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域 -->
|
||||||
@ -43,30 +55,40 @@
|
|||||||
/>
|
/>
|
||||||
<view
|
<view
|
||||||
class="send-code-btn"
|
class="send-code-btn"
|
||||||
:class="{ 'countdown': codeStatus === 'countdown', 'verified': codeStatus === 'verified' }"
|
:class="{
|
||||||
|
countdown: codeStatus === 'countdown',
|
||||||
|
verified: codeStatus === 'verified',
|
||||||
|
}"
|
||||||
@click="handleSendCode"
|
@click="handleSendCode"
|
||||||
>
|
>
|
||||||
<text v-if="codeStatus === 'unsent' || codeStatus === 'resend'">发送验证码</text>
|
<text v-if="codeStatus === 'unsent' || codeStatus === 'resend'"
|
||||||
<text v-else-if="codeStatus === 'countdown'">{{countdown}}秒</text>
|
>发送验证码</text
|
||||||
|
>
|
||||||
|
<text v-else-if="codeStatus === 'countdown'"
|
||||||
|
>{{ countdown }}秒</text
|
||||||
|
>
|
||||||
<text v-else-if="codeStatus === 'verified'">已验证</text>
|
<text v-else-if="codeStatus === 'verified'">已验证</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 验证码错误提示 -->
|
<!-- 验证码错误提示 -->
|
||||||
<view v-if="codeError" class="error-message">
|
<view v-if="codeError" class="error-message">
|
||||||
<text>{{codeError}}</text>
|
<text>{{ codeError }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 验证按钮(验证码输入后显示) -->
|
<!-- 验证按钮(验证码输入后显示) -->
|
||||||
<view v-if="showCodeInput && codeStatus !== 'verified'" class="verify-btn-wrapper">
|
<!-- <view
|
||||||
|
v-if="showCodeInput && codeStatus !== 'verified'"
|
||||||
|
class="verify-btn-wrapper"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="btn-secondary"
|
class="btn-secondary"
|
||||||
:disabled="isVerifying || !form.code || form.code.length !== 6"
|
:disabled="isVerifying || !form.code || form.code.length !== 6"
|
||||||
@click="handleVerifyCode"
|
@click="handleVerifyCode"
|
||||||
>
|
>
|
||||||
{{ isVerifying ? '验证中...' : '验证验证码' }}
|
{{ isVerifying ? "验证中..." : "验证验证码" }}
|
||||||
</button>
|
</button>
|
||||||
</view>
|
</view> -->
|
||||||
|
|
||||||
<!-- 密码输入框 -->
|
<!-- 密码输入框 -->
|
||||||
<view class="input-wrapper password-wrapper">
|
<view class="input-wrapper password-wrapper">
|
||||||
@ -78,7 +100,7 @@
|
|||||||
placeholder-class="input-placeholder"
|
placeholder-class="input-placeholder"
|
||||||
/>
|
/>
|
||||||
<view class="eye-icon" @click="togglePassword">
|
<view class="eye-icon" @click="togglePassword">
|
||||||
<text class="eye-text">{{ showPassword ? '👁️' : '👁️🗨️' }}</text>
|
<text class="eye-text">{{ showPassword ? "👁️" : "👁️🗨️" }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -101,12 +123,14 @@
|
|||||||
<view class="footer-text">
|
<view class="footer-text">
|
||||||
<view class="agreement-wrapper">
|
<view class="agreement-wrapper">
|
||||||
<view class="agreement-checkbox" @click="toggleAgreement">
|
<view class="agreement-checkbox" @click="toggleAgreement">
|
||||||
<view class="custom-checkbox" :class="{ 'checked': agreedToTerms }">
|
<view class="custom-checkbox" :class="{ checked: agreedToTerms }">
|
||||||
<view v-if="agreedToTerms" class="checkbox-inner"></view>
|
<view v-if="agreedToTerms" class="checkbox-inner"></view>
|
||||||
</view>
|
</view>
|
||||||
<text class="agreement-label">我已阅读并同意</text>
|
<text class="agreement-label">我已阅读并同意</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="agreement-link" @click="showAgreementModal">《Topfans用户服务协议》</text>
|
<text class="agreement-link" @click="showAgreementModal"
|
||||||
|
>《Topfans用户服务协议》</text
|
||||||
|
>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -120,23 +144,35 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="tip-dialog-content">
|
<view class="tip-dialog-content">
|
||||||
<text class="tip-text">阅读并同意以下条款</text>
|
<text class="tip-text">阅读并同意以下条款</text>
|
||||||
<text class="tip-agreement-link" @click="openAgreementFromTip">《Topfans用户服务协议》</text>
|
<text class="tip-agreement-link" @click="openAgreementFromTip"
|
||||||
|
>《Topfans用户服务协议》</text
|
||||||
|
>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 协议全文弹窗 -->
|
<!-- 协议全文弹窗 -->
|
||||||
<view v-if="showAgreementDialog" class="agreement-dialog-mask" @click="closeAgreementDialog">
|
<view
|
||||||
|
v-if="showAgreementDialog"
|
||||||
|
class="agreement-dialog-mask"
|
||||||
|
@click="closeAgreementDialog"
|
||||||
|
>
|
||||||
<view class="agreement-dialog" @click.stop>
|
<view class="agreement-dialog" @click.stop>
|
||||||
<view class="agreement-dialog-header">
|
<view class="agreement-dialog-header">
|
||||||
<text class="agreement-dialog-title">Topfans用户服务协议</text>
|
<text class="agreement-dialog-title">Topfans用户服务协议</text>
|
||||||
<text class="agreement-dialog-close" @click="closeAgreementDialog">×</text>
|
<text class="agreement-dialog-close" @click="closeAgreementDialog"
|
||||||
|
>×</text
|
||||||
|
>
|
||||||
</view>
|
</view>
|
||||||
<scroll-view class="agreement-dialog-content" scroll-y>
|
<scroll-view class="agreement-dialog-content" scroll-y>
|
||||||
<text class="agreement-text">{{ agreementContent || '协议内容加载中...' }}</text>
|
<text class="agreement-text">{{
|
||||||
|
agreementContent || "协议内容加载中..."
|
||||||
|
}}</text>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view class="agreement-dialog-footer">
|
<view class="agreement-dialog-footer">
|
||||||
<button class="agreement-confirm-btn" @click="agreeAndClose">我同意</button>
|
<button class="agreement-confirm-btn" @click="agreeAndClose">
|
||||||
|
我同意
|
||||||
|
</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -144,29 +180,29 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from "vue";
|
||||||
import { validatePhone, validatePassword } from '@/utils/validator';
|
import { validatePhone, validatePassword } from "@/utils/validator";
|
||||||
import { AGREEMENT_CONTENT } from '@/utils/agreement';
|
import { AGREEMENT_CONTENT } from "@/utils/agreement";
|
||||||
import { checkmobileApi, sendCodeApi, verifyCodeApi } from '@/utils/api';
|
import { checkmobileApi, sendCodeApi, verifyCodeApi } from "@/utils/api";
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const form = ref({
|
const form = ref({
|
||||||
phone: '',
|
phone: "",
|
||||||
password: '',
|
password: "",
|
||||||
code: ''
|
code: "",
|
||||||
});
|
});
|
||||||
const showPassword = ref(false);
|
const showPassword = ref(false);
|
||||||
const errorMessage = ref('');
|
const errorMessage = ref("");
|
||||||
const agreedToTerms = ref(false);
|
const agreedToTerms = ref(false);
|
||||||
const agreementContent = ref('');
|
const agreementContent = ref("");
|
||||||
const showAgreementDialog = ref(false);
|
const showAgreementDialog = ref(false);
|
||||||
const showTipDialog = ref(false);
|
const showTipDialog = ref(false);
|
||||||
const phoneChecking = ref(false);
|
const phoneChecking = ref(false);
|
||||||
const showCodeInput = ref(true); // 是否显示验证码输入框
|
const showCodeInput = ref(true); // 是否显示验证码输入框
|
||||||
const codeStatus = ref('unsent'); // unsent, countdown, resend, verified
|
const codeStatus = ref("unsent"); // unsent, countdown, resend, verified
|
||||||
const countdown = ref(60);
|
const countdown = ref(60);
|
||||||
const codeError = ref('');
|
const codeError = ref("");
|
||||||
const verifyToken = ref('');
|
const verifyToken = ref("");
|
||||||
const countdownTimer = ref(null);
|
const countdownTimer = ref(null);
|
||||||
const isVerifying = ref(false);
|
const isVerifying = ref(false);
|
||||||
|
|
||||||
@ -198,7 +234,7 @@ const checkPhoneDuplicate = async (phone) => {
|
|||||||
// 手机号格式验证
|
// 手机号格式验证
|
||||||
const phoneValidation = validatePhone(phone);
|
const phoneValidation = validatePhone(phone);
|
||||||
if (!phoneValidation.valid || phone.length !== 11) {
|
if (!phoneValidation.valid || phone.length !== 11) {
|
||||||
errorMessage.value = '';
|
errorMessage.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,13 +244,13 @@ const checkPhoneDuplicate = async (phone) => {
|
|||||||
try {
|
try {
|
||||||
const res = await checkmobileApi(phone);
|
const res = await checkmobileApi(phone);
|
||||||
if (res.code === 200 && res.data && res.data.exists) {
|
if (res.code === 200 && res.data && res.data.exists) {
|
||||||
errorMessage.value = '该手机号已被注册';
|
errorMessage.value = "该手机号已被注册";
|
||||||
} else {
|
} else {
|
||||||
errorMessage.value = '';
|
errorMessage.value = "";
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 接口错误不阻断流程,留到注册时统一处理
|
// 接口错误不阻断流程,留到注册时统一处理
|
||||||
errorMessage.value = '';
|
errorMessage.value = "";
|
||||||
} finally {
|
} finally {
|
||||||
phoneChecking.value = false;
|
phoneChecking.value = false;
|
||||||
}
|
}
|
||||||
@ -230,16 +266,16 @@ const handleSendCode = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await sendCodeApi(form.value.phone, 'register');
|
const res = await sendCodeApi(form.value.phone, "register");
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
codeStatus.value = 'countdown';
|
codeStatus.value = "countdown";
|
||||||
countdown.value = res.expires_in || 60;
|
countdown.value = res.expires_in || 60;
|
||||||
showCodeInput.value = true;
|
showCodeInput.value = true;
|
||||||
startCountdown();
|
startCountdown();
|
||||||
uni.showToast({ title: '验证码已发送', icon: 'success' });
|
uni.showToast({ title: "验证码已发送", icon: "success" });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
codeError.value = error.message || '发送失败,请重试';
|
codeError.value = error.message || "发送失败,请重试";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -252,7 +288,7 @@ const startCountdown = () => {
|
|||||||
countdown.value--;
|
countdown.value--;
|
||||||
if (countdown.value <= 0) {
|
if (countdown.value <= 0) {
|
||||||
clearInterval(countdownTimer.value);
|
clearInterval(countdownTimer.value);
|
||||||
codeStatus.value = 'resend';
|
codeStatus.value = "resend";
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
};
|
};
|
||||||
@ -260,21 +296,25 @@ const startCountdown = () => {
|
|||||||
// 验证验证码
|
// 验证验证码
|
||||||
const handleVerifyCode = async () => {
|
const handleVerifyCode = async () => {
|
||||||
if (!form.value.code || form.value.code.length !== 6) {
|
if (!form.value.code || form.value.code.length !== 6) {
|
||||||
codeError.value = '请输入6位验证码';
|
codeError.value = "请输入6位验证码";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
isVerifying.value = true;
|
isVerifying.value = true;
|
||||||
codeError.value = '';
|
codeError.value = "";
|
||||||
try {
|
try {
|
||||||
const res = await verifyCodeApi(form.value.phone, form.value.code, 'register');
|
const res = await verifyCodeApi(
|
||||||
|
form.value.phone,
|
||||||
|
form.value.code,
|
||||||
|
"register",
|
||||||
|
);
|
||||||
if (res.code === 200 && res.data && res.data.verified) {
|
if (res.code === 200 && res.data && res.data.verified) {
|
||||||
verifyToken.value = res.data.verify_token;
|
verifyToken.value = res.data.verify_token;
|
||||||
codeStatus.value = 'verified';
|
codeStatus.value = "verified";
|
||||||
uni.showToast({ title: '验证成功', icon: 'success' });
|
uni.showToast({ title: "验证成功", icon: "success" });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
codeError.value = error.message || '验证失败';
|
codeError.value = error.message || "验证失败";
|
||||||
} finally {
|
} finally {
|
||||||
isVerifying.value = false;
|
isVerifying.value = false;
|
||||||
}
|
}
|
||||||
@ -289,7 +329,7 @@ const goToLogin = () => {
|
|||||||
} else {
|
} else {
|
||||||
// 没有上一页,跳转到square页面
|
// 没有上一页,跳转到square页面
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: '/pages/login/login'
|
url: "/pages/login/login",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -341,6 +381,7 @@ const openAgreementFromTip = () => {
|
|||||||
|
|
||||||
// 注册
|
// 注册
|
||||||
const handleRegister = async () => {
|
const handleRegister = async () => {
|
||||||
|
handleVerifyCode();
|
||||||
// 验证是否勾选协议
|
// 验证是否勾选协议
|
||||||
if (!agreedToTerms.value) {
|
if (!agreedToTerms.value) {
|
||||||
openTipDialog();
|
openTipDialog();
|
||||||
@ -348,8 +389,8 @@ const handleRegister = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否已验证(仅当显示了验证码输入框时)
|
// 检查是否已验证(仅当显示了验证码输入框时)
|
||||||
if (showCodeInput.value && codeStatus.value !== 'verified') {
|
if (showCodeInput.value && codeStatus.value !== "verified") {
|
||||||
errorMessage.value = '请先完成手机号验证';
|
errorMessage.value = "请先完成手机号验证";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,7 +400,7 @@ const handleRegister = async () => {
|
|||||||
errorMessage.value = phoneValidation.message;
|
errorMessage.value = phoneValidation.message;
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: phoneValidation.message,
|
title: phoneValidation.message,
|
||||||
icon: 'none'
|
icon: "none",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -369,30 +410,30 @@ const handleRegister = async () => {
|
|||||||
errorMessage.value = passwordValidation.message;
|
errorMessage.value = passwordValidation.message;
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: passwordValidation.message,
|
title: passwordValidation.message,
|
||||||
icon: 'none'
|
icon: "none",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorMessage.value = '';
|
errorMessage.value = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 暂存手机号和密码到临时存储,供后续注册流程使用
|
// 暂存手机号和密码到临时存储,供后续注册流程使用
|
||||||
uni.setStorageSync('temp_register_mobile', form.value.phone);
|
uni.setStorageSync("temp_register_mobile", form.value.phone);
|
||||||
uni.setStorageSync('temp_register_password', form.value.password);
|
uni.setStorageSync("temp_register_password", form.value.password);
|
||||||
|
|
||||||
// 存储verify_token
|
// 存储verify_token
|
||||||
uni.setStorageSync('temp_register_verify_token', verifyToken.value);
|
uni.setStorageSync("temp_register_verify_token", verifyToken.value);
|
||||||
|
|
||||||
// 跳转到昵称设置页面
|
// 跳转到昵称设置页面
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: '/pages/profile/setNickname'
|
url: "/pages/profile/setNickname",
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
errorMessage.value = error.message || '操作失败,请重试';
|
errorMessage.value = error.message || "操作失败,请重试";
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: errorMessage.value,
|
title: errorMessage.value,
|
||||||
icon: 'none'
|
icon: "none",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -489,15 +530,15 @@ const handleRegister = async () => {
|
|||||||
font-size: 135rpx;
|
font-size: 135rpx;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
letter-spacing: 12rpx;
|
letter-spacing: 12rpx;
|
||||||
background: linear-gradient(to right, #B52920 0%, #86D9E0 85%, #56C1FF 110%);
|
background: linear-gradient(to right, #b52920 0%, #86d9e0 85%, #56c1ff 110%);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
color: #8B0000;
|
color: #8b0000;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-family: 'TheMiladiatorRegular', sans-serif !important;
|
font-family: "TheMiladiatorRegular", sans-serif !important;
|
||||||
filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.15));
|
filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.15));
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -547,7 +588,7 @@ const handleRegister = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.send-code-btn.verified {
|
.send-code-btn.verified {
|
||||||
background: #4CAF50;
|
background: #4caf50;
|
||||||
}
|
}
|
||||||
|
|
||||||
.verify-btn-wrapper {
|
.verify-btn-wrapper {
|
||||||
@ -558,11 +599,11 @@ const handleRegister = async () => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 88rpx;
|
height: 88rpx;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 2rpx solid #B94E73;
|
border: 2rpx solid #b94e73;
|
||||||
border-radius: 50rpx;
|
border-radius: 50rpx;
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #B94E73;
|
color: #b94e73;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -614,7 +655,13 @@ const handleRegister = async () => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100rpx;
|
height: 100rpx;
|
||||||
margin-bottom: 30rpx;
|
margin-bottom: 30rpx;
|
||||||
background: linear-gradient(165deg, #F0E4B1 0%, #F08399 50%, #B94E73 90%, #834B9E 100%);
|
background: linear-gradient(
|
||||||
|
165deg,
|
||||||
|
#f0e4b1 0%,
|
||||||
|
#f08399 50%,
|
||||||
|
#b94e73 90%,
|
||||||
|
#834b9e 100%
|
||||||
|
);
|
||||||
border-radius: 50rpx;
|
border-radius: 50rpx;
|
||||||
border: none;
|
border: none;
|
||||||
font-size: 36rpx;
|
font-size: 36rpx;
|
||||||
@ -884,10 +931,9 @@ const handleRegister = async () => {
|
|||||||
|
|
||||||
.tip-agreement-link {
|
.tip-agreement-link {
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
color: #007AFF;
|
color: #007aff;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 63 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 410 KiB After Width: | Height: | Size: 1.6 MiB |
Loading…
Reference in New Issue
Block a user