Commit 8c8efd1e authored by 高滢's avatar 高滢

feat(招标计划): 填报统计

parent a51ef495
......@@ -10,14 +10,26 @@ enum Api {
SelectCount = '/pro/tenderYearManage/selectCount',
GetListAll = '/pro/tenderYearManage/statistics',
Export = '/pro/tenderYearManage/export',
Import = '/pro/tenderYearManage/import',
}
export const selectPageList = (params?: any) =>
defHttp.post({ url: Api.GetPageList, data: params });
export const addProject = (params?: any) => defHttp.post({ url: Api.AddProject, data: params });
export const addProject = (params?: any) =>
defHttp.post({
url: Api.AddProject,
data: params,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
});
export const updateProject = (params?: any) =>
defHttp.post({ url: Api.UpdateProject, data: params });
defHttp.post({
url: Api.UpdateProject,
data: params,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
});
export const deleteProject = (params?: any) =>
defHttp.get({ url: Api.DeleteProject, data: params });
......@@ -27,4 +39,8 @@ export const handelExamine = (params?: any) => defHttp.get({ url: Api.Audit, dat
export const getCount = (params?: any) => defHttp.post({ url: Api.SelectCount, data: params });
export const selectListAll = (params?: any) => defHttp.post({ url: Api.GetListAll, data: params });
export const exportTender = (params?: any) => defHttp.post({ url: Api.Export, data: params });
export const exportTender = (params?: any) =>
defHttp.post(
{ url: Api.Export, data: params, responseType: 'blob' },
{ errorMessageMode: 'none', isTransformResponse: false },
);
import { defHttp } from '@/utils/http/axios';
enum Api {
GetPageList = '/pro/tenderYearPlan/page',
AddProject = '/pro/tenderYearPlan/add',
UpdateProject = '/pro/tenderYearPlan/edit',
DeleteProject = '/pro/tenderYearPlan/del',
ProjectDetail = '/pro/tenderYearPlan/details',
Audit = '/pro/tenderYearPlan/examine',
SelectCount = '/pro/tenderYearPlan/count',
GetListAll = '/pro/tenderYearPlan/statistics',
Export = '/pro/tenderYearPlan/export',
}
export const selectPageList = (params?: any) =>
defHttp.post({ url: Api.GetPageList, data: params });
export const addProject = (params?: any) =>
defHttp.post({
url: Api.AddProject,
data: params,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
});
export const updateProject = (params?: any) =>
defHttp.post({
url: Api.UpdateProject,
data: params,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
});
export const deleteProject = (params?: any) =>
defHttp.get({ url: Api.DeleteProject, data: params });
export const selectDetail = (params?: any) => defHttp.get({ url: Api.ProjectDetail, data: params });
export const handelExamine = (params?: any) => defHttp.get({ url: Api.Audit, data: params });
export const getCount = (params?: any) => defHttp.post({ url: Api.SelectCount, data: params });
export const selectListAll = (params?: any) => defHttp.post({ url: Api.GetListAll, data: params });
export const exportTender = (params?: any) =>
defHttp.post(
{ url: Api.Export, data: params, responseType: 'blob' },
{ errorMessageMode: 'none', isTransformResponse: false },
);
......@@ -94,6 +94,16 @@ const biddingPlan: AppRouteModule = {
orderNo: 5,
},
},
{
path: 'tendeYearManage',
name: 'TendeYearManage',
component: () => import('@/views/tendeYearManage/index.vue'),
meta: {
auth: '/www/dist/index.html#/biddingManagement/index',
title: '年度招标管理填报',
orderNo: 5,
},
},
{
path: 'tendeYearManageSta',
name: 'TendeYearManageSta',
......@@ -105,13 +115,36 @@ const biddingPlan: AppRouteModule = {
},
},
{
path: 'tendeYearManage',
name: 'TendeYearManage',
component: () => import('@/views/tendeYearManage/index.vue'),
path: 'tendeYearPlanEdit',
name: 'TendeYearPlanEdit',
component: () => import('@/views/tenderYearPlan/edit.vue'),
meta: {
hideTab: true,
hideMenu: true,
hideBreadcrumb: true,
auth: '/www/dist/index.html#/biddingManagement/index',
title: '年度招标管理填报',
orderNo: 5,
title: '年度招标计划填报',
orderNo: 6,
},
},
{
path: 'tendeYearPlan',
name: 'TendeYearPlan',
component: () => import('@/views/tenderYearPlan/index.vue'),
meta: {
auth: '/www/dist/index.html#/biddingManagement/index',
title: '年度招标计划填报',
orderNo: 7,
},
},
{
path: 'tendeYearPlanSta',
name: 'TendeYearMPlanSta',
component: () => import('@/views/tenderYearPlan/statistics.vue'),
meta: {
auth: '/www/dist/index.html#/biddingManagement/index',
title: '年度招标计划统计',
orderNo: 7,
},
},
],
......
......@@ -46,7 +46,7 @@
accept=".xlsx,.xls"
:on-success="uploadFile"
>
<a-button v-if="!disabled" type="dashed" @click="excelAdd" class="ml-2" preIcon="ei:plus">
<a-button v-if="!disabled" type="dashed" class="ml-2" preIcon="ei:plus">
Excel导入
</a-button>
</Upload>
......
......@@ -157,7 +157,7 @@
import { useUserStore } from '@/store/modules/user';
import PageCard from '@/components/Page/src/PageCard.vue';
import CycleModel from '@/views/monthlyPlan/cycleModel/cycleModel.vue';
import FillDetailsModel from '@/views/biddingManagement/fillDetailsModel/fillDetailsModel.vue';
import FillDetailsModel from '@/views/monthlyPlan/fillDetailsModel/fillDetailsModel.vue';
import { Divider, Row, Col } from 'ant-design-vue';
import {getMothCycel, SetEditStatus} from "@/api/project/monthlyPlan";
......@@ -243,11 +243,15 @@
function selectCycle() {
openCycleModel(true, {
data: mothCycle.value,
type: 'year',
id: 11,
});
}
function getFillDetails() {
openFillDetailModel(true, {
data: mothCycle.value,
url: '/pro/monthEngineer/businessComDetails',
module: 'TenderMan',
});
}
function handleCreate() {
......
......@@ -106,54 +106,31 @@
loadingRef.value = true;
let data = await selectListAll(params.value);
let propsList = ['companyName', 'projectName'];
let propsList = ['companyName'];
propsList.map((item) => {
changeData(data, item);
});
loadingRef.value = false;
}
function changeData(data, field) {
if (field == 'companyName') {
let count = 0; //重复项的第一项
let indexCount = 1; //下一项
while (indexCount < data.length) {
let item = data.slice(count, count + 1)[0]; //获取没有比较的第一个对象
if (!item[`${field}rowSpan`]) {
item[`${field}rowSpan`] = 1; //初始化为1
}
if (item[field] === data[indexCount][field]) {
//第一个对象与后面的对象相比,有相同项就累加,并且后面相同项设置为0
item[`${field}rowSpan`]++;
data[indexCount][`${field}rowSpan`] = 0;
} else {
count = indexCount;
}
indexCount++;
let count = 0; // 当前组中第一个元素的索引
let indexCount = 1; // 下一个需要比较的元素的索引
while (indexCount < data.length) {
const item = data[count]; // 获取当前组的第一个元素
const nextItem = data[indexCount]; // 获取下一个需要比较的元素
if (!item[`${field}rowSpan`]) {
item[`${field}rowSpan`] = 1; // 初始化rowSpan属性为1
}
}
if (field == 'proName') {
let count = 0; //重复项的第一项
let indexCount = 1; //下一项
while (indexCount < data.length) {
let item = data.slice(count, count + 1)[0]; //获取没有比较的第一个对象
if (!item[`${field}rowSpan`]) {
item[`${field}rowSpan`] = 1; //初始化为1
}
if (
item[field] === data[indexCount][field] &&
item['companyName'] === data[indexCount]['companyName']
) {
//第一个对象与后面的对象相比,有相同项就累加,并且后面相同项设置为0
item[`${field}rowSpan`]++;
data[indexCount][`${field}rowSpan`] = 0;
} else {
count = indexCount;
}
indexCount++;
// 检查companyName和指定字段是否匹配
if (item[field] === nextItem[field] && item.companyName === nextItem.companyName) {
item[`${field}rowSpan`]++; // 增加当前元素的rowSpan值
nextItem[`${field}rowSpan`] = 0; // 标记为已合并
} else {
count = indexCount; // 将当前组的起始位置移动到下一个元素
}
indexCount++;
}
dataSource.value = data;
dataSource.value = data; // 更新数据源
}
// 列表
......
import { BasicColumn, FormSchema } from '@/components/Table';
import { useUserStore } from '@/store/modules/user';
const deptId = useUserStore().userInfo.deptParentId;
//主模块-招标计划列表页
export const columns: BasicColumn[] = [
{
title: '序号',
dataIndex: 'serialNumber',
width: 100,
},
{
title: '填报周期',
dataIndex: 'tenderYear',
width: 200,
},
{
title: '项目数量',
dataIndex: 'proNumber',
width: 180,
},
{
title: '公司名称',
dataIndex: 'companyName',
width: 180,
},
{
title: '最新更新人',
dataIndex: 'updateBy',
width: 180,
},
{
title: '审核状态',
dataIndex: 'reviewStatus',
ifShow: deptId != '100',
width: 140,
},
{
title: '审核人',
dataIndex: 'revieweUser',
width: 180,
},
{
title: '审核时间',
dataIndex: 'reviewTime',
width: 180,
},
];
export const searchFormSchema: FormSchema[] = [
{
field: 'tenderYear',
label: '',
component: 'DatePicker',
componentProps: {
placeholder: '年份',
picker: 'year',
valueFormat: 'YYYY',
format: 'YYYY',
style: {
width: '100%',
},
},
colProps: { span: 4 },
},
{
field: 'companyId',
label: '',
component: 'Select',
componentProps: {
placeholder: '公司名称',
options: [
{
label: '公司名称',
value: '公司名称',
},
],
},
colProps: { span: 4 },
},
];
export const formSchema: FormSchema[] = [
{
field: 'proName',
label: '项目名称',
required: true,
component: 'Input',
componentProps: {
readonly: true,
disabled: true,
},
colProps: { span: 7, offset: 1 },
},
{
field: 'fundingSource',
label: '资金来源',
required: true,
component: 'Input',
componentProps: {
readonly: true,
disabled: true,
},
colProps: { span: 7, offset: 1 },
},
{
field: 'projectInitiator',
label: '立项主体',
required: true,
component: 'Input',
colProps: { span: 7, offset: 1 },
},
{
field: 'investmentAmount',
label: '立项投资额',
required: true,
component: 'InputNumber',
componentProps: {
addonAfter: '万元',
},
colProps: { span: 7, offset: 1 },
},
{
field: 'biddingType',
label: '招标类型(施工、监理、设计、图审等)',
required: true,
component: 'Input',
colProps: { span: 7, offset: 1 },
labelWidth: 400,
},
{
field: 'controlPrice',
label: '预计控制价',
required: true,
component: 'InputNumber',
componentProps: {
addonAfter: '万元',
},
colProps: { span: 7, offset: 1 },
},
{
field: 'plannedPeriod',
label: '计划工期',
required: true,
component: 'RangePicker',
colProps: { span: 7, offset: 1 },
componentProps: {
valueFormat: 'YYYY/MM/DD',
format: 'YYYY/MM/DD',
},
},
{
field: 'biddingPeriod',
label: '计划招标周期',
required: true,
component: 'RangePicker',
colProps: { span: 7, offset: 1 },
componentProps: {
valueFormat: 'YYYY/MM/DD',
format: 'YYYY/MM/DD',
},
},
{
field: 'biddingMethod',
label: '招标方式',
required: true,
component: 'Select',
componentProps: {
options: [
{
label: '建委招标',
value: '建委招标',
},
{
label: '平台招标',
value: '平台招标',
},
{
label: '邀标比选',
value: '邀标比选',
},
{
label: '直接委托',
value: '直接委托',
},
{
label: '评定分离',
value: '评定分离',
},
],
},
colProps: { span: 7, offset: 1 },
},
{
label: '招标内容',
field: 'tenderContent',
required: true,
component: 'InputTextArea',
componentProps: {
maxlength: 100,
showCount: true,
},
colProps: { span: 7, offset: 1 },
},
{
label: '备注',
field: 'remark',
// required: true,
component: 'InputTextArea',
componentProps: {
maxlength: 100,
showCount: true,
},
colProps: { span: 7, offset: 1 },
},
];
This diff is collapsed.
This diff is collapsed.
<template>
<div style="margin: 16px">
<PageCard title="招标计划统计">
<BasicForm ref="formElRef" @register="registerForm">
<template #formFooter>
<a-button type="primary" @click="handleSubmit"> 查询</a-button>
<a-button type="primary" @click="exportCount" style="margin-left: 10px"> 导出</a-button>
</template>
</BasicForm>
<Table
:pagination="false"
:dataSource="dataSource"
:columns="columns"
bordered
:loading="loadingRef"
:rowClassName="setRowClassName"
:scroll="{ x: 1300, y: 600 }"
/>
</PageCard>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { Table } from 'ant-design-vue';
import { exportTender, selectListAll } from '@/api/project/yearTenderPlan';
import { BasicForm, FormActionType, useForm } from '@/components/Form';
import PageCard from '@/components/Page/src/PageCard.vue';
import { downloadByData } from '@/utils/file/download';
import moment from 'moment';
import { getDepartmentList } from '@/api/project/settlementManage';
const seach = ref([
{
field: 'tenderYear',
label: '',
component: 'DatePicker',
componentProps: {
placeholder: '年份',
picker: 'year',
defaultValue: moment().format('YYYY'),
valueFormat: 'YYYY',
format: 'YYYY',
style: {
width: '100%',
},
},
colProps: { span: 4 },
},
{
field: 'companyId',
label: '',
component: 'Select',
componentProps: {
placeholder: '公司名称',
options: [
{
label: '公司名称',
value: '公司名称',
},
],
},
colProps: { span: 4 },
},
]);
const formElRef = ref<Nullable<FormActionType>>(null);
const [registerForm, { getFieldsValue }] = useForm({
labelWidth: 90,
baseColProps: { span: 24 },
schemas: seach,
showActionButtonGroup: false,
});
const params = ref({ tenderYear: '', companyName: '' });
const loadingRef = ref(false);
onMounted(async () => {
// 设置当前年份
params.value.tenderYear = moment().format('YYYY');
const data = await getDepartmentList();
seach.value[1].componentProps.options = data;
getStatisticList();
});
function handleSubmit() {
let data = getFieldsValue();
params.value = data;
getStatisticList();
}
async function exportCount() {
const data = await exportTender(params.value);
downloadByData(data, '年度招标计划统计报表' + '.xls');
}
function setRowClassName(record) {
if (record.projectName === '总计(万元)') {
return 'rowcolor';
} else if (record.companyName === '合计(万元)') {
return 'rowcolor';
} else {
return;
}
}
async function getStatisticList() {
loadingRef.value = true;
let data = await selectListAll(params.value);
let propsList = ['companyName'];
propsList.map((item) => {
changeData(data, item);
});
loadingRef.value = false;
}
function changeData(data, field) {
let count = 0; // 当前组中第一个元素的索引
let indexCount = 1; // 下一个需要比较的元素的索引
while (indexCount < data.length) {
const item = data[count]; // 获取当前组的第一个元素
const nextItem = data[indexCount]; // 获取下一个需要比较的元素
if (!item[`${field}rowSpan`]) {
item[`${field}rowSpan`] = 1; // 初始化rowSpan属性为1
}
// 检查companyName和指定字段是否匹配
if (item[field] === nextItem[field] && item.companyName === nextItem.companyName) {
item[`${field}rowSpan`]++; // 增加当前元素的rowSpan值
nextItem[`${field}rowSpan`] = 0; // 标记为已合并
} else {
count = indexCount; // 将当前组的起始位置移动到下一个元素
}
indexCount++;
}
dataSource.value = data; // 更新数据源
}
// 列表
const dataSource = ref([]);
// 表头
const columns = [
{
title: '公司名称',
dataIndex: 'companyName',
fixed: 'left',
width: 180,
customCell: (_, any) => ({
rowSpan: _.companyNamerowSpan,
}),
},
{
title: '项目名称',
dataIndex: 'projectName',
width: 180,
customCell: (_, any) => ({
rowSpan: _.projectNamerowSpan,
}),
},
{
title: '立项投资额(万元)',
dataIndex: 'investmentAmount',
width: 180,
},
{
title: '预计控制价(万元)',
dataIndex: 'controlPrice',
width: 180,
},
{
title: '招标类型',
dataIndex: 'biddingType',
width: 180,
},
{
title: '招标方式',
dataIndex: 'biddingMethod',
width: 180,
},
];
</script>
<style lang="less" scoped>
::v-deep .ant-table-tbody .ant-table-row {
&.rowcolor .ant-table-cell-fix-left {
background-color: #f5f5f5;
}
}
.action-container {
display: flex;
justify-content: space-between;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment