This commit is contained in:
那些花儿
2025-05-06 20:15:51 +08:00
parent 178da5f9df
commit c21ba7b426
13 changed files with 120 additions and 137 deletions
@@ -47,6 +47,9 @@ public class ClientActivityServiceImpl extends BaseServiceImpl<Activity> impleme
public void signUp(ClientActivitySignVO signVO) { public void signUp(ClientActivitySignVO signVO) {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
Client_user selfUser = dao().fetch(Client_user.class, StpClientUtil.STP.getLoginIdAsLong());
dao().fetchLinks(selfUser, "unit");
List<ActUser> userList = signVO.getUserList(); List<ActUser> userList = signVO.getUserList();
// 首先检查报名人员是否已经在用户表中 // 首先检查报名人员是否已经在用户表中
for (ActUser user : userList) { for (ActUser user : userList) {
@@ -58,6 +61,7 @@ public class ClientActivityServiceImpl extends BaseServiceImpl<Activity> impleme
clientUser.setSex(user.getSex()); clientUser.setSex(user.getSex());
clientUser.setPhone(user.getPhone()); clientUser.setPhone(user.getPhone());
clientUser.setIdCard(user.getIdCard()); clientUser.setIdCard(user.getIdCard());
clientUser.setUnitId(selfUser.getUnitId());
dao().insert(clientUser); dao().insert(clientUser);
} else { } else {
// 验证用户之前是不是已经报名 别人帮报 自己报 管理员报 // 验证用户之前是不是已经报名 别人帮报 自己报 管理员报
@@ -71,6 +75,7 @@ public class ClientActivityServiceImpl extends BaseServiceImpl<Activity> impleme
user.setActivityId(signVO.getActivityId()); user.setActivityId(signVO.getActivityId());
user.setUserId(clientUser.getId()); user.setUserId(clientUser.getId());
user.setUnitId(selfUser.getUnitId());
user.setUnitName(signVO.getUnitName()); user.setUnitName(signVO.getUnitName());
user.setSignUpContacts(signVO.getContactName()); user.setSignUpContacts(signVO.getContactName());
user.setSignUpMobile(signVO.getContactPhone()); user.setSignUpMobile(signVO.getContactPhone());
@@ -12,6 +12,7 @@ import java.util.List;
public class ClientActivitySignVO { public class ClientActivitySignVO {
private Long activityId; private Long activityId;
private Long itemId; private Long itemId;
private String unitId; private String unitId;
@@ -40,13 +40,13 @@ const actQrCode = {
width: 150, width: 150,
height: 150 height: 150
}) })
signUpCode.makeCode("/pages/activity/detail/index?id=" + this.actId) signUpCode.makeCode("https://192.168.41.118:5173" + "/pages/activity/detail/index?id=" + this.actId)
let signInCode = new QRCode(document.getElementById("signInCode"), { let signInCode = new QRCode(document.getElementById("signInCode"), {
width: 150, width: 150,
height: 150 height: 150
}) })
signInCode.makeCode("/pages/activity/scan-sign/index?id=" + this.actId) signInCode.makeCode("https://192.168.41.118:5173" + "/pages/activity/scan-sign/index?id=" + this.actId)
}, },
download() { download() {
// 获取base64 // 获取base64
+2 -2
View File
@@ -131,8 +131,8 @@
"pagePath": "pages/activity/rank/index", "pagePath": "pages/activity/rank/index",
"text": "排行榜", "text": "排行榜",
"iconfont": { "iconfont": {
"text": "\ue64d", "text": "\ue8b3",
"selectedText": "\ue64d", "selectedText": "\ue8b3",
"fontSize": "17px", "fontSize": "17px",
"color": "#333", "color": "#333",
"selectedColor": "#f45a5a" "selectedColor": "#f45a5a"
@@ -8,6 +8,7 @@
show-error-message show-error-message
label-align="left" label-align="left"
scroll-to-first-error="auto" scroll-to-first-error="auto"
labelWidth="90px"
> >
<!-- <view class="form-block">--> <!-- <view class="form-block">-->
<!-- <view class="form-block-title">--> <!-- <view class="form-block-title">-->
@@ -69,9 +70,9 @@
<t-radio :block="false" name="radio" :value="false" label="否"/> <t-radio :block="false" name="radio" :value="false" label="否"/>
</t-radio-group> </t-radio-group>
</t-form-item> </t-form-item>
<t-form-item label="是否联系人" :name="`userList[${index}].isStay`" <t-form-item label="是否联系人" :name="`userList[${index}].isContacts`"
:rules="[{required:true,message: '请选择是否住宿'}]"> :rules="[{required:true,message: '请选择是否为联系人'}]">
<t-radio-group v-model="user.isStay" class="radio-box"> <t-radio-group v-model="user.isContacts" class="radio-box">
<t-radio :block="false" name="radio" :value="true" label="是"/> <t-radio :block="false" name="radio" :value="true" label="是"/>
<t-radio :block="false" name="radio" :value="false" label="否"/> <t-radio :block="false" name="radio" :value="false" label="否"/>
</t-radio-group> </t-radio-group>
@@ -161,9 +162,9 @@ onLoad((option) => {
listSignUpUser() listSignUpUser()
getIsSignUp() getIsSignUp()
// 没报名进行引导 // 没报名进行引导
if(formData.userList.length === 0){ if(formData.value.userList.length === 0){
guideCurrent.value = 0 guideCurrent.value = 0
formData.value.unitName = userStore.userInfo?.unit.name //formData.value.unitName = userStore.userInfo?.unit.name
} }
} else { } else {
Toast({message: 'ID不存在', theme: 'error'}); Toast({message: 'ID不存在', theme: 'error'});
@@ -255,6 +256,7 @@ async function submitForm() {
title: '提交中...', title: '提交中...',
mask: true, mask: true,
}) })
console.log(formData.value)
try { try {
const {code, data, msg} = await request.post('/client/activity/sign-up', formData.value) const {code, data, msg} = await request.post('/client/activity/sign-up', formData.value)
if (code === 0) { if (code === 0) {
@@ -22,7 +22,7 @@
<!-- 底部按钮 --> <!-- 底部按钮 -->
<view class="action-buttons"> <view class="action-buttons">
<t-button theme="default" shape="round" @click="navigateToHome">返回首页</t-button> <t-button theme="default" shape="round" @click="navigateToHome">返回首页</t-button>
<t-button theme="primary" shape="round" @click="viewRegistrationDetails">查看报名详情</t-button> <t-button theme="primary" shape="round" @click="navigateToEdit">修改报名信息</t-button>
</view> </view>
</view> </view>
</view> </view>
@@ -69,9 +69,9 @@ const navigateToHome = () => {
}; };
// 查看报名详情 // 查看报名详情
const viewRegistrationDetails = () => { const navigateToEdit = () => {
uni.navigateTo({ uni.redirectTo({
url: '/pages/activity/registration-details/index?id=' + actId.value url: '/pages/activity/registration-form/index?id=' + actId.value
}); });
}; };
</script> </script>
+42 -51
View File
@@ -69,32 +69,10 @@
</view> </view>
</view> </view>
</view> </view>
<div class="bg-decoration">
<svg class="wave" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320">
<path fill="#f45a5a" fill-opacity="0.1" d="M0,160L48,154.7C96,149,192,139,288,144C384,149,480,171,576,176C672,181,768,171,864,154.7C960,139,1056,117,1152,128C1248,139,1344,181,1392,202.7L1440,224L1440,0L1392,0C1344,0,1248,0,1152,0C1056,0,960,0,864,0C768,0,672,0,576,0C480,0,384,0,288,0C192,0,96,0,48,0L0,0Z"></path>
</svg>
<svg class="dots" width="100" height="100" viewBox="0 0 100 100">
<circle fill="#f45a5a" fill-opacity="0.2" cx="10" cy="10" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="30" cy="10" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="50" cy="10" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="70" cy="10" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="90" cy="10" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="10" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="30" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="50" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="70" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="90" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="10" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="30" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="50" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="70" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="90" cy="50" r="3" />
</svg>
</div>
</template> </template>
<view style="flex: 1;display: flex;justify-content: center;align-items: center"> <view v-if="actOptions && actOptions.length === 0" style="flex: 1;display: flex;justify-content: center;align-items: center">
<t-empty v-if="actOptions && actOptions.length === 0" <t-empty
image="/static/img/empty.png" image="/static/img/empty.png"
description="报名活动后才能扫码签到" description="报名活动后才能扫码签到"
style="flex: 1"> style="flex: 1">
@@ -114,12 +92,14 @@
<script setup> <script setup>
import {ref, computed, onMounted} from 'vue'; import {ref, computed, onMounted} from 'vue';
import {onBackPress, onLoad} from "@dcloudio/uni-app";
import {useRequest} from '@/utils/request'; import {useRequest} from '@/utils/request';
import {useUserStore} from "@/store";
import {Dialog, Toast} from 'tdesign-mobile-vue'; import {Dialog, Toast} from 'tdesign-mobile-vue';
import moment from 'moment';
import ScanQRCode from '@/components/scanQrCode.vue' import ScanQRCode from '@/components/scanQrCode.vue'
const request = useRequest() const request = useRequest()
const userStore = useUserStore()
const list = ref([]) const list = ref([])
const signInfo = ref({}) const signInfo = ref({})
@@ -138,6 +118,20 @@ onMounted(() => {
listMineAct(); listMineAct();
}); });
onLoad((options)=>{
if(options.id){
selectActId.value = Number(options.id)
signIn()
}
})
// 返回按钮
onBackPress(()=>{
uni.redirectTo({
url: '/pages/index/index'
})
})
// 获取活动列表 // 获取活动列表
async function listMineAct() { async function listMineAct() {
try { try {
@@ -175,6 +169,10 @@ async function getSignInfo(val) {
// 扫码签到 // 扫码签到
function handleScan() { function handleScan() {
if(signInfo.value.isSignIn){
Toast('您已签到')
return
}
qrScannerRef.value.startScan() qrScannerRef.value.startScan()
} }
@@ -185,6 +183,20 @@ function handleScanSuccess(val) {
Toast.error("请扫描合法的二维码") Toast.error("请扫描合法的二维码")
return return
} }
if(val.indexOf('http')!== -1){
const url = new URL(val)
const id = url.searchParams.get('id')
if(id){
val = id
signIn()
return;
}else{
Toast.error("请扫描合法的二维码")
return
}
}
if (String(val) !== String(selectActId.value)) { if (String(val) !== String(selectActId.value)) {
Toast.error('请扫码签到当前活动,扫描成功,活动ID为' + val + ",当前选择活动ID为" + selectActId.value) Toast.error('请扫码签到当前活动,扫描成功,活动ID为' + val + ",当前选择活动ID为" + selectActId.value)
return return
@@ -195,6 +207,11 @@ function handleScanSuccess(val) {
// 签到 // 签到
async function signIn() { async function signIn() {
try { try {
if(signInfo.value.isSignIn){
Toast.error('您已签到')
return
}
await uni.showLoading({ await uni.showLoading({
title: '签到中...', title: '签到中...',
mask: true, mask: true,
@@ -538,32 +555,6 @@ function navigateToSignUp(){
color: #999999; color: #999999;
} }
.bg-decoration {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 1;
overflow: hidden;
}
.wave {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 200px;
}
.dots {
position: absolute;
bottom: 5%;
right: 5%;
animation: float 4s ease-in-out infinite;
}
/* 导入Animate.css的部分动画 */ /* 导入Animate.css的部分动画 */
.animate__animated { .animate__animated {
animation-duration: 1s; animation-duration: 1s;
+11 -11
View File
@@ -1,9 +1,10 @@
<template> <template>
<view class="page-container"> <view class="page-container">
<template v-if="actOptions && actOptions.length>0">
<t-dropdown-menu class="top-dropdown"> <t-dropdown-menu class="top-dropdown">
<t-dropdown-item :options="actOptions" :value="selectActId"/> <t-dropdown-item :options="actOptions" :value="selectActId"/>
</t-dropdown-menu> </t-dropdown-menu>
<template v-if="actOptions && actOptions.length > 0 && teamMembers.length > 0">
<view class="content-container"> <view class="content-container">
<!-- <view class="page-header">--> <!-- <view class="page-header">-->
<!-- <text class="page-title">团队报名</text>--> <!-- <text class="page-title">团队报名</text>-->
@@ -25,8 +26,11 @@
<view class="project-card__title">{{ project.name }}</view> <view class="project-card__title">{{ project.name }}</view>
<div style="display: flex;justify-content: flex-end;margin-top: 10px;"> <div style="display: flex;justify-content: flex-end;margin-top: 10px;">
<t-button size="small" class="project-card__button" @click="openDesc(project)">项目介绍</t-button> <t-button theme="primary" size="small" class="project-card__button" @click="openDesc(project)">
<t-button size="small" @click="selectProject(project)" class="project-card__button"> 活动报名 {{ 项目介绍
</t-button>
<t-button theme="primary" size="small" @click="selectProject(project)" class="project-card__button">
活动报名 {{
registrationStatus.get(project.id)?.length ? registrationStatus.get(project.id)?.length : 0 registrationStatus.get(project.id)?.length ? registrationStatus.get(project.id)?.length : 0
}}人 }}人
</t-button> </t-button>
@@ -41,7 +45,7 @@
</view> </view>
</template> </template>
<view v-else style="flex: 1;display: flex;justify-content: center;align-items: center"> <view v-else style="flex: 1;display: flex;justify-content: center;align-items: center">
<t-empty v-if="actOptions && actOptions.length === 0" <t-empty
image="/static/img/empty.png" image="/static/img/empty.png"
description="您没有任何团队信息,无法进行项目报名" description="您没有任何团队信息,无法进行项目报名"
style="flex: 1"> style="flex: 1">
@@ -205,9 +209,9 @@ async function listActs() {
label: item.title label: item.title
} }
}) })
// if(selectActId.value === null && data.length){ if (selectActId.value === null && data.length) {
// selectActId.value = data[0].id selectActId.value = data[0].id
// } }
} else { } else {
Toast.error(msg) Toast.error(msg)
} }
@@ -240,7 +244,6 @@ async function listTeamUser() {
teamMembers.value = data; teamMembers.value = data;
isSelfLeader.value = data.find(t => t.userId === userStore?.userInfo.id)?.isLeader isSelfLeader.value = data.find(t => t.userId === userStore?.userInfo.id)?.isLeader
} else { } else {
Toast.error(msg)
} }
} catch (e) { } catch (e) {
Toast.error(e) Toast.error(e)
@@ -285,7 +288,6 @@ const getApplyUsers = async () => {
if (code === 0) { if (code === 0) {
selectedMemberList.value = data selectedMemberList.value = data
} else { } else {
Toast.error(msg)
} }
} catch (e) { } catch (e) {
Toast.error(e.message) Toast.error(e.message)
@@ -461,8 +463,6 @@ const submitRegistration = async () => {
.project-card__button { .project-card__button {
margin-left: 10px; margin-left: 10px;
background-color: #0052D9;
color: #ffffff;
} }
+4 -4
View File
@@ -1,11 +1,11 @@
<template> <template>
<view class="page-container"> <view class="page-container">
<view v-if="team">
<t-sticky> <t-sticky>
<t-dropdown-menu class="top-dropdown-menu"> <t-dropdown-menu class="top-dropdown-menu">
<t-dropdown-item :options="actOptions" :value="pageForm.actId" @change="actChange"/> <t-dropdown-item :options="actOptions" :value="pageForm.actId" @change="actChange"/>
</t-dropdown-menu> </t-dropdown-menu>
</t-sticky> </t-sticky>
<view v-if="team">
<!-- 团队卡片 --> <!-- 团队卡片 -->
<div class="content-area"> <div class="content-area">
<div class="team-card"> <div class="team-card">
@@ -118,8 +118,7 @@
</div> </div>
</view> </view>
<view v-else style="flex: 1;display: flex;justify-content: center;align-items: center"> <view v-else style="flex: 1;display: flex;justify-content: center;align-items: center">
<t-empty v-if="actOptions && actOptions.length === 0" <t-empty image="/static/img/empty.png"
image="/static/img/empty.png"
description="您没有任何团队信息" description="您没有任何团队信息"
style="flex: 1"> style="flex: 1">
</t-empty> </t-empty>
@@ -265,7 +264,8 @@ const getListAct = async () => {
// 点击查看成绩排名 // 点击查看成绩排名
const queryRank = () => { const queryRank = () => {
uni.navigateTo({url: '/pages/activity/rank/index?id=' + pageForm.actId}) // uni.navigateTo({url: '/pages/activity/rank/index?id=' + pageForm.actId})
uni.switchTab({url: '/pages/activity/rank/index?id=' + pageForm.actId})
} }
// 初始化 // 初始化
+15 -28
View File
@@ -136,6 +136,7 @@ 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"; import {useUserStore} from "@/store";
import {onLoad} from "@dcloudio/uni-app";
const request = useRequest() const request = useRequest()
const userStore = useUserStore() const userStore = useUserStore()
@@ -287,44 +288,30 @@ async function handleLogin() {
userStore.smsLogin(loginForm).then(() => { userStore.smsLogin(loginForm).then(() => {
userStore.getUserInfo().then(() => { userStore.getUserInfo().then(() => {
Toast({message: '登录成功', theme: 'success'}) Toast({message: '登录成功', theme: 'success'})
const redirect = uni.getStorageSync("REDIRECT_URL")
if(redirect){
if(redirect.startsWith('/pages/index/index') || redirect.startsWith('/pages/profile/index')){
uni.switchTab({
url: redirect
})
}else{
uni.navigateTo({
url: redirect
})
}
}else{
uni.switchTab({ uni.switchTab({
url: '/pages/index/index' url: '/pages/index/index'
}) })
}
}).catch(e => { }).catch(e => {
console.log(e)
Toast({message: e.message, theme: 'error'}) Toast({message: e.message, theme: 'error'})
}) })
}).catch(e => { }).catch(e => {
console.log(e) console.log(e)
Toast({message: e.message, theme: 'error'}) Toast({message: e.message, 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'})
Binary file not shown.
+2 -5
View File
@@ -19,6 +19,7 @@ export const checkAuth = async () => {
if (token) { if (token) {
await useUserStore().getUserInfo() await useUserStore().getUserInfo()
} else { } else {
uni.setStorageSync('REDIRECT_URL', window.location.pathname + window.location.search)
await uni.redirectTo({ await uni.redirectTo({
url: '/pages/login/index' url: '/pages/login/index'
}) })
@@ -88,12 +89,8 @@ async function routeInterceptor(args, whiteList) {
return args return args
} else { } else {
console.log('拦截导航,跳转到登录页') console.log('拦截导航,跳转到登录页')
// 保存用户尝试访问的页面,以便登录后跳回 // 保存用户尝试访问的页面,以便登录后跳回
try { uni.setStorageSync('REDIRECT_URL', targetUrl + args.query)
uni.setStorageSync('REDIRECT_URL', targetUrl)
} catch (e) {
}
Dialog.confirm({ Dialog.confirm({
title: '提示', title: '提示',
+3 -3
View File
@@ -28,13 +28,13 @@ export default defineConfig({
} }
}, },
server: { server: {
/* https: { https: {
cert: fs.readFileSync(path.join(__dirname, 'src/ssl/localhost+2.pem')), cert: fs.readFileSync(path.join(__dirname, 'src/ssl/localhost+2.pem')),
key: fs.readFileSync(path.join(__dirname, 'src/ssl/localhost+2-key.pem')) key: fs.readFileSync(path.join(__dirname, 'src/ssl/localhost+2-key.pem'))
},*/ },
proxy: { proxy: {
'/api': { '/api': {
target: 'http://localhost:9090', target: 'http://192.168.41.118:9090',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '') rewrite: (path) => path.replace(/^\/api/, '')
} }