Files
zhgh_cpu/src/main/resources/views/mobile/club/inClub.html
T
2026-10-20 20:50:11 +08:00

513 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!--#
layout("/mobile/platform.html"){
#-->
<style>
.van-index-bar__sidebar {
display: none;
}
.van-doc-card {
margin: 14px;
padding: 12px 12px 12px 12px;
background-color: #fff;
border-radius: 10px;
box-shadow: 0 8px 12px #ebedf0;
line-height: 20px;
font-size: 13px;
position: relative;
}
.van-divider {
margin: 6px 0 6px 0px;
border-color: lightgray;
}
.van-button--small {
border-top-right-radius: 16px;
border-bottom-left-radius: 16px;
height: 26px;
}
.van-col {
line-height: 24px;
}
.title_span {
font-size: 16px;
font-weight: bold;
position: absolute;
left: -1px;
top: 11px;
color: #1867b0;
}
.title {
font-size: 13px;
font-weight: bold;
flex: 1;
overflow: hidden;
white-space: nowrap;
}
.cus_overflow {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.van-dropdown-menu__item {
flex: auto;
}
p {
margin: 0 !important;
}
.van-cell__title {
width: 30%;
}
.van-cell__title, .van-cell__value{
flex: none;
}
.van-cell__value {
width: 70%;
}
.footer {
background-color: white;
width: 100%;
height: 60px;
display: flex;
justify-content: space-evenly;
align-items: center;
left: 0;
}
.footer .van-button {
height: 34px;
border-radius: 6px;
width: 90% !important;
}
.join {
background-color: #0e78c5;
color: white;
}
</style>
<div id="app" v-cloak>
<m-page-loading v-if="mLoading"></m-page-loading>
<!--top栏-->
<van-nav-bar
title="加入社团"
left-arrow
placeholder
fixed
@click-left="leavePage"
safe-area-inset-top
></van-nav-bar>
<!--筛选框-->
<div class="search-fixed">
<van-search
v-model="pageForm.searchKeyword"
shape="round"
maxlength="10"
@search="doSearch"
placeholder="请输入社团名称进行查询"
>
</van-search>
<van-dropdown-menu>
<van-dropdown-item v-model="pageForm.isjr" :options="clubType"
@change="doSearch"></van-dropdown-item>
<van-dropdown-item v-model="pageForm.clubType" :options="typeOptions"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
</div>
<!--列表-->
<div style="margin-top: 116px">
<van-list
v-model="loading"
:finished="finished" :immediate-check="false" @load="onLoad"
:finished-text="tableData.length>0?'没有更多了':''">
<div class="van-doc-card" v-for="o in tableData">
<div>
<div style="display: flex; justify-content: space-between">
<div style="width: 74%">
<div class="van-ellipsis title">
<span class="title_span">|</span>
<span>{{o.name}}</span>
</div>
<div style="color: grey">{{o.location}}</div>
</div>
<div style="color: #1867b0; white-space: nowrap;">
<span v-if="o.status==1">待社团审核</span>
<span v-if="o.status==2" style="color: red">社团拒绝</span>
<span v-if="o.status==3">待校工会审核</span>
<span v-if="o.status==4" style="color: red">校工会拒绝</span>
<span v-if="o.status==5" style="color: green">审核通过</span>
</div>
</div>
<div style="margin-top: 4px">
<van-row>
<van-col span="12"><span style="color: grey">联&ensp;系&ensp;人:</span>{{o.fzrname}}</van-col>
<van-col span="12">
<span style="color: grey">电&emsp;&emsp;话:</span>
<span>{{o.fzr_mobile}}</span>
</van-col>
</van-row>
<van-row>
<van-col span="12"><span style="color: grey">会&emsp;&emsp;长:</span>{{o.hz}}</van-col>
<van-col span="12">
<span style="color: grey">成立时间:</span>
<span>{{moment(o.foundTime).format('YYYY-MM-DD')}}</span>
</van-col>
</van-row>
</div>
<van-divider></van-divider>
<div style="display: flex; justify-content: flex-end">
<div>
<van-button @click="openInfo(o, 'view')" color="#1867b0"
size="small" style="margin-right: 8px" type="primary">
查看
</van-button>
<van-button @click="rollback(o)" color="#1867b0"
size="small" style="margin-right: 8px" type="primary"
v-if="pageForm.isjr === true && (o.status==1 || o.status==3)">撤销申请
</van-button>
<van-button @click="openInfo(o, 'join')"
color="#1867b0" v-if="pageForm.isjr === false"
size="small" style="margin-right: 8px" type="primary">
我要加入
</van-button>
</div>
</div>
</div>
</div>
</van-list>
<van-empty
v-if="mLoading==false&&tableData.length==0"
class="custom-image"
image="/none.svg"
description="暂无数据"
></van-empty>
</div>
<van-popup v-model="infoShow" :close-on-click-overlay="false" get-container="#app" position="right" :style="{ height: '100%', width: '100%' }">
<van-nav-bar
title="社团详细信息"
left-arrow
placeholder
fixed
@click-left="closePopup"
safe-area-inset-top></van-nav-bar>
<van-tabs v-model="infoActive">
<van-tab title="社团信息">
<van-cell-group inset>
<van-cell title="社团名称">{{ detailData.name }}</van-cell>
<van-cell title="成立时间">{{ detailData.foundtime }}</van-cell>
<van-cell title="报名联系人">{{ detailData.fzrname }}</van-cell>
<van-cell title="所属单位">{{ detailData.fzr_unit_name }}</van-cell>
<van-cell title="联系人电话">{{ detailData.concatpersonmobile }}</van-cell>
<van-cell title="联系人邮箱">{{ detailData.concatpersonemail }}</van-cell>
<van-cell title="会费标准">{{ detailData.dues_standard }}</van-cell>
<van-cell title="当前人数">{{ detailData.cynum }}</van-cell>
<van-cell title="QQ群二维码" @click="showCode('QQ')">
<span style="cursor: pointer; color: #236eb4">点击查看</span>
</van-cell>
<van-cell title="微信群二维码" @click="showCode('weChat')">
<span style="cursor: pointer; color: #236eb4">点击查看</span>
</van-cell>
</van-cell-group>
<div class="footer" v-if="canJoin">
<van-button class="join" @click="startJoin">我要加入</van-button>
</div>
<van-cell v-else title="申请状态" :value="joinStatus"></van-cell>
</van-tab>
<van-tab v-if="viewType === 'join'" title="个人信息">
<van-form @submit="needJoin" ref="form" :show-error-message="false">
<van-cell-group inset class="mt10">
<van-field v-model="formData.username" name="username" label="姓名" placeholder="请填写姓名" readonly required :rules="[{ required: true, message: '请填写姓名' }]"></van-field>
<van-field v-model="formData.sex" name="sex" label="性别" placeholder="请填写性别" readonly required :rules="[{ required: true, message: '请填写性别' }]"></van-field>
<van-field v-model="formData.loginname" name="loginname" label="工号" placeholder="请填写工号" readonly required :rules="[{ required: true, message: '请填写工号' }]"></van-field>
<van-field v-model="formData.birthday" name="birthday" label="出生年月" placeholder="请填写出生年月" readonly @click="openBirthday" required :rules="[{ required: true, message: '请填写出生年月' }]"></van-field>
<van-popup v-model="showPicker" position="bottom" :close-on-click-overlay="false">
<van-datetime-picker v-model="birthdayPickerValue" type="date" :min-date="birthdayMinDate" :max-date="birthdayMaxDate" title="选择出生日期" @confirm="confirmBirthday" @cancel="closePopup"></van-datetime-picker>
</van-popup>
<van-field v-model="formData.mobile" name="mobile" label="联系电话" placeholder="请填写联系电话" maxlength="20" required :rules="[{ required: true, message: '请填写联系电话' }]"></van-field>
<van-field name="medicalHistory" label="是否有特殊病史" required><template #input><van-radio-group v-model="formData.medicalHistory" direction="horizontal"><van-radio :name="true">是</van-radio><van-radio :name="false">否</van-radio></van-radio-group></template></van-field>
<van-field v-model="formData.otherThing" name="otherThing" label="是否有特别需要说明的问题" placeholder="如有,请填写特别需要说明的问题" maxlength="100" type="textarea" autosize></van-field>
<van-field v-model="formData.emergencyContact" name="emergencyContact" label="紧急联系人" placeholder="请填写紧急联系人" maxlength="50" required :rules="[{ required: true, message: '请填写紧急联系人' }]"></van-field>
<van-field v-model="formData.emergencyMobile" name="emergencyMobile" label="紧急联系电话" placeholder="请填写紧急联系电话" maxlength="20" required :rules="[{ required: true, message: '请填写紧急联系电话' }]"></van-field>
</van-cell-group>
<div class="footer">
<van-button class="join join_submit" :loading="formLoading" native-type="submit">申请加入</van-button>
</div>
</van-form>
</van-tab>
</van-tabs>
</van-popup>
</div>
<script>
const vue = new Vue({
el: '#app',
mixins: [mobileMixins],
data() {
return {
showPicker: false,
birthdayPickerValue: new Date(),
birthdayMinDate: new Date(1900, 0, 1),
birthdayMaxDate: new Date(),
infoActive: 0,
clickRow: {},
typeOptions: [],
clubType: [{text: '未加入', value: false}, {text: '已加入', value: true}],
infoShow: false,
detailData: {},
viewType: '',
formLoading: false,
// 服务端保留本次页面请求的社团 ID,避免依赖页面切换时的地址栏状态。
scanClubId: decodeURIComponent('${scanClubId!}'.replace(/\+/g, '%20')),
}
},
computed: {
canJoin() {
return !!this.detailData.id && ![1, 3, 5].includes(Number(this.detailData.status))
},
joinStatus() {
return {1: '待社团审核', 3: '待校工会审核', 5: '已加入'}[this.detailData.status] || ''
}
},
methods: {
// 所有弹层由统一历史栈同步;页面不单独监听 popstate。
syncPopup(key, visible) {
if (key === 'info') this.$set(this, 'infoShow', visible)
if (key === 'birthday') this.$set(this, 'showPicker', visible)
if (key === 'confirm' && !visible) vant.Dialog.close()
if (key === 'preview' && !visible && this.clubPreview) this.clubPreview.close()
},
closePopup() {
return mobilePopupHistory.close()
},
leavePage() {
if (mobilePopupHistory.stack.length) {
this.closePopup()
return
}
this.disposePopup()
pjaxReplace('/mobile/index')
},
disposePopup() {
mobilePopupHistory.unregister(this.syncPopup)
$(document).off('pjax:beforeSend.clubScan')
},
openBirthday() {
// 选择器定位到系统出生日期;档案为空时允许用户补填。
const date = moment(this.formData.birthday, 'YYYY-MM-DD', true)
this.$set(this, 'birthdayPickerValue', date.isValid() ? date.toDate() : new Date())
mobilePopupHistory.open('birthday')
},
confirmBirthday(value) {
this.$set(this.formData, 'birthday', moment(value).format('YYYY-MM-DD'))
this.closePopup()
},
// 确认/取消先回退本层历史,系统返回由同步回调关闭确认框。
confirmAction(message) {
mobilePopupHistory.open('confirm')
return vant.Dialog.confirm({title: '提示', message, closeOnPopstate: false})
.then(() => this.closePopup())
.catch(() => {
if (mobilePopupHistory.stack.includes('confirm')) {
return this.closePopup().then(() => Promise.reject())
}
return Promise.reject()
})
},
showCode(type) {
const files = type === 'QQ' ? this.detailData.qqgroupcode : this.detailData.wechatgroupcode
if (!files) return
const images = (typeof files === 'string' ? JSON.parse(files) : files)
.map(o => FILE_DOMAIN + '/fileStreamPreview?id=' + o.id)
if (!images.length) return
mobilePopupHistory.open('preview')
this.clubPreview = vant.ImagePreview({
images, closeOnPopstate: false,
onClose: () => {
if (mobilePopupHistory.stack.includes('preview')) this.closePopup()
}
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.tableData = []
this.finished = false
this.onLoad()
},
onLoad() {
this.loading = true
$.post('/platform/sys/club/sq/pageData', this.pageForm).then(res => {
if (res.code === 0) {
this.tableData = this.tableData.concat(res.data.list)
if (this.tableData.length === res.data.totalCount) {
this.finished = true
} else {
this.pageForm.pageNumber++
}
}
}).always(() => { this.loading = false })
},
openInfo(row, type) {
if (this.mLoading) return
this.mLoading = true
// clubId 是社团主键;data 返回详情及登录用户状态,不受列表页码、筛选影响。
$.post('/platform/sys/club/sq/scanDetail', {clubId: row.id}).then(res => {
if (res.code !== 0) {
vant.Toast(res.msg || '社团信息加载失败')
return
}
this.detailData = res.data
this.clickRow = res.data
this.viewType = 'view'
this.infoActive = 0
if (this.canJoin && (type === 'join' || type === 'scan')) {
this.prepareJoin()
}
// 等待条件页签及弹框渲染后再打开;扫码先展示社团信息,列表申请展示个人信息。
this.$nextTick(() => {
this.infoActive = type === 'join' && this.canJoin ? 1 : 0
mobilePopupHistory.open('info')
})
}).fail(() => vant.Toast('社团信息加载失败,请重试'))
.always(() => { this.mLoading = false })
},
startJoin() {
if (!this.canJoin) return
// 已进入加入模式时保留用户填写的数据,不因切换页签再次清空。
if (this.viewType !== 'join') this.prepareJoin()
this.$nextTick(() => { this.infoActive = 1 })
},
// 初始化当前社团的加入表单;扫码展示两个页签时也复用此方法。
prepareJoin() {
this.viewType = 'join'
this.$set(this, 'formData', {
username: "${@shiro.getPrincipalProperty('username')}",
sex: "${@shiro.getPrincipalProperty('sex')}",
loginname: "${@shiro.getPrincipalProperty('loginname')}",
birthday: "${@shiro.getPrincipalProperty('birthday')}",
mobile: "${@shiro.getPrincipalProperty('mobile')}",
medicalHistory: null, otherThing: '', emergencyContact: '', emergencyMobile: ''
})
},
needJoin() {
if (this.formLoading || !this.canJoin) return
const row = this.clickRow
if(this.formData.medicalHistory === '' || this.formData.medicalHistory === undefined || this.formData.medicalHistory === null) {
vant.Toast('请选择是否有特殊病史')
return
}
this.$set(this, 'formLoading', true)
$.post('/platform/sys/club/sq/getInClubByCurUser').then(res => {
if (res.code !== 0) {
vant.Toast(res.msg)
return
}
const data = res.data
let str = ''
if (data && data.length > 0) {
str = '您已经加入了'
data.forEach((item) => {
str += '【' + item.name + '】'
})
str += ','
}
str += '请确认是否申请加入【' + row.name + '】?'
this.confirmAction(str).then(() => {
this.$set(this, 'formLoading', true)
// 仅提交精简后的入会资料,出生年月和电话不回写用户档案。
const params = Object.assign({}, this.formData, {
clubid: row.id
})
$.post("/platform/sys/club/sq/submit", params).then(data => {
if (data.code === 0) {
vant.Toast(data.msg)
mobilePopupHistory.clear().then(() => this.doSearch())
} else {
vant.Toast(data.msg)
}
}).always(() => { this.$set(this, 'formLoading', false) })
}).catch(() => {
});
}).always(() => { this.$set(this, 'formLoading', false) })
},
rollback(o) {
this.confirmAction('请确定是否撤销申请?').then(() => {
const id = o.id
this.$set(this, 'formLoading', true)
$.post("/platform/sys/club/sq/revocation", {id}).then(data => {
if (data.code === 0) {
vant.Toast('撤销申请成功');
this.doSearch();
} else {
vant.Toast(data.msg);
}
}).always(() => { this.$set(this, 'formLoading', false) })
}).catch(() => {
});
}
},
created() {
mobilePopupHistory.register(this.syncPopup)
// PJAX 离开前先清理弹框历史,重新发起原页面跳转,并注销本页回调。
$(document).on('pjax:beforeSend.clubScan', (event, xhr, options) => {
if (mobilePopupHistory.stack.length) {
event.preventDefault()
mobilePopupHistory.clear().then(() => {
this.disposePopup()
pjaxReplace(options.url)
})
return false
}
this.disposePopup()
})
this.$set(this.pageForm, 'isjr', false)
this.$set(this.pageForm, 'searchName', 'club.name')
this.onLoad()
getClubType().then(data => {
data.forEach(item => {
this.typeOptions.push({text: item.name, value: item.code})
})
this.typeOptions.unshift({text: '全部类型'})
this.$set(this.pageForm, "clubType", this.typeOptions[0].value)
})
},
mounted() {
// 兼容已有二维码;无 clubId 的普通入口仍显示列表,不猜测目标社团。
const clubId = this.scanClubId || new URLSearchParams(window.location.search).get('clubId')
if (clubId) this.openInfo({id: clubId}, 'scan')
},
beforeDestroy() {
mobilePopupHistory.clear().then(() => this.disposePopup())
}
})
</script>
<!--#
}
#-->