Files
UNION_NJUST/src/main/resources/views/platform/levelCheck/school.html
T
c-duxc1 eaac21eebc 南京理工-分级核对需求:
1.工会组织管理页面仅给‘机关党委工会’的成员单位列表加三级单位管理员设置按钮;
2.新增‘分级核对管理’(校工会管理员可见)和‘单位数据核对’(三级单位管理员和分工会管理员可见)菜单页面;
2026-10-14 16:26:16 +08:00

550 lines
28 KiB
HTML

<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava @vchange="guavaViewChange" ref="guava">
<template>
<el-card shadow="never">
<div slot="header">
<span>分级核对任务</span>
<el-button @click="uploadDialogVisible=true" icon="el-icon-upload2"
size="small" style="float:right" type="primary">上传并分发</el-button>
</div>
<el-alert :closable="false" show-icon style="margin-bottom:15px"
title="系统仅按 Excel 的“所在单位”列分发,文件名不参与匹配。"></el-alert>
<el-form :inline="true" :model="taskSearch" size="small">
<el-form-item label="任务名称">
<el-input clearable placeholder="请输入任务名称" v-model="taskSearch.taskName"></el-input>
</el-form-item>
<el-form-item label="任务日期">
<el-date-picker clearable format="yyyy-MM-dd" placeholder="请选择任务日期" type="date"
value-format="yyyy-MM-dd" v-model="taskSearch.taskDate"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button @click="loadTasks(true)" icon="el-icon-search" type="primary">查询</el-button>
<el-button @click="resetTaskSearch">重置</el-button>
</el-form-item>
</el-form>
<el-table :data="tasks" border v-loading="loading">
<el-table-column label="任务名称" prop="name"></el-table-column>
<el-table-column align="center" label="任务日期" min-width="160">
<template slot-scope="scope">{{formatDateTime(scope.row.taskDate)}}</template>
</el-table-column>
<el-table-column align="center" label="完成进度" width="180">
<template slot-scope="scope">{{scope.row.finishedUnits || 0}} / {{scope.row.totalUnits || 0}}</template>
</el-table-column>
<el-table-column label="任务说明" prop="description" show-overflow-tooltip></el-table-column>
<el-table-column align="center" label="操作" width="300">
<template slot-scope="scope">
<el-button @click="openUnits(scope.row)" size="mini" type="primary">单位核对明细</el-button>
<el-button @click="openCurrentData(scope.row)" size="mini" type="primary">查看数据</el-button>
<el-button @click="deleteTask(scope.row)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination :current-page="taskPage.pageNumber" :page-size="taskPage.pageSize"
:page-sizes="[10,20,50,100]" :total="taskPage.totalCount"
@current-change="taskPageNumberChange" @size-change="taskPageSizeChange"
layout="total, sizes, prev, pager, next, jumper"
style="margin-top:15px;text-align:right"></el-pagination>
</el-card>
</template>
<template #edit_func>
<el-button @click="exportCurrent(dataTarget)" icon="el-icon-download"
size="small" type="primary"
v-if="detailView==='data' && dataScope==='task'">导出生效数据</el-button>
<template v-if="detailView==='data' && dataScope==='unit'">
<el-button @click="download(dataTarget,'original')" icon="el-icon-download"
size="small">下载原始数据</el-button>
<el-button @click="download(dataTarget,'pending')" icon="el-icon-download"
size="small" v-if="dataTarget.state===2">下载修改版</el-button>
<el-button @click="download(dataTarget,'current')" icon="el-icon-download"
size="small" type="primary"
v-if="dataVersionType==='current' && dataTarget.state===4">导出已核对版</el-button>
</template>
</template>
<template #edit>
<div key="unit-detail" v-if="detailView==='units'">
<el-divider content-position="left">{{currentTask.name}} - 单位核对明细</el-divider>
<el-form :inline="true" :model="unitSearch" size="small">
<el-form-item label="单位名称">
<el-input clearable placeholder="请输入单位名称" v-model="unitSearch.unitName"></el-input>
</el-form-item>
<el-form-item label="核对状态">
<el-select clearable placeholder="全部" v-model="unitSearch.state">
<el-option :key="index" :label="name" :value="index"
v-for="(name,index) in statusOptions"></el-option>
</el-select>
</el-form-item>
<el-form-item label="核对人员状态">
<el-select clearable placeholder="全部" v-model="unitSearch.managerState">
<el-option label="已分配核对人员" :value="1"></el-option>
<el-option label="未分配核对人员" :value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="loadUnitTasks(true)" icon="el-icon-search" type="primary">查询</el-button>
<el-button @click="resetUnitSearch">重置</el-button>
</el-form-item>
</el-form>
<el-table :data="unitTasks" border v-loading="unitLoading">
<el-table-column label="单位" prop="unitName" show-overflow-tooltip></el-table-column>
<el-table-column align="center" label="行数" prop="rowCount" width="90"></el-table-column>
<el-table-column align="center" label="状态" width="120">
<template slot-scope="scope">
<el-tag :type="statusType(scope.row.state)">{{statusText(scope.row.state)}}</el-tag>
</template>
</el-table-column>
<el-table-column label="核对人员" min-width="180" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.managerNames || scope.row.managernames">
{{scope.row.managerNames || scope.row.managernames}}
</span>
<el-tag type="warning" v-else>未分配核对人员</el-tag>
</template>
</el-table-column>
<el-table-column label="审核意见" prop="auditOpinion" show-overflow-tooltip></el-table-column>
<el-table-column align="center" label="核对日期" min-width="160">
<template slot-scope="scope">
{{formatDateTime(scope.row.checkedAt)}}
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="450">
<template slot-scope="scope">
<el-button @click="openUnitData(scope.row)" size="mini" type="primary">查看原始数据</el-button>
<template v-if="scope.row.state===2">
<el-button @click="openUnitData(scope.row,'pending')" size="mini" type="primary">查看修改版</el-button>
<el-button @click="audit(scope.row,true)" size="mini" type="success">通过</el-button>
<el-button @click="audit(scope.row,false)" size="mini" type="danger">退回</el-button>
</template>
</template>
</el-table-column>
</el-table>
<el-pagination :current-page="unitPage.pageNumber" :page-size="unitPage.pageSize"
:page-sizes="[10,20,50,100]" :total="unitPage.totalCount"
@current-change="unitPageNumberChange" @size-change="unitPageSizeChange"
layout="total, sizes, prev, pager, next, jumper"
style="margin-top:15px;text-align:right"></el-pagination>
</div>
<div key="data-detail" v-else>
<el-divider content-position="left">{{dataDialogTitle}}</el-divider>
<el-form :inline="true" :model="dataSearch" size="small">
<el-form-item>
<el-input @keyup.enter.native="loadDataRows(true)" clearable placeholder="请输入查询内容"
v-model="dataSearch.searchKeyword">
<el-select placeholder="查询字段" slot="prepend" style="width:120px"
v-model="dataSearch.searchName">
<el-option label="薪酬单位代码" value="salaryUnitCode"></el-option>
<el-option label="职工号" value="employeeNo"></el-option>
<el-option label="姓名" value="employeeName"></el-option>
<el-option label="扣工会会费" value="unionFee"></el-option>
<el-option label="年月" value="yearMonth"></el-option>
<el-option label="所在单位" value="unitName"></el-option>
</el-select>
</el-input>
</el-form-item>
<el-form-item label="核对情况">
<el-select clearable placeholder="全部" v-model="dataSearch.state">
<el-option :key="index" :label="name" :value="index"
v-for="(name,index) in statusOptions"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="loadDataRows(true)" icon="el-icon-search" type="primary">查询</el-button>
<el-button @click="resetDataSearch">重置</el-button>
</el-form-item>
</el-form>
<el-table :data="dataRows" border v-loading="dataLoading">
<el-table-column align="center" label="序号" width="70">
<template slot-scope="scope">
{{scope.$index + (dataPage.pageNumber - 1) * dataPage.pageSize + 1}}
</template>
</el-table-column>
<el-table-column label="薪酬单位代码" min-width="130" prop="薪酬单位代码" show-overflow-tooltip></el-table-column>
<el-table-column label="职工号" min-width="120" prop="职工号" show-overflow-tooltip></el-table-column>
<el-table-column label="姓名" min-width="100" prop="姓名" show-overflow-tooltip></el-table-column>
<el-table-column label="扣工会会费" min-width="120" prop="扣工会会费" show-overflow-tooltip></el-table-column>
<el-table-column label="年月" min-width="100" prop="年月" show-overflow-tooltip></el-table-column>
<el-table-column label="所在单位" min-width="180" prop="所在单位" show-overflow-tooltip></el-table-column>
<el-table-column align="center" label="核对情况" min-width="110">
<template slot-scope="scope">
<el-tag :type="statusType(scope.row.state)">{{statusText(scope.row.state)}}</el-tag>
</template>
</el-table-column>
<el-table-column label="核对人员" min-width="180" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.managerNames || scope.row.managernames">
{{scope.row.managerNames || scope.row.managernames}}
</span>
<el-tag type="warning" v-else>未分配核对人员</el-tag>
</template>
</el-table-column>
<el-table-column label="核对日期" min-width="160">
<template slot-scope="scope">
{{formatDateTime(scope.row.checkedAt)}}
</template>
</el-table-column>
</el-table>
<el-pagination :current-page="dataPage.pageNumber" :page-size="dataPage.pageSize"
:page-sizes="[10,20,50,100]" :total="dataPage.totalCount"
@current-change="dataPageNumberChange" @size-change="dataPageSizeChange"
layout="total, sizes, prev, pager, next, jumper"
style="margin-top:15px;text-align:right"></el-pagination>
</div>
</template>
</guava>
<el-dialog :close-on-click-modal="false" :visible.sync="uploadDialogVisible" title="上传并分发" width="50%">
<el-form label-width="90px">
<el-form-item label="任务名称" required>
<el-input maxlength="100" v-model="uploadForm.taskName"></el-input>
</el-form-item>
<el-form-item label="任务说明">
<el-input maxlength="500" type="textarea" v-model="uploadForm.description"></el-input>
</el-form-item>
<el-form-item label="Excel文件" required>
<el-upload :action="uploadAction" :auto-upload="false" :data="uploadForm"
:limit="20" :multiple="true" :on-error="uploadError"
:on-success="uploadSuccess" accept=".xls,.xlsx" name="files" ref="upload">
<el-button icon="el-icon-plus" size="small">选择文件</el-button>
<div class="el-upload__tip" slot="tip">可同时选择多个文件,数据按“所在单位”首段归组。</div>
</el-upload>
<el-button @click="downloadTemplate" icon="el-icon-download"
size="small" style="margin-top:10px">下载导入模板</el-button>
</el-form-item>
</el-form>
<span class="dialog-footer" slot="footer">
<el-button @click="uploadDialogVisible=false">取 消</el-button>
<el-button :loading="uploading" @click="submitUpload" type="primary">上传并分发</el-button>
</span>
</el-dialog>
<el-dialog :close-on-click-modal="false" :visible.sync="rejectDialogVisible"
title="退回修改版" width="45%">
<el-form label-width="90px">
<el-form-item label="退回原因" required>
<el-input :rows="5" maxlength="500" placeholder="请输入退回原因"
show-word-limit type="textarea" v-model="rejectOpinion"></el-input>
</el-form-item>
</el-form>
<span class="dialog-footer" slot="footer">
<el-button @click="rejectDialogVisible=false">取 消</el-button>
<el-button :loading="auditSubmitting" @click="submitReject" type="primary">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
const vue = new Vue({
el: '#app',
data() {
return {
loading: false,
unitLoading: false,
uploading: false,
tasks: [],
unitTasks: [],
statusOptions: ['待核对', '已确认', '待审核', '已退回', '已通过'],
taskSearch: {taskName: '', taskDate: ''},
taskPage: {pageNumber: 1, pageSize: 20, totalCount: 0},
unitSearch: {unitName: '', state: null, managerState: null},
unitPage: {pageNumber: 1, pageSize: 20, totalCount: 0},
currentTask: {},
detailView: '',
dataTarget: {},
dataScope: '',
dataVersionType: 'current',
dataRows: [],
dataLoading: false,
dataDialogTitle: '',
dataSearch: {searchName: 'employeeNo', searchKeyword: '', state: null},
dataPage: {pageNumber: 1, pageSize: 10, totalCount: 0},
uploadDialogVisible: false,
uploadForm: {taskName: '', description: ''},
uploadAction: loc() + '/doUpload',
rejectDialogVisible: false,
rejectTarget: {},
rejectOpinion: '',
auditSubmitting: false
}
},
components: {
'guava': httpVueLoader('/components/plugins/Guava.vue')
},
methods: {
formatDateTime(value) {
return value ? moment(value).format('YYYY-MM-DD HH:mm') : '-'
},
statusText(state) {
return ['待核对', '已确认', '待审核', '已退回', '已通过'][state] || '未知'
},
statusType(state) {
return ['', 'success', 'warning', 'danger', 'success'][state] || 'info'
},
async loadTasks(resetPage) {
if (resetPage) this.taskPage.pageNumber = 1
this.loading = true
const resp = await $.post(loc() + '/taskData', {
taskName: this.taskSearch.taskName,
taskDate: this.taskSearch.taskDate,
pageNumber: this.taskPage.pageNumber,
pageSize: this.taskPage.pageSize
})
this.loading = false
if (resp.code === 0) {
const page = resp.data || {}
this.tasks = page.list || []
this.taskPage.totalCount = page.totalCount || 0
} else this.$notify.warning(resp.msg)
},
resetTaskSearch() {
this.taskSearch = {taskName: '', taskDate: ''}
this.loadTasks(true)
},
taskPageNumberChange(value) {
this.taskPage.pageNumber = value
this.loadTasks(false)
},
taskPageSizeChange(value) {
this.taskPage.pageSize = value
this.loadTasks(true)
},
submitUpload() {
if (!this.uploadForm.taskName) {
this.$notify.warning('请输入任务名称')
return
}
if (!this.$refs.upload.uploadFiles.length) {
this.$notify.warning('请选择 Excel 文件')
return
}
this.uploading = true
const formData = new FormData()
formData.append('taskName', this.uploadForm.taskName)
formData.append('description', this.uploadForm.description || '')
this.$refs.upload.uploadFiles.forEach(item => formData.append('files', item.raw))
$.ajax({
url: this.uploadAction,
type: 'POST',
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: resp => this.uploadSuccess(resp),
error: () => this.uploadError()
})
},
downloadTemplate() {
window.open(loc() + '/downloadTemplate')
},
uploadSuccess(resp) {
this.uploading = false
if (resp.code === 0) {
this.uploadDialogVisible = false
this.$refs.upload.clearFiles()
this.loadTasks(true)
const result = resp.data || {}
if (result.errorCount > 0) {
this.$confirm('共读取 ' + result.totalCount + ' 条,成功分发 ' + result.successCount
+ ' 条,失败 ' + result.errorCount + ' 条。', '导入完成', {
confirmButtonText: '导出错误信息',
cancelButtonText: '关闭',
type: 'warning'
}).then(() => {
window.open(loc() + '/exportImportErrors?cacheKey=' + encodeURIComponent(result.errorCacheKey))
}).catch(() => {})
} else {
this.$notify.success(resp.msg)
}
} else {
this.$notify.warning(resp.msg)
}
},
uploadError() {
this.uploading = false
this.$notify.error('上传失败')
},
async openUnits(row) {
this.currentTask = row
this.detailView = 'units'
this.unitSearch = {unitName: '', state: null, managerState: null}
this.unitPage.pageNumber = 1
this.$refs.guava.edit()
await this.loadUnitTasks(false)
},
guavaViewChange(view) {
if (view.newValue === 'index' && view.oldValue === 'edit'
&& this.detailView === 'data' && this.dataScope === 'unit') {
this.detailView = 'units'
this.$nextTick(() => this.$refs.guava.edit())
}
},
async loadUnitTasks(resetPage) {
if (resetPage) this.unitPage.pageNumber = 1
this.unitLoading = true
const resp = await $.post(loc() + '/unitTaskData', {
taskId: this.currentTask.id,
unitName: this.unitSearch.unitName,
state: this.unitSearch.state,
managerState: this.unitSearch.managerState,
pageNumber: this.unitPage.pageNumber,
pageSize: this.unitPage.pageSize
})
this.unitLoading = false
if (resp.code === 0) {
const page = resp.data || {}
this.unitTasks = page.list || []
this.unitPage.totalCount = page.totalCount || 0
} else this.$notify.warning(resp.msg)
},
resetUnitSearch() {
this.unitSearch = {unitName: '', state: null, managerState: null}
this.loadUnitTasks(true)
},
unitPageNumberChange(value) {
this.unitPage.pageNumber = value
this.loadUnitTasks(false)
},
unitPageSizeChange(value) {
this.unitPage.pageSize = value
this.loadUnitTasks(true)
},
openUnitData(row, versionType) {
this.detailView = 'data'
this.dataScope = 'unit'
this.dataVersionType = versionType || 'current'
this.dataTarget = row
this.dataDialogTitle = row.unitName
+ (this.dataVersionType === 'pending' ? ' - 待审核修改版数据' : ' - 当前生效数据')
this.dataSearch = {searchName: 'employeeNo', searchKeyword: '', state: null}
this.dataPage.pageNumber = 1
this.$refs.guava.edit()
this.loadDataRows(false)
},
openCurrentData(row) {
this.detailView = 'data'
this.dataScope = 'task'
this.dataVersionType = 'current'
this.dataTarget = row
this.dataDialogTitle = row.name + ' - 生效数据'
this.dataSearch = {searchName: 'employeeNo', searchKeyword: '', state: null}
this.dataPage.pageNumber = 1
this.$refs.guava.edit()
this.loadDataRows(false)
},
async loadDataRows(resetPage) {
if (resetPage) this.dataPage.pageNumber = 1
this.dataLoading = true
const url = this.dataScope === 'unit' ? '/unitDataPage' : '/currentDataPage'
const params = {
searchName: this.dataSearch.searchName,
searchKeyword: this.dataSearch.searchKeyword,
state: this.dataSearch.state,
pageNumber: this.dataPage.pageNumber,
pageSize: this.dataPage.pageSize
}
if (this.dataScope === 'unit') {
params.unitTaskId = this.dataTarget.id
params.versionType = this.dataVersionType
}
else params.taskId = this.dataTarget.id
const resp = await $.post(loc() + url, params)
this.dataLoading = false
if (resp.code === 0) {
const page = resp.data || {}
this.dataRows = page.list || []
this.dataPage.totalCount = page.totalCount || 0
} else {
this.dataRows = []
this.dataPage.totalCount = 0
this.$notify.warning(resp.msg)
}
},
resetDataSearch() {
this.dataSearch = {searchName: 'employeeNo', searchKeyword: '', state: null}
this.loadDataRows(true)
},
dataPageNumberChange(value) {
this.dataPage.pageNumber = value
this.loadDataRows(false)
},
dataPageSizeChange(value) {
this.dataPage.pageSize = value
this.loadDataRows(true)
},
download(row, versionType) {
window.open(loc() + '/download?unitTaskId=' + row.id + '&versionType=' + versionType)
},
exportCurrent(row) {
window.open(loc() + '/exportCurrent?taskId=' + row.id)
},
async deleteTask(row) {
try {
await this.$confirm('删除后,该任务的单位数据、修改数据和审核记录都将被清除,且无法恢复。',
'确认删除“' + row.name + '”?', {
confirmButtonText: '确认删除',
cancelButtonText: '取消',
type: 'warning'
})
} catch (e) {
return
}
const resp = await $.post(loc() + '/doDelete', {taskId: row.id})
if (resp.code === 0) {
this.$notify.success(resp.msg)
if (this.currentTask.id === row.id) {
this.$refs.guava.index()
this.currentTask = {}
this.unitTasks = []
}
if (this.dataScope === 'task' && this.dataTarget.id === row.id) {
this.$refs.guava.index()
this.dataTarget = {}
this.dataRows = []
}
this.loadTasks(false)
} else this.$notify.warning(resp.msg)
},
async audit(row, approved) {
if (!approved) {
this.rejectTarget = row
this.rejectOpinion = ''
this.rejectDialogVisible = true
return
}
await this.submitAudit(row, true, '')
},
async submitReject() {
const opinion = (this.rejectOpinion || '').trim()
if (!opinion) {
this.$notify.warning('请输入退回原因')
return
}
this.auditSubmitting = true
const success = await this.submitAudit(this.rejectTarget, false, opinion)
this.auditSubmitting = false
if (success) this.rejectDialogVisible = false
},
async submitAudit(row, approved, opinion) {
const resp = await $.post(loc() + '/doAudit', {unitTaskId: row.id, approved, opinion})
if (resp.code === 0) {
this.$notify.success(resp.msg)
await this.loadUnitTasks(false)
this.loadTasks(false)
return true
}
this.$notify.warning(resp.msg)
return false
}
},
created() {
this.loadTasks(false)
}
})
</script>
<!--#
}
#-->