This commit is contained in:
=
2026-08-05 08:35:17 +08:00
parent ff3e8075b5
commit de5f8dc9ba
55 changed files with 1667 additions and 449 deletions
@@ -237,17 +237,18 @@ layout("/layouts/platform.html"){
<el-dialog append-to-body :title="menuDialogTitle" :visible.sync="menuDialogVisible" :close-on-click-modal="false"
width="70%">
<!-- 搜索框 -->
<!-- <el-row style="margin-bottom: 10px">-->
<!-- <el-input-->
<!-- v-model="searchText"-->
<!-- placeholder="搜索11"-->
<!-- size="small"-->
<!-- clearable-->
<!-- style="width: 300px"-->
<!-- >-->
<!-- <i slot="prefix" class="el-input__icon el-icon-search"></i>-->
<!-- </el-input>-->
<!-- </el-row>-->
<el-row style="margin-bottom: 10px">
<el-input
v-model="searchText"
placeholder="请输入权限名称"
size="small"
clearable
style="width: 300px"
@input="handleSearch"
>
<i slot="prefix" class="el-input__icon el-icon-search"></i>
</el-input>
</el-row>
<el-row style="margin-bottom: 3px">
<el-button size="small" @click="menuRoleSelAll">全选</el-button>
<el-button size="small" @click="menuRoleSelClear">清空</el-button>
@@ -257,7 +258,7 @@ layout("/layouts/platform.html"){
<el-tree
ref="doMenuTree"
:data="filteredMenuData"
:data="doMenuData"
:default-checked-keys="doMenuCheckedData"
check-strictly
show-checkbox
@@ -265,6 +266,7 @@ layout("/layouts/platform.html"){
check-strictly
:props="defaultProps"
:filter-node-method="filterNode"
@check="handleMenuCheck"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span v-html="getDisplayText(node, data)"></span>
@@ -444,6 +446,7 @@ layout("/layouts/platform.html"){
addMenuData: [],
doMenuData: [],
doMenuCheckedData: [], //已分配的权限选中状态
menuCheckedMap: {}, //完整权限树的勾选状态,搜索隐藏节点时仍需保留
doCmsData: [],
doCmsCheckedData: [], //已分配的CMS权限
doCmsForm: {},
@@ -494,7 +497,16 @@ layout("/layouts/platform.html"){
methods: {
// 搜索处理
handleSearch(value) {
this.$refs.doMenuTree.filter(value);
// 弹框初次渲染完成后再执行筛选,避免树实例尚未创建。
this.$nextTick(() => {
this.$refs.doMenuTree.filter(value)
})
},
// 更新单个权限的勾选状态,避免搜索隐藏的权限在保存时丢失。
handleMenuCheck(data, checked) {
const isChecked = checked.checkedKeys.indexOf(data.id) !== -1
this.$set(this.menuCheckedMap, data.id, isChecked)
},
// 过滤节点方法
@@ -578,8 +590,15 @@ layout("/layouts/platform.html"){
doMenuLoad() {
this.$axios.post("/platform/sys/role/menuRole/" + this.roleId + "/" + this.platform, {}).then((res) => {
if (res.code === 0) {
this.doMenuData = res.data.menu
this.doMenuCheckedData = res.data.cmenu
const menuCheckedMap = {}
res.data.cmenu.forEach((menuId) => {
menuCheckedMap[menuId] = true
})
this.$set(this, "doMenuData", res.data.menu)
this.$set(this, "doMenuCheckedData", res.data.cmenu)
this.$set(this, "menuCheckedMap", menuCheckedMap)
// 权限树数据刷新后清空上次搜索产生的筛选状态。
this.handleSearch(this.searchText)
}
})
},
@@ -669,7 +688,10 @@ layout("/layouts/platform.html"){
// return;
// }
const ids = this.$refs["doMenuTree"].getCheckedKeys()
// 从完整权限树的状态中组装提交数据,搜索隐藏节点不会被遗漏。
const allMenuIds = []
this.getTreeAllIds(allMenuIds, this.doMenuData)
const ids = allMenuIds.filter((menuId) => this.menuCheckedMap[menuId])
if (!ids || ids.length === 0) {
this.$message.warning("请选择菜单或数据权限")
return
@@ -721,6 +743,7 @@ layout("/layouts/platform.html"){
this.menuDialogVisible = true
this.platform = "PC"
this.roleId = command.id
this.$set(this, "searchText", "")
this.doMenuLoad()
}
if ("h5_menu" === command.type) {
@@ -728,6 +751,7 @@ layout("/layouts/platform.html"){
this.menuDialogVisible = true
this.platform = "H5"
this.roleId = command.id
this.$set(this, "searchText", "")
this.doMenuLoad()
}
@@ -837,9 +861,15 @@ layout("/layouts/platform.html"){
menuRoleSelAll() {
const ids = []
this.getTreeAllIds(ids, this.doMenuData)
const menuCheckedMap = {}
ids.forEach((menuId) => {
menuCheckedMap[menuId] = true
})
this.$set(this, "menuCheckedMap", menuCheckedMap)
this.$refs["doMenuTree"].setCheckedKeys(ids)
},
menuRoleSelClear() {
this.$set(this, "menuCheckedMap", {})
this.$refs["doMenuTree"].setCheckedKeys([])
},
clearButtons(list) {
@@ -75,7 +75,14 @@ const branchUnionUserManage = {
<el-dialog title="添加" :visible.sync="dialogFormVisible" width="600px" :close-on-click-modal="false">
<el-form :model="formData" ref="form" size="small" label-width="80px">
<el-form-item prop="roleCode" label="角色">
<dict-select v-model="formData.roleCode" code="BRANCH_UNION_ROLES" placeholder="请选择角色"></dict-select>
<el-select v-model="formData.roleCode" placeholder="请选择角色" @change="handleRoleChange">
<el-option v-for="item in roleOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="isUnitPartySecretary()" prop="unitIds" label="所属单位">
<el-select v-model="formData.unitIds" multiple collapse-tags placeholder="请选择单位">
<el-option v-for="item in partySecretaryUnitOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="j" label="届数">
<dict-select v-model="formData.j" code="TEACHER_CONGRESS_J" placeholder="请选择届数"></dict-select>
@@ -138,6 +145,8 @@ const branchUnionUserManage = {
},
dialogFormVisible: false,
formData: {},
roleOptions: [],
partySecretaryUnitOptions: [],
leaveDialogVisible: false,
leaveForm: {
id: "",
@@ -200,6 +209,32 @@ const branchUnionUserManage = {
isLeft(row) {
return row.isServing === false || row.isServing === 0 || row.displayStatus === "离任"
},
isUnitPartySecretary() {
return this.formData.roleCode === "UNIT_PARTY_SECRETARY"
},
loadRoleOptions() {
return $.get("/platform/sys/union/branchUnionRoleOptions").then((res) => {
if (res.code === 0) {
this.$set(this, "roleOptions", res.data || [])
}
})
},
loadPartySecretaryUnitOptions() {
return $.get("/platform/sys/union/branchUnionPartySecretaryUnitOptions", {
unionId: this.union_id
}).then((res) => {
if (res.code === 0) {
this.$set(this, "partySecretaryUnitOptions", res.data || [])
}
})
},
handleRoleChange() {
if (this.isUnitPartySecretary()) {
this.loadPartySecretaryUnitOptions()
return
}
this.$set(this.formData, "unitIds", [])
},
openAdd() {
this.dialogFormVisible = true
this.$nextTick(() => {
@@ -218,8 +253,16 @@ const branchUnionUserManage = {
this.$message.error("请选择届数")
return
}
$.post("/platform/sys/union/insertBranchUnionUserRole", {
if (this.isUnitPartySecretary() && (!this.formData.unitIds || this.formData.unitIds.length === 0)) {
this.$message.error("请选择所属单位")
return
}
const submitUrl = this.isUnitPartySecretary()
? "/platform/sys/union/insertBranchUnionPartySecretaryRole"
: "/platform/sys/union/insertBranchUnionUserRole"
$.post(submitUrl, {
...this.formData,
unitIds: JSON.stringify(this.formData.unitIds || []),
unionId: this.union_id
}).then((res) => {
if (res.code === 0) {
@@ -279,6 +322,7 @@ const branchUnionUserManage = {
}
},
created() {
this.loadRoleOptions()
this.initJSearch()
},
style: /*language=CSS*/ `
@@ -780,13 +780,13 @@ layout("/layouts/platform.html"){
return data;
},
async getUnionList(row) {
const {activityId, eventId} = row
const {data} = await this.$axios.post(loc() + "/getUnionList", {
activityId: activityId,
eventId: eventId
async getUnionList() {
// 团体成绩可录入任意分工会,使用全量分工会列表而非项目报名分工会。
const unionList = await this.$businessTool.listUnion()
return unionList.map(item => {
this.$set(item, "unionname", item.name)
return item
})
return data;
},
openAddUser() {
this.userData.push({})
@@ -73,7 +73,7 @@ layout("/layouts/platform.html"){
<evaluate-info ref="evaluateInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">
{{formData.taskName}}
会长审核
</div>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=""
class="flow-task-form">
@@ -29,7 +29,7 @@ const EVALUATE_INFO_COMPONENT = {
<template v-for="task in doneTasks">
<div class="mt10">
<div class="process-title">{{ task.displayName }}</div>
<div class="process-title">{{ getAuditDisplayName(task.displayName) }}</div>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
v-if="task.ext.isFirstTaskNode">
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName
@@ -72,6 +72,10 @@ const EVALUATE_INFO_COMPONENT = {
}
},
methods: {
// 兼容历史流程节点名称,统一展示为会长审核。
getAuditDisplayName(displayName) {
return displayName === "协会审核" ? "会长审核" : displayName
},
onOpen(row) {
this.row = row
this.$axios.post("/platform/club/evaluate/apply/info", { id: row.id }).then((res) => {
@@ -70,7 +70,7 @@ layout("/layouts/platform.html"){
<examine-info ref="examineInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">
{{formData.taskName}}
会长审核
</div>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=""
class="flow-task-form">
@@ -91,7 +91,7 @@
<el-tab-pane name="5" label="审核记录">
<template v-if="doneTasks.length > 0" v-for="task in doneTasks">
<div class="mt10">
<div class="process-title">{{ task.displayName }}</div>
<div class="process-title">{{ getAuditDisplayName(task.displayName) }}</div>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
v-if="task.ext.isFirstTaskNode">
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName
@@ -119,6 +119,17 @@
</el-descriptions>
</div>
</template>
<template v-else-if="legacyAuditRecords.length > 0">
<div class="mt10" v-for="record in legacyAuditRecords" :key="record.id">
<div class="process-title">{{ record.auditName }}</div>
<el-descriptions border class="flow-task-form" :column="3">
<el-descriptions-item label="办理用户">{{ record.userName }}({{ record.loginName }})</el-descriptions-item>
<el-descriptions-item label="办理时间">{{ record.auditTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">{{ record.auditPass ? "审核通过" : "审核不通过" }}</el-descriptions-item>
<el-descriptions-item label="办理意见" span="3">{{ record.auditOpinion }}</el-descriptions-item>
</el-descriptions>
</div>
</template>
<template v-else>
<el-empty description="暂无审核记录"></el-empty>
</template>
@@ -133,6 +144,7 @@
activeName: "1",
row: {},
doneTasks: [],
legacyAuditRecords: [],
}
},
methods: {
@@ -149,11 +161,16 @@
const totalExpend = Number(row.totalExpend) || 0
return lastYearSurplus + income + allocate + support + otherIncome - totalExpend
},
// 兼容历史流程节点名称,统一展示为会长审核。
getAuditDisplayName(displayName) {
return displayName === "协会审核" ? "会长审核" : displayName
},
async onOpen(row) {
this.row = row
const resp = await this.$axios.post("/platform/club/examine/common/findOne", { id: row.id })
if (resp.code === 0) {
this.viewData = resp.data
this.$set(this, "legacyAuditRecords", resp.data.legacyAuditRecords || [])
await this.getClubUserNum(resp.data.clubId)
await this.getJgUser(resp.data.clubId)
}
@@ -176,7 +193,7 @@
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
this.$set(this, "doneTasks", res.data || [])
}
})
},
@@ -163,11 +163,7 @@ const CLUB_FORM_TEMPLATE = {
clubCode: [{ required: false, message: "请填写社团编码", trigger: ["blur", "change"] }],
clubType: [{ required: true, message: "请选择社团类型", trigger: ["blur", "change"] }],
//concatPerson: [{ required: true, message: "请选择社团联系人", trigger: ["blur", "change"] }],
foundTime: [{ required: true, message: "请选择成立时间", trigger: ["blur", "change"] }],
establishReport: [{ required: true, message: "请上传申请成立报告", trigger: ["blur", "change"] }],
rulesFile: [{ required: true, message: "请上传章程草案", trigger: ["blur", "change"] }],
manageFile: [{ required: true, message: "请上传经费来源及管理办法", trigger: ["blur", "change"] }],
yearPlanFile: [{ required: true, message: "请上传年度活动计划", trigger: ["blur", "change"] }]
foundTime: [{ required: true, message: "请选择成立时间", trigger: ["blur", "change"] }]
}
}
},
@@ -121,8 +121,11 @@ layout("/layouts/platform.html"){
if(valid) await this.doHandle("onFinishTask")
},
async doHandle(type) {
let formData = {}
try {
// 保存和提交均需传递发起人,确保草稿再次编辑时可正确回显。
const sponsors = this.$refs.clubSponsorRef.sponsorData
.filter((item) => item.userId !== "" && item.userId !== undefined)
.map((item) => ({ sponsorId: item.userId }))
if("onSave" !== type) {
let hz = this.$refs.clubManagerRef.managePerson.filter((o) => o.roleCode === CLUB_ROLE_CONSTANT.CLUB_PRESIDENT)
if (hz.length !== 1) {
@@ -134,9 +137,6 @@ layout("/layouts/platform.html"){
this.$message.warning({ title: "警告", message: "秘书长需要1人" })
return
}
formData.sponsor = this.$refs.clubSponsorRef.sponsorData
.filter((o) => o.userId !== "" && o.userId !== undefined)
.map((o) => o.userId)
if (['onFinishTask', 'onSubmit'].includes(type) && !this.validateSponsorCount()) {
return
}
@@ -153,15 +153,7 @@ layout("/layouts/platform.html"){
}
}
const cloneData = clone(this.$refs.clubFormRef.formData)
let array = []
if (formData.sponsor) {
formData.sponsor.forEach((item) => {
array.push({
sponsorId: item
})
})
}
cloneData.sponsors = array
cloneData.sponsors = sponsors
let url = '';
if(type === 'onSave') {
url = '/platform/club/register/clubRegisterApply/save'
@@ -229,44 +229,54 @@ const apply_component = {
})
},
onSubmit() {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/evaluate/apply/submit', {
data: JSON.stringify(this.formData),
taskId: this.taskId
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
if (this.formData.id) {
this.$emit('refresh')
} else {
commonUtil.pjaxPush('/platform/evaluate/mine')
this.$refs.formRef.validate((valid) => {
if (!valid) {
return
}
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/evaluate/apply/submit', {
data: JSON.stringify(this.formData),
taskId: this.taskId
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
if (this.formData.id) {
this.$emit('refresh')
} else {
commonUtil.pjaxPush('/platform/evaluate/mine')
}
}
}
})
})
})
},
onFinishTask() {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/evaluate/apply/submitAgain', {
data: JSON.stringify(this.formData),
taskId: this.taskId
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
if (this.formData.id) {
this.$emit('refresh')
} else {
commonUtil.pjaxPush('/platform/evaluate/mine')
this.$refs.formRef.validate((valid) => {
if (!valid) {
return
}
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/evaluate/apply/submitAgain', {
data: JSON.stringify(this.formData),
taskId: this.taskId
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
if (this.formData.id) {
this.$emit('refresh')
} else {
commonUtil.pjaxPush('/platform/evaluate/mine')
}
}
}
})
})
})
},
@@ -168,7 +168,6 @@ layout("/layouts/platform.html"){
created() {
this.listSession()
this.setTableColumnsByProposalResult()
this.pageData()
}
})
</script>
@@ -77,6 +77,7 @@ layout("/layouts/platform.html"){
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%" row-key="id">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"></el-table-column>
<el-table-column label="提案编号" prop="code" sortable="custom" width="100px" show-overflow-tooltip></el-table-column>
<el-table-column label="立案编号" prop="caseFilingCode" width="100px" show-overflow-tooltip></el-table-column>
<el-table-column label="提案名称" prop="name" sortable="custom" show-overflow-tooltip></el-table-column>
<el-table-column label="提案人" prop="createUserName" sortable="custom"></el-table-column>
<el-table-column label="提案类别" prop="typeName" sortable="custom"></el-table-column>
@@ -133,8 +134,16 @@ layout("/layouts/platform.html"){
:rules="[{required:true,message:'请输入提案编号',trigger:'blur'}]">
<el-input maxlength="100" placeholder="提案编号" v-model="formData.code"></el-input>
</el-form-item>
</el-col>
</el-col>
<el-col :span="12">
<el-form-item label="立案编号" prop="caseFilingCode">
<el-input maxlength="100" placeholder="立案编号" v-model="formData.caseFilingCode"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" type="flex">
<el-col :span="24">
<el-form-item label="提案名称" prop="name"
:rules="[{required:true,message:'请输入提案名称',trigger:'blur'}]">
<el-input maxlength="100" placeholder="提案名称" v-model="formData.name"></el-input>
@@ -75,6 +75,7 @@ layout("/layouts/platform.html"){
<!-- <el-dropdown-item :command="{type:'status',data:row}">{{row.isDisabled?'发布':'关闭'}}</el-dropdown-item>-->
<!-- <el-dropdown-item :command="{type:'sendMsg',data:row}">通知未选择人员</el-dropdown-item>-->
<el-dropdown-item :command="{type:'createList',data:row}">生成福利名单</el-dropdown-item>
<el-dropdown-item :command="{type:'clearList',data:row}">清空福利名单</el-dropdown-item>
<el-dropdown-item :command="{type:'edit',data:row}">编辑</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',data:row}">删除</el-dropdown-item>
</el-dropdown-menu>
@@ -88,6 +89,14 @@ layout("/layouts/platform.html"){
<template #edit>
<el-form :model="formData" :rules="formRules" label-width="150px" ref="form" v-loading="formLoading">
<el-form-item label="沿用往期福利" v-if="!formData.id">
<el-select clearable filterable placeholder="请选择往期福利" style="width: 100%"
v-model="reuseProjectId" @change="reuseHistoryProject">
<el-option :key="item.id" :label="item.year + '年 - ' + item.name" :value="item.id"
v-for="item in historyProjectOptions"></el-option>
</el-select>
</el-form-item>
<el-form-item label="项目名称" prop="name">
<el-input maxlength="100" placeholder="项目名称" v-model="formData.name"></el-input>
</el-form-item>
@@ -211,7 +220,7 @@ layout("/layouts/platform.html"){
<template v-if="formData.flexible">
<el-form-item label="福利选项">
<welfare-option v-model="formData.options"></welfare-option>
<welfare-option :key="welfareOptionKey" v-model="formData.options"></welfare-option>
</el-form-item>
</template>
@@ -278,7 +287,10 @@ layout("/layouts/platform.html"){
gift: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
multiSelectNum: [{ required: true, message: "必填", trigger: ["blur", "change"] }]
},
welfarePersonTypeList: []
welfarePersonTypeList: [],
historyProjectOptions: [],
reuseProjectId: null,
welfareOptionKey: 0
}
},
methods: {
@@ -290,6 +302,8 @@ layout("/layouts/platform.html"){
this.doDelete(data.id)
} else if (type === "createList") {
this.$refs.filterUserRef.onOpen(data.id)
} else if (type === "clearList") {
this.clearWelfareList(data)
} else if (type === "status") {
this.projectStatusChange(data)
} else if (type === "sendMsg") {
@@ -364,8 +378,9 @@ layout("/layouts/platform.html"){
}
},
sendMsg(row) {},
openAdd() {
this.formData = {
async openAdd() {
this.$set(this, "reuseProjectId", null)
this.$set(this, "formData", {
isPushHome: false,
signMode: 4,
isRoutine: true,
@@ -375,9 +390,54 @@ layout("/layouts/platform.html"){
noticePushMode: 1,
welfareProjectSubjects: [],
flexibleGifts: [{}]
}
})
this.$refs.guava.edit()
if (this.$refs.form) this.$refs.form.resetFields()
await this.loadHistoryProjectOptions()
},
// 查询可沿用的历史福利项目,用于下拉选择。
async loadHistoryProjectOptions() {
const resp = await this.$axios.post(loc() + "/historyProjectList")
if (resp.code === 0) {
this.$set(this, "historyProjectOptions", resp.data || [])
} else {
this.$message.error(resp.msg)
}
},
// 清除往期项目的主键、关联和审计字段,确保提交时创建全新的福利项目及选项。
clearReuseProjectIdentifiers(project) {
["id", "year", "taskId", "createdBy", "createdAt", "updatedBy", "updatedAt"].forEach((field) => {
delete project[field]
})
const options = project.options || []
options.forEach((option) => {
["id", "subjectId", "welfareId", "createdBy", "createdAt", "updatedBy", "updatedAt"].forEach((field) => {
delete option[field]
})
})
},
async reuseHistoryProject(projectId) {
if (!projectId) {
return
}
this.$set(this, "submitLoading", true)
try {
const resp = await this.$axios.post(loc() + "/findOne", { id: projectId })
if (resp.code !== 0 || !resp.data) {
this.$message.error(resp.msg || "往期福利查询失败")
return
}
const projectData = clone(resp.data)
this.clearReuseProjectIdentifiers(projectData)
this.$set(projectData, "choiceTime", [projectData.choiceTimeStart, projectData.choiceTimeEnd])
this.$set(projectData, "provideTime", [projectData.provideTimeStart, projectData.provideTimeEnd])
this.$set(this, "formData", projectData)
this.$set(this, "welfareOptionKey", this.welfareOptionKey + 1)
} catch (e) {
this.$message.error("往期福利查询失败,请稍后重试")
} finally {
this.$set(this, "submitLoading", false)
}
},
async projectStatusChange({ id, isDisabled: val }) {
const resp = await this.$axios.post(loc() + "/projectStatusChange", {
@@ -391,6 +451,27 @@ layout("/layouts/platform.html"){
this.$message.warning(resp.msg)
}
},
// 清空指定项目的福利名单及用户已选福利记录,保留项目配置和历史评价数据。
clearWelfareList(row) {
this.$confirm("确定清空“" + row.name + "”的福利名单吗?该操作会同时删除已选福利记录,且不可恢复。", "高风险操作", {
confirmButtonText: "确认清空",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
try {
this.submitLoading = true
const resp = await this.$axios.post(loc() + "/clearWelfareList", { id: row.id })
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
} else {
this.$message.error(resp.msg)
}
} finally {
this.submitLoading = false
}
})
},
async openEdit(row) {
this.submitLoading = true
@@ -63,12 +63,10 @@ const addUser = {
</search-item>
<search-item label="所属单位">
<el-select clearable
<el-select @change="unitChange" clearable
filterable
multiple
collapse-tags
placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitIds">
v-model="pageForm.unitId">
<el-option
:key="item.id"
:label="item.name"
@@ -78,6 +76,18 @@ const addUser = {
</el-select>
</search-item>
<search-item label="三级单位">
<el-select clearable filterable placeholder="请先选择所属单位" style="width: 100%"
v-model="pageForm.threeUnitId">
<el-option
:key="item.id"
:label="item.name"
:value="item.id"
v-for="item in threeUnitOptions">
</el-option>
</el-select>
</search-item>
<search-item label="人员类型:">
<dict-select clearable code="USER_PERSON_TYPE"
multiple
@@ -86,6 +96,13 @@ const addUser = {
v-model="pageForm.personTypes"></dict-select>
</search-item>
<search-item label="人员属性:">
<dict-select clearable code="USER_ATTRIBUTE"
multiple
collapse-tags
placeholder="请选择人员属性"
v-model="pageForm.userAttributes"></dict-select>
</search-item>
<search-item label="在职状态:">
<dict-select clearable code="USER_STATE"
@@ -153,8 +170,10 @@ const addUser = {
birthday: null,
birthMonths: [],
unionId: null,
unitIds: [],
unitId: null,
threeUnitId: null,
personTypes: [],
userAttributes: [],
preparedBys: [],
userStates: [],
isMember: null
@@ -162,6 +181,7 @@ const addUser = {
sexOptions: ["男", "女"],
unionOptions: [],
unitOptions: [],
threeUnitOptions: [],
tableColumns: [
{ prop: "loginname", label: "工号" },
{ prop: "username", label: "姓名" },
@@ -170,7 +190,8 @@ const addUser = {
{ prop: "personType", label: "人员类型", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true }
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "threeUnitName", label: "三级单位", sortable: true }
]
}
},
@@ -192,20 +213,45 @@ const addUser = {
this.$set(this.pageForm, "birthMonths", [])
this.$set(this.pageForm, "unionId", null)
this.$set(this.pageForm, "unitId", null)
this.$set(this.pageForm, "threeUnitId", null)
this.$set(this, "threeUnitOptions", [])
this.$set(this.pageForm, "personTypes", [])
this.$set(this.pageForm, "userAttributes", [])
this.$set(this.pageForm, "preparedBys", [])
this.$set(this.pageForm, "userStates", [])
this.$set(this.pageForm, "isMember", null)
},
async unionIdChange(val) {
this.$set(this.pageForm, "unitId", null)
this.unitChange(null)
if (val) {
this.unitOptions = await this.$businessTool.listUnit(val)
this.$set(this, "unitOptions", await this.$businessTool.listUnit(val))
} else {
this.pageForm.unitIds = []
this.$set(this, "unitOptions", await this.$businessTool.listUnit())
}
},
// 所属单位改变后,仅加载该单位直属的三级单位,避免跨单位筛选。
unitChange(unitId) {
this.$set(this.pageForm, "threeUnitId", null)
this.$set(this, "threeUnitOptions", [])
if (!unitId) {
return
}
this.$axios.post("/platform/sys/unit/child", { pid: unitId })
.then((res) => {
if (res.code === 0) {
this.$set(this, "threeUnitOptions", res.data || [])
} else {
this.$message.error(res.msg || "三级单位查询失败")
}
})
.catch(() => {
this.$message.error("三级单位查询失败,请稍后重试")
})
},
pageData() {
this.tableLoading = true
this.$axios
@@ -81,12 +81,27 @@ layout("/layouts/platform.html"){
collapse-tags
placeholder="请选择所属单位"
style="width: 100%"
@change="unitIdsChange"
v-model="pageForm.unitIds"
>
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unitOptions"></el-option>
</el-select>
</search-item>
<search-item label="三级单位">
<el-select
clearable
filterable
multiple
collapse-tags
placeholder="请先选择所属单位"
style="width: 100%"
v-model="pageForm.threeUnitIds"
>
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in threeUnitOptions"></el-option>
</el-select>
</search-item>
<search-item label="人员类型:">
<dict-select
clearable
@@ -114,8 +129,8 @@ layout("/layouts/platform.html"){
code="AIDFUND_MEMBER_USER_TYPE"></dict-select>
</search-item>
<search-item label="人员属性">
<dict-select v-model="pageForm.userAttribute" placeholder="请选择人员属性" @change="doSearch"
code="USER_ATTRIBUTE"></dict-select>
<dict-select v-model="pageForm.userAttributes" placeholder="请选择人员属性" @change="doSearch"
code="USER_ATTRIBUTE" clearable multiple collapse-tags></dict-select>
</search-item>
<!-- <search-item label="所选福利:">-->
@@ -128,6 +143,9 @@ layout("/layouts/platform.html"){
<el-card class="mt10" shadow="never">
<table-tool :app="this" label="福利名单">
<el-button :disabled="!pageForm.projectId" :loading="batchDeleteLoading" @click="deleteSearchUsers" icon="el-icon-delete" size="small" type="danger">
删除人员
</el-button>
<el-button :disabled="!pageForm.projectId" @click="openExport" icon="el-icon-download" size="small" type="primary">
导出名单
</el-button>
@@ -143,6 +161,9 @@ layout("/layouts/platform.html"){
>
添加人员
</el-button>
<el-button :disabled="!canSyncUnion" :loading="syncUnionLoading" @click="syncWelfareListUnitAndUnion" icon="el-icon-refresh" size="small" type="primary">
同步工会
</el-button>
</table-tool>
<el-table
@@ -239,6 +260,13 @@ layout("/layouts/platform.html"){
return null
}
return null
},
canSyncUnion() {
const projectInfo = this.projectSelectOptions.find((v) => v.id === this.pageForm.projectId)
if (!projectInfo || !projectInfo.choiceTimeStart || !projectInfo.choiceTimeEnd) {
return false
}
return moment().isBetween(projectInfo.choiceTimeStart, projectInfo.choiceTimeEnd, null, "[]")
}
},
components: {
@@ -255,6 +283,7 @@ layout("/layouts/platform.html"){
},
unionOptions: [],
unitOptions: [],
threeUnitOptions: [],
sexOptions: ["男", "女"],
projectSelectOptions: [],
tableColumns: [
@@ -266,6 +295,7 @@ layout("/layouts/platform.html"){
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "welfareUnionName", label: "所属工会", sortable: true },
{ prop: "welfareUnitName", label: "所属单位", sortable: true },
{ prop: "threeUnitName", label: "三级单位", sortable: true },
{ prop: "remark", label: "备注", sortable: true }
],
@@ -275,7 +305,9 @@ layout("/layouts/platform.html"){
welfareListUserDrawer: false,
showImportDialog: false
showImportDialog: false,
batchDeleteLoading: false,
syncUnionLoading: false
}
},
methods: {
@@ -286,6 +318,72 @@ layout("/layouts/platform.html"){
})
},
// 按当前搜索条件统计并删除名单人员,删除前必须由用户二次确认。
async deleteSearchUsers() {
this.$set(this, "batchDeleteLoading", true)
try {
const countResp = await this.$axios.post("/platform/welfare/list/mange/countByPageForm", {
pageForm: JSON.stringify(this.pageForm)
})
if (countResp.code !== 0) {
this.$message.error(countResp.msg)
return
}
const userCount = countResp.data || 0
if (userCount === 0) {
this.$message.warning("当前搜索条件未查询到人员")
return
}
const confirmed = await this.$confirm("当前搜索条件查询到" + userCount + "人,确认删除吗?该操作会同时删除这些人员的已选福利记录,且不可恢复。", "高风险操作", {
confirmButtonText: "确认删除",
cancelButtonText: "取消",
type: "warning"
}).then(() => true).catch(() => false)
if (!confirmed) {
return
}
const deleteResp = await this.$axios.post("/platform/welfare/list/mange/deleteByPageForm", {
pageForm: JSON.stringify(this.pageForm)
})
if (deleteResp.code === 0) {
this.$message.success(deleteResp.msg)
this.doSearch()
} else {
this.$message.error(deleteResp.msg)
}
} catch (e) {
this.$message.error("删除人员失败,请稍后重试")
} finally {
this.$set(this, "batchDeleteLoading", false)
}
},
// 同步当前福利项目名单人员的单位和工会快照,后端会再次校验选择时间。
syncWelfareListUnitAndUnion() {
this.$confirm("将按人员当前所属单位同步福利名单中的所属单位和所属工会,确认继续吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
this.$set(this, "syncUnionLoading", true)
try {
const resp = await this.$axios.post("/platform/welfare/list/mange/syncWelfareListUnitAndUnion", {
projectId: this.pageForm.projectId
})
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.$message.error(resp.msg)
}
} catch (e) {
this.$message.error("同步工会失败,请稍后重试")
} finally {
this.$set(this, "syncUnionLoading", false)
}
})
},
successImport() {
this.doSearch()
this.importDialog = false
@@ -325,6 +423,32 @@ layout("/layouts/platform.html"){
this.doSearch()
})
},
// 根据已选所属单位查询直属三级单位,筛选项只保留当前所属单位范围内的数据。
async unitIdsChange(unitIds) {
this.$set(this.pageForm, "threeUnitIds", [])
this.$set(this, "threeUnitOptions", [])
if (!unitIds || unitIds.length === 0) {
return
}
try {
const responses = await Promise.all(unitIds.map((unitId) => this.$axios.post("/platform/sys/unit/child", { pid: unitId })))
const failedResponse = responses.find((res) => res.code !== 0)
if (failedResponse) {
this.$message.error(failedResponse.msg || "三级单位查询失败")
return
}
const optionMap = {}
responses.forEach((res) => {
const options = res.data || []
options.forEach((item) => {
optionMap[item.id] = item
})
})
this.$set(this, "threeUnitOptions", Object.keys(optionMap).map((id) => optionMap[id]))
} catch (e) {
this.$message.error("三级单位查询失败,请稍后重试")
}
},
pageData() {
this.tableLoading = true
this.$axios
@@ -555,7 +555,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
}
}).catch(() => {
this.submitLoading = false
vant.Toast("报名提交失败")
// 接口失败提示由全局 Axios 拦截器统一展示,避免与名额已满等业务提示重复。
})
}
},
@@ -18,7 +18,7 @@ layout("/layouts/platform_h5.html"){
</van-dropdown-menu>
</van-sticky>
<table-list api="/platform/proposal/mine/pageData" :page_form.sync="pageForm" @ready="onReady" ref="tableListRef"
<table-list api="/platform/proposal/mine/h5/pageData" :page_form.sync="pageForm" @ready="onReady" ref="tableListRef"
title="name">
<template v-slot="{index,row}">
<table-column label="提案编号">{{row.code}}</table-column>
@@ -23,7 +23,7 @@ layout("/layouts/platform_h5.html"){
</van-tabs>
</van-sticky>
<table-list api="/platform/proposal/seconded/pageData" :page_form.sync="pageForm" @ready="onReady"
<table-list api="/platform/proposal/seconded/h5/pageData" :page_form.sync="pageForm" @ready="onReady"
ref="tableListRef"
title="name">
<template v-slot="{index,row}">
@@ -189,7 +189,19 @@ layout("/layouts/platform_h5.html"){
this.$refs.proposalInfoRef.onOpen(row)
},
onApproval(row) {
async onApproval(row) {
// 与 PC 端答复入口保持一致,确认已沟通后才允许进入答复表单。
try {
await this.$dialog.confirm({
title: "提示",
message: "是否已与提案代表进行充分沟通?",
confirmButtonText: "是",
cancelButtonText: "否"
})
} catch (error) {
return
}
this.loadCandidates(row.taskId)
this.showApprovalForm = true