Browse Source

Merge branch 'wangyi/feature-20251022162725-启动页登录注册' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into dongqian/feature-20251022181325-deepmate简版

wangyi/feature-20251022162725-启动页登录注册
wangyetao 4 weeks ago
parent
commit
6af246bf65
  1. 90
      api/deepMate/deepMate.js
  2. 105
      api/start/login.js
  3. 8
      main.js
  4. 1820
      package-lock.json
  5. 11
      package.json
  6. 48
      pages/deepMate/deepMate.vue
  7. 88
      pages/start/login/login.vue
  8. 23
      server/deepchart.json
  9. 131
      server/login.json
  10. 12
      stores/index.js
  11. 44
      stores/modules/userInfo.js
  12. 69
      utils/http.js

90
api/deepMate/deepMate.js

@ -0,0 +1,90 @@
import { http } from '../../utils/http'
export const getData = () => {
return http({
method: 'GET',
url: '/ka',
})
}
/**
* 意图识别
{
"content":"森那美",
"language": "cn",
"marketlist": "hk,cn,usa,my,sg,vi,in,gb",
"token": "9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnilrmTwo5Fb"qJ91WrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs"
"model":1
}
* {
"code": 200,
"message": "操作成功",
"data": {
"code": "1A0001",
"market": "cn",
"name": "上证指数",
"refuse": "",
"recordId": 15,
"parentId": 14,
"stockId": 25,
"language": "cn",
"debug_url": "https://www.coze.cn/work_flow?execute_id=7564771475955515444&space_id=7564250621483040822&workflow_id=7564368306322292788&execute_mode=2"
}
*/
export const postIntent = (data) => {
return http({
method: 'GET',
url: '/intent',
data
})
}
/**
* 获取股票信息
* data{
"language": "cn",
"token": "9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnIlrmTwo5FbqJ9lWrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs",
"recordId": 5214,
"parentId": 4887,
"stockId": 1523
}
*
{"cftl":"当前股票处于安全区,牵牛绳为红色,出现蓝色推进K线","date":"更新时间: 24/10/2025","debug_url":"https://www.coze.cn/work_flow?execute_id=7565080703726846004&space_id=7564250621483040822&workflow_id=7564596757864071195&execute_mode=2","gfzl":"该股整体趋势相对较强,个股正处于推进上涨的关键阶段。若当前持有该股票,建议继续持有,进行持续跟踪。若当前无该股票,建议持续跟踪,等待适当时机再进行介入。","hxjzpg":"(1)牛股评级:★★☆☆☆\n(2)暴涨概率:40%\n(3)风险评估:非常安全\n(4)黄金价域:258.984~266.753\n(5)核心证据链\n 资金共识:当日多方资金流入\n 趋势动能:该股中长期处于上升趋势,短期处于强势状态。","kongjian":"预测低一值255.468,预测高一值257.692,预测低二值255.156,预测高二值255.807",
"markdown":"\n# <font color=\"#1890ff\">Alphabet Inc.全景作战报告</font>\n## 📊 股票分析报告\n### 📈 股票基本信息\n- **股票名称**: <font color=\"#52c41a\">Alphabet Inc.</font>\n- **股票代码**: <font color=\"#1890ff\">GOOGL</font>\n- **当前价格**: <font color=\"#ff4d4f\">259.920</font>\n- **更新时间**: 2025年10月24日\n- **时间节点**: 今日无变盘点\n\n### 🎯 核心价值评估\n- **安全边际**: <font color=\"#13c2c2\">164.424 ~ </font>\n- **黄金价域**: <font color=\"#faad14\">258.984 ~ 266.753</font>\n- **核心证据链**:\n - 🟢 **资金共识**: 当日多方资金<font color=\"#52c41a\">流入</font>\n - 🔥 **趋势动能**: 该股中长期处于<b><font color='#FF0000'>上升趋势</font></b>,短期处于<b><font color='#FF0000'>强势状态</font></b>。\n\n### 🕵️ 主力作战分析\n- **主力行为**:\n 1. 📊 该股庄家中长期筹码成本价格为 207.497,短期资金成本价格为 239.503。该股筹码分散,当日筹码成本价格为 254.335。\n 2. 🔍 近日没有出现主力集中吸筹。\n 3. 📈 近期主力持仓比例大于散户持仓比例。 当日主力持仓增加。 当日散户持仓减少。\n\n### 📊 技术分析\n- **空间维度**:\n - 📉 预测低一值: <font color=\"#13c2c2\">255.468</font>\n - 📈 预测高一值: <font color=\"#ff4d4f\">257.692</font>\n - 📉 预测低二值: <font color=\"#13c2c2\">255.156</font>\n - 📈 预测高二值: <font color=\"#ff4d4f\">255.807</font>\n- **能量分析**: <font color=\"#722ed1\">AI智能均线多头排列,当前卖盘小于买盘</font>\n\n### ⚡ 综合作战分析\n- **触发条件**: <font color=\"#fa8c16\">当前股票处于安全区,牵牛绳为红色,出现蓝色推进K线</font>\n- **攻防指令**: <font color=\"#eb2f96\">该股整体趋势相对较强,个股正处于推进上涨的关键阶段。若当前持有该股票,建议继续持有,进行持续跟踪。若当前无该股票,建议持续跟踪,等待适当时机再进行介入。</font>\n\n---\n<font color=\"#8c8c8c\">*该内容由AI生成,仅供参考,投资有风险,请注意甄别。*</font>\n ","message":"","name":"股票名称: Alphabet Inc.(GOOGL)","nengliang":"AI智能均线多头排列,当前卖盘小于买盘","price":"当前价格: 259.920","shijian":"今日无变盘点","zhuli1":"(1)该股庄家中长期筹码成本价格为 207.497,短期资金成本价格为 239.503。该股筹码分散,当日筹码成本价格为 254.335。","zhuli2":"(2)近日没有出现主力集中吸筹。","zhuli3":"(3)近期主力持仓比例大于散户持仓比例。 当日主力持仓增加。 当日散户持仓减少。"}
}
*/
export const postStock = (data) => {
return http({
method: 'GET',
url: '/stocks',
data
})
}
/**
* 获取历史记录
*/
export const postHistory = (data) => {
return http({
method: 'POST',
url: '/history',
data
})
}
/**
*
*/

