feat: 工会报销优化
This commit is contained in:
@@ -80,3 +80,10 @@ custom:
|
||||
encrypted-secret-key: ''
|
||||
connect-timeout: 5000
|
||||
read-timeout: 10000
|
||||
|
||||
invoice:
|
||||
tencent:
|
||||
# 发票 OCR 使用腾讯云 SecretId/SecretKey;为空时会回退读取 secret-file 指向的 csv。
|
||||
secret-id: AKID1473y253saFsMelgS4TjnfLofMrAHDyX
|
||||
secret-key: TlrlTzIRNjtIj296riPuISbmqplnhQDy
|
||||
secret-file: C:/Users/Administrator/Desktop
|
||||
@@ -10,9 +10,8 @@ CREATE TABLE IF NOT EXISTS `outlay_annual_base` (
|
||||
`calculatedMoney` decimal(10,2) NOT NULL,
|
||||
`allocateMoney` decimal(10,2) NOT NULL,
|
||||
`remark` varchar(1000) DEFAULT NULL,
|
||||
`status` tinyint NOT NULL DEFAULT 0 COMMENT '0待下拨 1已下拨',
|
||||
`status` tinyint NOT NULL DEFAULT 0 COMMENT '0待下拨 1已下拨 2已重置',
|
||||
`version` int NOT NULL DEFAULT 0,
|
||||
`allocatedAt` bigint DEFAULT NULL,
|
||||
`createdAt` bigint NOT NULL,
|
||||
`createdBy` varchar(32) NOT NULL,
|
||||
`updatedAt` bigint NOT NULL,
|
||||
@@ -30,7 +29,6 @@ CREATE TABLE IF NOT EXISTS `outlay_annual_special` (
|
||||
`remark` varchar(1000) DEFAULT NULL,
|
||||
`status` tinyint NOT NULL DEFAULT 0 COMMENT '0待下拨 1已下拨',
|
||||
`version` int NOT NULL DEFAULT 0,
|
||||
`allocatedAt` bigint DEFAULT NULL,
|
||||
`createdAt` bigint NOT NULL,
|
||||
`createdBy` varchar(32) NOT NULL,
|
||||
`updatedAt` bigint NOT NULL,
|
||||
@@ -53,6 +51,23 @@ CREATE TABLE IF NOT EXISTS `outlay_annual_allocate_log` (
|
||||
KEY `idx_annual_log_record_time` (`allocateType`,`allocateId`,`createdAt`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='经费下拨及调整记录';
|
||||
|
||||
-- 兼容已执行旧版建表脚本的数据库。
|
||||
SET @drop_annual_allocated_at = IF(EXISTS (
|
||||
SELECT 1 FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'outlay_annual_base' AND COLUMN_NAME = 'allocatedAt'
|
||||
), 'ALTER TABLE `outlay_annual_base` DROP COLUMN `allocatedAt`', 'DO 0');
|
||||
PREPARE drop_annual_allocated_at FROM @drop_annual_allocated_at;
|
||||
EXECUTE drop_annual_allocated_at;
|
||||
DEALLOCATE PREPARE drop_annual_allocated_at;
|
||||
|
||||
SET @drop_annual_allocated_at = IF(EXISTS (
|
||||
SELECT 1 FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'outlay_annual_special' AND COLUMN_NAME = 'allocatedAt'
|
||||
), 'ALTER TABLE `outlay_annual_special` DROP COLUMN `allocatedAt`', 'DO 0');
|
||||
PREPARE drop_annual_allocated_at FROM @drop_annual_allocated_at;
|
||||
EXECUTE drop_annual_allocated_at;
|
||||
DEALLOCATE PREPARE drop_annual_allocated_at;
|
||||
|
||||
-- 沿用现有权限与入口,仅调整菜单名称。
|
||||
UPDATE sys_menu SET name='年度经费下拨', aliasName='年度经费下拨'
|
||||
WHERE permission='outlay.outlayManage.union.allocate';
|
||||
|
||||
@@ -177,7 +177,7 @@ layout("/layouts/platform.html"){
|
||||
getTreeData() {
|
||||
this.$set(this, "treeLoading", true)
|
||||
// tree 返回单位树数组;失败时保留现有内容,成功后按 ID 恢复当前单位。
|
||||
return this.$axios.post(loc() + "/tree").then((res) => {
|
||||
return this.$axios.post("/platform/sys/unit/tree").then((res) => {
|
||||
if (res.code !== 0 || !Array.isArray(res.data)) return
|
||||
const selectedId = this.currentTreeData?.id
|
||||
this.$set(this, "treeData", res.data)
|
||||
|
||||
+115
-24
@@ -6,6 +6,14 @@ layout("/layouts/platform.html"){
|
||||
.fund-log-dialog .el-dialog { width: 94%; max-width: 1800px; height: 86vh; display: flex; flex-direction: column; }
|
||||
.fund-log-dialog .el-dialog__body { padding: 16px 24px 24px; flex: 1; min-height: 0; display: flex; flex-direction: column; }
|
||||
.fund-log-dialog .el-pagination { margin-top: 16px; text-align: right; flex: 0 0 auto; }
|
||||
.fund-import-dialog .el-dialog { max-width: calc(100vw - 32px); }
|
||||
.fund-import-dialog .el-dialog__body { padding: 16px 24px; max-height: 68vh; overflow-y: auto; }
|
||||
.fund-import-dialog .el-dialog__footer { border-top: 1px solid #ebeef5; }
|
||||
.fund-import-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 16px 0 8px; }
|
||||
.fund-import-upload .el-upload,
|
||||
.fund-import-upload .el-upload-dragger { display: block; width: 100%; }
|
||||
.fund-import-upload .el-upload-dragger { height: 140px; }
|
||||
.fund-import-upload .el-icon-upload { margin: 16px 0 8px; }
|
||||
.fund-edit-dialog .el-dialog { max-width: calc(100vw - 32px); }
|
||||
.fund-edit-dialog .el-dialog__body { padding: 20px 28px; max-height: 65vh; overflow-y: auto; }
|
||||
.fund-edit-dialog .el-dialog__footer { padding: 16px 28px; border-top: 1px solid #ebeef5; }
|
||||
@@ -23,6 +31,14 @@ layout("/layouts/platform.html"){
|
||||
.fund-edit-amount { display: flex; align-items: center; flex-wrap: wrap; gap: 16px; }
|
||||
.fund-edit-amount .el-input-number { flex: 1; min-width: 200px; }
|
||||
.fund-edit-calculated { display: block; padding: 0 15px; background: #f5f7fa; border: 1px solid #e4e7ed; border-radius: 4px; font-size: 20px; font-weight: 600; color: #303133; }
|
||||
.fund-adjust-dialog .el-dialog__header { padding-bottom: 8px; }
|
||||
.fund-adjust-dialog .el-dialog__body { padding: 12px 24px; }
|
||||
.fund-adjust-dialog .el-dialog__footer { padding: 12px 24px; }
|
||||
.fund-adjust-dialog .el-alert { margin-bottom: 12px; }
|
||||
.fund-adjust-dialog .fund-edit-form { gap: 10px 20px; }
|
||||
.fund-adjust-dialog .fund-edit-section { padding-bottom: 6px; }
|
||||
.fund-adjust-dialog .el-form-item__label { padding-bottom: 4px; line-height: 20px; }
|
||||
.fund-adjust-dialog .fund-edit-difference { padding: 6px 12px; }
|
||||
@media (max-width: 600px) {
|
||||
.fund-edit-form { grid-template-columns: minmax(0, 1fr); }
|
||||
}
|
||||
@@ -35,6 +51,13 @@ layout("/layouts/platform.html"){
|
||||
<search-item label="年度"><el-date-picker v-model="query.year" type="year" value-format="yyyy" :clearable="false" @change="doSearch"></el-date-picker></search-item>
|
||||
<search-item label="分工会"><el-select v-model="query.unionId" clearable filterable @change="doSearch"><el-option v-for="u in unionList" :key="u.id" :value="u.id" :label="u.name"></el-option></el-select></search-item>
|
||||
<search-item v-if="tab==='special'" label="专项名称"><el-input v-model="query.projectName" clearable placeholder="请输入专项名称" @keyup.enter.native="doSearch" @clear="doSearch"></el-input></search-item>
|
||||
<search-item v-if="tab==='base'" label="金额一致性">
|
||||
<el-select v-model="query.amountMatch" @change="doSearch">
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="一致" value="equal"></el-option>
|
||||
<el-option label="不一致" value="different"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
<el-card class="outlay-union-fixed-list-card mt10" shadow="never">
|
||||
@@ -47,8 +70,9 @@ layout("/layouts/platform.html"){
|
||||
<table-tool label="年度经费下拨">
|
||||
<el-button v-if="tab==='base'" size="small" type="primary" @click="generateVisible=true" :disabled="busy">生成年度基础经费</el-button>
|
||||
<el-button v-if="tab==='special'" size="small" type="primary" @click="addSpecial" :disabled="busy">新增专项经费</el-button>
|
||||
<el-button v-if="tab==='base' || tab==='special'" size="small" type="success" @click="batchConfirm" :loading="busy">一键下拨</el-button>
|
||||
<el-button v-if="tab==='base' && isCurrentYear" size="small" type="danger" plain @click="resetBaseRecords" :disabled="busy || loading">重置分配记录</el-button>
|
||||
<el-button v-if="tab==='summary' || tab==='history'" size="small" type="primary" @click="doExport" :disabled="loading || busy">导出Excel</el-button>
|
||||
<el-button v-if="tab==='base'" size="small" type="primary" plain @click="openBaseImport" :disabled="busy || loading">Excel导入金额</el-button>
|
||||
</table-tool>
|
||||
<el-table :key="tab" ref="tableRef" :data="rows" :height="tableHeight" v-loading="loading" border row-key="id">
|
||||
<el-table-column v-if="tab!=='summary'" prop="year" label="年度" width="85"></el-table-column>
|
||||
@@ -71,14 +95,11 @@ layout("/layouts/platform.html"){
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-table-column prop="allocateMoney" label="实际下拨金额(元)" width="160"></el-table-column>
|
||||
<el-table-column label="状态" width="100"><template slot-scope="{row}">{{Number(row.status)===1?'已下拨':'待下拨'}}</template></el-table-column>
|
||||
<el-table-column prop="remark" label="说明" min-width="150" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="下拨时间" width="165"><template slot-scope="{row}">{{time(row.allocatedAt)}}</template></el-table-column>
|
||||
<el-table-column prop="operatorName" label="操作人" width="100"></el-table-column>
|
||||
<el-table-column label="最后操作时间" width="165"><template slot-scope="{row}">{{time(row.updatedAt)}}</template></el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="220"><template slot-scope="{row}">
|
||||
<el-button type="text" :disabled="busy" @click="edit(row)">{{Number(row.status)===1?'调整':'编辑'}}</el-button>
|
||||
<el-button v-if="Number(row.status)===0" type="text" :disabled="busy" @click="confirm(row)">确认下拨</el-button>
|
||||
<el-button type="text" @click="showLogs(row)">操作记录</el-button>
|
||||
</template></el-table-column>
|
||||
</template>
|
||||
@@ -89,7 +110,7 @@ layout("/layouts/platform.html"){
|
||||
</el-card>
|
||||
</div>
|
||||
<el-dialog title="生成年度基础经费" :visible.sync="generateVisible" width="550px" :close-on-click-modal="false">
|
||||
<el-alert title="按所选年度、分工会生成;已有记录不覆盖。人数沿用会员统计口径并保存快照,确认下拨前请核对。" type="info" :closable="false"></el-alert>
|
||||
<el-alert title="按所选年度、分工会生成并计入年度预算。已有记录不覆盖,人数沿用会员统计口径并保存快照。" type="info" :closable="false"></el-alert>
|
||||
<el-form label-width="130px" class="mt10">
|
||||
<el-form-item label="年度">{{query.year}}</el-form-item>
|
||||
<el-form-item label="分工会">{{selectedUnionName}}</el-form-item>
|
||||
@@ -97,8 +118,40 @@ layout("/layouts/platform.html"){
|
||||
</el-form>
|
||||
<span slot="footer"><el-button @click="generateVisible=false" :disabled="busy">取消</el-button><el-button type="primary" :loading="busy" @click="generate">生成</el-button></span>
|
||||
</el-dialog>
|
||||
<el-dialog :title="form.status===1?'调整已下拨经费':'编辑经费'" :visible.sync="editVisible" width="860px" class="fund-edit-dialog" top="6vh" :close-on-click-modal="false" :show-close="!busy">
|
||||
<el-alert v-if="form.status===1" title="当前经费已下拨,保存后将按新旧金额差额调整年度预算,请填写调整原因。" type="warning" show-icon :closable="false"></el-alert>
|
||||
<el-dialog title="Excel导入年度基础经费金额" :visible.sync="baseImportVisible" width="780px" top="6vh" class="fund-import-dialog" :close-on-click-modal="false" :show-close="!busy" destroy-on-close>
|
||||
<el-alert :title="query.year+'年 / '+selectedUnionName" type="info" show-icon :closable="false">
|
||||
请在模板中仅保留需调整的分工会并填写分配额度。导入会更新已有基础经费记录并同步年度预算。任一行未匹配到唯一有效记录时,整批导入失败。
|
||||
</el-alert>
|
||||
<div class="fund-import-toolbar">
|
||||
<strong>导入文件</strong>
|
||||
<el-button size="small" @click="downloadBaseImportTemplate">下载模板</el-button>
|
||||
</div>
|
||||
<el-upload class="fund-import-upload" action="/platform/outlay/outlayManage/unionAllocate/readImportExcel" drag accept=".xls,.xlsx" :limit="1"
|
||||
:before-upload="validateBaseImportFile" :on-exceed="onBaseImportExceed"
|
||||
:on-success="onBaseImportPreview" :on-error="onBaseImportError" :on-remove="clearBaseImportPreview" :disabled="busy">
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将 Excel 文件拖到此处,或<em>点击上传</em></div>
|
||||
<div slot="tip" class="el-upload__tip">支持 .xls、.xlsx,每次上传一个文件</div>
|
||||
</el-upload>
|
||||
<el-form label-position="top" class="mt10">
|
||||
<el-form-item label="调整说明" required>
|
||||
<el-input v-model="baseImportRemark" type="textarea" :rows="2" maxlength="1000" show-word-limit></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table v-if="baseImportRows.length" :data="baseImportRows" max-height="300" border>
|
||||
<el-table-column prop="unionCode" label="工会编码" width="120"></el-table-column>
|
||||
<el-table-column prop="unionName" label="分工会" min-width="180"></el-table-column>
|
||||
<el-table-column prop="allocateMoney" label="实际下拨金额(元)" min-width="150"></el-table-column>
|
||||
<el-table-column label="校验结果" min-width="150"><template slot-scope="{row}">{{row.errMsg || '通过'}}</template></el-table-column>
|
||||
</el-table>
|
||||
<span slot="footer">
|
||||
<el-button @click="baseImportVisible=false" :disabled="busy">取消</el-button>
|
||||
<el-button type="primary" @click="saveBaseImport" :loading="busy" :disabled="!baseImportRows.length">确认导入</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-dialog :title="form.status===1?'调整经费':'编辑经费'" :visible.sync="editVisible" width="860px" class="fund-edit-dialog" :class="{'fund-adjust-dialog': form.status===1}" top="6vh" :close-on-click-modal="false" :show-close="!busy">
|
||||
<el-alert v-if="form.status===1" title="保存后将按新旧金额差额调整年度预算,请填写调整原因。" type="warning" show-icon :closable="false"></el-alert>
|
||||
<el-alert v-else title="保存后金额将计入年度预算。" type="info" show-icon :closable="false"></el-alert>
|
||||
<el-form class="fund-edit-form" label-position="top">
|
||||
<div class="fund-edit-section">基础信息 · {{tab==='base'?'年度基础经费':'专项经费'}}</div>
|
||||
<el-form-item label="年度"><el-date-picker v-model="form.year" type="year" value-format="yyyy" :clearable="false" :disabled="!isNew"></el-date-picker></el-form-item>
|
||||
@@ -139,12 +192,14 @@ layout("/layouts/platform.html"){
|
||||
mixins: [OUTLAY_UNION_FIXED_LIST_MIXIN],
|
||||
dicts: ['OUTLAY_QUARTERLY'],
|
||||
data() { return {
|
||||
tab: 'base', query: {year: this.$moment().format('YYYY'), unionId: '', projectName: '', pageNumber: 1, pageSize: 20},
|
||||
tab: 'base', query: {year: this.$moment().format('YYYY'), unionId: '', projectName: '', amountMatch: '', pageNumber: 1, pageSize: 20},
|
||||
unionList: [], rows: [], total: 0, loading: false, busy: false, requestSequence: 0,
|
||||
standard: 800, generateVisible: false, editVisible: false, isNew: false, form: {}, originalAllocateMoney: 0,
|
||||
baseImportVisible: false, baseImportRows: [], baseImportRemark: '',
|
||||
logsVisible: false, logsLoading: false, logs: [], logPage: 1, logTotal: 0, logRecord: null
|
||||
}},
|
||||
computed: {
|
||||
isCurrentYear() { return this.query.year===this.$moment().format('YYYY') },
|
||||
calculated() { return ((this.form.memberCount || 0) * (this.form.standard || 0)).toFixed(2) },
|
||||
amountDifference() {
|
||||
const amount=Number(this.form.allocateMoney)
|
||||
@@ -153,13 +208,17 @@ layout("/layouts/platform.html"){
|
||||
return Number((amount-reference).toFixed(2))
|
||||
},
|
||||
remarkRequired() { return this.form.status===1 || (this.tab==='base' && this.amountDifference!==0) },
|
||||
amountMatchScope() {
|
||||
if (!this.query.amountMatch) return ''
|
||||
return this.query.amountMatch==='equal'?' / 金额一致':' / 金额不一致'
|
||||
},
|
||||
selectedUnionName() { const u=this.unionList.find(u=>u.id===this.query.unionId); return u?u.name:'全部分工会' }
|
||||
},
|
||||
methods: {
|
||||
time(value) { return value?this.$moment(Number(value)).format('YYYY-MM-DD HH:mm:ss'):'—' },
|
||||
snapshot(value) {
|
||||
if (!value) return '—'
|
||||
try { const v=JSON.parse(value); return v.year+'年 / '+(v.memberCount==null?(v.projectName || ''):v.memberCount+'人 × '+v.standard+'元,计算 '+v.calculatedMoney+'元')+' / 实际 '+v.allocateMoney+'元 / '+(Number(v.status)===1?'已下拨':'待下拨') }
|
||||
try { const v=JSON.parse(value); return v.year+'年 / '+(v.memberCount==null?(v.projectName || ''):v.memberCount+'人 × '+v.standard+'元,计算 '+v.calculatedMoney+'元')+' / 实际 '+v.allocateMoney+'元 / '+(Number(v.status)===2?'已重置':Number(v.status)===1?'已下拨':'待下拨') }
|
||||
catch(e) { return value }
|
||||
},
|
||||
doExport() {
|
||||
@@ -221,27 +280,59 @@ layout("/layouts/platform.html"){
|
||||
try { await this.request('save',payload); this.$message.success('保存成功'); this.editVisible=false; this.doSearch() }
|
||||
catch(e) {} finally { this.busy=false }
|
||||
},
|
||||
async batchConfirm() {
|
||||
if (this.busy) return
|
||||
const params={type:this.tab,year:this.query.year,unionId:this.query.unionId || '',projectName:this.tab==='special'?(this.query.projectName || '').trim():''}
|
||||
const typeName=this.tab==='base'?'年度基础经费':'专项经费'
|
||||
const scope=this.selectedUnionName+(params.projectName?' / 专项名称包含:'+params.projectName:'')
|
||||
if (!params.year) { this.$message.warning('请选择年度'); return }
|
||||
openBaseImport() {
|
||||
this.clearBaseImportPreview()
|
||||
this.baseImportRemark=''
|
||||
this.baseImportVisible=true
|
||||
},
|
||||
downloadBaseImportTemplate() {
|
||||
window.open('/platform/outlay/outlayManage/unionAllocate/downloadImportTemplate')
|
||||
},
|
||||
clearBaseImportPreview() { this.baseImportRows=[] },
|
||||
validateBaseImportFile(file) {
|
||||
if (/\.(xls|xlsx)$/i.test(file.name)) return true
|
||||
this.$message.warning('请上传 .xls 或 .xlsx 文件')
|
||||
return false
|
||||
},
|
||||
onBaseImportExceed() {
|
||||
this.$message.warning('每次只能上传一个 Excel 文件,更换时请先移除已选文件')
|
||||
},
|
||||
onBaseImportPreview(resp) {
|
||||
this.clearBaseImportPreview()
|
||||
if (resp.code===0) this.baseImportRows=resp.data || []
|
||||
else this.$message.error(resp.msg || 'Excel读取失败')
|
||||
},
|
||||
onBaseImportError() {
|
||||
this.clearBaseImportPreview()
|
||||
this.$message.error('Excel上传失败')
|
||||
},
|
||||
async saveBaseImport() {
|
||||
if (this.busy || !this.baseImportRows.length) return
|
||||
if (this.baseImportRows.some(row=>row.errMsg)) { this.$message.warning('请修正校验未通过的记录后重新上传'); return }
|
||||
if (!this.baseImportRemark.trim()) { this.$message.warning('请填写调整说明'); return }
|
||||
this.busy=true
|
||||
try {
|
||||
await this.$confirm('确认一键下拨【'+params.year+'年 / '+scope+'】的全部待下拨'+typeName+'?范围包含所有分页,已下拨记录自动跳过,请先核对金额及历史下拨记录。','一键下拨',{type:'warning'})
|
||||
const resp=await this.request('batchConfirm',params)
|
||||
const resp=await this.request('importBaseAmounts',{
|
||||
year:this.query.year,unionId:this.query.unionId || '',
|
||||
data:JSON.stringify(this.baseImportRows),remark:this.baseImportRemark.trim()
|
||||
})
|
||||
this.$message.success(resp.msg)
|
||||
this.baseImportVisible=false
|
||||
this.doSearch()
|
||||
} catch(e) {} finally { this.busy=false }
|
||||
},
|
||||
async resetBaseRecords() {
|
||||
if (this.busy || !this.isCurrentYear) return
|
||||
const params={year:this.query.year,unionId:this.query.unionId || '',amountMatch:this.query.amountMatch}
|
||||
const scope=params.year+'年 / '+this.selectedUnionName+this.amountMatchScope
|
||||
this.busy=true
|
||||
try {
|
||||
await this.$confirm('确认重置【'+scope+'】全部分页中的基础经费分配记录?已计入预算的金额将扣回,重置后可重新生成。','重置分配记录',{type:'warning',confirmButtonText:'确认重置'})
|
||||
const resp=await this.request('resetBaseRecords',params)
|
||||
this.$message.success(resp.msg)
|
||||
this.load()
|
||||
} catch(e) {} finally { this.busy=false }
|
||||
},
|
||||
async confirm(row) {
|
||||
try { await this.$confirm('确认向【'+row.unionName+'】下拨 '+row.allocateMoney+' 元?此操作将计入年度预算,请核对历史下拨记录。','确认下拨',{type:'warning'}) }
|
||||
catch(e) { return }
|
||||
this.busy=true
|
||||
try { await this.request('confirm',{type:this.tab,id:row.id,version:row.version}); this.$message.success('下拨成功'); this.load() }
|
||||
catch(e) {} finally { this.busy=false }
|
||||
},
|
||||
showLogs(row) { this.logRecord={id:row.id,type:this.tab}; this.logPage=1; this.logsVisible=true; this.loadLogs() },
|
||||
async loadLogs() {
|
||||
this.logsLoading=true
|
||||
|
||||
+6
-12
@@ -4,22 +4,15 @@ let OUTLAY_MANAGE_UNION_QUARTERLY_ALLOCATE = {
|
||||
`
|
||||
<div>
|
||||
<template>
|
||||
<table-tool label="分配记录"></table-tool>
|
||||
<table-tool label="年度已下拨记录"></table-tool>
|
||||
<el-table :data="tableData" style="width: 100%" row-key="id" class="vi-table">
|
||||
<el-table-column type="index" label="序号" width="80px"></el-table-column>
|
||||
<el-table-column label="分配项目" prop="quarterly">
|
||||
<template v-slot="{row}">
|
||||
<dict-tag :options="dict.type.OUTLAY_QUARTERLY"
|
||||
:value="row.quarterly"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="年初数" prop="allocateHeadMoney"></el-table-column>
|
||||
<el-table-column label="经费额度" prop="allocateMoney"></el-table-column>
|
||||
<el-table-column label="分配项目" prop="projectName"></el-table-column>
|
||||
<el-table-column label="实际下拨金额(元)" prop="allocateMoney"></el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
</div>
|
||||
`,
|
||||
dicts: ["OUTLAY_QUARTERLY"],
|
||||
data() {
|
||||
return {
|
||||
rowData: {},
|
||||
@@ -29,11 +22,12 @@ let OUTLAY_MANAGE_UNION_QUARTERLY_ALLOCATE = {
|
||||
methods: {
|
||||
open(row) {
|
||||
this.rowData = row
|
||||
this.$axios.post("/platform/outlay/outlayManage/unionUseDetail/queryQuarterlyList", {
|
||||
this.tableData = []
|
||||
this.$axios.post("/platform/outlay/outlayManage/unionUseDetail/queryAnnualAllocateList", {
|
||||
year: row.year,
|
||||
unionId: row.unionId
|
||||
}).then(resp => {
|
||||
if (resp.code === 0) {
|
||||
if (this.rowData === row && resp.code === 0) {
|
||||
this.tableData = resp.data
|
||||
}
|
||||
})
|
||||
|
||||
+40
-26
@@ -52,6 +52,21 @@ layout("/layouts/platform.html"){
|
||||
.payment-info-table .el-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.invoice-detail-dialog {
|
||||
max-width: calc(100vw - 32px);
|
||||
}
|
||||
|
||||
.invoice-detail-dialog .el-dialog__body {
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
padding: 12px 24px;
|
||||
}
|
||||
|
||||
.invoice-detail-dialog .el-form-item__label {
|
||||
line-height: 22px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
@@ -266,7 +281,7 @@ layout("/layouts/platform.html"){
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="报销金额" v-if="isManualReimburseAmount">
|
||||
<el-form-item label="报销金额" prop="money">
|
||||
<el-input v-model="formData.money" placeholder="请输入报销金额,最多两位小数"></el-input>
|
||||
<el-input :value="formData.money" @input="updateReimburseAmount" placeholder="请输入报销金额,最多两位小数"></el-input>
|
||||
</el-form-item>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="所属协会"
|
||||
@@ -605,11 +620,11 @@ layout("/layouts/platform.html"){
|
||||
<div>
|
||||
<div class="invoice-toolbar-title">发票明细列表</div>
|
||||
<div class="invoice-summary-tip">
|
||||
{{ isManualReimburseAmount ? '发票选填;有发票时报销金额不得超过发票总额,无发票仍可提交。' : '发票选填;无发票时按支付信息汇总报销金额。' }}上传后须通过验真,每条明细对应一张发票图片或单页 PDF。
|
||||
提交时至少上传一张发票,上传后须通过验真。每条明细对应一张发票图片或单页 PDF。
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<el-tag type="info">发票选填,上传须验真</el-tag>
|
||||
<el-tag type="info">提交时必填</el-tag>
|
||||
<el-button @click="openInvoiceDialog('add')" plain type="primary"
|
||||
style="margin-left: 12px">新增发票
|
||||
</el-button>
|
||||
@@ -677,10 +692,11 @@ layout("/layouts/platform.html"){
|
||||
:title="invoiceDialogMode === 'edit' ? '编辑发票明细' : '新增发票明细'"
|
||||
:visible.sync="invoiceDialogVisible"
|
||||
append-to-body
|
||||
width="820px">
|
||||
<el-form :model="detailForm" :rules="detailRules" label-position="right"
|
||||
label-suffix=":" label-width="120px" ref="invoiceDetailForm">
|
||||
<el-row :gutter="30">
|
||||
custom-class="invoice-detail-dialog"
|
||||
top="5vh"
|
||||
width="1000px">
|
||||
<el-form :model="detailForm" :rules="detailRules" label-position="top" ref="invoiceDetailForm">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="发票文件" prop="invoiceFiles">
|
||||
<file-upload
|
||||
@@ -700,41 +716,41 @@ layout("/layouts/platform.html"){
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="发票号码" prop="invoiceNo">
|
||||
<el-input placeholder="验真后自动回填" v-model="detailForm.invoiceNo" readonly></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="开票日期">
|
||||
<el-input placeholder="识别后自动回填" v-model="detailForm.invoiceDate" readonly></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :xs="24" :sm="8">
|
||||
<el-form-item label="价税合计" prop="invoiceAmount">
|
||||
<el-input-number :controls="false" :min="0" :precision="2"
|
||||
placeholder="验真后自动回填" style="width: 100%"
|
||||
v-model="detailForm.invoiceAmount" disabled></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :xs="24" :sm="8">
|
||||
<el-form-item label="税前金额">
|
||||
<el-input-number :controls="false" :precision="2" style="width: 100%"
|
||||
v-model="detailForm.amountWithoutTax" disabled></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :xs="24" :sm="8">
|
||||
<el-form-item label="税额">
|
||||
<el-input-number :controls="false" :precision="2" style="width: 100%"
|
||||
v-model="detailForm.taxAmount" disabled></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="销售方信息名称" prop="sellerName">
|
||||
<el-input placeholder="验真后自动回填" v-model="detailForm.sellerName" readonly></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :xs="24" :sm="12">
|
||||
<el-form-item label="项目名称" prop="itemName">
|
||||
<el-input placeholder="验真后自动回填" v-model="detailForm.itemName" readonly></el-input>
|
||||
</el-form-item>
|
||||
@@ -1647,7 +1663,10 @@ layout("/layouts/platform.html"){
|
||||
return false
|
||||
}
|
||||
const invoiceDetails = this.formData.invoiceDetails || []
|
||||
// 发票可不上传;已经添加的发票仍须填写完整并沿用验真流程。
|
||||
if (!invoiceDetails.length) {
|
||||
this.$message.warning("提交前请至少上传一张发票")
|
||||
return false
|
||||
}
|
||||
for (let i = 0; i < invoiceDetails.length; i++) {
|
||||
const currentDetail = invoiceDetails[i]
|
||||
if (!currentDetail.invoiceFiles || currentDetail.invoiceFiles.length === 0) {
|
||||
@@ -1710,6 +1729,11 @@ layout("/layouts/platform.html"){
|
||||
this.syncLegacyPaymentFields(submitData.paymentDetails, submitData)
|
||||
return submitData
|
||||
},
|
||||
updateReimburseAmount(value) {
|
||||
this.$set(this.formData, "money", value)
|
||||
const details = this.formData.paymentDetails || []
|
||||
if (details.length === 1) this.$set(details[0], "money", value)
|
||||
},
|
||||
// 金额输入允许编辑中的空值和末尾小数点;非法字符或超出两位小数时恢复原值,避免改变金额含义。
|
||||
inputPaymentMoney(row, value) {
|
||||
const previous = row.money
|
||||
@@ -1831,18 +1855,8 @@ layout("/layouts/platform.html"){
|
||||
// 保存
|
||||
onSave() {
|
||||
if (this.formLoading || this.recognizingInvoice) return
|
||||
if (!this.validateInvoiceDetailsBeforeSubmit()) {
|
||||
this.$set(this, "activeTabName", "invoice")
|
||||
return
|
||||
}
|
||||
this.rebuildInvoiceSummary()
|
||||
this.normalizeFundBalance()
|
||||
const paymentDetails = this.preparePaymentDetailsForSubmit()
|
||||
// 保存草稿也必须填写完整支付信息,避免非法金额和空明细入库。
|
||||
if (!this.validatePaymentDetailsBeforeSubmit(paymentDetails)) {
|
||||
this.$set(this, "activeTabName", "invoice")
|
||||
return
|
||||
}
|
||||
this.$confirm("您确定保存吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
@@ -1850,7 +1864,7 @@ layout("/layouts/platform.html"){
|
||||
}).then(() => {
|
||||
if (this.formLoading) return
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/platform/unionReimburse/apply/save", {data: JSON.stringify(this.buildSubmitFormData(paymentDetails))}).then(res => {
|
||||
this.$axios.post("/platform/unionReimburse/apply/save", {data: JSON.stringify(this.buildSubmitFormData())}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
commonUtil.pjaxPush("/platform/unionReimburse/mine/index")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const unionReimburseInfo = {
|
||||
template: /*language=HTML*/ `
|
||||
<div>
|
||||
<div class="process-title">
|
||||
申请信息
|
||||
<div class="process-title" style="display: flex; align-items: center; justify-content: space-between; gap: 12px;">
|
||||
<span>申请信息</span>
|
||||
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
|
||||
</div>
|
||||
|
||||
|
||||
+14
-11
@@ -682,7 +682,8 @@ layout("/layouts/platform_h5.html"){
|
||||
></van-field>
|
||||
<van-field v-if="isManualReimburseAmount"
|
||||
label="报销金额" name="money"
|
||||
v-model="formData.money"
|
||||
:model-value="formData.money"
|
||||
@update:model-value="updateReimburseAmount"
|
||||
placeholder="请输入报销金额,最多两位小数"
|
||||
:rules="[{ required: true, message: '请填写报销金额' }, { validator: () => !getReimburseAmountMessage(), message: getReimburseAmountMessage }]"
|
||||
required></van-field>
|
||||
@@ -773,8 +774,8 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-action-sheet>
|
||||
</van-cell-group>
|
||||
<van-cell-group class="form-section" v-if="formData.reimburseProject">
|
||||
<div class="form-section__title">电子发票(选填)</div>
|
||||
<div class="invoice-tip">{{ isManualReimburseAmount ? '有发票时报销金额不得超过发票总额,无发票仍可提交;上传的发票仍须通过验真。' : '无发票时按支付信息汇总报销金额;上传的发票仍须通过验真。' }}</div>
|
||||
<div class="form-section__title">电子发票(提交时必填)</div>
|
||||
<div class="invoice-tip">提交时至少上传一张发票,上传后须通过验真。</div>
|
||||
<van-field label="报销金额"
|
||||
v-model="formData.money"
|
||||
:placeholder="isManualReimburseAmount ? '请在报销信息填写报销金额' : '有发票按发票汇总,无发票按支付信息汇总'"
|
||||
@@ -1942,7 +1943,10 @@ layout("/layouts/platform_h5.html"){
|
||||
return false
|
||||
}
|
||||
const invoiceDetails = this.formData.invoiceDetails || []
|
||||
// 发票可不上传;已经添加的发票仍须填写完整并沿用验真流程。
|
||||
if (!invoiceDetails.length) {
|
||||
this.$toast.fail("提交前请至少上传一张发票")
|
||||
return false
|
||||
}
|
||||
for (let i = 0; i < invoiceDetails.length; i++) {
|
||||
const currentDetail = invoiceDetails[i]
|
||||
if (!currentDetail.invoiceFiles || currentDetail.invoiceFiles.length === 0) {
|
||||
@@ -2190,6 +2194,11 @@ layout("/layouts/platform_h5.html"){
|
||||
this.syncLegacyPaymentFields(submitData.paymentDetails, submitData)
|
||||
return submitData
|
||||
},
|
||||
updateReimburseAmount(value) {
|
||||
this.$set(this.formData, "money", value)
|
||||
const details = this.formData.paymentDetails || []
|
||||
if (details.length === 1) this.$set(details[0], "money", value)
|
||||
},
|
||||
// 金额输入允许编辑中的空值和末尾小数点;非法字符或超出两位小数时恢复原值,避免改变金额含义。
|
||||
inputPaymentMoney(row, value) {
|
||||
const previous = row.money
|
||||
@@ -2323,17 +2332,11 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
onSave() {
|
||||
if (this.formLoading || this.recognizingInvoice) return
|
||||
if (!this.validateInvoiceDetailsBeforeSubmit()) return
|
||||
this.normalizeContactFields()
|
||||
this.normalizeCondolenceDateFields()
|
||||
this.rebuildInvoiceSummary()
|
||||
const paymentDetails = this.preparePaymentDetailsForSubmit()
|
||||
// 保存草稿也必须填写完整支付信息,避免非法金额和空明细入库。
|
||||
if (!this.validatePaymentDetailsBeforeSubmit(paymentDetails)) {
|
||||
return
|
||||
}
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/platform/unionReimburse/apply/save", { data: JSON.stringify(this.buildSubmitFormData(paymentDetails)) })
|
||||
this.$axios.post("/platform/unionReimburse/apply/save", { data: JSON.stringify(this.buildSubmitFormData()) })
|
||||
.then((res) => {
|
||||
this.$toast.clear()
|
||||
if (res.code === 0) {
|
||||
|
||||
Reference in New Issue
Block a user