1、香樟工会讲堂->人员调整:添加代人报表(功能,系统管理员可用)

2、费用报销管理->费用报销:添加弹窗须知(参数配置:ExpenseDeclaration)
This commit is contained in:
2026-04-10 10:27:05 +08:00
parent bcb5b3564e
commit 8c19109326
11 changed files with 404 additions and 18 deletions
@@ -0,0 +1,246 @@
const applyForm = {
template: /*language=HTML*/ `
<div>
<el-dialog :close-on-click-modal="false" :visible.sync="signDialog" title="信息填写" width="50%" append-to-body>
<el-form :model="formData" ref="form" label-width="120px">
<el-row>
<el-form-item prop="userId" label="人员">
<user-select
v-model="formData.userId"
style="width: 100%"
api="/platform/sys/union/listUnion"
ref="useRef"
@change="selectUserFun"
:option_label_func="
(item) => {
return item.username + item.loginname
}
"
></user-select>
</el-form-item>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="姓名" prop="username">
<el-input readonly v-model="formData.username"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="工号" prop="loginname">
<el-input readonly v-model="formData.loginname"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="所属单位" prop="unitName">
<el-input readonly v-model="formData.unitName"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="所属工会" prop="unionName">
<el-input readonly v-model="formData.unionName"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="性别" prop="sex">
<el-input readonly v-model="formData.sex"></el-input>
</el-form-item>
</el-col>
<!--<el-col :span="24">
<el-form-item label="联系方式" prop="mobile">
<el-input v-model="formData.mobile"></el-input>
</el-form-item>
</el-col>-->
</el-row>
<el-row v-if="courseRow.courseIsLimitApply">
<el-col :span="24">
<el-form-item label="报名时段" prop="activityCourseId"
:rules="{ required: true, message: '请选择报名时段', trigger: 'blur'}">
<el-select style="width: 100%" v-model="formData.activityCourseId" placeholder="请选择报名时段">
<el-option v-for="item in courseTimeSelectList"
:label="item.text.substring(0, 12)"
:value="item.value"
:key="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item
v-for="(column, index) in formData.trainMobileSignColumnList"
:prop="'trainMobileSignColumnList.' + index + '.columnValue'"
:label="column.columnName"
:key="column.columnCode"
:rules="{ required: column.isRequired,
message: (['SELECT', 'FILE'].includes(column.columnFormType) ? '请选择' : '请填写') + column.columnName,
trigger: 'blur'}"
>
<!--文本框-->
<template v-if="!['SELECT'].includes(column.columnFormType) && ['VARCHAR','TEXT','INT'].includes(column.columnType)">
<el-input
v-model="column.columnValue"
:placeholder="'请填写' + column.columnName"
:type="['INT'].includes(column.columnType) ? 'number' : ''"
></el-input>
</template>
<!--选择框-->
<template v-else-if="['SELECT'].includes(column.columnFormType) && ['VARCHAR','TEXT','INT'].includes(column.columnType)">
<el-select v-model="column.columnValue" :placeholder="'请选择' + column.columnName" style="width: 100%">
<el-option v-for="item in column.selectValues" :key="item" :label="item" :value="item"></el-option>
</el-select>
</template>
<!--时间框-->
<template v-else-if="['DATE', 'DATETIME'].includes(column.columnType)">
<el-date-picker
style="width: 100%"
v-model="column.columnValue"
:type="column.columnType === 'DATE' ? 'date' : 'datetime'"
:placeholder="'请选择' + column.columnName"
:value-format="column.columnType === 'DATE' ? 'yyyy-MM-dd' : 'yyyy-MM-dd HH:mm:ss'"
></el-date-picker>
</template>
<!--文件-->
<template v-else-if="['JSON'].includes(column.columnType)">
<file-upload :upload_number="column.fileNumber" :value.sync="column.columnValue"
:accept="column.fileType ? column.fileType.join(',') : ''"
upload_result_type="url"
complete_result upload_mode="drag"
upload_result_category="array"></file-upload>
</template>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-row class="mt20" justify="end" type="flex">
<el-button @click="signDialog = false">取 消</el-button>
<el-button @click="onSubmit" type="primary">提 交</el-button>
</el-row>
</el-dialog>
</div>
`,
store,
dicts: ["TRAIN_SIGNUP_TYPE"],
data() {
return {
signDialog: false,
formData: {},
courseRow: {},
courseTimeSelectList: [],
}
},
methods: {
async getCourseTimeSelectList(o) {
const resp = await $.post('/platform/trainSignUp/apply/getCourseTimeSelectList',{ courseId: o.id })
if (resp.code === 0) {
this.courseTimeSelectList = resp.data
} else {
this.$message.warning('获取时段信息失败,请联系管理员')
}
},
async onOpen(row, course) {
this.initData(row, course)
if (row.courseIsLimitApply) {
await this.getCourseTimeSelectList(row)
}
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/trainSignUp/apply/validateSignUp", {
courseId: this.formData.courseId,
currentFamilyNumber: familyCount,
IsVerifyUserApply: "1"
})
return res.code === 0
},
async validateCourseTime() {
const res = await this.$axios.post('/platform/trainSignUp/apply/validateSourceSignUp', {
activityCourseId: this.formData.activityCourseId,
courseId: this.courseRow.id
})
return res.code === 0
},
async onSubmit() {
if(!await this.validateSignUp()) return
if(!this.formData.username) {
this.$message.warning("请选择参加人员")
return ;
}
this.$refs["form"].validate(async (valid) => {
if (valid) {
if(this.courseRow.courseIsLimitApply && !await this.validateCourseTime()) return
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const mobileColumnsValue = this.formData.trainMobileSignColumnList.map((v) => {
return {
columnName: v.columnName,
columnValue: v.columnValue,
columnCode: v.columnCode,
columnFormType: v.columnFormType
}
})
this.formData.mobileColumnsValue = JSON.stringify(mobileColumnsValue)
const resp = await this.$axios.post("/platform/trainSignUp/apply/doSignUpInsteadApply", this.formData)
if (resp.code === 0) {
this.signDialog = false
this.$message.success(resp.msg)
this.$emit('refresh')
this.formData.userId = '';
this.formData.username = '';
this.formData.loginname = '';
this.formData.unionName = '';
this.formData.unitName = '';
this.formData.sex = '';
} else {
this.$message.warning(resp.msg)
}
})
}
})
},
initData(row, course) {
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.$store.state.user[item.columnCode] || ""
})
},
selectUserFun() {
if(this.$refs.useRef.options){
let event = this.$refs.useRef.options.find(item => item.id === this.formData.userId);
if(event){
this.$set(this.formData, 'username', event.username)
this.$set(this.formData, 'loginname', event.loginname)
this.$set(this.formData, 'unionName', event.unionName)
this.$set(this.formData, 'unitName', event.unitName)
this.$set(this.formData, 'sex', event.sex)
}
}
}
},
style: /*language=CSS*/ `
`
}
@@ -60,9 +60,11 @@ layout("/layouts/platform.html"){
</template>
</el-table-column>
<el-table-column label="操作" width="150px">
<el-table-column label="操作" width="200px">
<template v-slot="{row}">
<el-button @click="openView(row)" size="mini" type="primary">调整</el-button>
<el-button type="primary" size="mini" @click="onSign(row)"
v-if="$auth.hasRoleOr(['SYSADMIN'])">代人报名</el-button>
</template>
</el-table-column>
</el-table>
@@ -72,18 +74,21 @@ layout("/layouts/platform.html"){
<template #view>
<user-info ref="userInfoRef" @refresh="doSearch"></user-info>
</template>
<apply-form ref="formRef" @refresh="doSearch"></apply-form>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('userInfo.js'){}#-->
<!--#include('applyForm.js'){}#-->
new Vue({
el: "#app",
dicts: ["TRAIN_SIGNUP_TYPE"],
mixins: [initTableMixins],
components: {
"user-info": userInfo,
"apply-form": applyForm,
},
data() {
return {
@@ -101,6 +106,7 @@ layout("/layouts/platform.html"){
{ label: "最多报名人数", prop: "coursePeopleNumber", sortable: true },
{ label: "已报名人数", prop: "registerNum", sortable: true }
],
trainMobileSignColumnList: [],
}
},
methods: {
@@ -133,6 +139,16 @@ layout("/layouts/platform.html"){
this.$refs.userInfoRef.onOpen(o, activity)
})
},
async onSign(row) {
await this.$axios.post("/platform/trainSignUp/type/getAllType", {id: row.courseTypeId})
.then((res) => {
if(res.data && res.data.length > 0){
this.trainMobileSignColumnList = res.data[0]?.trainMobileSignColumnList || [];
}
});
row.activityId = this.pageForm.activityId
this.$refs.formRef.onOpen(row, {trainMobileSignColumnList: this.trainMobileSignColumnList})
},
},
async created() {
await this.initData()
@@ -129,6 +129,14 @@ layout("/layouts/platform.html"){
</el-row>
</el-card>
<el-dialog title="费用报销须知" :visible.sync="noticeDialogVisible" v-model="noticeDialogVisible">
<div style="max-height: 50vh; overflow-y: auto; white-space: pre-line">
{{friendlyReminderText}}
</div>
<div slot="footer">
<el-button type="primary" @click="noticeDialogVisible = false">我已知晓</el-button>
</div>
</el-dialog>
</div>
<script>
new Vue({
@@ -145,6 +153,8 @@ layout("/layouts/platform.html"){
activityList: [],
moneyPlaceholder: "请输入金额",
budgetMoney: 0,
noticeDialogVisible: false,
friendlyReminderText: ""
}
},
methods: {
@@ -352,6 +362,7 @@ layout("/layouts/platform.html"){
mobile: mobile,
}
}
this.getConfigKeyObj();
},
clubChange() {
if (this.formData.clubId) {
@@ -360,7 +371,16 @@ layout("/layouts/platform.html"){
} else {
this.$set(this.formData, 'clubName', null)
}
}
},
async getConfigKeyObj() {
const resp = await this.$axios.post("/open/common/getConfigKeyObj", { key: "ExpenseDeclaration" })
if(resp.data?.note){
this.noticeDialogVisible = true;
this.friendlyReminderText = resp.data?.note;
} else {
return "暂无配置提示内容";
}
},
},
async created() {
this.init()