|
|
@@ -1,244 +1,593 @@
|
|
|
<template>
|
|
|
<div class="app-container">
|
|
|
- <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="80px">
|
|
|
- <el-form-item label="项目名称" prop="projectName">
|
|
|
- <el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="填报月份" prop="month">
|
|
|
- <el-date-picker v-model="queryParams.month" type="month" value-format="YYYY-MM" placeholder="请选择月份" clearable style="width: 200px" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="审核状态" prop="reviewStatus">
|
|
|
- <el-select v-model="queryParams.reviewStatus" placeholder="审核状态" clearable style="width: 200px">
|
|
|
- <el-option label="待提交" value="DRAFT" />
|
|
|
- <el-option label="已提交待审核" value="SUBMITTED" />
|
|
|
- <el-option label="审核通过" value="APPROVED" />
|
|
|
- <el-option label="审核不通过" value="REJECTED" />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item>
|
|
|
- <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
|
|
- <el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
-
|
|
|
- <el-row :gutter="10" class="mb8">
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="primary" plain icon="Edit" @click="handleAdd" v-hasPermi="['performance:output:add']">填报产值</el-button>
|
|
|
- </el-col>
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="success" plain icon="Upload" :disabled="multiple" @click="handleBatchSubmit" v-hasPermi="['performance:output:submit']">批量提交</el-button>
|
|
|
- </el-col>
|
|
|
- <el-col :span="1.5">
|
|
|
- <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['performance:output:export']">导出</el-button>
|
|
|
- </el-col>
|
|
|
- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
|
|
- </el-row>
|
|
|
-
|
|
|
- <el-table v-loading="loading" :data="outputList" @selection-change="handleSelectionChange">
|
|
|
- <el-table-column type="selection" width="50" align="center" />
|
|
|
- <el-table-column label="项目名称" align="center" prop="projectName" :show-overflow-tooltip="true" />
|
|
|
- <el-table-column label="填报月份" align="center" prop="month" />
|
|
|
- <el-table-column label="当月进度(%)" align="center" prop="currentProgress" />
|
|
|
- <el-table-column label="当月产值(万元)" align="center" prop="currentOutput" />
|
|
|
- <el-table-column label="协作产值(万元)" align="center" prop="coopOutput" />
|
|
|
- <el-table-column label="审核状态" align="center" prop="reviewStatus">
|
|
|
- <template #default="scope">
|
|
|
- <dict-tag :options="reviewStatusOptions" :value="scope.row.reviewStatus" />
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="操作" align="center" width="150" class-name="small-padding fixed-width">
|
|
|
- <template #default="scope">
|
|
|
- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-if="scope.row.reviewStatus === 'DRAFT'" v-hasPermi="['performance:output:edit']">修改</el-button>
|
|
|
- <el-button link type="primary" icon="Upload" @click="handleSubmit(scope.row)" v-if="scope.row.reviewStatus === 'DRAFT'" v-hasPermi="['performance:output:submit']">提交</el-button>
|
|
|
- <el-button link type="primary" icon="View" @click="handleDetail(scope.row)">详情</el-button>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
|
|
-
|
|
|
- <!-- 产值填报对话框 -->
|
|
|
- <el-dialog :title="title" v-model="open" width="650px" append-to-body>
|
|
|
- <el-form :model="form" :rules="rules" ref="outputRef" label-width="140px">
|
|
|
- <el-form-item label="项目" prop="projectId">
|
|
|
- <el-select v-model="form.projectId" placeholder="请选择项目" :disabled="form.outputId !== undefined" style="width: 100%">
|
|
|
- <el-option v-for="item in projectOptions" :key="item.projectId" :label="item.projectName" :value="item.projectId" />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
+ <!-- 填报截止倒计时 -->
|
|
|
+ <el-alert :title="deadlineMessage" :type="deadlineType" :closable="false" show-icon class="mb16">
|
|
|
+ <template v-if="isOverdue">
|
|
|
+ <span style="font-weight: bold">当前月份已超过填报截止日期(12日),系统将视为本月该部门无产值。</span>
|
|
|
+ </template>
|
|
|
+ </el-alert>
|
|
|
+
|
|
|
+ <!-- 双Tab切换 -->
|
|
|
+ <el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
|
|
+ <!-- Tab 1: 待填报项目 -->
|
|
|
+ <el-tab-pane label="待填报项目" name="pending">
|
|
|
+ <el-row :gutter="10" class="mb8">
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" plain icon="Edit" @click="handleBatchAdd" :disabled="selectCount === 0" v-hasPermi="['performance:output:add']">
|
|
|
+ 批量填报 ({{ selectCount }})
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="success" plain icon="Upload" @click="handleBatchSubmit" :disabled="draftCount === 0" v-hasPermi="['performance:output:submit']">
|
|
|
+ 批量提交草稿 ({{ draftCount }})
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button text @click="toggleAllSelect">
|
|
|
+ {{ allSelected ? '取消全选' : '全选未填项目' }}
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-table v-loading="loading" :data="pendingProjects" @selection-change="handlePendingSelection" ref="pendingTableRef">
|
|
|
+ <el-table-column type="selection" width="50" align="center" />
|
|
|
+ <el-table-column label="项目名称" align="center" prop="projectName" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="项目类型" align="center" prop="projectType" width="100">
|
|
|
+ <template #default="scope">{{ typeMap[scope.row.projectType] || scope.row.projectType }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="项目状态" align="center" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <ReviewStatusTag :status="scope.row.status" :options="projectStatusOptions" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="总产值得(万元)" align="center" prop="totalOutput" width="120" />
|
|
|
+ <el-table-column label="已填报产值(万元)" align="center" prop="filledOutput" width="120" />
|
|
|
+ <el-table-column label="剩余产值(万元)" align="center" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <span :style="{ color: (scope.row.totalOutput - scope.row.filledOutput) > 0 ? '#67C23A' : '#F56C6C' }">
|
|
|
+ {{ ((scope.row.totalOutput || 0) - (scope.row.filledOutput || 0)).toFixed(4) }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="协作部门" align="center" width="140">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag v-if="scope.row.coopDeptName" type="warning" effect="plain" size="small">
|
|
|
+ {{ scope.row.coopDeptName }}
|
|
|
+ </el-tag>
|
|
|
+ <span v-else>无</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="草稿" align="center" width="60">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag v-if="scope.row.draftId" type="info" size="small">有</el-tag>
|
|
|
+ <span v-else style="color: #C0C4CC">--</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" align="center" width="150" class-name="small-padding fixed-width">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button link type="primary" icon="Edit" @click="handleSingleAdd(scope.row)">
|
|
|
+ {{ scope.row.draftId ? '修改草稿' : '填报' }}
|
|
|
+ </el-button>
|
|
|
+ <el-button link type="success" icon="Upload" @click="handleSubmitSingle(scope.row)" v-if="scope.row.draftId">
|
|
|
+ 提交
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <!-- Tab 2: 填报历史 -->
|
|
|
+ <el-tab-pane label="填报历史" name="history">
|
|
|
+ <el-form :model="historyParams" ref="historyRef" :inline="true" v-show="showSearch" label-width="80px">
|
|
|
+ <el-form-item label="项目名称" prop="projectName">
|
|
|
+ <el-input v-model="historyParams.projectName" placeholder="请输入项目名称" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="填报月份" prop="month">
|
|
|
+ <el-date-picker v-model="historyParams.month" type="month" value-format="YYYY-MM" placeholder="请选择月份" clearable style="width: 200px" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="审核状态" prop="reviewStatus">
|
|
|
+ <el-select v-model="historyParams.reviewStatus" placeholder="审核状态" clearable style="width: 200px">
|
|
|
+ <el-option v-for="dict in reviewStatusOptions" :key="dict.value" :label="dict.label" :value="dict.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
|
|
+ <el-button icon="Refresh" @click="resetHistoryQuery">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <el-row :gutter="10" class="mb8">
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['performance:output:export']">导出</el-button>
|
|
|
+ </el-col>
|
|
|
+ <right-toolbar v-model:showSearch="showSearch" @queryTable="getHistoryList"></right-toolbar>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-table v-loading="historyLoading" :data="historyList">
|
|
|
+ <el-table-column label="项目名称" align="center" prop="projectName" :show-overflow-tooltip="true" />
|
|
|
+ <el-table-column label="填报月份" align="center" prop="month" width="120" />
|
|
|
+ <el-table-column label="当月进度(%)" align="center" prop="currentProgress" width="110" />
|
|
|
+ <el-table-column label="当月产值(万元)" align="center" prop="currentOutput" width="130" />
|
|
|
+ <el-table-column label="协作产值(万元)" align="center" prop="coopOutput" width="130" />
|
|
|
+ <el-table-column label="审核状态" align="center" prop="reviewStatus" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <ReviewStatusTag :status="scope.row.reviewStatus" :options="reviewStatusTagOptions" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="审核意见" align="center" prop="reviewComment" :show-overflow-tooltip="true" width="150" />
|
|
|
+ <el-table-column label="填报时间" align="center" prop="createTime" width="160">
|
|
|
+ <template #default="scope">{{ parseTime(scope.row.createTime) }}</template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" align="center" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button link type="primary" icon="View" @click="handleViewDetail(scope.row)">详情</el-button>
|
|
|
+ <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-if="scope.row.reviewStatus === 'DRAFT'" v-hasPermi="['performance:output:edit']">修改</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <pagination v-show="historyTotal > 0" :total="historyTotal" v-model:page="historyParams.pageNum" v-model:limit="historyParams.pageSize" @pagination="getHistoryList" />
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+
|
|
|
+ <!-- 批量填报对话框 -->
|
|
|
+ <el-dialog title="批量产值填报" v-model="batchOpen" width="700px" append-to-body @close="cancelBatch">
|
|
|
+ <el-alert title="提示" type="info" :closable="false" show-icon style="margin-bottom: 16px">
|
|
|
+ 已选择 {{ selectedProjects.length }} 个项目进行批量填报。以下字段将应用于所有选中的项目。
|
|
|
+ </el-alert>
|
|
|
+ <el-form :model="batchForm" ref="batchRef" label-width="140px">
|
|
|
<el-form-item label="填报月份" prop="month">
|
|
|
- <el-date-picker v-model="form.month" type="month" value-format="YYYY-MM" placeholder="请选择月份" :disabled="form.outputId !== undefined" style="width: 100%" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="当月实际进度(%)" prop="currentProgress">
|
|
|
- <el-input-number v-model="form.currentProgress" :precision="1" :min="0" :max="100" placeholder="请输入当月实际进度" style="width: 100%" />
|
|
|
+ <el-date-picker v-model="batchForm.month" type="month" value-format="YYYY-MM" placeholder="请选择填报月份" style="width: 100%" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="当月实际产值(万元)" prop="currentOutput">
|
|
|
- <el-input-number v-model="form.currentOutput" :precision="4" :min="0" placeholder="请输入当月实际产值" style="width: 100%" />
|
|
|
+ <el-form-item label="统一进度(%)" prop="currentProgress">
|
|
|
+ <el-slider v-model="batchForm.currentProgress" :min="0" :max="100" :step="0.5" show-input style="width: 100%" />
|
|
|
</el-form-item>
|
|
|
<el-form-item label="进度说明" prop="description">
|
|
|
- <el-input v-model="form.description" type="textarea" placeholder="请输入进度说明" maxlength="500" />
|
|
|
+ <el-input v-model="batchForm.description" type="textarea" :rows="3" placeholder="统一进度说明(可选)" maxlength="500" />
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
+ <el-divider content-position="left">各项目产值明细</el-divider>
|
|
|
+ <el-table :data="selectedProjects" border max-height="300">
|
|
|
+ <el-table-column label="项目名称" prop="projectName" :show-overflow-tooltip="true" width="180" />
|
|
|
+ <el-table-column label="剩余产值(万元)" prop="remainingOutput" width="130">
|
|
|
+ <template #default="scope">
|
|
|
+ <span>{{ ((scope.row.totalOutput || 0) - (scope.row.filledOutput || 0)).toFixed(4) }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="当月产值(万元)" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-input-number v-model="batchOutputs[scope.row.projectId]" :precision="4" :min="0" :max="Math.max(0, (scope.row.totalOutput || 0) - (scope.row.filledOutput || 0))" size="small" style="width: 130px" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
<template #footer>
|
|
|
<div class="dialog-footer">
|
|
|
- <el-button type="primary" @click="submitForm">保 存</el-button>
|
|
|
- <el-button @click="cancel">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="submitBatchSave">保存草稿</el-button>
|
|
|
+ <el-button type="success" @click="submitBatchAndSubmit">保存并提交</el-button>
|
|
|
+ <el-button @click="batchOpen = false">取 消</el-button>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
+
|
|
|
+ <!-- 单个填报对话框 -->
|
|
|
+ <el-dialog :title="singleTitle" v-model="singleOpen" width="650px" append-to-body @close="cancelSingle">
|
|
|
+ <OutputForm
|
|
|
+ ref="outputFormRef"
|
|
|
+ v-model="singleForm"
|
|
|
+ :projectOptions="availableProjects"
|
|
|
+ :disabled="!!singleForm.outputId"
|
|
|
+ :showCooperation="currentProjectHasCooperation"
|
|
|
+ :projectTotalOutput="projectTotalOutputLimit"
|
|
|
+ />
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="submitSingleSave">保存草稿</el-button>
|
|
|
+ <el-button type="success" @click="submitSingleAndSubmit" :disabled="isOverdue">提交审核</el-button>
|
|
|
+ <el-button @click="singleOpen = false">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 填报详情对话框 -->
|
|
|
+ <el-dialog title="填报详情" v-model="detailOpen" width="550px" append-to-body>
|
|
|
+ <el-descriptions :column="1" border>
|
|
|
+ <el-descriptions-item label="项目名称">{{ detailData.projectName }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="填报月份">{{ detailData.month }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="当月进度(%)">{{ detailData.currentProgress }}%</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="当月产值(万元)">{{ detailData.currentOutput }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="协作产值(万元)">{{ detailData.coopOutput || '--' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="审核状态">
|
|
|
+ <ReviewStatusTag :status="detailData.reviewStatus" :options="reviewStatusTagOptions" />
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item label="审核意见">{{ detailData.reviewComment || '--' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="进度说明">{{ detailData.description || '--' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="填报时间">{{ parseTime(detailData.createTime) }}</el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup name="PerformanceOutput">
|
|
|
-import { listOutput, getOutput, addOutput, updateOutput, submitOutput } from '@/api/performance/output'
|
|
|
+import { listOutput, getOutput, addOutput, updateOutput, submitOutput, batchOutput, listCooperation } from '@/api/performance/output'
|
|
|
+import { listProject } from '@/api/performance/project'
|
|
|
+import { OutputForm, ReviewStatusTag } from '@/components/performance'
|
|
|
|
|
|
const { proxy } = getCurrentInstance()
|
|
|
|
|
|
-const reviewStatusOptions = ref([
|
|
|
+// 截止日期计算
|
|
|
+const now = new Date()
|
|
|
+const currentDay = now.getDate()
|
|
|
+const currentMonth = now.getMonth() + 1
|
|
|
+const currentYear = now.getFullYear()
|
|
|
+const isOverdue = currentDay > 12
|
|
|
+
|
|
|
+const deadlineMessage = computed(() => {
|
|
|
+ if (isOverdue) {
|
|
|
+ return `本月填报已截止(12日),当前日期 ${currentMonth}月${currentDay}日。逾期未填报视为本月该部门无产值。`
|
|
|
+ }
|
|
|
+ const remainDays = 12 - currentDay
|
|
|
+ return `月度填报进行中,距离截止日期(${currentMonth}月12日)还有 ${remainDays} 天。请在截止前完成填报并提交审核!`
|
|
|
+})
|
|
|
+
|
|
|
+const deadlineType = computed(() => isOverdue ? 'error' : currentDay >= 8 ? 'warning' : 'success')
|
|
|
+
|
|
|
+// 选项数据
|
|
|
+const projectStatusOptions = [
|
|
|
+ { label: '已完成招投标在建', value: 'BIDDING_IN_PROGRESS', tagType: 'warning' },
|
|
|
+ { label: '前期策划但未开工', value: 'PLANNING_NOT_STARTED', tagType: 'info' },
|
|
|
+ { label: '前期策划并且同步开工', value: 'PLANNING_IN_PROGRESS', tagType: '' }
|
|
|
+]
|
|
|
+
|
|
|
+const reviewStatusOptions = [
|
|
|
{ label: '待提交', value: 'DRAFT' },
|
|
|
{ label: '已提交待审核', value: 'SUBMITTED' },
|
|
|
{ label: '审核通过', value: 'APPROVED' },
|
|
|
{ label: '审核不通过', value: 'REJECTED' }
|
|
|
-])
|
|
|
+]
|
|
|
+
|
|
|
+const reviewStatusTagOptions = [
|
|
|
+ { label: '待提交', value: 'DRAFT', tagType: 'info' },
|
|
|
+ { label: '已提交待审核', value: 'SUBMITTED', tagType: 'warning' },
|
|
|
+ { label: '审核通过', value: 'APPROVED', tagType: 'success' },
|
|
|
+ { label: '审核不通过', value: 'REJECTED', tagType: 'danger' }
|
|
|
+]
|
|
|
|
|
|
-const outputList = ref([])
|
|
|
-const open = ref(false)
|
|
|
-const loading = ref(true)
|
|
|
+const typeMap = {
|
|
|
+ 'ENGINEERING': '工程项目',
|
|
|
+ 'TECHNICAL_SERVICE': '技术服务',
|
|
|
+ 'CONSULTING': '咨询服务',
|
|
|
+ 'OTHER': '其他'
|
|
|
+}
|
|
|
+
|
|
|
+// 状态变量
|
|
|
+const activeTab = ref('pending')
|
|
|
+const loading = ref(false)
|
|
|
+const historyLoading = ref(false)
|
|
|
const showSearch = ref(true)
|
|
|
-const ids = ref([])
|
|
|
-const single = ref(true)
|
|
|
-const multiple = ref(true)
|
|
|
-const total = ref(0)
|
|
|
-const title = ref('')
|
|
|
-const projectOptions = ref([])
|
|
|
-
|
|
|
-const data = reactive({
|
|
|
- form: {},
|
|
|
- queryParams: {
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 10,
|
|
|
- projectName: undefined,
|
|
|
- month: undefined,
|
|
|
- reviewStatus: undefined
|
|
|
- },
|
|
|
- rules: {
|
|
|
- projectId: [{ required: true, message: '项目不能为空', trigger: 'change' }],
|
|
|
- month: [{ required: true, message: '填报月份不能为空', trigger: 'change' }],
|
|
|
- currentProgress: [{ required: true, message: '当月实际进度不能为空', trigger: 'blur' }],
|
|
|
- currentOutput: [{ required: true, message: '当月实际产值不能为空', trigger: 'blur' }]
|
|
|
- }
|
|
|
+const selectCount = ref(0)
|
|
|
+const draftCount = ref(0)
|
|
|
+const allSelected = ref(false)
|
|
|
+const historyTotal = ref(0)
|
|
|
+
|
|
|
+const pendingProjects = ref([])
|
|
|
+const selectedProjects = ref([])
|
|
|
+const historyList = ref([])
|
|
|
+const availableProjects = ref([])
|
|
|
+
|
|
|
+const batchOpen = ref(false)
|
|
|
+const singleOpen = ref(false)
|
|
|
+const detailOpen = ref(false)
|
|
|
+
|
|
|
+const singleTitle = ref('')
|
|
|
+
|
|
|
+const batchOutputs = reactive({})
|
|
|
+
|
|
|
+const detailData = reactive({})
|
|
|
+
|
|
|
+const batchForm = reactive({
|
|
|
+ month: undefined,
|
|
|
+ currentProgress: undefined,
|
|
|
+ description: undefined
|
|
|
})
|
|
|
|
|
|
-const { queryParams, form, rules } = toRefs(data)
|
|
|
+const singleForm = reactive({
|
|
|
+ outputId: undefined,
|
|
|
+ projectId: undefined,
|
|
|
+ month: undefined,
|
|
|
+ currentProgress: undefined,
|
|
|
+ currentOutput: undefined,
|
|
|
+ coopOutput: undefined,
|
|
|
+ description: undefined
|
|
|
+})
|
|
|
+
|
|
|
+const historyParams = reactive({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ projectName: undefined,
|
|
|
+ month: undefined,
|
|
|
+ reviewStatus: undefined
|
|
|
+})
|
|
|
|
|
|
-function getList() {
|
|
|
+const outputFormRef = ref(null)
|
|
|
+
|
|
|
+const currentProject = computed(() => {
|
|
|
+ if (!singleForm.projectId) return {}
|
|
|
+ return pendingProjects.value.find(p => p.projectId === singleForm.projectId) || {}
|
|
|
+})
|
|
|
+
|
|
|
+const currentProjectHasCooperation = computed(() => !!currentProject.value.coopDeptName)
|
|
|
+
|
|
|
+const projectTotalOutputLimit = computed(() => {
|
|
|
+ const p = currentProject.value
|
|
|
+ return Math.max(0, (p.totalOutput || 0) - (p.filledOutput || 0))
|
|
|
+})
|
|
|
+
|
|
|
+// 加载待填报项目
|
|
|
+function getPendingProjects() {
|
|
|
loading.value = true
|
|
|
- listOutput(queryParams.value).then(res => {
|
|
|
- outputList.value = res.rows
|
|
|
- total.value = res.total
|
|
|
+ listProject({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 999,
|
|
|
+ status: 'BIDDING_IN_PROGRESS,PLANNING_IN_PROGRESS,PLANNING_NOT_STARTED',
|
|
|
+ myDept: true
|
|
|
+ }).then(res => {
|
|
|
+ pendingProjects.value = (res.rows || []).map(p => {
|
|
|
+ const remaining = Math.max(0, (p.totalOutput || 0) - (p.filledOutput || 0))
|
|
|
+ return {
|
|
|
+ ...p,
|
|
|
+ remainingOutput: remaining,
|
|
|
+ hasCooperation: !!p.coopDeptName
|
|
|
+ }
|
|
|
+ })
|
|
|
loading.value = false
|
|
|
+ availableProjects.value = pendingProjects.value.map(p => ({
|
|
|
+ projectId: p.projectId,
|
|
|
+ projectName: p.projectName,
|
|
|
+ deptName: p.deptName,
|
|
|
+ totalOutput: p.totalOutput
|
|
|
+ }))
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 加载填报历史
|
|
|
+function getHistoryList() {
|
|
|
+ historyLoading.value = true
|
|
|
+ listOutput(historyParams).then(res => {
|
|
|
+ historyList.value = res.rows
|
|
|
+ historyTotal.value = res.total
|
|
|
+ historyLoading.value = false
|
|
|
})
|
|
|
}
|
|
|
|
|
|
function handleQuery() {
|
|
|
- queryParams.value.pageNum = 1
|
|
|
- getList()
|
|
|
+ historyParams.pageNum = 1
|
|
|
+ getHistoryList()
|
|
|
}
|
|
|
|
|
|
-function resetQuery() {
|
|
|
- proxy.resetForm('queryRef')
|
|
|
+function resetHistoryQuery() {
|
|
|
+ proxy.resetForm('historyRef')
|
|
|
handleQuery()
|
|
|
}
|
|
|
|
|
|
-function handleSelectionChange(selection) {
|
|
|
- ids.value = selection.map(item => item.outputId)
|
|
|
- single.value = selection.length !== 1
|
|
|
- multiple.value = !selection.length
|
|
|
+function handleTabChange(tab) {
|
|
|
+ if (tab === 'history') {
|
|
|
+ getHistoryList()
|
|
|
+ } else {
|
|
|
+ getPendingProjects()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-function reset() {
|
|
|
- form.value = {
|
|
|
- outputId: undefined,
|
|
|
- projectId: undefined,
|
|
|
- month: undefined,
|
|
|
- currentProgress: undefined,
|
|
|
- currentOutput: undefined,
|
|
|
- description: undefined
|
|
|
+// 选择操作
|
|
|
+function handlePendingSelection(selection) {
|
|
|
+ selectedProjects.value = selection
|
|
|
+ selectCount.value = selection.length
|
|
|
+ draftCount.value = selection.filter(item => item.draftId).length
|
|
|
+
|
|
|
+ // 初始化批量产值
|
|
|
+ selection.forEach(p => {
|
|
|
+ if (!(p.projectId in batchOutputs)) {
|
|
|
+ batchOutputs[p.projectId] = undefined
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function toggleAllSelect() {
|
|
|
+ allSelected.value = !allSelected.value
|
|
|
+ const tableRef = proxy.$refs.pendingTableRef
|
|
|
+ if (allSelected.value) {
|
|
|
+ const unfilled = pendingProjects.value.filter(p => {
|
|
|
+ const remaining = (p.totalOutput || 0) - (p.filledOutput || 0)
|
|
|
+ return remaining > 0
|
|
|
+ })
|
|
|
+ unfilled.forEach(row => tableRef.toggleRowSelection(row, true))
|
|
|
+ } else {
|
|
|
+ tableRef.clearSelection()
|
|
|
}
|
|
|
- proxy.resetForm('outputRef')
|
|
|
}
|
|
|
|
|
|
-function cancel() {
|
|
|
- open.value = false
|
|
|
- reset()
|
|
|
+// 批量填报
|
|
|
+function handleBatchAdd() {
|
|
|
+ if (selectedProjects.value.length === 0) {
|
|
|
+ proxy.$modal.msgWarning('请至少选择一个项目')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 验证选中的项目都有剩余产值
|
|
|
+ const invalid = selectedProjects.value.filter(p => {
|
|
|
+ const remaining = (p.totalOutput || 0) - (p.filledOutput || 0)
|
|
|
+ return remaining <= 0
|
|
|
+ })
|
|
|
+ if (invalid.length > 0) {
|
|
|
+ proxy.$modal.msgWarning(`以下项目已无剩余产值: ${invalid.map(p => p.projectName).join('、')}`)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ batchForm.month = `${currentYear}-${String(currentMonth).padStart(2, '0')}`
|
|
|
+ batchForm.currentProgress = undefined
|
|
|
+ batchForm.description = undefined
|
|
|
+ batchOpen.value = true
|
|
|
}
|
|
|
|
|
|
-function handleAdd() {
|
|
|
- reset()
|
|
|
- open.value = true
|
|
|
- title.value = '产值填报'
|
|
|
+function cancelBatch() {
|
|
|
+ batchOpen.value = false
|
|
|
}
|
|
|
|
|
|
-function handleUpdate(row) {
|
|
|
- reset()
|
|
|
- getOutput(row.outputId).then(res => {
|
|
|
- form.value = res.data
|
|
|
- open.value = true
|
|
|
- title.value = '修改产值填报'
|
|
|
+function buildBatchOutputData(submitNow) {
|
|
|
+ return selectedProjects.value.map(p => ({
|
|
|
+ projectId: p.projectId,
|
|
|
+ month: batchForm.month,
|
|
|
+ currentProgress: batchForm.currentProgress,
|
|
|
+ currentOutput: batchOutputs[p.projectId],
|
|
|
+ description: batchForm.description,
|
|
|
+ submitNow
|
|
|
+ }))
|
|
|
+}
|
|
|
+
|
|
|
+function submitBatchSave() {
|
|
|
+ if (!batchForm.month) {
|
|
|
+ proxy.$modal.msgWarning('请选择填报月份')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const batchData = buildBatchOutputData(false)
|
|
|
+ const invalid = batchData.filter(d => d.currentOutput == null || d.currentOutput < 0)
|
|
|
+ if (invalid.length > 0) {
|
|
|
+ proxy.$modal.msgWarning('请为所有项目填写当月产值')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ batchOutput({ records: batchData }).then(() => {
|
|
|
+ proxy.$modal.msgSuccess('批量保存草稿成功')
|
|
|
+ batchOpen.value = false
|
|
|
+ getPendingProjects()
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-function handleDetail(row) {
|
|
|
- // TODO: 查看填报详情
|
|
|
+function submitBatchAndSubmit() {
|
|
|
+ if (!batchForm.month) {
|
|
|
+ proxy.$modal.msgWarning('请选择填报月份')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const batchData = buildBatchOutputData(true)
|
|
|
+ const invalid = batchData.filter(d => d.currentOutput == null || d.currentOutput < 0)
|
|
|
+ if (invalid.length > 0) {
|
|
|
+ proxy.$modal.msgWarning('请为所有项目填写当月产值')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (isOverdue) {
|
|
|
+ proxy.$modal.confirm('当前已超过填报截止日期,确认仍要提交?提交后将进入审核流程。').then(() => {
|
|
|
+ return batchOutput({ records: batchData })
|
|
|
+ }).then(() => {
|
|
|
+ proxy.$modal.msgSuccess('批量提交成功')
|
|
|
+ batchOpen.value = false
|
|
|
+ getPendingProjects()
|
|
|
+ }).catch(() => {})
|
|
|
+ return
|
|
|
+ }
|
|
|
+ batchOutput({ records: batchData }).then(() => {
|
|
|
+ proxy.$modal.msgSuccess('批量提交成功')
|
|
|
+ batchOpen.value = false
|
|
|
+ getPendingProjects()
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 单个填报
|
|
|
+function handleSingleAdd(row) {
|
|
|
+ singleForm.outputId = row.draftId || undefined
|
|
|
+ singleForm.projectId = row.projectId
|
|
|
+ singleForm.month = row.draftMonth || `${currentYear}-${String(currentMonth).padStart(2, '0')}`
|
|
|
+ singleForm.currentProgress = row.draftProgress || undefined
|
|
|
+ singleForm.currentOutput = row.draftOutput || undefined
|
|
|
+ singleForm.coopOutput = row.draftCoopOutput || undefined
|
|
|
+ singleForm.description = row.draftDescription || undefined
|
|
|
+ singleTitle.value = row.draftId ? '修改产值草稿' : '产值填报'
|
|
|
+ singleOpen.value = true
|
|
|
+}
|
|
|
+
|
|
|
+function cancelSingle() {
|
|
|
+ singleOpen.value = false
|
|
|
+}
|
|
|
+
|
|
|
+function submitSingleSave() {
|
|
|
+ outputFormRef.value?.validate().then(valid => {
|
|
|
+ if (!valid) return
|
|
|
+ const data = { ...singleForm }
|
|
|
+ if (singleForm.outputId) {
|
|
|
+ updateOutput(data).then(() => {
|
|
|
+ proxy.$modal.msgSuccess('草稿已保存')
|
|
|
+ singleOpen.value = false
|
|
|
+ getPendingProjects()
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ addOutput(data).then(() => {
|
|
|
+ proxy.$modal.msgSuccess('草稿已保存')
|
|
|
+ singleOpen.value = false
|
|
|
+ getPendingProjects()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function submitSingleAndSubmit() {
|
|
|
+ outputFormRef.value?.validate().then(valid => {
|
|
|
+ if (!valid) return
|
|
|
+ const data = { ...singleForm }
|
|
|
+ const api = singleForm.outputId ? updateOutput : addOutput
|
|
|
+ api(data).then(() => {
|
|
|
+ return submitOutput(singleForm.outputId || data.outputId)
|
|
|
+ }).then(() => {
|
|
|
+ proxy.$modal.msgSuccess('已提交审核')
|
|
|
+ singleOpen.value = false
|
|
|
+ getPendingProjects()
|
|
|
+ })
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
-function handleSubmit(row) {
|
|
|
- proxy.$modal.confirm('确认提交该条产值填报?提交后将无法修改。').then(() => {
|
|
|
- return submitOutput(row.outputId)
|
|
|
+function handleSubmitSingle(row) {
|
|
|
+ if (!row.draftId) return
|
|
|
+ proxy.$modal.confirm('确认提交该草稿?提交后将进入审核流程。').then(() => {
|
|
|
+ return submitOutput(row.draftId)
|
|
|
}).then(() => {
|
|
|
proxy.$modal.msgSuccess('提交成功')
|
|
|
- getList()
|
|
|
+ getPendingProjects()
|
|
|
}).catch(() => {})
|
|
|
}
|
|
|
|
|
|
function handleBatchSubmit() {
|
|
|
- if (ids.value.length === 0) {
|
|
|
- proxy.$modal.msgWarning('请选择要提交的填报记录')
|
|
|
+ if (draftCount.value === 0) {
|
|
|
+ proxy.$modal.msgWarning('没有可提交的草稿')
|
|
|
return
|
|
|
}
|
|
|
- proxy.$modal.confirm('确认批量提交选中的产值填报?').then(() => {
|
|
|
- const tasks = ids.value.map(id => submitOutput(id))
|
|
|
+ proxy.$modal.confirm(`确认批量提交 ${draftCount.value} 条草稿?`).then(() => {
|
|
|
+ const tasks = selectedProjects.value.filter(p => p.draftId).map(p => submitOutput(p.draftId))
|
|
|
return Promise.all(tasks)
|
|
|
}).then(() => {
|
|
|
proxy.$modal.msgSuccess('批量提交成功')
|
|
|
- getList()
|
|
|
+ getPendingProjects()
|
|
|
}).catch(() => {})
|
|
|
}
|
|
|
|
|
|
-function handleExport() {
|
|
|
- proxy.download('/performance/output/export', { ...queryParams.value }, `output_${new Date().getTime()}.xlsx`)
|
|
|
-}
|
|
|
-
|
|
|
-function submitForm() {
|
|
|
- proxy.$refs.outputRef.validate(valid => {
|
|
|
- if (valid) {
|
|
|
- if (form.value.outputId) {
|
|
|
- updateOutput(form.value).then(() => {
|
|
|
- proxy.$modal.msgSuccess('修改成功')
|
|
|
- open.value = false
|
|
|
- getList()
|
|
|
- })
|
|
|
- } else {
|
|
|
- addOutput(form.value).then(() => {
|
|
|
- proxy.$modal.msgSuccess('填报成功')
|
|
|
- open.value = false
|
|
|
- getList()
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
+// 历史操作
|
|
|
+function handleUpdate(row) {
|
|
|
+ getOutput(row.outputId).then(res => {
|
|
|
+ Object.assign(singleForm, res.data)
|
|
|
+ singleTitle.value = '修改产值填报'
|
|
|
+ singleOpen.value = true
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+function handleViewDetail(row) {
|
|
|
+ Object.assign(detailData, row)
|
|
|
+ detailOpen.value = true
|
|
|
+}
|
|
|
+
|
|
|
+function handleExport() {
|
|
|
+ proxy.download('/performance/output/export', { ...historyParams }, `output_${new Date().getTime()}.xlsx`)
|
|
|
+}
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
- getList()
|
|
|
+ getPendingProjects()
|
|
|
})
|
|
|
</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.mb16 {
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+</style>
|