Commit e173f956 authored by ccc2wdd's avatar ccc2wdd

Merge remote-tracking branch 'origin/develop' into develop

parents a440540a bf0967b9
...@@ -17,8 +17,36 @@ enum Api { ...@@ -17,8 +17,36 @@ enum Api {
Itemdelete = '/pro/tenderManager/details/del', Itemdelete = '/pro/tenderManager/details/del',
audit = '/pro/tenderManager/examine', audit = '/pro/tenderManager/examine',
GetListAll = '/pro/tenderManager/selectAll', GetListAll = '/pro/tenderManager/selectAll',
ExportCount = '/pro/export/tendMangeStatistic' ExportCount = '/pro/export/tendMangeStatistic',
GetMothCycelDetails = '/pro/tenderManager/details',
MothCycelEdit = '/pro/tenderManager/edit',
EditStatus = '/pro/tenderManager/editStatus',
BusinessComDetails = '/pro/tenderManager/businessComDetails',
} }
// 详情表单
export const getTenderManagerFillComDetails = (params?: any) =>
defHttp.post<any>({
url: Api.BusinessComDetails,
params,
});
// 修改编辑状态
export const SetTenderManagerEditStatus = (params?: any) =>
defHttp.post<any>({
url: Api.EditStatus,
params,
});
// 修改搜索参数
export const SetTenderManagerMothCycelEdit = (params?: any) =>
defHttp.post<any>({
url: Api.MothCycelEdit,
params,
});
// 查询周期详情
export const getTenderManagerMothCycel = (params?: any) =>
defHttp.post<any>({
url: Api.GetMothCycelDetails,
params,
});
export const getListByPage = (params?: ProjectPageParams) => export const getListByPage = (params?: ProjectPageParams) =>
defHttp.post<ListGetResultModel>({ url: Api.GetList, data: params }); defHttp.post<ListGetResultModel>({ url: Api.GetList, data: params });
......
...@@ -13,7 +13,35 @@ enum Api { ...@@ -13,7 +13,35 @@ enum Api {
selectCount = '/pro/tenderPlan/selectCount', selectCount = '/pro/tenderPlan/selectCount',
GetListAll = '/pro/tenderPlan/listAll', GetListAll = '/pro/tenderPlan/listAll',
ExportCount = '/pro/export/tenderPlanStatistic', ExportCount = '/pro/export/tenderPlanStatistic',
GetMothCycelDetails = '/pro/tenderPlan/details',
MothCycelEdit = '/pro/tenderPlan/edit',
EditStatus = '/pro/tenderPlan/editStatus',
BusinessComDetails = '/pro/tenderPlan/businessComDetails',
} }
// 详情表单
export const getTenderPlanFillComDetails = (params?: any) =>
defHttp.post<any>({
url: Api.BusinessComDetails,
params,
});
// 修改编辑状态
export const SetTenderPlanEditStatus = (params?: any) =>
defHttp.post<any>({
url: Api.EditStatus,
params,
});
// 修改搜索参数
export const SetTenderPlanMothCycelEdit = (params?: any) =>
defHttp.post<any>({
url: Api.MothCycelEdit,
params,
});
// 查询周期详情
export const getTenderPlanMothCycel = (params?: any) =>
defHttp.post<any>({
url: Api.GetMothCycelDetails,
params,
});
export const getListByPage = (params?: ProjectPageParams) => export const getListByPage = (params?: ProjectPageParams) =>
defHttp.post<ListGetResultModel>({ url: Api.GetList, data: params }); defHttp.post<ListGetResultModel>({ url: Api.GetList, data: params });
......
...@@ -26,7 +26,35 @@ enum Api { ...@@ -26,7 +26,35 @@ enum Api {
isSettlement = '/pro/settlement/is-settlement', isSettlement = '/pro/settlement/is-settlement',
GetListAll = '/pro/settlement/listAll', GetListAll = '/pro/settlement/listAll',
ExportCount= '/pro/export/settlementManagementStatistic', ExportCount= '/pro/export/settlementManagementStatistic',
GetMothCycelDetails = '/pro/settlement/details',
MothCycelEdit = '/pro/settlement/edit',
EditStatus = '/pro/settlement/editStatus',
BusinessComDetails = '/pro/settlement/businessComDetails',
} }
// 详情表单
export const getSettlementFillComDetails = (params?: any) =>
defHttp.post<any>({
url: Api.BusinessComDetails,
params,
});
// 修改编辑状态
export const SetSettlementEditStatus = (params?: any) =>
defHttp.post<any>({
url: Api.EditStatus,
params,
});
// 修改搜索参数
export const SetSettlementMothCycelEdit = (params?: any) =>
defHttp.post<any>({
url: Api.MothCycelEdit,
params,
});
// 查询周期详情
export const getSettlementMothCycel = (params?: any) =>
defHttp.post<any>({
url: Api.GetMothCycelDetails,
params,
});
export const getSettlementManageList = (params?: ProjectParams) => export const getSettlementManageList = (params?: ProjectParams) =>
defHttp.post<ProjectParams>({ url: Api.GetList, data: params }); defHttp.post<ProjectParams>({ url: Api.GetList, data: params });
......
...@@ -342,6 +342,7 @@ ...@@ -342,6 +342,7 @@
// router.back(); // router.back();
} catch (e) { } catch (e) {
// 验证失败或出错,切换到对应标签页 // 验证失败或出错,切换到对应标签页
createMessage.error('请将项目' + e.values.projectName + '信息填写完整!');
console.log(e); console.log(e);
} finally { } finally {
loadingRef.value = false; loadingRef.value = false;
......
<template>
<BasicModal
v-bind="$attrs"
@register="register"
title="设置填报周期"
:minHeight="30"
okText="保存"
@ok="handleSubmit"
>
<BasicForm @register="registerForm" :model="modelRef" />
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue';
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, FormSchema, useForm } from '@/components/Form';
import {SetTenderManagerMothCycelEdit} from "@/api/project/biddingManagement";
const props = defineProps({
userData: { type: Object },
});
const emit = defineEmits(['getCycle', 'register']);
const modelRef = ref({});
const [registerForm, { getFieldsValue, validate }] = useForm({
labelWidth: 100,
schemas: [
// {
// field: 'fillCycle',
// label: '填报周期',
// component: 'DatePicker',
// defaultValue: '',
// required: true,
// componentProps: {
// placeholder: '请选择填报周期',
// picker: 'month',
// valueFormat: 'YYYY-MM',
// format: 'YYYY-MM',
// style: {
// width: '100%',
// },
// },
// },
{
field: 'tenderYear',
label: '选择填报周期',
component: 'DatePicker',
required: true,
componentProps: {
placeholder: '选择填报周期',
picker: 'year',
style: { width: '100%' },
valueFormat: 'YYYY',
format: 'YYYY',
},
colProps: { span: 12 },
},
{
field: 'biddingQuarter',
label: '季度',
component: 'Select',
required: true,
componentProps: {
style: { width: '100%' },
options: [
{
label: '第一季度',
value: '第一季度',
},
{
label: '第二季度',
value: '第二季度',
},
{
label: '第三季度',
value: '第三季度',
},
{
label: '第四季度',
value: '第四季度',
},
],
placeholder: '季度',
},
colProps: { span: 12 },
},
],
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const cycleData = ref({
beginTime: '2024-07-01',
endTime: '2024-09-02',
fillCycle: '2024-09',
isEdit: '0',
deptNum: 12,
noNum: 6,
});
const [register, { closeModal }] = useModalInner((data) => {
console.log(data.data);
cycleData.value = data.data;
});
function handleSubmit() {
validate().then(() => {
const value = getFieldsValue();
cycleData.value.fillCycle = value.tenderYear +'年'+ value.biddingQuarter;
cycleData.value.tenderYear = value.tenderYear;
cycleData.value.biddingQuarter = value.biddingQuarter;
console.log('!!!!!!!!-', cycleData.value.fillCycle)
SetTenderManagerMothCycelEdit(cycleData.value).then(() => {
emit('getCycle');
console.log('2123', cycleData.value);
});
closeModal();
});
}
</script>
<template>
<BasicModal v-bind="$attrs" width="80%" @register="register" :title="getTitle" :showOkBtn="false">
<Table
:pagination="false"
:dataSource="dataSource"
:columns="columns"
bordered
:sticky="true"
:loading="loadingRef"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'comStatus'">
<Tag color="green" v-if="record.comStatus == '1'"> 已完成 </Tag>
<Tag color="red" v-else> 未完成 </Tag>
</template>
</template>
</Table>
</BasicModal>
</template>
<script setup lang="ts">
import { useModalInner } from '@/components/Modal';
import BasicModal from '@/components/Modal/src/BasicModal.vue';
import { ref } from 'vue';
import {Table, Tag} from 'ant-design-vue';
import {getTenderManagerFillComDetails} from "@/api/project/biddingManagement";
const loadingRef = ref(false);
// 列表
const dataSource = ref([]);
// 表头
const columns = [
{
title: '公司名称',
dataIndex: 'companyName',
width: 200,
},
{
title: '完成状态',
dataIndex: 'comStatus',
width: 180,
},
{
title: '上报时间',
dataIndex: 'updateTime',
width: 150,
},
];
const getTitle = ref('');
const params = ref({ mothCycle: '' });
const [register, { closeModal }] = useModalInner(async (data) => {
const fillCycle = data.data.fillCycle;
console.log('fillCycle', fillCycle)
const [targetYearStr, quarterStr] = fillCycle.split('年');
// params.value.mothCycle = data.data.fillCycle;
params.value.tenderYear = targetYearStr;
params.value.biddingQuarter = quarterStr;
dataSource.value = await getTenderManagerFillComDetails(params.value);
// console.log('212', list);
});
</script>
<style scoped lang="less"></style>
<template> <template>
<div> <div>
<div v-if="deptId == 100 || deptId == 0" style="margin: 16px">
<PageCard title="数据填报周期">
<Row>
<Col :span="20">
<div class="cycleFrame">
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/tianbaoriqi.png" />
</div>
<div class="characte">
<div class="top">填报周期</div>
<div @click="selectCycle" class="bottom" style="color: #0d84ff; text-decoration: underline; cursor: pointer">{{ mothCycle.fillCycle}}</div>
</div>
</div>
<Divider type="vertical" style="height: 36px; border-color: rgba(22,106,203,0.30)" dashed />
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/shenyutianshu.png" />
</div>
<div class="characte">
<div class="top">剩余天数</div>
<div class="bottom" style="color:#DFAA21 ">{{
daysReturn() + '天'
}}</div>
</div>
</div>
<Divider type="vertical" style="height: 36px; border-color: rgba(22,106,203,0.30)" dashed />
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/weiwancheng.png" />
</div>
<div class="characte">
<div class="top">企业未完成</div>
<div class="bottom" style="color:#DB4343">{{
mothCycle.noNum + '家'
}}</div>
</div>
</div>
<Divider type="vertical" style="height: 36px; border-color: rgba(22,106,203,0.30)" dashed />
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/yiwancheng.png" />
</div>
<div class="characte">
<div class="top">企业已完成</div>
<div class="bottom" style="color:#16CB28">{{
mothCycle.deptNum - mothCycle.noNum + '家'
}}</div>
</div>
</div>
</div>
</Col>
<Col :span="4">
<a-button class="btn" @click="getFillDetails">
查看填报详情
</a-button>
<a-button class="btn" type="primary" @click="returnEdit">
{{ mothCycle.isEdit === '1' ? '开启本轮填报' : '结束本轮填报' }}
</a-button>
</Col>
</Row>
</PageCard>
</div>
<BasicTable @register="registerTable" :title="'招标管理填报'"> <BasicTable @register="registerTable" :title="'招标管理填报'">
<template #toolbar> <template #toolbar>
<a-button type="primary" preIcon="mdi:plus" @click="handleCreate"> 新增招标管理 </a-button> <a-button type="primary" preIcon="mdi:plus" @click="handleCreate"> 新增招标管理 </a-button>
...@@ -24,8 +88,8 @@ ...@@ -24,8 +88,8 @@
{ {
label: '修改', label: '修改',
onClick: handleEdit.bind(null, record, 0), onClick: handleEdit.bind(null, record, 0),
ifShow: (_action) => { ifShow: (_action) => {
return true; return record.isEdit === '0';
}, },
}, },
{ {
...@@ -58,6 +122,8 @@ ...@@ -58,6 +122,8 @@
</template> </template>
</BasicTable> </BasicTable>
<yearModal @register="register" @close="handleNew" /> <yearModal @register="register" @close="handleNew" />
<CycleModel @register="registerCycleModel" :user-data="mothCycle" @get-cycle="getSetCycle" />
<FillDetailsModel @register="registerFillDetail"></FillDetailsModel>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
...@@ -69,7 +135,7 @@ ...@@ -69,7 +135,7 @@
getListByPage, getListByPage,
deleteItem, deleteItem,
auditItem, auditItem,
selectCount, selectCount, getTenderManagerMothCycel, SetTenderManagerEditStatus,
} from '@/api/project/biddingManagement'; } from '@/api/project/biddingManagement';
import { columns, searchFormSchema } from './biddingManagement.data'; import { columns, searchFormSchema } from './biddingManagement.data';
import { useModal } from '@/components/Modal'; import { useModal } from '@/components/Modal';
...@@ -79,13 +145,17 @@ ...@@ -79,13 +145,17 @@
import {onMounted, ref} from "vue"; import {onMounted, ref} from "vue";
import {getDepartmentList} from "@/api/project/settlementManage"; import {getDepartmentList} from "@/api/project/settlementManage";
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
import PageCard from '@/components/Page/src/PageCard.vue';
import CycleModel from '@/views/biddingManagement/cycleModel/cycleModel.vue';
import FillDetailsModel from "@/views/biddingManagement/fillDetailsModel/fillDetailsModel.vue";
import {Divider,Row, Col} from 'ant-design-vue'
const deptId = ref('');
const { push } = useRouter(); const { push } = useRouter();
const { createMessage } = useMessage(); const { createMessage } = useMessage();
const { error } = createMessage; const { error } = createMessage;
defineOptions({ name: 'RoleManagement' }); defineOptions({ name: 'RoleManagement' });
const [registerFillDetail, { openModal: openFillDetailModel }] = useModal();
const [registerCycleModel, { openModal: openCycleModel }] = useModal();
const [registerTable, { reload }] = useTable({ const [registerTable, { reload }] = useTable({
api: getListByPage, api: getListByPage,
columns, columns,
...@@ -107,17 +177,94 @@ ...@@ -107,17 +177,94 @@
}); });
const [register, { openModal: openModal, closeModal: closeModal }] = useModal(); const [register, { openModal: openModal, closeModal: closeModal }] = useModal();
const isExamine = ref<boolean>(false); const isExamine = ref<boolean>(false);
const deptId = ref(100);
const mothCycle = ref({
beginTime: '2024-07-01',
endTime: '2024-09-02',
fillCycle:'2024-09',
isEdit: '0',
deptNum: 12,
noNum: 6,
});
onMounted(async () => { onMounted(async () => {
deptId.value = useUserStore().userInfo.deptParentId;
let roles = useUserStore().userInfo.roles; let roles = useUserStore().userInfo.roles;
roles.forEach((item) => { roles.forEach((item) => {
if (item.role_key === 'approver') { if (item.role_key === 'approver') {
isExamine.value = true; isExamine.value = true;
} }
}); });
// console.log('deptId.value:',deptId.value) const cycle = await getTenderManagerMothCycel();
mothCycle.value = cycle;
console.log(cycle, "cycle")
const data = await getDepartmentList(); const data = await getDepartmentList();
searchFormSchema[2].componentProps.options = data; searchFormSchema[2].componentProps.options = data;
}); });
function returnEdit() {
const fillCycle = mothCycle.value.fillCycle;
const [tenderYear, biddingQuarter] = fillCycle.split('年');
mothCycle.value.tenderYear = tenderYear
mothCycle.value.biddingQuarter = biddingQuarter
console.log('mothCycle.value',mothCycle.value)
if (mothCycle.value.isEdit == '1') {
mothCycle.value.isEdit = '0';
SetTenderManagerEditStatus(mothCycle.value);
} else {
mothCycle.value.isEdit = '1';
SetTenderManagerEditStatus(mothCycle.value);
}
reload();
}
function daysReturn() {
// 获取今天的日期
const today = new Date();
// 获取目标年份和月份
const fillCycle = mothCycle.value.fillCycle;
const [targetYearStr, quarterStr] = fillCycle.split('年');
const targetYear = parseInt(targetYearStr, 10);
let targetMonth = 0;
switch (quarterStr) {
case '第一季度':
targetMonth = 2;
break;
case '第二季度':
targetMonth = 5;
break;
case '第三季度':
targetMonth = 8;
break;
case '第四季度':
targetMonth = 11;
break;
default:
return null;
}
// 创建目标日期(2024年9月30日)
const targetDate = new Date(targetYear, targetMonth, 0); // 0表示上一个月的最后一天,即9月30日
console.log(targetDate, '目标日期')
// 计算时间差(毫秒)
const timeDifference = targetDate - today;
// 计算天数差(天数 = 毫秒差 / 每天的毫秒数)
const daysUntilTarget = Math.max(0, Math.ceil(timeDifference / (1000 * 60 * 60 * 24)));
return daysUntilTarget
}
function selectCycle() {
openCycleModel(true, {
data: mothCycle.value,
});
}
function getFillDetails(){
openFillDetailModel(true,{
data:mothCycle.value
})
}
async function getSetCycle() {
const cycle = await getTenderManagerMothCycel();
mothCycle.value = cycle;
}
function handleCreate() { function handleCreate() {
openModal(true, { openModal(true, {
data: ['year', 'quarter'], data: ['year', 'quarter'],
...@@ -164,3 +311,30 @@ ...@@ -164,3 +311,30 @@
reload(); reload();
} }
</script> </script>
<style scoped>
.btn {
margin-right: 10px;
margin-top: 8px;
}
.cycleFrame{
border: 1px solid rgba(22, 106, 203, 0.10);
border-radius: 6px;
padding: 20px 50px;
margin-right: 20px;
display: flex;
justify-content: space-between;
.card{
display: flex;
.cycleIcon{
margin-right: 10px;
}
.characte{
display: flex;
flex-direction: column;
justify-content: space-around;
.top{}
.bottom{}
}
}
}
</style>
...@@ -328,6 +328,7 @@ ...@@ -328,6 +328,7 @@
// router.back(); // router.back();
} catch (e) { } catch (e) {
// 验证失败或出错,切换到对应标签页 // 验证失败或出错,切换到对应标签页
createMessage.error('请将项目' + e.values.projectName + '信息填写完整!');
console.log(e); console.log(e);
} finally { } finally {
loadingRef.value = false; loadingRef.value = false;
......
<template>
<BasicModal
v-bind="$attrs"
@register="register"
title="设置填报周期"
:minHeight="30"
okText="保存"
@ok="handleSubmit"
>
<BasicForm @register="registerForm" :model="modelRef" />
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue';
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, FormSchema, useForm } from '@/components/Form';
import {SetSettlementMothCycelEdit} from "@/api/project/settlementManage";
import {SetTenderPlanMothCycelEdit} from "@/api/project/biddingPlan";
const props = defineProps({
userData: { type: Object },
});
const emit = defineEmits(['getCycle', 'register']);
const modelRef = ref({});
const [registerForm, { getFieldsValue, validate }] = useForm({
labelWidth: 100,
schemas: [
// {
// field: 'fillCycle',
// label: '填报周期',
// component: 'DatePicker',
// defaultValue: '',
// required: true,
// componentProps: {
// placeholder: '请选择填报周期',
// picker: 'month',
// valueFormat: 'YYYY-MM',
// format: 'YYYY-MM',
// style: {
// width: '100%',
// },
// },
// },
{
field: 'tenderYear',
label: '选择填报周期',
component: 'DatePicker',
required: true,
componentProps: {
placeholder: '选择填报周期',
picker: 'year',
style: { width: '100%' },
valueFormat: 'YYYY',
format: 'YYYY',
},
colProps: { span: 12 },
},
{
field: 'biddingQuarter',
label: '季度',
component: 'Select',
required: true,
componentProps: {
style: { width: '100%' },
options: [
{
label: '第一季度',
value: '第一季度',
},
{
label: '第二季度',
value: '第二季度',
},
{
label: '第三季度',
value: '第三季度',
},
{
label: '第四季度',
value: '第四季度',
},
],
placeholder: '季度',
},
colProps: { span: 12 },
},
],
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const cycleData = ref({
beginTime: '2024-07-01',
endTime: '2024-09-02',
fillCycle: '2024-09',
isEdit: '0',
deptNum: 12,
noNum: 6,
});
const [register, { closeModal }] = useModalInner((data) => {
console.log(data.data);
cycleData.value = data.data;
});
function handleSubmit() {
validate().then(() => {
const value = getFieldsValue();
cycleData.value.fillCycle = value.tenderYear +'年'+ value.biddingQuarter;
cycleData.value.tenderYear = value.tenderYear;
cycleData.value.biddingQuarter = value.biddingQuarter;
console.log('!!!!!!!!-', cycleData.value.fillCycle)
SetTenderPlanMothCycelEdit(cycleData.value).then(() => {
emit('getCycle');
console.log('2123', cycleData.value);
});
closeModal();
});
}
</script>
<template>
<BasicModal v-bind="$attrs" width="80%" @register="register" :title="getTitle" :showOkBtn="false">
<Table
:pagination="false"
:dataSource="dataSource"
:columns="columns"
bordered
:sticky="true"
:loading="loadingRef"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'comStatus'">
<Tag color="green" v-if="record.comStatus == '1'"> 已完成 </Tag>
<Tag color="red" v-else> 未完成 </Tag>
</template>
</template>
</Table>
</BasicModal>
</template>
<script setup lang="ts">
import { useModalInner } from '@/components/Modal';
import BasicModal from '@/components/Modal/src/BasicModal.vue';
import { ref } from 'vue';
import {Table, Tag} from 'ant-design-vue';
import {getSettlementFillComDetails} from "@/api/project/settlementManage";
import {getTenderPlanFillComDetails} from "@/api/project/biddingPlan";
const loadingRef = ref(false);
// 列表
const dataSource = ref([]);
// 表头
const columns = [
{
title: '公司名称',
dataIndex: 'companyName',
width: 200,
},
{
title: '完成状态',
dataIndex: 'comStatus',
width: 180,
},
{
title: '上报时间',
dataIndex: 'updateTime',
width: 150,
},
];
const getTitle = ref('');
const params = ref({ mothCycle: '' });
const [register, { closeModal }] = useModalInner(async (data) => {
const fillCycle = data.data.fillCycle; // 假设 monthCycle.value.fillCycle 是类似 "2024年第一季度" 的字符串
console.log('fillCycle', fillCycle)
const [targetYearStr, quarterStr] = fillCycle.split('年');
// params.value.mothCycle = data.data.fillCycle;
params.value.tenderYear = targetYearStr;
params.value.biddingQuarter = quarterStr;
dataSource.value = await getTenderPlanFillComDetails(params.value);
// console.log('212', list);
});
</script>
<style scoped lang="less"></style>
<template> <template>
<div> <div>
<div v-if="deptId == 100 || deptId == 0" style="margin: 16px">
<PageCard title="数据填报周期">
<Row>
<Col :span="20">
<div class="cycleFrame">
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/tianbaoriqi.png" />
</div>
<div class="characte">
<div class="top">填报周期</div>
<div @click="selectCycle" class="bottom" style="color: #0d84ff; text-decoration: underline; cursor: pointer">{{ mothCycle.fillCycle}}</div>
</div>
</div>
<Divider type="vertical" style="height: 36px; border-color: rgba(22,106,203,0.30)" dashed />
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/shenyutianshu.png" />
</div>
<div class="characte">
<div class="top">剩余天数</div>
<div class="bottom" style="color:#DFAA21 ">{{
daysReturn() + '天'
}}</div>
</div>
</div>
<Divider type="vertical" style="height: 36px; border-color: rgba(22,106,203,0.30)" dashed />
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/weiwancheng.png" />
</div>
<div class="characte">
<div class="top">企业未完成</div>
<div class="bottom" style="color:#DB4343">{{
mothCycle.noNum + '家'
}}</div>
</div>
</div>
<Divider type="vertical" style="height: 36px; border-color: rgba(22,106,203,0.30)" dashed />
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/yiwancheng.png" />
</div>
<div class="characte">
<div class="top">企业已完成</div>
<div class="bottom" style="color:#16CB28">{{
mothCycle.deptNum - mothCycle.noNum + '家'
}}</div>
</div>
</div>
</div>
</Col>
<Col :span="4">
<a-button class="btn" @click="getFillDetails">
查看填报详情
</a-button>
<a-button class="btn" type="primary" @click="returnEdit">
{{ mothCycle.isEdit === '1' ? '开启本轮填报' : '结束本轮填报' }}
</a-button>
</Col>
</Row>
</PageCard>
</div>
<BasicTable @register="registerTable" :title="'招标计划填报'"> <BasicTable @register="registerTable" :title="'招标计划填报'">
<template #toolbar> <template #toolbar>
<a-button type="primary" preIcon="mdi:plus" @click="handleCreate"> 新增招标计划 </a-button> <a-button type="primary" preIcon="mdi:plus" @click="handleCreate"> 新增招标计划 </a-button>
...@@ -30,6 +94,9 @@ ...@@ -30,6 +94,9 @@
{ {
label: '编辑', label: '编辑',
onClick: handleEdit.bind(null, record, 0), onClick: handleEdit.bind(null, record, 0),
ifShow: (_action) => {
return record.isEdit === '0';
},
}, },
{ {
label: '删除', label: '删除',
...@@ -58,11 +125,20 @@ ...@@ -58,11 +125,20 @@
</template> </template>
</BasicTable> </BasicTable>
<yearModal @register="register" @close="handleNew" /> <yearModal @register="register" @close="handleNew" />
<CycleModel @register="registerCycleModel" :user-data="mothCycle" @get-cycle="getSetCycle" />
<FillDetailsModel @register="registerFillDetail"></FillDetailsModel>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { BasicTable, useTable, TableAction } from '@/components/Table'; import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getListByPage, deleteItem, auditItem, selectCount } from '@/api/project/biddingPlan'; import {
getListByPage,
deleteItem,
auditItem,
selectCount,
getTenderPlanMothCycel,
SetTenderPlanEditStatus
} from '@/api/project/biddingPlan';
import { useModal } from '@/components/Modal'; import { useModal } from '@/components/Modal';
import yearModal from '@/components/yearModal.vue'; import yearModal from '@/components/yearModal.vue';
import { columns, searchFormSchema } from './biddingPlan.data'; import { columns, searchFormSchema } from './biddingPlan.data';
...@@ -72,13 +148,17 @@ ...@@ -72,13 +148,17 @@
//审核相关操作 //审核相关操作
import { operateType, addItemApi, addItemData } from '@/api/operations/operations'; import { operateType, addItemApi, addItemData } from '@/api/operations/operations';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { getDepartmentList } from '@/api/project/settlementManage';
import {useUserStore} from "@/store/modules/user"; import {useUserStore} from "@/store/modules/user";
import PageCard from '@/components/Page/src/PageCard.vue';
import CycleModel from '@/views/biddingPlan/cycleModel/cycleModel.vue';
import FillDetailsModel from "@/views/biddingPlan/fillDetailsModel/fillDetailsModel.vue";
import {Divider,Row, Col} from 'ant-design-vue'
const deptId = ref('');
const { createMessage } = useMessage(); const { createMessage } = useMessage();
const { error } = createMessage; const { error } = createMessage;
const { push } = useRouter(); const { push } = useRouter();
const [registerFillDetail, { openModal: openFillDetailModel }] = useModal();
const [registerCycleModel, { openModal: openCycleModel }] = useModal();
const [register, { openModal: openModal, closeModal: closeModal }] = useModal(); const [register, { openModal: openModal, closeModal: closeModal }] = useModal();
const [registerTable, { reload }] = useTable({ const [registerTable, { reload }] = useTable({
api: getListByPage, api: getListByPage,
...@@ -100,17 +180,94 @@ ...@@ -100,17 +180,94 @@
}, },
}); });
const isExamine = ref<boolean>(false); const isExamine = ref<boolean>(false);
const deptId = ref(100);
const mothCycle = ref({
beginTime: '2024-07-01',
endTime: '2024-09-02',
fillCycle:'2024-09',
isEdit: '0',
deptNum: 12,
noNum: 6,
});
onMounted(async () => { onMounted(async () => {
deptId.value = useUserStore().userInfo.deptParentId;
let roles = useUserStore().userInfo.roles; let roles = useUserStore().userInfo.roles;
roles.forEach((item) => { roles.forEach((item) => {
if (item.role_key === 'approver') { if (item.role_key === 'approver') {
isExamine.value = true; isExamine.value = true;
} }
}); });
const data = await getDepartmentList(); const cycle = await getTenderPlanMothCycel();
searchFormSchema[2].componentProps.options = data; mothCycle.value = cycle;
console.log(cycle, "cycle")
// const data = await getDepartmentList();
// searchFormSchema[2].componentProps.options = data;
}); });
function returnEdit() {
const fillCycle = mothCycle.value.fillCycle;
const [tenderYear, biddingQuarter] = fillCycle.split('年');
mothCycle.value.tenderYear = tenderYear
mothCycle.value.biddingQuarter = biddingQuarter
console.log('mothCycle.value',mothCycle.value)
if (mothCycle.value.isEdit == '1') {
mothCycle.value.isEdit = '0';
SetTenderPlanEditStatus(mothCycle.value);
} else {
mothCycle.value.isEdit = '1';
SetTenderPlanEditStatus(mothCycle.value);
}
reload();
}
function daysReturn() {
// 获取今天的日期
const today = new Date();
// 获取目标年份和月份
const fillCycle = mothCycle.value.fillCycle;
const [targetYearStr, quarterStr] = fillCycle.split('年');
const targetYear = parseInt(targetYearStr, 10);
let targetMonth = 0;
switch (quarterStr) {
case '第一季度':
targetMonth = 2;
break;
case '第二季度':
targetMonth = 5;
break;
case '第三季度':
targetMonth = 8;
break;
case '第四季度':
targetMonth = 11;
break;
default:
return null;
}
// 创建目标日期(2024年9月30日)
const targetDate = new Date(targetYear, targetMonth, 0); // 0表示上一个月的最后一天,即9月30日
console.log(targetDate, '目标日期')
// 计算时间差(毫秒)
const timeDifference = targetDate - today;
// 计算天数差(天数 = 毫秒差 / 每天的毫秒数)
const daysUntilTarget = Math.max(0, Math.ceil(timeDifference / (1000 * 60 * 60 * 24)));
return daysUntilTarget
}
function selectCycle() {
openCycleModel(true, {
data: mothCycle.value,
});
}
function getFillDetails(){
openFillDetailModel(true,{
data:mothCycle.value
})
}
async function getSetCycle() {
const cycle = await getTenderPlanMothCycel();
mothCycle.value = cycle;
}
function handleCreate() { function handleCreate() {
openModal(true, { openModal(true, {
data: ['year', 'quarter'], data: ['year', 'quarter'],
...@@ -157,3 +314,30 @@ ...@@ -157,3 +314,30 @@
reload(); reload();
} }
</script> </script>
<style scoped>
.btn {
margin-right: 10px;
margin-top: 8px;
}
.cycleFrame{
border: 1px solid rgba(22, 106, 203, 0.10);
border-radius: 6px;
padding: 20px 50px;
margin-right: 20px;
display: flex;
justify-content: space-between;
.card{
display: flex;
.cycleIcon{
margin-right: 10px;
}
.characte{
display: flex;
flex-direction: column;
justify-content: space-around;
.top{}
.bottom{}
}
}
}
</style>
<template>
<BasicModal
v-bind="$attrs"
@register="register"
title="设置填报周期"
:minHeight="30"
okText="保存"
@ok="handleSubmit"
>
<BasicForm @register="registerForm" :model="modelRef" />
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue';
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, FormSchema, useForm } from '@/components/Form';
import {SetSettlementMothCycelEdit} from "@/api/project/settlementManage";
const props = defineProps({
userData: { type: Object },
});
const emit = defineEmits(['getCycle', 'register']);
const modelRef = ref({});
const [registerForm, { getFieldsValue, validate }] = useForm({
labelWidth: 100,
schemas: [
// {
// field: 'fillCycle',
// label: '填报周期',
// component: 'DatePicker',
// defaultValue: '',
// required: true,
// componentProps: {
// placeholder: '请选择填报周期',
// picker: 'month',
// valueFormat: 'YYYY-MM',
// format: 'YYYY-MM',
// style: {
// width: '100%',
// },
// },
// },
{
field: 'year',
label: '选择填报周期',
component: 'DatePicker',
required: true,
componentProps: {
placeholder: '选择填报周期',
picker: 'year',
style: { width: '100%' },
valueFormat: 'YYYY',
format: 'YYYY',
},
colProps: { span: 12 },
},
{
field: 'quarter',
label: '季度',
component: 'Select',
required: true,
componentProps: {
style: { width: '100%' },
options: [
{
label: '第一季度',
value: '第一季度',
},
{
label: '第二季度',
value: '第二季度',
},
{
label: '第三季度',
value: '第三季度',
},
{
label: '第四季度',
value: '第四季度',
},
],
placeholder: '季度',
},
colProps: { span: 12 },
},
],
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const cycleData = ref({
beginTime: '2024-07-01',
endTime: '2024-09-02',
fillCycle: '2024-09',
isEdit: '0',
deptNum: 12,
noNum: 6,
});
const [register, { closeModal }] = useModalInner((data) => {
console.log(data.data);
cycleData.value = data.data;
});
function handleSubmit() {
validate().then(() => {
const value = getFieldsValue();
cycleData.value.fillCycle = value.year + value.quarter;
console.log('!!!!!!!!-', cycleData.value.fillCycle)
SetSettlementMothCycelEdit(cycleData.value).then(() => {
emit('getCycle');
console.log('2123', cycleData.value);
});
closeModal();
});
}
</script>
<template>
<BasicModal v-bind="$attrs" width="80%" @register="register" :title="getTitle" :showOkBtn="false">
<Table
:pagination="false"
:dataSource="dataSource"
:columns="columns"
bordered
:sticky="true"
:loading="loadingRef"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'comStatus'">
<Tag color="green" v-if="record.comStatus == '1'"> 已完成 </Tag>
<Tag color="red" v-else> 未完成 </Tag>
</template>
</template>
</Table>
</BasicModal>
</template>
<script setup lang="ts">
import { useModalInner } from '@/components/Modal';
import BasicModal from '@/components/Modal/src/BasicModal.vue';
import { ref } from 'vue';
import {Table, Tag} from 'ant-design-vue';
import {getSettlementFillComDetails} from "@/api/project/settlementManage";
const loadingRef = ref(false);
// 列表
const dataSource = ref([]);
// 表头
const columns = [
{
title: '公司名称',
dataIndex: 'companyName',
width: 200,
},
{
title: '完成状态',
dataIndex: 'comStatus',
width: 180,
},
{
title: '上报时间',
dataIndex: 'updateTime',
width: 150,
},
];
const getTitle = ref('');
const params = ref({ mothCycle: '' });
const [register, { closeModal }] = useModalInner(async (data) => {
params.value.mothCycle = data.data.fillCycle;
dataSource.value = await getSettlementFillComDetails(params.value);
// console.log('212', list);
});
</script>
<style scoped lang="less"></style>
<template> <template>
<div> <div>
<div v-if="deptId == 100 || deptId == 0" style="margin: 16px">
<PageCard title="数据填报周期">
<Row>
<Col :span="20">
<div class="cycleFrame">
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/tianbaoriqi.png" />
</div>
<div class="characte">
<div class="top">填报周期</div>
<div @click="selectCycle" class="bottom" style="color: #0d84ff; text-decoration: underline; cursor: pointer">{{ mothCycle.fillCycle}}</div>
</div>
</div>
<Divider type="vertical" style="height: 36px; border-color: rgba(22,106,203,0.30)" dashed />
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/shenyutianshu.png" />
</div>
<div class="characte">
<div class="top">剩余天数</div>
<div class="bottom" style="color:#DFAA21 ">{{
daysReturn() + '天'
}}</div>
</div>
</div>
<Divider type="vertical" style="height: 36px; border-color: rgba(22,106,203,0.30)" dashed />
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/weiwancheng.png" />
</div>
<div class="characte">
<div class="top">企业未完成</div>
<div class="bottom" style="color:#DB4343">{{
mothCycle.noNum + '家'
}}</div>
</div>
</div>
<Divider type="vertical" style="height: 36px; border-color: rgba(22,106,203,0.30)" dashed />
<div class="card">
<div class="cycleIcon">
<img src="@/assets/icons/yiwancheng.png" />
</div>
<div class="characte">
<div class="top">企业已完成</div>
<div class="bottom" style="color:#16CB28">{{
mothCycle.deptNum - mothCycle.noNum + '家'
}}</div>
</div>
</div>
</div>
</Col>
<Col :span="4">
<a-button class="btn" @click="getFillDetails">
查看填报详情
</a-button>
<a-button class="btn" type="primary" @click="returnEdit">
{{ mothCycle.isEdit === '1' ? '开启本轮填报' : '结束本轮填报' }}
</a-button>
</Col>
</Row>
</PageCard>
</div>
<BasicTable @register="registerTable" :title="'结算管理填报'"> <BasicTable @register="registerTable" :title="'结算管理填报'">
<template #toolbar> <template #toolbar>
...@@ -28,8 +92,11 @@ ...@@ -28,8 +92,11 @@
}, },
}, },
{ {
label: '编辑', label: '修改',
onClick: handleEdit.bind(null, record,true), onClick: handleEdit.bind(null, record,true),
ifShow: (_action) => {
return record.isEdit === '0';
},
}, },
{ {
label: '删除', label: '删除',
...@@ -47,6 +114,9 @@ ...@@ -47,6 +114,9 @@
{ {
label: '修改', label: '修改',
onClick: handleEdit.bind(null, record, true), onClick: handleEdit.bind(null, record, true),
ifShow: (_action) => {
return record.isEdit === '0';
},
}, },
{ {
label: '详情', label: '详情',
...@@ -67,6 +137,8 @@ ...@@ -67,6 +137,8 @@
</template> </template>
</BasicTable> </BasicTable>
<yearModal @register="register" @close="handleNew"/> <yearModal @register="register" @close="handleNew"/>
<CycleModel @register="registerCycleModel" :user-data="mothCycle" @get-cycle="getSetCycle" />
<FillDetailsModel @register="registerFillDetail"></FillDetailsModel>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
...@@ -82,17 +154,31 @@ import {useRouter} from "vue-router"; ...@@ -82,17 +154,31 @@ import {useRouter} from "vue-router";
import {onMounted,ref} from "vue" import {onMounted,ref} from "vue"
const [register, {openModal: openModal, closeModal: closeModal}] = useModal(); const [register, {openModal: openModal, closeModal: closeModal}] = useModal();
import {getListByPage, auditItem, getDepartmentList, isSettlement} from '@/api/project/settlementManage'; import {
getListByPage,
auditItem,
getDepartmentList,
isSettlement,
getSettlementMothCycel,
SetSettlementEditStatus
} from '@/api/project/settlementManage';
import {deleteList} from "@/api/project/settlementManage" import {deleteList} from "@/api/project/settlementManage"
import {columns, searchFormSchema} from './data'; import {columns, searchFormSchema} from './data';
import {useDrawer} from '@/components/Drawer'; import {useDrawer} from '@/components/Drawer';
import PageCard from '@/components/Page/src/PageCard.vue';
import CycleModel from '@/views/settlementManagement/cycleModel/cycleModel.vue';
import FillDetailsModel from "@/views/settlementManagement/fillDetailsModel/fillDetailsModel.vue";
import {Divider,Row, Col} from 'ant-design-vue'
const {createMessage} = useMessage(); const {createMessage} = useMessage();
import {Tag} from "ant-design-vue"; import {Tag} from "ant-design-vue";
import {useMessage} from "@/hooks/web/useMessage"; import {useMessage} from "@/hooks/web/useMessage";
import {useUserStore} from "@/store/modules/user"; import {useUserStore} from "@/store/modules/user";
import {getMonthlyPlanList, getMothCycel, SetEditStatus} from "@/api/project/monthlyPlan";
defineOptions({name: 'SettlementManagement'}); defineOptions({name: 'SettlementManagement'});
const [registerFillDetail, { openModal: openFillDetailModel }] = useModal();
const [registerCycleModel, { openModal: openCycleModel }] = useModal();
const [registerDrawer, {openDrawer}] = useDrawer(); const [registerDrawer, {openDrawer}] = useDrawer();
const [registerTable, {reload}] = useTable({ const [registerTable, {reload}] = useTable({
api: getListByPage, api: getListByPage,
...@@ -114,7 +200,17 @@ const [registerTable, {reload}] = useTable({ ...@@ -114,7 +200,17 @@ const [registerTable, {reload}] = useTable({
}, },
}); });
const isExamine = ref<boolean>(false); const isExamine = ref<boolean>(false);
const deptId = ref(100);
const mothCycle = ref({
beginTime: '2024-07-01',
endTime: '2024-09-02',
fillCycle:'2024-09',
isEdit: '0',
deptNum: 12,
noNum: 6,
});
onMounted(async () => { onMounted(async () => {
deptId.value = useUserStore().userInfo.deptParentId;
let roles = useUserStore().userInfo.roles; let roles = useUserStore().userInfo.roles;
roles.forEach((item) => { roles.forEach((item) => {
if (item.role_key === 'approver') { if (item.role_key === 'approver') {
...@@ -129,10 +225,72 @@ onMounted(async () => { ...@@ -129,10 +225,72 @@ onMounted(async () => {
value: item.label, value: item.label,
label: item.label label: item.label
})); }));
const cycle = await getSettlementMothCycel();
mothCycle.value = cycle;
console.log(cycle, "cycle")
console.log(searchFormSchema[2].componentProps.options, "数据仓库") console.log(searchFormSchema[2].componentProps.options, "数据仓库")
}) })
function returnEdit() {
console.log();
if (mothCycle.value.isEdit == '1') {
mothCycle.value.isEdit = '0';
SetSettlementEditStatus(mothCycle.value);
} else {
mothCycle.value.isEdit = '1';
SetSettlementEditStatus(mothCycle.value);
}
reload();
}
function daysReturn() {
// 获取今天的日期
const today = new Date();
// 获取目标年份和月份
const fillCycle = mothCycle.value.fillCycle;
const [targetYearStr, quarterStr] = fillCycle.split('年');
const targetYear = parseInt(targetYearStr, 10);
let targetMonth = 0;
switch (quarterStr) {
case '第一季度':
targetMonth = 2;
break;
case '第二季度':
targetMonth = 5;
break;
case '第三季度':
targetMonth = 8;
break;
case '第四季度':
targetMonth = 11;
break;
default:
return null;
}
// 创建目标日期(2024年9月30日)
const targetDate = new Date(targetYear, targetMonth, 0);
console.log(targetDate, '目标日期')
// 计算时间差(毫秒)
const timeDifference = targetDate - today;
// 计算天数差(天数 = 毫秒差 / 每天的毫秒数)
const daysUntilTarget = Math.max(0, Math.ceil(timeDifference / (1000 * 60 * 60 * 24)));
return daysUntilTarget
}
function selectCycle() {
openCycleModel(true, {
data: mothCycle.value,
});
}
function getFillDetails(){
openFillDetailModel(true,{
data:mothCycle.value
})
}
async function getSetCycle() {
const cycle = await getSettlementMothCycel();
mothCycle.value = cycle;
}
function handleEdit(record: Recordable, disabled: boolean) { function handleEdit(record: Recordable, disabled: boolean) {
console.log(record, "ddddd") console.log(record, "ddddd")
push({ push({
...@@ -206,3 +364,30 @@ const handleNew = (e) => { ...@@ -206,3 +364,30 @@ const handleNew = (e) => {
}; };
</script> </script>
<style scoped>
.btn {
margin-right: 10px;
margin-top: 8px;
}
.cycleFrame{
border: 1px solid rgba(22, 106, 203, 0.10);
border-radius: 6px;
padding: 20px 50px;
margin-right: 20px;
display: flex;
justify-content: space-between;
.card{
display: flex;
.cycleIcon{
margin-right: 10px;
}
.characte{
display: flex;
flex-direction: column;
justify-content: space-around;
.top{}
.bottom{}
}
}
}
</style>
...@@ -304,12 +304,7 @@ async function deleteItemCon(index: any, key: any) { ...@@ -304,12 +304,7 @@ async function deleteItemCon(index: any, key: any) {
{field: 'sumOfMoney', required: false}, {field: 'sumOfMoney', required: false},
{field: 'proportionContractAmount', required: false}, {field: 'proportionContractAmount', required: false},
{field: 'meetingMinutes', required: false}, {field: 'meetingMinutes', required: false},
{ {field: 'remark', required: false},
field: 'remark',
dynamicRules: ({values}) => {
return [{required: false}];
},
},
]); ]);
} else { } else {
updateSchema([ updateSchema([
...@@ -331,12 +326,7 @@ async function deleteItemCon(index: any, key: any) { ...@@ -331,12 +326,7 @@ async function deleteItemCon(index: any, key: any) {
{field: 'sumOfMoney', required: true}, {field: 'sumOfMoney', required: true},
{field: 'proportionContractAmount', required: true}, {field: 'proportionContractAmount', required: true},
{field: 'meetingMinutes', required: true}, {field: 'meetingMinutes', required: true},
{ {field: 'remark', required: false},
field: 'remark',
dynamicRules: ({values}) => {
return [{required: false}];
},
},
]); ]);
} }
}); });
...@@ -395,7 +385,8 @@ async function deleteItemCon(index: any, key: any) { ...@@ -395,7 +385,8 @@ async function deleteItemCon(index: any, key: any) {
createMessage.success('提交成功!'); createMessage.success('提交成功!');
} }
}catch (e){ }catch (e){
createMessage.error('e'); // createMessage.error('e');
createMessage.error('请将项目' + e.values.projectName + '信息填写完整!');
}finally { }finally {
loading.value = false; loading.value = false;
} }
......
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