提案整改

This commit is contained in:
2026-04-24 15:26:30 +08:00
parent 3207e0a594
commit 79f9cf9123
65 changed files with 2561 additions and 419 deletions
@@ -9,6 +9,10 @@ const APPLY_INFO = {
<el-descriptions-item label="工号">{{viewData.loginname}}</el-descriptions-item>
<el-descriptions-item label="联系方式">{{viewData.mobile}}</el-descriptions-item>
<el-descriptions-item label="性别">{{viewData.sex}}</el-descriptions-item>
<el-descriptions-item label="基金会员类型">
<dict-tag :options="dict.type.AIDFUND_MEMBER_USER_TYPE"
:value="viewData.aidFundMemberUserType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="入校时间">{{$moment(viewData.arrivalAtSchoolDate).format('YYYY-MM-DD')}}
</el-descriptions-item>
<el-descriptions-item label="所在单位">{{viewData.unitName}}</el-descriptions-item>
@@ -60,6 +60,16 @@ layout("/layouts/platform.html"){
<el-card shadow="never" class="mt10">
<table-tool label="申请记录">
<el-button @click="openBatchAudit"
:disabled="pageForm.approval===true||pageForm.approval==='true'"
size="small"
type="primary">批量审核
</el-button>
<el-button @click="exportApplyRecord"
icon="el-icon-download"
size="small"
type="primary">导出
</el-button>
<el-radio-group @change="doSearch" class="mr5" size="small" v-model="pageForm.approval">
<el-radio-button label="true">已审核</el-radio-button>
<el-radio-button label="false">未审核</el-radio-button>
@@ -68,6 +78,11 @@ layout("/layouts/platform.html"){
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder"
ref="table" row-key="id" style="width: 100%">
<el-table-column
:reserve-selection="true"
type="selection"
width="55">
</el-table-column>
<el-table-column :index="indexMethod" header-align="center" label="序号"
type="index" width="60px"></el-table-column>
<el-table-column
@@ -90,19 +105,8 @@ layout("/layouts/platform.html"){
:value="row.aidFundMemberUserType"></dict-tag>
</template>
<template scope="{row}" v-else-if="column.prop=='changeType'">
<template v-if="row.changeType==='AIDFUND_MEMBER_CHANGE_TYPE_ONE'">
<el-tag type="success">
<dict-tag :options="dict.type.AIDFUND_MEMBER_CHANGE_TYPE"
:value="row.changeType"></dict-tag>
</el-tag>
</template>
<template v-else>
<el-tag type="danger">
<dict-tag :options="dict.type.AIDFUND_MEMBER_CHANGE_TYPE"
:value="row.changeType"></dict-tag>
</el-tag>
</template>
<dict-tag :options="dict.type.AIDFUND_MEMBER_CHANGE_TYPE"
:value="row.changeType"></dict-tag>
</template>
<template scope="{row}" v-else-if="column.prop=='money'">
<template v-if="row.changeType==='AIDFUND_MEMBER_CHANGE_TYPE_ONE'">
@@ -124,6 +128,43 @@ layout("/layouts/platform.html"){
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog
:visible.sync="batchAuditVisible"
title="批量审核"
width="40%">
<el-form :model="batchForm" :rules="batchFormRules" label-width="100px" ref="batchFormRef">
<el-form-item label="审核状态" prop="submitType">
<el-radio-group v-model="batchForm.submitType">
<el-radio-button :label="2">拒绝</el-radio-button>
<el-radio-button :label="1">通过</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="审核名单">
<el-table :data="batchAuditTableData" row-key="id" style="width: 100%" max-height="300">
<el-table-column label="姓名" prop="userName" min-width="100"></el-table-column>
<el-table-column label="工号" prop="loginName" min-width="120"></el-table-column>
<el-table-column label="单位" prop="unitName" min-width="140" show-overflow-tooltip></el-table-column>
<el-table-column label="入校时间" prop="arrivalAtSchoolDate" min-width="110"></el-table-column>
<el-table-column label="缴费金额" prop="money" min-width="100"></el-table-column>
</el-table>
</el-form-item>
<el-alert
:closable="false"
class="mb10"
title="批量通过时,将按人员当前入校时间自动提交;缺少入校时间的记录会审核失败。"
type="warning"
v-if="batchForm.submitType===1">
</el-alert>
<el-form-item label="审批意见" prop="tf_opinion">
<user-opinion-textarea v-model="batchForm.tf_opinion"></user-opinion-textarea>
</el-form-item>
</el-form>
<span class="dialog-footer" slot="footer">
<el-button @click="batchAuditVisible = false">取 消</el-button>
<el-button @click="submitBatchAudit" type="primary">提 交</el-button>
</span>
</el-dialog>
<template #edit>
<info ref="infoRef">
<div v-if="showApprovalForm">
@@ -202,12 +243,27 @@ layout("/layouts/platform.html"){
{prop: "unitName", label: "所属单位"},
{prop: "unionName", label: "所属工会"},
{prop: "aidFundMemberUserType", label: "基金会员类型"},
{prop: "money", label: "缴费金额"},
{prop: "changeType", label: "变更类型"},
{prop: "applyTime", label: "申请日期"},
{prop: "curTaskName", label: "当前节点"},
{prop: "instanceState", label: "流程状态"}
],
showApprovalForm: false,
batchAuditVisible: false,
batchAuditTableData: [],
batchForm: {
submitType: 1,
tf_opinion: ""
},
batchFormRules: {
submitType: [
{required: true, message: "必填", trigger: ["change", "blur"]}
],
tf_opinion: [
{required: true, message: "必填", trigger: ["change", "blur"]}
]
},
unionOptions: [],
unitOptions: [],
pickerOptions: {
@@ -221,6 +277,91 @@ layout("/layouts/platform.html"){
'info': APPLY_INFO,
},
methods: {
openBatchAudit() {
const selection = this.$refs.table.selection
if (!selection || selection.length === 0) {
this.$message.warning("请先勾选需要审核的记录")
return
}
this.$set(this, "batchForm", {
submitType: 1,
tf_opinion: ""
})
this.$set(this, "batchAuditTableData", selection.map(row => {
return {
id: row.id,
userName: row.userName,
loginName: row.loginName,
unitName: row.unitName,
arrivalAtSchoolDate: row.arrivalAtSchoolDate,
money: row.money
}
}))
this.$set(this, "batchAuditVisible", true)
this.$nextTick(() => {
if (this.$refs.batchFormRef) {
this.$refs.batchFormRef.clearValidate()
}
})
},
submitBatchAudit() {
const selection = this.$refs.table.selection
if (!selection || selection.length === 0) {
this.$message.warning("请先勾选需要审核的记录")
return
}
this.$refs.batchFormRef.validate((valid) => {
if (!valid) {
return
}
let message = "确定要审核这 " + selection.length + " 条记录吗?"
const joinCount = selection.filter(row => row.changeType === "AIDFUND_MEMBER_CHANGE_TYPE_ONE").length
if (this.batchForm.submitType === 1 && joinCount > 0) {
message = "确定要批量通过这 " + selection.length + " 条记录吗?其中有 " + joinCount + " 条加入基金记录将按当前人员入校时间自动审核。"
}
this.$confirm(message, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const ids = selection.map(row => row.id)
const loading = this.$loading({
lock: true,
text: "正在批量审核...",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)"
})
this.$axios.post("/platform/medicalMutualAid/aidFund/foundationAudit/batchExecuteTask", {
ids: JSON.stringify(ids),
data: JSON.stringify(this.batchForm)
}).then((res) => {
if (res.code === 0) {
const result = res.data || {}
const successCount = result.successCount || 0
const failCount = result.failCount || 0
const failMessages = result.failMessages || []
if (failCount > 0) {
let failText = failMessages.slice(0, 3).join(";")
if (failMessages.length > 3) {
failText = failText + ";其余记录请查看列表后重试"
}
this.$message.warning("批量审核完成:成功 " + successCount + " 条,失败 " + failCount + " 条。" + failText)
} else {
this.$message.success("批量审核完成:成功 " + successCount + " 条")
}
this.$set(this, "batchAuditVisible", false)
this.doSearch()
this.$refs.table.clearSelection()
}
}).finally(() => {
loading.close()
})
})
})
},
exportApplyRecord() {
this.$downLoad("/platform/medicalMutualAid/aidFund/foundationAudit/exportApplyRecord", this.pageForm)
},
getPayMoney() {
this.$axios.post('/platform/medicalMutualAid/aidFund/foundationAudit/getPayMoney', {
arrivalAtSchoolDate: this.formData.arrivalAtSchoolDate,
@@ -56,6 +56,11 @@ layout("/layouts/platform.html"){
批量变更
</el-button>
<el-button @click="exportMemberList" icon="el-icon-download" size="small" type="primary"
v-if="$auth.hasPermission('medicalMutualAid.aidFund.manage')">
导出会员名单
</el-button>
<el-button @click="exportNewMember" icon="el-icon-download" size="small" type="primary"
v-if="$auth.hasPermission('medicalMutualAid.aidFund.manage.exportNewMember')" class="mr10">
导出{{new
@@ -448,6 +453,9 @@ layout("/layouts/platform.html"){
exportNewMember() {
this.$downLoad(loc() + "/exportNewMember")
},
exportMemberList() {
this.$downLoad(loc() + "/exportMemberList", this.pageForm)
},
getYearOptions() {
let year = new Date().getFullYear();
let arr = []
@@ -534,6 +534,7 @@ layout("/layouts/platform.html"){
} else {
await this.createRemoteMethod(this.$store.state.user.id)
this.$set(this.formData, 'sex', this.$store.state.user.sex)
this.$set(this.formData, 'userName', this.$store.state.user.username)
if (this.$store.state.user.birthday) {
this.$set(this.formData, 'age', this.$moment().diff(this.$store.state.user.birthday, 'years'))
}
@@ -216,6 +216,7 @@ layout("/layouts/platform.html"){
}
},
computed: {
//申请费用总额
applyLoveSum() {
const {applySum, loveSubsidyMoney} = this.calcData
@@ -244,6 +245,16 @@ layout("/layouts/platform.html"){
},
},
methods: {
async grantOrIntoChange(key, val) {
if (val === '') {
if (key === 'grants') {
this.calcData.schoolGrants = 0
} else if (key === 'into') {
this.calcData.unionInto = 0
}
}
const resp = await this.$axios.post(loc() + '/setGrantsOrUnionInto', {keys: key, value: val})
},
getSummaries(param) {
const {columns, data} = param
const sums = []
@@ -0,0 +1,418 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.medical-dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 180px 1fr 1fr;
gap: 20px;
width: 100%;
min-height: calc(100vh - 126px);
box-sizing: border-box;
}
.dashboard-card {
background: #ffffff;
border-radius: 8px;
overflow: hidden;
display: flex;
flex-direction: column;
border: 1px solid #eef1f6;
}
.dashboard-title {
padding: 16px 20px 8px;
font-size: 16px;
font-weight: 600;
color: #333333;
border-bottom: 1px solid #f0f2f5;
flex-shrink: 0;
}
.overview-card {
padding: 20px;
box-sizing: border-box;
justify-content: space-between;
}
.overview-label {
font-size: 14px;
color: #7a7f87;
line-height: 1;
}
.overview-value {
font-size: 34px;
font-weight: 700;
color: #1f6f5f;
line-height: 1.2;
margin-top: 18px;
}
.overview-sub {
font-size: 13px;
color: #949aa3;
line-height: 1.6;
margin-top: auto;
}
.wide-panel {
grid-column: span 2;
min-height: 0;
}
.full-panel {
grid-column: 1 / -1;
min-height: 0;
}
.chart-panel {
min-height: 0;
}
.table-panel {
min-height: 0;
}
.panel-body {
flex: 1;
min-height: 0;
padding: 12px 16px 16px;
}
.chart-box {
width: 100%;
height: 100%;
min-height: 260px;
}
.money-text {
color: #cf6a32;
}
@media (max-width: 1400px) {
.medical-dashboard {
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 180px) auto auto auto;
}
.wide-panel {
grid-column: span 2;
}
.full-panel {
grid-column: 1 / -1;
}
}
@media (max-width: 768px) {
.medical-dashboard {
grid-template-columns: 1fr;
grid-template-rows: repeat(4, 160px) auto auto auto;
gap: 15px;
}
.wide-panel {
grid-column: span 1;
}
.full-panel {
grid-column: span 1;
}
.overview-value {
font-size: 28px;
}
.chart-box {
min-height: 220px;
}
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<div class="medical-dashboard">
<div class="dashboard-card overview-card" v-loading="loading.overview">
<div class="overview-label">基金会员总数</div>
<div class="overview-value">{{ overview.fundMemberCount || 0 }}</div>
<div class="overview-sub">
本年度申请数:{{ overview.currentYearApplyCount || 0 }}
</div>
</div>
<div class="dashboard-card overview-card" v-loading="loading.overview">
<div class="overview-label">重疾 / 普疾申请数</div>
<div class="overview-value">{{ overview.majorDiseaseApplyCount || 0 }} / {{ overview.commonDiseaseApplyCount || 0 }}</div>
<div class="overview-sub">
统计口径:流程已办结
</div>
</div>
<div class="dashboard-card overview-card" v-loading="loading.overview">
<div class="overview-label">补助金额合计</div>
<div class="overview-value money-text">{{ formatMoney(overview.totalSubsidyMoney) }}</div>
<div class="overview-sub">
单位:元
</div>
</div>
<div class="dashboard-card overview-card" v-loading="loading.overview">
<div class="overview-label">爱心基金合计</div>
<div class="overview-value money-text">{{ formatMoney(overview.totalLoveSubsidyMoney) }}</div>
<div class="overview-sub">
单位:元
</div>
</div>
<div class="dashboard-card wide-panel table-panel">
<div class="dashboard-title">各工会医疗互助统计表</div>
<div class="panel-body" v-loading="loading.unionStat">
<el-table
:data="unionTableData"
:header-cell-style="{background:'#FAFAFA'}"
height="100%"
style="width: 100%">
<el-table-column type="index" label="序号" width="70" align="center"></el-table-column>
<el-table-column prop="unionName" label="工会名称" min-width="180" show-overflow-tooltip></el-table-column>
<el-table-column prop="applyCount" label="申请数" width="100" align="center"></el-table-column>
<el-table-column label="补助金额" min-width="140" align="right">
<template slot-scope="{row}">
{{ formatMoney(row.subsidyMoney) }}
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="dashboard-card wide-panel chart-panel">
<div class="dashboard-title">在职状态分布</div>
<div class="panel-body" v-loading="loading.userStateStat">
<div id="userStateChart" class="chart-box"></div>
</div>
</div>
<div class="dashboard-card full-panel chart-panel">
<div class="dashboard-title">人员类型统计</div>
<div class="panel-body" v-loading="loading.personTypeStat">
<div id="personTypeChart" class="chart-box"></div>
</div>
</div>
<div class="dashboard-card full-panel">
<div class="dashboard-title">疾病类型统计</div>
<div class="panel-body" v-loading="loading.diseaseTypeStat">
<div id="diseaseTypeChart" class="chart-box"></div>
</div>
</div>
</div>
</guava>
</div>
<script nonce="${cspNonce!}">
const chartMap = {
userStateChart: null,
personTypeChart: null,
diseaseTypeChart: null
}
new Vue({
el: "#app",
data() {
return {
loading: {
overview: false,
unionStat: false,
userStateStat: false,
personTypeStat: false,
diseaseTypeStat: false
},
overview: {
fundMemberCount: 0,
currentYearApplyCount: 0,
majorDiseaseApplyCount: 0,
commonDiseaseApplyCount: 0,
totalSubsidyMoney: 0,
totalLoveSubsidyMoney: 0
},
unionTableData: [],
userStateData: [],
personTypeData: [],
diseaseTypeData: []
}
},
methods: {
formatMoney(value) {
if (value === null || value === undefined || value === "") {
return "0.00"
}
const num = Number(value)
if (isNaN(num)) {
return "0.00"
}
return num.toFixed(2)
},
getOverview() {
this.$set(this.loading, "overview", true)
this.$axios.post("/platform/medicalMutualAid/medical/dashboard/overview").then((res) => {
this.$set(this.loading, "overview", false)
if (res.code === 0) {
this.$set(this, "overview", res.data || {})
} else {
this.$message.warning(res.msg)
}
})
},
getUnionStat() {
this.$set(this.loading, "unionStat", true)
this.$axios.post("/platform/medicalMutualAid/medical/dashboard/unionStat").then((res) => {
this.$set(this.loading, "unionStat", false)
if (res.code === 0) {
const tableData = res.data && res.data.tableData ? res.data.tableData : []
this.$set(this, "unionTableData", tableData)
} else {
this.$message.warning(res.msg)
}
})
},
getUserStateStat() {
this.$set(this.loading, "userStateStat", true)
this.$axios.post("/platform/medicalMutualAid/medical/dashboard/userStateStat").then((res) => {
this.$set(this.loading, "userStateStat", false)
if (res.code === 0) {
this.$set(this, "userStateData", res.data || [])
this.renderUserStateChart()
} else {
this.$message.warning(res.msg)
}
})
},
getPersonTypeStat() {
this.$set(this.loading, "personTypeStat", true)
this.$axios.post("/platform/medicalMutualAid/medical/dashboard/personTypeStat").then((res) => {
this.$set(this.loading, "personTypeStat", false)
if (res.code === 0) {
this.$set(this, "personTypeData", res.data || [])
this.renderPersonTypeChart()
} else {
this.$message.warning(res.msg)
}
})
},
getDiseaseTypeStat() {
this.$set(this.loading, "diseaseTypeStat", true)
this.$axios.post("/platform/medicalMutualAid/medical/dashboard/diseaseTypeStat").then((res) => {
this.$set(this.loading, "diseaseTypeStat", false)
if (res.code === 0) {
this.$set(this, "diseaseTypeData", res.data || [])
this.renderDiseaseTypeChart()
} else {
this.$message.warning(res.msg)
}
})
},
renderUserStateChart() {
if (chartMap.userStateChart) {
chartMap.userStateChart.destroy()
}
chartMap.userStateChart = new G2Plot.Pie("userStateChart", {
data: this.userStateData,
angleField: "applyCount",
colorField: "name",
radius: 0.85,
label: {
type: "outer",
content: "{name} {percentage}"
},
legend: {
position: "bottom"
},
color: ["#1f6f5f", "#f59f45", "#5b8ff9", "#9270ca"]
})
chartMap.userStateChart.render()
},
renderPersonTypeChart() {
if (chartMap.personTypeChart) {
chartMap.personTypeChart.destroy()
}
chartMap.personTypeChart = new G2Plot.Column("personTypeChart", {
data: this.personTypeData,
autoFit: true,
xField: "name",
yField: "applyCount",
color: "#4e8f81",
columnStyle: {
radius: [6, 6, 0, 0]
},
label: {
position: "top",
style: {
fill: "#1f2d3d"
}
},
xAxis: {
label: {
autoHide: true,
autoRotate: false
}
},
meta: {
name: {
alias: "人员类型"
},
applyCount: {
alias: "申请数"
}
}
})
chartMap.personTypeChart.render()
},
renderDiseaseTypeChart() {
if (chartMap.diseaseTypeChart) {
chartMap.diseaseTypeChart.destroy()
}
chartMap.diseaseTypeChart = new G2Plot.Bar("diseaseTypeChart", {
data: this.diseaseTypeData,
autoFit: true,
xField: "applyCount",
yField: "name",
legend: false,
color: "#cf6a32",
barStyle: {
radius: [0, 6, 6, 0]
},
label: {
position: "right",
style: {
fill: "#1f2d3d"
}
},
meta: {
name: {
alias: "疾病类型"
},
applyCount: {
alias: "申请数"
}
}
})
chartMap.diseaseTypeChart.render()
},
initData() {
this.getOverview()
this.getUnionStat()
this.getUserStateStat()
this.getPersonTypeStat()
this.getDiseaseTypeStat()
}
},
mounted() {
this.initData()
}
})
</script>
<!--#
}
#-->