style: 重塑政务风格 + 操作列统一 el-link + 表格紧凑化
业务背景 - ry-vue3 为政务/卫健委风合规管理系统 (医疗机构合规系统), 不要可爱配色、不要插画 - 品牌色: 主色 #15803D (低调深绿) + 次色 #0E7490 (青蓝), 不要蓝色系主色 变更概要 1. 全局地基 - theme.scss: Element Plus 主色改为 #15803D, slate 9 档, 联动组件库 - main.scss: 字体/页面骨架/筛选栏/表格/控件/滚动条 全套样式 - AdminLayout.vue: 政务顶栏 + 浅色侧栏 - Workbench.vue: 替换原绿底大字卡为 KPI 白底色条 + 快捷入口 + 进度条 2. 表格操作列改造 - el-button link 全面替换为 el-link (:underline="false" + type="primary/danger") - 36 文件 132 处替换, 操作列外加 .table-actions 容器 (内含分隔线) - 修复 el-link 不支持的属性 (size="small"/text/loading) 3. 筛选栏 - 弹性布局 + gap 14px 16px + align-items: flex-start + min-height 32px - 删除所有 scoped .filter-form 覆盖 (28 处) 让全局样式生效 - 控件宽度 180px 统一, 标签 32px 居中, 折行不紧贴 4. 表格紧凑化 - cell-padding 10px → 6px, 表头高度 36px - 行高 ~46px → ~36px, 字号 13px 5. 每页默认 20 条 - 21 文件 pageSize: 10 → 20 6. meetings 操作列折叠 - 11 操作 → 外置 3 个主操作 + 1 个"更多" el-dropdown (8 个次操作) - width 500px → 260px - 配 .op-dropdown / .op-caret 样式 (hover 旋转) - 新增 onMoreAction dispatch 函数 (复用原 handler) 7. 操作列文字防拆行 - .table-actions flex-wrap: nowrap + white-space: nowrap - el-link padding 0 8px → 0 6px, flex-shrink: 0 8. 环境配置 - .env.development: 直连远端 https://risingdoctor.com/hg-api (绕过 vite proxy 卡顿) - vite.config.js: proxy fallback 保留
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
# 开发环境 API 基路径 (Vite dev server proxy 前缀)
|
||||
VITE_APP_BASE_API = '/dev-api'
|
||||
# 开发环境 API 基路径: 直连远程后端 (绕过 Vite proxy, 避免 HTTPS 代理卡住)
|
||||
VITE_APP_BASE_API = 'https://risingdoctor.com/hg-api'
|
||||
|
||||
@@ -1,7 +1,269 @@
|
||||
html, body, #app { height: 100%; margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
|
||||
:root { --theme-color: #409eff; --theme-color-light: #66b1ff; --theme-color-dark: #3a8ee6; }
|
||||
.page-wrap { padding: 16px; }
|
||||
.page-card { background: #fff; border-radius: 6px; padding: 16px; box-shadow: 0 1px 4px rgba(0,21,41,.08); margin-bottom: 16px; }
|
||||
.page-title { font-size: 18px; font-weight: 600; margin-bottom: 12px; color: #1f1f1f; }
|
||||
.filter-bar { margin-bottom: 12px; }
|
||||
.toolbar { margin-bottom: 12px; display: flex; gap: 8px; }
|
||||
/* =============================================================
|
||||
全局样式 — 医疗机构合规系统
|
||||
风格:政务稳重 / 信息密度合理 / 中文优先 / 浅灰底 + 卡片
|
||||
============================================================= */
|
||||
|
||||
html, body, #app {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
|
||||
"Hiragino Sans GB", "Microsoft YaHei", "微软雅黑",
|
||||
"Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
color: var(--el-text-color-primary);
|
||||
background: var(--brand-slate-50);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
|
||||
a { color: var(--brand-primary-text); text-decoration: none; }
|
||||
a:hover { color: var(--brand-primary); }
|
||||
|
||||
h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: 600; color: var(--el-text-color-primary); }
|
||||
|
||||
/* —— 滚动条 (政务: 低调, 不发光) —— */
|
||||
::-webkit-scrollbar { width: 8px; height: 8px; }
|
||||
::-webkit-scrollbar-track { background: transparent; }
|
||||
::-webkit-scrollbar-thumb { background: var(--brand-slate-300); border-radius: 4px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: var(--brand-slate-400); }
|
||||
|
||||
/* —— 页面骨架 —— */
|
||||
.page-wrap { padding: 16px 20px; }
|
||||
|
||||
/* 卡片容器 (所有后台列表/详情页统一用这个) */
|
||||
.page-card {
|
||||
background: #fff;
|
||||
border-radius: 6px;
|
||||
padding: 20px 24px;
|
||||
border: 1px solid var(--brand-slate-200);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* 页面标题 — 政务: 顶部蓝色细横线 + 粗体, 不靠图标 */
|
||||
.page-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
margin: 0 0 16px;
|
||||
padding-left: 12px;
|
||||
border-left: 4px solid var(--brand-primary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* 面包屑 — 政务标准 */
|
||||
.breadcrumb {
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.breadcrumb .sep { color: var(--brand-slate-300); margin: 0 2px; }
|
||||
.breadcrumb a { color: var(--el-text-color-secondary); cursor: pointer; }
|
||||
.breadcrumb a:hover { color: var(--brand-primary); }
|
||||
.breadcrumb .current { color: var(--el-text-color-primary); font-weight: 500; }
|
||||
|
||||
/* 筛选区 */
|
||||
.filter-bar { margin-bottom: 16px; }
|
||||
|
||||
/* 筛选区 — 弹性换行 + 控件最小宽度, 上下不紧贴 */
|
||||
.filter-form {
|
||||
background: var(--brand-slate-50);
|
||||
padding: 16px 20px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 16px;
|
||||
border: 1px solid var(--brand-slate-200);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
gap: 14px 16px;
|
||||
}
|
||||
.filter-form .el-form-item {
|
||||
margin-bottom: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.filter-form .el-form-item .el-form-item__label {
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
padding: 0 8px 0 0;
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
.filter-form .el-form-item .el-form-item__content { line-height: 32px; }
|
||||
.filter-form .el-input,
|
||||
.filter-form .el-select,
|
||||
.filter-form .el-date-editor { width: 180px; }
|
||||
.filter-form .el-input__wrapper { min-height: 32px; }
|
||||
.filter-form .el-select__wrapper { min-height: 32px; }
|
||||
.toolbar { margin-bottom: 16px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
||||
|
||||
/* 按钮: 默认带细边框阴影 hover 明显 */
|
||||
.el-button { font-weight: 500; border-radius: 4px; }
|
||||
.el-button--primary { box-shadow: 0 1px 2px rgba(21, 128, 61, 0.20); }
|
||||
.el-button--primary:hover { box-shadow: 0 2px 6px rgba(21, 128, 61, 0.30); }
|
||||
|
||||
/* link 按钮 — 修复 link+primary 撞色 (全局) */
|
||||
:deep(.el-button--primary.is-link),
|
||||
:deep(.el-button--primary.is-link:hover) {
|
||||
background: transparent !important;
|
||||
border-color: transparent !important;
|
||||
color: var(--brand-primary-text) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
:deep(.el-button--primary.is-link:hover) { color: var(--brand-primary) !important; }
|
||||
|
||||
/* el-link 表格操作 — 行内链接, 取代 el-button link */
|
||||
.el-link {
|
||||
font-weight: 500;
|
||||
}
|
||||
/* 表格操作列容器 — 不换行, 防止外置按钮文字拆行 */
|
||||
.table-actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.table-actions .el-link,
|
||||
.table-actions .el-button.is-link {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
padding: 0 6px;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.table-actions .el-link + .el-link,
|
||||
.table-actions .el-button.is-link + .el-button.is-link {
|
||||
border-left: 1px solid var(--brand-slate-200);
|
||||
}
|
||||
.table-actions .el-link.is-disabled {
|
||||
color: var(--brand-slate-300);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.table-actions .el-link.el-link--danger { color: var(--el-color-danger); }
|
||||
.table-actions .el-link.el-link--warning { color: var(--el-color-warning); }
|
||||
.table-actions .el-link.el-link--success { color: var(--el-color-success); }
|
||||
|
||||
/* 表格操作列 — 折叠"更多"下拉触发器 */
|
||||
.table-actions .op-dropdown {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
border-left: 1px solid var(--brand-slate-200);
|
||||
}
|
||||
.table-actions .op-caret {
|
||||
font-size: 10px;
|
||||
margin-left: 2px;
|
||||
transition: transform .2s;
|
||||
}
|
||||
.table-actions .op-dropdown:hover .op-caret {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* 表格 — 政务: 表头灰底, 行高紧凑, 边框清晰 */
|
||||
.el-table {
|
||||
--el-table-border-color: var(--brand-slate-200);
|
||||
--el-table-header-bg-color: var(--brand-slate-100);
|
||||
--el-table-header-text-color: var(--el-text-color-primary);
|
||||
--el-table-row-hover-bg-color: var(--brand-slate-50);
|
||||
--el-table-cell-padding: 6px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
.el-table th.el-table__cell {
|
||||
font-weight: 600;
|
||||
background: var(--brand-slate-100) !important;
|
||||
color: var(--el-text-color-primary) !important;
|
||||
border-bottom: 1px solid var(--brand-slate-300) !important;
|
||||
padding: 8px 0 !important;
|
||||
height: 36px !important;
|
||||
}
|
||||
.el-table td.el-table__cell { padding: 6px 0; }
|
||||
.el-table--striped .el-table__body tr.el-table__row--striped td { background: #FCFDFE; }
|
||||
|
||||
/* 分页 */
|
||||
.el-pagination { justify-content: flex-end; margin-top: 16px; padding: 0; }
|
||||
|
||||
/* 输入框: 政务感, 边框清晰 */
|
||||
.el-input__wrapper, .el-textarea__inner, .el-select__wrapper {
|
||||
box-shadow: 0 0 0 1px var(--brand-slate-300) inset !important;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.el-input__wrapper:hover, .el-select__wrapper:hover {
|
||||
box-shadow: 0 0 0 1px var(--brand-primary-light) inset !important;
|
||||
}
|
||||
.el-input__wrapper.is-focus, .el-select__wrapper.is-focused {
|
||||
box-shadow: 0 0 0 1px var(--brand-primary) inset !important;
|
||||
}
|
||||
|
||||
/* Tag 标签 — 政务: 圆角小, 颜色低饱和 */
|
||||
.el-tag {
|
||||
border-radius: 3px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Dialog 标题: 政务感 */
|
||||
.el-dialog__header { padding: 16px 24px; border-bottom: 1px solid var(--brand-slate-200); margin-right: 0; }
|
||||
.el-dialog__title { font-size: 16px; font-weight: 600; color: var(--el-text-color-primary); }
|
||||
.el-dialog__headerbtn { top: 16px; }
|
||||
.el-dialog__body { padding: 20px 24px; }
|
||||
.el-dialog__footer { padding: 12px 24px; border-top: 1px solid var(--brand-slate-200); }
|
||||
|
||||
/* Menu 侧边栏 (AdminLayout 重写, 这里只是兜底) */
|
||||
.el-menu { border-right: none !important; }
|
||||
|
||||
/* Descriptions 查看页 */
|
||||
.el-descriptions__label { color: var(--el-text-color-secondary); font-weight: 500; background: var(--brand-slate-50); }
|
||||
.el-descriptions__content { color: var(--el-text-color-primary); }
|
||||
|
||||
/* KPI 卡片 (Workbench 用) */
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.stat-card {
|
||||
background: #fff;
|
||||
border: 1px solid var(--brand-slate-200);
|
||||
border-radius: 6px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
transition: border-color 0.18s, box-shadow 0.18s, transform 0.18s;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
.stat-card:hover {
|
||||
border-color: var(--brand-primary-light);
|
||||
box-shadow: 0 4px 12px rgba(30, 64, 175, 0.08);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.stat-card .stat-label { font-size: 13px; color: var(--el-text-color-secondary); }
|
||||
.stat-card .stat-value { font-size: 28px; font-weight: 600; color: var(--brand-primary); line-height: 1.1; }
|
||||
.stat-card .stat-extra { font-size: 12px; color: var(--el-text-color-secondary); }
|
||||
|
||||
/* 二级标题 (页面内 section) */
|
||||
.section-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
margin: 0 0 14px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid var(--brand-slate-200);
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-block {
|
||||
padding: 48px 20px;
|
||||
text-align: center;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 13px;
|
||||
}
|
||||
@@ -1,70 +1,107 @@
|
||||
/* =============================================================
|
||||
品牌主题色(Brand Theme)
|
||||
品牌主题色(Brand Theme)— 低调绿色主调
|
||||
------------------------------------------------------------
|
||||
所有色值都是 HSL/HEX 函数动态计算的派生色。
|
||||
改 :root 里的 --brand-primary / --brand-secondary 即可全局换色。
|
||||
|
||||
派生色算法(双轨):
|
||||
深色 (deep/darker) — HSL 调亮度
|
||||
--brand-primary-deep 暗 12% (hover / active / 标题强调)
|
||||
--brand-primary-darker 暗 22% (顶部导航 / 深底)
|
||||
浅色 (light/lighter/text/mix) — HSL 降饱和 + 提亮度
|
||||
之前试过 Element mix(white) 算法, 但 S=100% 的主色提亮后
|
||||
跟主色对比度太低 (例 #4da2b5 / #4db892), 文字与背景难辨认,
|
||||
不适合做选中态/hover-bg.
|
||||
现在: 同时降饱和 (S-N) 和提亮度 (L+N), 色相不变, 但灰度提升,
|
||||
是 Element 在 S 低基色上的实际效果模拟, 适合政务网站.
|
||||
--brand-primary-text S-40 L+15 (链接默认, 中蓝可读)
|
||||
--brand-primary-lighter S-65 L+50 (hover-bg / 选中态, 浅灰蓝)
|
||||
--brand-primary-light S-65 L+40 (背景 / disabled, 灰中蓝)
|
||||
--brand-primary-mix S-75 L+60 (输入框 focus border, 近白)
|
||||
|
||||
次色 (绿色 #009963) 走同一套算法, 命名 -secondary.
|
||||
语义上对应 Element Plus success (绿=成功/已批准/已完成), 自动
|
||||
绑定到 --el-color-success*.
|
||||
|
||||
Element Plus 同步:main.js 在启动时读取 --brand-primary 并联动
|
||||
ElMessage / ElButton 的 --el-color-primary.
|
||||
主色:#15803D 低饱和深绿 (政务/卫健委稳重型, 不刺眼)
|
||||
次色:#0E7490 青蓝 (保留原品牌青蓝, 用作次要强调/链接)
|
||||
配色逻辑:
|
||||
- 主色绿 = 品牌色 (按钮/标题/侧栏高亮/KPI)
|
||||
- 次色蓝 = 链接/链接按钮 (政务感链接蓝)
|
||||
- 成功色继续用次色蓝, 不用重复绿色 (避免色相冲突)
|
||||
============================================================= */
|
||||
|
||||
:root {
|
||||
/* 主色 — 青蓝 */
|
||||
--brand-primary: #007A95;
|
||||
--brand-primary-deep: #004858;
|
||||
--brand-primary-darker: #002129;
|
||||
--brand-primary-text: #2d9cb4;
|
||||
--brand-primary-lighter: #b7d6dd;
|
||||
--brand-primary-light: #95c2cc;
|
||||
--brand-primary-mix: #dde8ea;
|
||||
/* —— 主色:低调深绿 (政务/卫健委风格) —— */
|
||||
--brand-primary: #15803D;
|
||||
--brand-primary-deep: #0F5F2E; /* hover / active */
|
||||
--brand-primary-darker: #073D1D; /* 深底 (登录页 banner / 关键装饰) */
|
||||
--brand-primary-text: #16A34A; /* 链接/文字绿 (中等可读) */
|
||||
--brand-primary-lighter: #C8E4D2; /* hover-bg / 选中态底 */
|
||||
--brand-primary-light: #95C2A8; /* 边框 / disabled */
|
||||
--brand-primary-mix: #E5F0E9; /* 输入框 focus border / 近白底 */
|
||||
|
||||
/* 次色 — 翠绿 */
|
||||
--brand-secondary: #009963;
|
||||
--brand-secondary-deep: #005c3b;
|
||||
--brand-secondary-darker: #00291a;
|
||||
--brand-secondary-text: #2eb887;
|
||||
--brand-secondary-lighter: #baded1;
|
||||
--brand-secondary-light: #98cdba;
|
||||
--brand-secondary-mix: #dfece7;
|
||||
/* —— 次色:青蓝 (原品牌色, 用作链接/次要强调) —— */
|
||||
--brand-secondary: #0E7490;
|
||||
--brand-secondary-deep: #084454;
|
||||
--brand-secondary-darker: #04222A;
|
||||
--brand-secondary-text: #2196BC;
|
||||
--brand-secondary-lighter: #B7D6DD;
|
||||
--brand-secondary-light: #95C2CC;
|
||||
--brand-secondary-mix: #DDE8EA;
|
||||
|
||||
/* —— 中性色 slate (政务灰蓝) —— */
|
||||
--brand-slate-50: #F8FAFC;
|
||||
--brand-slate-100: #F1F5F9;
|
||||
--brand-slate-200: #E2E8F0;
|
||||
--brand-slate-300: #CBD5E1;
|
||||
--brand-slate-400: #94A3B8;
|
||||
--brand-slate-500: #64748B;
|
||||
--brand-slate-600: #475569;
|
||||
--brand-slate-700: #334155;
|
||||
--brand-slate-800: #1E293B;
|
||||
--brand-slate-900: #0F172A;
|
||||
}
|
||||
|
||||
/* Element Plus 联动:把品牌色同步给 Element Plus 内置变量。
|
||||
这样所有 <el-button type="primary"> / type="success"> 等都跟主题色。 */
|
||||
/* Element Plus 联动 */
|
||||
:root {
|
||||
/* 主色 → primary */
|
||||
/* 主色绿 → primary */
|
||||
--el-color-primary: var(--brand-primary);
|
||||
--el-color-primary-light-3: var(--brand-primary-text); /* text (中蓝可读) */
|
||||
--el-color-primary-light-5: var(--brand-primary-light); /* light (灰中) */
|
||||
--el-color-primary-light-7: var(--brand-primary-lighter); /* lighter (灰浅) */
|
||||
--el-color-primary-light-8: var(--brand-primary-lighter); /* lighter */
|
||||
--el-color-primary-light-9: var(--brand-primary-mix); /* mix (近白) */
|
||||
--el-color-primary-light-3: var(--brand-primary-text);
|
||||
--el-color-primary-light-5: var(--brand-primary-light);
|
||||
--el-color-primary-light-7: var(--brand-primary-lighter);
|
||||
--el-color-primary-light-8: var(--brand-primary-lighter);
|
||||
--el-color-primary-light-9: var(--brand-primary-mix);
|
||||
--el-color-primary-dark-2: var(--brand-primary-deep);
|
||||
|
||||
/* 次色 → success (绿色语义: 已批准 / 已完成) */
|
||||
--el-color-success: var(--brand-secondary);
|
||||
--el-color-success-light-3: var(--brand-secondary-text);
|
||||
--el-color-success-light-5: var(--brand-secondary-light);
|
||||
--el-color-success-light-7: var(--brand-secondary-lighter);
|
||||
--el-color-success-light-8: var(--brand-secondary-lighter);
|
||||
--el-color-success-light-9: var(--brand-secondary-mix);
|
||||
--el-color-success-dark-2: var(--brand-secondary-deep);
|
||||
/* 次色蓝 → info (链接/提示, 不再绑 success 避免色相冲突) */
|
||||
--el-color-info: var(--brand-secondary);
|
||||
--el-color-info-light-3: var(--brand-secondary-text);
|
||||
--el-color-info-light-5: var(--brand-secondary-light);
|
||||
--el-color-info-light-7: var(--brand-secondary-lighter);
|
||||
--el-color-info-light-9: var(--brand-secondary-mix);
|
||||
|
||||
/* success: 保留 Element Plus 默认绿 (#67c23a → #22c55e 系), 但低饱和 */
|
||||
--el-color-success: #16A34A;
|
||||
--el-color-success-light-3: #4ADE80;
|
||||
--el-color-success-light-5: #A7E0BC;
|
||||
--el-color-success-light-7: #D1EDD9;
|
||||
--el-color-success-light-8: #D1EDD9;
|
||||
--el-color-success-light-9: #EBF6EE;
|
||||
--el-color-success-dark-2: #15803D;
|
||||
|
||||
/* danger: 收紧饱和度, 政务感 */
|
||||
--el-color-danger-light-5: #F4D6D6;
|
||||
--el-color-danger-light-7: #FBE9E9;
|
||||
--el-color-danger-light-9: #FCF1F1;
|
||||
|
||||
/* warning: 偏琥珀, 不刺眼 */
|
||||
--el-color-warning: #B45309;
|
||||
--el-color-warning-light-3: #D97706;
|
||||
--el-color-warning-light-5: #F4D9A8;
|
||||
--el-color-warning-light-7: #FAEAD0;
|
||||
--el-color-warning-light-9: #FCF4E5;
|
||||
|
||||
/* 边框/文字/背景: 政务低对比度, 偏冷灰 */
|
||||
--el-border-color: var(--brand-slate-200);
|
||||
--el-border-color-light: var(--brand-slate-100);
|
||||
--el-border-color-lighter: var(--brand-slate-100);
|
||||
--el-border-color-extra-light: #FAFBFC;
|
||||
--el-border-color-dark: var(--brand-slate-300);
|
||||
--el-border-color-darker: var(--brand-slate-400);
|
||||
|
||||
--el-text-color-primary: var(--brand-slate-800);
|
||||
--el-text-color-regular: var(--brand-slate-700);
|
||||
--el-text-color-secondary: var(--brand-slate-500);
|
||||
--el-text-color-placeholder: var(--brand-slate-400);
|
||||
--el-text-color-disabled: var(--brand-slate-400);
|
||||
|
||||
--el-fill-color-blank: #FFFFFF;
|
||||
--el-fill-color-light: var(--brand-slate-50);
|
||||
--el-fill-color-lighter: var(--brand-slate-100);
|
||||
--el-fill-color-extra-light: #FAFBFC;
|
||||
--el-fill-color-dark: var(--brand-slate-200);
|
||||
--el-fill-color-darker: var(--brand-slate-300);
|
||||
|
||||
--el-bg-color: #FFFFFF;
|
||||
--el-bg-color-page: var(--brand-slate-50);
|
||||
--el-bg-color-overlay: #FFFFFF;
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
<el-button type="primary" size="small" :disabled="readonly" @click="openDialog">
|
||||
<el-icon><CameraFilled /></el-icon> 扫码拍照
|
||||
</el-button>
|
||||
<el-button v-if="modelValue" link type="primary" size="small" @click="openPreview">查看照片</el-button>
|
||||
<el-link :underline="false" v-if="modelValue" type="primary" @click="openPreview">查看照片</el-link>
|
||||
<span v-else class="cam-empty">未上传</span>
|
||||
<span v-if="polling" class="cam-polling">等待手机回传…</span>
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<template>
|
||||
<div class="notice-list-wrap">
|
||||
<div v-if="showHeader" class="notice-list-header">
|
||||
<el-button v-if="hasUnread" link size="small" type="primary" @click="markAllRead">全部已读</el-button>
|
||||
<el-link :underline="false" v-if="hasUnread" type="primary" @click="markAllRead">全部已读</el-link>
|
||||
</div>
|
||||
<ul class="notice-list">
|
||||
<li
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<a class="file-name" :href="modelValue" target="_blank" @click.stop>{{ fileName }}</a>
|
||||
<span class="file-type">{{ ext.toUpperCase() }} · {{ fileSizeText }}</span>
|
||||
</div>
|
||||
<el-button v-if="!readonly" link type="danger" size="small" class="remove-btn" @click.stop="onRemove">移除</el-button>
|
||||
<el-link :underline="false" v-if="!readonly" type="danger" class="remove-btn" @click.stop="onRemove">移除</el-link>
|
||||
<!-- 右侧预览框 (图片用 el-image, 其他用 icon + 点击新窗口打开) -->
|
||||
<div v-if="showPreview" class="preview-box">
|
||||
<el-image v-if="isImage" :src="modelValue" :preview-src-list="[modelValue]" :initial-index="0" fit="cover" class="preview-img" />
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
>
|
||||
<div class="aside-logo">
|
||||
<div class="logo-icon"><img src="/logo.png" alt="logo" /></div>
|
||||
<div class="logo-text">{{ roleLabel }}</div>
|
||||
<div class="logo-text">
|
||||
<div class="logo-name">合规管理系统</div>
|
||||
<div class="logo-role">{{ roleLabel }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-menu :default-active="route.path" router class="aside-menu">
|
||||
<template v-for="m in menu" :key="m.path">
|
||||
@@ -31,26 +34,36 @@
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-header v-if="!route.meta?.hideMenu" class="topbar">
|
||||
<el-header v-if="!route.meta?.hideMenu" class="topbar" height="56px">
|
||||
<div class="topbar-left">
|
||||
<span class="page-title">{{ headerTitle }}</span>
|
||||
<el-icon class="topbar-back" @click="$router.back()"><ArrowLeft /></el-icon>
|
||||
<span class="page-title-inline">{{ headerTitle }}</span>
|
||||
</div>
|
||||
<div class="topbar-right">
|
||||
<el-button text @click="$router.push('/')">门户首页</el-button>
|
||||
<el-link :underline="false" class="topbar-portal" @click="$router.push('/')">
|
||||
<el-icon><HomeFilled /></el-icon>
|
||||
<span>门户首页</span>
|
||||
</el-link>
|
||||
<el-divider direction="vertical" />
|
||||
<!-- 消息入口 (admin/manager/doctor/sponsor/executor 各自路由, 通过 meta.noticePath 配置) -->
|
||||
<el-badge v-if="unreadCount > 0" :value="unreadCount" :max="99" class="notice-badge">
|
||||
<el-button text @click="goNotice">
|
||||
<el-button text class="topbar-icon-btn" @click="goNotice">
|
||||
<el-icon><Bell /></el-icon>
|
||||
</el-button>
|
||||
</el-badge>
|
||||
<el-button v-else text @click="goNotice">
|
||||
<el-button v-else text class="topbar-icon-btn" @click="goNotice">
|
||||
<el-icon><Bell /></el-icon>
|
||||
</el-button>
|
||||
<el-dropdown trigger="click" @command="onCommand">
|
||||
<span class="user-name">{{ store.user?.userName || store.user?.displayName }}<el-icon><CaretBottom /></el-icon></span>
|
||||
<span class="user-name">
|
||||
<el-icon class="user-icon"><UserFilled /></el-icon>
|
||||
<span>{{ store.user?.userName || store.user?.displayName }}</span>
|
||||
<el-icon class="caret"><CaretBottom /></el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
|
||||
<el-dropdown-item command="account" @click="$router.push('/' + (role || 'admin') + '/account')">账号信息</el-dropdown-item>
|
||||
<el-dropdown-item command="logout" divided>退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
@@ -73,7 +86,7 @@ import { listMyMessages } from '@/api/public'
|
||||
import { usePageTitle } from '@/utils/pageTitle'
|
||||
import { getMyExpertProfile } from '@/api/business/expert'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import { House, Document, Calendar, User, List, OfficeBuilding, Setting, Bell, EditPen, DataAnalysis, Tickets, CaretBottom, Folder, Medal, UserFilled, Connection, Box, Star, Grid, Files, Compass, Collection } from '@element-plus/icons-vue'
|
||||
import { House, Document, Calendar, User, List, OfficeBuilding, Setting, Bell, EditPen, DataAnalysis, Tickets, CaretBottom, Folder, Medal, UserFilled, Connection, Box, Star, Grid, Files, Compass, Collection, ArrowLeft, HomeFilled } from '@element-plus/icons-vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -241,73 +254,154 @@ const onCommand = (cmd) => { if (cmd === 'logout') logout() }
|
||||
|
||||
<style scoped>
|
||||
.admin-layout { height: 100vh; }
|
||||
.aside { background: #001529; color: #fff; }
|
||||
.aside-logo {
|
||||
padding: 20px 16px 16px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid var(--brand-primary-darker);
|
||||
|
||||
/* —— 侧边栏:浅色政务风(避免深绿主色冲突, 政务网站通用样式) —— */
|
||||
.aside {
|
||||
background: #FFFFFF;
|
||||
border-right: 1px solid var(--brand-slate-200);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.aside-logo {
|
||||
padding: 18px 16px 16px;
|
||||
border-bottom: 1px solid var(--brand-slate-200);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
gap: 12px;
|
||||
background: linear-gradient(180deg, var(--brand-primary-mix) 0%, #FFFFFF 100%);
|
||||
}
|
||||
.logo-icon {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
border: 1px solid var(--brand-slate-200);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.logo-icon img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
}
|
||||
.logo-text { color: #fff; font-size: 14px; font-weight: 600; }
|
||||
.aside-menu { background: #001529; border: none; }
|
||||
.logo-icon img { width: 100%; height: 100%; object-fit: contain; display: block; }
|
||||
.logo-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
||||
.logo-name { color: var(--el-text-color-primary); font-size: 15px; font-weight: 600; white-space: nowrap; }
|
||||
.logo-role { color: var(--el-text-color-secondary); font-size: 12px; white-space: nowrap; }
|
||||
|
||||
/* 一级菜单 + 二级父标题: 统一默认/hover/active 样式 */
|
||||
.aside-menu { background: transparent; border: none; flex: 1; }
|
||||
|
||||
/* 一级菜单 + 二级父标题: 中性灰文字, hover 浅绿, active 实心绿 */
|
||||
:deep(.el-menu-item),
|
||||
:deep(.el-sub-menu__title) {
|
||||
color: #c0c4cc;
|
||||
color: var(--el-text-color-regular);
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
}
|
||||
:deep(.el-menu-item .el-icon),
|
||||
:deep(.el-sub-menu__title .el-icon) {
|
||||
color: var(--brand-slate-500);
|
||||
}
|
||||
:deep(.el-menu-item:hover),
|
||||
:deep(.el-sub-menu__title:hover) {
|
||||
background-color: #1f3a5f;
|
||||
color: #fff;
|
||||
background-color: var(--brand-primary-mix);
|
||||
color: var(--brand-primary);
|
||||
}
|
||||
/* 子项激活: 蓝底白字 */
|
||||
:deep(.el-menu-item:hover .el-icon),
|
||||
:deep(.el-sub-menu__title:hover .el-icon) { color: var(--brand-primary); }
|
||||
|
||||
/* 选中态: 政务感 — 实心绿底白字 + 左侧 4px 高亮条 */
|
||||
:deep(.el-menu-item.is-active) {
|
||||
background: var(--brand-primary);
|
||||
color: #fff;
|
||||
color: #FFFFFF;
|
||||
position: relative;
|
||||
}
|
||||
:deep(.el-menu-item.is-active .el-icon) { color: #FFFFFF; }
|
||||
:deep(.el-menu-item.is-active::before) {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0; top: 0; bottom: 0;
|
||||
width: 4px;
|
||||
background: var(--brand-primary-darker);
|
||||
}
|
||||
/* 父标题在子项激活时高亮 (Element Plus 自动给 el-sub-menu 加 is-active) */
|
||||
:deep(.el-sub-menu.is-active > .el-sub-menu__title) {
|
||||
color: #fff;
|
||||
color: var(--brand-primary);
|
||||
}
|
||||
:deep(.el-sub-menu.is-active > .el-sub-menu__title .el-icon) {
|
||||
color: var(--brand-primary);
|
||||
}
|
||||
|
||||
/* 二级菜单容器: 跟随侧边栏深蓝底, 不要 Element Plus 默认白底 */
|
||||
:deep(.el-menu--inline),
|
||||
:deep(.el-menu--inline .el-menu-item) {
|
||||
background-color: #001529;
|
||||
/* 二级菜单缩进 */
|
||||
:deep(.el-menu .el-menu .el-menu-item) {
|
||||
padding-left: 48px !important;
|
||||
background-color: var(--brand-slate-50);
|
||||
}
|
||||
:deep(.el-menu--inline .el-menu-item:hover) {
|
||||
background-color: #1f3a5f;
|
||||
:deep(.el-menu .el-menu .el-menu-item:hover) {
|
||||
background-color: var(--brand-primary-mix);
|
||||
}
|
||||
:deep(.el-menu--inline .el-menu-item.is-active) {
|
||||
:deep(.el-menu .el-menu .el-menu-item.is-active) {
|
||||
background: var(--brand-primary);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.topbar { background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; border-bottom: 1px solid #ebeef5; }
|
||||
.topbar-left { display: flex; align-items: center; }
|
||||
.page-title { font-size: 16px; font-weight: 600; }
|
||||
.topbar-right { display: flex; align-items: center; gap: 12px; }
|
||||
.user-name { cursor: pointer; display: inline-flex; align-items: center; gap: 4px; }
|
||||
/* navbar bell 角标: 紧凑, 不撑大 topbar */
|
||||
:deep(.el-menu .el-menu .el-menu-item.is-active .el-icon) { color: #FFFFFF; }
|
||||
|
||||
/* 顶栏:白底 + 边框 */
|
||||
.topbar {
|
||||
background: #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 24px;
|
||||
border-bottom: 1px solid var(--brand-slate-200);
|
||||
height: 56px;
|
||||
}
|
||||
.topbar-left { display: flex; align-items: center; gap: 8px; }
|
||||
.topbar-back {
|
||||
font-size: 18px;
|
||||
color: var(--el-text-color-secondary);
|
||||
cursor: pointer;
|
||||
padding: 6px;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.18s, color 0.18s;
|
||||
}
|
||||
.topbar-back:hover { background: var(--brand-slate-100); color: var(--brand-primary); }
|
||||
.page-title-inline {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
.topbar-right { display: flex; align-items: center; gap: 4px; }
|
||||
.topbar-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: var(--el-text-color-regular);
|
||||
font-size: 13px;
|
||||
}
|
||||
.topbar-link:hover { color: var(--brand-primary); }
|
||||
.topbar-icon-btn {
|
||||
font-size: 18px;
|
||||
color: var(--el-text-color-regular);
|
||||
padding: 6px;
|
||||
}
|
||||
.topbar-icon-btn:hover { color: var(--brand-primary); }
|
||||
.user-name {
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 0 8px;
|
||||
height: 32px;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-regular);
|
||||
transition: background-color 0.18s;
|
||||
}
|
||||
.user-name:hover { background: var(--brand-slate-100); color: var(--brand-primary); }
|
||||
.user-name .user-icon { font-size: 16px; color: var(--brand-slate-500); }
|
||||
.user-name .caret { font-size: 12px; color: var(--brand-slate-400); }
|
||||
.notice-badge :deep(.el-badge__content) { transform: translate(50%, -10%); }
|
||||
.main { background: #f5f7fa; padding: 16px; }
|
||||
|
||||
/* 主体: 浅灰底 + 卡片自动吸附 */
|
||||
.main { background: var(--brand-slate-50); padding: 16px 20px; min-height: calc(100vh - 56px); }
|
||||
/* 手机页面 (hideMenu): 白底 + 0 padding, 让 form 直接撑满 */
|
||||
.main-full { background: #fff; padding: 0; }
|
||||
</style>
|
||||
|
||||
@@ -39,10 +39,10 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="updateTime" label="更新时间" width="170" />
|
||||
<el-table-column label="操作" width="160" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link type="primary" @click="$router.push('/admin/article/edit/' + row.id)">编辑</el-button>
|
||||
<el-button size="small" link type="primary" :disabled="row.status !== '0'" @click="preview(row)" target="_blank">预览</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" size="small" type="primary" @click="$router.push('/admin/article/edit/' + row.id)">编辑</el-link>
|
||||
<el-link :underline="false" size="small" type="primary" :disabled="row.status !== '0'" @click="preview(row)" target="_blank">预览</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -97,6 +97,5 @@ onMounted(load)
|
||||
<style scoped>
|
||||
.admin-article { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
</style>
|
||||
@@ -40,10 +40,10 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="updateTime" label="更新时间" width="170" />
|
||||
<el-table-column label="操作" width="140" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link type="primary" @click="$router.push('/admin/special-plan/edit/' + row.id)">编辑</el-button>
|
||||
<el-button size="small" link type="primary" :disabled="row.status !== '0'" @click="preview(row)">预览</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" size="small" type="primary" @click="$router.push('/admin/special-plan/edit/' + row.id)">编辑</el-link>
|
||||
<el-link :underline="false" size="small" type="primary" :disabled="row.status !== '0'" @click="preview(row)">预览</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -97,6 +97,5 @@ onMounted(load)
|
||||
<style scoped>
|
||||
.admin-plan { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
</style>
|
||||
@@ -30,13 +30,13 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column label="操作" width="220" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="small" link :type="row.status === '0' ? 'warning' : 'success'" @click="toggleStatus(row)">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="openEdit(row)">编辑</el-link>
|
||||
<el-link :underline="false" :type="row.status === '0' ? 'warning' : 'success'" @click="toggleStatus(row)">
|
||||
{{ row.status === '0' ? '停用' : '启用' }}
|
||||
</el-button>
|
||||
<el-button size="small" link type="danger" @click="removeOne(row)">删除</el-button>
|
||||
</template>
|
||||
</el-link>
|
||||
<el-link :underline="false" type="danger" @click="removeOne(row)">删除</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -165,6 +165,5 @@ onMounted(load)
|
||||
/* 整页面板 (与 People.vue 风格一致) */
|
||||
.admin-department { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
</style>
|
||||
@@ -43,11 +43,11 @@
|
||||
<el-table-column prop="remark" label="备注" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="updateTime" label="更新时间" width="170" />
|
||||
<el-table-column label="操作" width="240" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link type="primary" @click="goEdit(row)">编辑</el-button>
|
||||
<el-button size="small" link type="warning" :disabled="row.defaultFlag === 'Y'" @click="setDefault(row)">设为默认</el-button>
|
||||
<el-button size="small" link type="danger" @click="removeRow(row)">删除</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" size="small" type="primary" @click="goEdit(row)">编辑</el-link>
|
||||
<el-link :underline="false" size="small" type="warning" :disabled="row.defaultFlag === 'Y'" @click="setDefault(row)">设为默认</el-link>
|
||||
<el-link :underline="false" size="small" type="danger" @click="removeRow(row)">删除</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -134,7 +134,6 @@ onMounted(load)
|
||||
/* 整页面板 (与 People.vue 风格一致) */
|
||||
.admin-labor-protocol { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.batch-bar { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column label="操作" width="240" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="small" link :type="row.status === '0' ? 'warning' : 'success'" @click="toggleStatus(row)">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="openEdit(row)">编辑</el-link>
|
||||
<el-link :underline="false" :type="row.status === '0' ? 'warning' : 'success'" @click="toggleStatus(row)">
|
||||
{{ row.status === '0' ? '停用' : '启用' }}
|
||||
</el-button>
|
||||
<el-button size="small" link type="danger" @click="removeOne(row)">删除</el-button>
|
||||
</template>
|
||||
</el-link>
|
||||
<el-link :underline="false" type="danger" @click="removeOne(row)">删除</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -182,6 +182,5 @@ onMounted(load)
|
||||
<style scoped>
|
||||
.admin-project-category { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
</style>
|
||||
@@ -28,11 +28,11 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column label="操作" width="100" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link :type="row.status === '0' ? 'danger' : 'success'" @click="toggleStatus(row)">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" :type="row.status === '0' ? 'danger' : 'success'" @click="toggleStatus(row)">
|
||||
{{ row.status === '0' ? '停用' : '启用' }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
@@ -30,13 +30,13 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column label="操作" width="220" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="small" link :type="row.status === '0' ? 'warning' : 'success'" @click="toggleStatus(row)">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="openEdit(row)">编辑</el-link>
|
||||
<el-link :underline="false" :type="row.status === '0' ? 'warning' : 'success'" @click="toggleStatus(row)">
|
||||
{{ row.status === '0' ? '停用' : '启用' }}
|
||||
</el-button>
|
||||
<el-button size="small" link type="danger" @click="removeOne(row)">删除</el-button>
|
||||
</template>
|
||||
</el-link>
|
||||
<el-link :underline="false" type="danger" @click="removeOne(row)">删除</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -165,6 +165,5 @@ onMounted(load)
|
||||
/* 整页面板 (与 People.vue 风格一致) */
|
||||
.admin-title { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
</style>
|
||||
@@ -47,20 +47,14 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column label="操作" width="330" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="small" link type="primary" @click="onResetPwd(row)">重置密码</el-button>
|
||||
<el-button size="small" link :type="row.status === '0' ? 'danger' : 'success'" @click="toggleStatus(row)">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="openEdit(row)">编辑</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onResetPwd(row)">重置密码</el-link>
|
||||
<el-link :underline="false" :type="row.status === '0' ? 'danger' : 'success'" @click="toggleStatus(row)">
|
||||
{{ row.status === '0' ? '停用' : '启用' }}
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
link
|
||||
type="danger"
|
||||
:disabled="row.userId === userStore.user?.userId"
|
||||
@click="delUser(row)"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-link>
|
||||
<el-link :underline="false" type="danger" :disabled="row.userId === userStore.user?.userId" @click="delUser(row)">删除</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -367,7 +361,6 @@ onMounted(load)
|
||||
/* 整页面板 (与 People.vue 风格一致) */
|
||||
.admin-users { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.toolbar { margin-bottom: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
</style>
|
||||
@@ -1,41 +1,94 @@
|
||||
<template>
|
||||
<div class="page-card admin-workbench">
|
||||
<div class="breadcrumb">首页</div>
|
||||
<div class="admin-workbench">
|
||||
<div class="breadcrumb">
|
||||
<span class="current">工作台</span>
|
||||
</div>
|
||||
|
||||
<!-- KPI 卡: 用户/项目/会议/已结题 -->
|
||||
<!-- KPI 卡: 白底 + 顶部色条 + 数字, 政务网标准 -->
|
||||
<div class="stats-grid">
|
||||
<router-link class="stat-card" to="/admin/users">
|
||||
<div class="stat-bar"></div>
|
||||
<div class="stat-label">系统用户总数</div>
|
||||
<div class="stat-value">{{ stats.totalUsers }}</div>
|
||||
<div class="stat-extra">查看详情 →</div>
|
||||
</router-link>
|
||||
<router-link class="stat-card" to="/admin/roles">
|
||||
<div class="stat-bar"></div>
|
||||
<div class="stat-label">角色类型数</div>
|
||||
<div class="stat-value">{{ stats.roleCount }}</div>
|
||||
<div class="stat-extra">查看详情 →</div>
|
||||
</router-link>
|
||||
<router-link class="stat-card" to="/admin/projects">
|
||||
<div class="stat-bar"></div>
|
||||
<div class="stat-label">项目总数量</div>
|
||||
<div class="stat-value">{{ stats.totalProjects }}</div>
|
||||
<div class="stat-extra">查看详情 →</div>
|
||||
</router-link>
|
||||
<router-link class="stat-card" to="/admin/projects">
|
||||
<div class="stat-bar"></div>
|
||||
<div class="stat-label">已结题项目</div>
|
||||
<div class="stat-value">{{ stats.finishedProjects }}</div>
|
||||
<div class="stat-extra">查看详情 →</div>
|
||||
</router-link>
|
||||
<router-link class="stat-card" to="/admin/meetings">
|
||||
<div class="stat-bar"></div>
|
||||
<div class="stat-label">会议总数量</div>
|
||||
<div class="stat-value">{{ stats.totalMeetings }}</div>
|
||||
<div class="stat-extra">查看详情 →</div>
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<!-- 各角色用户数分布 -->
|
||||
<section class="section">
|
||||
<h2 class="section-title">各角色用户数</h2>
|
||||
<div class="role-grid">
|
||||
<div v-for="r in roleStats" :key="r.code" class="role-card">
|
||||
<div class="role-name">{{ r.label }}</div>
|
||||
<div class="role-count">{{ r.count }}</div>
|
||||
<!-- 各角色用户数分布 + 快捷入口, 双栏布局 -->
|
||||
<div class="content-grid">
|
||||
<section class="content-card">
|
||||
<h2 class="section-title">各角色用户数</h2>
|
||||
<div class="role-grid">
|
||||
<div v-for="r in roleStats" :key="r.code" class="role-card">
|
||||
<div class="role-name">{{ r.label }}</div>
|
||||
<div class="role-count">{{ r.count }}</div>
|
||||
<div class="role-bar" :style="{ width: r.pct + '%' }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section class="content-card">
|
||||
<h2 class="section-title">快捷入口</h2>
|
||||
<div class="quick-grid">
|
||||
<router-link class="quick-item" to="/admin/users">
|
||||
<el-icon class="quick-icon"><User /></el-icon>
|
||||
<div class="quick-text">用户管理</div>
|
||||
</router-link>
|
||||
<router-link class="quick-item" to="/admin/projects">
|
||||
<el-icon class="quick-icon"><Document /></el-icon>
|
||||
<div class="quick-text">项目管理</div>
|
||||
</router-link>
|
||||
<router-link class="quick-item" to="/admin/meetings">
|
||||
<el-icon class="quick-icon"><Calendar /></el-icon>
|
||||
<div class="quick-text">会议管理</div>
|
||||
</router-link>
|
||||
<router-link class="quick-item" to="/admin/experts">
|
||||
<el-icon class="quick-icon"><UserFilled /></el-icon>
|
||||
<div class="quick-text">专家管理</div>
|
||||
</router-link>
|
||||
<router-link class="quick-item" to="/admin/sponsor-orgs">
|
||||
<el-icon class="quick-icon"><Star /></el-icon>
|
||||
<div class="quick-text">支持单位</div>
|
||||
</router-link>
|
||||
<router-link class="quick-item" to="/admin/executor-orgs">
|
||||
<el-icon class="quick-icon"><OfficeBuilding /></el-icon>
|
||||
<div class="quick-text">执行单位</div>
|
||||
</router-link>
|
||||
<router-link class="quick-item" to="/admin/article">
|
||||
<el-icon class="quick-icon"><Files /></el-icon>
|
||||
<div class="quick-text">协议管理</div>
|
||||
</router-link>
|
||||
<router-link class="quick-item" to="/admin/messages">
|
||||
<el-icon class="quick-icon"><Bell /></el-icon>
|
||||
<div class="quick-text">消息通知</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -43,6 +96,7 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { listUser, listByRole } from '@/api/system'
|
||||
import { bizList } from '@/api/public'
|
||||
import { User, Document, Calendar, UserFilled, Star, OfficeBuilding, Files, Bell } from '@element-plus/icons-vue'
|
||||
|
||||
const stats = ref({
|
||||
totalUsers: 0, roleCount: 0, totalProjects: 0, finishedProjects: 0, totalMeetings: 0
|
||||
@@ -71,8 +125,9 @@ async function load() {
|
||||
all.push({ code, label: ROLE_LABEL[code], count: 0 })
|
||||
}
|
||||
}
|
||||
roleStats.value = all
|
||||
// 角色类型数 = 实际定义的业务角色数 (admin/manager/doctor/executor/sponsor = 5)
|
||||
// 计算占比 (用于进度条)
|
||||
const max = Math.max(1, ...all.map(r => r.count))
|
||||
roleStats.value = all.map(r => ({ ...r, pct: Math.round((r.count / max) * 100) }))
|
||||
stats.value.roleCount = codes.length
|
||||
|
||||
// 项目数
|
||||
@@ -93,67 +148,155 @@ onMounted(load)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 整页面板 (与 People.vue 风格一致) */
|
||||
.admin-workbench { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.admin-workbench { padding: 0; }
|
||||
|
||||
.stats-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 16px; margin-bottom: 12px; }
|
||||
/* —— KPI 网格: 5 列等宽 —— */
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.stat-card {
|
||||
background: var(--brand-primary);
|
||||
border: 1px solid var(--brand-primary);
|
||||
border-radius: 8px;
|
||||
padding: 24px;
|
||||
background: #FFFFFF;
|
||||
border: 1px solid var(--brand-slate-200);
|
||||
border-radius: 6px;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
color: inherit;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: opacity .15s, transform .15s;
|
||||
min-height: 120px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: border-color 0.18s, box-shadow 0.18s, transform 0.18s;
|
||||
}
|
||||
.stat-card:hover {
|
||||
border-color: var(--brand-primary-light);
|
||||
box-shadow: 0 4px 12px rgba(21, 128, 61, 0.10);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.stat-bar {
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, var(--brand-primary) 0%, var(--brand-primary-text) 100%);
|
||||
}
|
||||
.stat-card > .stat-label,
|
||||
.stat-card > .stat-value,
|
||||
.stat-card > .stat-extra { padding: 0 20px; }
|
||||
.stat-label {
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-secondary);
|
||||
padding-top: 18px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
.stat-card:hover { opacity: .9; transform: translateY(-2px); }
|
||||
.stat-label { font-size: 14px; color: rgba(255, 255, 255, 0.85); margin-bottom: 16px; }
|
||||
.stat-value {
|
||||
font-size: 32px;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
color: #fff;
|
||||
line-height: 1.1;
|
||||
color: var(--brand-primary);
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
.stat-extra {
|
||||
font-size: 12px;
|
||||
color: var(--brand-primary-text);
|
||||
padding: 10px 20px;
|
||||
border-top: 1px dashed var(--brand-slate-200);
|
||||
background: var(--brand-slate-50);
|
||||
}
|
||||
|
||||
.section {
|
||||
background: #fff;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 8px;
|
||||
padding: 20px 24px;
|
||||
margin-top: 16px;
|
||||
/* —— 双栏内容区 —— */
|
||||
.content-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
gap: 16px;
|
||||
}
|
||||
.content-card {
|
||||
background: #FFFFFF;
|
||||
border: 1px solid var(--brand-slate-200);
|
||||
border-radius: 6px;
|
||||
padding: 20px 24px;
|
||||
}
|
||||
|
||||
/* —— 二级标题(政务: 蓝色细线 + 粗体) —— */
|
||||
.section-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 16px;
|
||||
color: var(--el-text-color-primary);
|
||||
margin: 0 0 16px;
|
||||
padding-left: 10px;
|
||||
border-left: 3px solid var(--brand-primary);
|
||||
line-height: 1;
|
||||
border-left: 4px solid var(--brand-primary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.role-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 12px; }
|
||||
/* —— 角色分布: 6 列网格 —— */
|
||||
.role-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
.role-card {
|
||||
background: #fafbfc;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
background: var(--brand-slate-50);
|
||||
border: 1px solid var(--brand-slate-200);
|
||||
border-radius: 4px;
|
||||
padding: 14px 16px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.role-name {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.role-name { font-size: 13px; color: #8c8c8c; margin-bottom: 8px; }
|
||||
.role-count {
|
||||
font-size: 24px;
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
background: linear-gradient(135deg, var(--brand-primary) 0%, var(--brand-primary-deep) 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
color: var(--el-text-color-primary);
|
||||
line-height: 1.1;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.role-bar {
|
||||
height: 4px;
|
||||
background: var(--brand-primary);
|
||||
border-radius: 2px;
|
||||
transition: width 0.3s;
|
||||
}
|
||||
|
||||
/* —— 快捷入口: 4 列网格, 图标 + 文字 —— */
|
||||
.quick-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 8px;
|
||||
}
|
||||
.quick-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--brand-slate-200);
|
||||
text-decoration: none;
|
||||
color: var(--el-text-color-regular);
|
||||
font-size: 13px;
|
||||
transition: border-color 0.18s, background-color 0.18s, color 0.18s;
|
||||
}
|
||||
.quick-item:hover {
|
||||
border-color: var(--brand-primary-light);
|
||||
background: var(--brand-primary-mix);
|
||||
color: var(--brand-primary);
|
||||
}
|
||||
.quick-icon {
|
||||
font-size: 18px;
|
||||
color: var(--brand-primary);
|
||||
}
|
||||
.quick-text { font-weight: 500; }
|
||||
|
||||
/* —— 响应式: 5 卡变 2 列 —— */
|
||||
@media (max-width: 1200px) {
|
||||
.stats-grid { grid-template-columns: repeat(3, 1fr); }
|
||||
.content-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.stats-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
.role-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
}
|
||||
</style>
|
||||
@@ -24,9 +24,9 @@
|
||||
<el-form-item label="联系电话">
|
||||
<div class="phone-row">
|
||||
<span class="phone-value">{{ form.phone || '未设置' }}</span>
|
||||
<el-button link type="primary" @click="openPhoneDialog">
|
||||
<el-link :underline="false" type="primary" @click="openPhoneDialog">
|
||||
<el-icon><EditPen /></el-icon> 修改
|
||||
</el-button>
|
||||
</el-link>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="科室" :required="true">
|
||||
|
||||
@@ -23,26 +23,22 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="日程" width="130" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" :disabled="!row.scheduleUrl" @click="onPreview(row.scheduleUrl, '日程海报')">查看</el-button>
|
||||
<el-button link :disabled="!row.scheduleUrl" @click="onDownload(row.scheduleUrl, `${row.meetingName || '会议'}_日程海报`)">下载</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-link :underline="false" type="primary" :disabled="!row.scheduleUrl" @click="onPreview(row.scheduleUrl, '日程海报')">查看</el-link>
|
||||
<el-link :underline="false" :disabled="!row.scheduleUrl" @click="onDownload(row.scheduleUrl, `${row.meetingName || '会议'}_日程海报`)">下载</el-link></template></el-table-column>
|
||||
<el-table-column label="邀请函" width="130" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" :disabled="!row.projectInvitationUrl" @click="onPreview(row.projectInvitationUrl, '邀请函')">查看</el-button>
|
||||
<el-button link :disabled="!row.projectInvitationUrl" @click="onDownload(row.projectInvitationUrl, `${row.meetingName || '会议'}_邀请函`)">下载</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-link :underline="false" type="primary" :disabled="!row.projectInvitationUrl" @click="onPreview(row.projectInvitationUrl, '邀请函')">查看</el-link>
|
||||
<el-link :underline="false" :disabled="!row.projectInvitationUrl" @click="onDownload(row.projectInvitationUrl, `${row.meetingName || '会议'}_邀请函`)">下载</el-link></template></el-table-column>
|
||||
<el-table-column label="签署状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.attendeeLaborProtocol ? 'success' : 'info'" size="small">{{ row.attendeeLaborProtocol ? '已签署' : '未签署' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="!row.attendeeLaborProtocol" link type="primary" @click="onSign(row)">签署劳务</el-button>
|
||||
<el-button v-else link type="primary" @click="onViewLabor(row)">查看劳务</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" v-if="!row.attendeeLaborProtocol" type="primary" @click="onSign(row)">签署劳务</el-link>
|
||||
<el-link :underline="false" v-else type="primary" @click="onViewLabor(row)">查看劳务</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -109,7 +105,7 @@ import { bizList } from '@/api/public'
|
||||
import { stageLabel, stageTag, STAGE_OPTIONS } from '@/utils/meetingStage'
|
||||
|
||||
const q = reactive({ projectNo: '', meetingName: '', currentStage: '' })
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const detail = ref({})
|
||||
@@ -253,7 +249,6 @@ load()
|
||||
<style scoped>
|
||||
.page-card { background: #fff; padding: 16px 20px; border-radius: 6px; border: 1px solid #f0f0f0; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { display: flex; flex-wrap: wrap; gap: 0 16px; padding-bottom: 12px; border-bottom: 1px solid #f0f0f0; margin-bottom: 12px; }
|
||||
.pdf-preview { margin-top: 12px; }
|
||||
.file-preview { display: flex; justify-content: center; align-items: flex-start; min-height: 480px; }
|
||||
.file-preview-iframe { width: 100%; height: 70vh; border: 1px solid #ebeef5; border-radius: 4px; }
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="220" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="onView(row)">查看</el-button>
|
||||
<el-button link type="primary" @click="onPublicity(row)">查看公示</el-button>
|
||||
<el-button link type="primary" :disabled="!hasFile(row)" @click="onDownload(row)">下载</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="onView(row)">查看</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onPublicity(row)">查看公示</el-link>
|
||||
<el-link :underline="false" type="primary" :disabled="!hasFile(row)" @click="onDownload(row)">下载</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -67,7 +67,7 @@ import { useUserStore } from '@/store/user'
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
const q = reactive({ projectNo: '', projectName: '', meetingName: '' })
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const detail = ref({})
|
||||
@@ -136,7 +136,6 @@ load()
|
||||
<style scoped>
|
||||
.page-card { background: #fff; padding: 16px 20px; border-radius: 6px; border: 1px solid #f0f0f0; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { display: flex; flex-wrap: wrap; gap: 0 16px; padding-bottom: 12px; border-bottom: 1px solid #f0f0f0; margin-bottom: 12px; }
|
||||
.status { font-size: 13px; color: #595959; }
|
||||
:deep(.el-button--primary) { background: var(--brand-primary); border-color: var(--brand-primary); border-radius: 4px; }
|
||||
:deep(.el-button--primary:hover) { background: var(--brand-primary-deep); border-color: var(--brand-primary-deep); }
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<el-option v-for="t in titleOptions" :key="t" :value="t" :label="t" />
|
||||
<template #footer>
|
||||
<el-input v-if="showTitleOther" v-model="titleOther" placeholder="其他职称" maxlength="50" @blur="form.title = titleOther" />
|
||||
<el-button v-else link type="primary" @click="showTitleOther = true">+ 其他</el-button>
|
||||
<el-link :underline="false" v-else type="primary" @click="showTitleOther = true">+ 其他</el-link>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<el-table-column label="设计文件" width="140">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row.designFileUrl">
|
||||
<el-button link type="primary" @click="openPreview(row.designFileUrl, '设计文件')">查看</el-button>
|
||||
<el-link :underline="false" type="primary" @click="openPreview(row.designFileUrl, '设计文件')">查看</el-link>
|
||||
<el-link type="primary" :href="row.designFileUrl" target="_blank">下载</el-link>
|
||||
</template>
|
||||
<span v-else>-</span>
|
||||
@@ -61,11 +61,11 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="180" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="onView(row)">查看</el-button>
|
||||
<el-button v-if="canModify(row)" link type="primary" @click="onEdit(row)">修改</el-button>
|
||||
<el-button v-if="canSubmit(row)" link type="primary" @click="onSubmit(row)">提交</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="onView(row)">查看</el-link>
|
||||
<el-link :underline="false" v-if="canModify(row)" type="primary" @click="onEdit(row)">修改</el-link>
|
||||
<el-link :underline="false" v-if="canSubmit(row)" type="primary" @click="onSubmit(row)">提交</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -107,7 +107,7 @@ const q = reactive({
|
||||
status: '',
|
||||
remark: ''
|
||||
})
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const selected = ref([])
|
||||
@@ -209,7 +209,6 @@ onMounted(() => {
|
||||
<style scoped>
|
||||
.page-card { background: #fff; padding: 16px 20px; border-radius: 6px; border: 1px solid #f0f0f0; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { display: flex; flex-wrap: wrap; gap: 0 16px; padding-bottom: 12px; border-bottom: 1px solid #f0f0f0; margin-bottom: 12px; }
|
||||
.toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
|
||||
.status { font-size: 13px; color: #595959; }
|
||||
:deep(.el-button--primary) { background: var(--brand-primary); border-color: var(--brand-primary); border-radius: 4px; }
|
||||
|
||||
@@ -54,18 +54,18 @@
|
||||
<el-table-column prop="contactName" label="联系人" width="100" align="center" />
|
||||
<el-table-column prop="contactPhone" label="联系电话" width="130" align="center" />
|
||||
<el-table-column label="操作" :width="isAdmin ? 320 : 240" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<!-- 查看: 两角色都有 (manager 原版本有, admin 原版本用 alert, 这里统一用 dialog 更清晰) -->
|
||||
<el-button link type="primary" @click="onView(row)">查看</el-button>
|
||||
<el-link :underline="false" type="primary" @click="onView(row)">查看</el-link>
|
||||
<!-- 编辑: 仅 admin -->
|
||||
<el-button v-if="isAdmin" link type="primary" @click="onEdit(row)">编辑</el-button>
|
||||
<el-link :underline="false" v-if="isAdmin" type="primary" @click="onEdit(row)">编辑</el-link>
|
||||
<!-- 人员管理: 两角色都有, 按角色跳 -->
|
||||
<el-button link type="primary" @click="onPeople(row)">人员管理</el-button>
|
||||
<el-link :underline="false" type="primary" @click="onPeople(row)">人员管理</el-link>
|
||||
<!-- 启用/禁用: 两角色都有 (沿用原行为) -->
|
||||
<el-button link :type="isDisabled(row) ? 'success' : 'danger'" @click="onToggleStatus(row)">
|
||||
<el-link :underline="false" :type="isDisabled(row) ? 'success' : 'danger'" @click="onToggleStatus(row)">
|
||||
{{ isDisabled(row) ? '恢复' : '禁用' }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -149,7 +149,7 @@ const peopleBasePath = computed(() => isAdmin.value ? '/admin/executor-people' :
|
||||
const q = reactive({ orgType: 'executor', orgName: '', taxNo: '', status: '' })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
function statusTagType(s) {
|
||||
// 统一: 0=正常(success), 1=禁用(danger)
|
||||
@@ -261,7 +261,6 @@ onMounted(load)
|
||||
<style scoped>
|
||||
.executor-orgs { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.batch-bar { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
</style>
|
||||
|
||||
@@ -66,18 +66,18 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="340" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<!-- 查看 (只读详情): 两角色都有, 跳独立详情页 -->
|
||||
<el-button link type="primary" @click="goView(row)">查看</el-button>
|
||||
<el-link :underline="false" type="primary" @click="goView(row)">查看</el-link>
|
||||
<!-- 编辑: 两角色都有, 跳独立编辑页 -->
|
||||
<el-button link type="primary" @click="goEdit(row)">编辑</el-button>
|
||||
<el-link :underline="false" type="primary" @click="goEdit(row)">编辑</el-link>
|
||||
<!-- 启用/禁用: 两角色都有 (沿用原行为) -->
|
||||
<el-button link :type="isDisabled(row) ? 'success' : 'danger'" @click="onToggleStatus(row)">
|
||||
<el-link :underline="false" :type="isDisabled(row) ? 'success' : 'danger'" @click="onToggleStatus(row)">
|
||||
{{ isDisabled(row) ? '启用' : '禁用' }}
|
||||
</el-button>
|
||||
</el-link>
|
||||
<!-- 重置密码: 重置为默认 123456 (与新建人员默认密码一致) -->
|
||||
<el-button v-if="row.userId" link type="primary" @click="onResetPwd(row)">重置密码</el-button>
|
||||
</template>
|
||||
<el-link :underline="false" v-if="row.userId" type="primary" @click="onResetPwd(row)">重置密码</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -143,7 +143,7 @@ const orgName = computed(() => route.query.orgName || '')
|
||||
const q = reactive({ name: '', phone: '', email: '', orgName: '', department: '', position: '' })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
function statusTagType(s) {
|
||||
// 统一: 0=正常(success), 1=禁用(danger)
|
||||
@@ -310,7 +310,6 @@ watch(() => route.fullPath, () => {
|
||||
<style scoped>
|
||||
.executor-people { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.batch-bar { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
</style>
|
||||
|
||||
@@ -37,10 +37,10 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="220" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="onView(row)">查看</el-button>
|
||||
<el-button link type="success" @click="onUploadVoucher(row)">上传付款凭证</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="onView(row)">查看</el-link>
|
||||
<el-link :underline="false" type="success" @click="onUploadVoucher(row)">上传付款凭证</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pager">
|
||||
@@ -104,7 +104,7 @@ import { uploadToOss } from '@/utils/oss'
|
||||
const q = ref({ meetingName: '', expertName: '' })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
const detail = ref({})
|
||||
const detailOpen = ref(false)
|
||||
|
||||
@@ -200,7 +200,6 @@ onMounted(load)
|
||||
.executor-labor { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.page-sub { font-size: 13px; color: #909399; margin-bottom: 16px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
|
||||
/* 红字提示 (与 People.vue 一致) */
|
||||
|
||||
@@ -56,11 +56,11 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="200" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="onView(row)">查看</el-button>
|
||||
<el-button link type="primary" @click="onUpload(row)">编辑材料</el-button>
|
||||
<el-button link type="primary" @click="onEdit(row)">修改</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="onView(row)">查看</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onUpload(row)">编辑材料</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onEdit(row)">修改</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pager">
|
||||
@@ -85,7 +85,7 @@ const q = ref({
|
||||
})
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
// 工具: 时间格式 (yyyy.MM.dd HH:mm), 与 manager 列表一致
|
||||
function fmtTime(d) {
|
||||
@@ -139,7 +139,6 @@ onMounted(() => { readQueryFromRoute(); load() })
|
||||
/* 整页面板 (仿 manager/meetings/Meetings.vue 风格) */
|
||||
.executor-meetings { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.date-sep { margin: 0 4px; color: #606266; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
|
||||
|
||||
@@ -42,17 +42,17 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="300" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link type="primary" @click="onView(row)">查看</el-button>
|
||||
<el-button size="small" link type="primary" @click="goEdit(row)">编辑</el-button>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" size="small" type="primary" @click="onView(row)">查看</el-link>
|
||||
<el-link :underline="false" size="small" type="primary" @click="goEdit(row)">编辑</el-link>
|
||||
<!-- 重置密码: 重置为默认 123456 (与新建人员默认密码一致) -->
|
||||
<el-button v-if="row.userId" size="small" link type="primary" @click="onResetPwd(row)">重置密码</el-button>
|
||||
<el-link :underline="false" v-if="row.userId" size="small" type="primary" @click="onResetPwd(row)">重置密码</el-link>
|
||||
<!-- 本人不显示禁用/恢复按钮 (跟 sponsor 一样, 避免主账号把自己禁用) -->
|
||||
<template v-if="row.userId !== store.user?.userId">
|
||||
<el-button v-if="row.status === '0'" size="small" link type="danger" @click="onToggleStatus(row, '禁用')">禁用</el-button>
|
||||
<el-button v-else size="small" link type="success" @click="onToggleStatus(row, '恢复')">恢复</el-button>
|
||||
<el-link :underline="false" v-if="row.status === '0'" size="small" type="danger" @click="onToggleStatus(row, '禁用')">禁用</el-link>
|
||||
<el-link :underline="false" v-else size="small" type="success" @click="onToggleStatus(row, '恢复')">恢复</el-link>
|
||||
</template>
|
||||
</template>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pager">
|
||||
@@ -122,7 +122,7 @@ const store = useUserStore()
|
||||
const list = ref([])
|
||||
const loading = ref(false)
|
||||
const q = reactive({ name: '', phone: '', orgName: '', department: '', position: '' })
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
const importOpen = ref(false)
|
||||
|
||||
@@ -246,5 +246,4 @@ onMounted(loadList)
|
||||
.hint-link { color: var(--brand-primary); cursor: pointer; font-size: 13px; }
|
||||
.hint-link:hover { color: var(--brand-primary-deep); }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
</style>
|
||||
@@ -77,11 +77,11 @@
|
||||
<el-table-column prop="startTime" label="项目开始时间" width="150" />
|
||||
<el-table-column prop="endTime" label="项目结束时间" width="150" />
|
||||
<el-table-column label="操作" width="250" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" :disabled="atCap(row)" :title="atCap(row) ? '已建会议数已达分配场次上限' : ''" @click="onCreateMeeting(row)">建会</el-button>
|
||||
<el-button link type="primary" @click="viewDetail(row)">查看</el-button>
|
||||
<el-button v-if="!isSub" link type="primary" @click="onAssign(row)">分配</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" :disabled="atCap(row)" :title="atCap(row) ? '已建会议数已达分配场次上限' : ''" @click="onCreateMeeting(row)">建会</el-link>
|
||||
<el-link :underline="false" type="primary" @click="viewDetail(row)">查看</el-link>
|
||||
<el-link :underline="false" v-if="!isSub" type="primary" @click="onAssign(row)">分配</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pager">
|
||||
@@ -137,7 +137,7 @@ const list = ref([])
|
||||
const loading = ref(false)
|
||||
const query = reactive({ projectNo: '', projectName: '', isFinished: '', isSettled: '' })
|
||||
const dateRange = ref([])
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
const selected = ref([])
|
||||
|
||||
// 项目分配 (执行人): 仿 sponsor/SponsorProjects.vue
|
||||
@@ -284,7 +284,6 @@ onMounted(() => { readQueryFromRoute(); loadList() })
|
||||
.batch-bar { margin-bottom: 12px; display: flex; gap: 8px; align-items: center; }
|
||||
.filter-tip { color: #909399; font-size: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.assign-project-info { background: #f5f7fa; padding: 12px 16px; border-radius: 4px; margin-bottom: 12px; }
|
||||
.assign-project-info > div { display: flex; line-height: 22px; }
|
||||
.assign-project-info .lbl { color: #909399; width: 90px; flex-shrink: 0; }
|
||||
|
||||
@@ -63,8 +63,8 @@
|
||||
<el-table-column label="执业证书" width="170">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row.practiceCertUrl">
|
||||
<el-button link type="primary" @click="onPreviewCert(row.practiceCertUrl)">查看</el-button>
|
||||
<el-button link type="primary" @click="onDownloadCert(row.practiceCertUrl, row.phone)">下载</el-button>
|
||||
<el-link :underline="false" type="primary" @click="onPreviewCert(row.practiceCertUrl)">查看</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onDownloadCert(row.practiceCertUrl, row.phone)">下载</el-link>
|
||||
</template>
|
||||
<span v-else style="color:#c0c4cc">-</span>
|
||||
</template>
|
||||
@@ -72,8 +72,8 @@
|
||||
<el-table-column label="职称证明" width="170">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row.titleCertUrl">
|
||||
<el-button link type="primary" @click="onPreviewCert(row.titleCertUrl)">查看</el-button>
|
||||
<el-button link type="primary" @click="onDownloadCert(row.titleCertUrl, row.phone)">下载</el-button>
|
||||
<el-link :underline="false" type="primary" @click="onPreviewCert(row.titleCertUrl)">查看</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onDownloadCert(row.titleCertUrl, row.phone)">下载</el-link>
|
||||
</template>
|
||||
<span v-else style="color:#c0c4cc">-</span>
|
||||
</template>
|
||||
@@ -93,20 +93,20 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="auditBy" label="审批人" width="120" align="center" />
|
||||
<el-table-column label="操作" :width="isAdmin ? 320 : 240" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<!-- 审核 (通过/拒绝): 两角色都有, manager 主业, admin 可兜底 -->
|
||||
<el-button link type="primary" @click="onAudit(row)">审核</el-button>
|
||||
<el-link :underline="false" type="primary" @click="onAudit(row)">审核</el-link>
|
||||
<!-- 修改: 两角色都有 (独立页编辑, route 自动决定回跳) -->
|
||||
<el-button link type="primary" @click="goEdit(row)">修改</el-button>
|
||||
<el-link :underline="false" type="primary" @click="goEdit(row)">修改</el-link>
|
||||
<!-- 查看 (只读详情): 仅 admin, manager 直接在审核 dialog 看 -->
|
||||
<el-button v-if="isAdmin" link type="primary" @click="goView(row)">查看</el-button>
|
||||
<el-link :underline="false" v-if="isAdmin" type="primary" @click="goView(row)">查看</el-link>
|
||||
<!-- 启用/禁用: 仅 admin, 是账号管理动作 (同步 sys_user.status) -->
|
||||
<el-button v-if="isAdmin" link :type="row.status === 'N' ? 'success' : 'danger'" @click="row.status === 'N' ? onEnable(row) : onDisable(row)">
|
||||
<el-link :underline="false" v-if="isAdmin" :type="row.status === 'N' ? 'success' : 'danger'" @click="row.status === 'N' ? onEnable(row) : onDisable(row)">
|
||||
{{ row.status === 'N' ? '恢复' : '禁用' }}
|
||||
</el-button>
|
||||
</el-link>
|
||||
<!-- 已拒绝 (查意见): 仅 auditStatus=3 时显示, 两角色都可见 -->
|
||||
<el-button v-if="row.auditStatus === '3'" link type="info" @click="onViewAuditOpinion(row)">已拒绝</el-button>
|
||||
</template>
|
||||
<el-link :underline="false" v-if="row.auditStatus === '3'" type="info" @click="onViewAuditOpinion(row)">已拒绝</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -239,7 +239,7 @@ const rows = ref([])
|
||||
const selection = ref([])
|
||||
const loading = ref(false)
|
||||
const submitting = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
function goNew() { router.push(listBasePath.value + '/new') }
|
||||
function goEdit(row) { router.push(listBasePath.value + '/edit/' + row.expertId) }
|
||||
@@ -464,7 +464,6 @@ watch(() => route.fullPath, () => {
|
||||
<style scoped>
|
||||
.experts-list { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.batch-bar { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; flex-wrap: wrap; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column v-if="false" label="操作" width="220" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row.intentStatus !== '已通过'" type="primary" link size="small" @click="changeStatus(row, '已通过')">通过</el-button>
|
||||
<el-button v-if="row.intentStatus !== '已拒绝'" type="danger" link size="small" @click="changeStatus(row, '已拒绝')">拒绝</el-button>
|
||||
<el-button v-if="row.intentStatus !== '待审核'" type="warning" link size="small" @click="changeStatus(row, '待审核')">重置</el-button>
|
||||
<el-button type="danger" link size="small" @click="removeOne(row)">删除</el-button>
|
||||
<el-link :underline="false" v-if="row.intentStatus !== '已通过'" type="primary" @click="changeStatus(row, '已通过')">通过</el-link>
|
||||
<el-link :underline="false" v-if="row.intentStatus !== '已拒绝'" type="danger" @click="changeStatus(row, '已拒绝')">拒绝</el-link>
|
||||
<el-link :underline="false" v-if="row.intentStatus !== '待审核'" type="warning" @click="changeStatus(row, '待审核')">重置</el-link>
|
||||
<el-link :underline="false" type="danger" @click="removeOne(row)">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -72,7 +72,7 @@ import {
|
||||
const q = ref({ projectNo: '', projectName: '', name: '', workUnit: '', phone: '', intentStatus: '' })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
@@ -145,6 +145,5 @@ onMounted(load)
|
||||
<style scoped>
|
||||
.manager-exec-intent { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; align-items: center; margin-top: 12px; }
|
||||
</style>
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
<span class="notice-label">{{ n.label }}</span>
|
||||
<span v-if="n.url" class="notice-file">
|
||||
<span class="file-name">{{ n.name || '已上传' }}</span>
|
||||
<el-button link type="primary" @click="openPreview(n.url, n.label)">查看</el-button>
|
||||
<el-link :underline="false" type="primary" @click="openPreview(n.url, n.label)">查看</el-link>
|
||||
</span>
|
||||
<span v-else class="file-empty">未上传</span>
|
||||
</div>
|
||||
|
||||
@@ -102,12 +102,12 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #default="{ $index }">
|
||||
<el-button link type="danger" :disabled="$index === 0 && assignForm.execRows.length === 1" @click="assignForm.execRows.splice($index, 1)">删除</el-button>
|
||||
<el-link :underline="false" type="danger" :disabled="$index === 0 && assignForm.execRows.length === 1" @click="assignForm.execRows.splice($index, 1)">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="margin-top:8px">
|
||||
<el-button type="primary" link @click="addExecRow">+ 增加执行方</el-button>
|
||||
<el-link :underline="false" type="primary" @click="addExecRow">+ 增加执行方</el-link>
|
||||
</div>
|
||||
|
||||
<el-form-item label="提交截止(天)" style="margin-top:12px">
|
||||
|
||||
@@ -48,8 +48,8 @@
|
||||
<el-table-column label="设计文件" width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row.designFileUrl">
|
||||
<el-button link type="primary" @click="openDesign(row)">查看</el-button>
|
||||
<el-button link type="primary" @click="downloadFile(row)">下载</el-button>
|
||||
<el-link :underline="false" type="primary" @click="openDesign(row)">查看</el-link>
|
||||
<el-link :underline="false" type="primary" @click="downloadFile(row)">下载</el-link>
|
||||
</template>
|
||||
<span v-else style="color:#c0c4cc">-</span>
|
||||
</template>
|
||||
@@ -69,11 +69,11 @@
|
||||
<el-table-column prop="projectNo" label="项目编号" width="140" align="center" />
|
||||
<el-table-column prop="remark" label="备注" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="onAudit(row)">审核</el-button>
|
||||
<el-button link type="primary" @click="goEdit(row)">修改</el-button>
|
||||
<el-button link type="primary" @click="onSettle(row)" v-if="row.isSettled!=='Y'">结算</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="onAudit(row)">审核</el-link>
|
||||
<el-link :underline="false" type="primary" @click="goEdit(row)">修改</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onSettle(row)" v-if="row.isSettled!=='Y'">结算</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pager">
|
||||
@@ -173,7 +173,7 @@ const q = ref({ planName: '', projectNo: '', planDirectionId: '', planCategory:
|
||||
const rows = ref([]); const selection = ref([])
|
||||
const loading = ref(false)
|
||||
const submitting = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
@@ -350,7 +350,6 @@ onMounted(() => { loadPlanDirectionOptions(); load() })
|
||||
border-left: 3px solid var(--brand-primary);
|
||||
}
|
||||
.page-sub { font-size: 13px; color: #909399; margin: 0 0 16px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.batch-bar { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; }
|
||||
.filter-tip { color: #909399; font-size: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
|
||||
@@ -116,14 +116,14 @@
|
||||
<el-table-column prop="startTime" label="项目开始时间" width="120" align="center" :formatter="fmtDate" />
|
||||
<el-table-column prop="endTime" label="项目结束时间" width="120" align="center" :formatter="fmtDate" />
|
||||
<el-table-column label="操作" width="180" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<div class="op-cell">
|
||||
<el-button link type="primary" @click="doCreateMeeting(row)">建会</el-button>
|
||||
<el-button link type="primary" @click="doAssign(row)">分配</el-button>
|
||||
<el-link :underline="false" type="primary" @click="doCreateMeeting(row)">建会</el-link>
|
||||
<el-link :underline="false" type="primary" @click="doAssign(row)">分配</el-link>
|
||||
<el-dropdown trigger="click" @command="(cmd) => onAction(cmd, row)">
|
||||
<el-button link type="primary" class="op-dropdown">
|
||||
<el-link :underline="false" type="primary" class="op-dropdown">
|
||||
更多<el-icon class="op-caret"><ArrowDown /></el-icon>
|
||||
</el-button>
|
||||
</el-link>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="row.isFinished !== '1' && row.isFinished !== 1" command="close">结题</el-dropdown-item>
|
||||
@@ -138,7 +138,7 @@
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination v-model:current-page="page.pageNum" v-model:page-size="page.pageSize" :total="page.total" :page-sizes="[10,20,50]" layout="total, sizes, prev, pager, next, jumper" @current-change="load" @size-change="load" />
|
||||
@@ -253,7 +253,7 @@ const route = useRoute()
|
||||
const q = ref({ sponsorOrgIds: [], execOrgIds: [], projectNo: '', projectName: '', projectForm: '', startTime: '', endTime: '', isFinished: '', isSettled: '' })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
@@ -695,7 +695,6 @@ watch(() => route.path + (route.query._t || ''), () => load())
|
||||
/* 1:1 抄 sponsor/SponsorProjects.vue */
|
||||
.page-card { background: #fff; padding: 16px 20px; border-radius: 6px; border: 1px solid #f0f0f0; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { display: flex; flex-wrap: wrap; gap: 0 16px; padding-bottom: 12px; border-bottom: 1px solid #f0f0f0; margin-bottom: 12px; }
|
||||
.toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
|
||||
|
||||
/* 操作列下拉 */
|
||||
|
||||
@@ -94,10 +94,10 @@
|
||||
<el-input v-if="r.role === '其他'" v-model="r.customName" placeholder="角色名" class="role-custom" />
|
||||
<el-input-number v-model="r.amount" :min="0" :precision="2" placeholder="劳务金额" class="role-amount" />
|
||||
<div class="row-actions">
|
||||
<el-button link type="danger" :disabled="form.roleRows.length<=1" @click="removeRoleRowAt(idx)">删除角色</el-button>
|
||||
<el-link :underline="false" type="danger" :disabled="form.roleRows.length<=1" @click="removeRoleRowAt(idx)">删除角色</el-link>
|
||||
</div>
|
||||
</div>
|
||||
<el-button link type="primary" @click="addRoleRow" style="margin-top: 8px;">+ 增加角色</el-button>
|
||||
<el-link :underline="false" type="primary" @click="addRoleRow" style="margin-top: 8px;">+ 增加角色</el-link>
|
||||
|
||||
<!-- ========== 第三区块:公告文件 ========== -->
|
||||
<div class="new-card-title">公告文件</div>
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" align="center" />
|
||||
<el-table-column v-if="false" label="操作" width="220" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row.intentStatus !== '已通过'" type="primary" link size="small" @click="changeStatus(row, '已通过')">通过</el-button>
|
||||
<el-button v-if="row.intentStatus !== '已拒绝'" type="danger" link size="small" @click="changeStatus(row, '已拒绝')">拒绝</el-button>
|
||||
<el-button v-if="row.intentStatus !== '待审核'" type="warning" link size="small" @click="changeStatus(row, '待审核')">重置</el-button>
|
||||
<el-button type="danger" link size="small" @click="removeOne(row)">删除</el-button>
|
||||
<el-link :underline="false" v-if="row.intentStatus !== '已通过'" type="primary" @click="changeStatus(row, '已通过')">通过</el-link>
|
||||
<el-link :underline="false" v-if="row.intentStatus !== '已拒绝'" type="danger" @click="changeStatus(row, '已拒绝')">拒绝</el-link>
|
||||
<el-link :underline="false" v-if="row.intentStatus !== '待审核'" type="warning" @click="changeStatus(row, '待审核')">重置</el-link>
|
||||
<el-link :underline="false" type="danger" @click="removeOne(row)">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -72,7 +72,7 @@ import {
|
||||
const q = ref({ projectNo: '', projectName: '', name: '', workUnit: '', phone: '', intentStatus: '' })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
@@ -145,7 +145,6 @@ onMounted(load)
|
||||
<style scoped>
|
||||
.manager-support-intent { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; align-items: center; margin-top: 12px; }
|
||||
|
||||
</style>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<div class="tag-list">
|
||||
<el-tag v-for="u in supervisors" :key="u.sponsorOrgId" type="info" size="small">{{ u.orgName }}</el-tag>
|
||||
<span v-if="!supervisors.length" class="text-muted">- 未分配 -</span>
|
||||
<el-button v-if="isManager && !isReadonly" link type="primary" size="small" @click="openAssignDialog('supervisor')">分配</el-button>
|
||||
<el-link :underline="false" v-if="isManager && !isReadonly" type="primary" @click="openAssignDialog('supervisor')">分配</el-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-row info-row-full">
|
||||
@@ -49,7 +49,7 @@
|
||||
<div class="tag-list">
|
||||
<el-tag v-for="u in executors" :key="u.executorOrgId" type="success" size="small">{{ u.orgName }}</el-tag>
|
||||
<span v-if="!executors.length" class="text-muted">- 未分配 -</span>
|
||||
<el-button v-if="isManager && !isReadonly" link type="primary" size="small" @click="openAssignDialog('executor')">分配</el-button>
|
||||
<el-link :underline="false" v-if="isManager && !isReadonly" type="primary" @click="openAssignDialog('executor')">分配</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -101,7 +101,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column v-if="!isSponsor" label="身份证附件" min-width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="idCardFiles(row).length" link type="primary" size="small" @click="openPreview(idCardFiles(row), '身份证')">查看</el-button>
|
||||
<el-link :underline="false" v-if="idCardFiles(row).length" type="primary" @click="openPreview(idCardFiles(row), '身份证')">查看</el-link>
|
||||
<span v-else class="text-muted">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -121,7 +121,7 @@
|
||||
<el-table-column prop="laborForm" label="角色" min-width="90" show-overflow-tooltip />
|
||||
<el-table-column label="劳务协议" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="protocolUrl(row)" link type="primary" size="small" @click="openPreview([protocolUrl(row)], '劳务协议')">查看</el-button>
|
||||
<el-link :underline="false" v-if="protocolUrl(row)" type="primary" @click="openPreview([protocolUrl(row)], '劳务协议')">查看</el-link>
|
||||
<span v-else class="text-muted">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -152,11 +152,11 @@
|
||||
<el-table-column v-if="!isSponsor && !isReadonly" label="操作" width="100" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="row-actions">
|
||||
<el-button link type="primary" size="small" @click="openAttendeeDialog(row)">编辑</el-button>
|
||||
<el-link :underline="false" type="primary" @click="openAttendeeDialog(row)">编辑</el-link>
|
||||
<el-dropdown trigger="click" @command="(cmd) => onAttendeeCommand(cmd, row)">
|
||||
<el-button link type="primary" size="small" :loading="inviteLoadingId === row.id || esignLoadingId === row.id">
|
||||
<el-link :underline="false" type="primary" :disabled="inviteLoadingId === row.id || esignLoadingId === row.id">
|
||||
更多<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
||||
</el-button>
|
||||
</el-link>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="invite" :disabled="inviteLoadingId === row.id">邀请参会</el-dropdown-item>
|
||||
|
||||
@@ -69,21 +69,35 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="500" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="viewOnly(row)">查看</el-button>
|
||||
<el-button v-if="isRole('manager') && isCompliancePending(row)" link type="warning" @click="onAudit(row)">审核</el-button>
|
||||
<el-button v-if="isRole('admin', 'manager')" link type="primary" @click="viewDetail(row)">编辑材料</el-button>
|
||||
<el-button v-if="isRole('admin', 'manager')" link type="primary" @click="onEdit(row)">修改</el-button>
|
||||
<el-button v-if="isRole('admin', 'manager')" link type="primary" @click="onCopy(row)">复制</el-button>
|
||||
<el-button v-if="isRole('admin', 'manager') && canSettleRow(row)" link type="success" @click="onSettle(row)">结算</el-button>
|
||||
<el-button v-if="isRole('admin', 'manager') && canFinishRow(row)" link type="primary" @click="onFinish(row)">完结</el-button>
|
||||
<el-button v-if="isRole('admin', 'manager') && isOneVal(row.isFrozen)" link type="warning" @click="onUnfreeze(row)">解冻</el-button>
|
||||
<el-button v-if="isRole('admin', 'manager')" link type="primary" @click="onDownloadService(row)">会务下载</el-button>
|
||||
<el-button v-if="isRole('admin', 'manager')" link type="primary" @click="onDownloadLabor(row)">劳务下载</el-button>
|
||||
<el-button v-if="isRole('admin', 'manager')" link type="danger" @click="onDelete(row)">删除</el-button>
|
||||
<el-button v-if="isRole('sponsor') && isSponsorPending(row)" link type="warning" @click="onAudit(row)">审核</el-button>
|
||||
</template>
|
||||
<el-table-column label="操作" width="260" fixed="right" align="center">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<!-- 主操作: 查看 / 审核 / 编辑材料 (按角色显隐) -->
|
||||
<el-link :underline="false" type="primary" @click="viewOnly(row)">查看</el-link>
|
||||
<el-link :underline="false" v-if="isRole('manager') && isCompliancePending(row)" type="warning" @click="onAudit(row)">审核</el-link>
|
||||
<el-link :underline="false" v-if="isRole('admin', 'manager')" type="primary" @click="viewDetail(row)">编辑材料</el-link>
|
||||
<!-- 更多: admin/manager 视角 ≥7 个次操作折叠 (sponsor 视角只 1 个审核, 始终走外置) -->
|
||||
<el-dropdown v-if="isRole('admin', 'manager')" trigger="click" @command="(cmd) => onMoreAction(cmd, row)">
|
||||
<el-link :underline="false" type="primary" class="op-dropdown">
|
||||
更多<el-icon class="op-caret"><ArrowDown /></el-icon>
|
||||
</el-link>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="edit">修改</el-dropdown-item>
|
||||
<el-dropdown-item command="copy">复制</el-dropdown-item>
|
||||
<el-dropdown-item v-if="canSettleRow(row)" command="settle">结算</el-dropdown-item>
|
||||
<el-dropdown-item v-if="canFinishRow(row)" command="finish">完结</el-dropdown-item>
|
||||
<el-dropdown-item v-if="isOneVal(row.isFrozen)" command="unfreeze">解冻</el-dropdown-item>
|
||||
<el-dropdown-item command="downloadService">会务下载</el-dropdown-item>
|
||||
<el-dropdown-item command="downloadLabor">劳务下载</el-dropdown-item>
|
||||
<el-dropdown-item divided command="delete">
|
||||
<span style="color:#DC2626">删除</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<!-- sponsor 视角: 额外只看合规审核 -->
|
||||
<el-link :underline="false" v-if="isRole('sponsor') && isSponsorPending(row)" type="warning" @click="onAudit(row)">审核</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pager">
|
||||
@@ -132,6 +146,7 @@ import { bizList, bizDelete } from '@/api/public'
|
||||
import request from '@/utils/request'
|
||||
import { stageLabel, STAGE_OPTIONS, stageClass } from '@/utils/meetingStage'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { ArrowDown } from '@element-plus/icons-vue'
|
||||
|
||||
// ========== 角色感知 (admin/manager 共用此页, 按 URL 第 1 段识别) ==========
|
||||
const router = useRouter()
|
||||
@@ -159,7 +174,7 @@ const q = ref({
|
||||
})
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
// ========== 表格多选 ==========
|
||||
const selectedIds = ref([])
|
||||
@@ -211,6 +226,17 @@ function viewDetail(row) {
|
||||
function viewOnly(row) {
|
||||
router.push(`${detailBase.value}/view/${row.meetingId}`)
|
||||
}
|
||||
// 操作列"更多"下拉分发: 把 cmd 映射到现有 handler
|
||||
function onMoreAction(cmd, row) {
|
||||
if (cmd === 'edit') onEdit(row)
|
||||
else if (cmd === 'copy') onCopy(row)
|
||||
else if (cmd === 'settle') onSettle(row)
|
||||
else if (cmd === 'finish') onFinish(row)
|
||||
else if (cmd === 'unfreeze') onUnfreeze(row)
|
||||
else if (cmd === 'downloadService') onDownloadService(row)
|
||||
else if (cmd === 'downloadLabor') onDownloadLabor(row)
|
||||
else if (cmd === 'delete') onDelete(row)
|
||||
}
|
||||
// 修改 / 复制: 按角色选 admin-meetings-new 或 manager-meetings-new (MeetingNew.vue 公共页)
|
||||
function onEdit(row) {
|
||||
router.push({ name: newRouteName.value, query: { meetingId: row.meetingId, projectId: row.projectId || '' } })
|
||||
@@ -439,7 +465,6 @@ onMounted(() => { readQueryFromRoute(); load() })
|
||||
/* 整页面板 (与 People.vue 风格一致, 双角色共用) */
|
||||
.meetings-list { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.batch-bar { margin-bottom: 12px; display: flex; gap: 8px; align-items: center; }
|
||||
.filter-tip { color: #909399; font-size: 12px; margin-left: auto; }
|
||||
.date-sep { margin: 0 4px; color: #606266; }
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="320" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="openDetail(row)">详情</el-button>
|
||||
<el-button link type="primary" :disabled="!row.templateUrl" @click="openPreview(row, 'template')">模板</el-button>
|
||||
<el-button link type="primary" :disabled="!row.qrCodeUrl" @click="openPreview(row, 'qr')">QR</el-button>
|
||||
<el-button link type="primary" :disabled="!row.shareUrl" @click="openPreview(row, 'share')">分享</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="openDetail(row)">详情</el-link>
|
||||
<el-link :underline="false" type="primary" :disabled="!row.templateUrl" @click="openPreview(row, 'template')">模板</el-link>
|
||||
<el-link :underline="false" type="primary" :disabled="!row.qrCodeUrl" @click="openPreview(row, 'qr')">QR</el-link>
|
||||
<el-link :underline="false" type="primary" :disabled="!row.shareUrl" @click="openPreview(row, 'share')">分享</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
@@ -77,7 +77,7 @@ import Preview from '@/components/Preview.vue'
|
||||
const q = ref({ projectNo: '', title: '' })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="supportCount" label="支持单位数" width="120" align="center" />
|
||||
<el-table-column label="操作" width="220" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="openDetail(row)">详情</el-button>
|
||||
<el-button link type="primary" :disabled="!row.fileUrl" @click="openPreview(row)">预览</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="openDetail(row)">详情</el-link>
|
||||
<el-link :underline="false" type="primary" :disabled="!row.fileUrl" @click="openPreview(row)">预览</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
@@ -66,7 +66,7 @@ import Preview from '@/components/Preview.vue'
|
||||
const q = ref({ projectNo: '', title: '' })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
|
||||
@@ -54,18 +54,18 @@
|
||||
<el-table-column prop="contactName" label="联系人" width="100" align="center" />
|
||||
<el-table-column prop="contactPhone" label="联系电话" width="130" align="center" />
|
||||
<el-table-column label="操作" :width="isAdmin ? 320 : 240" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<!-- 查看: 两角色都有 (manager 原版本有, admin 原版本用 alert, 这里统一用 dialog 更清晰) -->
|
||||
<el-button link type="primary" @click="onView(row)">查看</el-button>
|
||||
<el-link :underline="false" type="primary" @click="onView(row)">查看</el-link>
|
||||
<!-- 编辑: 仅 admin -->
|
||||
<el-button v-if="isAdmin" link type="primary" @click="onEdit(row)">编辑</el-button>
|
||||
<el-link :underline="false" v-if="isAdmin" type="primary" @click="onEdit(row)">编辑</el-link>
|
||||
<!-- 人员管理: 两角色都有, 按角色跳 -->
|
||||
<el-button link type="primary" @click="onPeople(row)">人员管理</el-button>
|
||||
<el-link :underline="false" type="primary" @click="onPeople(row)">人员管理</el-link>
|
||||
<!-- 启用/禁用: 两角色都有 (沿用原行为) -->
|
||||
<el-button link :type="isDisabled(row) ? 'success' : 'danger'" @click="onToggleStatus(row)">
|
||||
<el-link :underline="false" :type="isDisabled(row) ? 'success' : 'danger'" @click="onToggleStatus(row)">
|
||||
{{ isDisabled(row) ? '恢复' : '禁用' }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -181,7 +181,7 @@ const peopleBasePath = computed(() => isAdmin.value ? '/admin/sponsor-people' :
|
||||
const q = reactive({ orgType: 'sponsor', orgName: '', taxNo: '', status: '' })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
function statusTagType(s) {
|
||||
// 统一: 0=正常(success), 1=禁用(danger)
|
||||
@@ -362,7 +362,6 @@ onMounted(load)
|
||||
<style scoped>
|
||||
.sponsor-orgs { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.batch-bar { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
</style>
|
||||
|
||||
@@ -62,18 +62,18 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="340" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<!-- 查看 (只读详情): 两角色都有, 跳独立详情页 -->
|
||||
<el-button link type="primary" @click="goView(row)">查看</el-button>
|
||||
<el-link :underline="false" type="primary" @click="goView(row)">查看</el-link>
|
||||
<!-- 编辑: 两角色都有, 跳独立编辑页 -->
|
||||
<el-button link type="primary" @click="goEdit(row)">编辑</el-button>
|
||||
<el-link :underline="false" type="primary" @click="goEdit(row)">编辑</el-link>
|
||||
<!-- 启用/禁用: 两角色都有 (沿用原行为) -->
|
||||
<el-button link :type="isDisabled(row) ? 'success' : 'danger'" @click="onToggleStatus(row)">
|
||||
<el-link :underline="false" :type="isDisabled(row) ? 'success' : 'danger'" @click="onToggleStatus(row)">
|
||||
{{ isDisabled(row) ? '启用' : '禁用' }}
|
||||
</el-button>
|
||||
</el-link>
|
||||
<!-- 重置密码: 重置为默认 123456 (与新建人员默认密码一致) -->
|
||||
<el-button v-if="row.userId" link type="primary" @click="onResetPwd(row)">重置密码</el-button>
|
||||
</template>
|
||||
<el-link :underline="false" v-if="row.userId" type="primary" @click="onResetPwd(row)">重置密码</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -139,7 +139,7 @@ const orgName = computed(() => route.query.orgName || '')
|
||||
const q = reactive({ name: '', phone: '', orgName: '', department: '', position: '' })
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
function statusTagType(s) {
|
||||
// 统一: 0=正常(success), 1=禁用(danger)
|
||||
@@ -319,7 +319,6 @@ watch(() => route.fullPath, () => {
|
||||
<style scoped>
|
||||
.sponsor-people { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.batch-bar { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; }
|
||||
.filter-tip { color: #909399; font-size: 12px; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
|
||||
@@ -70,15 +70,15 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="项目形式" prop="projectForm" width="100" />
|
||||
<el-table-column label="操作" width="420" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link type="primary" @click="onView(row)">查看</el-button>
|
||||
<el-button size="small" link type="primary" @click="onEdit(row)">修改</el-button>
|
||||
<el-button size="small" link type="warning" :disabled="!canSettle(row)" @click="onSettle(row)">结算</el-button>
|
||||
<el-button size="small" link type="primary" @click="onAudit(row)">审核</el-button>
|
||||
<el-button size="small" link @click="onDownload(row, 'labor')">劳务下载</el-button>
|
||||
<el-button size="small" link @click="onDownload(row, 'meeting')">会务下载</el-button>
|
||||
<el-button size="small" link type="danger" :disabled="row.currentStage !== 'FROZEN'" @click="onUnfreeze(row)">解冻</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" size="small" type="primary" @click="onView(row)">查看</el-link>
|
||||
<el-link :underline="false" size="small" type="primary" @click="onEdit(row)">修改</el-link>
|
||||
<el-link :underline="false" size="small" type="warning" :disabled="!canSettle(row)" @click="onSettle(row)">结算</el-link>
|
||||
<el-link :underline="false" size="small" type="primary" @click="onAudit(row)">审核</el-link>
|
||||
<el-link :underline="false" size="small" @click="onDownload(row, 'labor')">劳务下载</el-link>
|
||||
<el-link :underline="false" size="small" @click="onDownload(row, 'meeting')">会务下载</el-link>
|
||||
<el-link :underline="false" size="small" type="danger" :disabled="row.currentStage !== 'FROZEN'" @click="onUnfreeze(row)">解冻</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pager">
|
||||
@@ -174,7 +174,7 @@ const q = reactive({
|
||||
projectNo: '', meetingId: '', meetingName: '', periodNo: null,
|
||||
startTimeRange: null, projectForm: '', currentStage: '', remark: ''
|
||||
})
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
|
||||
const view = ref({})
|
||||
const viewOpen = ref(false)
|
||||
@@ -323,7 +323,6 @@ onMounted(() => { readQueryFromRoute(); loadList() })
|
||||
/* 1:1 抄 doctor/Submissions.vue + SponsorPeople.vue */
|
||||
.page-card { background: #fff; padding: 16px 20px; border-radius: 6px; border: 1px solid #f0f0f0; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { display: flex; flex-wrap: wrap; gap: 0 16px; padding-bottom: 12px; border-bottom: 1px solid #f0f0f0; margin-bottom: 12px; }
|
||||
.batch-bar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
</style>
|
||||
@@ -59,9 +59,7 @@
|
||||
<el-table-column type="selection" width="48" />
|
||||
<el-table-column prop="projectNo" label="项目编号" min-width="140" fixed>
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" :underline="false" @click="openDetail(row)">{{ row.projectNo }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-link type="primary" :underline="false" @click="openDetail(row)">{{ row.projectNo }}</el-link></template></el-table-column>
|
||||
<el-table-column prop="projectName" label="项目名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="totalSessions" label="总场次/总期数" width="120" align="center" />
|
||||
<el-table-column prop="doneSessions" label="已执行" width="80" align="center" />
|
||||
@@ -94,17 +92,17 @@
|
||||
<el-table-column prop="startTime" label="项目开始时间" min-width="160" />
|
||||
<el-table-column prop="endTime" label="项目结束时间" min-width="160" />
|
||||
<el-table-column label="操作" width="480" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="onCreateMeeting(row)">建会</el-button>
|
||||
<el-button link type="primary" @click="openAssign(row)">分配</el-button>
|
||||
<el-button link type="primary" @click="onFinish(row)">结题</el-button>
|
||||
<el-button link type="primary" @click="openDetail(row)">查看</el-button>
|
||||
<el-button link type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button link type="primary" @click="onOpen(row)">开通</el-button>
|
||||
<el-button link type="danger" @click="onDeleteNotice(row)">删除公告</el-button>
|
||||
<el-button link type="primary" @click="onSupportUnit(row)">支持单位</el-button>
|
||||
<el-button link type="primary" @click="openRate(row)">执行单位评分</el-button>
|
||||
</template>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="onCreateMeeting(row)">建会</el-link>
|
||||
<el-link :underline="false" type="primary" @click="openAssign(row)">分配</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onFinish(row)">结题</el-link>
|
||||
<el-link :underline="false" type="primary" @click="openDetail(row)">查看</el-link>
|
||||
<el-link :underline="false" type="primary" @click="openEdit(row)">编辑</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onOpen(row)">开通</el-link>
|
||||
<el-link :underline="false" type="danger" @click="onDeleteNotice(row)">删除公告</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onSupportUnit(row)">支持单位</el-link>
|
||||
<el-link :underline="false" type="primary" @click="openRate(row)">执行单位评分</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -220,7 +218,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
const rows = ref([])
|
||||
const loading = ref(false)
|
||||
const q = reactive({ projectNo: '', projectName: '', projectForm: '', isFinished: '', isSettled: '' })
|
||||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||||
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
|
||||
const selected = ref([])
|
||||
|
||||
const formOpen = ref(false)
|
||||
@@ -456,7 +454,6 @@ onMounted(() => { readQueryFromRoute(); load(); loadPersons() })
|
||||
/* 1:1 抄 doctor/Projects.vue + doctor/Submissions.vue */
|
||||
.page-card { background: #fff; padding: 16px 20px; border-radius: 6px; border: 1px solid #f0f0f0; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { display: flex; flex-wrap: wrap; gap: 0 16px; padding-bottom: 12px; border-bottom: 1px solid #f0f0f0; margin-bottom: 12px; }
|
||||
.toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
|
||||
.hint { color: #909399; font-size: 12px; margin-left: 8px; }
|
||||
.score-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
|
||||
|
||||
@@ -65,18 +65,18 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
<el-table-column label="操作" width="320" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="onView(row)">查看</el-button>
|
||||
<el-button link type="primary" @click="onEdit(row)">编辑</el-button>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="onView(row)">查看</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onEdit(row)">编辑</el-link>
|
||||
<!-- 重置密码: 重置为默认 123456 (与新建人员默认密码一致) -->
|
||||
<el-button v-if="row.userId" link type="primary" @click="onResetPwd(row)">重置密码</el-button>
|
||||
<el-link :underline="false" v-if="row.userId" type="primary" @click="onResetPwd(row)">重置密码</el-link>
|
||||
<!-- 本人不显示禁用/恢复按钮 (避免主账号把自己禁用导致登录不上) -->
|
||||
<el-button v-if="row.userId !== store.user?.userId" link :type="row.status === '0' ? 'warning' : 'success'" @click="onToggleStatus(row)">
|
||||
<el-link :underline="false" v-if="row.userId !== store.user?.userId" :type="row.status === '0' ? 'warning' : 'success'" @click="onToggleStatus(row)">
|
||||
{{ row.status === '0' ? '禁用' : '恢复' }}
|
||||
</el-button>
|
||||
</el-link>
|
||||
<!-- 本人不显示删除按钮 (避免主账号误删自己的 biz_person) -->
|
||||
<el-button v-if="row.userId !== store.user?.userId" link type="danger" @click="onRemoveOne(row)">删除</el-button>
|
||||
</template>
|
||||
<el-link :underline="false" v-if="row.userId !== store.user?.userId" type="danger" @click="onRemoveOne(row)">删除</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -303,7 +303,6 @@ load()
|
||||
/* 1:1 抄 doctor/Submissions.vue */
|
||||
.page-card { background: #fff; padding: 16px 20px; border-radius: 6px; border: 1px solid #f0f0f0; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { display: flex; flex-wrap: wrap; gap: 0 16px; padding-bottom: 12px; border-bottom: 1px solid #f0f0f0; margin-bottom: 12px; }
|
||||
.toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
|
||||
|
||||
.hint-link { color: var(--brand-primary); cursor: pointer; font-size: 13px; }
|
||||
|
||||
@@ -88,12 +88,12 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="240" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="openSingleScore(row)">项目评价</el-button>
|
||||
<template #default="{ row }"><div class="table-actions">
|
||||
<el-link :underline="false" type="primary" @click="openSingleScore(row)">项目评价</el-link>
|
||||
<!-- SUB 子账号仅查看, 不参与分配 -->
|
||||
<el-button v-if="!isSub" link type="primary" @click="openAssign(row)">分配</el-button>
|
||||
<el-button link type="primary" @click="onView(row)">查看</el-button>
|
||||
</template>
|
||||
<el-link :underline="false" v-if="!isSub" type="primary" @click="openAssign(row)">分配</el-link>
|
||||
<el-link :underline="false" type="primary" @click="onView(row)">查看</el-link>
|
||||
</div></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -387,7 +387,6 @@ onMounted(load)
|
||||
<style scoped>
|
||||
.page-card { background: #fff; border: 1px solid #f0f0f0; border-radius: 6px; padding: 16px 20px; }
|
||||
.breadcrumb { color: #909399; font-size: 13px; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.toolbar { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
|
||||
.link { color: var(--brand-primary); }
|
||||
.link-bold { color: #303133; font-weight: 600; }
|
||||
|
||||
@@ -29,9 +29,11 @@ export default defineConfig(({ mode }) => {
|
||||
host: '0.0.0.0',
|
||||
proxy: {
|
||||
[apiPath]: {
|
||||
target: 'http://127.0.0.1:8080',
|
||||
// 远程后端: risingdoctor.com/hg-api (HTTPS, 远程 RuoYi v3.9.2)
|
||||
target: 'https://risingdoctor.com',
|
||||
changeOrigin: true,
|
||||
rewrite: (p) => p.replace(new RegExp('^' + apiPath), '')
|
||||
secure: true,
|
||||
rewrite: (p) => p.replace(new RegExp('^' + apiPath), '/hg-api')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user