105
api/start/login.js

@ -0,0 +1,105 @@
import { http } from '../../utils/http'
/**
*
* @param data 模拟手机号码
* {
"loginType":"EMAIL", //登录方式
"account":"q614588746@163.com" , //登陆账号 手机号/邮箱/dccode
"verifyCode":"837012", //验证码
"password":"", //密码
"useCode":"true", //是否使用验证码 true/false
"idToken":"", //第三方登录idToken
}
*/
export const LoginApi = (data) => {
return http({
method: 'GET',
url: '/loginFailureWrongCode',
data: {
data
},
})
}
/**
* 发送验证码
* @param {*} phoneNumber
* @returns
*/
export const SendCodeApi = (data) => {
return http({
method: 'GET',
url: '/sendCodeFailureTooFrequent',
data:{
data
}
})
}
/**
* 注册
*/
export const register = (data) => {
return http({
method: 'GET',
url: '/register',
data: {
data
},
})
}
/**
* 修改密码
*
*/
export const updatePassword = (data) => {
return http({
method: 'GET',
url: '/updatePassword',
data: {
data
},
})
}
/**
* 通过苹果登录
*/
export const postLoginAppleSimpleAPI = (phoneNumber) => {
return http({
method: 'POST',
url: '/login',
data: {
phoneNumber,
},
})
}
/**
* 通过谷歌登录
*/
export const postLoginGoogleSimpleAPI = (phoneNumber) => {
return http({
method: 'POST',
url: '/login/wxMin/simple',
data: {
phoneNumber,
},
})
}

8
main.js

