主要改动: - SQL: biz_support_unit → biz_org, 加 org_type, 加 business_nature; 删 biz_execution_unit, biz_service_org - SQL: biz_project.support_unit_id/name + service_org_id/name → org_id/name/type - SQL: biz_meeting.support_unit_name → org_name - SQL: biz_person.work_unit → org_id (FK) - 后端: 新 BizOrg entity/mapper/service/controller - 后端: BizProject/BizMeeting 字段重命名 - 后端: 删 12 个 BizSupportUnit/BizExecutionUnit/BizServiceOrg Java 文件 - 后端: BizPersonImportVO.workUnit → orgName (导入时查 biz_org 取 org_id) - 后端: BizAuthController.registerExecutor 完整实现 (原 registerSupplier stub) - 前端: 新 admin/Orgs.vue + manager/Orgs.vue (原 SupportUnits) - 前端: RegisterExecutor.vue (原 RegisterSupplier, 单页 2 步) - 前端: sponsor/executor/manager 多个文件 workUnit → orgId/orgName 重命名 - 前端: 统一 supplier → executor, 业务命名 sponsor(赞助方) / executor(执行方=供应商) - 前端: 全工程 execution → executor (company type / role / person unit_type)
72 lines
2.6 KiB
Vue
72 lines
2.6 KiB
Vue
<template>
|
||
<el-dialog v-model="open" :title="title" width="780" top="6vh" :close-on-click-modal="false" destroy-on-close>
|
||
<div v-if="fileUrl" class="preview-box">
|
||
<!-- 图片 -->
|
||
<img v-if="kind === 'image'" :src="fileUrl" class="preview-img" :alt="title" />
|
||
<!-- PDF:iframe 预览,浏览器内置 viewer -->
|
||
<iframe v-else-if="kind === 'pdf'" :src="fileUrl" class="preview-iframe" />
|
||
<!-- 其它(doc/xls/zip 等):给下载链接 -->
|
||
<div v-else class="preview-fallback">
|
||
<el-icon class="fallback-icon"><Document /></el-icon>
|
||
<p>该文件类型暂不支持页内预览,请点击下方按钮下载/在新窗口打开查看。</p>
|
||
<el-button type="primary" @click="openNew">在新窗口打开</el-button>
|
||
<el-button @click="copyUrl">复制链接</el-button>
|
||
</div>
|
||
</div>
|
||
<el-empty v-else description="暂无附件" />
|
||
<template #footer>
|
||
<el-button @click="open = false">关闭</el-button>
|
||
<el-button v-if="fileUrl" type="primary" @click="openNew">在新窗口打开</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, watch } from 'vue'
|
||
import { Document } from '@element-plus/icons-vue'
|
||
import { ElMessage } from 'element-plus'
|
||
|
||
const props = defineProps({
|
||
modelValue: Boolean,
|
||
url: { type: String, default: '' },
|
||
title: { type: String, default: '附件预览' }
|
||
})
|
||
const emit = defineEmits(['update:modelValue'])
|
||
|
||
const open = computed({
|
||
get: () => props.modelValue,
|
||
set: v => emit('update:modelValue', v)
|
||
})
|
||
|
||
const fileUrl = computed(() => props.url || '')
|
||
|
||
const kind = computed(() => {
|
||
const u = fileUrl.value.split('?')[0].toLowerCase()
|
||
if (/\.(png|jpe?g|gif|webp|bmp|svg)(\?.*)?$/.test(u)) return 'image'
|
||
if (/\.pdf(\?.*)?$/.test(u)) return 'pdf'
|
||
return 'other'
|
||
})
|
||
|
||
function openNew() {
|
||
if (!fileUrl.value) return
|
||
window.open(fileUrl.value, '_blank', 'noopener')
|
||
}
|
||
async function copyUrl() {
|
||
if (!fileUrl.value) return
|
||
try {
|
||
await navigator.clipboard.writeText(fileUrl.value)
|
||
ElMessage.success('链接已复制')
|
||
} catch {
|
||
ElMessage.error('复制失败,请手动复制')
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.preview-box { display: flex; justify-content: center; align-items: flex-start; min-height: 480px; }
|
||
.preview-img { max-width: 100%; max-height: 70vh; object-fit: contain; }
|
||
.preview-iframe { width: 100%; height: 70vh; border: 1px solid #ebeef5; border-radius: 4px; }
|
||
.preview-fallback { text-align: center; padding: 48px 24px; color: #606266; }
|
||
.fallback-icon { font-size: 48px; color: #909399; margin-bottom: 12px; }
|
||
.preview-fallback p { margin: 12px 0 24px; }
|
||
</style> |