feat: 会议批量审核 + 公示按发布时间倒序 + 现场照片 dialog 预览 + 重复报错精确
- 会议列表 manager 批量合规审核 (批量通过/退回, best-effort 逐条回执) - 公示列表按 publish_time 倒序, 发布/开通写本地 publish_time (修 toISOString UTC 时区 bug) - 签到表/前全景/后全景「查看照片」改 dialog 预览 (复用 Preview.vue) - 手机号/用户名重复报错精确提示 (后端 fieldMap + 前端 duplicateTip) - 医生首页欢迎语改「欢迎使用合规系统」
This commit is contained in:
@@ -42,30 +42,48 @@
|
||||
</div>
|
||||
|
||||
<div class="filter-bar">
|
||||
<input v-model="currentKeyword" @keydown.enter="applyFilter" type="text" class="filter-input" placeholder="">
|
||||
<div class="filter-input-wrap">
|
||||
<svg class="filter-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||||
<circle cx="11" cy="11" r="7"/>
|
||||
<path d="M21 21l-4.3-4.3"/>
|
||||
</svg>
|
||||
<input v-model="currentKeyword" @keydown.enter="applyFilter" type="text" class="filter-input" placeholder="搜索项目名称">
|
||||
</div>
|
||||
<button class="filter-btn" @click="applyFilter">查询</button>
|
||||
<button class="filter-btn" style="background: #fff; color: var(--brand-primary); border: 1px solid var(--brand-primary);" @click="resetFilter">重置</button>
|
||||
<button class="filter-btn filter-btn-plain" @click="resetFilter">重置</button>
|
||||
</div>
|
||||
|
||||
<div class="notice-list">
|
||||
<template v-if="pageItems.length === 0">
|
||||
<div style="padding: 40px 0; text-align: center; color: #9ca3af; font-size: 13px;">暂无数据</div>
|
||||
<div class="notice-empty">
|
||||
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
||||
<path d="M14 2v6h6"/>
|
||||
</svg>
|
||||
<span>暂无公示项目</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="notice-header">
|
||||
<span class="notice-header-no">序号</span>
|
||||
<span class="notice-header-title">项目</span>
|
||||
<span class="notice-header-date">开始日期</span>
|
||||
<span class="notice-header-end">截止日期</span>
|
||||
<span class="notice-header-title">项目名称</span>
|
||||
<span class="notice-header-date">发布日期</span>
|
||||
</div>
|
||||
<div v-for="(n, i) in pageItems" :key="n.annId || i" class="notice-item" @click="goDetail(n)">
|
||||
<span class="notice-item-no">{{ String((currentPage - 1) * PAGE_SIZE + i + 1).padStart(3, '0') }}</span>
|
||||
<span class="notice-title">
|
||||
<span v-if="n.projectNo" style="color:#909399;margin-right:8px;font-size:13px">【{{ n.projectNo }}】</span>
|
||||
{{ n.title }}
|
||||
<svg class="notice-arrow" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M9 6l6 6-6 6"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="notice-date">
|
||||
<svg class="notice-date-icon" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="3" y="4" width="18" height="18" rx="2"/>
|
||||
<line x1="16" y1="2" x2="16" y2="6"/>
|
||||
<line x1="8" y1="2" x2="8" y2="6"/>
|
||||
<line x1="3" y1="10" x2="21" y2="10"/>
|
||||
</svg>
|
||||
{{ fmtDate(n.publishTime) }}
|
||||
</span>
|
||||
<span class="notice-date">{{ fmtDate(n.date) }}</span>
|
||||
<span class="notice-end">{{ fmtDate(n.endTime) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -121,8 +139,7 @@ async function load() {
|
||||
allRows.value = list.map(r => {
|
||||
return {
|
||||
annId: r.projectId,
|
||||
date: r.startTime,
|
||||
endTime: r.endTime,
|
||||
publishTime: r.publishTime,
|
||||
type: '公示',
|
||||
projectNo: r.projectNo || '',
|
||||
projectName: r.projectName,
|
||||
@@ -430,30 +447,47 @@ main.container {
|
||||
|
||||
/* ========== 筛选条 ========== */
|
||||
.filter-bar {
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #f3f4f6;
|
||||
margin-bottom: 0;
|
||||
padding: 14px 0;
|
||||
border-bottom: 1px solid #f0f2f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
gap: 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.filter-input-wrap {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-icon {
|
||||
position: absolute;
|
||||
left: 13px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #9ca3af;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.filter-input {
|
||||
height: 30px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #d1d5db;
|
||||
background: #fff;
|
||||
height: 34px;
|
||||
padding: 0 12px 0 34px;
|
||||
border: 1px solid #dde1e6;
|
||||
border-radius: 17px;
|
||||
background: #f7f8fa;
|
||||
font-size: 13px;
|
||||
color: #1f2937;
|
||||
font-family: inherit;
|
||||
outline: none;
|
||||
width: 220px;
|
||||
transition: border-color 0.2s;
|
||||
width: 240px;
|
||||
transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.filter-input:focus {
|
||||
border-color: var(--brand-primary);
|
||||
background: #fff;
|
||||
box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.filter-input::placeholder {
|
||||
@@ -461,20 +495,33 @@ main.container {
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
height: 30px;
|
||||
padding: 0 18px;
|
||||
height: 34px;
|
||||
padding: 0 20px;
|
||||
background: var(--brand-primary);
|
||||
color: #fff;
|
||||
border: none;
|
||||
font-size: 12px;
|
||||
border: 1px solid var(--brand-primary);
|
||||
border-radius: 17px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
letter-spacing: 1px;
|
||||
transition: background 0.2s;
|
||||
transition: background 0.2s, border-color 0.2s, color 0.2s;
|
||||
}
|
||||
|
||||
.filter-btn:hover {
|
||||
background: var(--brand-primary-deep);
|
||||
border-color: var(--brand-primary-deep);
|
||||
}
|
||||
|
||||
.filter-btn-plain {
|
||||
background: #fff;
|
||||
color: var(--brand-primary);
|
||||
}
|
||||
|
||||
.filter-btn-plain:hover {
|
||||
background: #f7f8fa;
|
||||
border-color: var(--brand-primary);
|
||||
color: var(--brand-primary);
|
||||
}
|
||||
|
||||
/* ========== 公示列表 ========== */
|
||||
@@ -482,40 +529,14 @@ main.container {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.notice-item {
|
||||
.notice-empty {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 14px 0;
|
||||
border-bottom: 1px solid #f3f4f6;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.notice-item:hover {
|
||||
background: #fafbfc;
|
||||
}
|
||||
|
||||
.notice-item:hover .notice-title {
|
||||
color: var(--brand-primary);
|
||||
}
|
||||
|
||||
.notice-date {
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
font-family: ui-monospace, "Courier New", monospace;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 64px 0;
|
||||
color: #c0c6cf;
|
||||
font-size: 14px;
|
||||
color: #1f2937;
|
||||
line-height: 1.7;
|
||||
transition: color 0.2s;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* 表头: 与 notice-item 相同的 flex + gap + 列宽, 保证列对齐 */
|
||||
@@ -523,23 +544,12 @@ main.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
background: #f9fafb;
|
||||
font-size: 13px;
|
||||
padding: 14px 20px;
|
||||
border-bottom: 1px solid #eef0f3;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.notice-header-no {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.notice-header-date {
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
color: #9ca3af;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.notice-header-title {
|
||||
@@ -547,29 +557,88 @@ main.container {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.notice-header-end {
|
||||
.notice-header-date {
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
width: 130px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* 右侧截止时间: 等宽数字 + 灰色, 与日期列同宽对齐 */
|
||||
.notice-end {
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
font-family: ui-monospace, "Courier New", monospace;
|
||||
padding-top: 2px;
|
||||
.notice-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid #f3f4f6;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.notice-item-no {
|
||||
.notice-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 3px;
|
||||
height: 52%;
|
||||
border-radius: 2px;
|
||||
background: var(--brand-primary);
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.notice-item:hover {
|
||||
background: #f7f9fb;
|
||||
}
|
||||
|
||||
.notice-item:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.notice-item:hover .notice-title {
|
||||
color: var(--brand-primary);
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #1f2937;
|
||||
line-height: 1.6;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.notice-arrow {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
text-align: center;
|
||||
color: var(--brand-primary);
|
||||
opacity: 0;
|
||||
transform: translateX(-6px);
|
||||
transition: opacity 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.notice-item:hover .notice-arrow {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.notice-date {
|
||||
flex-shrink: 0;
|
||||
width: 130px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 6px;
|
||||
font-size: 12px;
|
||||
color: #9ca3af;
|
||||
font-family: ui-monospace, "Courier New", monospace;
|
||||
padding-top: 2px;
|
||||
color: #8a919c;
|
||||
}
|
||||
|
||||
.notice-date-icon {
|
||||
color: #b6bcc6;
|
||||
}
|
||||
|
||||
/* ========== 分页 ========== */
|
||||
|
||||
Reference in New Issue
Block a user