@ -1,4 +1,5 @@
import App from './App' import App from './App'
import pinia from './stores/index.js'
// #ifndef VUE3 // #ifndef VUE3
import Vue from 'vue' import Vue from 'vue'
@ -12,7 +13,9 @@ Vue.component('LoginPrompt', LoginPrompt)
Vue.config.productionTip = false Vue.config.productionTip = false
App.mpType = 'app' App.mpType = 'app'
const app = new Vue({ const app = new Vue({
...App
...App,
// 挂载 store
pinia
}) })
app.$mount() app.$mount()
// #endif // #endif
@ -28,6 +31,9 @@ export function createApp() {
// 全局注册组件 // 全局注册组件
app.component('LoginPrompt', LoginPrompt) app.component('LoginPrompt', LoginPrompt)
// 挂载 store
app.use(pinia)
return { return {
app app
} }

1820
package-lock.json
File diff suppressed because it is too large
View File

11
package.json

@ -3,10 +3,13 @@
"server-deepchart": "json-server ./server/deepchart.json --port 8888" "server-deepchart": "json-server ./server/deepchart.json --port 8888"
}, },
"dependencies": { "dependencies": {
"markdown-it": "^14.1.0",
"marked": "^2.0.1"
"json-server": "^1.0.0-beta.3",
"marked": "^2.0.1",
"pinia": "^3.0.3",
"pinia-plugin-persistedstate": "^4.5.0"
}, },
"devDependencies": {
"json-server": "^0.17.4"
"scripts": {
"server-login": "json-server ./server/login.json --port 8888",
"server-deepchart": "json-server ./server/deepchart.json --port 8888"
} }
} }

48
pages/deepMate/deepMate.vue

