feat: OA(ecology)项目拉取 + 会议邀请函PDF/微信分享 + 参会人/执行意向增强
OA ecology: - BizEcologyController + EcologyProjectService: 项目编号搜索/详情回填, 负责人静默建档 - ComplianceLoginService: 合规/负责人登录校验 + 视图 role 匹配 - application-prod/test.yml: ecology 只读库数据源 会议邀请函/分享: - InvitationPdfService + WxShareService: 邀请函 PDF 生成 + 微信分享 - PdfViewer.vue (pdfjs-dist) + MeetingInvitation.vue: PDF 预览 + 邀请函页 参会人/执行意向: - BizMeetingAttendee*: 参会人模块增强 - BizExecutionIntent*: 执行意向增强 签到/劳务/导入: - BizSignServiceImpl + SignFill.vue: 签到劳务 - FieldMismatch/ImportMismatch: 导入校验 VO 公示/会议详情: - PublicityDetail.vue / MeetingDetail.vue 等前端增强 配置: - test 短信 mock + 供应商/招标接口切生产域名
This commit is contained in:
@@ -10,13 +10,18 @@
|
||||
<div class="new-card-title">项目信息</div>
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input v-model="form.projectName" placeholder="请输入项目名称" />
|
||||
<el-form-item label="项目编号" prop="projectNo">
|
||||
<el-select v-model="form.projectNo" placeholder="输入项目编号搜索" filterable allow-create default-first-option
|
||||
:filter-method="searchProjectNos" :loading="projectNoLoading" clearable style="width:100%"
|
||||
@change="onProjectNoChange">
|
||||
<el-option v-for="p in projectNoOptions" :key="p.projectNo"
|
||||
:label="p.projectName ? `${p.projectNo}(${p.projectName})` : p.projectNo" :value="p.projectNo" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目编号" prop="projectNo">
|
||||
<el-input v-model="form.projectNo" placeholder="请输入项目编号" />
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input v-model="form.projectName" placeholder="请输入项目名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -132,7 +137,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { bizAdd, bizUpdate, bizGet } from '@/api/public'
|
||||
import { bizAdd, bizUpdate, bizGet, searchEcologyProjects, pullEcologyProject } from '@/api/public'
|
||||
import { listExecutor, listLeaders } from '@/api/system'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import request from '@/utils/request'
|
||||
@@ -211,6 +216,61 @@ function syncProjectData() {
|
||||
ElMessage.info('同步数据:从外部数据源拉取最新项目信息 (后端支持时启用)')
|
||||
}
|
||||
|
||||
// ===== ecology 项目编号远程搜索 + 自动拉取 =====
|
||||
const projectNoOptions = ref([])
|
||||
const projectNoLoading = ref(false)
|
||||
let _projectNoTimer = null
|
||||
|
||||
// 项目编号边输入边搜索 (空关键词清空, 不发请求)
|
||||
function searchProjectNos(query) {
|
||||
if (_projectNoTimer) clearTimeout(_projectNoTimer)
|
||||
_projectNoTimer = setTimeout(async () => {
|
||||
const kw = (query || '').trim()
|
||||
if (!kw) {
|
||||
projectNoOptions.value = []
|
||||
projectNoLoading.value = false
|
||||
return
|
||||
}
|
||||
projectNoLoading.value = true
|
||||
try {
|
||||
const r = await searchEcologyProjects({ xmbh: kw })
|
||||
projectNoOptions.value = (r?.data) || []
|
||||
} catch (e) {
|
||||
projectNoOptions.value = []
|
||||
} finally {
|
||||
projectNoLoading.value = false
|
||||
}
|
||||
}, 200)
|
||||
}
|
||||
|
||||
// 选中项目编号 → 拉取完整信息并覆盖表单 (负责人静默建档由后端完成)
|
||||
async function onProjectNoChange(val) {
|
||||
if (!val) return
|
||||
// 仅当所选值来自 ecology 下拉时才拉取 (allow-create 自由输入不拉, 避免无谓请求)
|
||||
const matched = projectNoOptions.value.find(p => p.projectNo === val)
|
||||
if (!matched) return
|
||||
try {
|
||||
const res = await pullEcologyProject(val, { __silentError: true })
|
||||
const d = res?.data || res
|
||||
if (!d) return
|
||||
form.projectName = d.projectName || ''
|
||||
form.projectForm = d.projectForm || ''
|
||||
form.totalAmount = d.totalAmount != null ? Number(d.totalAmount) : 0
|
||||
form.manageFee = d.manageFee != null ? Number(d.manageFee) : 0
|
||||
form.startTime = d.startTime || ''
|
||||
form.endTime = d.endTime || ''
|
||||
if (d.leaderUserId != null) {
|
||||
form.leadUserId = d.leaderUserId
|
||||
// 把自动建档的负责人塞进 leaderOptions, 避免 el-select 选中后 label 空白
|
||||
if (!leaderOptions.value.find(u => u.userId === d.leaderUserId)) {
|
||||
leaderOptions.value = [{ userId: d.leaderUserId, nickName: d.leaderName, userName: d.leaderPhone }, ...leaderOptions.value]
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// ecology 未找到/不可达: 静默, 保留用户手填内容
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑模式:加载已有项目数据并反显到表单
|
||||
async function loadProject() {
|
||||
if (!isEdit || !projectId) return
|
||||
@@ -221,6 +281,8 @@ async function loadProject() {
|
||||
if (!p) return
|
||||
form.projectName = p.projectName || ''
|
||||
form.projectNo = p.projectNo || ''
|
||||
// 编辑模式: 项目编号 select 预置当前项, 避免远程搜索 select 无选项时 label 空白
|
||||
if (form.projectNo) projectNoOptions.value = [{ projectNo: form.projectNo, projectName: form.projectName }]
|
||||
form.projectForm = p.projectForm || ''
|
||||
form.totalSessions = p.totalSessions || 0
|
||||
form.totalAmount = p.totalAmount || 0
|
||||
@@ -293,7 +355,9 @@ onMounted(() => {
|
||||
})
|
||||
function goBack() {
|
||||
// 带 _t 强制 Projects.vue watch 触发 reload, 即便路由一样也重载
|
||||
router.push({ path: '/manager/projects', query: { _t: Date.now() } })
|
||||
// 本页被 admin/manager 复用, 按当前路由前缀回各自项目列表 (否则 admin 会被角色守卫拦回工作台)
|
||||
const base = '/' + route.path.split('/')[1]
|
||||
router.push({ path: `${base}/projects`, query: { _t: Date.now() } })
|
||||
}
|
||||
function confirmCancel() {
|
||||
ElMessageBox.confirm(`确定取消${isEdit ? '编辑' : '新建'}项目?未保存的内容将丢失`, '提示', { type: 'warning' })
|
||||
|
||||
Reference in New Issue
Block a user