This commit is contained in:
那些花儿
2025-04-30 13:34:37 +08:00
parent ad9a7bc7b8
commit baa6f7284a
12 changed files with 567 additions and 284 deletions
@@ -15,6 +15,8 @@ import com.budwk.app.web.commons.slog.SLogService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao; import org.nutz.dao.Dao;
import org.nutz.integration.jedis.RedisService; import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.Inject;
@@ -89,7 +91,7 @@ public class ClientAuthController {
} }
} }
@At("/info") @At(value = {"/info", "/user-info"})
@Ok("json") @Ok("json")
@SaCheckLogin(type = StpClientUtil.TYPE) @SaCheckLogin(type = StpClientUtil.TYPE)
public Result info() { public Result info() {
@@ -97,6 +99,17 @@ public class ClientAuthController {
return Result.success(user); return Result.success(user);
} }
@At("/update-user-info")
@Ok("json")
@SaCheckLogin(type = StpClientUtil.TYPE)
@ApiOperation(value = "修改用户信息", nickname = "/update-user-info", httpMethod = "POST")
@AdaptBy(type = JsonAdaptor.class)
public Result updateUserInfo(Client_user user) {
user.setId(StpClientUtil.STP.getLoginIdAsLong());
user.setAvatar("https://tdesign.gtimg.com/mobile/demos/avatar1.png");
dao.updateIgnoreNull(user);
return Result.success(user);
}
/** /**
* 退出登录 * 退出登录
@@ -38,6 +38,11 @@ public class Client_user extends BaseModel implements Serializable {
@Comment("身份证") @Comment("身份证")
private String idCard; private String idCard;
@Column
@ColDefine(type = ColType.VARCHAR, width = 255)
@Comment("头像")
private String avatar;
@Column @Column
@ColDefine(type = ColType.VARCHAR, width = 255) @ColDefine(type = ColType.VARCHAR, width = 255)
@Comment("openId") @Comment("openId")
+136
View File
@@ -26,6 +26,7 @@
"@dcloudio/uni-quickapp-webview": "3.0.0-4050720250324001", "@dcloudio/uni-quickapp-webview": "3.0.0-4050720250324001",
"html5-qrcode": "^2.3.8", "html5-qrcode": "^2.3.8",
"moment": "^2.30.1", "moment": "^2.30.1",
"pinia": "^3.0.2",
"tdesign-mobile-vue": "^1.8.3", "tdesign-mobile-vue": "^1.8.3",
"vue": "^3.4.21", "vue": "^3.4.21",
"vue-i18n": "^9.1.9" "vue-i18n": "^9.1.9"
@@ -4609,6 +4610,30 @@
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@vue/devtools-kit": {
"version": "7.7.6",
"resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.6.tgz",
"integrity": "sha512-geu7ds7tem2Y7Wz+WgbnbZ6T5eadOvozHZ23Atk/8tksHMFOFylKi1xgGlQlVn0wlkEf4hu+vd5ctj1G4kFtwA==",
"license": "MIT",
"dependencies": {
"@vue/devtools-shared": "^7.7.6",
"birpc": "^2.3.0",
"hookable": "^5.5.3",
"mitt": "^3.0.1",
"perfect-debounce": "^1.0.0",
"speakingurl": "^14.0.1",
"superjson": "^2.2.2"
}
},
"node_modules/@vue/devtools-shared": {
"version": "7.7.6",
"resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.6.tgz",
"integrity": "sha512-yFEgJZ/WblEsojQQceuyK6FzpFDx4kqrz2ohInxNj5/DnhoX023upTv4OD6lNPLAA5LLkbwPVb10o/7b+Y4FVA==",
"license": "MIT",
"dependencies": {
"rfdc": "^1.4.1"
}
},
"node_modules/@vue/reactivity": { "node_modules/@vue/reactivity": {
"version": "3.5.13", "version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz", "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz",
@@ -5219,6 +5244,15 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/birpc": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.3.0.tgz",
"integrity": "sha512-ijbtkn/F3Pvzb6jHypHRyve2QApOCZDR25D/VnkY2G/lBNcXCTsnsCxgY4k4PkVB7zfwzYbY3O9Lcqe3xufS5g==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/bmp-js": { "node_modules/bmp-js": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmmirror.com/bmp-js/-/bmp-js-0.1.0.tgz", "resolved": "https://registry.npmmirror.com/bmp-js/-/bmp-js-0.1.0.tgz",
@@ -6931,6 +6965,12 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
"license": "MIT"
},
"node_modules/html-encoding-sniffer": { "node_modules/html-encoding-sniffer": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", "resolved": "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
@@ -8751,6 +8791,12 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
"license": "MIT"
},
"node_modules/mkdirp": { "node_modules/mkdirp": {
"version": "0.5.6", "version": "0.5.6",
"resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz",
@@ -9185,6 +9231,12 @@
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/perfect-debounce": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
"license": "MIT"
},
"node_modules/phin": { "node_modules/phin": {
"version": "2.9.3", "version": "2.9.3",
"resolved": "https://registry.npmmirror.com/phin/-/phin-2.9.3.tgz", "resolved": "https://registry.npmmirror.com/phin/-/phin-2.9.3.tgz",
@@ -9219,6 +9271,36 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/pinia": {
"version": "3.0.2",
"resolved": "https://registry.npmmirror.com/pinia/-/pinia-3.0.2.tgz",
"integrity": "sha512-sH2JK3wNY809JOeiiURUR0wehJ9/gd9qFN2Y828jCbxEzKEmEt0pzCXwqiSTfuRsK9vQsOflSdnbdBOGrhtn+g==",
"license": "MIT",
"dependencies": {
"@vue/devtools-api": "^7.7.2"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"typescript": ">=4.4.4",
"vue": "^2.7.0 || ^3.5.11"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/pinia/node_modules/@vue/devtools-api": {
"version": "7.7.6",
"resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.7.6.tgz",
"integrity": "sha512-b2Xx0KvXZObePpXPYHvBRRJLDQn5nhKjXh7vUhMEtWxz1AYNFOVIsh5+HLP8xDGL7sy+Q7hXeUxPHB/KgbtsPw==",
"license": "MIT",
"dependencies": {
"@vue/devtools-kit": "^7.7.6"
}
},
"node_modules/pirates": { "node_modules/pirates": {
"version": "4.0.7", "version": "4.0.7",
"resolved": "https://registry.npmmirror.com/pirates/-/pirates-4.0.7.tgz", "resolved": "https://registry.npmmirror.com/pirates/-/pirates-4.0.7.tgz",
@@ -9886,6 +9968,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/rfdc": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
"license": "MIT"
},
"node_modules/rimraf": { "node_modules/rimraf": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz",
@@ -10277,6 +10365,15 @@
"source-map": "^0.6.0" "source-map": "^0.6.0"
} }
}, },
"node_modules/speakingurl": {
"version": "14.0.1",
"resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
"integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sprintf-js": { "node_modules/sprintf-js": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -10413,6 +10510,45 @@
"integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/superjson": {
"version": "2.2.2",
"resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.2.tgz",
"integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
"license": "MIT",
"dependencies": {
"copy-anything": "^3.0.2"
},
"engines": {
"node": ">=16"
}
},
"node_modules/superjson/node_modules/copy-anything": {
"version": "3.0.5",
"resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
"integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
"license": "MIT",
"dependencies": {
"is-what": "^4.1.8"
},
"engines": {
"node": ">=12.13"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/superjson/node_modules/is-what": {
"version": "4.1.16",
"resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz",
"integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
"license": "MIT",
"engines": {
"node": ">=12.13"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
+1
View File
@@ -54,6 +54,7 @@
"@dcloudio/uni-quickapp-webview": "3.0.0-4050720250324001", "@dcloudio/uni-quickapp-webview": "3.0.0-4050720250324001",
"html5-qrcode": "^2.3.8", "html5-qrcode": "^2.3.8",
"moment": "^2.30.1", "moment": "^2.30.1",
"pinia": "^3.0.2",
"tdesign-mobile-vue": "^1.8.3", "tdesign-mobile-vue": "^1.8.3",
"vue": "^3.4.21", "vue": "^3.4.21",
"vue-i18n": "^9.1.9" "vue-i18n": "^9.1.9"
+1 -2
View File
@@ -5,9 +5,8 @@ export default {
globalData: { globalData: {
user: null user: null
}, },
onLaunch: function () { onLaunch: async function () {
console.log('App Launch') console.log('App Launch')
console.log(process.env.VUE_APP_PLATFORM)
// 检查访问页面是否需要登录(不走拦截器 直接从地址栏进入) // 检查访问页面是否需要登录(不走拦截器 直接从地址栏进入)
checkAuth() checkAuth()
// 初始化路由拦截器 // 初始化路由拦截器
+9 -1
View File
@@ -1,4 +1,5 @@
import {createSSRApp} from "vue"; import {createSSRApp} from "vue";
import * as Pinia from 'pinia';
import App from "./App.vue"; import App from "./App.vue";
// 引入TDesign组件库 // 引入TDesign组件库
@@ -14,10 +15,17 @@ import 'moment/dist/locale/zh-cn'
moment.locale('zh-cn') moment.locale('zh-cn')
uni.$on('beforeRouterEnter', async (to, from, next) => {
console.log('beforeRouterEnter', to, from)
})
export function createApp() { export function createApp() {
const app = createSSRApp(App); const app = createSSRApp(App);
app.use(TDesign); // 使用TDesign组件库 app.use(TDesign);
app.use(Pinia.createPinia())
return { return {
app, app,
Pinia
}; };
} }
+1 -2
View File
@@ -152,11 +152,10 @@ const getListData = async (isRefresh = false) => {
hasMore.value = dataList.value.length < totalCount; hasMore.value = dataList.value.length < totalCount;
pageForm.pageNumber++; pageForm.pageNumber++;
} else { } else {
Toast({message: '获取活动列表失败', theme: 'error'}); Toast({message: response.msg, theme: 'error'});
} }
} catch (error) { } catch (error) {
console.error('获取活动列表失败', error); console.error('获取活动列表失败', error);
Toast({message: '获取活动列表失败', theme: 'error'});
} finally { } finally {
loading.value = false; loading.value = false;
+63 -45
View File
@@ -3,13 +3,15 @@
<view class="title-area"> <view class="title-area">
<div class="tech-animation"> <div class="tech-animation">
<svg preserveAspectRatio="xMidYMid slice" viewBox="0 0 300 100"> <svg preserveAspectRatio="xMidYMid slice" viewBox="0 0 300 100">
<pattern id="pattern-hex" x="0" y="0" width="10" height="10" patternUnits="userSpaceOnUse" patternTransform="scale(0.8)"> <pattern id="pattern-hex" x="0" y="0" width="10" height="10" patternUnits="userSpaceOnUse"
patternTransform="scale(0.8)">
<rect x="0" y="0" width="10" height="10" fill="none"/> <rect x="0" y="0" width="10" height="10" fill="none"/>
<path d="M0,5 L2.5,0 L7.5,0 L10,5 L7.5,10 L2.5,10 Z" stroke-width="0.5" stroke="rgba(244, 90, 90, 0.2)" fill="rgba(244, 90, 90, 0.1)"> <path d="M0,5 L2.5,0 L7.5,0 L10,5 L7.5,10 L2.5,10 Z" stroke-width="0.5" stroke="rgba(244, 90, 90, 0.2)"
<animate attributeName="stroke-opacity" values="0.1;0.3;0.1" dur="3s" repeatCount="indefinite" /> fill="rgba(244, 90, 90, 0.1)">
<animate attributeName="stroke-opacity" values="0.1;0.3;0.1" dur="3s" repeatCount="indefinite"/>
</path> </path>
</pattern> </pattern>
<rect x="0" y="0" width="100%" height="100%" fill="url(#pattern-hex)" /> <rect x="0" y="0" width="100%" height="100%" fill="url(#pattern-hex)"/>
<g fill="none" stroke-width="0.5"> <g fill="none" stroke-width="0.5">
<path d="M20,50 Q60,20 100,50 T180,50 T260,50" stroke="rgba(244, 90, 90, 0.6)"> <path d="M20,50 Q60,20 100,50 T180,50 T260,50" stroke="rgba(244, 90, 90, 0.6)">
@@ -17,7 +19,7 @@
values="M20,50 Q60,20 100,50 T180,50 T260,50; values="M20,50 Q60,20 100,50 T180,50 T260,50;
M20,50 Q60,80 100,50 T180,50 T260,50; M20,50 Q60,80 100,50 T180,50 T260,50;
M20,50 Q60,20 100,50 T180,50 T260,50" M20,50 Q60,20 100,50 T180,50 T260,50"
dur="10s" repeatCount="indefinite" /> dur="10s" repeatCount="indefinite"/>
</path> </path>
<path d="M20,70 Q60,40 100,70 T180,70 T260,70" stroke="rgba(244, 90, 90, 0.4)"> <path d="M20,70 Q60,40 100,70 T180,70 T260,70" stroke="rgba(244, 90, 90, 0.4)">
@@ -25,26 +27,26 @@
values="M20,70 Q60,40 100,70 T180,70 T260,70; values="M20,70 Q60,40 100,70 T180,70 T260,70;
M20,70 Q60,100 100,70 T180,70 T260,70; M20,70 Q60,100 100,70 T180,70 T260,70;
M20,70 Q60,40 100,70 T180,70 T260,70" M20,70 Q60,40 100,70 T180,70 T260,70"
dur="12s" repeatCount="indefinite" /> dur="12s" repeatCount="indefinite"/>
</path> </path>
</g> </g>
<circle cx="50" cy="50" r="1" fill="rgba(244, 90, 90, 0.8)"> <circle cx="50" cy="50" r="1" fill="rgba(244, 90, 90, 0.8)">
<animate attributeName="cx" values="50;250;50" dur="20s" repeatCount="indefinite" /> <animate attributeName="cx" values="50;250;50" dur="20s" repeatCount="indefinite"/>
<animate attributeName="cy" values="50;30;80;50" dur="16s" repeatCount="indefinite" /> <animate attributeName="cy" values="50;30;80;50" dur="16s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;1.5;1" dur="5s" repeatCount="indefinite" /> <animate attributeName="r" values="1;1.5;1" dur="5s" repeatCount="indefinite"/>
</circle> </circle>
<circle cx="150" cy="30" r="1" fill="rgba(244, 90, 90, 0.8)"> <circle cx="150" cy="30" r="1" fill="rgba(244, 90, 90, 0.8)">
<animate attributeName="cx" values="150;100;200;150" dur="25s" repeatCount="indefinite" /> <animate attributeName="cx" values="150;100;200;150" dur="25s" repeatCount="indefinite"/>
<animate attributeName="cy" values="30;60;20;30" dur="18s" repeatCount="indefinite" /> <animate attributeName="cy" values="30;60;20;30" dur="18s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;1.8;1" dur="6s" repeatCount="indefinite" /> <animate attributeName="r" values="1;1.8;1" dur="6s" repeatCount="indefinite"/>
</circle> </circle>
<circle cx="250" cy="70" r="1" fill="rgba(244, 90, 90, 0.8)"> <circle cx="250" cy="70" r="1" fill="rgba(244, 90, 90, 0.8)">
<animate attributeName="cx" values="250;150;250" dur="22s" repeatCount="indefinite" /> <animate attributeName="cx" values="250;150;250" dur="22s" repeatCount="indefinite"/>
<animate attributeName="cy" values="70;40;70" dur="15s" repeatCount="indefinite" /> <animate attributeName="cy" values="70;40;70" dur="15s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;1.2;1" dur="4s" repeatCount="indefinite" /> <animate attributeName="r" values="1;1.2;1" dur="4s" repeatCount="indefinite"/>
</circle> </circle>
</svg> </svg>
</div> </div>
@@ -77,7 +79,7 @@
<view class="form-container"> <view class="form-container">
<!-- 手机号码输入框 --> <!-- 手机号码输入框 -->
<view class="input-box"> <view class="input-box">
<t-icon name="mobile" size="20px" class="input-icon" /> <t-icon name="mobile" size="20px" class="input-icon"/>
<input <input
class="input" class="input"
type="tel" type="tel"
@@ -89,7 +91,7 @@
<!-- 验证码输入框 --> <!-- 验证码输入框 -->
<view class="input-box"> <view class="input-box">
<t-icon name="shield-error" size="20px" class="input-icon" /> <t-icon name="shield-error" size="20px" class="input-icon"/>
<input <input
class="input" class="input"
type="number" type="number"
@@ -107,11 +109,11 @@
立即登录 立即登录
</view> </view>
<!-- &lt;!&ndash; 注册链接 &ndash;&gt;--> <!-- &lt;!&ndash; 注册链接 &ndash;&gt;-->
<!-- <view class="register-link">--> <!-- <view class="register-link">-->
<!-- <text>没有账号?</text>--> <!-- <text>没有账号?</text>-->
<!-- <text class="link">去注册</text>--> <!-- <text class="link">去注册</text>-->
<!-- </view>--> <!-- </view>-->
</view> </view>
</view> </view>
</view> </view>
@@ -121,8 +123,10 @@
import {ref, reactive, computed, onMounted, onBeforeUnmount} from 'vue' import {ref, reactive, computed, onMounted, onBeforeUnmount} from 'vue'
import {Toast} from 'tdesign-mobile-vue'; import {Toast} from 'tdesign-mobile-vue';
import {useRequest} from "@/utils/request"; import {useRequest} from "@/utils/request";
import {useUserStore} from "@/store";
const request = useRequest() const request = useRequest()
const userStore = useUserStore()
const activeMethod = ref('phone') const activeMethod = ref('phone')
const loginForm = reactive({ const loginForm = reactive({
@@ -267,33 +271,47 @@ async function handleLogin() {
} }
try { try {
const {data, code, msg} = await request.post('/client/auth/sms-login', loginForm) userStore.smsLogin(loginForm).then(() => {
if (code === 0) { userStore.getUserInfo().then(() => {
Toast({message: '登录成功', theme: 'success'}) Toast({message: '登录成功', theme: 'success'})
// 保存token
uni.setStorageSync('token', data)
// 获取之前保存的重定向URL
const redirectUrl = uni.getStorageSync('REDIRECT_URL') || '/pages/index/index'
uni.removeStorageSync('REDIRECT_URL') // 使用后删除
// 延迟跳转,让用户看到成功提示
setTimeout(() => {
if (redirectUrl.startsWith('/pages/index/') || redirectUrl.startsWith('/pages/profile/')) {
// 主页和个人中心,使用switchTab
uni.switchTab({ uni.switchTab({
url: redirectUrl url: '/pages/index/index'
}) })
} else { }).catch(e => {
// 其他页面使用reLaunch Toast({message: e.message, theme: 'error'})
uni.reLaunch({
url: redirectUrl
}) })
} }).catch(e => {
}, 1000) console.log(e)
} else { Toast({message: e.message, theme: 'error'})
Toast({message: msg, theme: 'error'}) })
}
// const {data, code, msg} = await request.post('/client/auth/sms-login', loginForm)
// if (code === 0) {
// Toast({message: '登录成功', theme: 'success'})
// // 保存token
// uni.setStorageSync('token', data)
//
// // 获取之前保存的重定向URL
// const redirectUrl = uni.getStorageSync('REDIRECT_URL') || '/pages/index/index'
// uni.removeStorageSync('REDIRECT_URL') // 使用后删除
//
// // 延迟跳转,让用户看到成功提示
// setTimeout(() => {
// if (redirectUrl.startsWith('/pages/index/') || redirectUrl.startsWith('/pages/profile/')) {
// // 主页和个人中心,使用switchTab
// uni.switchTab({
// url: redirectUrl
// })
// } else {
// // 其他页面使用reLaunch
// uni.reLaunch({
// url: redirectUrl
// })
// }
// }, 1000)
// } else {
// Toast({message: msg, theme: 'error'})
// }
} catch (e) { } catch (e) {
console.error(e) console.error(e)
Toast({message: e.message, theme: 'error'}) Toast({message: e.message, theme: 'error'})
+48 -43
View File
@@ -1,21 +1,16 @@
<script setup> <script setup>
import {ref, onMounted} from 'vue'; import {ref, onMounted, computed} from 'vue';
import {Toast, Dialog} from 'tdesign-mobile-vue'; import {Toast, Dialog} from 'tdesign-mobile-vue';
import {useRequest} from "@/utils/request"; import {useRequest} from "@/utils/request";
import {useUserStore} from "@/store";
// 用户资料数据 const userStore = useUserStore()
const userInfo = ref({
id: '--',
name: '--',
avatar: '/static/avatar.png',
phone: '--',
company: '--'
});
// 我的活动数据 // 用户信息
const activities = ref({ const userInfo = computed(() => {
enrolled: 6 return userStore.userInfo
}); })
console.log('userInfo', userInfo)
// 退出登录 // 退出登录
const handleLogout = () => { const handleLogout = () => {
@@ -25,18 +20,11 @@ const handleLogout = () => {
confirmBtn: '确定', confirmBtn: '确定',
cancelBtn: '取消', cancelBtn: '取消',
onConfirm: () => { onConfirm: () => {
useRequest().post('/client/auth/logout').then(res=>{ userStore.logout().then(() => {
if(res.code===0){
uni.clearStorageSync()
Toast({message: '退出登录成功', theme: 'success'}); Toast({message: '退出登录成功', theme: 'success'});
setTimeout(() => {
uni.reLaunch({ uni.reLaunch({
url: '/pages/login/index' url: '/pages/login/index'
}); });
}, 1000);
}else{
Toast({message: '退出登录失败', theme: 'error'});
}
}) })
} }
}); });
@@ -47,22 +35,41 @@ const navigateTo = (path) => {
uni.navigateTo({url: path}); uni.navigateTo({url: path});
}; };
// 处理编辑资料 // 选择头像
const handleEditProfile = () => { function changeAvatar() {
navigateTo('/pages/profile/edit/index'); uni.chooseImage({
}; count: 1,
sizeType: ['original', 'compressed'],
onMounted(() => { success: async (res) => {
// 获取用户信息 try {
console.log('个人资料页面已加载'); const {code, data, msg} = await useRequest().upload(res.tempFiles[0])
userInfo.value={ if (code === 0) {
id: getApp().globalData.user.id, updateAvatar(data)
name: getApp().globalData.user.userName, } else {
avatar: '/static/avatar.png', Toast({message: msg, theme: 'error'});
phone: getApp().globalData.user.phone,
company: getApp().globalData.user.unitName
} }
}); } catch (e) {
Toast({message: e, theme: 'error'});
}
}
})
}
// 修改头像
async function updateAvatar(avatar) {
try {
await userStore.updateUserInfo({
...userStore.userInfo,
avatar: avatar
})
Toast({message: '修改头像成功', theme: 'success'});
} catch (e) {
Toast({message: e, theme: 'error'});
}
}
</script> </script>
<template> <template>
@@ -74,14 +81,14 @@ onMounted(() => {
<view class="user-profile-section"> <view class="user-profile-section">
<view class="user-info-container"> <view class="user-info-container">
<view class="avatar-wrapper"> <view class="avatar-wrapper">
<t-avatar :image="userInfo.avatar" size="large"/> <t-avatar :image="userInfo.avatar" size="large" @click="changeAvatar"/>
</view> </view>
<view class="user-info"> <view class="user-info">
<view class="user-name-row"> <view class="user-name-row">
<text class="user-name">{{ userInfo.name }}</text> <text class="user-name">{{ userInfo.userName }}</text>
<view class="edit-profile" @click="handleEditProfile"> <!-- <view class="edit-profile" @click="handleEditProfile">-->
<t-icon name="edit" size="20"/> <!-- <t-icon name="edit" size="20"/>-->
</view> <!-- </view>-->
</view> </view>
<view class="user-company">{{ userInfo.phone }}</view> <view class="user-company">{{ userInfo.phone }}</view>
</view> </view>
@@ -115,12 +122,10 @@ onMounted(() => {
</t-cell-group> </t-cell-group>
</view> </view>
<!-- 退出登录按钮 -->
<view class="logout-btn"> <view class="logout-btn">
<t-button theme="danger" size="large" block @click="handleLogout">退出登录</t-button> <t-button theme="danger" size="large" block @click="handleLogout">退出登录</t-button>
</view> </view>
<!-- 底部版权信息 -->
<view class="footer"> <view class="footer">
<t-divider>活动报名系统 v1.0.0</t-divider> <t-divider>活动报名系统 v1.0.0</t-divider>
</view> </view>
+86
View File
@@ -0,0 +1,86 @@
import {defineStore} from "pinia";
import {useRequest} from "@/utils/request";
const request = useRequest()
export const useUserStore = defineStore("user", {
state: () => ({
userInfo: uni.getStorageSync('userInfo') || null,
token: uni.getStorageSync('token')
}),
actions: {
setToken(token) {
this.token = token
uni.setStorageSync('token', token)
},
setUserInfo(userInfo) {
this.userInfo = userInfo
uni.setStorageSync('userInfo', userInfo)
},
setUserInfoKV(key, value) {
this.userInfo[key] = value
},
async smsLogin(loginForm) {
try {
const {data, code, msg} = await request.post('/client/auth/sms-login', loginForm)
if (code === 0) {
this.setToken(data)
} else {
throw new Error(msg)
}
} catch (e) {
console.log(e)
throw e
}
},
async getUserInfo() {
try {
const {data, code, msg} = await request.get('/client/auth/user-info')
if (code === 0) {
this.setUserInfo(data)
} else {
throw new Error(msg)
}
} catch (e) {
console.log(e)
throw e
}
},
async updateUserInfo(userInfo) {
try {
const {data, code, msg} = await request.post('/client/auth/update-user-info', userInfo)
if (code === 0) {
this.setUserInfo(data)
} else {
throw new Error(msg)
}
} catch (e) {
console.log(e)
throw e
}
},
async logout() {
try {
const {code, msg} = await request.post('/client/auth/logout')
if (code === 0) {
this.setToken(null)
this.setUserInfo(null)
await uni.reLaunch({
url: '/pages/login/index'
});
} else {
throw new Error(msg)
}
} catch (e) {
console.log(e)
throw e
}
}
}
})
+29 -5
View File
@@ -1,4 +1,4 @@
import { reactive } from "vue"; import {reactive} from "vue";
/** /**
* 全局请求状态管理 * 全局请求状态管理
@@ -54,7 +54,7 @@ function handleUnauthorized() {
}); });
setTimeout(() => { setTimeout(() => {
uni.navigateTo({ url: "/pages/login/index" }); uni.navigateTo({url: "/pages/login/index"});
}, 2000); }, 2000);
} }
@@ -97,14 +97,14 @@ export function useRequest(options = {}) {
uni.request({ uni.request({
...mergedConfig, ...mergedConfig,
success: (response) => { success: (response) => {
const { statusCode, data } = response; const {statusCode, data} = response;
// HTTP状态码成功 // HTTP状态码成功
if (statusCode >= 200 && statusCode < 300) { if (statusCode >= 200 && statusCode < 300) {
if (data.code === 600098) { if (data.code === 600098) {
handleUnauthorized(); handleUnauthorized();
reject(data); reject(data);
}else{ } else {
resolve(data); resolve(data);
} }
// // 业务逻辑成功 // // 业务逻辑成功
@@ -188,13 +188,37 @@ export function useRequest(options = {}) {
}); });
}; };
/**
* 上传文件
*/
const upload = (file) => {
return new Promise((resolve, reject) => {
uni.uploadFile({
url: '/api/open/file/upload/image',
file: file,
name: 'file',
success: (res) => {
if (res.statusCode === 200) {
resolve(JSON.parse(res.data))
} else {
reject(res)
}
},
fail: (err) => {
reject(err)
}
})
})
}
// 返回所有HTTP方法 // 返回所有HTTP方法
return { return {
request, request,
get, get,
post, post,
put, put,
delete: del delete: del,
upload
}; };
} }
+9 -20
View File
@@ -1,5 +1,6 @@
import {Dialog} from "tdesign-mobile-vue"; import {Dialog} from "tdesign-mobile-vue";
import {useRequest} from "@/utils/request"; import {useRequest} from "@/utils/request";
import {useUserStore} from "@/store";
/** /**
* 路由拦截器配置 * 路由拦截器配置
@@ -10,24 +11,15 @@ export const setupRouterInterceptor = (whiteList = []) => {
addNavigationInterceptors(whiteList) addNavigationInterceptors(whiteList)
} }
export const checkAuth = () => { export const checkAuth = async () => {
debugger
if (process.env.VUE_APP_PLATFORM === 'h5' && window.location.pathname !== '/') { if (process.env.VUE_APP_PLATFORM === 'h5' && window.location.pathname !== '/') {
const path = window.location.pathname.replace(/^\//, '') const path = window.location.pathname.replace(/^\//, '')
if (!getDefaultWhiteList().includes(path)) { if (!getDefaultWhiteList().includes(path)) {
const token = uni.getStorageSync('token') const token = uni.getStorageSync('token')
if(token){ if (token) {
// 获取用户信息 await useUserStore().getUserInfo()
const {user} = getApp().globalData } else {
if(user == null){ await uni.redirectTo({
return useRequest().get('/client/auth/info').then(({code, data, msg}) => {
if(code === 0){
getApp().globalData.user = data
}
})
}
}else{
uni.redirectTo({
url: '/pages/login/index' url: '/pages/login/index'
}) })
} }
@@ -84,17 +76,14 @@ async function routeInterceptor(args, whiteList) {
} }
console.log('路由拦截检查:', {url: targetUrl, isInWhiteList, hasToken: !!token}) console.log('路由拦截检查:', {url: targetUrl, isInWhiteList, hasToken: !!token})
// 如果不在白名单且未登录,则跳转到登录页 // 如果不在白名单且未登录,则跳转到登录页
if (!isInWhiteList) { if (!isInWhiteList) {
if (token) { if (token) {
// 获取用户信息 // 获取用户信息
const {user} = getApp().globalData const user = useUserStore().userInfo
if (user == null) { if (user == null) {
const {code, data, msg} = await useRequest().get('/client/auth/info') await userStore().getUserInfo()
if (code === 0) {
getApp().globalData.user = data
return args
}
} }
return args return args
} else { } else {