进度计划添加计划,添加日报
This commit is contained in:
@ -31,8 +31,10 @@ onMounted(() => {
|
|||||||
|
|
||||||
input {
|
input {
|
||||||
-webkit-user-select: auto; /*webkit浏览器*/
|
-webkit-user-select: auto; /*webkit浏览器*/
|
||||||
|
user-select: auto;
|
||||||
}
|
}
|
||||||
textarea {
|
textarea {
|
||||||
|
user-select: auto;
|
||||||
-webkit-user-select: auto; /*webkit浏览器*/
|
-webkit-user-select: auto; /*webkit浏览器*/
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import { AxiosPromise } from 'axios';
|
import { AxiosPromise } from 'axios';
|
||||||
import { ProgressCategoryVO, ProgressCategoryForm, ProgressCategoryQuery } from '@/api/progress/plan/types';
|
import { ProgressCategoryVO, ProgressCategoryForm, ProgressCategoryQuery, ProgressPlanForm, lastTimeVo, workScheduleListVO, workScheduleListQuery, progressPlanDetailForm } from '@/api/progress/plan/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询进度类别列表
|
* 查询进度类别列表
|
||||||
@ -74,8 +74,55 @@ export const getProjectSquare = (projectId: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const lastTime=()=>{}
|
/**
|
||||||
export const workScheduleAddPlan=()=>{}
|
* 获取进度类别最后一次进度信息
|
||||||
export const workScheduleList=()=>{}
|
* @param id
|
||||||
|
*/
|
||||||
|
export const lastTime = (id: string | number ):AxiosPromise<lastTimeVo> => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressCategory/lastTime/' + id,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增进度计划
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const workScheduleAddPlan = (data: ProgressPlanForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressPlan',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取进度计划详细信息
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const workScheduleList = (query: workScheduleListQuery):AxiosPromise<workScheduleListVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressPlan/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增进度计划详情(百分比设施)
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const workScheduleSubmit = (data: progressPlanDetailForm) => {
|
||||||
|
return request({
|
||||||
|
url: '/progress/progressPlanDetail/insert/percentage',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
};
|
||||||
export const workScheduleDel=()=>{}
|
export const workScheduleDel=()=>{}
|
||||||
export const workScheduleSubmit=()=>{}
|
|
||||||
|
export const pvModuleList=()=>{}
|
||||||
|
export const addDaily=()=>{}
|
||||||
|
export const getDailyBook=()=>{}
|
||||||
|
export const deleteDaily=()=>{}
|
@ -23,11 +23,11 @@ export interface ProgressCategoryVO {
|
|||||||
* 项目id(0表示共用)
|
* 项目id(0表示共用)
|
||||||
*/
|
*/
|
||||||
projectId: string | number;
|
projectId: string | number;
|
||||||
|
matrixId?: string | number;
|
||||||
/**
|
/**
|
||||||
* 子对象
|
* 子对象
|
||||||
*/
|
*/
|
||||||
children: ProgressCategoryVO[];
|
children: ProgressCategoryVO[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProgressCategoryForm extends BaseEntity {
|
export interface ProgressCategoryForm extends BaseEntity {
|
||||||
@ -55,13 +55,57 @@ export interface ProgressCategoryForm extends BaseEntity {
|
|||||||
* 项目id(0表示共用)
|
* 项目id(0表示共用)
|
||||||
*/
|
*/
|
||||||
projectId?: string | number;
|
projectId?: string | number;
|
||||||
matrixId?: string | number;
|
matrixId?: string | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProgressPlanForm {
|
||||||
|
projectId?: string | number;
|
||||||
|
matrixId?: string | number;
|
||||||
|
progressCategoryId?: string | number;
|
||||||
|
startDate?: string;
|
||||||
|
endDate?: string;
|
||||||
|
planNumber?: number;
|
||||||
|
detailList: {
|
||||||
|
date: string;
|
||||||
|
planNumber: number;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface workScheduleListVO {
|
||||||
|
id: string | number;
|
||||||
|
progressCategoryId: string | number;
|
||||||
|
progressCategoryName: string;
|
||||||
|
startDate: string;
|
||||||
|
endDate: string;
|
||||||
|
planNumber: number;
|
||||||
|
finishedNumber: number;
|
||||||
|
detailList: {
|
||||||
|
id: string | number;
|
||||||
|
date: string;
|
||||||
|
planNumber: number;
|
||||||
|
finishedNumber: number;
|
||||||
|
aiFill: boolean;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface progressPlanDetailForm {
|
||||||
|
id: string | number;
|
||||||
|
finishedNumber: number;
|
||||||
|
submitTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface workScheduleListQuery {
|
||||||
|
progressCategoryId?: string | number;
|
||||||
|
pageSize?: number;
|
||||||
|
pageNum?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface lastTimeVo {
|
||||||
|
endDate: string;
|
||||||
|
leftNum: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProgressCategoryQuery {
|
export interface ProgressCategoryQuery {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 父类别id
|
* 父类别id
|
||||||
*/
|
*/
|
||||||
@ -82,15 +126,12 @@ export interface ProgressCategoryQuery {
|
|||||||
*/
|
*/
|
||||||
projectId?: string | number;
|
projectId?: string | number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日期范围参数
|
* 日期范围参数
|
||||||
*/
|
*/
|
||||||
params?: any;
|
params?: any;
|
||||||
/**
|
/**
|
||||||
* 方阵id
|
* 方阵id
|
||||||
*/
|
*/
|
||||||
matrixId?: string | number;
|
matrixId?: string | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,19 +22,23 @@
|
|||||||
<div style="margin-left: 45px" m="4">
|
<div style="margin-left: 45px" m="4">
|
||||||
<el-table
|
<el-table
|
||||||
:border="true"
|
:border="true"
|
||||||
:data="props.row.detail"
|
:data="props.row.detailList"
|
||||||
:header-cell-style="{ 'text-align': 'center' }"
|
:header-cell-style="{ 'text-align': 'center' }"
|
||||||
:cell-style="{ 'text-align': 'center' }"
|
:cell-style="{ 'text-align': 'center' }"
|
||||||
highlight-current-row
|
highlight-current-row
|
||||||
>
|
>
|
||||||
<el-table-column label="序号" type="index" width="50px" />
|
<el-table-column label="序号" type="index" width="60px" />
|
||||||
<el-table-column label="计划日期" prop="date"> </el-table-column>
|
<el-table-column label="计划日期" prop="date">
|
||||||
<el-table-column label="数量" prop="planNum" width="60" />
|
<template #default="scope">
|
||||||
<el-table-column label="完成量" prop="finishedNum" width="60" />
|
<span class="text-3">{{ scope.row.date }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="数量" prop="planNumber" width="60" />
|
||||||
|
<el-table-column label="完成量" prop="finishedNumber" width="65" />
|
||||||
<el-table-column label="操作" class-name="small-padding" width="80px" fixed="right">
|
<el-table-column label="操作" class-name="small-padding" width="80px" fixed="right">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button type="primary" link @click="handleDayAdd(scope.row, props.row)"
|
<el-button type="primary" link @click="handleDayAdd(scope.row, props.row)"
|
||||||
><el-icon><ele-Plus /></el-icon>日报</el-button
|
><el-icon><Plus /></el-icon>日报</el-button
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -42,11 +46,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="序号" type="index" :index="indexMethod" width="50px" />
|
<el-table-column label="序号" type="index" :index="indexMethod" width="60px" />
|
||||||
<el-table-column label="计划数量" prop="planNum" min-width="100px" />
|
<el-table-column label="计划数量" prop="planNumber" min-width="100px" />
|
||||||
<el-table-column label="开始时间" min-width="100px">
|
<el-table-column label="开始时间" min-width="100px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.startAt.split(' ')[0] }}</span>
|
<span>{{ scope.row.startDate.split(' ')[0] }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -62,10 +66,10 @@
|
|||||||
<div class="box_form" v-if="formDetail.submitTime">
|
<div class="box_form" v-if="formDetail.submitTime">
|
||||||
<span>{{ dayDetail.date }}</span>
|
<span>{{ dayDetail.date }}</span>
|
||||||
<el-form size="large" ref="formRef" :model="formDetail" :rules="rules" label-width="110px">
|
<el-form size="large" ref="formRef" :model="formDetail" :rules="rules" label-width="110px">
|
||||||
<el-form-item label="实际完成数量" prop="finishedNum">
|
<el-form-item label="实际完成数量" prop="finishedNumber">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="18">
|
<el-col :span="18">
|
||||||
<el-input type="number" :min="0" v-model="formDetail.finishedNum" placeholder="请输入实际完成数量"> </el-input
|
<el-input type="number" :min="0" v-model="formDetail.finishedNumber" placeholder="请输入实际完成数量"> </el-input
|
||||||
></el-col>
|
></el-col>
|
||||||
</el-row> </el-form-item
|
</el-row> </el-form-item
|
||||||
></el-form>
|
></el-form>
|
||||||
@ -85,15 +89,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, reactive, toRefs, getCurrentInstance } from 'vue';
|
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import { workScheduleList, workScheduleDel, workScheduleSubmit } from '@/api/progress/plan';
|
import { workScheduleList, workScheduleDel, workScheduleSubmit } from '@/api/progress/plan';
|
||||||
|
import { progressPlanDetailForm, workScheduleListQuery } from '@/api/progress/plan/types';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as any;
|
const { proxy } = getCurrentInstance() as any;
|
||||||
|
|
||||||
const menuRef = ref();
|
const menuRef = ref();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
|
const rowData = ref(null);
|
||||||
const expandRowKeys = ref([]);
|
const expandRowKeys = ref([]);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const isShowDialog = ref(false);
|
const isShowDialog = ref(false);
|
||||||
@ -101,26 +105,25 @@ const tableData = ref([]);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const oldLength = ref(0);
|
const oldLength = ref(0);
|
||||||
|
|
||||||
const queryParams = reactive({
|
const queryParams = reactive<workScheduleListQuery>({
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
workId: ''
|
progressCategoryId: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const infoDetail = reactive({
|
const infoDetail = reactive({
|
||||||
name: ''
|
name: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const formDetail = reactive({
|
const formDetail = reactive<progressPlanDetailForm>({
|
||||||
workId: '',
|
|
||||||
id: '',
|
id: '',
|
||||||
submitTime: '',
|
submitTime: '',
|
||||||
finishedNum: 0
|
finishedNumber: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
const dayDetail = reactive({
|
const dayDetail = reactive({
|
||||||
date: '',
|
date: '',
|
||||||
finishedNum: 0
|
finishedNumber: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
@ -128,20 +131,20 @@ const rules = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const openDialog = (row: any) => {
|
const openDialog = (row: any) => {
|
||||||
queryParams.workId = row.work_id;
|
queryParams.progressCategoryId = row.id;
|
||||||
formDetail.workId = row.work_id;
|
|
||||||
infoDetail.name = row.name;
|
infoDetail.name = row.name;
|
||||||
isShowDialog.value = true;
|
isShowDialog.value = true;
|
||||||
|
rowData.value = row;
|
||||||
getWorkList(true);
|
getWorkList(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getWorkList = (bool = false) => {
|
const getWorkList = (bool = false) => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
workScheduleList(queryParams).then((res: any) => {
|
workScheduleList(queryParams).then((res: any) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 200) {
|
||||||
tableData.value = res.data.list.map((item: any, index: number) => ({ ...item, index: index + 1 }));
|
tableData.value = res.rows.map((item: any, index: number) => ({ ...item, index: index + 1 }));
|
||||||
if (bool) oldLength.value = res.data.list.length;
|
if (bool) oldLength.value = res.rows.length;
|
||||||
total.value = res.data.total;
|
total.value = res.rows.total;
|
||||||
}
|
}
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
@ -156,45 +159,27 @@ const onCancel = () => {
|
|||||||
closeDialog();
|
closeDialog();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = (row: any) => {
|
|
||||||
ElMessageBox.confirm('你确定要删除所选计划?', '温馨提示', {
|
|
||||||
confirmButtonText: '确认',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
workScheduleDel({ ids: [row.id] }).then((res: any) => {
|
|
||||||
if (res.code === 0) {
|
|
||||||
ElMessage.success('删除成功');
|
|
||||||
getWorkList();
|
|
||||||
} else {
|
|
||||||
ElMessage.error(res.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
};
|
|
||||||
|
|
||||||
const indexMethod = (index: number) => {
|
const indexMethod = (index: number) => {
|
||||||
const currentPage = queryParams.pageNum - 1;
|
const currentPage = queryParams.pageNum - 1;
|
||||||
return index + 1 + (currentPage > 0 ? currentPage * queryParams.pageSize : 0);
|
return index + 1 + (currentPage > 0 ? currentPage * queryParams.pageSize : 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDayAdd = (row: any, obj: any) => {
|
const handleDayAdd = (row: any, obj: any) => {
|
||||||
formDetail.id = obj.id;
|
formDetail.id = row.id;
|
||||||
formDetail.submitTime = row.date;
|
formDetail.submitTime = row.date;
|
||||||
formDetail.finishedNum = row.finishedNum;
|
formDetail.finishedNumber = row.finishedNumber;
|
||||||
Object.assign(dayDetail, row);
|
Object.assign(dayDetail, row);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAddSubmit = () => {
|
const onAddSubmit = () => {
|
||||||
dayDetail.finishedNum = Number(dayDetail.finishedNum);
|
dayDetail.finishedNumber = Number(dayDetail.finishedNumber);
|
||||||
workScheduleSubmit(formDetail).then((res: any) => {
|
workScheduleSubmit(formDetail).then((res: any) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 200) {
|
||||||
ElMessage.success('添加成功');
|
ElMessage.success('添加成功');
|
||||||
dayDetail.finishedNum = formDetail.finishedNum;
|
dayDetail.finishedNumber = formDetail.finishedNumber;
|
||||||
formDetail.submitTime = '';
|
formDetail.submitTime = '';
|
||||||
formDetail.finishedNum = 0;
|
formDetail.finishedNumber = 0;
|
||||||
|
getWorkList();
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.message);
|
ElMessage.error(res.message);
|
||||||
}
|
}
|
||||||
|
550
src/views/progress/plan/component/createDailyRate.vue
Normal file
550
src/views/progress/plan/component/createDailyRate.vue
Normal file
@ -0,0 +1,550 @@
|
|||||||
|
<template>
|
||||||
|
<div class="daily-paper-count">
|
||||||
|
<el-dialog v-model="isShowDialog" @close="onCancel" width="65vw" :close-on-click-modal="false" :destroy-on-close="true">
|
||||||
|
<template #header>
|
||||||
|
<div v-drag="['.daily-paper-count .el-dialog', '.daily-paper-count .el-dialog__header']" style="font-size: 18px">
|
||||||
|
{{ infoDetail.name }} 日报填写
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-left">
|
||||||
|
<el-table
|
||||||
|
v-loading="loading"
|
||||||
|
:data="tableData"
|
||||||
|
height="64vh"
|
||||||
|
:cell-style="{ textAlign: 'center' }"
|
||||||
|
:header-cell-style="{ textAlign: 'center' }"
|
||||||
|
border
|
||||||
|
:row-key="tableKey"
|
||||||
|
:expand-row-keys="expandRowKeys"
|
||||||
|
@expand-change="clickOpen"
|
||||||
|
>
|
||||||
|
<el-table-column type="expand">
|
||||||
|
<template #default="{ row: propsRow }">
|
||||||
|
<div style="margin-left: 45px" m="4">
|
||||||
|
<el-table
|
||||||
|
:border="true"
|
||||||
|
:data="propsRow.detail"
|
||||||
|
:header-cell-style="{ 'text-align': 'center' }"
|
||||||
|
:cell-style="{ 'text-align': 'center' }"
|
||||||
|
highlight-current-row
|
||||||
|
>
|
||||||
|
<el-table-column label="序号" type="index" width="60px" />
|
||||||
|
<el-table-column label="计划日期" prop="date" />
|
||||||
|
<el-table-column label="数量" prop="planNum" width="60" />
|
||||||
|
<el-table-column label="完成量" prop="finishedNum" width="60" />
|
||||||
|
<el-table-column label="AI填报" prop="autoFill" width="60" />
|
||||||
|
<el-table-column label="操作" class-name="small-padding" width="200px" fixed="right">
|
||||||
|
<template #default="{ row: scopeRow, $index }">
|
||||||
|
<el-button type="primary" link @click="handleDayAdd(scopeRow, propsRow)">
|
||||||
|
<el-icon><ele-Plus /></el-icon>日报
|
||||||
|
</el-button>
|
||||||
|
<el-button type="success" link @click="handleView(scopeRow, propsRow)">
|
||||||
|
<el-icon><ele-View /></el-icon>查看
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="序号" type="index" :index="indexMethod" width="60px" />
|
||||||
|
<el-table-column label="计划数量" prop="planNum" min-width="100px" />
|
||||||
|
<el-table-column label="完成数量" prop="finishedNum" min-width="100px" />
|
||||||
|
<el-table-column label="延期量" min-width="100px">
|
||||||
|
<template #default="{ row: scopeRow }">
|
||||||
|
<el-tag :type="filterW(scopeRow) ? 'danger' : 'success'">
|
||||||
|
{{ filterW(scopeRow) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="AI填报" prop="autoFill" min-width="100px" />
|
||||||
|
<el-table-column label="开始时间" min-width="100px">
|
||||||
|
<template #default="{ row: scopeRow }">
|
||||||
|
<span>{{ scopeRow.startAt.split(' ')[0] }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination
|
||||||
|
v-show="total > 0"
|
||||||
|
:total="total"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getWorkList"
|
||||||
|
layout="total, sizes, prev, pager, next"
|
||||||
|
:isSmall="5"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="box_right" v-if="showDayWork">
|
||||||
|
<div class="time_submit">
|
||||||
|
<span>{{ formDetail.submitTime }}</span>
|
||||||
|
<el-button type="primary" :disabled="!checkedList.length || flag" @click="onUploadDaily" size="large">
|
||||||
|
<el-icon><ele-Upload /></el-icon>提交日报
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
v-loading="loading1"
|
||||||
|
height="58vh"
|
||||||
|
:data="detialList"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
:row-key="(row) => row.id"
|
||||||
|
ref="multipleTableRef"
|
||||||
|
>
|
||||||
|
<el-table-column label="未完成工作" align="center">
|
||||||
|
<el-table-column :reserve-selection="true" type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="序号" align="center" type="index" width="60px" />
|
||||||
|
<el-table-column label="编号" align="center" prop="name" min-width="100px" />
|
||||||
|
<el-table-column label="状态" align="center" min-width="100px">
|
||||||
|
<template #default="{ row: scopeRow }">
|
||||||
|
<el-tag :type="typeList[scopeRow.status]">
|
||||||
|
{{ filterStatus(scopeRow.status) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination
|
||||||
|
v-show="detailTotal > 0"
|
||||||
|
:total="detailTotal"
|
||||||
|
v-model:page="detailQueryParams.pageNum"
|
||||||
|
v-model:limit="detailQueryParams.pageSize"
|
||||||
|
@pagination="getPvModuleList"
|
||||||
|
layout="total, sizes, prev, pager, next"
|
||||||
|
:isSmall="5"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="box_right" v-else>
|
||||||
|
<div class="time_submit">
|
||||||
|
<span>{{ formDetail.submitTime }}</span>
|
||||||
|
<el-button type="danger" :disabled="single" @click="handleRemove(null)" size="large">
|
||||||
|
<el-icon><ele-SemiSelect /></el-icon>批量移除
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
v-loading="loading2"
|
||||||
|
height="58vh"
|
||||||
|
:data="detialWordList"
|
||||||
|
@selection-change="handleSelectionChangeWork"
|
||||||
|
:row-key="(row) => row.id"
|
||||||
|
ref="multipleTableWorkRef"
|
||||||
|
>
|
||||||
|
<el-table-column label="已完成工作" align="center">
|
||||||
|
<el-table-column :reserve-selection="true" type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="序号" align="center" type="index" width="60px" />
|
||||||
|
<el-table-column label="编号" align="center" prop="name" min-width="100px" />
|
||||||
|
<el-table-column label="填报方式" align="center" prop="status" min-width="100px">
|
||||||
|
<template #default="{ row: scopeRow }">
|
||||||
|
<span v-if="scopeRow.status === 2">手动填报</span>
|
||||||
|
<span v-if="scopeRow.status === 3">AI识别</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" min-width="100px">
|
||||||
|
<template #default="{ row: scopeRow }">
|
||||||
|
<el-button type="danger" link @click="handleRemove(scopeRow)">
|
||||||
|
<el-icon><ele-SemiSelect /></el-icon>移除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination
|
||||||
|
v-show="detailTotalWork > 0"
|
||||||
|
:total="detailTotalWork"
|
||||||
|
v-model:page="detailQueryParamsWork.pageNum"
|
||||||
|
v-model:limit="detailQueryParamsWork.pageSize"
|
||||||
|
@pagination="getPvModuleList"
|
||||||
|
layout="total, sizes, prev, pager, next"
|
||||||
|
:isSmall="5"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="onCancel" size="large">关 闭</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, computed, watch, onMounted } from 'vue';
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
|
import { workScheduleList, pvModuleList, addDaily, getDailyBook, deleteDaily } from '@/api/progress/plan';
|
||||||
|
import { workScheduleListQuery } from '@/api/progress/plan/types';
|
||||||
|
|
||||||
|
// 响应式状态
|
||||||
|
const state = reactive<{
|
||||||
|
expandRowKeys: number[];
|
||||||
|
loading: boolean;
|
||||||
|
isShowDialog: boolean;
|
||||||
|
queryParams: workScheduleListQuery;
|
||||||
|
infoDetail: { name: string };
|
||||||
|
tableData: any[];
|
||||||
|
total: number;
|
||||||
|
formDetail: {
|
||||||
|
workId: string;
|
||||||
|
id: string;
|
||||||
|
submitTime: string;
|
||||||
|
finishedNum: number;
|
||||||
|
};
|
||||||
|
detialList: any[];
|
||||||
|
detailTotal: number;
|
||||||
|
detailQueryParams: {
|
||||||
|
pageSize: number;
|
||||||
|
pageNum: number;
|
||||||
|
};
|
||||||
|
loading1: boolean;
|
||||||
|
loading2: boolean;
|
||||||
|
typeList: ('info' | 'warning' | 'success' | 'danger')[];
|
||||||
|
checkedList: number[];
|
||||||
|
updateRow: any | null;
|
||||||
|
showDayWork: boolean;
|
||||||
|
detialWordList: any[];
|
||||||
|
detailTotalWork: number;
|
||||||
|
detailQueryParamsWork: {
|
||||||
|
pageSize: number;
|
||||||
|
pageNum: number;
|
||||||
|
};
|
||||||
|
single: boolean;
|
||||||
|
checkList: number[];
|
||||||
|
flag: boolean;
|
||||||
|
}>({
|
||||||
|
expandRowKeys: [],
|
||||||
|
loading: false,
|
||||||
|
isShowDialog: false,
|
||||||
|
queryParams: {
|
||||||
|
pageSize: 10,
|
||||||
|
pageNum: 1,
|
||||||
|
progressCategoryId: ''
|
||||||
|
},
|
||||||
|
infoDetail: { name: '' },
|
||||||
|
tableData: [],
|
||||||
|
total: 0,
|
||||||
|
formDetail: {
|
||||||
|
workId: '',
|
||||||
|
id: '',
|
||||||
|
submitTime: '选择日期',
|
||||||
|
finishedNum: 0
|
||||||
|
},
|
||||||
|
detialList: [],
|
||||||
|
detailTotal: 0,
|
||||||
|
detailQueryParams: {
|
||||||
|
pageSize: 20,
|
||||||
|
pageNum: 1
|
||||||
|
},
|
||||||
|
loading1: false,
|
||||||
|
loading2: false,
|
||||||
|
typeList: ['info', 'warning', 'success', 'danger'],
|
||||||
|
checkedList: [],
|
||||||
|
updateRow: null,
|
||||||
|
showDayWork: true,
|
||||||
|
detialWordList: [],
|
||||||
|
detailTotalWork: 0,
|
||||||
|
detailQueryParamsWork: {
|
||||||
|
pageSize: 20,
|
||||||
|
pageNum: 1
|
||||||
|
},
|
||||||
|
single: true,
|
||||||
|
checkList: [],
|
||||||
|
flag: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// 引用refs
|
||||||
|
const multipleTableRef = ref();
|
||||||
|
const multipleTableWorkRef = ref();
|
||||||
|
|
||||||
|
// 状态解包
|
||||||
|
const {
|
||||||
|
expandRowKeys,
|
||||||
|
loading,
|
||||||
|
isShowDialog,
|
||||||
|
queryParams,
|
||||||
|
infoDetail,
|
||||||
|
tableData,
|
||||||
|
total,
|
||||||
|
formDetail,
|
||||||
|
detialList,
|
||||||
|
detailTotal,
|
||||||
|
detailQueryParams,
|
||||||
|
loading1,
|
||||||
|
loading2,
|
||||||
|
typeList,
|
||||||
|
checkedList,
|
||||||
|
updateRow,
|
||||||
|
showDayWork,
|
||||||
|
detialWordList,
|
||||||
|
detailTotalWork,
|
||||||
|
detailQueryParamsWork,
|
||||||
|
single,
|
||||||
|
checkList,
|
||||||
|
flag
|
||||||
|
} = toRefs(state);
|
||||||
|
|
||||||
|
// 状态过滤函数
|
||||||
|
const filterStatus = (val: number): string => {
|
||||||
|
switch (val) {
|
||||||
|
case 0:
|
||||||
|
return '未开始';
|
||||||
|
case 1:
|
||||||
|
return '进行中';
|
||||||
|
case 2:
|
||||||
|
return '已完成';
|
||||||
|
case 3:
|
||||||
|
return '已延期';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const openDialog = (row: any) => {
|
||||||
|
resetForm(false);
|
||||||
|
formDetail.value.submitTime = '';
|
||||||
|
queryParams.value.progressCategoryId = row.id;
|
||||||
|
formDetail.value.workId = row.work_id;
|
||||||
|
infoDetail.value = row;
|
||||||
|
state.isShowDialog = true;
|
||||||
|
getWorkList(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetForm = (bool: boolean) => {
|
||||||
|
showDayWork.value = bool;
|
||||||
|
detialList.value = [];
|
||||||
|
detialWordList.value = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取未完成数据
|
||||||
|
const getPvModuleList = () => {
|
||||||
|
loading1.value = true;
|
||||||
|
pvModuleList({
|
||||||
|
workId: formDetail.value.workId,
|
||||||
|
...detailQueryParams.value,
|
||||||
|
type: infoDetail.value.work_type,
|
||||||
|
status: 0
|
||||||
|
}).then((res: any) => {
|
||||||
|
loading1.value = false;
|
||||||
|
if (res.code === 0) {
|
||||||
|
detialList.value = res.data.list;
|
||||||
|
detailTotal.value = res.data.total;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取计划列表
|
||||||
|
const getWorkList = (bool = false) => {
|
||||||
|
loading.value = true;
|
||||||
|
workScheduleList(queryParams.value).then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
state.tableData = res.data.list.map((item: any, i: number) => {
|
||||||
|
item.index = i + 1;
|
||||||
|
item.autoFill = item.detail?.reduce((sum: number, child: any) => sum + child.autoFill, 0) || 0;
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
state.total = res.data.total;
|
||||||
|
}
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const onCancel = () => {
|
||||||
|
closeDialog();
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeDialog = () => {
|
||||||
|
isShowDialog.value = false;
|
||||||
|
emit('getProgressList');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 自定义序号
|
||||||
|
const indexMethod = (index: number): number => {
|
||||||
|
const currentPage = queryParams.value.pageNum - 1;
|
||||||
|
return currentPage > -1 ? index + 1 + currentPage * queryParams.value.pageSize : index + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 日报添加
|
||||||
|
const handleDayAdd = (row: any, obj: any) => {
|
||||||
|
resetForm(true);
|
||||||
|
formDetail.value.id = obj.id;
|
||||||
|
formDetail.value.submitTime = row.date;
|
||||||
|
state.updateRow = row;
|
||||||
|
getPvModuleList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableKey = (row: any) => row.id;
|
||||||
|
|
||||||
|
// 展开行处理
|
||||||
|
const clickOpen = (row: any) => {
|
||||||
|
const index = state.expandRowKeys.indexOf(row.id);
|
||||||
|
index === -1 ? state.expandRowKeys.push(row.id) : state.expandRowKeys.splice(index, 1);
|
||||||
|
state.expandRowKeys = [...new Set(state.expandRowKeys)];
|
||||||
|
};
|
||||||
|
|
||||||
|
// 多选框处理
|
||||||
|
const handleSelectionChange = (selection: any[]) => {
|
||||||
|
state.checkedList = selection.map((item: any) => item.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交日报
|
||||||
|
const onUploadDaily = () => {
|
||||||
|
if (!checkedList.value.length) {
|
||||||
|
ElMessage.warning('请添加完成的任务编号');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj = {
|
||||||
|
ids: checkedList.value,
|
||||||
|
workID: formDetail.value.workId,
|
||||||
|
doneTime: formDetail.value.submitTime,
|
||||||
|
planID: formDetail.value.id
|
||||||
|
};
|
||||||
|
|
||||||
|
state.flag = true;
|
||||||
|
addDaily(obj).then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success('添加成功');
|
||||||
|
if (state.updateRow) {
|
||||||
|
state.updateRow.finishedNum += checkedList.value.length;
|
||||||
|
}
|
||||||
|
checkedList.value = [];
|
||||||
|
multipleTableRef.value?.clearSelection();
|
||||||
|
getPvModuleList();
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.message);
|
||||||
|
}
|
||||||
|
state.flag = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查看日报
|
||||||
|
const handleView = (row: any, obj: any) => {
|
||||||
|
resetForm(false);
|
||||||
|
getDailyBookList(row.date);
|
||||||
|
state.updateRow = row;
|
||||||
|
formDetail.value.id = obj.id;
|
||||||
|
formDetail.value.submitTime = row.date;
|
||||||
|
showDayWork.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取已填日报
|
||||||
|
const getDailyBookList = (doneTime: string) => {
|
||||||
|
detialWordList.value = [];
|
||||||
|
getDailyBook({
|
||||||
|
workId: formDetail.value.workId,
|
||||||
|
type: infoDetail.value.work_type,
|
||||||
|
doneTime
|
||||||
|
}).then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
detialWordList.value = res.data.list || [];
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选中处理(已完成)
|
||||||
|
const handleSelectionChangeWork = (selection: any[]) => {
|
||||||
|
state.checkList = selection.map((item: any) => item.id);
|
||||||
|
state.single = selection.length === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 移除日报
|
||||||
|
const handleRemove = (row?: any) => {
|
||||||
|
const planID = row ? [row.id] : state.checkList;
|
||||||
|
const obj = {
|
||||||
|
planID,
|
||||||
|
id: formDetail.value.id,
|
||||||
|
workID: formDetail.value.workId,
|
||||||
|
time: formDetail.value.submitTime
|
||||||
|
};
|
||||||
|
|
||||||
|
ElMessageBox.confirm('确认移除该条数据?', '温馨提示', {
|
||||||
|
confirmButtonText: '确认',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
deleteDaily(obj).then((res: any) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success('移除成功');
|
||||||
|
if (state.updateRow) {
|
||||||
|
state.updateRow.finishedNum -= planID.length;
|
||||||
|
}
|
||||||
|
getDailyBookList(formDetail.value.submitTime);
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 延期计算
|
||||||
|
const filterW = (row: any): number => {
|
||||||
|
const { finishedNum, planNum, endAt } = row;
|
||||||
|
if (!endAt) return 0;
|
||||||
|
|
||||||
|
const endTime = new Date(endAt).getTime();
|
||||||
|
const now = new Date().getTime();
|
||||||
|
|
||||||
|
if (endTime <= now && planNum > finishedNum) {
|
||||||
|
return planNum - finishedNum;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 暴露给模板的属性和方法
|
||||||
|
defineExpose({
|
||||||
|
openDialog,
|
||||||
|
closeDialog
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['getProgressList']);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.daily-paper-count {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.box {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 10px;
|
||||||
|
|
||||||
|
.box-left {
|
||||||
|
width: 50%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_right {
|
||||||
|
width: 46%;
|
||||||
|
float: left;
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
height: 64vh;
|
||||||
|
margin-left: 20px;
|
||||||
|
|
||||||
|
.time_submit {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
font-size: 20px;
|
||||||
|
font-family: revert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-container {
|
||||||
|
padding: 10px 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-drawer__title {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -19,7 +19,7 @@
|
|||||||
value-format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
||||||
size="large"
|
size="large"
|
||||||
:disabled-date="pickerOptionsStart"
|
:disabled-date="pickerOptionsStart"
|
||||||
:disabled="remainingNumAt.remainingNum === 0"
|
:disabled="remainingNumAt.leftNum === 0"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="结束时间" prop="end_at">
|
<el-form-item label="结束时间" prop="end_at">
|
||||||
@ -31,26 +31,26 @@
|
|||||||
value-format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
||||||
size="large"
|
size="large"
|
||||||
:disabled-date="pickerOptionsEnd"
|
:disabled-date="pickerOptionsEnd"
|
||||||
:disabled="remainingNumAt.remainingNum === 0"
|
:disabled="remainingNumAt.leftNum === 0"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="计划数量" prop="planNum">
|
<el-form-item label="计划数量" prop="planNumber">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="18">
|
<el-col :span="18">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="formData.planNum"
|
v-model="formData.planNumber"
|
||||||
type="number"
|
type="number"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="remainingNumAt.remainingNum"
|
:max="remainingNumAt.leftNum"
|
||||||
:disabled="remainingNumAt.remainingNum === 0"
|
:disabled="remainingNumAt.leftNum === 0"
|
||||||
placeholder="请输入计划数量"
|
placeholder="请输入计划数量"
|
||||||
>
|
>
|
||||||
<template #append>
|
<template #append>
|
||||||
<span style="font-size: 12px">最大值:{{ remainingNumAt.remainingNum }}</span>
|
<span style="font-size: 12px">最大值:{{ remainingNumAt.leftNum }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-button type="primary" @click="onAverage" :disabled="!formData.planNum || tableData.length === 0" style="margin-left: 10px"
|
<el-button type="primary" @click="onAverage" :disabled="!formData.planNumber || tableData.length === 0" style="margin-left: 10px"
|
||||||
>均值</el-button
|
>均值</el-button
|
||||||
>
|
>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -70,9 +70,16 @@
|
|||||||
>
|
>
|
||||||
<el-table-column type="index" :index="indexMethod" label="序号" width="60" />
|
<el-table-column type="index" :index="indexMethod" label="序号" width="60" />
|
||||||
<el-table-column prop="date" label="日期" width="130" />
|
<el-table-column prop="date" label="日期" width="130" />
|
||||||
<el-table-column prop="planNum" label="数量">
|
<el-table-column prop="planNumber" label="数量">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-input-number v-model="scope.row.planNum" :value-on-clear="0" :min="0" :max="scope.row.max" @change="onChangeSum" size="small" />
|
<el-input-number
|
||||||
|
v-model="scope.row.planNumber"
|
||||||
|
:value-on-clear="0"
|
||||||
|
:min="0"
|
||||||
|
:max="scope.row.max"
|
||||||
|
@change="onChangeSum"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -103,6 +110,7 @@
|
|||||||
import { ref, reactive, watch, computed } from 'vue';
|
import { ref, reactive, watch, computed } from 'vue';
|
||||||
import { ElMessage, FormInstance } from 'element-plus';
|
import { ElMessage, FormInstance } from 'element-plus';
|
||||||
import { workScheduleAddPlan, lastTime } from '@/api/progress/plan';
|
import { workScheduleAddPlan, lastTime } from '@/api/progress/plan';
|
||||||
|
import { lastTimeVo, ProgressCategoryVO, ProgressPlanForm } from '@/api/progress/plan/types';
|
||||||
|
|
||||||
// Form refs
|
// Form refs
|
||||||
const formRef = ref<FormInstance | null>(null);
|
const formRef = ref<FormInstance | null>(null);
|
||||||
@ -115,27 +123,40 @@ const pageSize = 10;
|
|||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
start_at: '',
|
start_at: '',
|
||||||
end_at: '',
|
end_at: '',
|
||||||
planNum: 0
|
planNumber: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
start_at: [{ required: true, message: '开始时间不能为空', trigger: 'blur' }],
|
start_at: [{ required: true, message: '开始时间不能为空', trigger: 'blur' }],
|
||||||
end_at: [{ required: true, message: '结束时间不能为空', trigger: 'blur' }],
|
end_at: [{ required: true, message: '结束时间不能为空', trigger: 'blur' }],
|
||||||
planNum: [{ required: true, message: '计划数量不能为空', trigger: 'blur' }]
|
planNumber: [
|
||||||
|
{
|
||||||
|
trigger: 'input', // 用户输入时触发校验
|
||||||
|
validator: (_rule: any, value: string, callback: any) => {
|
||||||
|
const numberValue = Number(value);
|
||||||
|
console.log(numberValue);
|
||||||
|
|
||||||
|
if (value === '') {
|
||||||
|
callback(new Error('请输入值'));
|
||||||
|
} else if (numberValue > remainingNumAt.leftNum) {
|
||||||
|
callback(new Error(`数字不能大于 ${remainingNumAt.leftNum}`));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ required: true, message: '计划数量不能为空', trigger: 'blur' }
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
const infoDetail = reactive({
|
const infoDetail = reactive<ProgressCategoryVO>({} as ProgressCategoryVO);
|
||||||
name: '',
|
|
||||||
work_id: '',
|
const remainingNumAt = reactive<lastTimeVo>({
|
||||||
is_delay: 0
|
endDate: '',
|
||||||
|
leftNum: 100
|
||||||
});
|
});
|
||||||
|
|
||||||
const remainingNumAt = reactive({
|
const tableData = ref<{ date: string; planNumber: number; max: number }[]>([]);
|
||||||
endAt: '',
|
|
||||||
remainingNum: 100
|
|
||||||
});
|
|
||||||
|
|
||||||
const tableData = ref<{ date: string; planNum: number; max: number }[]>([]);
|
|
||||||
|
|
||||||
// Computed paginated data
|
// Computed paginated data
|
||||||
const paginatedData = computed(() => {
|
const paginatedData = computed(() => {
|
||||||
@ -151,8 +172,8 @@ watch(
|
|||||||
const dates = generateDateRange(start, end);
|
const dates = generateDateRange(start, end);
|
||||||
tableData.value = dates.map((date) => ({
|
tableData.value = dates.map((date) => ({
|
||||||
date,
|
date,
|
||||||
planNum: 0,
|
planNumber: 0,
|
||||||
max: remainingNumAt.remainingNum
|
max: remainingNumAt.leftNum
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
tableData.value = [];
|
tableData.value = [];
|
||||||
@ -175,38 +196,38 @@ const generateDateRange = (start: string, end: string): string[] => {
|
|||||||
// Picker rules
|
// Picker rules
|
||||||
const pickerOptionsStart = (date: Date) => {
|
const pickerOptionsStart = (date: Date) => {
|
||||||
if (formData.end_at) return date.getTime() > new Date(formData.end_at).getTime();
|
if (formData.end_at) return date.getTime() > new Date(formData.end_at).getTime();
|
||||||
if (remainingNumAt.endAt) return date.getTime() < new Date(remainingNumAt.endAt).getTime();
|
if (remainingNumAt.endDate) return date.getTime() < new Date(remainingNumAt.endDate).getTime();
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const pickerOptionsEnd = (date: Date) => {
|
const pickerOptionsEnd = (date: Date) => {
|
||||||
if (formData.start_at) return date.getTime() < new Date(formData.start_at).getTime();
|
if (formData.start_at) return date.getTime() < new Date(formData.start_at).getTime();
|
||||||
if (remainingNumAt.endAt) return date.getTime() < new Date(remainingNumAt.endAt).getTime();
|
if (remainingNumAt.endDate) return date.getTime() < new Date(remainingNumAt.endDate).getTime();
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Average calculation
|
// Average calculation
|
||||||
const onAverage = () => {
|
const onAverage = () => {
|
||||||
const total = formData.planNum;
|
const total = formData.planNumber;
|
||||||
const len = tableData.value.length;
|
const len = tableData.value.length;
|
||||||
const avg = Math.floor(total / len);
|
const avg = Math.floor(total / len);
|
||||||
let remainder = total % len;
|
let remainder = total % len;
|
||||||
|
|
||||||
tableData.value.forEach((row) => {
|
tableData.value.forEach((row) => {
|
||||||
row.planNum = avg + (remainder > 0 ? 1 : 0);
|
row.planNumber = avg + (remainder > 0 ? 1 : 0);
|
||||||
remainder--;
|
remainder--;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Total sum validation
|
// Total sum validation
|
||||||
const onChangeSum = () => {
|
const onChangeSum = () => {
|
||||||
let total = tableData.value.reduce((sum, item) => sum + item.planNum, 0);
|
let total = tableData.value.reduce((sum, item) => sum + item.planNumber, 0);
|
||||||
if (total > remainingNumAt.remainingNum) {
|
if (total > remainingNumAt.leftNum) {
|
||||||
tableData.value.forEach((item) => {
|
tableData.value.forEach((item) => {
|
||||||
item.max = item.planNum;
|
item.max = item.planNumber;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
formData.planNum = total;
|
formData.planNumber = total;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Index method
|
// Index method
|
||||||
@ -219,16 +240,18 @@ const onSubmit = () => {
|
|||||||
if (!formRef.value) return;
|
if (!formRef.value) return;
|
||||||
formRef.value.validate((valid) => {
|
formRef.value.validate((valid) => {
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
|
const payload: ProgressPlanForm = {
|
||||||
const payload = {
|
projectId: infoDetail.projectId,
|
||||||
workId: infoDetail.work_id,
|
planNumber: formData.planNumber,
|
||||||
planNum: formData.planNum,
|
detailList: tableData.value,
|
||||||
scheduledTime: tableData.value,
|
startDate: formData.start_at,
|
||||||
is_delay: infoDetail.is_delay === 1 ? 1 : undefined
|
endDate: formData.end_at,
|
||||||
|
progressCategoryId: infoDetail.id,
|
||||||
|
matrixId: infoDetail.matrixId
|
||||||
};
|
};
|
||||||
|
|
||||||
workScheduleAddPlan(payload).then((res: any) => {
|
workScheduleAddPlan(payload).then((res: any) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 200) {
|
||||||
ElMessage.success('添加成功');
|
ElMessage.success('添加成功');
|
||||||
closeDialog();
|
closeDialog();
|
||||||
} else {
|
} else {
|
||||||
@ -253,13 +276,15 @@ const closeDialog = () => {
|
|||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
formData.start_at = '';
|
formData.start_at = '';
|
||||||
formData.end_at = '';
|
formData.end_at = '';
|
||||||
formData.planNum = 0;
|
formData.planNumber = 0;
|
||||||
tableData.value = [];
|
tableData.value = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchLastTime = (row: typeof infoDetail) => {
|
const fetchLastTime = (row: typeof infoDetail) => {
|
||||||
lastTime({ workId: row.work_id, is_delay: row.is_delay }).then((res: any) => {
|
console.log(row);
|
||||||
if (res.code === 0) {
|
|
||||||
|
lastTime(row.id).then((res: any) => {
|
||||||
|
if (res.code === 200) {
|
||||||
Object.assign(remainingNumAt, res.data);
|
Object.assign(remainingNumAt, res.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -6,13 +6,16 @@
|
|||||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
<el-form-item label="请选择方阵:" prop="pid" label-width="100">
|
<el-form-item label="请选择方阵:" prop="pid" label-width="100">
|
||||||
<!-- <el-input v-model="queryParams.pid" placeholder="请选择" clearable /> -->
|
<!-- <el-input v-model="queryParams.pid" placeholder="请选择" clearable /> -->
|
||||||
<el-cascader
|
<!-- <el-cascader
|
||||||
:options="matrixOptions"
|
:options="matrixOptions"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
:props="{ value: 'id', label: 'matrixName' }"
|
:props="{ value: 'id', label: 'matrixName' }"
|
||||||
clearable
|
clearable
|
||||||
/>
|
/> -->
|
||||||
|
<el-select v-model="matrixValue" placeholder="请选择" @change="handleChange" clearable>
|
||||||
|
<el-option v-for="item in matrixOptions" :key="item.id" :label="item.matrixName" :value="item.id" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="Download" @click="handleQuery">导出周报</el-button>
|
<el-button type="primary" icon="Download" @click="handleQuery">导出周报</el-button>
|
||||||
@ -117,7 +120,7 @@
|
|||||||
icon="Plus"
|
icon="Plus"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click="dailyRef.openDialog(scope.row)"
|
@click="handleDayAdd(scope.row)"
|
||||||
v-hasPermi="['progress:progressCategory:add']"
|
v-hasPermi="['progress:progressCategory:add']"
|
||||||
>
|
>
|
||||||
日报
|
日报
|
||||||
@ -162,8 +165,9 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!-- 创建计划对话框 -->
|
<!-- 创建计划对话框 -->
|
||||||
<CreatePlan ref="planRef"></CreatePlan>
|
<CreatePlan ref="planRef" @getProgressList="getList"></CreatePlan>
|
||||||
<CreateDaily ref="dailyRef"></CreateDaily>
|
<CreateDaily ref="dailyRef" @getProgressList="getList"></CreateDaily>
|
||||||
|
<CreateDailyRate ref="dailyRateRef" @getProgressList="getList"></CreateDailyRate>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -183,6 +187,7 @@ const { progress_unit_type, progress_status } = toRefs<any>(proxy?.useDict('prog
|
|||||||
import { useUserStoreHook } from '@/store/modules/user';
|
import { useUserStoreHook } from '@/store/modules/user';
|
||||||
import CreatePlan from './component/createPlan.vue';
|
import CreatePlan from './component/createPlan.vue';
|
||||||
import CreateDaily from './component/createDaily.vue';
|
import CreateDaily from './component/createDaily.vue';
|
||||||
|
import CreateDailyRate from './component/createDailyRate.vue';
|
||||||
type ProgressCategoryOption = {
|
type ProgressCategoryOption = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
@ -201,16 +206,11 @@ const isExpandAll = ref(true);
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const planRef = ref<InstanceType<typeof CreatePlan>>();
|
const planRef = ref<InstanceType<typeof CreatePlan>>();
|
||||||
const dailyRef = ref<InstanceType<typeof CreateDaily>>();
|
const dailyRef = ref<InstanceType<typeof CreateDaily>>();
|
||||||
|
const dailyRateRef = ref<InstanceType<typeof CreateDailyRate>>();
|
||||||
const queryFormRef = ref<ElFormInstance>();
|
const queryFormRef = ref<ElFormInstance>();
|
||||||
const progressCategoryFormRef = ref<ElFormInstance>();
|
const progressCategoryFormRef = ref<ElFormInstance>();
|
||||||
const progressCategoryTableRef = ref<ElTableInstance>();
|
const progressCategoryTableRef = ref<ElTableInstance>();
|
||||||
const matrixOptions = ref([
|
const matrixOptions = ref([]);
|
||||||
{
|
|
||||||
id: currentProject.value.id,
|
|
||||||
matrixName: currentProject.value.name,
|
|
||||||
children: []
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
const dialog = reactive<any>({
|
const dialog = reactive<any>({
|
||||||
dailyStatus: false,
|
dailyStatus: false,
|
||||||
planStatus: false,
|
planStatus: false,
|
||||||
@ -219,7 +219,7 @@ const dialog = reactive<any>({
|
|||||||
title: '',
|
title: '',
|
||||||
file: ''
|
file: ''
|
||||||
});
|
});
|
||||||
|
const matrixValue = ref<number | undefined>(matrixOptions.value.length > 0 ? matrixOptions.value[0].id : undefined);
|
||||||
const initFormData: ProgressCategoryForm = {
|
const initFormData: ProgressCategoryForm = {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
pid: undefined,
|
pid: undefined,
|
||||||
@ -254,9 +254,8 @@ const { queryParams, form, rules } = toRefs(data);
|
|||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
if (!queryParams.value.matrixId) {
|
if (!queryParams.value.matrixId) {
|
||||||
const res = await getProjectSquare(currentProject.value.id);
|
const res = await getProjectSquare(currentProject.value.id);
|
||||||
console.log('🚀 ~ getList ~ res:', res);
|
if (!matrixValue.value) matrixValue.value = res.rows[0].id;
|
||||||
|
matrixOptions.value = res.rows;
|
||||||
matrixOptions.value[0].children = res.rows;
|
|
||||||
queryParams.value.matrixId = res.rows[0].id;
|
queryParams.value.matrixId = res.rows[0].id;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
@ -295,12 +294,20 @@ const handleQuery = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 级联选择器改变事件 */
|
/** 级联选择器改变事件 */
|
||||||
const handleChange = (value: number[]) => {
|
const handleChange = (value: number) => {
|
||||||
queryParams.value.matrixId = value[1];
|
queryParams.value.matrixId = value;
|
||||||
|
|
||||||
getList();
|
getList();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDayAdd = (row: ProgressCategoryVO) => {
|
||||||
|
if (row.unitType === '2') {
|
||||||
|
dailyRef.value.openDialog(row);
|
||||||
|
} else {
|
||||||
|
dailyRateRef.value.openDialog(row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** 导入按钮操作 */
|
/** 导入按钮操作 */
|
||||||
const openDialog = (row: ProgressCategoryVO, status: string, title: string) => {
|
const openDialog = (row: ProgressCategoryVO, status: string, title: string) => {
|
||||||
reset();
|
reset();
|
||||||
|
Reference in New Issue
Block a user