feat: 疗休养优化

This commit is contained in:
2026-11-04 17:11:14 +08:00
parent 894c720bb8
commit 060e8d5bc7
20 changed files with 730 additions and 98 deletions
@@ -0,0 +1,32 @@
package com.budwk.app.sys.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.result.Result;
import com.budwk.app.sys.services.SysDataUserPullService;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
@IocBean
@At("/platform/sys/data/user/query")
@Ok("json:full")
public class SysDataUserQueryController {
@Inject
private SysDataUserPullService sysUserPullService;
@At("")
@Ok("beetl:/platform/sys/data/user/query.html")
@SaCheckPermission("sys.data.user.query")
public void index() {
}
@At
@SaCheckPermission("sys.data.user.query")
public Result queryData(@Param("zgh") String zgh, @Param("pageNumber") int pageNumber,
@Param("pageSize") int pageSize) {
return Result.success(sysUserPullService.queryUsers(zgh, pageNumber, pageSize));
}
}
@@ -15,6 +15,8 @@ public interface SysDataUserPullService extends BaseService<Sys_user_source> {
*/
Date pull();
NutMap queryUsers(String zgh, int pageNumber, int pageSize);
/**
* 拉取人员博士后的信息
*/
@@ -334,12 +334,39 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
return url;
}
@Override
public NutMap queryUsers(String zgh, int pageNumber, int pageSize) {
if (pageNumber < 1 || pageSize < 1 || pageSize > 200) {
throw new BaseException("分页参数不合法");
}
if (!dataCenterProperties.isTokenEnabled()) {
JSONObject response = DataCenterUtil.queryPage(getDmpUrl(DMP_TEACHER_KEY), zgh, pageNumber, pageSize);
JSONObject pageInfo = response.getJSONObject("pageInfo");
JSONArray data = response.getJSONArray("dataSet");
if (pageInfo == null || pageInfo.getLong("total") == null || data == null) {
throw new BaseException("数据中心接口未返回有效的分页数据");
}
return NutMap.NEW().addv("list", data).addv("totalCount", pageInfo.getLong("total"));
}
String accessToken = getDmpAccessToken();
List<JSONObject> records = new ArrayList<>();
records.addAll(pullDmpUsers(getDmpUrl(DMP_TEACHER_KEY), accessToken, "在岗教职工", StrUtil.trim(zgh)));
records.addAll(pullDmpUsers(getDmpUrl(DMP_DISPATCH_KEY), accessToken, "在岗劳务派遣", StrUtil.trim(zgh)));
int from = (int) Math.min((long) (pageNumber - 1) * pageSize, records.size());
return NutMap.NEW().addv("list", records.subList(from, Math.min(from + pageSize, records.size())))
.addv("totalCount", records.size());
}
/**
* 分页拉取单个人员接口数据。
* 入参 url 为人员接口地址,accessToken 为信息中心令牌,sourceName 用于日志区分接口来源。
* 返回值为该接口所有分页合并后的原始人员 JSON 列表。
*/
private List<JSONObject> pullDmpUsers(String url, String accessToken, String sourceName) {
return pullDmpUsers(url, accessToken, sourceName, null);
}
private List<JSONObject> pullDmpUsers(String url, String accessToken, String sourceName, String zgh) {
List<JSONObject> rawDataList = new ArrayList<>();
int page = 1;
int maxPage = 1;
@@ -349,11 +376,14 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
// 信息中心接口单页最多返回1000条,按page循环拉完当前接口全部数据。
HttpRequest httpRequest = HttpUtil.createPost(url);
httpRequest.header(Header.CONTENT_TYPE, "application/json");
httpRequest.body(JSONUtil.toJsonStr(Map.of(
"access_token", accessToken,
"per_page", String.valueOf(DMP_PAGE_SIZE),
"page", String.valueOf(page)
)));
Map<String, Object> body = new HashMap<>();
body.put("access_token", accessToken);
body.put("per_page", String.valueOf(DMP_PAGE_SIZE));
body.put("page", String.valueOf(page));
if (StrUtil.isNotBlank(zgh)) {
body.put("zgh", zgh);
}
httpRequest.body(JSONUtil.toJsonStr(body));
log.info("请求{}人员数据,第{}页: {}", sourceName, page, httpRequest);
String resBody = httpRequest.execute().body();
@@ -14,6 +14,7 @@ import com.budwk.app.sys.models.Sys_unit;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -40,7 +41,11 @@ public class DataCenterUtil {
}
public static List<JSONObject> pullData(String url) {
JSONObject firstResponse = requestData(url, Map.of("", ""));
return pullData(url, Map.of("", ""));
}
public static List<JSONObject> pullData(String url, Map<String, ?> params) {
JSONObject firstResponse = requestData(url, params);
JSONObject pageInfo = firstResponse.getJSONObject("pageInfo");
Integer pages = pageInfo == null ? null : pageInfo.getInt("pages");
if (pages == null || pages < 0) {
@@ -48,7 +53,9 @@ public class DataCenterUtil {
}
List<JSONObject> records = new ArrayList<>();
for (int page = 1; page <= pages; page++) {
JSONObject response = requestData(url, Map.of("pageNum", page));
Map<String, Object> body = new HashMap<>(params);
body.put("pageNum", page);
JSONObject response = requestData(url, body);
JSONArray data = response.getJSONArray("dataSet");
if (data == null) {
throw new BaseException("数据中心接口第{}页缺少 dataSet", page);
@@ -58,6 +65,16 @@ public class DataCenterUtil {
return records;
}
public static JSONObject queryPage(String url, String zgh, int pageNumber, int pageSize) {
Map<String, Object> body = new HashMap<>();
body.put("pageNum", pageNumber);
body.put("pageSize", pageSize);
if (StrUtil.isNotBlank(zgh)) {
body.put("zgh", zgh.trim());
}
return requestData(url, body);
}
private static JSONObject requestData(String url, Map<String, ?> body) {
try (HttpResponse response = HttpUtil.createPost(url)
.body(JSONUtil.toJsonStr(body)).execute()) {
@@ -0,0 +1,28 @@
-- 在人员数据拉取菜单同级新增实时查询入口,沿用现有菜单的角色授权。
INSERT INTO sys_menu (
id, parentId, path, name, type, href, target, icon, showit, disabled,
permission, location, hasChildren, platform, moduleId,
createdBy, createdAt, updatedBy, updatedAt, delFlag
)
SELECT 'bc6cf4034e9449bfa6e81c7d26509129', source.parentId,
CONCAT(LEFT(source.path, CHAR_LENGTH(source.path) - 4),
LPAD(COALESCE((SELECT MAX(CAST(RIGHT(sibling.path, 4) AS UNSIGNED))
FROM sys_menu sibling WHERE sibling.parentId = source.parentId), 0) + 1, 4, '0')),
'数据中心人员查询', 'menu', '/platform/sys/data/user/query', source.target,
source.icon, 1, 0, 'sys.data.user.query', source.location + 1, 0,
source.platform, source.moduleId, '', UNIX_TIMESTAMP(NOW()) * 1000,
'', UNIX_TIMESTAMP(NOW()) * 1000, 0
FROM sys_menu source
WHERE source.permission = 'sys.data.user.pull'
AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE permission = 'sys.data.user.query')
LIMIT 1;
INSERT INTO sys_role_menu (roleId, menuId)
SELECT DISTINCT relation.roleId, target.id
FROM sys_role_menu relation
JOIN sys_menu source ON source.id = relation.menuId AND source.permission = 'sys.data.user.pull'
JOIN sys_menu target ON target.permission = 'sys.data.user.query'
WHERE NOT EXISTS (
SELECT 1 FROM sys_role_menu existing
WHERE existing.roleId = relation.roleId AND existing.menuId = target.id
);
@@ -1,9 +1,9 @@
Vue.component('vi-title', {
props: ['title'],
template: `
<div style="display: flex;flex-direction:row;color: var(--color-primary);font-weight: bolder;margin-bottom: 20px">
<div style="width: 5px;height: 24px;background-color: var(--color-primary);border-radius: 2px"></div>
<div style="margin-left: 20px;line-height: 24px;font-size: 15px;letter-spacing: 1px">
<div class="therapy-title" style="display: flex;flex-direction:row;color: var(--color-primary);font-weight: bolder;margin-bottom: 20px">
<div class="therapy-title-marker" style="width: 5px;height: 24px;background-color: var(--color-primary);border-radius: 2px"></div>
<div class="therapy-title-text" style="margin-left: 20px;line-height: 24px;font-size: 15px;letter-spacing: 1px">
{{ title }}
</div>
</div>
@@ -79,7 +79,7 @@ Vue.component('table-tool', {
this.getColumns()
},
template: `
<el-row type="flex" justify="space-between" align="middle" style="margin-bottom: 15px">
<el-row class="therapy-table-tool" type="flex" justify="space-between" align="middle" style="margin-bottom: 15px">
<div style="display: flex;justify-content: center;align-items: center">
<vi-title :title="label" style="margin-bottom: 0"></vi-title><slot name="label_end"></slot>
@@ -0,0 +1,189 @@
.therapy-desktop {
font-family: "Helvetica Neue", "Microsoft YaHei", Arial, sans-serif;
font-size: 14px;
color: #303133;
}
.therapy-desktop #app {
height: auto;
min-height: 100%;
overflow: visible;
background: transparent;
}
.therapy-desktop #app .el-card__header {
padding: 16px 20px;
color: #303133;
font-size: 16px;
font-weight: 600;
line-height: 24px;
}
.therapy-desktop #app .el-form-item__label {
color: #606266;
font-weight: 400;
}
.therapy-desktop #app .search {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px 24px;
margin: 0;
}
.therapy-desktop #app .search .search-item {
width: auto;
min-width: 0;
margin: 0;
padding: 0;
overflow: visible;
}
.therapy-desktop #app .search .search-item-label {
flex: 0 0 90px;
width: 90px;
min-width: 0;
margin-right: 12px;
color: #606266;
text-align: right;
line-height: 20px;
overflow: visible;
}
.therapy-desktop #app .search .search-item-option {
flex: 1;
width: 0;
min-width: 0;
overflow: visible;
}
.therapy-desktop #app .search-item-option > .el-input,
.therapy-desktop #app .search-item-option > .el-select,
.therapy-desktop #app .search-item-option > .el-date-editor {
width: 100%;
max-width: 100%;
}
.therapy-desktop #app .search-item-option > .el-radio-group {
display: flex;
flex-wrap: wrap;
gap: 4px 0;
}
.therapy-desktop #app .search .search-query {
display: flex;
align-items: center;
gap: 10px;
width: auto;
margin: 0;
padding-left: 102px;
overflow: visible;
}
.therapy-desktop #app .query-row {
height: auto;
min-height: 56px;
padding: 12px 0;
}
.therapy-desktop #app .query-row > .query-row-title:empty {
display: none;
}
.therapy-desktop #app .query-row .el-col {
min-width: 0;
overflow: visible;
}
.therapy-desktop #app .query-row-content {
flex: 1;
}
.therapy-desktop #app .query-row-content > .el-row {
display: flex;
flex-wrap: wrap;
row-gap: 12px;
}
.therapy-desktop #app .query-row-content > .el-row > .el-col {
display: flex;
align-items: center;
gap: 12px;
padding-right: 24px;
}
.therapy-desktop #app .query-row-content > .el-row > .el-col > span:first-child {
flex: 0 0 90px;
color: #606266;
text-align: right;
}
.therapy-desktop #app .query-row-content > .el-row > .el-col > .el-input,
.therapy-desktop #app .query-row-content > .el-row > .el-col > .el-select {
flex: 1;
width: 0 !important;
min-width: 0;
}
.therapy-desktop .therapy-table-tool {
flex-wrap: wrap;
gap: 12px;
}
.therapy-desktop .therapy-table-tool > div {
min-width: 0;
max-width: 100%;
flex-wrap: wrap;
gap: 10px;
}
.therapy-desktop .therapy-title {
display: flex;
align-items: center;
min-width: 0;
margin-bottom: 16px;
color: #303133 !important;
font-size: 16px;
font-weight: 600 !important;
line-height: 24px;
overflow-wrap: anywhere;
}
.therapy-desktop .therapy-title .therapy-title-marker {
flex: 0 0 3px;
height: 16px !important;
}
.therapy-desktop .therapy-title .therapy-title-text {
margin-left: 10px !important;
font-size: 16px !important;
letter-spacing: normal !important;
}
.therapy-desktop #app .chart-title,
.therapy-desktop #app .col-title {
color: #303133;
font-size: 16px;
font-weight: 600;
}
@media (max-width: 1199px) {
.therapy-desktop #app .search {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 767px) {
.therapy-desktop #app .search {
grid-template-columns: minmax(0, 1fr);
}
.therapy-desktop #app .query-row-content > .el-row > .el-col {
width: 100%;
padding-right: 0;
}
.therapy-desktop .therapy-table-tool > div {
width: 100%;
}
}
@@ -1,6 +1,6 @@
<template>
<div>
<div class="panel panel-default mt20" style="border: none">
<div class="panel panel-default" style="border: none">
<div class="panel-heading" style="background: #fafafa;border:1px solid #ebeef5;border-bottom: none">
<h3 class="panel-title">
基地信息
@@ -3,7 +3,7 @@
<div>
<el-tabs tab-position="top" v-model="activeName" v-loading="loading">
<el-tab-pane label="报名信息" name="1">
<div class="panel panel-default mt20" style="border: none">
<div class="panel panel-default" style="border: none">
<div class="panel-heading" style="background: #fafafa;border:1px solid #ebeef5;border-bottom: none">
<h3 class="panel-title">
本人信息
@@ -8,7 +8,7 @@
<template #header>
<el-row type="flex">
<el-col :span="12">
<el-button icon="el-icon-back" style="font-size: 16px" type="text" @click="v='index'">返回</el-button>
<el-button icon="el-icon-back" style="font-size: 16px; padding: 0" type="text" @click="v='index'">返回</el-button>
</el-col>
<el-col :span="12" class="text-right">
<slot name="edit_func"></slot>
@@ -22,7 +22,7 @@
<el-card v-show="v==='view'" key="view" shadow="never" class="animated-card">
<template #header>
<el-button icon="el-icon-back" style="font-size: 16px" type="text" @click="v='index'">返回</el-button>
<el-button icon="el-icon-back" style="font-size: 16px; padding: 0" type="text" @click="v='index'">返回</el-button>
</template>
<div :class="{'card_scroll':edit_scroll}">
<slot name="view"></slot>
@@ -31,7 +31,7 @@
<el-card v-show="v==='public'" key="public" shadow="never" class="animated-card">
<div slot="header" class="clearfix">
<el-button icon="el-icon-back" style="font-size: 16px" type="text" @click="back()">返回
<el-button icon="el-icon-back" style="font-size: 16px; padding: 0" type="text" @click="back()">返回
</el-button>
</div>
<div>
@@ -92,7 +92,7 @@ module.exports = {
<style>
.guava-main-content {
padding: 10px 12px;
padding: 0;
background-color: #f6f6f6;
min-height: 100%;
}
@@ -114,8 +114,12 @@ module.exports = {
}
}
.el-card__header {
padding: 5px 20px !important;
.guava-main-content > .animated-card > .el-card__header {
padding: 12px 24px !important;
}
.guava-main-content > .animated-card > .el-card__body {
padding: 20px 24px;
}
.el-tabs--border-card {
@@ -143,4 +147,4 @@ module.exports = {
display: none;
}
</style>
</style>
@@ -1,16 +1,16 @@
<template>
<div>
<div class="panel panel-default mt20" style="border: none">
<div class="panel-heading" style="background: #fafafa;border:1px solid #ebeef5;border-bottom: none">
<h3 class="panel-title">
<div class="therapy-line-info">
<div class="line-info-section">
<div class="line-info-section-header">
<h3 class="line-info-section-title">
线路信息
</h3>
</div>
<el-descriptions :column="2" border class="viewTable">
<el-descriptions-item label="年度">{{ viewData.year }}</el-descriptions-item>
<el-descriptions-item label="编号">{{ viewData.serialNumber }}</el-descriptions-item>
<el-descriptions-item label="线路名称">{{ viewData.lineName }}</el-descriptions-item>
<el-descriptions-item label="区域性质">{{ viewData.regionalNature }}</el-descriptions-item>
<dl class="line-info-fields">
<div class="line-info-field"><dt>年度</dt><dd>{{ viewData.year }}</dd></div>
<div class="line-info-field"><dt>编号</dt><dd>{{ viewData.serialNumber }}</dd></div>
<div class="line-info-field"><dt>线路名称</dt><dd>{{ viewData.lineName }}</dd></div>
<div class="line-info-field"><dt>区域性质</dt><dd>{{ viewData.regionalNature }}</dd></div>
<!-- <el-descriptions-item label="最少参与教工">{{ viewData.minimumGroupSize }}</el-descriptions-item>-->
<!-- (校工会创建AND自由模式) OR (分工会创建) -->
<!-- <template v-if="(viewData.createMode === 2 && viewData.signUpMode === 2 ) || viewData.createMode === 1">-->
@@ -25,12 +25,12 @@
<!-- <el-descriptions-item label="预计费用(元)">{{ viewData.estimatedCost }}</el-descriptions-item>-->
<!-- <el-descriptions-item label="预计人数(含家属)">{{ viewData.estimatedFamilyNumbers }}</el-descriptions-item>-->
<!-- <el-descriptions-item label=""></el-descriptions-item>-->
</el-descriptions>
</dl>
</div>
<div class="panel panel-default mt20" style="border:none" v-if="showTravelTimePeriod">
<div class="panel-heading" style="background: #fafafa;border:1px solid #ebeef5;border-bottom: none">
<h3 class="panel-title">
<div class="line-info-section" v-if="showTravelTimePeriod">
<div class="line-info-section-header">
<h3 class="line-info-section-title">
出行时间段
</h3>
</div>
@@ -73,14 +73,15 @@
</el-descriptions>
</div>
-->
<div class="panel panel-default mt20" style="border-color: #ebeef5">
<div class="panel-heading" style="background: #fafafa;border-color: #ebeef5">
<h3 class="panel-title">
<div class="line-info-section">
<div class="line-info-section-header">
<h3 class="line-info-section-title">
线路内容
</h3>
</div>
<div class="panel-body">
<div v-html="viewData.content"></div>
<div class="line-info-content">
<div v-html="viewData.content" v-if="viewData.content"></div>
<div class="line-info-empty" v-else>暂无线路内容</div>
</div>
</div>
</div>
@@ -134,12 +135,113 @@ module.exports = {
}
</script>
<style scoped>
.viewTable .el-descriptions__table {
table-layout: fixed !important;
<style>
.therapy-line-info {
color: #303133;
font-size: 14px;
line-height: 1.6;
}
.viewTable .el-descriptions-item__cell {
text-align: center !important;
.therapy-line-info .line-info-section {
margin-bottom: 24px;
overflow: hidden;
border: 1px solid #ebeef5;
border-radius: 4px;
background: #fff;
}
.therapy-line-info .line-info-section:last-child {
margin-bottom: 0;
}
.therapy-line-info .line-info-section-header {
padding: 14px 20px;
border-bottom: 1px solid #ebeef5;
background: #fafafa;
}
.therapy-line-info .line-info-section-title {
margin: 0;
padding-left: 10px;
border-left: 3px solid var(--color-primary, #409eff);
color: #303133;
font-size: 16px;
font-weight: 600;
line-height: 22px;
}
.therapy-line-info .line-info-fields {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
margin: 0;
}
.therapy-line-info .line-info-field {
display: grid;
grid-template-columns: 120px minmax(0, 1fr);
min-width: 0;
}
.therapy-line-info .line-info-field:nth-child(n + 3) {
border-top: 1px solid #ebeef5;
}
.therapy-line-info .line-info-field:nth-child(2n) {
border-left: 1px solid #ebeef5;
}
.therapy-line-info .line-info-field dt,
.therapy-line-info .line-info-field dd {
margin: 0;
padding: 14px 16px;
line-height: 24px;
text-align: left;
overflow-wrap: anywhere;
}
.therapy-line-info .line-info-field dt {
border-right: 1px solid #ebeef5;
background: #fafafa;
color: #606266;
font-weight: 400;
}
.therapy-line-info .line-info-content {
padding: 20px 24px;
color: #303133;
line-height: 1.9;
overflow-wrap: anywhere;
overflow-x: auto;
}
.therapy-line-info .line-info-content p {
margin: 0 0 12px;
}
.therapy-line-info .line-info-content img,
.therapy-line-info .line-info-content video {
max-width: 100%;
height: auto;
}
.therapy-line-info .line-info-empty {
padding: 12px 0;
color: #909399;
text-align: center;
}
@media (max-width: 767px) {
.therapy-line-info .line-info-fields {
grid-template-columns: minmax(0, 1fr);
}
.therapy-line-info .line-info-field + .line-info-field {
border-top: 1px solid #ebeef5;
border-left: 0;
}
.therapy-line-info .line-info-content {
padding: 16px;
}
}
</style>
@@ -3,7 +3,7 @@
<div>
<el-tabs tab-position="top" v-model="activeName" v-loading="loading">
<el-tab-pane label="报名信息" name="1">
<div class="panel panel-default mt20" style="border: none">
<div class="panel panel-default" style="border: none">
<div class="panel-heading" style="background: #fafafa;border:1px solid #ebeef5;border-bottom: none">
<h3 class="panel-title">
本人信息
@@ -504,7 +504,9 @@ layout("/layouts/v4/baseLayout.html"){
// 页面加载时获取到正确的菜单
const pathname = window.location.pathname
if (!pathname.startsWith("/platform/v4/subApp")) {
const path = this.getMenuOwnerFullPath()
// 普惠疗休养子菜单含 mode 等参数,刷新时统一从模块根菜单恢复侧栏。
const path = pathname === "/platform/inclusiveTherapyV3" || pathname.startsWith("/platform/inclusiveTherapyV3/")
? "/platform/inclusiveTherapyV3" : this.getMenuOwnerFullPath()
this.$axios.post("/platform/sys/user/rootMenuByPath", {pathname: path}).then((res) => {
if (res.code === 0) {
this.setAppInfo(res.data)
@@ -0,0 +1,82 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="工号">
<el-input placeholder="请输入工号" clearable v-model="pageForm.zgh" @keyup.enter.native="doSearch"></el-input>
</search-item>
<el-button slot="actions" icon="el-icon-refresh-left" :disabled="tableLoading" @click="resetSearch">重置</el-button>
</search>
</el-card>
<el-card shadow="never">
<table-tool :label="'数据中心人员数据(' + tableData.length + '条)'"></table-tool>
<el-table :data="tableData" v-loading="tableLoading" empty-text="暂无数据" border>
<el-table-column type="index" label="序号" width="70" fixed="left" :index="indexMethod"></el-table-column>
<el-table-column v-for="column in columns" :key="column.key" :label="column.label" min-width="160" show-overflow-tooltip>
<template slot-scope="{row}">{{formatValue(row[column.key] != null ? row[column.key] : row[column.alias])}}</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
pageDataUrl: "/platform/sys/data/user/query/queryData",
pageForm: { zgh: "" },
columns: [
{ key: "ZGH", label: "工号", alias: "ID" },
{ key: "XM", label: "姓名", alias: "" },
{ key: "XBMC", label: "性别", alias: "XB" },
{ key: "SJHM", label: "手机号码", alias: "YDDH" },
{ key: "CSRQ", label: "出生日期", alias: "" },
{ key: "DQZTMC", label: "在职状态", alias: "DQZT" },
{ key: "LXRQ", label: "来校时间", alias: "LXNY" },
{ key: "YRFSDM", label: "人员类型", alias: "RYLX" },
{ key: "SZDW", label: "单位名称", alias: "" },
{ key: "SZDWDM", label: "单位编码", alias: "SZDWH" },
{ key: "ZZMMM", label: "政治面貌", alias: "" },
{ key: "MZDM", label: "民族", alias: "MZM" },
{ key: "ZGXLMC", label: "学历", alias: "" },
{ key: "ZGXWMC", label: "学位", alias: "" },
{ key: "ZYJSGWLBDMMC", label: "聘岗类型", alias: "" },
{ key: "ZYJSZWDMMC", label: "职称", alias: "" },
{ key: "BZLBDMMC", label: "编制类别", alias: "" },
{ key: "SFSJT", label: "是否双肩挑", alias: "" },
{ key: "SFZJLXDM", label: "证件类型", alias: "" },
{ key: "SFZJH", label: "证件号码", alias: "" },
{ key: "ZGXLDM", label: "最高学历代码", alias: "" },
{ key: "XWDM", label: "最高学位代码", alias: "" },
{ key: "BZLBDM", label: "编制类别代码", alias: "" },
{ key: "ZYJSGWLBDM", label: "聘岗类型代码", alias: "" },
{ key: "ZYJSZWDM", label: "专业技术职务代码", alias: "" },
{ key: "DQZTDM", label: "当前状态代码", alias: "" }
]
}
},
methods: {
resetSearch() {
this.pageForm.zgh = ""
this.doSearch()
},
formatValue(value) {
if (value == null) return ""
return typeof value === "object" ? JSON.stringify(value) : value
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -14,32 +14,60 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
.el-radio {
margin-right: 0;
}
#app .search .line-year-filter {
grid-column: span 2;
}
#app .search .line-year-range {
display: grid;
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
align-items: center;
gap: 10px;
}
#app .search .line-year-range > .picker-year {
width: 100%;
min-width: 0;
}
#app .search .line-year-range > span {
width: auto;
color: #909399;
font-weight: 400;
}
@media (max-width: 767px) {
#app .search .line-year-filter {
grid-column: span 1;
}
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<div class="search">
<div class="search-item">
<div class="search-item line-year-filter">
<div class="search-item-label">年度范围:</div>
<div class="search-item-option" style="display:flex;align-items:center;gap:10px">
<div class="search-item-option line-year-range">
<el-date-picker
v-model="pageForm.startYear"
type="year"
class="picker-year"
format="yyyy"
style="flex:1;width:0;min-width:0"
placeholder="开始年份"
value-format="yyyy"
@change="handleChangeYear"
>
</el-date-picker>
<span style="flex-shrink:0">至</span>
<span>至</span>
<el-date-picker
v-model="pageForm.endYear"
type="year"
class="picker-year"
format="yyyy"
style="flex:1;width:0;min-width:0"
placeholder="结束年份"
value-format="yyyy"
@change="handleChangeYear"
>
@@ -24,6 +24,7 @@
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index_custom.css">
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/override.css">
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css">
<link rel="stylesheet" href="${base!}/assets/staffbenefit/therapyRecuperation/css/desktop.css">
<script src="${base!}/assets/platform/plugins/element-ui/lib/index.js"></script>
<script>
ELEMENT.Dialog.props.closeOnClickModal.default = false;
@@ -68,6 +69,6 @@ Vue.directive('auth', {inserted(el, binding) {
if (!requested.some(role => roles.includes(role))) el.parentNode.removeChild(el);
}});
</script>
<style>body{margin:0;padding:12px;box-sizing:border-box;background:#f6f6f6} [v-cloak]{display:none}</style>
</head><body>${layoutContent}</body></html>
<style>body{margin:0;padding:0;box-sizing:border-box;background:#f6f6f6} [v-cloak]{display:none}</style>
</head><body class="therapy-desktop">${layoutContent}</body></html>
<!--# } #-->
@@ -78,13 +78,11 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div class="search-item">
<div class="search-item-label">线路类型:</div>
<div class="search-item-option">
<el-radio-group class="mr0-radio"
<el-select placeholder="请选择线路类型" style="width: 100%"
v-model="pageForm.regionalNature">
<el-radio-button :label="item.value"
border v-for="(item, therapyIndex) in regionalNatureList" :key="item.id || item.code || therapyIndex">
{{item.label}}
</el-radio-button>
</el-radio-group>
<el-option :value="item.value" :label="item.label"
v-for="(item, therapyIndex) in regionalNatureList" :key="item.id || item.code || therapyIndex"></el-option>
</el-select>
</div>
</div>
@@ -41,15 +41,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div class="search-item">
<div class="search-item-label">线路类型:</div>
<div class="search-item-option">
<el-radio-group class="mr0-radio"
<el-select placeholder="请选择线路类型" style="width: 100%"
@change="doSearch"
v-model="pageForm.regionalNature">
<el-radio-button :label="item.value"
border
v-for="(item, therapyIndex) in regionalNatureList" :key="item.id || item.code || therapyIndex">
{{item.label}}
</el-radio-button>
</el-radio-group>
<el-option :value="item.value" :label="item.label"
v-for="(item, therapyIndex) in regionalNatureList" :key="item.id || item.code || therapyIndex"></el-option>
</el-select>
</div>
</div>
@@ -58,14 +58,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div class="search-item">
<div class="search-item-label">线路类型:</div>
<div class="search-item-option">
<el-radio-group class="mr0-radio"
<el-select placeholder="请选择线路类型" style="width: 100%"
@change="doSearch"
v-model="pageForm.regionalNature">
<el-radio-button :label="item.value"
border v-for="(item, therapyIndex) in regionalNatureList" :key="item.id || item.code || therapyIndex">
{{item.label}}
</el-radio-button>
</el-radio-group>
<el-option :value="item.value" :label="item.label"
v-for="(item, therapyIndex) in regionalNatureList" :key="item.id || item.code || therapyIndex"></el-option>
</el-select>
</div>
</div>
@@ -4,14 +4,130 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<style>
.item-button {
#app .therapy-config .el-card__header {
padding: 16px 20px;
font-size: 16px;
font-weight: 600;
line-height: 24px;
}
#app .therapy-config .el-tabs__header {
margin-bottom: 24px;
}
#app .config-base {
display: grid;
grid-template-columns: minmax(0, 1fr);
max-width: 860px;
}
#app .config-section-title {
grid-column: 1 / -1;
margin: 4px 0 18px;
padding: 8px 12px;
border-left: 3px solid var(--color-primary, #409eff);
color: #303133;
font-size: 14px;
font-weight: 600;
line-height: 20px;
background: #f5f7fa;
}
#app .config-base .el-form-item {
min-width: 0;
margin-bottom: 18px;
}
#app .config-base .el-form-item__label {
line-height: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
#app .config-wide {
grid-column: 1 / -1;
max-width: 860px;
}
#app .config-scope,
#app .config-time-range {
display: flex;
align-items: center;
gap: 12px;
}
#app .config-scope .el-select {
flex: 1;
min-width: 0;
}
#app .config-time-range .el-date-editor {
width: 0;
flex: 1;
min-width: 0;
}
#app .config-time-separator {
color: #909399;
}
#app .config-table-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
color: #606266;
}
#app .config-actions {
position: sticky;
bottom: 0;
z-index: 20;
margin: 20px 0 0;
padding: 16px 0;
background: #fff;
border-top: 1px solid #ebeef5;
text-align: right;
}
.item-button .el-button {
#app .config-actions .el-form-item__content {
margin-left: 0 !important;
}
#app .config-actions .el-button {
padding: 12px 25px;
}
@media (min-width: 1280px) {
#app .config-base {
max-width: 1120px;
grid-template-columns: repeat(2, minmax(0, 1fr));
column-gap: 24px;
}
}
@media (max-width: 767px) {
#app .config-base > .el-form-item > .el-form-item__label {
float: none;
display: block;
width: auto !important;
text-align: left;
}
#app .config-base > .el-form-item > .el-form-item__content {
margin-left: 0 !important;
}
#app .config-time-range {
flex-wrap: wrap;
}
#app .config-time-range .el-date-editor {
flex: 1 1 100%;
width: 100%;
}
}
/*.el-dialog__title {
font-size: 18px; !* 修改标题字体大小 *!
color: red; !* 修改标题字体颜色 *!
@@ -22,37 +138,34 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<el-card shadow="never" class="therapy-config">
<div slot="header" class="clearfix">
<h3 style="color: var(--color-primary);font-family: Microsoft YaHei;">疗休养配置</h3>
<span>普惠疗休养基础设置</span>
</div>
<el-form ref="addForm" :model="formData" :rules="formRules" label-width="170px">
<el-tabs v-model="activeTab" type="card">
<el-tab-pane label="基本配置" name="baseConfig">
<el-form ref="addForm" :model="formData" :rules="formRules" label-width="200px">
<el-tabs v-model="activeTab">
<el-tab-pane label="基本配置" name="baseConfig" class="config-base">
<div class="config-section-title">基本信息</div>
<el-form-item label="配置名称" prop="configName">
<el-input v-model="formData.configName" placeholder="请输入配置名称"></el-input>
</el-form-item>
<el-form-item prop="activityGroupId" label="参加人员范围">
<div style="display: flex; justify-content: space-between">
<div style="width: 99%">
<div class="config-scope">
<el-select v-model="formData.activityGroupId" placeholder="请选择参加人员范围" filterable
clearable
style="width: 99%">
clearable>
<el-option v-for="item in activityGroupList"
:value="item.groupId"
:key="item.groupId"
:label="item.groupName"></el-option>
</el-select>
</div>
<div>
<el-button @click="$refs.drawerUserScope.userScopeDialog = true" type="primary">设置</el-button>
</div>
</div>
</el-form-item>
<!-- 报名时间范围绑定配置实体的两个独立字段,保存时随 formData 一并提交到后台。 -->
<el-form-item label="报名时间">
<el-form-item label="报名时间" class="config-wide">
<div class="config-time-range">
<el-date-picker
v-model="formData.signUpStartTime"
type="datetime"
@@ -60,7 +173,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
format="yyyy-MM-dd HH:mm"
placeholder="请选择报名开始时间">
</el-date-picker>
<span style="display: inline-block; margin: 0 10px;">至</span>
<span class="config-time-separator">至</span>
<el-date-picker
v-model="formData.signUpEndTime"
type="datetime"
@@ -68,10 +181,12 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
format="yyyy-MM-dd HH:mm"
placeholder="请选择报名结束时间">
</el-date-picker>
</div>
</el-form-item>
<!-- 选择线路时间用于控制分工会/校工会在线路选择页可选择、修改、取消选择的时间范围。 -->
<el-form-item label="选择线路时间">
<el-form-item label="选择线路时间" class="config-wide">
<div class="config-time-range">
<el-date-picker
v-model="formData.lineSelectStartTime"
type="datetime"
@@ -79,7 +194,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
format="yyyy-MM-dd HH:mm"
placeholder="请选择选择线路开始时间">
</el-date-picker>
<span style="display: inline-block; margin: 0 10px;">至</span>
<span class="config-time-separator">至</span>
<el-date-picker
v-model="formData.lineSelectEndTime"
type="datetime"
@@ -87,8 +202,10 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
format="yyyy-MM-dd HH:mm"
placeholder="请选择选择线路结束时间">
</el-date-picker>
</div>
</el-form-item>
<div class="config-section-title">报名与出行规则</div>
<el-form-item label="省外最少成团人数(包括家属)" prop="outsideQuota">
<el-input v-model.number="formData.outsideQuota"
placeholder="请输入省外最少成团人数(包括家属)"></el-input>
@@ -132,6 +249,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
v-model.number="formData.modifyNumber"></el-input>
</el-form-item>
<div class="config-section-title">审核规则</div>
<el-form-item label="省内线路是否需要审核" prop="isSnLine">
<el-radio-group v-model="formData.isSnLine">
<el-radio-button :label="true">需要</el-radio-button>
@@ -153,6 +271,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-radio-group>
</el-form-item>
<div class="config-section-title">名额与报名信息</div>
<el-form-item label="全批次最多报名人数" prop="allLineSignUpNumber">
<el-input max="100"
placeholder="请输入全批次最多报名人数"
@@ -181,12 +300,14 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-tab-pane>
<el-tab-pane label="标段管理" name="lotManage">
<el-form-item label="标段">
<el-button type="primary" @click="formData.lots.push({})"
style="float: right;">增加一条
<el-form-item label-width="0">
<div class="config-table-toolbar">
<span>标段列表</span>
<el-button type="primary" size="small" icon="el-icon-plus" @click="formData.lots.push({})">增加一条
</el-button>
</div>
<el-table :data="formData.lots" stripe style="width: 100%">
<el-table-column prop="index" label="序号" width="180">
<el-table-column prop="index" label="序号" width="80">
<template slot-scope="scope">
{{scope.$index+1}}
</template>
@@ -220,7 +341,7 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-tab-pane>
<el-tab-pane label="分工会线路数量管理" name="unionLineNumberManage">
<el-form-item label="分工会线路数量">
<el-form-item label-width="0">
<el-table :data="formData.unionLineNumberConfigs" stripe style="width: 100%">
<el-table-column prop="index" label="序号" width="120">
<template slot-scope="scope">
@@ -265,15 +386,16 @@ layout("/platform/zhgh/staffbenefit/therapyRecuperation/layouts/platform.html"){
</el-tab-pane>
<el-tab-pane label="服务须知" name="serviceNotice">
<el-form-item label="疗休养服务须知" prop="notice">
<div class="config-section-title">疗休养服务须知</div>
<el-form-item prop="notice" label-width="0">
<text-editor v-model="formData.notice"></text-editor>
</el-form-item>
</el-tab-pane>
</el-tabs>
<el-form-item class="item-button">
<el-button type="danger" @click="resetForm">重&emsp;置</el-button>
<el-button type="primary" @click="operation" :loading="subLoading">提&emsp;交
<el-form-item class="config-actions">
<el-button @click="resetForm">重置</el-button>
<el-button type="primary" @click="operation" :loading="subLoading">保存配置
</el-button>
</el-form-item>
</el-form>