feat: 会议批量审核 + 公示按发布时间倒序 + 现场照片 dialog 预览 + 重复报错精确

- 会议列表 manager 批量合规审核 (批量通过/退回, best-effort 逐条回执)
- 公示列表按 publish_time 倒序, 发布/开通写本地 publish_time (修 toISOString UTC 时区 bug)
- 签到表/前全景/后全景「查看照片」改 dialog 预览 (复用 Preview.vue)
- 手机号/用户名重复报错精确提示 (后端 fieldMap + 前端 duplicateTip)
- 医生首页欢迎语改「欢迎使用合规系统」
This commit is contained in:
郭庆泰
2026-08-26 00:41:33 +08:00
parent ea2024d083
commit b5b3e3a213
15 changed files with 387 additions and 115 deletions
+16 -3
View File
@@ -21,11 +21,14 @@
<el-button type="primary" size="small" :disabled="readonly" @click="openDialog">
<el-icon><CameraFilled /></el-icon>&nbsp;扫码拍照
</el-button>
<a v-if="modelValue" :href="modelValue" target="_blank" class="cam-link">查看照片</a>
<el-button v-if="modelValue" link type="primary" size="small" @click="openPreview">查看照片</el-button>
<span v-else class="cam-empty">未上传</span>
<span v-if="polling" class="cam-polling">等待手机回传</span>
</div>
<!-- 照片预览: 复用全局 Preview.vue (dialog 内预览, 图片/PDF 自适应, 非新窗口) -->
<Preview v-model="previewOpen" :url="previewUrl" :title="previewTitle" />
<el-dialog
v-model="visible"
:title="`扫码拍照 - ${label}`"
@@ -52,6 +55,7 @@ import request from '@/utils/request'
import { ElMessage } from 'element-plus'
import { CameraFilled } from '@element-plus/icons-vue'
import QRCode from 'qrcode'
import Preview from '@/components/Preview.vue'
const props = defineProps({
modelValue: { type: String, default: '' },
@@ -73,6 +77,9 @@ const visible = ref(false)
const qrUrl = ref('')
const qrLoading = ref(false)
const polling = ref(false)
const previewOpen = ref(false)
const previewUrl = ref('')
const previewTitle = ref('')
let pollTimer = null
let baseline = ''
@@ -142,6 +149,14 @@ function onClosed() {
stopPolling()
}
/** 打开照片预览 dialog (复用全局 Preview.vue, 图片/PDF 自适应) */
function openPreview() {
if (!props.modelValue) return
previewUrl.value = props.modelValue
previewTitle.value = props.label
previewOpen.value = true
}
onBeforeUnmount(stopPolling)
</script>
@@ -151,8 +166,6 @@ onBeforeUnmount(stopPolling)
display: flex; align-items: center; gap: 12px;
min-height: 36px;
}
.cam-link { color: var(--brand-primary); text-decoration: none; font-size: 13px; }
.cam-link:hover { text-decoration: underline; }
.cam-empty { color: #c0c4cc; font-size: 13px; }
.cam-polling { color: #e6a23c; font-size: 12px; }