This commit is contained in:
server
2025-06-30 14:40:59 +08:00
parent cfa2b34ee8
commit 69d3ce0744
33 changed files with 1703 additions and 292 deletions
@@ -173,10 +173,6 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
cnd = ConditionGroupUtil.applyConditionGroup(cnd, updateParam.getConditionGroup());
}
// List<Map<String, String>> allList = ExcelImportUtil.importExcel(new File("C:\\Users\\jug\\Desktop\\南京师范蛋糕卡\\匹配上生日.xlsx"), Map.class, new ImportParams());
// List<String> loginNames = allList.stream().map(v -> v.get("工号")).toList();
// cnd.and("loginname", "in", loginNames);
List<Sys_user_source> sources = dao.query(Sys_user_source.class, cnd.groupBy("loginname"));
log.info("符合条件的数据源记录数: {}", sources.size());
@@ -57,6 +57,6 @@ public class SysUserAllRenewJob implements Job {
param.setUpdateMode(SysDataUpdateMode.ALL.name());
param.setConditionGroup(conditionGroup);
sysDataUserUpdateService.update(param);
// sysDataUserUpdateService.update(param);
}
}
@@ -78,7 +78,8 @@ public class MemberInfoServiceImpl extends BaseServiceImpl<Sys_user> implements
unitId,
unitName,
education,
nation
nation,
postDoctoralJoinDate
FROM
vw_user
$condition
@@ -142,7 +142,8 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
u.userState,
u.unionName,
u.unitName,
u.member
u.member,
u.postDoctoralJoinDate
FROM
$table
$hisUser
@@ -8,6 +8,7 @@ import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.welfare.model.WelfareList;
import com.budwk.app.zhgh.welfare.model.WelfareUserSelection;
import com.budwk.app.zhgh.welfare.param.WelfareSelectionSituationPageForm;
import com.budwk.app.zhgh.welfare.service.WelfareListService;
@@ -84,6 +85,11 @@ public class WelfareSelectionSituationController {
@SLog(type = "welfare", tag = "选择福利", msg = "代选福利")
@SaCheckPermission("welfare.selection.situation")
public Result confirmSelect(@Param("selections") WelfareUserSelection[] selections, String projectId, String userId) {
int count = dao.count(WelfareList.class, Cnd.where(WelfareList::getProjectId, "=", projectId).and(WelfareList::getUserId, "=", userId));
if(count==0){
return Result.error("此用户没有选择的权限");
}
//删除上次选择的
dao.clear(WelfareUserSelection.class, Cnd.where(WelfareUserSelection::getWelfareId, "=", projectId).and(WelfareUserSelection::getSelectUserId, "=", userId));
for (WelfareUserSelection welfareUserSelection : selections) {
@@ -81,6 +81,11 @@ public class WelfareUserSelectController {
@SLog(type = "welfare", tag = "选择福利", msg = "福利")
@SaCheckPermission("welfare.user.select")
public Result confirmSelect(@Param("selections") WelfareUserSelection[] selections, String projectId) {
int count = dao.count(WelfareList.class, Cnd.where(WelfareList::getProjectId, "=", projectId).and(WelfareList::getUserId, "=", SecurityUtil.getUserId()));
if(count==0){
return Result.error("您没有选择的权限");
}
//删除上次选择的
dao.clear(WelfareUserSelection.class, Cnd.where(WelfareUserSelection::getWelfareId, "=", projectId).and(WelfareUserSelection::getSelectUserId, "=", SecurityUtil.getUserId()));
for (WelfareUserSelection welfareUserSelection : selections) {
@@ -536,7 +536,7 @@ public class WelfareListServiceImpl extends BaseServiceImpl<WelfareList> impleme
WelfareList wl = new WelfareList();
wl.setProjectId(pageForm.getProjectId());
wl.setUserId(user.getString("id"));
wl.setWelfareUnitId(user.getString("unionId"));
wl.setWelfareUnitId(user.getString("unitId"));
wl.setWelfareUnitName(user.getString("unitName"));
wl.setWelfareUnionId(user.getString("unionId"));
wl.setWelfareUnionName(user.getString("unionName"));
@@ -60,7 +60,7 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
""");
Cnd cnd = Cnd.NEW();
if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name()) || AuthUtil.hasRole(RoleConstant.BRANCH_UNION_OPERATOR.name())) {
cnd.and("t1.welfareUnionId", "=", SecurityUtil.getUnionId());
}
@@ -117,7 +117,7 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
""");
Cnd cnd = Cnd.NEW();
if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name()) || AuthUtil.hasRole(RoleConstant.BRANCH_UNION_OPERATOR.name())) {
cnd.and("t1.welfareUnionId", "=", SecurityUtil.getUnionId());
}
@@ -122,8 +122,13 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
SELECT
u.loginname AS loginName,
u.username AS userName,
wl.userState,
wl.personType,
wl.preparedBy,
wl.welfareUnitName,
wl.welfareUnionName,
u.postDoctoralJoinDate,
DATE_FORMAT(u.birthday, '%Y-%m-%d') AS birthday,
wpus.mobile,
GROUP_CONCAT(DISTINCT wpso.optionName, '', wpus.selectNum, '份)') selectOptionName
FROM
@@ -155,8 +160,13 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
SELECT
u.loginname AS loginName,
u.username AS userName,
wl.userState,
wl.personType,
wl.preparedBy,
wl.welfareUnitName,
wl.welfareUnionName,
u.postDoctoralJoinDate,
DATE_FORMAT(u.birthday, '%Y-%m-%d') AS birthday,
wpus.mobile,
GROUP_CONCAT(DISTINCT wpso.optionName, '', wpus.selectNum, '份)') selectOptionName
FROM
@@ -188,6 +198,11 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
List<ExcelExportEntity> entities = new ArrayList<>();
entities.add(new ExcelExportEntity("工号", "loginName", 20));
entities.add(new ExcelExportEntity("姓名", "userName", 20));
entities.add(new ExcelExportEntity("生日", "birthday", 20));
entities.add(new ExcelExportEntity("在职状态", "userState", 20));
entities.add(new ExcelExportEntity("教职工类别", "personType", 20));
entities.add(new ExcelExportEntity("聘用方式", "preparedBy", 20));
entities.add(new ExcelExportEntity("进站时间", "postDoctoralJoinDate", 20));
entities.add(new ExcelExportEntity("单位", "welfareUnitName", 20));
entities.add(new ExcelExportEntity("工会", "welfareUnionName", 20));
entities.add(new ExcelExportEntity("手机号", "mobile", 20));
@@ -210,8 +225,13 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
SELECT
u.loginname AS loginName,
u.username AS userName,
wl.userState,
wl.personType,
wl.preparedBy,
wl.welfareUnitName,
wl.welfareUnionName
wl.welfareUnionName,
u.postDoctoralJoinDate,
DATE_FORMAT(u.birthday, '%Y-%m-%d') AS birthday
FROM
`welfare_list` wl
LEFT JOIN welfare_project_user_selection wpus ON wl.userId = wpus.selectUserId
@@ -245,8 +265,13 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
SELECT
u.loginname AS loginName,
u.username AS userName,
wl.userState,
wl.personType,
wl.preparedBy,
wl.welfareUnitName,
wl.welfareUnionName
wl.welfareUnionName,
u.postDoctoralJoinDate,
DATE_FORMAT(u.birthday, '%Y-%m-%d') AS birthday
FROM
`welfare_list` wl
LEFT JOIN welfare_project_user_selection wpus ON wl.userId = wpus.selectUserId
@@ -279,6 +304,7 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
List<ExcelExportEntity> entities = new ArrayList<>();
entities.add(new ExcelExportEntity("工号", "loginName", 20));
entities.add(new ExcelExportEntity("姓名", "userName", 20));
entities.add(new ExcelExportEntity("姓名", "userName", 20));
entities.add(new ExcelExportEntity("单位", "welfareUnitName", 20));
entities.add(new ExcelExportEntity("工会", "welfareUnionName", 20));
@@ -446,17 +446,29 @@
:root {
/*--color-primary: #1890ff;*/
--color-primary: #1867b0;
--color-primary-1: #e6f7ff;
--color-primary-2: #bae7ff;
--color-primary-3: #91d5ff;
--color-primary-4: #69c0ff;
--color-primary-5: #096dd9;
--color-primary-6: #1890ff;
--color-primary-7: #096dd9;
--color-primary-8: #0050b3;
--color-primary-9: #003a8c;
--color-primary-10: #002766;
/*--color-primary-1: #e6f7ff;*/
/*--color-primary-2: #bae7ff;*/
/*--color-primary-3: #91d5ff;*/
/*--color-primary-4: #69c0ff;*/
/*--color-primary-5: #73d13d;*/
/*--color-primary-6: #1890ff;*/
/*--color-primary-7: #096dd9;*/
/*--color-primary-8: #0050b3;*/
/*--color-primary-9: #003a8c;*/
/*--color-primary-10: #002766;*/
--color-primary: #217050;
--color-primary-1: #e8f5eb;
--color-primary-2: #c3e6d1;
--color-primary-3: #9dd7b7;
--color-primary-4: #78c89d;
--color-primary-5: #53b983;
--color-primary-6: #217050; /* 主色 */
--color-primary-7: #1a5a40;
--color-primary-8: #134330;
--color-primary-9: #0d2d20;
--color-primary-10: #061610;
--color-success: #52c41a;
--color-success-1: #f6ffed;
--color-success-2: #d9f7be;
@@ -2807,7 +2819,7 @@
}
.el-menu-item.is-active {
color: var(--color-primary);
color: #FFFFFF!important;
}
.el-menu-item.is-active i {
@@ -5547,7 +5559,7 @@
.el-breadcrumb__inner a:hover,
.el-breadcrumb__inner.is-link:hover {
color: var(--color-primary);
/*color: var(--color-primary);*/
cursor: pointer;
}
@@ -18669,7 +18681,8 @@ body [class^="el-icon-_"] {
.el-breadcrumb__inner,
.el-breadcrumb__inner a,
.el-breadcrumb__inner.is-link {
color: var(--color-text-secondary);
/*color: var(--color-text-secondary);*/
color: var(--color-white);
font-weight: 400;
}
@@ -18677,7 +18690,7 @@ body [class^="el-icon-_"] {
.el-breadcrumb__item:last-child .el-breadcrumb__inner a,
.el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover,
.el-breadcrumb__item:last-child .el-breadcrumb__inner:hover {
color: var(--color-text-regular);
/*color: var(--color-text-regular);*/
}
.el-tabs .el-tabs__header,
@@ -18931,7 +18944,8 @@ body [class^="el-icon-_"] {
.el-menu .el-menu-item,
.el-menu .el-submenu > .el-submenu__title {
color: var(--color-text-dark-regular);
/*color: var(--color-text-dark-regular);*/
color: #000000;
background: none;
}
@@ -18948,7 +18962,8 @@ body [class^="el-icon-_"] {
.el-menu .el-menu-item.is-active,
.el-menu .el-submenu.is-active > .el-submenu__title {
color: var(--color-text-dark-primary);
/*color: var(--color-text-dark-primary);*/
color: #000000;
background: none;
}
@@ -21071,6 +21086,7 @@ body.ele-transition-disabled .ele-modal-mask-inner {
align-items: center;
height: 56px;
background: var(--header-light-background);
background: var(--color-primary);
position: relative;
}
@@ -21669,8 +21685,8 @@ span {
/*}*/
.ele-admin-show-tabs:not(.ele-admin-tab-card):not(.ele-admin-head-dark) .ele-admin-header {
-webkit-box-shadow: 240px -1px 0 var(--border-color-extra-light) inset;
box-shadow: 240px -1px 0 var(--border-color-extra-light) inset;
/*-webkit-box-shadow: 240px -1px 0 var(--border-color-extra-light) inset;*/
/*box-shadow: 240px -1px 0 var(--border-color-extra-light) inset;*/
-webkit-transition: padding-left 0.3s cubic-bezier(0.2, 0, 0, 1) 0s,
-webkit-box-shadow 0.3s cubic-bezier(0.2, 0, 0, 1) 0s;
transition: padding-left 0.3s cubic-bezier(0.2, 0, 0, 1) 0s,
@@ -22174,15 +22190,15 @@ span {
.ele-admin-side-dark .ele-admin-logo {
color: var(--color-text-dark-primary);
-webkit-box-shadow: var(--logo-dark-shadow);
box-shadow: var(--logo-dark-shadow);
background: var(--sidebar-background-dark);
/*-webkit-box-shadow: var(--logo-dark-shadow);*/
/*box-shadow: var(--logo-dark-shadow);*/
background: var(--color-primary);
}
.ele-admin-side-dark .ele-admin-sidebar {
-webkit-box-shadow: var(--sidebar-dark-shadow);
box-shadow: var(--sidebar-dark-shadow);
background: var(--sidebar-background-dark);
/*-webkit-box-shadow: var(--sidebar-dark-shadow);*/
/*box-shadow: var(--sidebar-dark-shadow);*/
background: #FFFFFF;
}
.ele-admin-side-dark.ele-admin-side-mix:not(.ele-admin-collapse) .ele-admin-logo,
@@ -126,12 +126,12 @@
*/
.text-primary,
.text-primary a {
color: #1582dc;
color: var(--color-primary);
}
.text-primary:focus,
.text-primary a:focus {
color: #0e5996;
color: var(--color-primary-6);
}
.text-default,
@@ -67,6 +67,11 @@ module.exports = {
<style scoped>
.appCenterPopover {
padding: 0 !important;
color: var(--color-white);
}
.el-popover__reference{
font-weight: normal!important;
}
.appCenterCard .el-card__header {
@@ -26,7 +26,7 @@
<a @click.prevent="viewMore" class="ele-cell-content">查看更多</a>
</div>
<el-badge :value="messages.length" slot="reference" :style="{ animation: messages.length > 0 ? 'bell-shake 0.5s infinite' : '' }">
<i class="el-icon-bell"></i>
<i class="el-icon-bell" style="color: var(--color-white)"></i>
</el-badge>
</el-popover>
</div>
@@ -10,10 +10,10 @@
/>
<img v-else alt="" src="/assets/platform/img/home/avatar_girl.png" />
</span>
<span class="hidden-xs-only">
<span class="hidden-xs-only" style="color: var(--color-white)">
{{ $store.state.user.username }}
</span>
<i class="el-icon-arrow-down"></i>
<i class="el-icon-arrow-down" style="color: var(--color-white)"></i>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="userInfo">个人信息</el-dropdown-item>
@@ -10,7 +10,7 @@
<link rel="stylesheet" href="${base!}/assets/platform/fonts/themify-icons.css" />
<link rel="stylesheet" href="${base!}/assets/platform/fonts/font-awesome.min.css" />
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css?v=1.0.1" />
<link rel="stylesheet" href="${base!}/assets/platform/css/a.css" />
<link rel="stylesheet" href="${base!}/assets/platform/css/a.css?v=1.0.0" />
<!-- import Vue before Element -->
<script src="${base!}/assets/platform/plugins/vue/vue.js"></script>
@@ -36,7 +36,7 @@ const appModule = {
width: 110px;
height: 110px;
border: 1px solid #f3efef;
/ / background-color: rgb(248, 248, 248);
/*/ / background-color: rgb(248, 248, 248);*/
display: flex;
justify-content: center;
align-items: center;
@@ -63,20 +63,36 @@ const quickEntry = {
padding: 10px;
transition: transform 0.3s ease-in-out,
box-shadow 0.3s ease-in-out;
background: #f3f3f3;
border-radius: 10px;
}
.home-quick-entry .quickEntries .quickEntryItem span {
margin-top: auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.home-quick-entry .quickEntries .quickEntryItem:hover {
cursor: pointer;
background: #f3f3f3;
border-radius: 10px;
border: 1px solid var(--color-primary);
box-shadow:
0 0 12px rgba(33, 112, 80, 0.4), /* 外发光 */
inset 0 0 8px rgba(33, 112, 80, 0.2); /* 内发光 */
background: rgba(33, 112, 80, 0.05); /* 悬浮背景微透主题色 */
}
.home-quick-entry .quickEntries .quickEntryItem:hover {
animation: shake 0.3s;
.home-quick-entry .quickEntries .quickEntryItem:hover .svg-icon {
transform: scale(1.1); /* 图标放大10% */
transition: transform 0.3s ease;
}
.home-quick-entry .quickEntries .quickEntryItem:hover span {
color: var(--color-primary); /* 使用主题色或自定义颜色 */
}
@keyframes shake {
@@ -9,7 +9,7 @@ layout("/layouts/platform.html"){
.alert {
padding: 15px;
background-color: #e8f4ff;
border-left: 4px solid #1890ff;
border-left: 4px solid var(--color-primary);
margin-bottom: 25px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
@@ -29,7 +29,7 @@ layout("/layouts/platform.html"){
}
.alert i {
color: #1890ff;
color: var(--color-primary);
margin-right: 8px;
}
@@ -54,7 +54,7 @@ layout("/layouts/platform.html"){
}
.book-header {
background: linear-gradient(120deg, #1e3c72, #2a5298);
background: linear-gradient(120deg, var(--color-primary), var(--color-primary-8));
color: white;
padding: 30px;
text-align: center;
@@ -107,7 +107,7 @@ layout("/layouts/platform.html"){
font-size: 18px;
font-weight: bold;
margin-bottom: 20px;
color: #1867b0;
color: var(--color-primary);
position: relative;
padding-left: 15px;
}
@@ -5,7 +5,7 @@ layout("/layouts/platform.html"){
<guava ref="guava">
<el-card shadow="never">
<template #header>
<h3 style="color: #1867b0">{{isEdit?'修改登记':'荣誉登记'}}</h3>
<h3 style="color: var(--color-primary)">{{isEdit?'修改登记':'荣誉登记'}}</h3>
</template>
<el-form :model="formData" label-width="120px">
<el-row type="flex" :gutter="20">
@@ -61,7 +61,7 @@ const MEMBER_RECORD = {
<el-table-column align="center" header-align="center" label="异动类型"
prop="changeType" show-overflow-tooltip sortable>
<template scope="{row}">
<span style="color: #0e78c5;cursor: pointer" @click="openUserChangeInfo(row)">
<span style="color: var(--color-primary);cursor: pointer" @click="openUserChangeInfo(row)">
{{getChangeTypes(row.changeTypes)}}
</span>
</template>
@@ -2,152 +2,346 @@
layout("/layouts/platform.html"){
#-->
<style>
.top-col {
background-color: white;
position: relative;
box-sizing: border-box;
padding: 20px;
width: calc((100% - (20px * 3)) / 4);
}
.top-col:not(:last-child),
.center-col:not(:last-child) {
margin-right: 20px;
}
.col-title {
color: rgba(0, 0, 0, 0.45);
font-size: 14px;
margin-bottom: 10px;
}
.top-col-member-number {
font-size: 30px;
color: rgba(0, 0, 0, 0.85);
}
.top-col-chart {
height: 80px;
/* 主网格布局 */
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 200px 1fr;
gap: 20px;
width: 100%;
position: relative;
}
.center-col {
background-color: white;
position: relative;
height: calc(100vh - 126px);
box-sizing: border-box;
padding: 20px;
width: calc((100% - (20px * 1)) / 2);
}
.idx {
/* 卡片基础样式 */
.card {
background-color: white;
border-radius: 8px;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
color: rgba(0, 0, 0, 0.85);
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #f0f0f0;
flex-direction: column;
}
/* 卡片标题样式 */
.card-title {
padding: 16px 20px 8px;
font-size: 16px;
font-weight: 600;
color: #333;
border-bottom: 1px solid #f0f0f0;
flex-shrink: 0;
}
/* 顶部统计卡片 */
.stats-card {
height: 200px;
padding: 20px;
box-sizing: border-box;
}
.stats-card .card-title {
padding: 0 0 8px 0;
border: none;
font-size: 14px;
color: #666;
margin-bottom: 8px;
}
.stat-value {
font-size: 32px;
font-weight: bold;
color: #217050;
margin: 10px 0;
line-height: 1.2;
}
.stat-meta {
font-size: 12px;
color: #999;
margin-top: auto;
}
.trend-up {
color: #52c41a;
}
.trend-down {
color: #ff4d4f;
}
/* 图表容器 */
.chart-container {
flex: 1;
min-height: 0;
padding: 10px;
}
/* 统计卡片中的图表容器 */
.stats-card .chart-container {
height: 120px;
min-height: 120px;
flex: none;
margin: 8px 0;
padding: 0;
}
/* 内容区域 - 左右布局 */
.content-left {
grid-column: 1 / 4;
display: grid;
grid-template-rows: 1fr 1fr;
gap: 20px;
min-height: 0;
}
.content-right {
grid-column: 4 / 5;
min-height: 0;
}
/* 左侧图表卡片 */
.content-left .card {
min-height: 0;
}
.content-left .card .chart-container {
flex: 1;
min-height: 200px;
}
/* 右侧表格样式 */
.content-right {
display: flex;
flex-direction: column;
}
.content-right .el-table {
flex: 1;
height: auto !important;
}
.content-right .card-title {
flex-shrink: 0;
}
/* 表格序号样式 */
.idx {
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
border-radius: 4px;
font-weight: bold;
margin: 0 auto;
}
.idx-rank {
color: white !important;
background-color: #314659 !important;
background: linear-gradient(135deg, #217050, #2d8a5f);
color: white;
}
.el-table__body-wrapper::-webkit-scrollbar {
display: none; /* Chrome Safari */
/* 响应式设计 */
@media (max-width: 1400px) {
.dashboard {
grid-template-columns: repeat(2, 1fr);
grid-template-rows: 200px 200px 1fr;
}
.stats-card:nth-child(1),
.stats-card:nth-child(2) {
grid-row: 1;
}
.stats-card:nth-child(3),
.stats-card:nth-child(4) {
grid-row: 2;
}
.content-left {
grid-column: 1 / 3;
grid-row: 3;
grid-template-columns: 2fr 1fr;
grid-template-rows: 1fr;
}
.content-right {
grid-column: 1 / 3;
grid-row: 4;
}
}
.el-table__body-wrapper {
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
overflow-x: hidden;
@media (max-width: 768px) {
.dashboard {
grid-template-columns: 1fr;
grid-template-rows: repeat(4, 180px) 1fr 300px;
gap: 15px;
}
.stats-card {
height: 180px;
padding: 15px;
}
.stats-card .chart-container {
height: 100px;
min-height: 100px;
}
.content-left {
grid-column: 1;
grid-row: 5;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
}
.content-right {
grid-column: 1;
grid-row: 6;
min-height: 300px;
}
.stat-value {
font-size: 24px;
}
}
/* Element UI 表格样式重写 */
.el-table {
font-size: 14px;
}
.el-table .el-table__header-wrapper {
background-color: #fafafa;
}
.el-table .el-table__body-wrapper {
max-height: calc(100% - 48px);
overflow-y: auto;
}
.el-table th {
background-color: #fafafa !important;
color: #333;
font-weight: 600;
}
.el-table td {
border-bottom: 1px solid #f0f0f0;
}
.el-table--border .el-table__inner-wrapper::after {
display: none;
}
/* Loading 样式优化 */
.el-loading-mask {
background-color: rgba(255, 255, 255, 0.8);
}
.el-loading-spinner .circular {
width: 32px;
height: 32px;
}
@media (max-width: 768px) {
.dashboard {
grid-template-columns: 1fr; /* 单列布局 */
grid-template-rows: repeat(6, auto); /* 自动高度,6行 */
gap: 15px;
}
/* 所有卡片独占一行 */
.stats-card,
.content-left,
.content-right {
grid-column: 1 !important; /* 强制占满整行 */
grid-row: auto !important; /* 自动行位置 */
height: auto; /* 高度自适应 */
min-height: 180px; /* 最小高度保障 */
}
/* 调整左侧内容区域为垂直堆叠 */
.content-left {
display: flex;
flex-direction: column;
gap: 15px;
}
/* 调整图表容器高度 */
.chart-container {
min-height: 200px;
}
/* 统计卡片调整 */
.stats-card {
padding: 15px;
}
.stats-card .chart-container {
height: 120px;
min-height: 120px;
}
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<el-row style="background-color: #f0f2f5" type="flex">
<el-col class="top-col" v-loading="loading.memberNumber">
<div class="col-title">会员数</div>
<div class="top-col-member-number">
<div class="dashboard">
<!-- 顶部四个统计卡片 - 高度固定200px -->
<div class="card stats-card">
<div class="card-title">会员数</div>
<div class="stat-value" v-loading="loading.memberNumber">
{{memberNumberData.memberNum}}
<span style="font-size: 14px">&ensp;</span>
</div>
<div
style="
color: rgba(0, 0, 0, 0.85);
margin-top: 20px;
font-size: 14px;
display: flex;
align-items: center;
justify-content: flex-end;
"
>
年同比 {{memberNumberData.ratio}}&ensp;
<svg
aria-hidden="true"
data-icon="caret-up"
fill="currentColor"
focusable="false"
height="1em"
style="color: #67c23a"
v-if="memberNumberData.diff>=0"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"
></path>
</svg>
<!-- <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>
<svg
aria-hidden="true"
data-icon="caret-up"
fill="currentColor"
focusable="false"
height="1em"
style="color: #f56c6c"
v-else
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"
></path>
</svg>
<div class="card stats-card">
<div class="card-title">增长趋势</div>
<div class="chart-container" id="growthTrendChart" v-loading="loading.growthTrend"></div>
</div>
<div class="card stats-card">
<div class="card-title">会员占比</div>
<div class="chart-container" id="memberPercentageChart" v-loading="loading.memberPercentage"></div>
</div>
<div class="card stats-card">
<div class="card-title">男女占比</div>
<div class="chart-container" id="memberSexPercentageChart" v-loading="loading.memberSexPercentage"></div>
</div>
<!-- 左侧内容区域 -->
<div class="content-left">
<!-- 工会会员数图表 -->
<div class="card">
<div class="card-title">工会会员数</div>
<div class="chart-container" id="unionMemberChart" v-loading="loading.unionMember"></div>
</div>
</el-col>
<el-col class="top-col" v-loading="loading.growthTrend">
<div class="col-title">增长趋势</div>
<div class="top-col-chart" id="growthTrendChart"></div>
</el-col>
<el-col class="top-col" v-loading="loading.memberPercentage">
<div class="col-title">会员占比</div>
<div class="top-col-chart" id="memberPercentageChart" style="position: absolute; height: 120px; right: -10%; bottom: 20px"></div>
</el-col>
<el-col class="top-col" v-loading="loading.memberSexPercentageChart">
<div class="col-title">男女占比</div>
<div class="top-col-chart" id="memberSexPercentageChart" style="position: absolute; height: 120px; right: -10%; bottom: 20px"></div>
</el-col>
</el-row>
<el-row style="background-color: #f0f2f5; margin-top: 20px" type="flex">
<el-col class="center-col" v-loading="loading.unionMember">
<div class="col-title">工会会员数</div>
<div id="unionMemberChart" style="width: 100%; height: 100px"></div>
<!-- 人员类型图表 -->
<div class="card">
<div class="card-title">人员类型统计</div>
<div class="chart-container" id="personTypeMemberChart" v-loading="loading.personTypeMember"></div>
</div>
</div>
<!-- 右侧表格区域 -->
<div class="card content-right">
<div class="card-title">工会会员明细</div>
<el-table
:data="unionMember"
:header-cell-style="{background:'#FAFAFA'}"
height="calc(100vh - 160px - 300px)"
row-key="id"
style="width: 100%; margin-top: 20px"
:data="unionMember"
:header-cell-style="{background:'#FAFAFA'}"
style="width: 100%; height: calc(100% - 40px)"
row-key="id"
v-loading="loading.unionMember"
>
<el-table-column label="序号" width="100px" align="center">
<template scope="{$index}">
@@ -159,34 +353,20 @@ layout("/layouts/platform.html"){
<template scope="{row}">{{row.unionname}}</template>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="会员人数"
prop="value"
show-overflow-tooltip
sortable
width="120px"
align="center"
header-align="center"
label="会员人数"
prop="value"
show-overflow-tooltip
sortable
width="120px"
></el-table-column>
</el-table>
</el-col>
<el-col class="center-col">
<div class="col-title">在职状态</div>
<div
id="userStateMemberChart"
style="width: 100%; height: calc(50% - 35px); box-sizing: border-box; padding: 30px 10px"
v-loading="loading.userStateMember"
></div>
<div class="col-title">人员类型</div>
<div
id="personTypeMemberChart"
style="width: 100%; height: calc(50% - 35px); box-sizing: border-box; padding: 30px 10px"
v-loading="loading.personTypeMember"
></div>
</el-col>
</el-row>
</div>
</div>
</guava>
</div>
<script>
const chart = {
growthTrendChart: undefined,
@@ -197,26 +377,29 @@ layout("/layouts/platform.html"){
userStateMemberChart: undefined
}
new Vue({
const vue = new Vue({
el: "#app",
data: {
loading: {
memberNumber: false,
growthTrend: false,
memberPercentage: false,
memberSexPercentage: false,
unionMember: false,
personTypeMember: false,
userStateMember: false
},
memberNumberData: {
memberNum: "--",
lastYearMemberNum: "--",
ratio: "0.0%",
diff: 0
},
memberPercentage: "--",
unionMember: []
data(){
return{
loading: {
memberNumber: false,
growthTrend: false,
memberPercentage: false,
memberSexPercentage: false,
unionMember: false,
personTypeMember: false,
userStateMember: false
},
memberNumberData: {
memberNum: "--",
lastYearMemberNum: "--",
ratio: "0.0%",
diff: 0
},
memberPercentage: "--",
unionMember: []
}
},
methods: {
/**
@@ -261,10 +444,30 @@ layout("/layouts/platform.html"){
autoFit: true,
data: values,
smooth: true,
showContent: true,
// 核心配色方案
color: '#217050', // 主色线
areaStyle: {
fill: "#d6e3fd"
fill: 'l(270) 0:#e8f5eb 1:#217050', // 线性渐变填充
opacity: 0.8
},
line: {
color: '#134330', // 深绿色线条
size: 2
},
// 数据点样式
point: {
size: 3,
style: {
fill: '#fff',
stroke: '#217050',
lineWidth: 2
}
},
showContent: true,
tooltip: {
customContent: function (i, data) {
if (labels[i]) {
@@ -305,10 +508,12 @@ layout("/layouts/platform.html"){
},
autoFit: true,
percent: data,
color: '#217050',
statistic: {
content: {
style: {
fontSize: 16
fontSize: 16,
fill: '#fff', // 白色文字
}
}
}
@@ -340,10 +545,21 @@ layout("/layouts/platform.html"){
colorField: "type",
legend: false,
label: {
formatter: () => ""
type: 'inner',
offset: '-30%',
style: {
fontSize: 14,
fontWeight: 'bold',
fill: '#fff', // 白色文字
textShadow: '0 1px 2px rgba(0,0,0,0.5)' // 增强可读性
},
formatter: (datum) => (datum.percent * 100).toFixed(1)
},
interactions: [{ type: "element-active" }],
color: ["#409EFF", "#F56C6C"]
// 交互效果
interactions: [
{ type: 'element-active' },
],
color: ['#217050', '#f0a35c']
})
chart.memberSexPercentageChart.render()
} else {
@@ -377,19 +593,66 @@ layout("/layouts/platform.html"){
autoFit: true,
xField: "unionname",
yField: "value",
label: {
// 可手动配置 label 数据标签位置
position: "middle", // 'top', 'bottom', 'middle',
// 配置样式
style: {
fill: "#FFFFFF",
opacity: 0.6
}
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
@@ -429,19 +692,72 @@ layout("/layouts/platform.html"){
autoFit: true,
xField: "label",
yField: "value",
label: {
// 可手动配置 label 数据标签位置
position: "middle", // 'top', 'bottom', 'middle',
// 配置样式
style: {
fill: "#FFFFFF",
opacity: 0.6
}
// 核心配色方案
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
// 数据标签
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
// 如需千分位格式化:.toLocaleString()
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
@@ -476,33 +792,87 @@ layout("/layouts/platform.html"){
return
}
chart.userStateMemberChart = new G2Plot.Radar("userStateMemberChart", {
chart.userStateMemberChart = new G2Plot.Column("userStateMemberChart", {
data,
autoFit: true,
xField: "label",
yField: "value",
appendPadding: [0, 10, 0, 10],
meta: {
value: {
alias: "会员数量",
min: 0,
nice: true,
formatter: (v) => parseInt(v)
}
// 核心配色方案
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
// 数据标签
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
// 如需千分位格式化:.toLocaleString()
},
// X轴配置
xAxis: {
tickLine: null
},
yAxis: {
label: false,
label: {
autoHide: true,
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
alternateColor: "rgba(0, 0, 0, 0.04)"
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// 开启辅助点
point: {
size: 2
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
area: {}
meta: {
label: {
alias: "类型"
},
value: {
alias: "会员数"
}
}
})
chart.userStateMemberChart.render()
} else {
@@ -518,7 +888,7 @@ layout("/layouts/platform.html"){
this.getMemberSexPercentage()
this.getUnionMember()
this.getPersonTypeMember()
this.getUserStateMember()
// this.getUserStateMember()
}
},
mounted() {
@@ -0,0 +1,718 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.top-col {
background-color: white;
position: relative;
box-sizing: border-box;
padding: 20px;
width: calc((100% - (20px * 3)) / 4);
}
.top-col:not(:last-child),
.center-col:not(:last-child) {
margin-right: 20px;
}
.col-title {
color: rgba(0, 0, 0, 0.45);
font-size: 14px;
margin-bottom: 10px;
}
.top-col-member-number {
font-size: 30px;
color: rgba(0, 0, 0, 0.85);
}
.top-col-chart {
height: 80px;
width: 100%;
position: relative;
}
.center-col {
background-color: white;
position: relative;
box-sizing: border-box;
padding: 20px;
width: calc((100% - (20px * 1)) / 2);
}
.idx {
display: flex;
justify-content: center;
align-items: center;
color: rgba(0, 0, 0, 0.85);
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #f0f0f0;
font-size: 12px;
margin: 0 auto;
}
.idx-rank {
color: white !important;
background-color: #314659 !important;
}
.el-table__body-wrapper::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
.el-table__body-wrapper {
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
overflow-x: hidden;
overflow-y: auto;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<el-row style="background-color: #f0f2f5" type="flex">
<el-col class="top-col" v-loading="loading.memberNumber">
<div class="col-title">会员数</div>
<div class="top-col-member-number">
{{memberNumberData.memberNum}}
<span style="font-size: 14px">&ensp;</span>
</div>
<div
style="
color: rgba(0, 0, 0, 0.85);
margin-top: 20px;
font-size: 14px;
display: flex;
align-items: center;
justify-content: flex-end;
"
>
年同比 {{memberNumberData.ratio}}&ensp;
<svg
aria-hidden="true"
data-icon="caret-up"
fill="currentColor"
focusable="false"
height="1em"
style="color: #67c23a"
v-if="memberNumberData.diff>=0"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"
></path>
</svg>
<svg
aria-hidden="true"
data-icon="caret-up"
fill="currentColor"
focusable="false"
height="1em"
style="color: #f56c6c"
v-else
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"
></path>
</svg>
</div>
</el-col>
<el-col class="top-col" v-loading="loading.growthTrend">
<div class="col-title">增长趋势</div>
<div class="top-col-chart" id="growthTrendChart"></div>
</el-col>
<el-col class="top-col" v-loading="loading.memberPercentage">
<div class="col-title">会员占比</div>
<div class="top-col-chart" id="memberPercentageChart" style="position: absolute; height: 120px; right: -10%; bottom: 20px"></div>
</el-col>
<el-col class="top-col" v-loading="loading.memberSexPercentageChart">
<div class="col-title">男女占比</div>
<div class="top-col-chart" id="memberSexPercentageChart" style="position: absolute; height: 120px; right: -10%; bottom: 20px"></div>
</el-col>
</el-row>
<el-row style="background-color: #f0f2f5; margin-top: 20px" type="flex">
<el-col class="center-col" v-loading="loading.unionMember">
<div class="col-title">工会会员数</div>
<div id="unionMemberChart" style="width: 100%; height: 200px"></div>
<el-table
:data="unionMember"
:header-cell-style="{background:'#FAFAFA'}"
height="calc(100vh - 190px - 400px)"
row-key="id"
style="width: 100%; margin-top: 20px"
>
<el-table-column label="序号" width="100px" align="center">
<template scope="{$index}">
<div class="idx idx-rank" v-if="$index<3">{{$index+1}}</div>
<div class="idx" v-else>{{$index+1}}</div>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="分工会" prop="unioncode" show-overflow-tooltip sortable>
<template scope="{row}">{{row.unionname}}</template>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="会员人数"
prop="value"
show-overflow-tooltip
sortable
width="120px"
></el-table-column>
</el-table>
</el-col>
<el-col class="center-col">
<div class="col-title">在职状态</div>
<div
id="userStateMemberChart"
style="width: 100%; height: calc(50% - 35px); box-sizing: border-box; padding: 30px 10px"
v-loading="loading.userStateMember"
></div>
<div class="col-title">人员类型</div>
<div
id="personTypeMemberChart"
style="width: 100%; height: calc(50% - 35px); box-sizing: border-box; padding: 30px 10px"
v-loading="loading.personTypeMember"
></div>
</el-col>
</el-row>
</guava>
</div>
<script>
const chart = {
growthTrendChart: undefined,
memberPercentageChart: undefined,
memberSexPercentageChart: undefined,
unionMemberChart: undefined,
personTypeMemberChart: undefined,
userStateMemberChart: undefined
}
new Vue({
el: "#app",
data: {
loading: {
memberNumber: false,
growthTrend: false,
memberPercentage: false,
memberSexPercentage: false,
unionMember: false,
personTypeMember: false,
userStateMember: false
},
memberNumberData: {
memberNum: "--",
lastYearMemberNum: "--",
ratio: "0.0%",
diff: 0
},
memberPercentage: "--",
unionMember: []
},
methods: {
/**
* 会员数
* @returns {Promise<void>}
*/
async getMemberNumber() {
this.loading.memberNumber = true
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
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 增长趋势
* @returns {Promise<void>}
*/
async getGrowthTrend() {
this.loading.growthTrend = true
this.$axios.post("/platform/member/info/board/growthTrend").then((resp) => {
this.loading.growthTrend = false
if (resp.code === 0) {
const { data } = resp
const labels = data.map((v) => v.label)
const values = data.map((v) => v.value)
if (chart.growthTrendChart) {
chart.growthTrendChart.changeData(values)
return
}
chart.growthTrendChart = new G2Plot.TinyArea("growthTrendChart", {
autoFit: true,
data: values,
smooth: true,
// 核心配色方案
color: '#217050', // 主色线
areaStyle: {
fill: 'l(270) 0:#e8f5eb 1:#217050', // 线性渐变填充
opacity: 0.8
},
line: {
color: '#134330', // 深绿色线条
size: 2
},
// 数据点样式
point: {
size: 3,
style: {
fill: '#fff',
stroke: '#217050',
lineWidth: 2
}
},
showContent: true,
tooltip: {
customContent: function (i, data) {
if (labels[i]) {
return labels[i] + "-" + data[0]?.data?.y + "人"
}
return ""
}
}
})
chart.growthTrendChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 会员占比
* @returns {Promise<void>}
*/
async getMemberPercentage() {
this.loading.memberPercentage = true
this.$axios.post("/platform/member/info/board/memberPercentage").then((resp) => {
this.loading.memberPercentage = false
if (resp.code === 0) {
const { data } = resp
this.memberPercentage = data.toFixed(2)
if (chart.memberPercentageChart) {
chart.memberPercentageChart.changeData(data)
return
}
chart.memberPercentageChart = new G2Plot.Liquid("memberPercentageChart", {
outline: {
border: 4,
distance: 8
},
wave: {
length: 128
},
autoFit: true,
percent: data,
color: '#217050',
statistic: {
content: {
style: {
fontSize: 16,
fill: '#fff', // 白色文字
}
}
}
})
chart.memberPercentageChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 男女占比
* @returns {Promise<void>}
*/
async getMemberSexPercentage() {
this.loading.memberSexPercentage = true
this.$axios.post("/platform/member/info/board/memberSexPercentage").then((resp) => {
this.loading.memberSexPercentage = false
if (resp.code === 0) {
const { data } = resp
if (chart.memberSexPercentageChart) {
chart.memberSexPercentageChart.changeData(data)
return
}
chart.memberSexPercentageChart = new G2Plot.Pie("memberSexPercentageChart", {
data,
angleField: "value",
colorField: "type",
legend: false,
label: {
type: 'inner',
offset: '-30%',
style: {
fontSize: 14,
fontWeight: 'bold',
fill: '#fff', // 白色文字
textShadow: '0 1px 2px rgba(0,0,0,0.5)' // 增强可读性
},
formatter: (datum) => (datum.percent * 100).toFixed(1)
},
// 交互效果
interactions: [
{ type: 'element-active' },
],
color: ['#217050', '#f0a35c']
})
chart.memberSexPercentageChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 各工会会员数
* @returns {Promise<void>}
*/
async getUnionMember() {
this.loading.unionMember = true
this.$axios.post("/platform/member/info/board/unionMember").then((resp) => {
this.loading.unionMember = false
if (resp.code === 0) {
const { chartData, tableData } = resp.data
this.unionMember = tableData
const labels = chartData.map((v) => v.unionname)
const values = chartData.map((v) => v.value)
if (chart.unionMemberChart) {
chart.unionMemberChart.changeData(values)
return
}
chart.unionMemberChart = new G2Plot.Column("unionMemberChart", {
data: chartData,
autoFit: true,
xField: "unionname",
yField: "value",
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
label: {
alias: "类型"
},
value: {
alias: "会员数"
}
}
})
chart.unionMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 根据人员类型查找会员数
* @returns {Promise<void>}
*/
async getPersonTypeMember() {
this.loading.personTypeMember = true
this.$axios.post("/platform/member/info/board/personTypeMember").then((resp) => {
this.loading.personTypeMember = false
if (resp.code === 0) {
const { data } = resp
if (chart.personTypeMemberChart) {
chart.personTypeMemberChart.changeData(data)
return
}
chart.personTypeMemberChart = new G2Plot.Column("personTypeMemberChart", {
data,
autoFit: true,
xField: "label",
yField: "value",
// 核心配色方案
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
// 数据标签
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
// 如需千分位格式化:.toLocaleString()
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
label: {
alias: "类型"
},
value: {
alias: "会员数"
}
}
})
chart.personTypeMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
/**
* 根据在职状态查找会员数
* @returns {Promise<void>}
*/
async getUserStateMember() {
this.loading.userStateMember = true
this.$axios.post("/platform/member/info/board/userStateMember").then((resp) => {
this.loading.userStateMember = false
if (resp.code === 0) {
const { data } = resp
if (chart.userStateMemberChart) {
chart.userStateMemberChart.changeData(data)
return
}
chart.userStateMemberChart = new G2Plot.Column("userStateMemberChart", {
data,
autoFit: true,
xField: "label",
yField: "value",
// 核心配色方案
color: '#217050', // 主色柱体
// 柱体样式
columnStyle: {
fill: '#217050',
stroke: '#134330',
lineWidth: 1,
shadowColor: 'rgba(33, 112, 80, 0.5)', // 主色阴影
shadowBlur: 6,
radius: [4, 4, 0, 0] // 顶部圆角
},
// 数据标签
label: {
position: "top",
style: {
fill: "#217050", // 白色文字
fontSize: 12,
fontWeight: 'bold',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
opacity: 0.9
},
formatter: (datum) => datum.value // 显示原始值
// 如需千分位格式化:.toLocaleString()
},
// X轴配置
xAxis: {
label: {
autoHide: true,
autoRotate: false,
style: {
fill: '#666',
fontSize: 12
}
},
line: {
style: {
stroke: '#e8f5eb' // 浅绿色轴线
}
},
grid: {
line: {
style: {
stroke: '#f0f0f0',
lineDash: [4, 2]
}
}
}
},
// Y轴配置
yAxis: {
label: {
style: {
fill: '#666'
},
formatter: (val) => val
},
grid: {
line: {
style: {
stroke: '#e8f5eb',
lineDash: [4, 2]
}
}
}
},
meta: {
label: {
alias: "类型"
},
value: {
alias: "会员数"
}
}
})
chart.userStateMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
})
},
initData() {
this.getMemberNumber()
this.getGrowthTrend()
this.getMemberPercentage()
this.getMemberSexPercentage()
this.getUnionMember()
this.getPersonTypeMember()
this.getUserStateMember()
}
},
mounted() {
this.initData()
}
})
</script>
<!--#
}
#-->
@@ -210,6 +210,7 @@ layout("/layouts/platform.html"){
{ prop: "mobile", label: "联系电话" },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "preparedBy", label: "聘用方式", sortable: true },
{ prop: "postDoctoralJoinDate", label: "进站时间", sortable: true },
{ prop: "personType", label: "人员类型", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true },
{ prop: "unitName", label: "所属单位", sortable: true }
@@ -123,6 +123,7 @@ layout("/layouts/platform.html"){
{ prop: "userState", label: "在职状态", width: 120, sortable: true },
{ prop: "personType", label: "教职工类别", width: 120, sortable: true },
{ prop: "preparedBy", label: "聘用方式", width: 120, sortable: true },
{ prop: "postDoctoralJoinDate", label: "进站时间", sortable: true },
{ prop: "identityType", label: "身份类型", width: 120, sortable: true },
{ prop: "unionName", label: "所属工会", width: 120, sortable: true },
{ prop: "unitName", label: "所属单位", width: 120, sortable: true },
@@ -114,19 +114,19 @@ layout("/layouts/platform.html"){
></el-date-picker>
</el-form-item>
</el-col>
<!-- <el-col span="12">
<el-form-item prop="provideTime" label="发放时间">
<el-date-picker
style="width: 100%"
v-model="formData.provideTime"
type="datetimerange"
value-format="yyyy-MM-dd HH:mm:ss"
range-separator="-"
start-placeholder="开始时间"
end-placeholder="结束时间" @change="provideTimeChange">
</el-date-picker>
</el-form-item>
</el-col>-->
<el-col span="12">
<el-form-item prop="provideTime" label="发放时间">
<el-date-picker
style="width: 100%"
v-model="formData.provideTime"
type="datetimerange"
value-format="yyyy-MM-dd HH:mm:ss"
range-separator="-"
start-placeholder="开始时间"
end-placeholder="结束时间" @change="provideTimeChange">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row>
@@ -129,7 +129,7 @@ layout("/layouts/platform.html"){
const now = this.$moment().valueOf()
if (overdueChoiceTimeEnd == null || overdueChoiceTimeEnd === "") {
if (now > this.$moment(choiceTimeStart).valueOf() && now < moment(choiceTimeEnd).valueOf()) {
return { text: isChoose ? "确定修改" : "确定选择", disabled: false }
return { text: isChoose ? "修改" : "确定选择", disabled: false }
} else if (now > this.$moment(choiceTimeEnd).valueOf()) {
return { text: "选择已结束", disabled: true }
} else if (now < this.$moment(choiceTimeStart).valueOf()) {
@@ -118,7 +118,7 @@ const optionSelect = {
<el-dialog
title="福利详情"
:visible.sync="showOptionDetailDialog"
width="600px"
width="60%"
append-to-body
custom-class="welfare-detail-dialog">
<div class="welfare-detail-popup" v-if="selectedOption">
@@ -1,6 +1,6 @@
const selectedUser = {
template: /*language=HTML*/ `
<el-dialog :title="unionName+'已选择用户'" :visible.sync="visible">
<el-dialog :title="unionName+'已选择用户'" :visible.sync="visible" width="70%">
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
<div>
<el-input
@@ -48,8 +48,12 @@ const selectedUser = {
tableColumns: [
{ label: "工号", prop: "loginName" },
{ label: "姓名", prop: "userName" },
{ label: "生日", prop: "birthday" },
{ prop: "userState", label: "在职状态", width: 120, sortable: true },
{ prop: "personType", label: "教职工类别", width: 120, sortable: true },
{ prop: "preparedBy", label: "聘用方式", width: 120, sortable: true },
{ prop: "postDoctoralJoinDate", label: "进站时间", sortable: true },
{ label: "单位", prop: "welfareUnitName" },
{ label: "分工会", prop: "welfareUnionName" },
{ label: "手机号", prop: "mobile" },
{ label: "所选福利", prop: "selectOptionName" }
]
@@ -1,6 +1,6 @@
const unSelectedUser = {
template: /*language=HTML*/ `
<el-dialog :title="unionName+'未选择用户'" :visible.sync="visible">
<el-dialog :title="unionName+'未选择用户'" :visible.sync="visible" width="70%">
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
<div>
<el-input
@@ -47,8 +47,12 @@ const unSelectedUser = {
tableColumns: [
{ label: "工号", prop: "loginName" },
{ label: "姓名", prop: "userName" },
{ label: "单位", prop: "welfareUnitName" },
{ label: "分工会", prop: "welfareUnionName" }
{ label: "生日", prop: "birthday" },
{ prop: "userState", label: "在职状态", width: 120, sortable: true },
{ prop: "personType", label: "教职工类别", width: 120, sortable: true },
{ prop: "preparedBy", label: "聘用方式", width: 120, sortable: true },
{ prop: "postDoctoralJoinDate", label: "进站时间", sortable: true },
{ label: "单位", prop: "welfareUnitName" }
]
}
},
@@ -992,7 +992,7 @@ layout("/layouts/platform_h5.html"){
if (!start || !end) return "未设置"
const startDate = this.$moment(start).format("YYYY-MM-DD")
const endDate = this.$moment(end).format("YYYY-MM-DD")
const endDate = this.$moment(end).format("YYYY-MM-DD HH:mm")
if (startDate === endDate) {
return startDate + " " + this.$moment(start).format("HH:mm") + "~" + this.$moment(end).format("HH:mm")