This commit is contained in:
@jyuhsin
2025-09-15 14:31:17 +08:00
parent 11b90741be
commit 20fe55813f
52 changed files with 5342 additions and 32348 deletions
@@ -1,4 +1,4 @@
const signForm = {
const applyForm = {
template: /*language=HTML*/ `
<div>
<el-dialog :close-on-click-modal="false" :visible.sync="signDialog" title="信息填写" width="50%" append-to-body>
@@ -33,11 +33,11 @@ const signForm = {
<el-input readonly v-model="formData.sex"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<!--<el-col :span="24">
<el-form-item label="联系方式" prop="mobile">
<el-input v-model="formData.mobile"></el-input>
</el-form-item>
</el-col>
</el-col>-->
</el-row>
<el-row v-if="courseRow.courseIsLimitApply">
@@ -121,7 +121,7 @@ const signForm = {
},
methods: {
async getCourseTimeSelectList(o) {
const resp = await $.post('/platform/mobile/trainSignUpActivity/getCourseTimeSelectList',{ courseId: o.id })
const resp = await $.post('/platform/trainSingUp/apply/getCourseTimeSelectList',{ courseId: o.id })
if (resp.code === 0) {
this.courseTimeSelectList = resp.data
} else {
@@ -135,35 +135,34 @@ const signForm = {
}
this.courseRow = row
this.signDialog = true
this.$nextTick(() => {
this.$refs.form.clearValidate()
})
},
async validateSignUp() {
// 获取家属人数
let familyCount = this.formData.trainMobileSignColumnList.filter(o => o.columnCode === 'xdqsrs').reduce((sum, item) => {
return sum + (Number(item.columnValue) || 0)
}, 0)
const res = await this.$axios.post("/platform/trainSingUp/apply/validateSignUp", {
courseId: this.formData.courseId,
currentFamilyNumber: familyCount
})
return res.code === 0
},
async validateCourseTime() {
const res = await this.$axios.post('/platform/trainSingUp/apply/validateSourceSignUp', {
activityCourseId: this.formData.activityCourseId,
courseId: this.courseRow.id
})
return res.code === 0
},
async onSubmit() {
//获取家属是多少人
let per = 0
this.formData.trainMobileSignColumnList.forEach((item) => {
if (item.columnCode === "xdqsrs") {
per += Number(item.columnValue)
}
})
const res = await this.$axios.post("/platform/mobile/trainSignUpActivity/validateSignUp", {
courseId: this.formData.courseId,
currentFamilyNumber: per
})
if (res.code !== 0) {
this.$message.warning(res.msg)
return
}
if(!await this.validateSignUp()) return
this.$refs["form"].validate(async (valid) => {
if (valid) {
if (this.courseRow.courseIsLimitApply) {
const resp = await this.$axios.post('/platform/mobile/trainSignUpActivity/validateSourceSignUp', {
activityCourseId: this.formData.activityCourseId,
courseId: this.courseRow.id
})
if (resp.code !== 0) {
this.$message.warning(res.msg)
return
}
}
if(this.courseRow.courseIsLimitApply && !await this.validateCourseTime()) return
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
@@ -178,7 +177,7 @@ const signForm = {
}
})
this.formData.mobileColumnsValue = JSON.stringify(mobileColumnsValue)
const resp = await this.$axios.post("/platform/mobile/trainSignUpActivity/doSignUp", this.formData)
const resp = await this.$axios.post("/platform/trainSingUp/apply/doSignUp", this.formData)
if (resp.code === 0) {
this.signDialog = false
this.$message.success(resp.msg)
@@ -191,22 +190,17 @@ const signForm = {
})
},
initData(row, course) {
this.formData = {
activityId: row.activityId,
courseId: row.id,
username: this.$store.state.user.username,
loginname: this.$store.state.user.loginname,
unionName: this.$store.state.user.union.name,
unitName: this.$store.state.user.unit.name,
sex: this.$store.state.user.sex,
mobile: this.$store.state.user.mobile,
trainMobileSignColumnList: course.trainMobileSignColumnList
}
this.$set(this.formData, 'username', this.$store.state.user.username)
this.$set(this.formData, 'loginname', this.$store.state.user.loginname)
this.$set(this.formData, 'unionName', this.$store.state.user.union.name)
this.$set(this.formData, 'unitName', this.$store.state.user.unit.name)
this.$set(this.formData, 'sex', this.$store.state.user.sex)
this.$set(this.formData, 'activityId', row.activityId)
this.$set(this.formData, 'courseId', row.id)
this.$set(this.formData, 'trainMobileSignColumnList', course.trainMobileSignColumnList)
this.formData.trainMobileSignColumnList.forEach((item) => {
item.columnValue = ""
})
this.$nextTick(() => {
this.$refs.form.clearValidate()
item.columnValue = this.$store.state.user[item.columnCode] || ""
})
},
},
@@ -1,5 +1,5 @@
<!--#include('signForm.js'){}#-->
const info = {
<!--#include('applyForm.js'){}#-->
const courseList = {
template: /*language=HTML*/ `
<div>
<el-row :gutter="20">
@@ -67,6 +67,11 @@ const info = {
<template v-slot="{row}" v-else-if="column.prop=='applyNum'">
<span v-html="calcSignUpCount(row)"></span>
</template>
<template v-slot="{row}" v-else-if="column.prop=='introduce'">
<span v-if="!row.introduce">暂无</span>
<el-button v-else style="padding: 0" @click="onPreview(row.introduce)" type="text">点击查看</el-button>
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template v-slot="{row}">
@@ -103,13 +108,13 @@ const info = {
</el-row>
</el-dialog>
<sign-form ref="signFormRef" @refresh="doSearch"></sign-form>
<apply-form ref="formRef" @refresh="doSearch"></apply-form>
</div>
`,
dicts: ["TRAIN_SIGNUP_TYPE"],
mixins: [initTableMixins],
components: {
"sign-form": signForm,
"apply-form": applyForm,
},
data() {
return {
@@ -125,6 +130,7 @@ const info = {
{ prop: "typeName", label: "类型", width: 130},
{ prop: "courseLocationCoordinates", label: "地点", width: 200 },
{ prop: "courseInstructor", label: "联系人", width: 100 },
{ prop: "introduce", label: "详细介绍", width: 100 },
{ prop: "courseTime", label: "时间", width: 200 },
{ prop: "applyNum", label: "已报名人数", width: 200 }
],
@@ -135,6 +141,17 @@ const info = {
}
},
methods: {
async onPreview(introduce) {
const parser = new DOMParser();
const doc = parser.parseFromString(introduce, 'text/html');
const link = doc.querySelector('a');
const href = link.getAttribute('href');
const id = href.substring(href.indexOf("=") + 1)
const res = await this.$axios.post("/platform/sys/file/previewFileData", { ids: JSON.stringify([id]) })
window.open("/assets/platform/plugins/pdfJs/web/viewer.html?file=" + encodeURIComponent(res.data[0].downloadPath), res.data[0].name)
},
tagClick(key, val) {
let idx = this.pageForm[key].indexOf(val)
if (idx !== -1) {
@@ -153,7 +170,7 @@ const info = {
},
onSign(row) {
const course = this.courseTypeList.find((v) => v.id === row.courseType)
this.$axios.post("/platform/mobile/trainSignUpActivity/validateSignUp", {courseId: row.id})
this.$axios.post("/platform/trainSingUp/apply/validateSignUp", {courseId: row.id})
.then((res) => {
if (res.code !== 0) {
this.$alert(res.msg, "提示", {
@@ -168,7 +185,7 @@ const info = {
type: "warning"
})
}
this.$refs.signFormRef.onOpen(row, course)
this.$refs.formRef.onOpen(row, course)
}
})
},
@@ -178,7 +195,7 @@ const info = {
cancelButtonText: "取消",
type: "info"
}).then(async () => {
const resp = await this.$axios.post("/platform/mobile/trainSignUpActivity/cancelSignUp", {
const resp = await this.$axios.post("/platform/trainSingUp/apply/cancelSignUp", {
activityId: row.activityId,
courseId: row.id
})
@@ -191,7 +208,7 @@ const info = {
})
},
async getCourseTypeList() {
const resp = await this.$axios.post("/platform/trainSingUp/manage/type/getAllType")
const resp = await this.$axios.post("/platform/trainSingUp/type/getAllType")
if (resp.code === 0) {
this.courseTypeList = resp.data
}
@@ -246,7 +263,6 @@ const info = {
}
},
queryCourseAssort() {
console.log(this.activity)
this.$axios.post(loc() + "/queryCourseAssort", {activityId: this.activity.id})
.then((resp) => {
this.assortList = resp.data
@@ -21,15 +21,16 @@ layout("/layouts/platform.html"){
></el-date-picker>
</search-item>
<search-item label="活动状态:" style="width: 340px">
<el-radio-group v-model="pageForm.activityType" @change="doSearch">
<el-radio-button :label="1">全部</el-radio-button>
<el-radio-button :label="2">报名中</el-radio-button>
<el-radio-button :label="3">已结束</el-radio-button>
</el-radio-group>
<el-select v-model="pageForm.activityType" @change="doSearch" style="width: 100%"
placeholder="请选择活动状态" filterable>
<el-option :value="1" label="全部"></el-option>
<el-option :value="4" label="即将开始"></el-option>
<el-option :value="2" label="报名中"></el-option>
<el-option :value="3" label="已结束"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="活动列表"></table-tool>
<el-table :data="tableData" :size="tableSize">
@@ -56,8 +57,9 @@ layout("/layouts/platform.html"){
<span>{{$moment(row.activityEndTime).format('MM/DD HH:mm')}}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<el-table-column label="操作" width="300">
<template v-slot="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看介绍</el-button>
<el-button @click="onOpen(row)" size="mini" type="primary">去报名</el-button>
</template>
</el-table-column>
@@ -66,24 +68,50 @@ layout("/layouts/platform.html"){
</el-card>
<template #view>
<info ref="infoRef"></info>
<course-list ref="courseListRef"></course-list>
</template>
</guava>
<el-dialog title="详细信息" :visible.sync="infoVisible" width="60%">
<activity-info ref="infoRef"></activity-info>
<el-statistic
v-if="time < 0"
format="DD 天 HH 时 mm 分钟 ss 秒"
:value="new Date(infoRow.activitySignUpStartTime)"
time-indices
title="距离开始:"
@finish="time = 0"
style="margin-top: 30px"
>
</el-statistic>
<span slot="footer" class="dialog-footer">
<el-button @click="infoVisible = false">取消</el-button>
<el-button type="primary" @click="onOpen(infoRow)" :disabled="time < 0">
去报名
</el-button>
</span>
</el-dialog>
</div>
<script>
<!--#include('info.js'){}#-->
<!--#include('courseList.js'){}#-->
<!--#include('../manage/info.js'){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"info": info,
"course-list": courseList,
"activity-info": info,
},
data() {
return {
pageForm: {
year: this.$moment().format("YYYY"),
activityType: "2"
activityType: 2
},
tableColumns: [
{ label: "活动名称", prop: "activityName", width: 600},
@@ -91,16 +119,32 @@ layout("/layouts/platform.html"){
{ label: "报名时间", prop: "activitySignUpStartTime"},
{ label: "活动时间", prop: "activityStartTime"},
],
time: 0,
infoRow: {},
infoVisible: false,
}
},
methods: {
onView(row) {
this.infoRow = row
this.time = this.$moment().diff(this.$moment(row.activitySignUpStartTime), 'milliseconds')
this.infoVisible = true
this.$nextTick(() => {
this.$refs.infoRef.initData(row.id)
})
},
onOpen(row) {
if(this.$moment().isBefore(this.$moment(row.activitySignUpStartTime))) {
this.onView(row)
return
}
this.infoVisible = false
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row)
this.$refs.courseListRef.onOpen(row)
})
},
pageData() {
this.$axios.post("/platform/trainSingUp/manage/apply/activityData", this.pageForm).then((res) => {
this.$axios.post("/platform/trainSingUp/apply/activityPageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
@@ -371,7 +371,7 @@ const basicForm = {
}
},
async getRegisterUserCount(courseId) {
const resp = await this.$axios.post("/platform/trainSingUp/manage/activity/getRegisterUserCount", { courseId })
const resp = await this.$axios.post("/platform/trainSingUp/manage/getRegisterUserCount", { courseId })
return resp.code === 0 ? resp.data : 0
},
courseTypeChange(val, row) {
@@ -444,7 +444,7 @@ const basicForm = {
this.formData.courseList.push({ courseTimeList: [], isMobileSign: false, isReceiveGift: false, reserveMode: 1, courseIsLimitApply: false })
},
async historicalActChange(val) {
const resp = await this.$axios.post("/platform/trainSingUp/manage/activity/findOne", {id: val})
const resp = await this.$axios.post("/platform/trainSingUp/manage/findOne", {id: val})
if (resp.code === 0) {
this.formData = resp.data
this.typeChange(this.formData.trainType)
@@ -468,7 +468,7 @@ const basicForm = {
return data
},
async getHistoricalActList() {
const resp = await this.$axios.post("/platform/trainSingUp/manage/activity/getHistoricalActList", {})
const resp = await this.$axios.post("/platform/trainSingUp/manage/getHistoricalActList", {})
return resp.data
},
async onSave() {
@@ -543,7 +543,7 @@ const basicForm = {
type: "warning"
})
if (confirm !== "confirm") return
const resp = await this.$axios.post("/platform/trainSingUp/manage/activity/doHandle", cloneData)
const resp = await this.$axios.post("/platform/trainSingUp/manage/doHandle", cloneData)
if (resp.code === 0) {
this.$message.success(resp.msg)
this.step = 1
@@ -554,12 +554,12 @@ const basicForm = {
}
},
async getAllType() {
const resp = await this.$axios.post("/platform/trainSingUp/manage/type/getAllType", {})
const resp = await this.$axios.post("/platform/trainSingUp/type/getAllType", {})
return resp.data
},
async init(row) {
if (row && row.id) {
const resp = await this.$axios.post("/platform/trainSingUp/manage/activity/findOne", {id: row.id})
const resp = await this.$axios.post("/platform/trainSingUp/manage/findOne", {id: row.id})
if (resp.code === 0) {
this.formData = resp.data
this.typeChange(this.formData.trainType)
@@ -140,6 +140,16 @@ const customForm = {
v-model="formData.courseList[moreInfoIndex].waitingNum"></el-input-number>
</el-col>
</el-row>
<el-row :gutter="50" type="flex">
<el-col :span="4">
<span>详细信息</span>
</el-col>
<el-col :span="20">
<text-editor v-model="formData.courseList[moreInfoIndex].introduce"></text-editor>
</el-col>
</el-row>
<div style="text-align: right">
<el-button @click="moreInfoDrawer = false">取 消</el-button>
<el-button type="primary" @click="moreInfoDrawer = false">保 存</el-button>
@@ -195,17 +205,6 @@ const customForm = {
}
},
style: /*language=CSS*/ `
.my-drawer .el-col-4 {
text-align: right;
}
.my-drawer .el-row {
margin-bottom: 20px;
}
.el-drawer__body {
padding: 20px;
}
.el-row--flex {
align-items: center;
}
`
}
@@ -3,7 +3,18 @@ layout("/layouts/platform.html"){
#-->
<style>
.my-drawer .el-col-4 {
text-align: right;
}
.my-drawer .el-row {
margin-bottom: 20px;
}
.el-drawer__body {
padding: 20px;
}
.el-row--flex {
align-items: center;
}
</style>
<div id="app" v-cloak>
@@ -115,6 +126,7 @@ layout("/layouts/platform.html"){
</guava>
</div>
<script src="${base!}/assets/platform/plugins/jr-qrcode/jr-qrcode.js"></script>
<script>
<!--#include('info.js'){}#-->
<!--#include('basicForm.js'){}#-->
@@ -164,8 +176,7 @@ layout("/layouts/platform.html"){
})
},
openActivityCode(id) {
this.activityUrl = location.origin + "/platform/mobile/trainSignUpActivity/activityInfo?activityId="
+ id + '&isMySign=0'
this.activityUrl = location.origin + "/platform/trainSingUp/apply/h5?id=" + id
this.codeDialogVisible = true
},
makeCode(row) {
@@ -66,7 +66,7 @@ const info = {
},
methods: {
initData(id) {
this.$axios.post(loc() + "/findOne", { id: id })
this.$axios.post("/platform/trainSingUp/manage/findOne", { id: id })
.then((resp) => {
if (resp.code === 0) {
this.viewData = resp.data
@@ -66,8 +66,10 @@ const makeQrcode = {
this.courseDialog = true
},
makeCourseCode(row) {
const o = {courseId: row.id}
const content = jrQrcode.getQrBase64(JSON.stringify(o))
const url = '/platform/trainSingUp/mine/drivingScan'
const data = url + '?courseId=' + row.id
console.log(data)
const content = jrQrcode.getQrBase64(data)
let image = new Image()
image.src = content
let viewer = new Viewer(image, {
@@ -150,7 +150,7 @@ const unionForm = {
!this.formData.courseList[this.unionLimitIndex].unionLimit ||
this.formData.courseList[this.unionLimitIndex].unionLimit.length === 0
) {
const resp = await this.$axios.get("/platform/trainSingUp/manage/activity/getUnionLimit", {
const resp = await this.$axios.get("/platform/trainSingUp/manage/getUnionLimit", {
activityScopeId: this.formData.activityGroupId
})
if (resp.code === 0) {
@@ -212,7 +212,7 @@ layout("/layouts/platform.html"){
await this.doSearch()
},
async getActivityList() {
const resp = await this.$axios.post("/platform/trainSingUp/statistics/activity/activityList", { year: this.pageForm.year })
const resp = await this.$axios.post("/platform/trainSingUp/statistics/activityList", { year: this.pageForm.year })
this.activityList = resp.data
if (this.activityList && this.activityList.length > 0) {
this.pageForm.activityId = this.activityList[0].id
@@ -0,0 +1,144 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<style scoped>
.info-title {
font-weight: bold;
background-color: white;
padding: 13px;
box-shadow: 0 8px 12px #ebedf0;
text-align: center !important;
}
.info-container {
height: calc(100vh - 46px - 44px);
min-height: calc(100vh - 46px - 44px);
overflow-y: auto;
}
.info-img {
display: block;
}
.van-count-down {
color: #fff;
}
</style>
<div id="app">
<van-nav-bar title="品牌活动" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
<van-sticky offset-top="46px">
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
</van-sticky>
<table-list api="/platform/trainSingUp/apply/activityPageData"
:page_form.sync="pageForm"
ref="tableListRef"
title="activityName"
img="cover"
@ready="onReady"
>
<template v-slot="{index,row}">
<table-column label="面向对象">{{row.activityGroupName}}</table-column>
<table-column label="报名时间">
{{$moment(row.activitySignUpStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activitySignUpEndTime).format('MM/DD HH:mm')}}
</table-column>
<table-column label="活动时间">
{{$moment(row.activityStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activityEndTime).format('MM/DD HH:mm')}}
</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看介绍</span>
</div>
<div class="action-btn" @click="onApply(row)">
<i class="fa fa-edit"></i>
<span>去报名</span>
</div>
</template>
</table-list>
<van-popup v-model="infoVisible" position="right" :style="{ width: '100%', height: '100%' }">
<van-nav-bar title="详细信息" left-text="返回" left-arrow @click-left="infoVisible = false" fixed placeholder></van-nav-bar>
<div class="info-container">
<van-image class="info-img" height="186" width="100%" :src="infoRow.cover"></van-image>
<div class="info-title">{{infoRow.activityName}}</div>
<pdf-preview style="height: calc(100vh - 46px - 44px - 186px - 57px)" :content="infoRow.introduce"></pdf-preview>
</div>
<van-button @click="onApply(infoRow)" type="primary" block>
<span v-if="time >= 0">
去报名
</span>
<template v-else>
距离开始
<van-count-down :time="Math.abs(time)" class="count-down" format="DD 天 HH 时 mm 分 ss 秒" @finish="time = 0"></van-count-down>
</template>
</van-button>
</van-popup>
</div>
<script>
const vue = new Vue({
el: "#app",
store,
components: {
"pdf-preview": httpVueLoader("/components/plugins/sysFilePreview/PdfIndex.vue?v=" + new Date().getTime())
},
data() {
return {
time: 0,
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: '',
year: new Date().getFullYear(),
activityType: 2,
},
typeOptions: [
{text: '全部', value: 1},
{text: '即将开始', value: 4},
{text: '报名中', value: 2},
{text: '已结束', value: 3},
],
infoVisible: false,
infoRow: {},
}
},
methods: {
onView(row) {
this.infoRow = row
this.time = this.$moment().diff(this.$moment(row.activitySignUpStartTime), 'milliseconds')
this.infoVisible = true
},
onApply(row) {
if(this.$moment().isBefore(this.$moment(row.activitySignUpStartTime))) {
this.onView(row)
return
}
this.$pjaxReplace('/platform/trainSingUp/apply/list/h5?id=' + row.id)
},
onReady() {
this.doSearch()
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
}
},
})
</script>
<!--#
}
#-->
@@ -0,0 +1,89 @@
const times = {
template:
/*language=HTML*/
`
<div>
<van-action-sheet v-model="visible" title="时间段" cancel-text="取消">
<button v-for="(item,index) in row?.courseTimes" type="button" class="van-action-sheet__item">
<div style="display: flex; justify-content: space-between; align-items: center">
<div>
<div class="van-action-sheet__name">
<label>{{ weekdayCNMap[$moment(item.courseDate).day()] }}</label>
<label>{{ $moment(item.courseDate).format('YYYY-MM-DD') }}</label>
</div>
<div class="van-action-sheet__subname">
{{$moment(item.courseStartTime).format('MM-DD HH:mm') + ' 至 ' + $moment(item.courseEndTime).format('MM-DD HH:mm')}}
</div>
</div>
<div v-if="row.isSign === true && row.isMobileSign === true" class="sign_button">
<van-button v-if="item.isAttend !== true" @click.stop="onSign(item)" size="mini" type="info">签到</van-button>
<van-button v-if="item.isAttend === true" size="mini" type="info" disabled>已签到</van-button>
</div>
</div>
</button>
</van-action-sheet>
<van-popup round :safe-area-inset-bottom="true"
:close-on-click-overlay="false"
v-model="signVisible"
:style="{ width: '80%', height: '66%' }"
get-container="#app"
@close="onSignClose"
closeable
>
<scan-code ref="scanCodeRef"></scan-code>
</van-popup>
</div>
`,
store,
data() {
return {
visible:false,
row: null,
weekdayCNMap: {0: '周日', 1: '周一', 2: '周二', 3: '周三', 4: '周四', 5: '周五', 6: '周六'},
selectCourseTime: {},
signVisible: false,
}
},
components: {
"scan-code": httpVueLoader("/components/plugins/sysScanCode/index.vue?v=" + new Date().getTime())
},
methods: {
onSignClose() {
this.$refs.scanCodeRef.closeScan()
},
onOpen(row) {
this.row = row
this.visible = true
},
onSign(courseTime) {
this.selectCourseTime = courseTime
if(this.row.signType === 1) {
this.signVisible = true
this.$nextTick(() => {
this.$refs.scanCodeRef.init()
})
}
if(this.row.signType === 2) {
this.makeCode()
}
if(this.row.signType === 3) {
this.$toast('此签到模式正在升级中')
}
},
makeCode() {
const url = '/platform/trainSingUp/mine/passiveScan'
const data = url + '?id=' + this.selectCourseTime.id
console.log(data)
const content = jrQrcode.getQrBase64(data)
vant.ImagePreview([content])
},
onClose(){
this.visible = false
},
},
style: /*language=CSS*/ `
`
}
@@ -0,0 +1,156 @@
const applyForm = {
template:
/*language=HTML*/
`
<div>
<van-popup v-model="visible" position="right" :style="{ width: '100%', height: '100%', 'background-color': '#F7F8FA' }">
<van-nav-bar title="报名信息" left-text="返回" left-arrow @click-left="visible = false" fixed placeholder></van-nav-bar>
<van-form ref="formRef" class="form-container">
<van-cell-group title="活动信息" class="form-section">
<van-field label="活动名称" readonly v-model="row.courseName"></van-field>
<van-field label="校区" readonly v-model="row.campus"></van-field>
<van-field label="活动地点" readonly v-model="row.courseLocation"></van-field>
</van-cell-group>
<van-cell-group title="基础信息" class="form-section">
<van-field label="姓名" readonly v-model="formData.username"></van-field>
<van-field label="工号" readonly v-model="formData.loginname"></van-field>
<van-field label="所在单位" readonly v-model="formData.unitName"></van-field>
<van-field label="所属工会" readonly v-model="formData.unionName"></van-field>
<van-field label="性别" readonly v-model="formData.sex"></van-field>
<template v-if="row.courseIsLimitApply">
<van-field label="报名时段"
required
:rules="[{ required: true, message: '请选择报名时段' }]"
readonly
@click="showCoursePicker = true"
placeholder="请选择报名时段"
name="courseTimeName"
v-model="formData.courseTimeName">
</van-field>
<van-popup v-model="showCoursePicker" position="bottom">
<van-picker
show-toolbar
:columns="courseTimeSelectList"
@confirm="onCourseConfirm"
@cancel="showCoursePicker=false"
></van-picker>
</van-popup>
</template>
<train-dynamic-form v-model="dynamicColumnsData" ref="dynamicForm"></train-dynamic-form>
</van-cell-group>
<div class="form-actions">
<van-button @click="onSubmit" round type="info">提交</van-button>
</div>
</van-form>
</van-popup>
</div>
`,
data() {
return {
row: {},
activity: {},
dynamicColumnsData: [],
visible: false,
formData: {},
showCoursePicker: false,
courseTimeSelectList: [],
}
},
components: {
"train-dynamic-form": httpVueLoader("/components/module/trainSignUp/TrainDynamicForm.vue")
},
methods: {
async onOpen(row, course) {
this.row = row
this.init(row, course)
if(row.courseIsLimitApply) {
await this.getCourseTimeSelectList(row)
}
this.visible = true
},
init(row, course) {
this.$set(this.formData, 'username', this.$store.state.user.username)
this.$set(this.formData, 'loginname', this.$store.state.user.loginname)
this.$set(this.formData, 'unionName', this.$store.state.user.union.name)
this.$set(this.formData, 'unitName', this.$store.state.user.unit.name)
this.$set(this.formData, 'sex', this.$store.state.user.sex)
this.$set(this.formData, 'activityId', row.activityId)
this.$set(this.formData, 'courseId', row.id)
this.dynamicColumnsData = course ? course.trainMobileSignColumnList : []
this.dynamicColumnsData.forEach((item) => {
item.columnValue = this.$store.state.user[item.columnCode] || ""
})
},
onCourseConfirm(val){
this.formData.activityCourseId = val.value
this.$set(this.formData, "activityCourseId", val.value)
this.$set(this.formData, "courseTimeName", val.text.substring(0, 12))
this.showCoursePicker = false
},
async getCourseTimeSelectList(o) {
const resp = await this.$axios.post('/platform/trainSingUp/apply/getCourseTimeSelectList',{courseId: o.id})
if (resp.code === 0) {
this.courseTimeSelectList = resp.data
} else {
this.$toast.fail("获取时段信息失败,请联系管理员")
}
},
async validateSignUp() {
// 验证自定义表单
await this.$refs.dynamicForm.$refs.form.validate()
// 获取家属人数
let familyCount = this.dynamicColumnsData.filter(o => o.columnCode === 'xdqsrs').reduce((sum, item) => {
return sum + (Number(item.columnValue) || 0)
}, 0)
const res = await this.$axios.post("/platform/trainSingUp/apply/validateSignUp", {
courseId: this.formData.courseId,
currentFamilyNumber: familyCount
})
return res.code === 0
},
async validateCourseTime() {
const res = await this.$axios.post('/platform/trainSingUp/apply/validateSourceSignUp', {
activityCourseId: this.formData.activityCourseId,
courseId: this.row.id
})
return res.code === 0
},
async onSubmit() {
if(!await this.validateSignUp()) return
this.$refs.formRef.validate().then(() => {
this.$dialog.confirm({
title: "提示",
message: "您确定要提交吗?"
}).then(async () => {
if (this.row.courseIsLimitApply) {
if(!await this.validateCourseTime()) return
}
const mobileColumnsValue = this.dynamicColumnsData.map((v) => {
return {
columnName: v.columnName,
columnValue: v.columnValue,
columnCode: v.columnCode,
columnFormType: v.columnFormType
}
})
this.formData.mobileColumnsValue = JSON.stringify(mobileColumnsValue)
this.$axios.post("/platform/trainSingUp/apply/doSignUp", this.formData).then(res => {
if (res.code === 0) {
this.$toast(res.msg)
this.visible = false
this.$emit('refresh')
}
})
})
})
},
},
style: /*language=CSS*/ `
`
}
@@ -0,0 +1,222 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<style scoped>
.primary-color {
color: var(--color-primary);
}
.sign_button .van-button{
width: 66px;
height: 30px;
font-size: 14px;
border-radius: 6px;
}
</style>
<div id="app">
<van-nav-bar title="活动报名" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
<van-sticky offset-top="46px">
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<van-dropdown-item v-model="pageForm.courseTypeId" :options="typeOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
</van-sticky>
<table-list api="/platform/trainSingUp/apply/pageData"
:page_form.sync="pageForm"
ref="tableListRef"
@ready="onReady"
>
<template #header="{index,row}">
<div class="item-header">
<div class="item-title">{{ row.courseName }}</div>
<div v-html="calcSignUpCount(row)"></div>
</div>
</template>
<template v-slot="{index,row}">
<table-column label="类型">{{row.typeName}}</table-column>
<table-column label="地点">{{row.courseLocation}}</table-column>
<table-column label="联系人">{{row.courseInstructor}}</table-column>
<table-column label="时间">
<span v-if="row.courseTimes && row.courseTimes.length === 1">
{{ $moment(row.courseTimes[0].courseStartTime).format('HH:mm') + '~' + $moment(row.courseTimes[0].courseEndTime).format('HH:mm') }}
</span>
<span v-else @click="onTime(row)" class="primary-color">点我查看</span>
</table-column>
<table-column v-if="row.introduce" label="详细信息">
<span @click="introduceRow = row; introduceVisible = true" class="primary-color">点我查看</span>
</table-column>
</template>
<template #actions="{index,row}">
<div v-if="activity.wechat && row.isSign" class="action-btn" @click="this.vant.ImagePreview([activity.wechat])">
<i class="fa fa-wechat"></i>
<span>微信群二维码</span>
</div>
<template v-if="$moment().isBefore($moment(activity.activitySignUpEndTime))">
<div v-if="row.isSign === false" class="action-btn" @click="onApply(row)">
<i class="fa fa-sign-in"></i>
<span>我要报名</span>
</div>
<div v-if="row.isSign === true" class="action-btn delete" @click="onCancel(row)">
<i class="fa fa-trash"></i>
<span>取消报名</span>
</div>
</template>
<div v-if="row.isSign === true && row.isMobileSign === true && $moment().isAfter($moment(activity.activitySignUpEndTime))"
class="action-btn"
@click="onTime(row)"
>
<i class="fa fa-sign-in"></i>
<span>签到</span>
</div>
</template>
</table-list>
<van-popup v-model="introduceVisible" position="right" :style="{ width: '100%', height: '100%', 'background-color': '#F7F8FA' }">
<van-nav-bar title="详细信息" left-text="返回" left-arrow @click-left="introduceVisible = false" fixed placeholder></van-nav-bar>
<pdf-preview style="height: calc(100vh - 46px)" :content="introduceRow.introduce"></pdf-preview>
</van-popup>
<times ref="timesRef"></times>
<apply-form ref="formRef" @refresh="refresh"></apply-form>
</div>
<script src="${base!}/assets/platform/plugins/jr-qrcode/jr-qrcode.js"></script>
<script>
<!--#include('../common/times.js'){}#-->
<!--#include('applyForm.js'){}#-->
const vue = new Vue({
el: "#app",
store,
components: {
'times': times,
'apply-form': applyForm,
"pdf-preview": httpVueLoader("/components/plugins/sysFilePreview/PdfIndex.vue?v=" + new Date().getTime())
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: '',
year: new Date().getFullYear(),
courseTypeId: null,
activityId: GetQueryString('id'),
dataType: GetQueryString('dataType'),
},
typeOptions: [],
assortOptions: [],
sourceTypeOptions: [],
introduceVisible: false,
introduceRow: {},
activity: {},
}
},
methods: {
refresh() {
this.doSearch()
},
async onTime(row) {
// 如果设置签到,并且也报名的话
if(row.isMobileSign === true && row.isSign === true) {
const res = await this.$axios.post('/platform/trainSingUp/mine/queryCourseSign', {
courseId: row.id
})
row.courseTimes = res.data
}
this.$refs.timesRef.onOpen(row)
},
onApply(row) {
const course = this.sourceTypeOptions.find((v) => v.id === row.courseType)
this.$axios.post('/platform/trainSingUp/apply/validateSignUp', {
courseId: row.id
})
.then((res) => {
if (res.code !== 0) {
vant.Dialog.alert({
title: '提示',
message: res.msg,
confirmButtonColor: '#1867b0'
})
} else {
let lave = row.coursePeopleNumber - (row.hasRegisterNum + row.courseReservedNumber)
if(row.reserveMode === 2 && lave <= 0) {
vant.Dialog.alert({
title: '提示',
message: '您当前的报名为候补报名状态',
confirmButtonColor: '#1867b0'
})
}
this.$refs.formRef.onOpen(row, course)
}
})
},
onCancel(row) {
vant.Dialog.confirm({
title: '温馨提示',
message: "您确定要<span style='color: red'>取消【" + row.courseName + "】</span>吗?",
confirmButtonColor: '#1867b0',
}).then(async () => {
const resp = await this.$axios.post('/platform/trainSingUp/apply/cancelSignUp', {
activityId: row.activityId,
courseId: row.id
})
this.$toast(resp.msg)
if (resp.code === 0) {
this.doSearch()
}
}).catch(() => {})
},
calcSignUpCount(row) {
let lave = row.coursePeopleNumber - (row.hasRegisterNum + row.courseReservedNumber)
if(row.reserveMode === 2) {
let lave2 = row.waitingNum - row.hasWaitingNum
return "<span style='color: red'>余" + lave +"</span>/" + row.coursePeopleNumber + "人"
+ "<span style='color: red'>候补余" + lave2 + "</span>/" + row.waitingNum + "人"
} else {
return "<span style='color: red'>余" + lave +"</span>/" + row.coursePeopleNumber + "人"
}
},
async onReady() {
const typeList = await this.getCourseTypeList()
this.sourceTypeOptions = clone(typeList)
this.typeOptions = [
{
text: "全部类型",
value: null
}
].concat(typeList.map((v) => ({ text: v.typeName, value: v.id })))
if (this.typeOptions.length > 0) {
this.pageForm.type = this.typeOptions[0].value
this.doSearch()
}
this.fetchActivity()
},
fetchActivity() {
this.$axios.post('/platform/trainSingUp/manage/findOne', {id: this.pageForm.activityId})
.then((res) => {
this.activity = res.data
})
},
async getCourseTypeList() {
const resp = await this.$axios.post("/platform/trainSingUp/type/getAllType")
return resp.data
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
}
},
})
</script>
<!--#
}
#-->
@@ -0,0 +1,130 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<style scoped>
.info-title {
font-weight: bold;
background-color: white;
padding: 13px;
box-shadow: 0 8px 12px #ebedf0;
text-align: center !important;
}
.info-container {
height: calc(100vh - 46px - 44px);
min-height: calc(100vh - 46px - 44px);
overflow-y: auto;
}
.info-img {
display: block;
}
.van-count-down {
color: #fff;
}
</style>
<div id="app">
<van-nav-bar title="品牌活动-我的报名" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
<van-sticky offset-top="46px">
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false"
@change="doSearch"></van-dropdown-item>
</van-dropdown-menu>
</van-sticky>
<table-list api="/platform/trainSingUp/apply/activityPageData"
:page_form.sync="pageForm"
ref="tableListRef"
title="activityName"
img="cover"
@ready="onReady"
>
<template v-slot="{index,row}">
<table-column label="面向对象">{{row.activityGroupName}}</table-column>
<table-column label="报名时间">
{{$moment(row.activitySignUpStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activitySignUpEndTime).format('MM/DD HH:mm')}}
</table-column>
<table-column label="活动时间">
{{$moment(row.activityStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activityEndTime).format('MM/DD HH:mm')}}
</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
<i class="fa fa-eye"></i>
<span>查看介绍</span>
</div>
<div class="action-btn" @click="onApply(row)">
<i class="fa fa-edit"></i>
<span>查看</span>
</div>
</template>
</table-list>
<van-popup v-model="infoVisible" position="right" :style="{ width: '100%', height: '100%' }">
<van-nav-bar title="详细信息" left-text="返回" left-arrow @click-left="infoVisible = false" fixed placeholder></van-nav-bar>
<div class="info-container">
<van-image class="info-img" height="186" width="100%" :src="infoRow.cover"></van-image>
<div class="info-title">{{infoRow.activityName}}</div>
<pdf-preview style="height: calc(100vh - 46px - 44px - 186px - 57px)" :content="infoRow.introduce"></pdf-preview>
</div>
<van-button @click="onApply(infoRow)" type="primary" block>下一步</van-button>
</van-popup>
</div>
<script>
const vue = new Vue({
el: "#app",
store,
components: {
"pdf-preview": httpVueLoader("/components/plugins/sysFilePreview/PdfIndex.vue?v=" + new Date().getTime())
},
data() {
return {
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: '',
year: new Date().getFullYear(),
activityType: 1,
dataType: 'mine'
},
typeOptions: [
{text: '全部', value: 1},
{text: '报名中', value: 2},
{text: '已结束', value: 3},
],
infoVisible: false,
infoRow: {},
}
},
methods: {
onView(row) {
this.infoRow = row
this.infoVisible = true
},
onApply(row) {
this.$pjaxReplace('/platform/trainSingUp/apply/list/h5?id=' + row.id + '&dataType=mine')
},
onReady() {
this.doSearch()
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
}
},
})
</script>
<!--#
}
#-->
@@ -744,7 +744,7 @@ layout("/layouts/platform_h5.html"){
this.pageData()
},
async getAllType() {
const resp = await this.$axios.post("/platform/trainSingUp/manage/type/getAllType", {})
const resp = await this.$axios.post("/platform/trainSingUp/type/getAllType", {})
this.allColumnsData = resp.data
return resp.data
},