整合前端

This commit is contained in:
砂糖
2026-04-13 17:04:38 +08:00
parent 69609a2cb1
commit 5d4794c9bd
915 changed files with 144259 additions and 0 deletions

View File

@@ -0,0 +1,383 @@
<template>
<div class="app-container" v-loading="loading">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="项目名称" prop="projectId">
<project-select v-model="queryParams.projectId" placeholder="请选择项目" clearable />
<!-- <el-select v-model="queryParams.projectId" filterable placeholder="请选择">
<el-option v-for="item in projects" :key="item.projectId" :label="item.projectName" :value="item.projectId">
</el-option>
</el-select> -->
</el-form-item>
<el-form-item label="项目编号" prop="projectNum">
<el-input v-model="queryParams.projectNum" placeholder="请输入项目编号" clearable />
</el-form-item>
<el-form-item label="贸易类型" prop="tradeType">
<el-select v-model="queryParams.tradeType" placeholder="请选择项目类型" clearable>
<el-option v-for="dict in dict.type.sys_trade_type" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="项目代号" prop="projectCode">
<el-select v-model="queryParams.projectCode" placeholder="请选择代号类型" style="width: 100%" filterable
@change="handleQuery">
<el-option v-for="dict in dict.type.sys_project_code" :key="dict.value" :label="dict.label"
:value="dict.value">
<span style="float: left">{{ dict.label }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ dict.value }}</span>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="项目周期">
<el-date-picker v-model="searchTime" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']">
</el-date-picker>
</el-form-item>
<el-form-item label="负责人">
<el-select filterable allow-add v-model="queryParams.steward" @change="handleStatusChange(scope.row)">
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.nickName">
</el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="优质筛选">
<el-switch v-model="queryParams.prePay" active-text="开" active-value="0.1" inactive-value="0"
@change="selectPrePay" inactive-text="">
</el-switch>
</el-form-item> -->
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @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="el-icon-plus" size="mini" @click="handleAdd">绑定进度
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete">删除
</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-row :gutter="20">
<el-table v-loading="loading" :data="scheduleList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="代号" prop="projectCode" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.projectCode == null" type="danger"></el-tag>
<el-tag v-else>{{ scope.row.projectCode }}</el-tag>
</template>
</el-table-column>
<el-table-column label="项目名称" prop="projectName" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.prePay > 0"></span>
<span>{{ scope.row.projectName }}</span>
</template>
</el-table-column>
<el-table-column label="项目编号" prop="projectNum"></el-table-column>
<el-table-column label="负责人" align="center">
<template slot-scope="scope">
<el-select filterable allow-add v-model="scope.row.steward" @change="handleStatusChange(scope.row)">
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.nickName">
</el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="状态" align="center">
<template slot-scope="scope">
<span v-if="scope.row.isTop" style="color: #ff4d4f;">重点关注</span>
<span v-else style="">一般项目</span>
</template>
</el-table-column>
<el-table-column label="延期进度数" prop="delayCount" />
<el-table-column label="未完成进度" prop="unFinishCount" />
<el-table-column label="完成状态" align="center" prop="sortNum">
<template slot-scope="scope">
<el-select size="mini" v-model="scope.row.status" placeholder="请选择完成状态"
@change="handleStatusChange(scope.row)">
<el-option label="进行中" :value="1"></el-option>
<el-option label="已完成" :value="2"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="开始时间" align="center" prop="startTime">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleDetail(scope.row)">进度详情
</el-button>
<el-button size="mini" type="text" icon="el-icon-time" @click="handlePostpone(scope.row)">延期记录
</el-button>
<el-button size="mini" type="text" icon="el-icon-check"
v-if="scope.row.schedulePercentage === 100 && scope.row.status !== 2"
@click="handleComplete(scope.row)">完成任务
</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
</el-row>
<el-drawer title="进度详情" :visible.sync="detailDrawer" direction="btt" size="90%" :before-close="closeDetailShow">
<div style="padding:0 20px">
<project-schedule-step :scheduleId="scheduleDetail.scheduleId" :master="scheduleDetail.functionary"
:projectName="scheduleDetail.projectName" :projectStatus="scheduleDetail.projectStatus"
:isTop="scheduleDetail.isTop" :projectId="scheduleDetail.projectId" />
</div>
</el-drawer>
<FormDialog v-model="addDialog" :projects="projects" @save="handleSave" />
<el-drawer title="延期记录" :visible.sync="postponeDrawer" direction="btt" size="90%">
<postpone :scheduleId="scheduleDetail.scheduleId" />
</el-drawer>
</div>
</template>
<script>
import { listProject } from "@/api/oa/project";
import { addByProjectId, delProjectSchedule, listProjectSchedule, updateProjectSchedule } from "@/api/oa/projectSchedule";
import { listUser } from "@/api/system/user";
import ProjectSelect from "@/components/fad-service/ProjectSelect/index.vue";
import UserSelect from "@/components/UserSelect/index.vue";
import FormDialog from "./components/FormDialog.vue";
import Postpone from "./components/postpone.vue";
import ProjectScheduleStep from "./components/step.vue";
export default {
name: "Schedule",
dicts: ['sys_project_status', 'sys_trade_type', 'sys_project_type', 'sys_project_code'],
components: {
UserSelect,
ProjectScheduleStep,
FormDialog,
ProjectSelect,
Postpone
},
data () {
return {
loading: false,
detailDrawer: false,
fileShow: false,
addDialog: false,
multiple: true,
form: {},
projects: [],
scheduleList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
startTime: '',
endTime: '',
steward: ''
},
total: 0,
searchTime: [],
showSearch: true,
recentProjects: [],
scheduleDetail: {},
userList: [],
postponeDrawer: false
};
},
mounted () {
this.currentUser = this.$store.state.user
this.getList();
this.getProjectList();
this.getAllUser();
const cache = localStorage.getItem('oa_recent_projects');
if (cache) {
this.recentProjects = JSON.parse(cache);
}
},
methods: {
// 关闭细节窗口
closeDetailShow (done) {
this.getList();
done()
},
getAllUser () {
listUser({ pageNum: 1, pageSize: 999 }).then(res => {
this.userList = res.rows
})
},
handleStatusChange (row) {
updateProjectSchedule(row).then(res => {
this.getList();
this.$modal.msgSuccess("操作成功")
})
},
// 绑定进度
handleAdd () {
this.addDialog = true;
},
selectPrePay () {
this.handleQuery()
},
/** 搜索按钮操作 */
handleQuery () {
this.queryParams.pageNum = 1;
this.getList();
},
getDateStr (date) {
if (!date) {
return ''
}
return this.parseTime(date, '{y}-{m}-{d} {h}:{i}:{s}')
},
getList () {
this.loading = true
console.log(this.queryParams, this.searchTime)
/* 日期搜索条件 */
if (this.searchTime && this.searchTime.length) {
this.queryParams.startTime = this.getDateStr(this.searchTime[0])
this.queryParams.endTime = this.getDateStr(this.searchTime[1])
}
listProjectSchedule(this.queryParams).then(res => {
this.scheduleList = res.rows
this.total = res.total
let cache = JSON.parse(localStorage.getItem('oa_recent_projects') || '[]')
const id2idx = new Map()
cache.forEach((item, idx) => id2idx.set(item.scheduleId, idx))
for (const row of res.rows) {
const hit = id2idx.get(row.scheduleId)
if (hit !== undefined) {
cache[hit] = row
} else {
cache.unshift(row)
}
}
cache = cache.slice(0, 2)
/* 25 回写缓存 + 更新响应式数据 */
localStorage.setItem('oa_recent_projects', JSON.stringify(cache))
this.recentProjects = cache
/* 3. 结束 loading */
this.loading = false
})
},
getProjectList () {
let params = {
pageNum: 1,
pageSize: 999,
}
listProject(params).then(res => {
this.projects = res.rows
})
},
/** 保存处理*/
handleSave (payload) {
addByProjectId(payload).then(response => {
this.getList();
this.$modal.msgSuccess("绑定成功")
})
},
handleDetail (row) {
// 把当前项目放到数组最前面,去重
const list = [row, ...this.recentProjects.filter(p => p.projectId !== row.projectId)];
// 只保留前 2 条
this.recentProjects = list.slice(0, 2);
// 持久化
localStorage.setItem('oa_recent_projects', JSON.stringify(this.recentProjects));
this.getScheduleDetail(row)
},
handlePostpone (row) {
// 打开延期记录弹窗
this.postponeDrawer = true
this.scheduleDetail = row
},
getScheduleDetail (row) {
this.scheduleDetail = row
this.detailDrawer = true
},
/* ========= 左侧主列表删除(支持单删或批量 ids ========= */
handleDelete (row) {
/* 支持row.scheduleId 或 this.ids = '1,2,3' */
const scheduleIds = row.scheduleId || this.ids
this.$modal.confirm(`将会删除进度编号为 "${scheduleIds}" 的数据项, 同时会删除所有的子进度且无法找回 !!! 是否继续? `)
.then(() => {
this.loading = true
return delProjectSchedule(scheduleIds)
})
.then(() => {
/* 刷新左侧列表并提示 */
this.getList()
this.$modal.msgSuccess('删除成功')
})
},
// 多选框选中数据
handleSelectionChange (selection) {
this.ids = selection.map(item => item.scheduleId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 重置按钮操作 */
resetQuery () {
this.searchTime = [];
this.resetForm("queryForm");
this.handleQuery();
},
},
}
</script>
<style scoped>
.uploader {
margin-top: 12px;
}
.file-item {
margin-top: 12px;
}
.file-row {
display: flex;
font-size: small;
color: #414141;
align-items: center;
}
.file-icon {
width: 40px;
text-align: center;
margin-right: 12px;
}
.file-info {
flex: 1;
}
.file-meta {
color: #909399;
font-size: 12px;
margin-top: 2px;
}
.file-actions el-button+el-button {
margin-left: 4px;
}
</style>