地大bug整改,提案数据看板列表增加字段,是否重点提案;会员数据看板增加年同比,修复会员人员占比数字没有显示;

This commit is contained in:
2026-09-15 10:53:01 +08:00
parent da13b19b57
commit 80774fdb0c
5 changed files with 351 additions and 215 deletions
@@ -206,6 +206,15 @@ layout("/layouts/platform.html"){
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT" :value="row.caseFilingResult"></dict-tag>
</template>
</el-table-column>
<!-- 是否重点复用立案类型字段;未立案与类型未填写分开展示,避免空值被误认为普通提案。 -->
<el-table-column label="是否重点" prop="caseFilingType" sortable="custom" width="110">
<template slot-scope="{row}">
<dict-tag v-if="row.caseFilingResult === 'CONFIRM_FILING' && row.caseFilingType"
:options="dict.type.PROPOSAL_CASE_FILING_TYPE" :value="row.caseFilingType"></dict-tag>
<span v-else-if="!row.caseFilingResult || row.caseFilingResult === 'CONFIRM_FILING'">未确定</span>
<span v-else>否</span>
</template>
</el-table-column>
<el-table-column label="是否并案" prop="isConsolidation" sortable="custom" width="100">
<template scope="{row}">
<el-tag size="mini" v-if="row.isConsolidation" type="success">是</el-tag>
@@ -241,7 +250,7 @@ layout("/layouts/platform.html"){
new Vue({
el: '#app',
dicts: ["PROPOSAL_TYPE", "PROPOSAL_CASE_FILING_RESULT"],
dicts: ["PROPOSAL_TYPE", "PROPOSAL_CASE_FILING_RESULT", "PROPOSAL_CASE_FILING_TYPE"],
components: {
"proposal-info": PROPOSAL_INFO
},
@@ -252,6 +261,8 @@ layout("/layouts/platform.html"){
nodes: [],
nodeDisplayModes: {}, // 存储每个节点的显示模式
pageForm: {
sessionId: null,
selectNodeMode: "todo",
selectNodeId: null,
selectNodeType: null,
pageSize: 5
@@ -268,6 +279,10 @@ layout("/layouts/platform.html"){
// 届次改变
sessionChange() {
// 切换届次后回到总数卡片,避免沿用上一届次的分类筛选。
this.$set(this.pageForm, "selectNodeId", null)
this.$set(this.pageForm, "selectNodeType", null)
this.$set(this.pageForm, "selectNodeMode", "todo")
this.getNodes()
this.doSearch()
},
@@ -276,8 +291,8 @@ layout("/layouts/platform.html"){
listSession() {
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
if (this.sessionOptions) {
this.$set(this, "sessionOptions", res.data || [])
if (this.sessionOptions.length) {
this.$set(this.pageForm, "sessionId", this.sessionOptions[0].id)
this.getNodes()
this.doSearch()
@@ -290,7 +305,7 @@ layout("/layouts/platform.html"){
getNodes() {
this.$axios.post('/platform/proposal/dashboard/listNode', {sessionId: this.pageForm.sessionId}).then(res => {
if (res.code === 0) {
this.nodes = res.data
this.$set(this, "nodes", res.data || [])
}
})
},
@@ -303,9 +318,9 @@ layout("/layouts/platform.html"){
// 节点选择
selectNode(node, index) {
this.pageForm.selectNodeId = node.id
this.pageForm.selectNodeType = node.type
this.pageForm.selectNodeMode = this.getNodeDisplayMode(node.id)
this.$set(this.pageForm, "selectNodeId", node.id)
this.$set(this.pageForm, "selectNodeType", node.type)
this.$set(this.pageForm, "selectNodeMode", this.getNodeDisplayMode(node.id))
this.doSearch()
},
@@ -297,10 +297,11 @@ layout("/layouts/platform.html"){
{{memberNumberData.memberNum}}
<span style="font-size: 14px">&ensp;人</span>
</div>
<!-- <div class="stat-meta" v-loading="loading.memberNumber">-->
<!-- 年同比 {{memberNumberData.ratio}}&ensp;-->
<!-- <i :class="memberNumberData.diff >= 0 ? 'el-icon-top trend-up' : 'el-icon-bottom trend-down'"></i>-->
<!-- </div>-->
<div class="stat-meta" style="text-align: right" v-loading="loading.memberNumber">
年同比 {{memberNumberData.ratio}}&ensp;
<i v-if="memberNumberData.diff > 0" class="el-icon-top trend-up"></i>
<i v-else-if="memberNumberData.diff < 0" class="el-icon-bottom trend-down"></i>
</div>
</div>
<div class="card stats-card">
@@ -393,8 +394,8 @@ layout("/layouts/platform.html"){
memberNumberData: {
memberNum: "--",
lastYearMemberNum: "--",
ratio: "0.0%",
diff: 0
ratio: "—",
diff: null
},
memberPercentage: "--",
unionMember: []
@@ -403,23 +404,39 @@ layout("/layouts/platform.html"){
},
methods: {
/**
* 会员数
* @returns {Promise<void>}
* 无需传参;接口返回 memberNum 当前会员数和 lastYearMemberNum 去年归档会员数。
* @returns {Promise<void>} 更新会员数、同比及涨跌方向,请求结束后关闭加载状态。
*/
async getMemberNumber() {
this.loading.memberNumber = true
this.$axios.post("/platform/member/info/board/memberNumber").then((resp) => {
getMemberNumber() {
this.$set(this.loading, "memberNumber", true)
return this.$axios.post("/platform/member/info/board/memberNumber").then((resp) => {
if (resp.code === 0) {
const {
data: { memberNum, lastYearMemberNum }
} = resp
const diff = memberNum - lastYearMemberNum
const ratio = (lastYearMemberNum ? (Math.abs(diff) / lastYearMemberNum) * 100 : (diff / 1) * 10).toFixed(2) + " %"
this.memberNumberData = { memberNum, lastYearMemberNum, diff, ratio }
this.loading.memberNumber = false
const data = resp.data || {}
// 兼容数字字符串,但不把空值、布尔值或异常人数转换成有效的零人数。
const memberNum = typeof data.memberNum === "number" || (typeof data.memberNum === "string" && data.memberNum.trim() !== "") ? Number(data.memberNum) : NaN
const lastYearMemberNum = typeof data.lastYearMemberNum === "number" || (typeof data.lastYearMemberNum === "string" && data.lastYearMemberNum.trim() !== "") ? Number(data.lastYearMemberNum) : NaN
const validMemberNum = Number.isSafeInteger(memberNum) && memberNum >= 0
const validLastYearMemberNum = Number.isSafeInteger(lastYearMemberNum) && lastYearMemberNum >= 0
let diff = null
let ratio = "—"
// 去年为零或没有归档人数时无法计算同比;仅在基数有效且大于零时显示涨跌。
if (validMemberNum && validLastYearMemberNum && lastYearMemberNum > 0) {
diff = memberNum - lastYearMemberNum
// 先按万分比对涨跌幅绝对值四舍五入,再恢复负号,避免 4.525% 被直接格式化成 4.52%。
const changePercent = Math.round(Math.abs(diff) * 10000 / lastYearMemberNum) / 100
ratio = diff === 0 ? "持平" : (diff < 0 && changePercent > 0 ? "-" : "") + changePercent.toFixed(2) + " %"
}
this.$set(this, "memberNumberData", {
memberNum: validMemberNum ? memberNum : "--",
lastYearMemberNum: validLastYearMemberNum ? lastYearMemberNum : "--",
diff: diff,
ratio: ratio
})
} else {
this.$message.warning(resp.msg)
}
}).finally(() => {
this.$set(this.loading, "memberNumber", false)
})
},
/**
@@ -484,18 +501,23 @@ layout("/layouts/platform.html"){
})
},
/**
* 会员占比
* @returns {Promise<void>}
* 无需传参;接口 data 为 0~1 的会员比例,兼容数值字符串后用于水波图。
* @returns {Promise<void>} 完成比例校验和图表更新,并在请求结束时关闭加载状态。
*/
async getMemberPercentage() {
this.loading.memberPercentage = true
this.$axios.post("/platform/member/info/board/memberPercentage").then((resp) => {
this.loading.memberPercentage = false
getMemberPercentage() {
this.$set(this.loading, "memberPercentage", true)
return this.$axios.post("/platform/member/info/board/memberPercentage").then((resp) => {
if (resp.code === 0) {
const { data } = resp
this.memberPercentage = data.toFixed(2)
// 空值、非数值和超出比例范围的数据不能作为 0% 展示;合法的零值需要保留。
const percent = typeof data === "number" || (typeof data === "string" && data.trim() !== "") ? Number(data) : NaN
if (!Number.isFinite(percent) || percent < 0 || percent > 1) {
this.$message.warning("会员占比数据异常,请稍后重试")
return
}
this.$set(this, "memberPercentage", percent.toFixed(2))
if (chart.memberPercentageChart) {
chart.memberPercentageChart.changeData(data)
chart.memberPercentageChart.changeData(percent)
return
}
chart.memberPercentageChart = new G2Plot.Liquid("memberPercentageChart", {
@@ -507,13 +529,17 @@ layout("/layouts/platform.html"){
length: 128
},
autoFit: true,
percent: data,
percent: percent,
color: '#217050',
statistic: {
content: {
style: {
fontSize: 16,
fill: '#fff', // 白色文字
// 深色文字配浅色描边,确保低水位白底和高水位绿底上的百分比均可读。
fill: '#1f2937',
fontWeight: 'bold',
stroke: '#fff',
lineWidth: 0.5,
}
}
}
@@ -522,6 +548,8 @@ layout("/layouts/platform.html"){
} else {
this.$message.warning(resp.msg)
}
}).finally(() => {
this.$set(this.loading, "memberPercentage", false)
})
},
/**