This commit is contained in:
2026-07-01 10:37:59 +08:00
10 changed files with 151 additions and 51 deletions
@@ -96,6 +96,12 @@ public class CareDataLeaderCon {
return Result.success(careDataLeaderService.dataMetricData(year));
}
@At
@SaCheckPermission("careData.union")
public Result memberOverviewData() {
return Result.success(careDataLeaderService.memberOverviewData());
}
@At
@SaCheckPermission("careData.union")
public Result assetDataData() {
@@ -45,6 +45,13 @@ public interface CareDataLeaderService {
*/
NutMap dataMetricData(Integer year);
/**
* 查询会员总数和男女会员数。
*
* @return 会员概览数据,包含 total、male、female、unknown。
*/
NutMap memberOverviewData();
/**
* 查询资产使用状态分布。
*
@@ -91,13 +91,38 @@ public class CareDataLeaderServiceImpl implements CareDataLeaderService {
int targetYear = year == null ? LocalDate.now().getYear() : year;
return NutMap.NEW()
.addv("year", targetYear)
.addv("budgetTotal", schoolBudgetTotal(targetYear))
.addv("budgetTotal", budgetTotal(targetYear))
.addv("tourCount", tourCount(targetYear))
.addv("honorCount", honorCount(targetYear))
.addv("difficultCount", difficultCount(targetYear))
.addv("reimburseTotal", reimburseTotal(targetYear));
}
@Override
public NutMap memberOverviewData() {
Sql sql = Sqls.create("""
SELECT
COUNT(1) AS total,
IFNULL(SUM(CASE WHEN sex = '男' THEN 1 ELSE 0 END), 0) AS male,
IFNULL(SUM(CASE WHEN sex = '女' THEN 1 ELSE 0 END), 0) AS female
FROM vw_user
WHERE member = 1
$unionFilter
""");
setUnionFilter(sql, "unionId", null);
NutMap memberOverview = firstMap(sql);
long total = memberOverview.getLong("total", 0L);
long male = memberOverview.getLong("male", 0L);
long female = memberOverview.getLong("female", 0L);
// 部分会员性别为空或不是“男/女”,总数需要保留这部分人员。
long unknown = Math.max(0L, total - male - female);
return NutMap.NEW()
.addv("total", total)
.addv("male", male)
.addv("female", female)
.addv("unknown", unknown);
}
@Override
public NutMap assetDataData() {
List<NutMap> states = assetUsageStateRows();
@@ -220,14 +245,41 @@ public class CareDataLeaderServiceImpl implements CareDataLeaderService {
return listMap(sql);
}
private BigDecimal schoolBudgetTotal(int year) {
Sql sql = Sqls.create("""
SELECT IFNULL(SUM(totalQuota), 0) AS total
FROM outlay_manage_school
WHERE delFlag = 0
AND `year` = @year
""");
sql.setParam("year", year);
private BigDecimal budgetTotal(int year) {
Sql sql;
if (canViewAllUnionData()) {
sql = Sqls.create("""
SELECT IFNULL(SUM(totalQuota), 0) AS total
FROM (
SELECT totalQuota
FROM outlay_manage_school
WHERE delFlag = 0
AND `year` = @year
UNION ALL
SELECT totalQuota
FROM outlay_manage_union
WHERE delFlag = 0
AND `year` = @year
UNION ALL
SELECT totalQuota
FROM outlay_manage_club
WHERE delFlag = 0
AND `year` = @year
) budget
""");
sql.setParam("year", year);
} else {
// 普通分工会用户只能看到本分工会预算,校级和社团预算不挂具体分工会。
sql = Sqls.create("""
SELECT IFNULL(SUM(totalQuota), 0) AS total
FROM outlay_manage_union
WHERE delFlag = 0
AND `year` = @year
AND unionId = @unionId
""");
sql.setParam("year", year);
sql.setParam("unionId", SecurityUtil.getUnionId());
}
return decimalValue(firstMap(sql), "total");
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 994 KiB

After

Width:  |  Height:  |  Size: 816 KiB

@@ -104,29 +104,16 @@ module.exports = {
if (val) {
if (Array.isArray(val)) {
this.fileList = val.map((v) => {
return {
...v,
status: null,
isImage: ["jpg", "jpeg", "png", "gif", "bmp", "webp"].includes(v.name.split(".").pop().toLowerCase())
}
return this.normalizeFile(v)
})
} else if(typeof val === "string") {
this.fileList = [
{
url: val,
status: null,
isImage: true
}
this.normalizeFile(val)
]
} else {
val = JSON.parse(val)
this.fileList = val.map((v) => {
return {
...v,
url: v.url ? v.url : v.response?.data,
isImage: ["jpg", "jpeg", "png", "gif", "bmp", "webp"].includes(v.name.split(".").pop().toLowerCase()),
status: null
}
return this.normalizeFile(v)
})
}
} else {
@@ -142,14 +129,50 @@ module.exports = {
}
},
methods: {
// 统一历史数据和上传返回数据的文件名、地址字段,避免 Vant 回显时把下载路径当文件名显示。
normalizeFile(file) {
const data = typeof file === "string" ? {url: file} : Object.assign({}, file)
const responseData = data.response && data.response.data ? data.response.data : ""
const url = data.url || responseData || data.downloadPath || data.path || ""
const name = data.name || data.fileName || data.originalName || data.originalFilename || this.getFileNameFromUrl(url) || "附件"
data.url = url
data.name = name
data.file = {name: name}
data.status = null
data.isImage = this.isImageFile(name)
delete data.content
return data
},
// 同步父组件前移除原始 File 对象,避免表单 JSON 保存时带入不可序列化内容。
getCleanFileList() {
return this.fileList.map((file) => {
const data = Object.assign({}, file)
delete data.file
delete data.content
return data
})
},
getFileNameFromUrl(url) {
if (!url || typeof url !== "string") {
return ""
}
const cleanUrl = url.split("?")[0].split("#")[0]
const splitUrl = cleanUrl.split("/")
const fileName = splitUrl[splitUrl.length - 1]
return fileName && fileName.indexOf(".") > -1 ? decodeURIComponent(fileName) : ""
},
isImageFile(name) {
if (!name || typeof name !== "string" || name.indexOf(".") === -1) {
return false
}
const suffix = name.split(".").pop().toLowerCase()
return ["jpg", "jpeg", "png", "gif", "bmp", "webp"].includes(suffix)
},
beforeDelete(file) {
this.fileList = this.fileList.filter((f) => f.url !== file.url)
this.$emit("update:value", this.fileList)
this.$emit("update:value", this.getCleanFileList())
},
beforeRead(file) {
debugger
console.log(file)
console.log(this.upload_size)
if (file.size > this.upload_size) {
this.$toast("文件过大,请上传小于" + (this.upload_size / 1024 / 1024).toFixed(2) + "M的文件!")
return false
@@ -178,7 +201,7 @@ module.exports = {
if (valid) {
return true
}
this.$toast(`文件只能是 ${this.accept} 格式!`)
this.$toast("文件只能是 " + this.accept + " 格式!")
return false
},
afterRead(files) {
@@ -200,8 +223,8 @@ module.exports = {
f.url = resp.data
f.response = resp
f.percentage = 100
f.isImage = true
delete f.file
f.isImage = this.isImageFile(f.name)
f.file = {name: f.name}
delete f.content
} else {
f.status = "fail"
@@ -213,7 +236,7 @@ module.exports = {
if (this.upload_result_category === "interval") {
} else if (this.upload_result_category === "array") {
if (this.complete_result) {
this.$emit("update:value", this.fileList)
this.$emit("update:value", this.getCleanFileList())
} else {
const resultArrayValue = []
this.fileList.forEach((data) => {
@@ -494,13 +494,16 @@
padding: 0 14px;
border-radius: 18px;
color: #ffffff;
cursor: pointer;
font-size: 12px;
font-weight: 700;
font-family: inherit;
line-height: 1;
text-decoration: none;
white-space: nowrap;
background: linear-gradient(90deg, #f5a300 0%, #ff8e00 42%, #ff4b16 100%);
border: 1px solid rgba(255, 247, 184, 0.9);
outline: none;
box-shadow: inset 0 2px 4px rgba(255, 255, 255, 0.48), 0 2px 6px rgba(141, 53, 0, 0.25);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
@@ -738,9 +741,9 @@
</div>
<div class="v4-user-section">
<a class="v4-retire-system-link" href="http://192.168.73.133:8081/platform/login">
<button id="v4-retire-system-btn" class="v4-retire-system-link" type="button">
离退休系统
</a>
</button>
<div class="v4-user-info">
<span class="v4-user-name">${@auth.getPrincipalProperty('username')} (${@auth.getPrincipalProperty('loginname')})</span>
<!-- <i class="fa fa-angle-down"></i> -->
@@ -812,6 +815,10 @@
$(this).addClass("active")
})
$("#v4-retire-system-btn").on("click", function () {
window.open("http://192.168.73.133:8081/platform/login", "_blank")
})
$(document).pjax(".v4-nav a[data-pjax]", "#container", {
maxCacheLength: 0,
push: false,
@@ -1346,7 +1346,7 @@ layout("/layouts/platform_leader_dashboard.html"){
class="staff-home-map-wrap"
:class="{ 'staff-home-map-wrap-capture': coordinateMode }"
@click="captureCoordinate">
<img class="staff-home-map" src="${base!}/assets/platform/images/careData/leader/staff-home-campus-map.png?v=20260527" alt="">
<img class="staff-home-map" src="${base!}/assets/platform/images/careData/leader/staff-home-campus-map.png?v=20260630_3" alt="">
<span
class="staff-home-marker"
v-for="item in littleHouses"
@@ -1603,18 +1603,11 @@ layout("/layouts/platform_leader_dashboard.html"){
}
},
loadMemberOverviewData() {
Promise.all([
this.$axios.post("/platform/member/info/board/memberNumber"),
this.$axios.post("/platform/member/info/board/memberSexPercentage")
]).then(([numberResp, sexResp]) => {
if (numberResp && numberResp.code === 0 && numberResp.data) {
this.$set(this.memberOverview, "total", Number(numberResp.data.memberNum || 0))
}
if (sexResp && sexResp.code === 0 && Array.isArray(sexResp.data)) {
const maleRow = sexResp.data.find(item => this.isMaleMemberType(item && item.type)) || sexResp.data[0] || {}
const femaleRow = sexResp.data.find(item => this.isFemaleMemberType(item && item.type)) || sexResp.data[1] || {}
this.$set(this.memberOverview, "male", Number(maleRow.value || 0))
this.$set(this.memberOverview, "female", Number(femaleRow.value || 0))
this.$axios.post("/platform/careData/leader/memberOverviewData").then(resp => {
if (resp && resp.code === 0 && resp.data) {
this.$set(this.memberOverview, "total", Number(resp.data.total || 0))
this.$set(this.memberOverview, "male", Number(resp.data.male || 0))
this.$set(this.memberOverview, "female", Number(resp.data.female || 0))
}
}).catch(() => {})
},
@@ -123,7 +123,7 @@ layout("/layouts/platform_leader_dashboard.html"){
<section class="staff-home-panel">
<div class="staff-home-title">&#32844;&#24037;&#23567;&#23478;</div>
<div class="staff-home-map-wrap">
<img class="staff-home-map" src="${base!}/assets/platform/images/careData/leader/staff-home-campus-map.png?v=20260527" alt="">
<img class="staff-home-map" src="${base!}/assets/platform/images/careData/leader/staff-home-campus-map.png?v=20260630_3" alt="">
</div>
</section>
</main>
@@ -736,6 +736,17 @@ layout("/layouts/platform_h5.html"){
const identity = this.reimbursementIdentityOption.find((item) => item.code === this.formData.reimbursementIdentity)
if (identity) {
this.$set(this.formData, 'reimbursementIdentityName', identity.name)
} else {
const identityNameMap = {
school: '校工会',
union: '分工会',
club: '协会'
}
this.$set(this.formData, 'reimbursementIdentityName', identityNameMap[this.formData.reimbursementIdentity] || '')
}
const club = this.clubOption.find((item) => item.id === this.formData.clubId)
if (club) {
this.$set(this.formData, 'clubName', club.clubName)
}
},
fillCurrentUser() {
@@ -176,11 +176,12 @@ const todo = {
// 处理任务
onView(task) {
const {taskId, taskKey, instanceId, businessNo, formKey, h5FormKey} = task;
if (!h5FormKey) {
const h5Url = h5FormKey || task.h5formkey
if (!h5Url) {
this.$toast("请到电脑端智慧工会系统审核");
return;
}
this.$pjaxReplace(h5FormKey + "?taskId=" + taskId + "bizId=" + businessNo + "taskKey=" + taskKey+ "&tab=" + this.activeTab)
this.$pjaxReplace(h5Url + "?taskId=" + taskId + "&bizId=" + businessNo + "&taskKey=" + taskKey + "&tab=" + this.activeTab)
},
// 获取空状态文本