chore: biz_org 合并 / BizProject 重构 / 各角色页面调整 (上次重构遗留)

涵盖改动范围:
- 后端 BizOrg / BizProject / BizProjectRating / BizSpecialPlan controller + domain + mapper + service
- 前端 admin (BizSpecialPlanAdmin, ProjectCategory) / executor / leader / manager / sponsor 多页调整
- api/dict.js + AdminLayout.vue 同步
This commit is contained in:
郭庆泰
2026-08-18 00:30:34 +08:00
parent c9fc6ebdb8
commit b52a334184
32 changed files with 744 additions and 454 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ async function loadStats() {
try {
const ps = await bizList('project', { pageNum: 1, pageSize: 1 })
stats.value.totalProjects = ps.total || 0
const settled = await bizList('project', { isSettled: '1', pageNum: 1, pageSize: 1 })
const settled = await bizList('project', { isSettled: 'Y', pageNum: 1, pageSize: 1 })
stats.value.settledProjects = settled.total || 0
const finished = await bizList('project', { isFinished: '1', pageNum: 1, pageSize: 1 })
stats.value.finishedProjects = finished.total || 0
+25 -68
View File
@@ -25,7 +25,6 @@
<!-- ========== 批量按钮 ( People.vue 风格一致) ========== -->
<div class="batch-bar">
<el-button type="primary" :disabled="!selected.length" @click="onAssign">项目分配</el-button>
<el-button type="primary" :disabled="!selected.length" @click="onBatchRate">批量评价</el-button>
<span class="filter-tip">已选 {{ selected.length }} </span>
</div>
@@ -35,12 +34,12 @@
<el-table-column prop="projectNo" label="项目编号" width="120" />
<el-table-column prop="projectName" label="项目名称" min-width="200" show-overflow-tooltip />
<el-table-column label="总场次/总期数" width="110" align="center">
<template #default="{ row }">{{ row.totalSessions || 0 }}/{{ row.totalPeriods || 0 }}</template>
<template #default="{ row }">{{ row.assignedSessions || 0 }}/{{ row.assignedSessions || 0 }}</template>
</el-table-column>
<el-table-column prop="doneSessions" label="已执行" width="80" align="center" />
<el-table-column prop="todoSessions" label="未执行" width="80" align="center" />
<el-table-column label="总金额" width="120" align="right">
<template #default="{ row }">¥ {{ formatNum(row.totalAmount) }}</template>
<template #default="{ row }">¥ {{ formatNum(row.assignedAmount) }}</template>
</el-table-column>
<el-table-column label="可用金额" width="120" align="right">
<template #default="{ row }">¥ {{ formatNum(row.availableAmount) }}</template>
@@ -51,9 +50,16 @@
<el-table-column label="已支付会务费" width="120" align="right">
<template #default="{ row }">¥ {{ formatNum(row.paidMeetingAmount) }}</template>
</el-table-column>
<el-table-column label="执行单位评价(支持方)" width="180" align="center">
<el-table-column prop="managerScore" label="执行单位得分(合规)" width="140" align="center">
<template #default="{ row }">
<el-rate v-model="row.ratingScore" disabled show-score :max="5" />
<span v-if="row.managerScore != null">{{ row.managerScore }}</span>
<span v-else style="color:#c0c4cc">-</span>
</template>
</el-table-column>
<el-table-column prop="sponsorScore" label="执行单位得分(支持)" width="140" align="center">
<template #default="{ row }">
<span v-if="row.sponsorScore != null">{{ row.sponsorScore }}</span>
<span v-else style="color:#c0c4cc">-</span>
</template>
</el-table-column>
<el-table-column prop="isFinished" label="是否结题" width="100" align="center">
@@ -65,11 +71,10 @@
</el-table-column>
<el-table-column prop="startTime" label="项目开始时间" width="150" />
<el-table-column prop="endTime" label="项目结束时间" width="150" />
<el-table-column label="操作" width="220" fixed="right">
<el-table-column label="操作" width="180" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click="viewDetail(row)">查看</el-button>
<el-button link type="primary" @click="onAssign(row)">分配</el-button>
<el-button link type="primary" @click="onRate(row)">项目评价</el-button>
</template>
</el-table-column>
</el-table>
@@ -97,27 +102,7 @@
</template>
</el-dialog>
<!-- 批量评价 弹窗 -->
<el-dialog v-model="rateOpen" :title="rateRow ? '项目评价' : '批量评价'" width="520px">
<el-form label-width="100px">
<el-form-item v-if="rateRow" label="项目名称">
<span>{{ rateRow.projectName }}</span>
</el-form-item>
<el-form-item v-else label="已选项目">
<span>{{ selected.length }} </span>
</el-form-item>
<el-form-item label="评分">
<el-rate v-model="rateForm.score" :max="5" show-text />
</el-form-item>
<el-form-item label="评价说明">
<el-input v-model="rateForm.comment" type="textarea" :rows="3" placeholder="请输入评价说明" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="rateOpen=false">取消</el-button>
<el-button type="primary" @click="onSaveRate">确定</el-button>
</template>
</el-dialog>
<!-- 评分弹窗已移除: executor 不可评分 -->
<el-dialog v-model="detailOpen" title="项目详情" width="720px">
<el-descriptions :column="2" border>
@@ -143,7 +128,14 @@
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { bizList, bizUpdate } from '@/api/public'
import request from '@/utils/request'
import { bizUpdate } from '@/api/public'
// executor 专属: 只查分给当前用户 (主账号 biz_org.org_id 或 子账号 exec_user_id) 的项目
async function listExecutorProjects(params) {
const { data } = await request.get('/business/project/executorList', { params })
return data || { rows: [], total: 0 }
}
const list = ref([])
const loading = ref(false)
@@ -159,10 +151,6 @@ const assignOpen = ref(false)
const assignRow = ref({})
const assignForm = reactive({ assignee: '' })
const rateOpen = ref(false)
const rateRow = ref(null)
const rateForm = reactive({ score: 5, comment: '' })
function formatNum(n) {
if (n == null) return '0.00'
return Number(n).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
@@ -176,9 +164,9 @@ async function loadList() {
params.startTime = dateRange.value[0]
params.endTime = dateRange.value[1]
}
const r = await bizList('project', params)
list.value = (r.data && r.data.rows) || r.rows || []
page.total = (r.data && r.data.total) || r.total || 0
const data = await listExecutorProjects(params)
list.value = data.rows || []
page.total = data.total || 0
} catch (e) { list.value = []; page.total = 0 }
finally { loading.value = false }
}
@@ -217,38 +205,7 @@ async function onSaveAssign() {
} catch (e) { ElMessage.error(e?.msg || '分配失败') }
}
function onRate(row) {
rateRow.value = row
rateForm.score = row?.ratingScore || 5
rateForm.comment = row?.ratingComment || ''
rateOpen.value = true
}
function onBatchRate() {
if (!selected.value.length) return
rateRow.value = null
rateForm.score = 5
rateForm.comment = ''
rateOpen.value = true
}
async function onSaveRate() {
try {
let ok = 0
const payload = { ratingScore: rateForm.score, ratingComment: rateForm.comment }
if (rateRow.value) {
await bizUpdate('project', { projectId: rateRow.value.projectId, ...payload })
ok = 1
} else {
for (const r of selected.value) {
try { await bizUpdate('project', { projectId: r.projectId, ...payload }); ok++ } catch {}
}
}
ElMessage.success(rateRow.value ? '评价成功' : `已评价 ${ok} 个项目`)
rateOpen.value = false
loadList()
} catch (e) { ElMessage.error(e?.msg || '评价失败') }
}
// 评价相关函数已移除: executor 不可评分
onMounted(() => { loadList(); loadPeople() })
</script>