@ -6,8 +6,11 @@
<image src="https://d31zlh4on95l9h.cloudfront.net/images/f91e09b5987802185e7679055dafd272.svg" class="icon"> <image src="https://d31zlh4on95l9h.cloudfront.net/images/f91e09b5987802185e7679055dafd272.svg" class="icon">
</image> </image>
</view> </view>
<view class="header-center">
<text class="title">DeepMate</text>
<view class="header-center"
>
<text class="title"
:style="{ paddingTop: safeAreaInsets?.top + 'px' }"
>DeepMate</text>
</view> </view>
<view class="header-right"> <view class="header-right">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/d7c4e74201213a25dd9574e908233928.svg" class="icon"> <image src="https://d31zlh4on95l9h.cloudfront.net/images/d7c4e74201213a25dd9574e908233928.svg" class="icon">
@ -194,6 +197,7 @@ import { ref, computed, onMounted, onUnmounted, watch, nextTick } from "vue";
import footerBar from '../../components/footerBar-cn' import footerBar from '../../components/footerBar-cn'
import marked from "marked"; // marked import marked from "marked"; // marked
import { onPageScroll } from '@dcloudio/uni-app' import { onPageScroll } from '@dcloudio/uni-app'
import {postStock,postIntent} from '../../api/deepMate/deepMate'
// marked // marked
marked.setOptions({ marked.setOptions({
renderer: new marked.Renderer(), renderer: new marked.Renderer(),
@ -420,9 +424,11 @@ const simulateBotResponse = async(userMessage) => {
// //
await new Promise((resolve) => setTimeout(resolve, 800));
// 使
const toDataInfo = { data: FAKE_MARKDOWN };
await new Promise((resolve) => setTimeout(resolve, 2000));
const toDataInfo = await getDataInfo();
console.log(toDataInfo);
// dataInfo.value = toDataInfo.data;
// console.log(dataInfo.value);
messages.value[messages.value.length - 1].isThinking = false; messages.value[messages.value.length - 1].isThinking = false;
@ -432,7 +438,7 @@ const simulateBotResponse = async(userMessage) => {
}); });
// //
let responseText = FAKE_MARKDOWN;
let responseText = `我已经收到您的消息: "${userMessage}"。+"${toDataInfo.data}" `;
let index = 0; let index = 0;
const botIndex = messages.value.length - 1; const botIndex = messages.value.length - 1;
@ -592,29 +598,6 @@ const onBackTopClick = () => {
}; };
function getDataInfo() {
return new Promise((resolve, reject) => {
uni.request({
url: "http://localhost:8888/ka",
data: {},
header: {
Accept: "application/json",
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
},
method: "GET",
sslVerify: true,
success: (res) => {
resolve(res.data);
},
fail: (error) => {
reject(error);
},
});
});
}
</script> </script>
<style scoped> <style scoped>
@ -954,7 +937,7 @@ function getDataInfo() {
.loading-dots { .loading-dots {
display: flex; display: flex;
align-items: center; align-items: center;
padding-top: 10rpx;
/* padding-top: 10rpx; */
} }
.dot { .dot {
@ -1210,9 +1193,9 @@ function getDataInfo() {
.history-time { margin-top: 8rpx; font-size: 22rpx; color: #888888; } .history-time { margin-top: 8rpx; font-size: 22rpx; color: #888888; }
.empty-history { padding: 40rpx; color: #999999; text-align: center; } .empty-history { padding: 40rpx; color: #999999; text-align: center; }
.thinking-process { .thinking-process {
margin: 20rpx 0;
margin: 10rpx 0;
border: 2rpx solid #e5e5e5; border: 2rpx solid #e5e5e5;
border-radius: 2rpx;
border-radius: 20rpx;
background-color: #f9f9f9; background-color: #f9f9f9;
} }
@ -1222,6 +1205,7 @@ function getDataInfo() {
padding: 20rpx 30rpx; padding: 20rpx 30rpx;
cursor: pointer; cursor: pointer;
background-color: #fff; background-color: #fff;
border-radius: 20rpx;
border-bottom: 2rpx solid #e5e5e5; border-bottom: 2rpx solid #e5e5e5;
} }

88
pages/start/login/login.vue

@ -119,7 +119,7 @@
class="input-field" class="input-field"
type="text" type="text"
placeholder="请输入验证码" placeholder="请输入验证码"
v-model="password"
v-model="verifyCode"
/> />
</view> </view>
</view> </view>
@ -165,7 +165,7 @@
class="input-field" class="input-field"
type="text" type="text"
placeholder="请输入验证码" placeholder="请输入验证码"
v-model="password"
v-model="verifyCode"
/> />
</view> </view>
</view> </view>
@ -242,6 +242,7 @@ import footerBar from "../../../components/footerBar-cn";
import uniPopupDialogVue from "../../../uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue"; import uniPopupDialogVue from "../../../uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue";
import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue"; import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";
import { verificationPhone, verificationEmail } from "../login/verification"; import { verificationPhone, verificationEmail } from "../login/verification";
import { LoginApi, SendCodeApi } from "../../../api/start/login";
const deepChartID = ref(""); const deepChartID = ref("");
const type = ref("member"); const type = ref("member");
@ -255,6 +256,8 @@ const { safeAreaInsets } = uni.getSystemInfoSync();
const codeBtnText = ref("获取验证码"); const codeBtnText = ref("获取验证码");
const isCodeBtnDisabled = ref(false); // const isCodeBtnDisabled = ref(false); //
const checkboxUrl = ref("../../../static/icons/Check-one-false.png"); const checkboxUrl = ref("../../../static/icons/Check-one-false.png");
const verifyCode = ref("");
const account = ref("");
// 使list.js // 使list.js
const countries = ref( const countries = ref(
@ -297,21 +300,24 @@ function switchUser() {
// //
switchType.value = "User"; switchType.value = "User";
password.value = ""; password.value = "";
verifyCode.value = "";
} }
function switchEmail() { function switchEmail() {
// //
switchType.value = "Email"; switchType.value = "Email";
password.value = ""; password.value = "";
verifyCode.value = "";
} }
function switchPhone() { function switchPhone() {
// //
switchType.value = "Phone"; switchType.value = "Phone";
password.value = ""; password.value = "";
verifyCode.value = "";
} }
function register() {
async function register() {
if (switchType.value === "User") { if (switchType.value === "User") {
if (!deepChartID.value) { if (!deepChartID.value) {
uni.showToast({ uni.showToast({
@ -340,7 +346,7 @@ function register() {
return; return;
} }
if (!password.value) {
if (!verifyCode.value) {
uni.showToast({ uni.showToast({
title: "请输入验证码", title: "请输入验证码",
icon: "none", icon: "none",
@ -349,8 +355,8 @@ function register() {
} }
const phoneAll = `${country.value}${phone.value}`; const phoneAll = `${country.value}${phone.value}`;
console.log("完整手机号" + phoneAll); console.log("完整手机号" + phoneAll);
if (validatePhoneNumber(country.value, phone.value)) {
console.log("登录成功:", phoneAll);
if (!validatePhoneNumber(country.value, phone.value)) {
return;
} }
// //
@ -367,7 +373,7 @@ function register() {
return; return;
} }
if (!password.value) {
if (!verifyCode.value) {
uni.showToast({ uni.showToast({
title: "请输入验证码", title: "请输入验证码",
icon: "none", icon: "none",
@ -386,9 +392,8 @@ function register() {
}); });
return; return;
} }
// //
console.log("登录:", email.value);
// console.log(":", email.value);
} }
if (!agreed.value) { if (!agreed.value) {
@ -402,6 +407,51 @@ function register() {
// title: "", // title: "",
// icon: "success", // icon: "success",
// }); // });
const account = changeAccount();
const res = await LoginApi({
loginType: switchType.value,
account: account,
verifyCode: verifyCode.value,
password: password.value,
useCode: verifyCode.value ? true : false,
idToken: "",
});
const message = res.message
if (res.code === 200) {
//
uni.showToast({
title: "登录成功",
icon: "success",
});
//
uni.switchTab({
url: "/pages/start/index/index",
});
} else {
//
uni.showToast({
title: message,
icon: "none",
});
}
}
function changeAccount() {
if (switchType.value === "User") {
account.value = deepChartID.value;
}
if (switchType.value === "Phone") {
account.value = `${country.value}${phone.value}`;
}
if (switchType.value === "Email") {
account.value = email.value;
}
return account.value;
} }
// //
@ -479,7 +529,7 @@ function onPhoneInput(e) {
} }
} }
function sendCode() {
async function sendCode() {
if (switchType.value === "Phone") { if (switchType.value === "Phone") {
if (!phone.value) { if (!phone.value) {
uni.showToast({ uni.showToast({
@ -526,6 +576,22 @@ function sendCode() {
// //
if (isCodeBtnDisabled.value) return; if (isCodeBtnDisabled.value) return;
//
const res = await SendCodeApi({
})
console.log("验证码:",res.message);
const message = res.message
if(res.code ===200){
uni.showToast({
title: message,
icon: "none",
});
}
// //
isCodeBtnDisabled.value = true; isCodeBtnDisabled.value = true;
codeBtnText.value = "重新发送"; codeBtnText.value = "重新发送";
@ -899,7 +965,7 @@ function validatePhoneNumber(countryCode, phoneNumber) {
margin-bottom: 40rpx; margin-bottom: 40rpx;
} }
.to-icon{
.to-icon {
width: 10rpx; width: 10rpx;
height: 16rpx; height: 16rpx;
} }

23
server/deepchart.json

@ -0,0 +1,23 @@
{
"intent":{
"code": 200,
"message": "操作成功",
"data": {
"code": "1A0001",
"market": "cn",
"name": "上证指数",
"refuse": "",
"recordId": 15,
"parentId": 14,
"stockId": 25,
"language": "cn",
"debug_url": "https://www.coze.cn/work_flow?execute_id=7564771475955515444&space_id=7564250621483040822&workflow_id=7564368306322292788&execute_mode=2"
}
},
"stocks":{"code":"200","cftl":"当前股票处于安全区,牵牛绳为红色,出现蓝色推进K线","date":"更新时间: 24/10/2025","debug_url":"https://www.coze.cn/work_flow?execute_id=7565080703726846004&space_id=7564250621483040822&workflow_id=7564596757864071195&execute_mode=2","gfzl":"该股整体趋势相对较强,个股正处于推进上涨的关键阶段。若当前持有该股票,建议继续持有,进行持续跟踪。若当前无该股票,建议持续跟踪,等待适当时机再进行介入。","hxjzpg":"(1)牛股评级:★★☆☆☆\n(2)暴涨概率:40%\n(3)风险评估:非常安全\n(4)黄金价域:258.984~266.753\n(5)核心证据链\n 资金共识:当日多方资金流入\n 趋势动能:该股中长期处于上升趋势,短期处于强势状态。","kongjian":"预测低一值255.468,预测高一值257.692,预测低二值255.156,预测高二值255.807",
"markdown":"\n# <font color=\"#1890ff\">Alphabet Inc.全景作战报告</font>\n## 📊 股票分析报告\n### 📈 股票基本信息\n- **股票名称**: <font color=\"#52c41a\">Alphabet Inc.</font>\n- **股票代码**: <font color=\"#1890ff\">GOOGL</font>\n- **当前价格**: <font color=\"#ff4d4f\">259.920</font>\n- **更新时间**: 2025年10月24日\n- **时间节点**: 今日无变盘点\n\n### 🎯 核心价值评估\n- **安全边际**: <font color=\"#13c2c2\">164.424 ~ </font>\n- **黄金价域**: <font color=\"#faad14\">258.984 ~ 266.753</font>\n- **核心证据链**:\n - 🟢 **资金共识**: 当日多方资金<font color=\"#52c41a\">流入</font>\n - 🔥 **趋势动能**: 该股中长期处于<b><font color='#FF0000'>上升趋势</font></b>,短期处于<b><font color='#FF0000'>强势状态</font></b>。\n\n### 🕵️ 主力作战分析\n- **主力行为**:\n 1. 📊 该股庄家中长期筹码成本价格为 207.497,短期资金成本价格为 239.503。该股筹码分散,当日筹码成本价格为 254.335。\n 2. 🔍 近日没有出现主力集中吸筹。\n 3. 📈 近期主力持仓比例大于散户持仓比例。 当日主力持仓增加。 当日散户持仓减少。\n\n### 📊 技术分析\n- **空间维度**:\n - 📉 预测低一值: <font color=\"#13c2c2\">255.468</font>\n - 📈 预测高一值: <font color=\"#ff4d4f\">257.692</font>\n - 📉 预测低二值: <font color=\"#13c2c2\">255.156</font>\n - 📈 预测高二值: <font color=\"#ff4d4f\">255.807</font>\n- **能量分析**: <font color=\"#722ed1\">AI智能均线多头排列,当前卖盘小于买盘</font>\n\n### ⚡ 综合作战分析\n- **触发条件**: <font color=\"#fa8c16\">当前股票处于安全区,牵牛绳为红色,出现蓝色推进K线</font>\n- **攻防指令**: <font color=\"#eb2f96\">该股整体趋势相对较强,个股正处于推进上涨的关键阶段。若当前持有该股票,建议继续持有,进行持续跟踪。若当前无该股票,建议持续跟踪,等待适当时机再进行介入。</font>\n\n---\n<font color=\"#8c8c8c\">*该内容由AI生成,仅供参考,投资有风险,请注意甄别。*</font>\n ","message":"","name":"股票名称: Alphabet Inc.(GOOGL)","nengliang":"AI智能均线多头排列,当前卖盘小于买盘","price":"当前价格: 259.920","shijian":"今日无变盘点","zhuli1":"(1)该股庄家中长期筹码成本价格为 207.497,短期资金成本价格为 239.503。该股筹码分散,当日筹码成本价格为 254.335。","zhuli2":"(2)近日没有出现主力集中吸筹。","zhuli3":"(3)近期主力持仓比例大于散户持仓比例。 当日主力持仓增加。 当日散户持仓减少。"}
}

131
server/login.json

@ -0,0 +1,131 @@
{
"loginSuccessByEmail": {
"code": 200,
"message": "登录成功",
"interface": "login",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"userInfo": {
"id": "123456789",
"username": "q614588746",
"email": "q614588746@163.com"
}
}
},
"loginFailureEmailNotFound": {
"code": 404,
"message": "账号不存在",
"interface": "login"
},
"loginFailureWrongCode": {
"code": 400,
"message": "验证码错误",
"interface": "login"
},
"loginSuccessByPhone": {
"code": 200,
"message": "登录成功",
"interface": "login",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"userInfo": {
"id": "987654321",
"username": "13800138000",
"phone": "13800138000"
}
}
},
"loginSuccessByPassword": {
"code": 200,
"message": "登录成功",
"interface": "login",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"userInfo": {
"id": "556677889",
"username": "testuser"
}
}
},
"sendCodeSuccess": {
"code": 200,
"message": "验证码发送成功",
"interface": "sendCode",
"data": {
"expireTime": 180
}
},
"sendCodeFailureInvalidFormat": {
"code": 400,
"message": "手机号格式错误",
"interface": "sendCode"
},
"sendCodeFailureTooFrequent": {
"code": 429,
"message": "发送频率过高,请稍后再试",
"interface": "sendCode"
},
"registerSuccess": {
"code": 200,
"message": "注册成功",
"interface": "register",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"userInfo": {
"id": "112233445",
"username": "newuser",
"email": "newuser@example.com"
}
}
},
"registerFailureEmailExist": {
"code": 400,
"message": "邮箱已被注册",
"interface": "register"
},
"registerFailurePhoneExist": {
"code": 400,
"message": "手机号已被注册",
"interface": "register"
},
"registerFailureWrongCode": {
"code": 400,
"message": "验证码错误",
"interface": "register"
},
"updatePasswordSuccess": {
"code": 200,
"message": "密码修改成功",
"interface": "updatePassword"
},
"updatePasswordFailureWrongOldPassword": {
"code": 400,
"message": "旧密码错误",
"interface": "updatePassword"
},
"updatePasswordFailureWrongCode": {
"code": 400,
"message": "验证码错误",
"interface": "updatePassword"
},
"forgotPasswordSuccessByEmail": {
"code": 200,
"message": "密码重置成功,新密码已发送至邮箱",
"interface": "forgotPassword"
},
"forgotPasswordSuccessByPhone": {
"code": 200,
"message": "密码重置成功,新密码已发送至手机",
"interface": "forgotPassword"
},
"forgotPasswordFailureAccountNotFound": {
"code": 404,
"message": "账号不存在",
"interface": "forgotPassword"
},
"forgotPasswordFailureWrongCode": {
"code": 400,
"message": "验证码错误",
"interface": "forgotPassword"
}
}

12
stores/index.js

@ -0,0 +1,12 @@
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'
// 创建 pinia 实例
const pinia = createPinia()
// 使用持久化存储插件
pinia.use(persist)
// 导入所有模块
export * from './modules/userInfo'
// 默认导出,给 main.js 使用
export default pinia

44
stores/modules/userInfo.js

@ -0,0 +1,44 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
// 定义 Store
export const useMemberStore = defineStore(
'member',
() => {
// 会员信息
const userInfo = ref()
// 保存会员信息,登录时使用
const setUserInfo = (val) => {
userInfo.value = val
}
// 清理会员信息,退出时使用
const clearUserInfo = () => {
userInfo.value = undefined
}
// 记得 return
return {
userInfo,
setUserInfo,
clearUserInfo,
}
},
// TODO: 持久化
{
// 网页端持久化
// persist: true,
// 小程序端持久化
persist: {
storage: {
getItem(key) {
return uni.getStorageSync(key)
},
setItem(key, value) {
uni.setStorageSync(key, value)
},
},
},
},
)

69
utils/http.js

@ -0,0 +1,69 @@
import { useMemberStore } from '@/stores'
const baseURL = "http://localhost:8888"
const httpInterceptor = {
// 拦截前触发
invoke(options) {
// 1.非http
if (!options.url.startsWith('http')) {
options.url = baseURL + options.url
}
// 2.请求超时,默认60s
options.timeout = 60000
console.log(options)
//3 添加小程序端请求头
options.header = {
...options.header,
'source-client': 'miniapp'
}
//4 添加token
const memberStore = useMemberStore()
const token = memberStore.profile?.token
if (token) {
options.header.Authorization = token
}
return options
}
}
// 添加拦截器
uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)
// 添加请求函数
export const http = (options) => {
return new Promise((resolve, reject) => {
uni.request({
...options,
// 1.请求成功
success: (result) => {
if (result.statusCode >= 200 && result.statusCode < 300) {
resolve(result.data)
} else if (result.statusCode === 401) {
// 清除登录信息
const memberStore = useMemberStore()
memberStore.clearProfile()
// 提示用户重新登录
uni.navigateTo({
url: '/pages/login/login'
})
reject(result)
} else {
uni.showToast({
title: (result.data).msg || '请求失败',
icon: 'none'
})
reject(result)
}
},
// 2.请求失败
fail: (err) => {
reject(err)
uni.showToast({
title: '网络错误',
icon: 'none'
})
}
})
})
}
Loading…
Cancel
Save