Browse Source

年度报表2

master
xuhuajiao 3 weeks ago
parent
commit
78d1376b16
  1. 28
      src/api/statistics/statistics.js
  2. 165
      src/views/archivesStatistics/Da3Report.vue
  3. 14
      src/views/archivesStatistics/annualReport‌/index.vue

28
src/api/statistics/statistics.js

@ -67,10 +67,28 @@ export function FetchInitStatisticsTemplate(params) {
}) })
} }
// 保存报表填报数据
export function SaveStatisticsTemplate(data) {
// 保存年度报表明细
export function FetchEditArchivesReportDetails(data) {
return request({ return request({
url: 'api/archives-report/save',
url: 'api/archives-report/editArchivesReportDetails',
method: 'post',
data
})
}
// 重新计算年度报表
export function FetchRecalculateArchivesReport(data) {
return request({
url: 'api/archives-report/recalculateArchivesReport',
method: 'post',
data
})
}
// 重新计算收集库信息
export function FetchRecalculateArchivesDoReport(data) {
return request({
url: 'api/archives-report/recalculateArchivesDoReport',
method: 'post', method: 'post',
data data
}) })
@ -129,6 +147,10 @@ export default {
FetchPageReports, FetchPageReports,
FetchSaveArchivesReport, FetchSaveArchivesReport,
FetchFindArchivesReportById, FetchFindArchivesReportById,
FetchRecalculateArchivesReport,
FetchEditArchivesReportDetails,
FetchRecalculateArchivesDoReport,
FetchInitStatisticsTemplate,
FetchAnnualStatisticalTemplateAll, FetchAnnualStatisticalTemplateAll,
FetchDeleteArchivesReport FetchDeleteArchivesReport
} }

165
src/views/archivesStatistics/Da3Report.vue

@ -141,6 +141,12 @@
</table> </table>
<!-- 编辑模式:底部固定保存栏 --> <!-- 编辑模式:底部固定保存栏 -->
<!-- 查看模式工具栏 -->
<div v-if="isView" class="save-bar">
<el-button @click="exportExcel">导出Excel</el-button>
<el-button @click="handleCancel">关闭</el-button>
</div>
<!-- 编辑模式工具栏 -->
<div v-if="!isView" class="save-bar"> <div v-if="!isView" class="save-bar">
<el-button class="saveetch-btn" type="primary" :loading="refetchLoading" @click="handleRefetch">重新获取统计数据</el-button> <el-button class="saveetch-btn" type="primary" :loading="refetchLoading" @click="handleRefetch">重新获取统计数据</el-button>
<el-button @click="exportExcel">导出Excel</el-button> <el-button @click="exportExcel">导出Excel</el-button>
@ -151,7 +157,7 @@
</template> </template>
<script> <script>
import { FetchInitStatisticsTemplate, SaveStatisticsTemplate } from '@/api/statistics/statistics'
import { FetchInitStatisticsTemplate, FetchRecalculateArchivesDoReport, FetchEditArchivesReportDetails } from '@/api/statistics/statistics'
import ExcelJS from 'exceljs' import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver' import { saveAs } from 'file-saver'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
@ -225,26 +231,12 @@ export default {
created() { created() {
this.fetchReport() this.fetchReport()
}, },
beforeDestroy() {
sessionStorage.removeItem('da3_fondsName')
},
methods: { methods: {
fetchReport() { fetchReport() {
const { reportingYear, unitId, templateId } = this.$route.query const { reportingYear, unitId, templateId } = this.$route.query
// 尝试读缓存(annualReport 预检时写入)
const cacheKey = 'da3_report_cache_' + reportingYear + '_' + unitId
let cached = null
try {
const raw = sessionStorage.getItem(cacheKey)
if (raw) cached = JSON.parse(raw)
} catch (e) { /* 解析失败忽略 */ }
if (cached) {
console.log('[Da3Report] 使用缓存数据', cached)
this.rawReport = cached
const model = this.normalizeModel(cached)
if (model) this.remoteModel = model
// 缓存用一次后清掉,避免脏数据
sessionStorage.removeItem(cacheKey)
return
}
this.loading = true this.loading = true
FetchInitStatisticsTemplate({ FetchInitStatisticsTemplate({
@ -302,14 +294,29 @@ export default {
const body = [] const body = []
const formData = { units: {}, data: {}} const formData = { units: {}, data: {}}
const leftCards = ['01', '02', '03', '04', '05'] const leftCards = ['01', '02', '03', '04', '05']
// 填报值:inputType 为 'code'/'number' 时用 valCurNum,'text' 时用 valCurText
// 填报值:优先按 inputType 取对应字段,没有则取另一个字段,都没有则为空
const pickVal = (r, which) => { const pickVal = (r, which) => {
const t = r.inputType const t = r.inputType
if (which === 'cur') {
// 本年:code/number 优先 valCurNum,text 优先 valCurText
if (t === 'code' || t === 'number') { if (t === 'code' || t === 'number') {
return which === 'cur' ? (r.valCurNum != null ? r.valCurNum : '') : (r.valPrevNum != null ? r.valPrevNum : '')
if (r.valCurNum != null) return r.valCurNum
if (r.valCurText != null) return r.valCurText
} else {
if (r.valCurText != null) return r.valCurText
if (r.valCurNum != null) return r.valCurNum
}
} else {
// 上年:code/number 优先 valPrevNum,text 优先 valPrevText
if (t === 'code' || t === 'number') {
if (r.valPrevNum != null) return r.valPrevNum
if (r.valPrevText != null) return r.valPrevText
} else {
if (r.valPrevText != null) return r.valPrevText
if (r.valPrevNum != null) return r.valPrevNum
} }
// text 或其他类型用 valCurText / valPrevText
return which === 'cur' ? (r.valCurText != null ? r.valCurText : '') : (r.valPrevText != null ? r.valPrevText : '')
}
return ''
} }
flat.forEach(r => { flat.forEach(r => {
@ -326,7 +333,8 @@ export default {
card: leftCards.indexOf(r.code) !== -1 ? 1 : 2, card: leftCards.indexOf(r.code) !== -1 ? 1 : 2,
kind: r.inputType === 'code' ? 'code' : 'text' kind: r.inputType === 'code' ? 'code' : 'text'
}) })
formData.units[r.code] = unitValues[r.code] != null ? unitValues[r.code] : (r.valCurText || '')
const curVal = pickVal(r, 'cur')
formData.units[r.code] = unitValues[r.code] != null ? unitValues[r.code] : (curVal != null && curVal !== '' ? curVal : (r.valCurText || r.valCurNum || ''))
return return
} }
@ -379,10 +387,6 @@ export default {
filler: res.filler || '', filler: res.filler || '',
submitTime: res.submitTime || '' submitTime: res.submitTime || ''
} }
// 填表人默认取当前登录用户名(接口无值时)
if (!footerFormData.filler && this.user && this.user.username) {
footerFormData.filler = this.user.username
}
const footer = [ const footer = [
{ col: 1, label: '单位负责人:' + footerFormData.unitHead }, { col: 1, label: '单位负责人:' + footerFormData.unitHead },
{ col: 5, label: '统计负责人:' + footerFormData.statsHead }, { col: 5, label: '统计负责人:' + footerFormData.statsHead },
@ -408,7 +412,7 @@ export default {
this.$set(this.form, code + '_p', item.prev) this.$set(this.form, code + '_p', item.prev)
}) })
} }
// 回填页脚签章
// 回填页脚签章(formData.footer 或 d.footerForm 都会走到这里)
if (formData.footer) { if (formData.footer) {
Object.keys(this.footerForm).forEach(k => { Object.keys(this.footerForm).forEach(k => {
if (formData.footer[k] != null) this.footerForm[k] = formData.footer[k] if (formData.footer[k] != null) this.footerForm[k] = formData.footer[k]
@ -572,6 +576,10 @@ export default {
ws.getCell('I6').alignment = { horizontal: 'right', vertical: 'middle' } ws.getCell('I6').alignment = { horizontal: 'right', vertical: 'middle' }
ws.getCell('I7').value = `有效期至:${this.data.template.valid_to}` ws.getCell('I7').value = `有效期至:${this.data.template.valid_to}`
ws.getCell('I7').font = { size: 10 } ws.getCell('I7').font = { size: 10 }
// 第7行 06 上方加当前年报年份
ws.getCell('G7').value = `${this.data.template.cur_year}年`
ws.getCell('G7').font = { size: 10 }
ws.getCell('G7').alignment = { horizontal: 'center', vertical: 'middle' }
ws.getCell('I7').alignment = { horizontal: 'right', vertical: 'middle' } ws.getCell('I7').alignment = { horizontal: 'right', vertical: 'middle' }
// ===== 第11行:表头(指标名称合并A-E) ===== // ===== 第11行:表头(指标名称合并A-E) =====
@ -688,7 +696,8 @@ export default {
// 生成并下载 // 生成并下载
const buffer = await wb.xlsx.writeBuffer() const buffer = await wb.xlsx.writeBuffer()
const fileName = `${this.data.template.title}_${this.data.template.cur_year}年.xlsx`
const fondsName = sessionStorage.getItem('da3_fondsName') || (this.rawReport && this.rawReport.fondsName) || this.form.u_02 || ''
const fileName = `${this.data.template.title}_${this.data.template.cur_year}年_${fondsName}.xlsx`
saveAs(new Blob([buffer]), fileName) saveAs(new Blob([buffer]), fileName)
}, },
// 保存:基于接口原始结构回填用户输入(数值也写入 text 字段,与回显口径一致) // 保存:基于接口原始结构回填用户输入(数值也写入 text 字段,与回显口径一致)
@ -717,6 +726,21 @@ export default {
// 指标行回填:inputType 为 'code'/'number' 写 valCurNum/valPrevNum,'text' 写 valCurText/valPrevText // 指标行回填:inputType 为 'code'/'number' 写 valCurNum/valPrevNum,'text' 写 valCurText/valPrevText
const walk = list => { const walk = list => {
(list || []).forEach(r => { (list || []).forEach(r => {
// 单位信息行(01-07)回填到 rows 对应节点
if (r.itemType === 'unit' && r.code) {
const v = this.form['u_' + r.code]
const val = v === '' || v == null ? null : v
if (r.inputType === 'code' || r.inputType === 'number') {
const num = Number(val)
if (val != null && !isNaN(num)) {
r.valCurNum = num
} else {
r.valCurText = val != null ? String(val) : null
}
} else {
r.valCurText = val != null ? String(val) : null
}
}
if (r.itemType === 'indicator' && r.isLeaf && r.code) { if (r.itemType === 'indicator' && r.isLeaf && r.code) {
const cur = this.form[r.code + '_c'] const cur = this.form[r.code + '_c']
const prev = this.form[r.code + '_p'] const prev = this.form[r.code + '_p']
@ -735,26 +759,91 @@ export default {
} }
walk(payload.rows) walk(payload.rows)
// 页脚签章回填到顶层字段
payload.unitHead = this.footerForm.unitHead || null
payload.statsHead = this.footerForm.statsHead || null
payload.filler = this.footerForm.filler || null
payload.submitTime = this.footerForm.submitTime || null
// 拍平 rows,只保留接口需要的字段
const flatList = []
const flatten = list => {
(list || []).forEach(r => {
if (r.code) {
flatList.push({
indicatorCode: r.code,
reportId: payload.reportId != null ? payload.reportId : null,
valCurNum: r.valCurNum != null ? r.valCurNum : null,
valCurText: r.valCurText != null ? r.valCurText : null,
valPrevNum: r.valPrevNum != null ? r.valPrevNum : null,
valPrevText: r.valPrevText != null ? r.valPrevText : null
})
}
if (r.children && r.children.length) flatten(r.children)
})
}
flatten(payload.rows)
// 组装最终传参
const savePayload = {
reportId: payload.reportId != null ? payload.reportId : null,
unitCreditCode: this.form.u_01 || null,
unitName: this.form.u_02 || null,
unitCategoryCode: this.form.u_03 || null,
postalCode: this.form.u_04 || null,
unitAddress: this.form.u_05 || null,
telephone: this.form.u_06 || null,
orgSituation: this.form.u_07 || null,
unitHead: this.footerForm.unitHead || null,
statsHead: this.footerForm.statsHead || null,
filler: this.footerForm.filler || null,
submitTime: this.footerForm.submitTime || null,
reportDataList: flatList
}
this.saving = true this.saving = true
SaveStatisticsTemplate(payload).then(() => {
this.$message({ message: '保存成功', type: 'success', offset: 80 })
console.log('payload', savePayload)
FetchEditArchivesReportDetails(savePayload).then((res) => {
console.log('保存成功', res)
if (res.code !== 500) {
this.$message({ message: res, type: 'success', offset: 80 })
this.fetchReport()
} else {
this.$message({ message: res.message || '保存失败', type: 'error', offset: 80 })
}
}).catch(() => {
this.$message({ message: '保存失败', type: 'error', offset: 80 })
}).finally(() => { }).finally(() => {
this.saving = false this.saving = false
}) })
}, },
// 重新获取统计数据:点击后调用 fetchReport 重新获取接口数据
// 重新获取统计数据
handleRefetch() { handleRefetch() {
this.refetchLoading = true this.refetchLoading = true
this.fetchReport()
FetchRecalculateArchivesDoReport(this.rawReport.reportId).then((res) => {
console.log('重新计算成功', res)
if (res.code !== 500) {
// 根据 value{code}_{1|2} 回填表单:1=本年,2=上年
if (res && typeof res === 'object') {
Object.keys(res).forEach(key => {
const m = key.match(/^value(\d+)_(1|2)$/)
if (m) {
const code = m[1]
const type = m[2] // 1=本年 2=上年
const val = res[key]
if (type === '1') {
this.$set(this.form, code + '_c', val)
} else {
this.$set(this.form, code + '_p', val)
}
}
})
}
this.$message({ message: '重新计算成功', type: 'success', offset: 80 })
} else {
this.$message({ message: res.message || '重新计算失败', type: 'error', offset: 80 })
}
}).finally(() => {
this.refetchLoading = false
})
}, },
// 取消:点击后关闭当前路由 // 取消:点击后关闭当前路由
handleCancel() { handleCancel() {
sessionStorage.removeItem('da3_fondsName')
window.close() window.close()
} }
} }

14
src/views/archivesStatistics/annualReport‌/index.vue

@ -43,8 +43,8 @@
<el-table v-loading="loading" class="archives-table" :data="allData" style="width: 100%;"> <el-table v-loading="loading" class="archives-table" :data="allData" style="width: 100%;">
<el-table-column prop="reportingYear" label="年度" align="center" width="100" /> <el-table-column prop="reportingYear" label="年度" align="center" width="100" />
<el-table-column prop="fondsName" label="填报单位" /> <el-table-column prop="fondsName" label="填报单位" />
<el-table-column prop="createBy" label="创建人" />
<el-table-column prop="createdAt" label="创建时间">
<el-table-column prop="createBy" label="创建人" width="120" />
<el-table-column prop="createdAt" label="创建时间" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<div>{{ scope.row.createdAt | parseTime }}</div> <div>{{ scope.row.createdAt | parseTime }}</div>
</template> </template>
@ -319,6 +319,9 @@ export default {
}) })
}, },
handleEditDetail() { handleEditDetail() {
const fondsItem = this.fondsOptions.find(f => f.id === this.form.unitId)
const fondsName = fondsItem ? fondsItem.fondsName : ''
sessionStorage.setItem('da3_fondsName', fondsName)
this.checkAndOpenReport('edit', { this.checkAndOpenReport('edit', {
reportingYear: this.form.reportingYear, reportingYear: this.form.reportingYear,
unitId: this.form.unitId, unitId: this.form.unitId,
@ -347,9 +350,8 @@ export default {
this.detailData = {} this.detailData = {}
}, },
handleReportDetail() { handleReportDetail() {
// 行数据无全宗 id 时,按填报单位名称匹配
// const fondsItem = this.fondsOptions.find(f => f.fondsName === this.detailData.archivesCount)
const unitId = this.detailData.unitId const unitId = this.detailData.unitId
sessionStorage.setItem('da3_fondsName', this.detailData.fondsName || '')
this.checkAndOpenReport('view', { this.checkAndOpenReport('view', {
reportingYear: this.detailData.reportingYear, reportingYear: this.detailData.reportingYear,
unitId, unitId,
@ -369,10 +371,6 @@ export default {
console.log('FetchInitStatisticsTemplate', res) console.log('FetchInitStatisticsTemplate', res)
// 接口正常且模板行有数据才放行 // 接口正常且模板行有数据才放行
if (res && Array.isArray(res.rows) && res.rows.length) { if (res && Array.isArray(res.rows) && res.rows.length) {
// 预检结果缓存到 sessionStorage,Da3Report 直接读取避免重复调接口
try {
sessionStorage.setItem('da3_report_cache_' + params.reportingYear + '_' + params.unitId, JSON.stringify(res))
} catch (e) { /* 存储满则忽略 */ }
const route = this.$router.resolve({ const route = this.$router.resolve({
path: '/da3Report', path: '/da3Report',
query: { mode, ...params } query: { mode, ...params }

Loading…
Cancel
Save