This commit is contained in:
zhouhefeng
2026-06-01 08:36:26 +08:00
parent f05e534e52
commit 8b47088953
47 changed files with 1733 additions and 301 deletions
@@ -0,0 +1,2 @@
ALTER TABLE `sys_home_template`
ADD COLUMN `templateFile` varchar(1000) DEFAULT NULL COMMENT 'template file' AFTER `templateIcon`;
@@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS `sys_home_template` (
`name` varchar(50) DEFAULT NULL COMMENT 'template name',
`templateName` varchar(50) DEFAULT NULL COMMENT 'display template name',
`templateIcon` varchar(255) DEFAULT NULL COMMENT 'template icon',
`templateFile` varchar(1000) DEFAULT NULL COMMENT 'template file',
`cover` varchar(255) DEFAULT NULL COMMENT 'template cover',
`content` text COMMENT 'template content',
`url` varchar(1000) DEFAULT NULL COMMENT 'pc url',
@@ -123,11 +123,17 @@
}
}
function historyBack(func) {
function historyBack(fallbackUrl, func) {
if (typeof fallbackUrl === "function") {
func = fallbackUrl
fallbackUrl = "/platform/h5/home"
} else if (typeof fallbackUrl !== "string" || !fallbackUrl) {
fallbackUrl = "/platform/h5/home"
}
if (window.history.length > 1) {
window.history.back()
} else {
window.location.href = "/platform/h5/home"
window.location.replace(fallbackUrl)
}
func && typeof func === "function" && func()
}
@@ -139,8 +145,8 @@
Vue.mixin({
methods: {
historyBack: function(func = function(){}) {
historyBack(func)
historyBack: function(fallbackUrl = "/platform/h5/home", func = function(){}) {
historyBack(fallbackUrl, func)
},
returnH5Home: function(activeTab = "home") {
returnH5Home(activeTab)
+23 -21
View File
@@ -1,7 +1,7 @@
const act = {
template: /*language=HTML*/ `
<!-- 活动 -->
<div class="section-wrapper">
<div class="activity-section-wrapper">
<div class="section-act">
<!-- Swiper容器 -->
@@ -77,8 +77,8 @@ const act = {
/*初始化Swiper*/
initSwiper() {
this.swiper = new Swiper('.activity-swiper', {
slidesPerView: 'auto',
spaceBetween: 30,
slidesPerView: 1,
spaceBetween: 18,
centeredSlides: false,
loop: false,
navigation: {
@@ -91,13 +91,13 @@ const act = {
},
breakpoints: {
768: {
slidesPerView: 1,
},
1024: {
slidesPerView: 2,
},
1024: {
slidesPerView: 4,
},
1200: {
slidesPerView: 3,
slidesPerView: 5,
}
}
})
@@ -131,7 +131,7 @@ const act = {
this.listAct()
},
style: /*language=CSS*/ `
.section-wrapper {
.activity-section-wrapper {
width: 100%;
}
@@ -176,7 +176,7 @@ const act = {
.activity-swiper-container {
position: relative;
width: 100%;
padding: 20px;
padding: 9px 14px;
/*margin-top: 30px;*/
}
@@ -217,7 +217,7 @@ const act = {
/* 进度条样式 */
.activity-swiper-container .swiper-pagination {
position: relative;
margin-top: 30px;
margin-top: 12px;
height: 4px;
}
@@ -239,8 +239,8 @@ const act = {
.activity-swiper .swiper-slide .item .img-box {
width: 100%;
height: 200px;
border-radius: 12px;
height: 128px;
border-radius: 8px;
overflow: hidden;
position: relative;
}
@@ -250,10 +250,12 @@ const act = {
left: 0;
top: 0;
background: #c11623;
padding: 6px 2px;
min-width: 50px;
padding: 4px 2px;
min-width: 42px;
color: #ffffff;
border-radius: 0 0 50% 0;
font-size: 12px;
line-height: 1.2;
}
@@ -269,16 +271,16 @@ const act = {
}
.activity-swiper .swiper-slide .item h4 {
font-size: 20px;
margin-top: 10px;
height: 60px;
font-size: 15px;
margin: 8px 0 0;
height: 42px;
color: #333;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.5;
line-height: 1.4;
text-align: left;
transition: color 0.3s ease;
}
@@ -292,14 +294,14 @@ const act = {
}
.activity-swiper .swiper-slide .item .time p {
font-size: 13px;
font-size: 12px;
margin: 0;
/*line-height: 1.5;*/
line-height: 1.4;
color: #666;
}
.activity-swiper .swiper-slide .item .time i {
margin-right: 5px;
margin-right: 4px;
color: var(--color-primary);
}
@@ -1,7 +1,7 @@
const entry = {
template: /*language=HTML*/ `
<div class="entry-wrapper">
<div class="entry-section" v-for="section in entrySections" :key="section.key">
<div :class="['entry-section', 'entry-section-' + section.key]" v-for="section in entrySections" :key="section.key">
<div class="entry-section-header">
<div class="entry-section-title">
<i :class="section.icon"></i>
@@ -126,6 +126,11 @@ const entry = {
margin-top: 22px;
}
/* 临时屏蔽“我的收藏”分组,保留原节点和数据逻辑便于恢复 */
.entry-section-fav {
display: none;
}
.entry-section-header {
display: flex;
align-items: center;
@@ -16,14 +16,8 @@ layout("/layouts/v4/baseLayout.html"){
.section-banner .banner-img img {
width: 100%;
/*height: 100%;*/
height: 470px;
object-fit: cover;
}
/* 临时屏蔽首页背景图,保留原图片节点便于恢复 */
.section-banner .banner-img > img {
display: none;
height: auto;
display: block;
}
.section-wrapper {
@@ -61,12 +55,44 @@ layout("/layouts/v4/baseLayout.html"){
align-items: center;
min-width: 320px;
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
padding: 16px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
padding: 11px;
transition: transform 0.2s, box-shadow 0.2s;
}
.home-section {
width: 100%;
}
.home-section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
}
.home-section-title {
display: inline-flex;
align-items: baseline;
gap: 6px;
color: #19324d;
font-size: 18px;
font-weight: 700;
}
.home-section-title i {
color: #409eff;
font-size: 16px;
}
.home-section-title em {
color: #b5c0d6;
font-size: 14px;
font-style: normal;
font-weight: 500;
}
</style>
<div class="v4-container" id="v4-home-app">
@@ -87,6 +113,21 @@ layout("/layouts/v4/baseLayout.html"){
</div>
</div>
<div class="home-grid">
<div class="home-section">
<div class="home-section-header">
<div class="home-section-title">
<i class="fa fa-calendar"></i>
<span>最新活动</span>
<em>/Activities</em>
</div>
</div>
<div class="act-card">
<act></act>
</div>
</div>
</div>
<work-template v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN'])"></work-template>
<jcdt :list="websiteNews"></jcdt>
@@ -126,6 +126,11 @@ const stats = {
/*border: 1px solid #e8e8e8;*/
}
/* 子内容临时屏蔽时,同步收起统计容器,避免首页 banner 下方出现空白 */
.stats-section {
display: none;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
@@ -135,6 +140,11 @@ const stats = {
margin-left: auto;
}
/* 临时屏蔽首页右上角“待办、已办、消息、发起”统计卡片,保留原模板便于恢复 */
.stats-grid {
display: none;
}
.stat-item {
background: #f8f9fa;
color: #495057;
@@ -138,20 +138,28 @@ const workTemplate = {
}
.work-template-icon {
width: 46px;
height: 46px;
width: 55px;
height: 55px;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.work-template-icon img {
width: 100%;
height: 100%;
object-fit: contain;
width: 55px !important;
height: 55px !important;
max-width: none;
max-height: none;
object-fit: cover;
border-radius: 8px;
}
.work-template-name {
min-height: 34px;
font-size: 12px;
font-size: 12px !important;
font-weight: 400;
color: #333;
line-height: 1.4;
word-break: break-word;
@@ -305,7 +305,7 @@ const user = {
.user-container {
width: 80%;
margin: 20px auto;
margin: 12px auto 20px;
display: grid;
grid-template-columns: 0.7fr 2.3fr;
gap: 24px;
@@ -92,12 +92,24 @@ layout("/layouts/platform.html"){
key="AppHomeImg"
style="--upload-width: 214px;--upload-height:64px"
:value.sync="formData.configValue"
:upload_number="10"
:upload_number="5"
upload_mode="image"
upload_result_category="interval"
upload_result_type="url"
></file-upload>
<span>最佳分辨率:2756 x 732,最多可上传 10 张,首页按上传顺序轮播</span>
<span>PC 首页轮播图,最佳分辨率:2756 x 732,最多可上传 5 张,首页按上传顺序轮播</span>
</template>
<template v-else-if="formData.configKey === 'H5AppHomeImg'">
<file-upload
key="H5AppHomeImg"
style="--upload-width: 214px;--upload-height:110px"
:value.sync="formData.configValue"
:upload_number="5"
upload_mode="image"
upload_result_category="interval"
upload_result_type="url"
></file-upload>
<span>移动端首页轮播图,建议分辨率:750 x 386,最多可上传 5 张,首页按上传顺序轮播</span>
</template>
<template v-else-if="formData.configKey === 'AppFeaturedActivityImg'">
<file-upload
@@ -24,6 +24,18 @@ layout("/layouts/platform.html"){
</el-input>
</template>
</el-table-column>
<el-table-column label="排序" prop="sortNo" width="120px" align="center">
<template slot-scope="scope">
<el-input-number
v-model="scope.row.sortNo"
size="mini"
:min="0"
:controls="false"
style="width: 80px"
@change="updateSortNo(scope.row)">
</el-input-number>
</template>
</el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="PC端链接" prop="url" show-overflow-tooltip></el-table-column>
<el-table-column label="模板图标" prop="templateIcon" width="120px" align="center">
@@ -40,13 +52,20 @@ layout("/layouts/platform.html"){
</file-upload>
</template>
</el-table-column>
<el-table-column label="是否置顶" prop="top" width="100px">
<el-table-column label="模板文件" prop="templateFile" width="170px" align="center">
<template slot-scope="scope">
<el-tag size="mini" v-if="scope.row.top" type="success"></el-tag>
<el-tag size="mini" v-else type="info"></el-tag>
<file-upload
class="template-file-upload"
:upload_number="1"
:value="scope.row.templateFile"
accept=".doc,.docx,.xls,.xlsx,.pdf,.ppt,.pptx,.jpg,.jpeg,.png"
upload_result_type="url"
upload_result_category="interval"
upload_mode="file"
@update:value="onTemplateFileChange(scope.row, $event)">
</file-upload>
</template>
</el-table-column>
<el-table-column label="关联类路径" prop="classPath" show-overflow-tooltip></el-table-column>
<el-table-column label="状态" prop="enable" width="80px">
<template slot-scope="scope">
<i v-if="!scope.row.enable" class="fa fa-circle text-danger ml5"></i>
@@ -57,8 +76,6 @@ layout("/layouts/platform.html"){
<template slot-scope="scope">
<el-link type="danger" size="mini" @click="disable(scope.row.id)" v-if="scope.row.enable">关闭</el-link>
<el-link type="primary" size="mini" @click="enable(scope.row.id)" v-if="!scope.row.enable">开启</el-link>
<el-link type="primary" size="mini" @click="topUp(scope.row.id)" v-if="!scope.row.top">置顶</el-link>
<el-link type="danger" size="mini" @click="cancelTopUp(scope.row.id)" v-if="scope.row.top">取消置顶</el-link>
</template>
</el-table-column>
</el-table>
@@ -84,6 +101,8 @@ layout("/layouts/platform.html"){
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
} else {
this.$message.error(resp.msg)
}
})
})
@@ -98,34 +117,8 @@ layout("/layouts/platform.html"){
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
}
})
})
},
topUp(id) {
this.$confirm("您确定要置顶吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
this.$axios.post(loc() + "/topUp", {id}).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
}
})
})
},
cancelTopUp(id) {
this.$confirm("您确定要取消置顶吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
this.$axios.post(loc() + "/cancelTopUp", {id}).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
} else {
this.$message.error(resp.msg)
}
})
})
@@ -142,6 +135,19 @@ layout("/layouts/platform.html"){
}
})
},
updateSortNo(row) {
this.$axios.post(loc() + "/updateSortNo", {
id: row.id,
sortNo: row.sortNo
}).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
} else {
this.$message.error(resp.msg)
}
})
},
onTemplateIconChange(row, templateIcon) {
if (templateIcon === undefined && !row.templateIcon) {
return
@@ -162,6 +168,27 @@ layout("/layouts/platform.html"){
}
})
})
},
onTemplateFileChange(row, templateFile) {
if (templateFile === undefined && !row.templateFile) {
return
}
row.templateFile = templateFile
this.updateTemplateFile(row)
},
updateTemplateFile(row) {
this.$nextTick(() => {
this.$axios.post(loc() + "/updateTemplateFile", {
id: row.id,
templateFile: row.templateFile
}).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
} else {
this.$message.error(resp.msg)
}
})
})
}
},
created() {
@@ -170,20 +197,24 @@ layout("/layouts/platform.html"){
})
</script>
<style>
.template-icon-upload {
.template-icon-upload,
.template-file-upload {
--upload-width: 48px;
--upload-height: 48px;
}
.template-icon-upload .el-upload-list--picture-card .el-upload-list__item,
.template-icon-upload .el-upload--picture-card {
.template-icon-upload .el-upload--picture-card,
.template-file-upload .el-upload-list--picture-card .el-upload-list__item,
.template-file-upload .el-upload--picture-card {
width: 48px !important;
height: 48px !important;
line-height: 48px !important;
margin: 0;
}
.template-icon-upload .el-upload--picture-card i {
.template-icon-upload .el-upload--picture-card i,
.template-file-upload .el-upload--picture-card i {
font-size: 18px;
}
</style>
@@ -523,9 +523,9 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
</el-tabs>
</el-form>
<el-row type="flex" justify="end" class="mt20">
<el-button type="primary" plain @click="onSave">保存</el-button>
<el-button type="primary" plain @click="onSave">{{ copyTemplateMode ? "另存为" : "保存" }}</el-button>
<template v-if="formData.isEnrollSystem">
<el-button type="primary" @click="onSubmit" v-if="!taskId">提交</el-button>
<el-button type="primary" @click="onSubmit" v-if="!taskId">{{ copyTemplateMode ? "新活动提交" : "提交" }}</el-button>
<el-button type="primary" @click="onFinishTask" v-else>提交</el-button>
</template>
@@ -581,6 +581,8 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
bizId: "",
taskId: "",
copyTemplateMode: false,
copyTemplateName: "",
activeName: "1",
pageForm: {
year: new Date().getFullYear() + ""
@@ -646,6 +648,81 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
const resp = await this.$axios.post("/platform/club/examine/apply/getClubsByRole")
return resp.data
},
buildSubmitData() {
const formData = JSON.parse(JSON.stringify(this.formData))
formData.activity_type = this.activity_type
const {time, applyTime2, plannedDate} = formData
if (applyTime2 && applyTime2.length) {
formData.applyStartTime = applyTime2[0]
formData.applyEndTime = applyTime2[1]
formData.applyTime2 = null
}
if (time && time.length) {
formData.startTime = formData.time[0]
formData.endTime = formData.time[1]
formData.time = null
}
if (plannedDate && plannedDate.length) {
formData.startPlannedDate = formData.plannedDate[0]
formData.endPlannedDate = formData.plannedDate[1]
formData.plannedDate = null
}
if (this.copyTemplateMode) {
this.cleanCopyTemplateData(formData)
}
return formData
},
cleanCopyTemplateData(data) {
data.id = null
data.auditId = null
data.state = null
data.instanceId = null
data.businessNo = null
data.taskId = null
data.startTaskId = null
data.isTemplate = false
data.createdBy = null
data.createdAt = null
data.updatedBy = null
data.updatedAt = null
data.delFlag = null
if (Array.isArray(data.tissuePersonList)) {
data.tissuePersonList = data.tissuePersonList.map((person) => {
person.id = null
person.tissueId = null
person.signId = null
person.signTime = null
person.applyDateTime = null
person.dynamicFormData = null
person.isSign = false
person.createdBy = null
person.createdAt = null
person.updatedBy = null
person.updatedAt = null
person.delFlag = null
return person
})
}
},
async setupCopyTemplateData(data) {
this.cleanCopyTemplateData(data)
this.bizId = ""
this.taskId = ""
data.activityCode = await this.generateActivityCode()
this.userData = Array.isArray(data.tissuePersonList) ? clone(data.tissuePersonList) : []
},
validateCopyTemplateName() {
if (!this.copyTemplateMode) {
return true
}
const currentName = (this.formData.name || "").trim()
const templateName = (this.copyTemplateName || "").trim()
if (currentName && templateName && currentName === templateName) {
this.$message.warning("请修改活动名称,不能与模板名称一致")
return false
}
return true
},
// 保存
onSave() {
if (!this.formData.projectTypeCode) {
@@ -656,29 +733,15 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
this.$message.error("请选择活动所属社团")
return
}
this.$confirm("您确定保存吗?", "提示", {
if (!this.validateCopyTemplateName()) {
return
}
this.$confirm(this.copyTemplateMode ? "您确定另存为新活动吗?" : "您确定保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const formData = JSON.parse(JSON.stringify(this.formData))
formData.activity_type = this.activity_type
const {time, applyTime2, plannedDate} = formData
if (applyTime2 && applyTime2.length) {
formData.applyStartTime = applyTime2[0]
formData.applyEndTime = applyTime2[1]
formData.applyTime2 = null
}
if (time && time.length) {
formData.startTime = formData.time[0]
formData.endTime = formData.time[1]
formData.time = null
}
if (plannedDate && plannedDate.length) {
formData.startPlannedDate = formData.plannedDate[0]
formData.endPlannedDate = formData.plannedDate[1]
formData.plannedDate = null
}
const formData = this.buildSubmitData()
this.$axios.post('/platform/activity/culture/applyActivity/save', {
data: JSON.stringify(formData),
userData: JSON.stringify(this.userData)
@@ -704,29 +767,15 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
onSubmit() {
this.$refs["addForm"].validate((valid) => {
if (valid) {
this.$confirm("您确定提交吗?", "提示", {
if (!this.validateCopyTemplateName()) {
return
}
this.$confirm(this.copyTemplateMode ? "您确定提交为新活动吗?" : "您确定提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const formData = JSON.parse(JSON.stringify(this.formData))
formData.activity_type = this.activity_type
const {time, applyTime2, plannedDate} = formData
if (applyTime2 && applyTime2.length) {
formData.applyStartTime = applyTime2[0]
formData.applyEndTime = applyTime2[1]
formData.applyTime2 = null
}
if (time && time.length) {
formData.startTime = formData.time[0]
formData.endTime = formData.time[1]
formData.time = null
}
if (plannedDate && plannedDate.length) {
formData.startPlannedDate = formData.plannedDate[0]
formData.endPlannedDate = formData.plannedDate[1]
formData.plannedDate = null
}
const formData = this.buildSubmitData()
this.$axios.post('/platform/activity/culture/applyActivity/submit', {
data: JSON.stringify(formData)
}).then(res => {
@@ -949,6 +998,9 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
return data
},
async init(id) {
if (!id && this.copyTemplateMode) {
return
}
this.formLoading = true
try {
if (id) {
@@ -1006,10 +1058,15 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
if (data.applyStartTime) data.applyTime2 = [data.applyStartTime, data.applyEndTime]
if (data.startTime) data.time = [data.startTime, data.endTime]
if (data.startPlannedDate) data.plannedDate = [data.startPlannedDate, data.endPlannedDate]
this.userData = clone(data.tissuePersonList)
data.unionUserNumberLimit = JSON.parse(data.unionUserNumberLimit)
if (data.undertakeUnitIds) data.undertakeUnitIds = JSON.parse(data.undertakeUnitIds)
if (data.hostUnitIds) data.hostUnitIds = JSON.parse(data.hostUnitIds)
if (this.copyTemplateMode) {
this.copyTemplateName = data.name
await this.setupCopyTemplateData(data)
} else {
this.userData = clone(data.tissuePersonList)
}
this.formData = data
if (!this.formData.unionUserNumberLimit) {
this.getUnionData().then((data) => {
@@ -1029,6 +1086,7 @@ const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
const mode = params.get("mode")
const id = params.get("id")
if (mode === "edit" && id) {
this.copyTemplateMode = true
this.openEdit({id})
}
}
@@ -1,5 +1,5 @@
<!--#include('courseTime.js'){}#-->
<!--#include('customForm.js'){}#-->
<!--#include("/platform/zhgh/activity/family/manage/courseTime.js"){}#-->
<!--#include("/platform/zhgh/activity/family/manage/customForm.js"){}#-->
const basicForm = {
template: /*language=HTML*/ `
<div>
@@ -290,8 +290,8 @@ const basicForm = {
<el-button @click="$emit('back')">取消</el-button>
<el-button v-if="step === 2" type="primary" @click="step = 1">上一步</el-button>
<el-button v-if="step === 1" type="primary" @click="step = 2">下一步</el-button>
<el-button type="primary" @click="onSave">保存</el-button>
<el-button type="primary" @click="onSubmit">提交</el-button>
<el-button type="primary" @click="onSave">{{ copyTemplateMode ? "另存为" : "保存" }}</el-button>
<el-button type="primary" @click="onSubmit">{{ copyTemplateMode ? "新活动提交" : "提交" }}</el-button>
</div>
<el-dialog :close-on-click-modal="false" :visible.sync="signUpDialog" title="设置报名限制" append-to-body>
@@ -326,6 +326,8 @@ const basicForm = {
return {
signUpDialog: false,
step: 1,
copyTemplateMode: false,
copyTemplateName: "",
formData: {
notice: false,
courseList: [
@@ -394,7 +396,7 @@ const basicForm = {
this.typeArray = [...uniqueMap.values(), ...withoutCode]
},
async validNumber(row, old) {
if (GetQueryString("id") === "") {
if (this.copyTemplateMode || GetQueryString("id") === "") {
if (row.courseReservedNumber > row.coursePeopleNumber && row.reserveMode === 1) {
this.$alert("预留人数不能大于" + this.activityType + "人数!", "提示", {
confirmButtonText: "确定"
@@ -503,6 +505,51 @@ const basicForm = {
this.formData = resp.data
this.typeChange(this.formData.trainType)
this.formData.id = ""
this.cleanCopyTemplateData(this.formData)
}
},
cleanCopyTemplateData(data) {
if (!data) {
return
}
data.id = null
data.isTemplate = false
data.createdBy = null
data.createdAt = null
data.updatedBy = null
data.updatedAt = null
data.delFlag = null
if (Array.isArray(data.typeLimits)) {
data.typeLimits = data.typeLimits.map((limit) => {
limit.id = null
limit.activityId = null
return limit
})
}
if (Array.isArray(data.courseList)) {
data.courseList = data.courseList.map((course) => {
course.id = null
course.activityId = null
course.hasRegisterNum = null
course.hasWaitingNum = null
course.isSign = false
course.canSignThisCourseType = null
course.createdBy = null
course.createdAt = null
course.updatedBy = null
course.updatedAt = null
course.delFlag = null
if (Array.isArray(course.courseTimeList)) {
course.courseTimeList = course.courseTimeList.map((courseTime) => {
courseTime.id = null
courseTime.activityId = null
courseTime.courseId = null
courseTime.hasRegisterNum = null
return courseTime
})
}
return course
})
}
},
typeChange(val) {
@@ -534,11 +581,17 @@ const basicForm = {
this.$message.warning("请输入活动名称")
return
}
await this.doHandle('保存')
if (!this.validateCopyTemplateName()) {
return
}
await this.doHandle(this.copyTemplateMode ? '另存为' : '保存')
},
onSubmit() {
this.$refs["form"].validate(async (valid, errMsg) => {
if (valid) {
if (!this.validateCopyTemplateName()) {
return
}
const courseValid = this.formData.courseList.some((v, i) => {
const basicValid = v.courseName && v.coursePeopleNumber && v.courseLocation && v.courseInstructor && v.courseType
const timeValid =
@@ -582,7 +635,7 @@ const basicForm = {
return
}
this.formData.isDisabled = false
await this.doHandle('提交')
await this.doHandle(this.copyTemplateMode ? '新活动提交' : '提交')
} else {
if(Object.keys(errMsg).length > 0) {
this.$message.warning(errMsg[Object.keys(errMsg)[0]][0].message)
@@ -592,8 +645,23 @@ const basicForm = {
}
})
},
validateCopyTemplateName() {
if (!this.copyTemplateMode) {
return true
}
const currentName = (this.formData.activityName || "").trim()
const templateName = (this.copyTemplateName || "").trim()
if (currentName && templateName && currentName === templateName) {
this.$message.warning("请修改活动名称,不能与模板名称一致")
return false
}
return true
},
async doHandle(type) {
const cloneData = clone(this.formData)
if (this.copyTemplateMode) {
this.cleanCopyTemplateData(cloneData)
}
cloneData.activitySignUpStartTime = cloneData.activitySignTime !== undefined ? cloneData.activitySignTime[0] : null
cloneData.activitySignUpEndTime = cloneData.activitySignTime !== undefined ? cloneData.activitySignTime[1] : null
cloneData.activityStartTime = cloneData.activityTime !== undefined ? cloneData.activityTime[0] : null
@@ -601,7 +669,7 @@ const basicForm = {
if (cloneData.activitySignUpStartTime !== undefined && cloneData.activitySignUpStartTime !== null) {
cloneData.year = new Date(cloneData.activitySignUpStartTime).getFullYear()
}
cloneData.typeLimits = JSON.stringify(this.formData.typeLimits)
cloneData.typeLimits = JSON.stringify(cloneData.typeLimits)
cloneData.courseList = JSON.stringify(cloneData.courseList)
const confirm = await this.$confirm("您确定要" + type + "吗?", "提示", {
confirmButtonText: "确定",
@@ -629,11 +697,16 @@ const basicForm = {
if (resp.code === 0) {
this.formData = resp.data
this.typeChange(this.formData.trainType)
if (this.copyTemplateMode) {
this.copyTemplateName = this.formData.activityName
this.cleanCopyTemplateData(this.formData)
}
if(this.formData.onlyKey) this.keyFocus()
}
}
},
async initData(row) {
async initData(row, copyTemplateMode = false) {
this.copyTemplateMode = copyTemplateMode
this.activityGroupList = await this.getActivityGroup()
this.historicalActList = await this.getHistoricalActList()
this.courseTypeList = await this.getAllType()
@@ -92,7 +92,13 @@ layout("/layouts/platform.html"){
<el-dropdown-item @click.native="makeCode(row)">签到二维码</el-dropdown-item>
<el-dropdown-item @click.native="onView(row)">查看</el-dropdown-item>
<el-dropdown-item @click.native="openEdit(row)">编辑</el-dropdown-item>
<el-dropdown-item @click.native="onDelete(row)">删除</el-dropdown-item>
<el-dropdown-item
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN']) && !row.isTemplate"
@click.native="setTemplate(row)">设为模板</el-dropdown-item>
<el-dropdown-item
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN']) && row.isTemplate"
@click.native="cancelTemplate(row)">取消模板</el-dropdown-item>
<el-dropdown-item :disabled="!!row.isTemplate" @click.native="onDelete(row)">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
@@ -190,14 +196,52 @@ layout("/layouts/platform.html"){
}
},
async onDelete(row) {
if (row.isTemplate) {
this.$message.warning("该活动已设为模板,请先取消模板后再删除")
return
}
this.$confirm("此操作将永久删除, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post(loc() + "/onDelete", { id: row.id })
this.$message.success(resp.msg)
this.doSearch()
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.$message.error(resp.msg)
}
}).catch(() => {})
},
async setTemplate(row) {
this.$confirm("确定将该活动设为工作模板吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post(loc() + "/setTemplate", { id: row.id })
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.$message.error(resp.msg)
}
}).catch(() => {})
},
async cancelTemplate(row) {
this.$confirm("确定取消该活动的工作模板吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post(loc() + "/cancelTemplate", { id: row.id })
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.$message.error(resp.msg)
}
}).catch(() => {})
},
},
@@ -0,0 +1,62 @@
<!--#
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>
<el-card shadow="never">
<basic-form ref="formRef" @back="back" @refresh="refresh"></basic-form>
</el-card>
</div>
<script nonce="${cspNonce!}">
<!--#include("/platform/zhgh/activity/family/manage/basicForm.js"){}#-->
new Vue({
el: "#app",
store,
dicts: ["USER_CAMPUS", "FAMILY_SIGNUP_TYPE"],
components: {
"basic-form": basicForm
},
methods: {
back() {
commonUtil.pjaxPush("/platform/family/manage")
},
refresh() {
},
initForm() {
const params = new URLSearchParams(window.location.search)
const mode = params.get("mode")
const id = params.get("id")
if (mode === "edit" && id) {
this.$refs.formRef.initData({id}, true)
} else {
this.$refs.formRef.initData()
}
}
},
mounted() {
this.$nextTick(() => {
this.initForm()
})
}
})
</script>
<!--#
}
#-->
@@ -604,6 +604,8 @@
planList: [],
events: [],
projectType: "",
copyTemplateMode: false,
copyTemplateName: "",
formRules: {
name: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
address: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
@@ -889,7 +891,7 @@
this.eventForm.checkedEventId = this.checkedEvents[0].id
this.projectType = this.checkedEvents[0].projectType
if (!formData.id || this.checkedEventInfo.length <= 0) {
if ((!formData.id && !this.copyTemplateMode) || this.checkedEventInfo.length <= 0) {
this.eventForm = {
checkedEventId: this.checkedEvents[0].id,
leanderNum: 0,
@@ -937,6 +939,8 @@
this.activityGroupList = data
},
async openAdd() {
this.copyTemplateMode = false
this.copyTemplateName = ""
this.events = await this.getEvents(2)
await this.getActivityGroup()
this.active = 0
@@ -964,9 +968,58 @@
const resp = await this.$axios.post("/platform/club/examine/apply/getClubsByRole")
return resp.data
},
async openEdit(row, flag) {
cleanCopyTemplateData(formData, events) {
if (formData) {
formData.id = null
formData.isTemplate = false
formData.createdBy = null
formData.createdAt = null
formData.updatedBy = null
formData.updatedAt = null
formData.delFlag = null
formData.foundDate = null
}
if (Array.isArray(events)) {
events.forEach((event) => {
if (event.id !== "allItems") {
event.id = null
}
event.activityId = null
event.createdBy = null
event.createdAt = null
event.updatedBy = null
event.updatedAt = null
event.delFlag = null
})
}
},
async setupCopyTemplateData(formData, events) {
this.cleanCopyTemplateData(formData, events)
if (formData && formData.activityLevel) {
const activityCode = await this.getActivityCode(formData.activityLevel)
this.$set(formData, "activityCode", activityCode)
}
this.eventsIds = []
this.checkedEvents = this.events.filter((event) => formData.eventsIds.some((id) => id === event.id))
if (this.checkedEvents.length > 0) {
await this.eventChange(this.checkedEvents[0].id)
}
},
validateCopyTemplateName() {
if (!this.copyTemplateMode) {
return true
}
const currentName = (this.formData.name || "").trim()
const templateName = (this.copyTemplateName || "").trim()
if (currentName && templateName && currentName === templateName) {
this.$message.warning("请修改活动名称,不能与模板名称一致")
return false
}
return true
},
async openEdit(row, flag, copyTemplateMode = false) {
this.copyTemplateMode = !!copyTemplateMode
this.active = flag ? 0 : this.active
await this.applyTypeChange(row.applyType)
await this.getActivityGroup()
const { id } = row
this.$set(row, "loading", true)
@@ -985,10 +1038,17 @@
v.unitSponsor = JSON.parse(v.unitSponsor)
v.undertakeUnit = JSON.parse(v.undertakeUnit)
v.unitJointly = JSON.parse(v.unitJointly)
v.applyType = parseInt(v.applyType)
v.activityGroupId = parseInt(v.activityGroupId)
v.activityLevel = parseInt(v.activityLevel)
const applyType = row.applyType ? parseInt(row.applyType) : v.applyType
await this.applyTypeChange(isNaN(applyType) ? v.applyType : applyType)
this.formData = clone(v)
this.checkedEventInfo = clone(v.schoolEvents)
if (this.copyTemplateMode) {
this.copyTemplateName = this.formData.name
await this.setupCopyTemplateData(this.formData, this.checkedEventInfo)
}
this.checkedEventInfo.map((v) => {
/*if (v.unionLimit) {
v.unionLimit = JSON.parse(v.unionLimit)
@@ -1014,9 +1074,15 @@
}
},
async doOperate() {
const method = this.formData.id ? "/doEdit" : "/doAdd"
if (!this.validateCopyTemplateName()) {
return
}
const method = this.copyTemplateMode || !this.formData.id ? "/doAdd" : "/doEdit"
const formData = clone(this.formData)
const events = clone(this.checkedEventInfo)
if (this.copyTemplateMode) {
this.cleanCopyTemplateData(formData, events)
}
formData.restrictMaxNum = formData.leanderNum + formData.coachNum + formData.athletesMaxNum + formData.substituteNum
formData.restrictMinNum = formData.athletesMaxNum
@@ -1035,6 +1101,7 @@
events: JSON.stringify(events)
})
if (resp.code === 0) {
this.copyTemplateMode = false
this.$emit("flip")
} else {
this.$notify.error({ title: "错误", message: resp.msg })
@@ -1042,6 +1109,10 @@
loading.close()
},
async operate() {
if (this.copyTemplateMode) {
await this.doOperate()
return
}
const deleteEventIds = this.eventsIds.filter((v) => !this.formData.eventsIds.includes(v))
const { data } = await $.get("/platform/activity/sports/info/mange/getEventApply", {
activityId: this.formData.id,
@@ -1061,7 +1132,10 @@
}
},
async doSave() {
let url = this.formData.id ? "/doEdit" : "/doAdd"
if (!this.validateCopyTemplateName()) {
return
}
let url = this.copyTemplateMode || !this.formData.id ? "/doAdd" : "/doEdit"
this.checkedEventInfo.forEach((v) => {
if (this.eventForm.projectType === "1" && this.eventForm.eventId === "eventId") {
@@ -1080,6 +1154,9 @@
let events = clone(this.checkedEventInfo)
const formData = clone(this.formData)
if (this.copyTemplateMode) {
this.cleanCopyTemplateData(formData, events)
}
formData.restrictMaxNum = formData.leanderNum + formData.coachNum + formData.athletesMaxNum + formData.substituteNum
formData.restrictMinNum = formData.athletesMaxNum
formData.isSave = true
@@ -1107,6 +1184,9 @@
this.$set(this.eventForm, "endAgeDate", this.eventForm.ageDate[1])
}
events = this.eventForm
if (this.copyTemplateMode) {
this.cleanCopyTemplateData(null, [events])
}
}
const loading = this.$loading({
lock: true,
@@ -1121,7 +1201,10 @@
})
if (resp.code === 0) {
this.$emit("flush")
if (!this.formData.id) formData.id = resp.data
if (this.copyTemplateMode || !this.formData.id) {
formData.id = resp.data
this.copyTemplateMode = false
}
await this.openEdit(formData, false)
this.$message.success(resp.msg)
} else {
@@ -85,7 +85,15 @@ layout("/layouts/platform.html"){
<el-dropdown-item :command="{type:'view',row}">查看</el-dropdown-item>
<el-dropdown-item :command="{type:'exportXlsx',row}">导出名单</el-dropdown-item>
<el-dropdown-item :command="{type:'edit',row}">编辑</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',row}">删除</el-dropdown-item>
<el-dropdown-item
:command="{type:'setTemplate',row}"
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN']) && !row.isTemplate"
>设为模板</el-dropdown-item>
<el-dropdown-item
:command="{type:'cancelTemplate',row}"
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN']) && row.isTemplate"
>取消模板</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',row}" :disabled="!!row.isTemplate">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
@@ -158,6 +166,10 @@ layout("/layouts/platform.html"){
this.openEdit(row)
} else if (type === "delete") {
this.doDelete(row)
} else if (type === "setTemplate") {
this.setTemplate(row)
} else if (type === "cancelTemplate") {
this.cancelTemplate(row)
} else if (type === "exportXlsx") {
window.open("/platform/activity/sports/info/mange/exportXlsx?id=" + row.id)
}
@@ -176,6 +188,10 @@ layout("/layouts/platform.html"){
},
doDelete(row) {
const { id } = row
if (row.isTemplate) {
this.$message.warning("该活动已设为模板,请先取消模板后再删除")
return
}
this.$confirm("确定要删除该活动吗?", "提示", { type: "warning" }).then(async () => {
this.$set(row, "loading", true)
const resp = await this.$axios.post(loc() + "/doDelete", { id })
@@ -188,6 +204,38 @@ layout("/layouts/platform.html"){
}
})
},
async setTemplate(row) {
try {
await this.$confirm("确定将该活动设为工作模板吗?", "提示", { type: "warning" })
this.$set(row, "loading", true)
const resp = await this.$axios.post(loc() + "/setTemplate", { id: row.id })
this.$set(row, "loading", false)
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.notifyWarning(resp.msg)
}
} catch (e) {
this.$set(row, "loading", false)
}
},
async cancelTemplate(row) {
try {
await this.$confirm("确定取消该工作模板吗?", "提示", { type: "warning" })
this.$set(row, "loading", true)
const resp = await this.$axios.post(loc() + "/cancelTemplate", { id: row.id })
this.$set(row, "loading", false)
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.notifyWarning(resp.msg)
}
} catch (e) {
this.$set(row, "loading", false)
}
},
async doOperate() {
await this.$refs.addActivity.operate()
},
@@ -6,8 +6,8 @@ layout("/layouts/platform.html"){
<el-card shadow="never">
<div slot="header">
<div class="sports-new-actions">
<el-button @click="doSave" type="primary">保 存</el-button>
<el-button @click="doOperate" type="primary">提 交</el-button>
<el-button @click="doSave" type="primary">{{ copyTemplateMode ? "另存为" : "保 存" }}</el-button>
<el-button @click="doOperate" type="primary">{{ copyTemplateMode ? "新活动提交" : "提 交" }}</el-button>
<!--<el-button @click="back">返 回</el-button>-->
</div>
</div>
@@ -31,6 +31,11 @@ layout("/layouts/platform.html"){
components: {
"add-activity": ACTIVITY_SPORTS_ADD_ACTIVITY
},
data() {
return {
copyTemplateMode: false
}
},
methods: {
back() {
commonUtil.pjaxPush("/platform/activity/sports/info/mange")
@@ -42,15 +47,19 @@ layout("/layouts/platform.html"){
},
async doOperate() {
await this.$refs.addActivity.operate()
this.copyTemplateMode = this.$refs.addActivity.copyTemplateMode
},
async doSave() {
await this.$refs.addActivity.doSave()
this.copyTemplateMode = this.$refs.addActivity.copyTemplateMode
},
initForm() {
const mode = GetQueryString("mode")
const id = GetQueryString("id")
if (mode === "edit" && id) {
this.$refs.addActivity.openEdit({id}, true)
const applyType = GetQueryString("applyType")
this.copyTemplateMode = mode === "edit" && !!id
if (this.copyTemplateMode) {
this.$refs.addActivity.openEdit({id, applyType}, true, true)
} else {
this.$refs.addActivity.openAdd()
}
@@ -42,7 +42,7 @@ layout("/layouts/platform.html"){
const mode = GetQueryString("mode")
const id = GetQueryString("id")
const row = mode === "edit" && id ? {id} : undefined
this.$refs.formRef.initData(row)
this.$refs.formRef.initData(row, mode === "edit" && !!id)
}
},
mounted() {
@@ -287,8 +287,8 @@ const basicForm = {
<el-button @click="$emit('back')">取消</el-button>
<el-button v-if="step === 2" type="primary" @click="step = 1">上一步</el-button>
<el-button v-if="step === 1" type="primary" @click="step = 2">下一步</el-button>
<el-button type="primary" @click="onSave">保存</el-button>
<el-button type="primary" @click="onSubmit">提交</el-button>
<el-button type="primary" @click="onSave">{{ copyTemplateMode ? "另存为" : "保存" }}</el-button>
<el-button type="primary" @click="onSubmit">{{ copyTemplateMode ? "新活动提交" : "提交" }}</el-button>
</div>
<el-dialog :close-on-click-modal="false" :visible.sync="signUpDialog" title="设置报名限制" append-to-body>
@@ -323,6 +323,8 @@ const basicForm = {
return {
signUpDialog: false,
step: 1,
copyTemplateMode: false,
copyTemplateName: "",
formData: {
notice: false,
courseList: [
@@ -359,7 +361,7 @@ const basicForm = {
},
methods: {
async validNumber(row, old) {
if (GetQueryString("id") === "") {
if (this.copyTemplateMode || GetQueryString("id") === "") {
if (row.courseReservedNumber > row.coursePeopleNumber && row.reserveMode === 1) {
this.$alert("预留人数不能大于" + this.trainType + "人数!", "提示", {
confirmButtonText: "确定"
@@ -468,6 +470,51 @@ const basicForm = {
this.formData = resp.data
this.typeChange(this.formData.trainType)
this.formData.id = ""
this.cleanCopyTemplateData(this.formData)
}
},
cleanCopyTemplateData(data) {
if (!data) {
return
}
data.id = null
data.isTemplate = false
data.createdBy = null
data.createdAt = null
data.updatedBy = null
data.updatedAt = null
data.delFlag = null
if (Array.isArray(data.typeLimits)) {
data.typeLimits = data.typeLimits.map((limit) => {
limit.id = null
limit.activityId = null
return limit
})
}
if (Array.isArray(data.courseList)) {
data.courseList = data.courseList.map((course) => {
course.id = null
course.activityId = null
course.hasRegisterNum = null
course.hasWaitingNum = null
course.isSign = false
course.canSignThisCourseType = null
course.createdBy = null
course.createdAt = null
course.updatedBy = null
course.updatedAt = null
course.delFlag = null
if (Array.isArray(course.courseTimeList)) {
course.courseTimeList = course.courseTimeList.map((courseTime) => {
courseTime.id = null
courseTime.activityId = null
courseTime.courseId = null
courseTime.hasRegisterNum = null
return courseTime
})
}
return course
})
}
},
typeChange(val) {
@@ -499,11 +546,17 @@ const basicForm = {
this.$message.warning("请输入活动名称")
return
}
await this.doHandle('保存')
if (!this.validateCopyTemplateName()) {
return
}
await this.doHandle(this.copyTemplateMode ? '另存为' : '保存')
},
onSubmit() {
this.$refs["form"].validate(async (valid, errMsg) => {
if (valid) {
if (!this.validateCopyTemplateName()) {
return
}
const courseValid = this.formData.courseList.some((v, i) => {
const basicValid = v.courseName && v.coursePeopleNumber && v.courseLocation && v.courseInstructor && v.courseType
const timeValid =
@@ -535,7 +588,7 @@ const basicForm = {
return
}
this.formData.isDisabled = false
await this.doHandle('提交')
await this.doHandle(this.copyTemplateMode ? '新活动提交' : '提交')
} else {
if(Object.keys(errMsg).length > 0) {
this.$message.warning(errMsg[Object.keys(errMsg)[0]][0].message)
@@ -545,8 +598,23 @@ const basicForm = {
}
})
},
validateCopyTemplateName() {
if (!this.copyTemplateMode) {
return true
}
const currentName = (this.formData.activityName || "").trim()
const templateName = (this.copyTemplateName || "").trim()
if (currentName && templateName && currentName === templateName) {
this.$message.warning("请修改活动名称,不能与模板名称一致")
return false
}
return true
},
async doHandle(type) {
const cloneData = clone(this.formData)
if (this.copyTemplateMode) {
this.cleanCopyTemplateData(cloneData)
}
cloneData.activitySignUpStartTime = cloneData.activitySignTime !== undefined ? cloneData.activitySignTime[0] : null
cloneData.activitySignUpEndTime = cloneData.activitySignTime !== undefined ? cloneData.activitySignTime[1] : null
cloneData.activityStartTime = cloneData.activityTime !== undefined ? cloneData.activityTime[0] : null
@@ -554,7 +622,7 @@ const basicForm = {
if (cloneData.activitySignUpStartTime !== undefined && cloneData.activitySignUpStartTime !== null) {
cloneData.year = new Date(cloneData.activitySignUpStartTime).getFullYear()
}
cloneData.typeLimits = JSON.stringify(this.formData.typeLimits)
cloneData.typeLimits = JSON.stringify(cloneData.typeLimits)
cloneData.courseList = JSON.stringify(cloneData.courseList)
cloneData.hostUnits = JSON.stringify(cloneData.hostUnits)
cloneData.helpUnits = JSON.stringify(cloneData.helpUnits)
@@ -584,10 +652,15 @@ const basicForm = {
if (resp.code === 0) {
this.formData = resp.data
this.typeChange(this.formData.trainType)
if (this.copyTemplateMode) {
this.copyTemplateName = this.formData.activityName
this.cleanCopyTemplateData(this.formData)
}
}
}
},
async initData(row) {
async initData(row, copyTemplateMode = false) {
this.copyTemplateMode = copyTemplateMode
this.activityGroupList = await this.getActivityGroup()
this.historicalActList = await this.getHistoricalActList()
this.courseTypeList = await this.getAllType()
@@ -48,11 +48,27 @@ layout("/layouts/platform.html"){
></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="300">
<el-table-column align="center" header-align="center" label="操作" width="150">
<template slot-scope="scope">
<el-button size="mini" type="primary" @click="sendNotice(scope.row.id)">发送通知</el-button>
<el-button size="mini" type="primary" @click="openEdit(scope.row.id)">编辑</el-button>
<el-button size="mini" type="danger" @click="doDelete(scope.row.id)">删除</el-button>
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'sendNotice',row:scope.row}">发送通知</el-dropdown-item>
<el-dropdown-item :command="{type:'edit',row:scope.row}">编辑</el-dropdown-item>
<el-dropdown-item
:command="{type:'setTemplate',row:scope.row}"
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN']) && !scope.row.isTemplate"
>设为模板</el-dropdown-item>
<el-dropdown-item
:command="{type:'cancelTemplate',row:scope.row}"
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN']) && scope.row.isTemplate"
>取消模板</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',row:scope.row}" :disabled="!!scope.row.isTemplate">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
@@ -61,6 +77,7 @@ layout("/layouts/platform.html"){
</template>
<template #edit>
<div v-if="formVisible">
<el-form :model="formData" ref="formRef" label-width="130px" :rules="formRules">
<el-form-item label="活动主题" prop="name">
<el-input placeholder="请输入活动主题" v-model="formData.name" clearable></el-input>
@@ -232,16 +249,17 @@ layout("/layouts/platform.html"){
</el-form>
<el-row class="mt20" justify="end" type="flex">
<el-button @click="close">取消</el-button>
<el-button type="primary" v-if="formData.isSubmit!=true" plain @click="doSave">保存</el-button>
<el-button type="primary" @click="doSubmit">确定</el-button>
<el-button type="primary" v-if="copyTemplateMode || formData.isSubmit!=true" plain @click="doSave">{{ copyTemplateMode ? "另存为" : "保存" }}</el-button>
<el-button type="primary" @click="doSubmit">{{ copyTemplateMode ? "新活动提交" : "确定" }}</el-button>
</el-row>
</div>
</template>
</guava>
<drawer-user-scope :group_id.sync="formData.activityGroupId" @group_change="getActivityGroup"
<drawer-user-scope v-if="formVisible" :group_id.sync="formData.activityGroupId" @group_change="getActivityGroup"
ref="drawerUserScope"></drawer-user-scope>
<el-dialog :close-on-click-modal="false" :visible.sync="settingDialogVisible" title="更多设置" top="4%" width="40%">
<el-dialog v-if="formVisible" :close-on-click-modal="false" :visible.sync="settingDialogVisible" title="更多设置" top="4%" width="40%">
<el-form :model="currentWorksType" label-width="160px" size="small">
<el-form-item label="作品介绍最多字数">
<el-input-number :max="10000" :min="1" style="width: 100%"
@@ -361,6 +379,11 @@ layout("/layouts/platform.html"){
activityTime: []
},
formVisible: false,
copyTemplateMode: false,
copyTemplateName: "",
formOptionsLoaded: false,
formOptionsPromise: null,
unitOptions: [],
clubOptions: [],
}
@@ -378,10 +401,73 @@ layout("/layouts/platform.html"){
}
},
methods: {
isNewPage() {
return window.location.pathname.toLowerCase() === "/platform/activity/workscollection/new"
},
backToManage() {
commonUtil.pjaxPush("/platform/activity/worksCollection/manage")
},
afterSaveSuccess() {
this.formVisible = false
if (this.isNewPage()) {
this.backToManage()
} else {
this.doSearch()
this.$refs.guava.index()
}
},
initNewPage() {
const params = new URLSearchParams(window.location.search)
const mode = params.get("mode")
const id = params.get("id")
if (mode === "edit" && id) {
this.openEdit(id, true)
} else {
this.openAdd()
}
},
async getActivityGroup() {
const {data} = await this.$axios.post("/platform/activity/basic/scope/getActivityUserScopeGroup")
return data
},
dropdownCommand(command) {
const {type, row} = command
if (type === "sendNotice") {
this.sendNotice(row.id)
} else if (type === "edit") {
this.openEdit(row.id)
} else if (type === "setTemplate") {
this.setTemplate(row)
} else if (type === "cancelTemplate") {
this.cancelTemplate(row)
} else if (type === "delete") {
this.doDelete(row.id)
}
},
async loadFormOptions() {
if (this.formOptionsLoaded) {
return
}
if (this.formOptionsPromise) {
return this.formOptionsPromise
}
this.formOptionsPromise = Promise.all([
this.getActivityGroup(),
this.getClubsByRole(),
this.$businessTool.listUnit()
]).then(([activityGroupList, clubOptions, units]) => {
this.activityGroupList = activityGroupList
this.clubOptions = clubOptions
this.clubOptions.map((v) => {
v.name = v.clubName
})
this.unitOptions = this.clubOptions.concat(units)
this.formOptionsLoaded = true
}).finally(() => {
this.formOptionsPromise = null
})
return this.formOptionsPromise
},
addType(index) {
let item = {}
this.initData(item)
@@ -410,7 +496,11 @@ layout("/layouts/platform.html"){
this.$set(worksType, "allowFileTypes", worksType.allowFileTypes ? worksType.allowFileTypes : [])
},
openAdd() {
async openAdd() {
this.copyTemplateMode = false
this.copyTemplateName = ""
await this.loadFormOptions()
this.formVisible = true
this.$refs.guava.edit()
this.$nextTick(() => {
this.formData = {
@@ -422,9 +512,80 @@ layout("/layouts/platform.html"){
this.initData(this.formData.subjectTypes[0].worksTypes[0])
})
},
async openEdit(id) {
const resp = await this.$axios.post(loc() + "/findOne", {id})
cleanCopyTemplateData(data) {
if (!data) {
return
}
data.id = null
data.isTemplate = false
data.createdBy = null
data.createdAt = null
data.updatedBy = null
data.updatedAt = null
data.delFlag = null
if (Array.isArray(data.subjectTypes)) {
data.subjectTypes = data.subjectTypes.map((subjectType) => {
subjectType.id = null
subjectType.activityId = null
subjectType.createdBy = null
subjectType.createdAt = null
subjectType.updatedBy = null
subjectType.updatedAt = null
subjectType.delFlag = null
if (Array.isArray(subjectType.worksTypes)) {
subjectType.worksTypes = subjectType.worksTypes.map((worksType) => {
worksType.id = null
worksType.subjectId = null
worksType.createdBy = null
worksType.createdAt = null
worksType.updatedBy = null
worksType.updatedAt = null
worksType.delFlag = null
return worksType
})
}
return subjectType
})
}
},
validateCopyTemplateName() {
if (!this.copyTemplateMode) {
return true
}
const currentName = (this.formData.name || "").trim()
const templateName = (this.copyTemplateName || "").trim()
if (currentName && templateName && currentName === templateName) {
this.$message.warning("请修改活动名称,不能与模板名称一致")
return false
}
return true
},
buildSubmitData() {
const data = clone(this.formData)
data.startDateTime = data.activityTime[0]
data.endDateTime = data.activityTime[1]
data.nbStartDateTime = data.nbTime ? data.nbTime[0] : null
data.nbEndDateTime = data.nbTime ? data.nbTime[1] : null
data.type = "1"
if (this.copyTemplateMode) {
this.cleanCopyTemplateData(data)
}
return data
},
async openEdit(id, copyTemplateMode = false) {
this.copyTemplateMode = !!copyTemplateMode
const [resp] = await Promise.all([
this.$axios.post("/platform/activity/worksCollection/manage/findOne", {id}),
this.loadFormOptions()
])
this.formVisible = true
this.formData = resp.data
if (this.copyTemplateMode) {
this.copyTemplateName = this.formData.name
this.cleanCopyTemplateData(this.formData)
} else {
this.copyTemplateName = ""
}
this.$set(this.formData, "activityTime", [this.formData.startDateTime, this.formData.endDateTime])
// this.formData.activityTime = [this.formData.startDateTime, this.formData.endDateTime]
if (this.formData.nbStartDateTime && this.formData.nbEndDateTime) {
@@ -436,27 +597,30 @@ layout("/layouts/platform.html"){
})
},
close() {
this.$refs.guava.index()
this.formVisible = false
if (this.isNewPage()) {
this.backToManage()
} else {
this.$refs.guava.index()
}
},
doSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.formData.startDateTime = this.formData.activityTime[0]
this.formData.endDateTime = this.formData.activityTime[1]
this.formData.nbStartDateTime = this.formData.nbTime[0]
this.formData.nbEndDateTime = this.formData.nbTime[1]
this.formData.type = "1"
if (!this.validateCopyTemplateName()) {
return
}
const submitData = this.buildSubmitData()
let loading = this.$loading({
lock: true,
text: "数据正在提交中,请稍后...",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)"
})
this.$axios.post(loc() + (this.formData.id ? "/update" : "/insert"), {data: JSON.stringify(this.formData)}).then((res) => {
this.$axios.post("/platform/activity/worksCollection/manage" + (this.copyTemplateMode || !this.formData.id ? "/insert" : "/update"), {data: JSON.stringify(submitData)}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
this.$refs.guava.index()
this.afterSaveSuccess()
} else {
this.$message.warning(res.msg)
}
@@ -466,22 +630,20 @@ layout("/layouts/platform.html"){
})
},
doSave() {
this.formData.startDateTime = this.formData.activityTime[0]
this.formData.endDateTime = this.formData.activityTime[1]
this.formData.nbStartDateTime = this.formData.nbTime[0]
this.formData.nbEndDateTime = this.formData.nbTime[1]
this.formData.type = "1"
if (!this.validateCopyTemplateName()) {
return
}
const submitData = this.buildSubmitData()
let loading = this.$loading({
lock: true,
text: "数据正在保存中,请稍后...",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)"
})
this.$axios.post("/platform/activity/worksCollection/manage" + (this.formData.id ? "/update" : "/insert"), {data: JSON.stringify(this.formData)}).then((res) => {
this.$axios.post("/platform/activity/worksCollection/manage" + (this.copyTemplateMode || !this.formData.id ? "/save" : "/update"), {data: JSON.stringify(submitData)}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
this.$refs.guava.index()
this.afterSaveSuccess()
} else {
this.$message.warning(res.msg)
}
@@ -489,6 +651,11 @@ layout("/layouts/platform.html"){
})
},
doDelete(id) {
const row = this.tableData.find((item) => item.id === id)
if (row && row.isTemplate) {
this.$message.warning("该活动已设为模板,请先取消模板后再删除")
return
}
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
@@ -502,6 +669,32 @@ layout("/layouts/platform.html"){
})
})
},
async setTemplate(row) {
try {
await this.$confirm("确定将该活动设为工作模板吗?", "提示", {type: "warning"})
const resp = await this.$axios.post(loc() + "/setTemplate", {id: row.id})
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.$message.warning(resp.msg)
}
} catch (e) {
}
},
async cancelTemplate(row) {
try {
await this.$confirm("确定取消该工作模板吗?", "提示", {type: "warning"})
const resp = await this.$axios.post(loc() + "/cancelTemplate", {id: row.id})
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.$message.warning(resp.msg)
}
} catch (e) {
}
},
enableChange(enable, id) {
this.$axios.post(loc() + "/enableChange", {id, enable}).then((res) => {
@@ -540,15 +733,15 @@ layout("/layouts/platform.html"){
},
},
async created() {
this.activityGroupList = await this.getActivityGroup()
this.pageData()
this.clubOptions = await this.getClubsByRole()
this.clubOptions.map((v) => {
v.name = v.clubName
})
const units = await this.$businessTool.listUnit()
this.unitOptions = this.clubOptions.concat(units)
if (this.isNewPage()) {
await this.loadFormOptions()
this.$nextTick(() => {
this.initNewPage()
})
} else {
this.pageData()
this.loadFormOptions()
}
}
})
</script>
@@ -224,7 +224,7 @@ layout("/layouts/platform.html"){
unionChange(id) {
if (id) {
const union = this.unionList.find(c => c.id === id)
this.$set(this.formData, "helpUnitName", union.unionname)
this.$set(this.formData, "helpUnitName", union ? union.name : "")
} else {
this.$set(this.formData, "helpUnitName", '')
}
@@ -243,42 +243,61 @@ layout("/layouts/platform.html"){
}
if (val) {
const budgetType = this.budgetTypeOption.find(b => b.code === val)
this.$set(this.formData, "budgetTypeId", budgetType.code)
this.$set(this.formData, "budgetTypeId", budgetType ? budgetType.code : "")
}
},
async getActivityBudgetType() {
const data = await this.$businessTool.getDictOptions("ACTIVITY_BUDGET_TYPE")
let budgetTypeOption = []
if (this.$auth.hasPermission(['activity.budget.apply.system'])) {
const budgetTypeOption = []
if (this.canApplyAllBudgetType()) {
this.budgetTypeOption = data
} else {
if (this.$auth.hasPermission(['activity.budget.apply.schoolAdmin'])) {
data.map(v => {
if (["ACTIVITY_BUDGET_TYPE_ONE"].includes(v.code)) {
budgetTypeOption.push(v)
}
})
if (this.canApplySchoolBudget()) {
this.pushBudgetTypeOption(data, budgetTypeOption, "ACTIVITY_BUDGET_TYPE_ONE")
}
if (this.$auth.hasPermission(['activity.budget.apply.branchAdmin'])) {
data.map(v => {
if (["ACTIVITY_BUDGET_TYPE_TWO"].includes(v.code)) {
budgetTypeOption.push(v)
}
})
if (this.canApplyBranchBudget()) {
this.pushBudgetTypeOption(data, budgetTypeOption, "ACTIVITY_BUDGET_TYPE_TWO")
}
if (this.$auth.hasPermission(['activity.budget.apply.clubPresident'])) {
data.map(v => {
if (["ACTIVITY_BUDGET_TYPE_THREE"].includes(v.code)) {
budgetTypeOption.push(v)
}
})
if (this.canApplyClubBudget()) {
this.pushBudgetTypeOption(data, budgetTypeOption, "ACTIVITY_BUDGET_TYPE_THREE")
}
this.budgetTypeOption = budgetTypeOption
if (this.budgetTypeOption.length === 1){
this.$set(this.formData, "outlayManageSource", this.budgetTypeOption[0].code)
this.budgetTypeCodeChange(this.budgetTypeOption[0].code)
}
}
this.initDefaultBudgetType()
},
pushBudgetTypeOption(source, target, code) {
const option = source.find(v => v.code === code)
if (option && !target.some(v => v.code === code)) {
target.push(option)
}
},
canApplyAllBudgetType() {
return this.$auth.hasPermission('activity.budget.apply.system')
|| this.$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])
},
canApplySchoolBudget() {
return this.$auth.hasPermission('activity.budget.apply.schoolAdmin')
|| this.$auth.hasRoleOr(['SCHOOL_REIMBURSEMENT_MANAGER', 'SCHOOL_OUTLAY_ADMIN'])
},
canApplyBranchBudget() {
return this.$auth.hasPermission('activity.budget.apply.branchAdmin')
|| this.$auth.hasRoleOr(['UNION_REIMBURSEMENT_MANAGER', 'BRANCH_UNION_ADMIN', 'BRANCH_UNION_CHAIRMAN', 'BRANCH_UNION_OPERATOR', 'BRANCH_UNION_WENTI_SPORTS'])
},
canApplyClubBudget() {
return this.$auth.hasPermission('activity.budget.apply.clubPresident')
|| this.$auth.hasRoleOr(['CLUB_REIMBURSEMENT_MANAGER', 'CLUB_MANAGER', 'CLUB_PRESIDENT'])
},
initDefaultBudgetType() {
if (this.bizId || this.formData.outlayManageSource || this.budgetTypeOption.length === 0) {
return
}
const defaultBudgetType = this.budgetTypeOption[0].code
this.$set(this.formData, "outlayManageSource", defaultBudgetType)
this.budgetTypeCodeChange(defaultBudgetType)
},
async loadUnionList() {
const unionId = this.canApplyAllBudgetType() ? null : this.$store.state.user.union.id
this.unionList = await this.$businessTool.listUnion(unionId)
},
getSchoolBudget() {
this.$axios.post("/platform/activity/budget/apply/getSchoolBudget").then((res) => {
@@ -343,7 +362,7 @@ layout("/layouts/platform.html"){
this.init()
await this.getActivityBudgetType()
await this.getSchoolBudget()
this.unionList = await this.$businessTool.listUnion(this.$store.state.user.union.id)
await this.loadUnionList()
this.clubOption = await this.$businessTool.listClubByRole()
}
})
@@ -99,7 +99,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
</style>
<div id="app">
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5/signup')" fixed placeholder></van-nav-bar>
<div class="tour-apply-page">
<van-loading v-if="pageLoading" size="24px" vertical>加载中...</van-loading>
@@ -544,7 +544,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
message: res.msg || "报名成功",
confirmButtonColor: "#1867b0"
}).then(() => {
window.location.href = "/platform/tour/signup/h5/signup"
window.location.replace("/platform/tour/signup/h5/signup")
})
} else {
vant.Dialog.alert({
@@ -173,7 +173,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
</style>
<div id="app">
<van-nav-bar title="线路详情" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
<van-nav-bar title="线路详情" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5/signup')" fixed placeholder></van-nav-bar>
<div class="tour-detail-page">
<van-loading v-if="detailLoading" size="24px" vertical>加载中...</van-loading>
@@ -379,7 +379,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
</style>
<div id="app" class="tour-line-page">
<van-nav-bar title="疗休养线路" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
<van-nav-bar title="疗休养线路" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5')" fixed placeholder></van-nav-bar>
<div class="tour-line-toolbar">
<div class="tour-line-search-row">
@@ -411,7 +411,8 @@ layout("/layouts/platform_h5.html"){
currentSegmentId: "",
studying: false,
pendingSeconds: 0,
heartbeatTimer: null
heartbeatTimer: null,
navigatingBack: false
}
},
computed: {
@@ -685,9 +686,29 @@ layout("/layouts/platform_h5.html"){
this.finishStudy(false)
this.playerVisible = false
},
goBack() {
this.finishStudy(true)
pjaxReplace("/platform/learning/course/h5")
async goBack() {
if (this.navigatingBack) return
this.navigatingBack = true
try {
await this.finishStudy(true)
} finally {
this.navigateBack()
}
},
navigateBack() {
if (window.history.length > 1) {
window.history.back()
return
}
$.pjax({
url: "/platform/learning/course/h5",
container: "#container",
maxCacheLength: 0,
push: false,
replace: true,
fragment: "#container",
timeout: 8000
})
}
},
async mounted() {
@@ -230,18 +230,18 @@ const home = {
.map(src => ({ src }))
},
listHomeBanner() {
const cached = this.readHomeCache("banner")
const cached = this.readHomeCache("h5Banner")
if (cached && cached.length) {
this.bannerList = cached
this.activeBannerIndex = 0
}
this.$axios.post("/open/common/getConfigKey", { key: "AppHomeImg" }).then((res) => {
this.$axios.post("/open/common/getConfigKey", { key: "H5AppHomeImg" }).then((res) => {
if (res.code === 0) {
const configBannerList = this.parseBannerList(res.data)
const nextBannerList = configBannerList.length > 0 ? configBannerList : this.defaultBannerList
this.bannerList = nextBannerList
this.activeBannerIndex = 0
this.writeHomeCache("banner", nextBannerList, this.homeCacheTtl.banner)
this.writeHomeCache("h5Banner", nextBannerList, this.homeCacheTtl.banner)
this.cacheBannerImages(nextBannerList)
}
}).catch(() => {
@@ -164,7 +164,7 @@ layout("/layouts/platform_h5.html"){
position: relative;
display: flex;
flex-direction: row;
height: 90px;
min-height: 120px;
}
.welfare-option.selected {
@@ -185,49 +185,87 @@ layout("/layouts/platform_h5.html"){
}
.welfare-option-image {
width: 90px;
height: 90px;
width: 100px;
height: 100px;
margin: 10px 0 10px 10px;
position: relative;
flex-shrink: 0;
border-radius: 8px;
overflow: hidden;
background: #f7f8fa;
}
.welfare-option-content {
padding: 6px 12px;
padding: 10px 12px;
flex: 1;
display: flex;
flex-direction: column;
position: relative;
min-width: 0;
}
.welfare-option-title {
font-size: 15px;
font-weight: bold;
color: var(--text-primary);
margin-bottom: 0;
padding-right: 30px;
margin-bottom: 5px;
padding-right: 34px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 1.4;
}
.welfare-option-type-tag {
display: inline-flex;
align-items: center;
height: 17px;
padding: 0 4px;
margin-right: 5px;
border-radius: 3px;
background: var(--primary-color);
color: #fff;
font-size: 11px;
line-height: 17px;
vertical-align: 1px;
}
.welfare-option-rank {
margin-bottom: 4px;
color: #d6a21e;
font-size: 12px;
line-height: 1.3;
display: flex;
align-items: center;
}
.welfare-option-rank .van-icon {
margin-right: 3px;
font-size: 14px;
}
.welfare-option-desc {
padding-right: 4px;
color: var(--text-secondary);
font-size: 12px;
line-height: 1.45;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
line-height: 1.4;
}
.welfare-option-desc {
display: none;
}
.welfare-option-footer {
margin-top: auto;
display: flex;
justify-content: space-between;
justify-content: flex-end;
align-items: center;
gap: 10px;
}
.welfare-option-checkbox {
position: absolute;
bottom: 12px;
right: 12px;
flex-shrink: 0;
}
.welfare-option-checkbox .van-stepper {
@@ -240,13 +278,16 @@ layout("/layouts/platform_h5.html"){
}
.welfare-detail-btn {
position: absolute;
bottom: 12px;
left: 12px;
color: var(--primary-color);
height: 24px;
padding: 0 10px;
border-radius: 12px;
background: var(--primary-color);
color: #fff;
font-size: 13px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.welfare-detail-btn .van-icon {
@@ -640,14 +681,17 @@ layout("/layouts/platform_h5.html"){
</div>
<div class="welfare-option-content">
<div class="welfare-option-title">{{ option.optionName }}</div>
<!-- 查看详情按钮 -->
<div class="welfare-detail-btn" @click.stop="showOptionDetail(option)">
<van-icon name="info-o"/>
<span style="position: relative; top: -0.5px">查看详情</span>
<div class="welfare-option-title">
<span class="welfare-option-type-tag">套餐</span>{{ option.optionName }}
</div>
<div class="welfare-option-rank">
<van-icon name="medal-o"/>
<span>{{ optionRankText(option) }}</span>
</div>
<div class="welfare-option-desc">{{ optionBrief(option) }}</div>
<!-- 单选模式使用单选按钮 -->
<div class="welfare-option-radio" v-if="projectInfo.isCheckBox === 'radio'">
<van-radio
@@ -658,21 +702,29 @@ layout("/layouts/platform_h5.html"){
></van-radio>
</div>
<!-- 多选模式使用步进器 -->
<div class="welfare-option-checkbox" v-else>
<van-stepper
:key="'input-number-'+index+'-'+option.selectNumKey|| 0"
v-model="option.selectNum"
integer
disable-input
:default-value="0"
:min="0"
:disabled="isDeadlinePassed"
input-width="40px"
button-size="22px"
@change="selectNumChange(index,option.selectNum)"
theme="round"
></van-stepper>
<div class="welfare-option-footer">
<!-- 查看详情按钮 -->
<div class="welfare-detail-btn" @click.stop="showOptionDetail(option)">
<van-icon name="info-o"/>
<span style="position: relative; top: -0.5px">查看详情</span>
</div>
<!-- 多选模式使用步进器 -->
<div class="welfare-option-checkbox" v-if="projectInfo.isCheckBox !== 'radio'">
<van-stepper
:key="'input-number-'+index+'-'+option.selectNumKey|| 0"
v-model="option.selectNum"
integer
disable-input
:default-value="0"
:min="0"
:disabled="isDeadlinePassed"
input-width="40px"
button-size="22px"
@change="selectNumChange(index,option.selectNum)"
theme="round"
></van-stepper>
</div>
</div>
</div>
</div>
@@ -894,6 +946,19 @@ layout("/layouts/platform_h5.html"){
},
methods: {
optionRankText(option) {
if (option.rankNo) {
return "此套餐在本次福利排行第" + option.rankNo + "名"
}
return "此套餐暂无排行数据"
},
optionBrief(option) {
const content = option.simpleDesc || option.description || option.supplier || ""
const div = document.createElement("div")
div.innerHTML = content
const text = (div.textContent || div.innerText || "").replace(/\s+/g, " ").trim()
return text || "暂无套餐详情"
},
selectNumChange(index, newValue) {
const option = this.projectInfo.options[index];
const maxSelect = this.projectInfo.multiSelectNum || this.projectInfo.options.length;
@@ -1221,8 +1286,6 @@ layout("/layouts/platform_h5.html"){
// 显示选项详情
showOptionDetail(option) {
// 阻止事件冒泡,避免触发父元素的点击事件
event.stopPropagation()
this.selectedOption = option
this.showOptionDetailDialog = true
},