|
|
|
|
<template>
|
|
|
|
|
<div class="p-4">
|
|
|
|
|
<!-- 标题 -->
|
|
|
|
|
<div class="mb-8 flex justify-between items-center">
|
|
|
|
|
<div class="text-2xl font-semibold">流水账</div>
|
|
|
|
|
<div class="flex items-center">
|
|
|
|
|
<a-button type="primary" :disabled="morningStatus">{{ morningStatus ? '已打卡' : '早打卡' }}</a-button>
|
|
|
|
|
<a-button class="mx-5" type="primary" :disabled="nightStatus">{{ nightStatus ? '已打卡' : '晚打卡' }}</a-button>
|
|
|
|
|
<FullscreenExitOutlined v-if="isFullScreen" class="text-lg" style="color: #777" @click="changeIsFullScreen(false)" />
|
|
|
|
|
<FullscreenOutlined v-else class="text-lg" style="color: #777" @click="changeIsFullScreen(true)" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 筛选 -->
|
|
|
|
|
<a-form class="flex flex-wrap" :model="formState">
|
|
|
|
|
<a-form-item name="timeRange" label="时间" style="width: 280px; margin-right: 20px; margin-bottom: 12px">
|
|
|
|
|
<a-range-picker v-model:value="formState.timeRange" />
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item name="staffRange" label="员工" style="width: 280px; margin-right: 20px; margin-bottom: 12px">
|
|
|
|
|
<a-select
|
|
|
|
|
v-model:value="formState.staffRange"
|
|
|
|
|
:options="memberList"
|
|
|
|
|
:field-names="{ label: 'empName', value: 'empName' }"
|
|
|
|
|
mode="multiple"
|
|
|
|
|
placeholder="请选择员工"
|
|
|
|
|
></a-select>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item name="programName" label="项目" style="width: 280px; margin-right: 20px; margin-bottom: 12px">
|
|
|
|
|
<a-select
|
|
|
|
|
v-model:value="formState.programName"
|
|
|
|
|
:options="proList"
|
|
|
|
|
:field-names="{ label: 'projectName', value: 'projectName' }"
|
|
|
|
|
mode="multiple"
|
|
|
|
|
placeholder="请输入项目名称"
|
|
|
|
|
></a-select>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<div class="block w-full">
|
|
|
|
|
<a-button type="primary" html-type="submit" @click="handleSubmit">筛选</a-button>
|
|
|
|
|
<a-button class="mx-3" type="primary">导出</a-button>
|
|
|
|
|
<a-button @click="resetData">重置</a-button>
|
|
|
|
|
</div>
|
|
|
|
|
</a-form>
|
|
|
|
|
|
|
|
|
|
<!-- 表格 -->
|
|
|
|
|
<a-table class="mt-6" :columns="columns" :data-source="columnDatas" bordered :pagination="false" :scroll="{ x: 1400 }">
|
|
|
|
|
<template #bodyCell="{ column, text, record }">
|
|
|
|
|
<div
|
|
|
|
|
style="height: 100px"
|
|
|
|
|
:class="{ 'text-left': column.dataIndex === 'program' }"
|
|
|
|
|
class="overflow-y-auto task-today"
|
|
|
|
|
@dblclick="showModal(record, column.proId)"
|
|
|
|
|
>
|
|
|
|
|
<template v-if="column.dataIndex === 'program'">
|
|
|
|
|
<template v-for="item in text">
|
|
|
|
|
<template v-if="column.proId === item.proId">
|
|
|
|
|
<div class="mb-3" v-for="(task, key) in item.tasks" :key="key">
|
|
|
|
|
<PushpinOutlined class="mr-2" v-if="task.cooperation === 1" title="协作任务" />
|
|
|
|
|
<span>
|
|
|
|
|
我今日计划结果{{ key + 1 }}是:{{ task.taskName }},交付物是:{{ task.deliverName }},截止时间:{{
|
|
|
|
|
dayjs(+task.deadline).format('MM-DD')
|
|
|
|
|
}},时长:{{ task.duration / 3600000 }},检查人:{{ task.checker }}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</template>
|
|
|
|
|
</template>
|
|
|
|
|
<template v-else>
|
|
|
|
|
{{ text }}
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</a-table>
|
|
|
|
|
|
|
|
|
|
<a-pagination
|
|
|
|
|
class="text-right"
|
|
|
|
|
v-model:current="current"
|
|
|
|
|
v-model:pageSize="pageSize"
|
|
|
|
|
:total="dataTotal"
|
|
|
|
|
@change="handlePage"
|
|
|
|
|
show-less-items
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<a-modal
|
|
|
|
|
v-model:visible="visible"
|
|
|
|
|
title="今日计划"
|
|
|
|
|
centered
|
|
|
|
|
:footer="null"
|
|
|
|
|
width="800px"
|
|
|
|
|
style="padding: 0; max-height: 800px; overflow-y: auto"
|
|
|
|
|
>
|
|
|
|
|
<div style="padding: 0 96px">
|
|
|
|
|
<div class="mb-4">当前操作项目:{{ currProName }},当前操作成员:{{ currEmpName }}</div>
|
|
|
|
|
|
|
|
|
|
<a-form :model="modalFormState">
|
|
|
|
|
<div v-for="(item, index) in modalFormState" :key="index">
|
|
|
|
|
<div class="flex justify-between items-center text-gray-400">
|
|
|
|
|
<div class="mb-5 text-right" style="width: 120px">计划结果{{ index + 1 }}:</div>
|
|
|
|
|
<DeleteOutlined v-if="modalFormState.length > 1" @click="delFormItem(index)" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<a-form-item name="taskName" style="margin-bottom: 20px">
|
|
|
|
|
<div class="flex">
|
|
|
|
|
<label class="flex-shrink-0 text-right" style="width: 120px; line-height: 32px">
|
|
|
|
|
<span style="color: #ff5353; margin-right: 5px">*</span>今日计划结果{{ index + 1 }}:
|
|
|
|
|
</label>
|
|
|
|
|
<a-textarea v-model:value="item.taskName" :disabled="isDisabled" placeholder="请输入今日计划" />
|
|
|
|
|
</div>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item name="deliverName" style="margin-bottom: 20px">
|
|
|
|
|
<div class="flex">
|
|
|
|
|
<label class="flex-shrink-0 text-right" style="width: 120px; line-height: 32px">
|
|
|
|
|
<span style="color: #ff5353; margin-right: 5px">*</span>交付物:
|
|
|
|
|
</label>
|
|
|
|
|
<a-input v-model:value="item.deliverName" :disabled="isDisabled" placeholder="请输入交付物" />
|
|
|
|
|
</div>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item name="showDeadLine" style="margin-bottom: 20px">
|
|
|
|
|
<div class="flex">
|
|
|
|
|
<label class="flex-shrink-0 text-right" style="width: 120px; line-height: 32px">
|
|
|
|
|
<span style="color: #ff5353; margin-right: 5px">*</span>截止时间:
|
|
|
|
|
</label>
|
|
|
|
|
<a-date-picker class="w-full" v-model:value="item.showDeadLine" :disabled="isDisabled" />
|
|
|
|
|
</div>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item name="showDuration" style="margin-bottom: 20px">
|
|
|
|
|
<div class="flex">
|
|
|
|
|
<label class="flex-shrink-0 text-right" style="width: 120px; line-height: 32px">
|
|
|
|
|
<span style="color: #ff5353; margin-right: 5px">*</span>时长:
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
<a-input-group compact class="items-center" style="width: 100%; display: flex">
|
|
|
|
|
<a-auto-complete
|
|
|
|
|
style="width: calc(100% - 35px)"
|
|
|
|
|
v-model:value="item.showDuration"
|
|
|
|
|
:options="workDurations"
|
|
|
|
|
placeholder="请输入工作时长"
|
|
|
|
|
:disabled="isDisabled"
|
|
|
|
|
@change="handleDuration($event, index)"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div style="width: 35px; border: none" class="text-right">小时</div>
|
|
|
|
|
</a-input-group>
|
|
|
|
|
</div>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item name="checker" style="margin-bottom: 20px">
|
|
|
|
|
<div class="flex">
|
|
|
|
|
<label class="flex-shrink-0 text-right" style="width: 120px; line-height: 32px">
|
|
|
|
|
<span style="color: #ff5353; margin-right: 5px">*</span>检查人:
|
|
|
|
|
</label>
|
|
|
|
|
<a-select
|
|
|
|
|
v-model:value="item.checker"
|
|
|
|
|
:options="memberList"
|
|
|
|
|
:field-names="{ label: 'empName', value: 'empName' }"
|
|
|
|
|
show-search
|
|
|
|
|
placeholder="请选择检查人"
|
|
|
|
|
:disabled="isDisabled"
|
|
|
|
|
:filter-option="filterOption"
|
|
|
|
|
@change="handleInspector($event, index)"
|
|
|
|
|
></a-select>
|
|
|
|
|
</div>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item name="cooperation" style="margin-bottom: 20px">
|
|
|
|
|
<div class="flex">
|
|
|
|
|
<label class="flex-shrink-0 text-right" style="width: 120px; line-height: 32px"> 是否协作: </label>
|
|
|
|
|
<a-radio-group v-model:value="item.cooperation" class="w-full items-center" style="display: flex">
|
|
|
|
|
<a-radio class="items-center" style="display: flex" :value="1" :disabled="isDisabled">是</a-radio>
|
|
|
|
|
<a-radio class="items-center" style="display: flex" :value="0" :disabled="isDisabled">否</a-radio>
|
|
|
|
|
</a-radio-group>
|
|
|
|
|
</div>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item name="deliverLink" style="margin-bottom: 20px">
|
|
|
|
|
<div class="flex">
|
|
|
|
|
<label class="flex-shrink-0 text-right" style="width: 120px; line-height: 32px"> 交付物链接: </label>
|
|
|
|
|
<a-textarea v-model:value="item.deliverLink" :disabled="isDisabled" placeholder="请输入交付物链接" />
|
|
|
|
|
</div>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<a-form-item v-if="!isDisabled">
|
|
|
|
|
<div class="flex">
|
|
|
|
|
<label class="flex-shrink-0 text-right" style="width: 120px"></label>
|
|
|
|
|
<a-button style="color: #1890ff; border-color: #1890ff" type="dashed" @click="addFormItem">+ 添加</a-button>
|
|
|
|
|
</div>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
|
|
|
|
|
<a-form-item v-if="!isDisabled">
|
|
|
|
|
<div class="flex items-center">
|
|
|
|
|
<label class="flex-shrink-0 text-right" style="width: 120px"></label>
|
|
|
|
|
<a-button class="mr-4" type="primary" @click="submitForm">提交</a-button>
|
|
|
|
|
<a-button @click="cancleModal">取消</a-button>
|
|
|
|
|
</div>
|
|
|
|
|
</a-form-item>
|
|
|
|
|
</a-form>
|
|
|
|
|
</div>
|
|
|
|
|
</a-modal>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { useStore } from 'vuex';
|
|
|
|
|
import { reactive, ref, onMounted, computed, watch } from 'vue';
|
|
|
|
|
import dayjs from 'dayjs';
|
|
|
|
|
import { FullscreenExitOutlined, FullscreenOutlined, DeleteOutlined, PushpinOutlined } from '@ant-design/icons-vue';
|
|
|
|
|
import { getBasicInfo, queryTasks, submitTask, clockQuery, clockPunch } from 'apis';
|
|
|
|
|
import { message } from 'ant-design-vue';
|
|
|
|
|
|
|
|
|
|
const store = useStore();
|
|
|
|
|
const projectId = computed(() => store.getters['project/projectId']);
|
|
|
|
|
const sessionProjectId = sessionStorage.getItem('projectId');
|
|
|
|
|
const roleId = computed(() => store.state.role.roleId);
|
|
|
|
|
const members = computed(() => store.state.role.members);
|
|
|
|
|
const userId = computed(() => store.getters['user/userId']); // 用户id
|
|
|
|
|
const isFullScreen = computed(() => store.state.layout.isFullScreen); // 是否全屏
|
|
|
|
|
const visible = ref(false); // 是否显示弹框表单
|
|
|
|
|
const isDisabled = ref(false); // 是否允许编辑
|
|
|
|
|
const morningStatus = ref(false); // 早打卡
|
|
|
|
|
const nightStatus = ref(false); // 晚打卡
|
|
|
|
|
const checkerId = ref(null); // 打卡审核人id
|
|
|
|
|
const recordId = ref(null); // 记录id
|
|
|
|
|
const memberId = ref(null); // 成员id
|
|
|
|
|
|
|
|
|
|
// 筛选表单
|
|
|
|
|
const formState = reactive({
|
|
|
|
|
timeRange: [dayjs(+new Date().getTime()), dayjs(+new Date().getTime()).add(1, 'day')], // 时间范围
|
|
|
|
|
staffRange: [], // 员工
|
|
|
|
|
programName: [], // 项目名称
|
|
|
|
|
});
|
|
|
|
|
const startTime = dayjs(+new Date().getTime());
|
|
|
|
|
const endTime = dayjs(+new Date().getTime()).add(1, 'day');
|
|
|
|
|
|
|
|
|
|
// 下拉选选项
|
|
|
|
|
const memberList = ref([]); // 成员列表
|
|
|
|
|
const proList = ref([]); // 项目列表
|
|
|
|
|
const emps = ref([]); // 选中的筛选成员
|
|
|
|
|
const proDatas = ref([]); // 选中的筛选项目
|
|
|
|
|
|
|
|
|
|
// 表格元素
|
|
|
|
|
const columns = ref();
|
|
|
|
|
const current = ref(1); // 当前页数
|
|
|
|
|
const pageSize = ref(10); // 每页条数
|
|
|
|
|
const dataTotal = ref(0); // 数据总量
|
|
|
|
|
|
|
|
|
|
// 表格数据
|
|
|
|
|
const columnDatas = ref([]);
|
|
|
|
|
|
|
|
|
|
// 今日计划表单
|
|
|
|
|
const modalFormState = ref([]);
|
|
|
|
|
// 工作时长
|
|
|
|
|
const workDurations = [...Array(8)].map((_, i) => ({ value: `${i + 1}` }));
|
|
|
|
|
const isSubmitDeliver = ref(false); // 是否提交交付物
|
|
|
|
|
const currEmpId = ref(null); // 当前点击的用户id
|
|
|
|
|
const currEmpName = ref(null); // 当前点击的用户名
|
|
|
|
|
const currProId = ref(null); // 当前点击的项目id
|
|
|
|
|
const currProName = ref(null); // 当前点击的项目名
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
getClockQuery();
|
|
|
|
|
await getInfo();
|
|
|
|
|
await getQueryTasks();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 改变全屏状态
|
|
|
|
|
function changeIsFullScreen(data) {
|
|
|
|
|
store.commit('layout/setIsFullScreen', data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取基本信息(成员列表、项目列表)
|
|
|
|
|
async function getInfo() {
|
|
|
|
|
try {
|
|
|
|
|
const { url } = store.state.projects.project;
|
|
|
|
|
const data = await getBasicInfo(url);
|
|
|
|
|
memberList.value = data.emps;
|
|
|
|
|
pageSize.value = data.emps.length;
|
|
|
|
|
proList.value = data.pros;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
message.info(error);
|
|
|
|
|
throw new Error(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取任务列表
|
|
|
|
|
async function getQueryTasks() {
|
|
|
|
|
try {
|
|
|
|
|
const { url } = store.state.projects.project;
|
|
|
|
|
const params = {
|
|
|
|
|
param: {
|
|
|
|
|
startTime: startTime.value || formState.timeRange[0].startOf('day').valueOf(),
|
|
|
|
|
endTime: endTime.value || formState.timeRange[1].startOf('day').valueOf(),
|
|
|
|
|
emps: emps.value || [],
|
|
|
|
|
pros: proDatas.value || [],
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 相差天数
|
|
|
|
|
const days = dayjs(+formState.timeRange[1].startOf('day')).diff(+formState.timeRange[0].startOf('day'), 'day');
|
|
|
|
|
dataTotal.value = pageSize.value * days; // 分页数据总量
|
|
|
|
|
|
|
|
|
|
const data = await queryTasks(params, url);
|
|
|
|
|
|
|
|
|
|
columns.value = [
|
|
|
|
|
{
|
|
|
|
|
title: '时间',
|
|
|
|
|
width: 100,
|
|
|
|
|
dataIndex: 'time',
|
|
|
|
|
key: 'time',
|
|
|
|
|
fixed: 'left',
|
|
|
|
|
align: 'center',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '员工',
|
|
|
|
|
width: 100,
|
|
|
|
|
dataIndex: 'staff',
|
|
|
|
|
key: 'staff',
|
|
|
|
|
fixed: 'left',
|
|
|
|
|
align: 'center',
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
columnDatas.value = [];
|
|
|
|
|
|
|
|
|
|
data.pros.forEach((proId, index) => {
|
|
|
|
|
const proInfo = proList.value.find(item => item.id === proId);
|
|
|
|
|
columns.value.push({
|
|
|
|
|
title: proInfo.projectName,
|
|
|
|
|
dataIndex: 'program',
|
|
|
|
|
key: `${index}`,
|
|
|
|
|
proId,
|
|
|
|
|
width: 300,
|
|
|
|
|
align: 'center',
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
memberList.value.forEach((member, key) => {
|
|
|
|
|
const obj = {
|
|
|
|
|
empId: member.id,
|
|
|
|
|
key,
|
|
|
|
|
time: dayjs(+params.param.startTime).format('MM-DD'),
|
|
|
|
|
staff: `${member.empName}`,
|
|
|
|
|
program: [],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const currMember = data.recs.filter(item => member.id === item.empId);
|
|
|
|
|
|
|
|
|
|
if (currMember.length > 0) {
|
|
|
|
|
const { pros } = currMember[0];
|
|
|
|
|
obj.program = pros;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
columnDatas.value.push(obj);
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
message.info(error);
|
|
|
|
|
throw new Error(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 筛选
|
|
|
|
|
function handleSubmit() {
|
|
|
|
|
emps.value = [];
|
|
|
|
|
proDatas.value = [];
|
|
|
|
|
memberList.value.forEach(item => {
|
|
|
|
|
const index = formState.staffRange.findIndex(emp => emp === item.empName);
|
|
|
|
|
if (index > -1) emps.value.push(item.id);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
proList.value.forEach(item => {
|
|
|
|
|
const index = formState.programName.findIndex(pro => pro === item.projectName);
|
|
|
|
|
if (index > -1) proDatas.value.push(item.id);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const end = dayjs(+formState.timeRange[0].startOf('day')).add(1, 'day');
|
|
|
|
|
endTime.value = dayjs(+end).valueOf();
|
|
|
|
|
getQueryTasks();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重置
|
|
|
|
|
function resetData() {
|
|
|
|
|
formState.timeRange = [dayjs(+new Date().getTime()), dayjs(+new Date().getTime()).add(1, 'day')];
|
|
|
|
|
formState.staffRange = [];
|
|
|
|
|
formState.programName = [];
|
|
|
|
|
emps.value = [];
|
|
|
|
|
proDatas.value = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 分页改变
|
|
|
|
|
function handlePage(e) {
|
|
|
|
|
const start = dayjs(+formState.timeRange[0].startOf('day')).add(e - 1, 'day');
|
|
|
|
|
const end = dayjs(+start).add(1, 'day');
|
|
|
|
|
startTime.value = dayjs(+start).valueOf();
|
|
|
|
|
endTime.value = dayjs(+end).valueOf();
|
|
|
|
|
getQueryTasks();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 打开今日计划编辑框
|
|
|
|
|
function showModal(data, proId) {
|
|
|
|
|
currEmpId.value = data.empId;
|
|
|
|
|
currProId.value = proId;
|
|
|
|
|
const currEmpInfo = memberList.value.find(item => item.id === data.empId);
|
|
|
|
|
currEmpName.value = currEmpInfo.empName;
|
|
|
|
|
const currProInfo = proList.value.find(item => item.id === proId);
|
|
|
|
|
currProName.value = currProInfo.projectName;
|
|
|
|
|
|
|
|
|
|
isDisabled.value = dayjs(+new Date().getTime()).format('MM-DD') !== data.time;
|
|
|
|
|
visible.value = true;
|
|
|
|
|
|
|
|
|
|
modalFormState.value = [
|
|
|
|
|
{
|
|
|
|
|
taskName: '',
|
|
|
|
|
deliverName: '',
|
|
|
|
|
showDeadLine: dayjs(+new Date().getTime()),
|
|
|
|
|
deadline: '',
|
|
|
|
|
showDuration: '2',
|
|
|
|
|
duration: '',
|
|
|
|
|
checker: '',
|
|
|
|
|
cooperation: 0,
|
|
|
|
|
deliverLink: '',
|
|
|
|
|
sequence: 0,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
data.program.forEach(item => {
|
|
|
|
|
if (proId === item.proId) {
|
|
|
|
|
modalFormState.value = [...item.tasks];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
modalFormState.value.forEach((item, index) => {
|
|
|
|
|
item.showDeadLine = item.deadline ? dayjs(+item.deadline) : dayjs(+new Date().getTime());
|
|
|
|
|
item.showDuration = item.duration ? `${item.duration / 3600000}` : '2';
|
|
|
|
|
item.sequence = index;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查人筛选
|
|
|
|
|
function filterOption(input, option) {
|
|
|
|
|
return option.empName.indexOf(input) >= 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 选择工作时长
|
|
|
|
|
function handleDuration(e, index) {
|
|
|
|
|
modalFormState.value[index].duration = e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 选择检查人
|
|
|
|
|
function handleInspector(e, index) {
|
|
|
|
|
modalFormState.value[index].checker = e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加计划
|
|
|
|
|
function addFormItem() {
|
|
|
|
|
const len = modalFormState.value.length;
|
|
|
|
|
modalFormState.value.push({
|
|
|
|
|
taskName: '',
|
|
|
|
|
deliverName: '',
|
|
|
|
|
showDeadLine: dayjs(+new Date().getTime()),
|
|
|
|
|
deadline: '',
|
|
|
|
|
showDuration: '2',
|
|
|
|
|
duration: '',
|
|
|
|
|
checker: '',
|
|
|
|
|
cooperation: 0,
|
|
|
|
|
deliverLink: '',
|
|
|
|
|
sequence: len,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 删除计划
|
|
|
|
|
const delFormItem = index => {
|
|
|
|
|
modalFormState.value.splice(index, 1);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 取消任务弹框
|
|
|
|
|
function cancleModal() {
|
|
|
|
|
visible.value = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 提交表单
|
|
|
|
|
async function submitForm() {
|
|
|
|
|
let flag = false;
|
|
|
|
|
for (let i = 0; i < modalFormState.value.length; i++) {
|
|
|
|
|
const data = modalFormState.value[i];
|
|
|
|
|
data.deadline = dayjs(+data.showDeadLine).valueOf();
|
|
|
|
|
data.duration = data.showDuration * 3600000;
|
|
|
|
|
|
|
|
|
|
if (!data.taskName) {
|
|
|
|
|
message.info(`请输入今日计划结果${i + 1}`);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!data.deliverName) {
|
|
|
|
|
message.info(`请输入交付物`);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!data.duration) {
|
|
|
|
|
message.info(`请输入时长`);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!data.checker) {
|
|
|
|
|
message.info(`请选择检查人`);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const reg = /[a-zA-z]+:\/\/[^\s]*/;
|
|
|
|
|
if (data.deliverLink && !reg.test(data.deliverLink)) {
|
|
|
|
|
message.info(`请输入正确的链接`);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
flag = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flag) {
|
|
|
|
|
isSubmitDeliver.value = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const params = {
|
|
|
|
|
param: {
|
|
|
|
|
time: new Date().getTime(),
|
|
|
|
|
empId: currEmpId.value,
|
|
|
|
|
proId: currProId.value,
|
|
|
|
|
tasks: modalFormState.value,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const { url } = store.state.projects.project;
|
|
|
|
|
const data = await submitTask(params, url);
|
|
|
|
|
visible.value = false;
|
|
|
|
|
punch();
|
|
|
|
|
getQueryTasks();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
message.info(error);
|
|
|
|
|
throw new Error(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取当前打卡信息
|
|
|
|
|
async function getClockQuery() {
|
|
|
|
|
const start = dayjs(+new Date().getTime()).valueOf();
|
|
|
|
|
const end = dayjs(+new Date().getTime())
|
|
|
|
|
.add(1, 'day')
|
|
|
|
|
.valueOf();
|
|
|
|
|
|
|
|
|
|
const params = {
|
|
|
|
|
param: {
|
|
|
|
|
projectId: projectId.value || sessionProjectId,
|
|
|
|
|
roleId: roleId.value,
|
|
|
|
|
memberIdList: [],
|
|
|
|
|
startTime: start,
|
|
|
|
|
endTime: end,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const { url } = store.state.projects.project;
|
|
|
|
|
const data = await clockQuery(params, url);
|
|
|
|
|
|
|
|
|
|
// 审核人
|
|
|
|
|
if (data[0].recordList[0].lastCheckerId) {
|
|
|
|
|
checkerId.value = data[0].recordList[0].lastCheckerId;
|
|
|
|
|
} else if (data[0].recordList[0].checkerId) {
|
|
|
|
|
checkerId.value = data[0].recordList[0].checkerId;
|
|
|
|
|
} else {
|
|
|
|
|
checkerId.value = members.value[0].memberId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 成员id
|
|
|
|
|
if (data[0].recordList[0].isMine === 1) {
|
|
|
|
|
memberId.value = data[0].recordList[0].memberId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
recordId.value = data[0].recordList[0].id;
|
|
|
|
|
|
|
|
|
|
morningStatus.value = data[0].recordList[0].morningStatus > 0; // 早打卡状态
|
|
|
|
|
nightStatus.value = data[0].recordList[0].nightStatus > 0; // 晚打卡状态
|
|
|
|
|
} catch (error) {
|
|
|
|
|
message.info(error);
|
|
|
|
|
throw new Error(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function punch() {
|
|
|
|
|
const clockType = isSubmitDeliver.value ? 1 : 0; // 打卡类型:1 晚打卡 0 早打卡
|
|
|
|
|
const dateTime = dayjs(+new Date().getTime()).valueOf(); // 打卡时间
|
|
|
|
|
|
|
|
|
|
const params = { param: { checkerId: checkerId.value, memberId: memberId.value, id: recordId.value, clockType, dateTime } };
|
|
|
|
|
try {
|
|
|
|
|
const { url } = store.state.projects.project;
|
|
|
|
|
const data = await clockPunch(params, url);
|
|
|
|
|
|
|
|
|
|
morningStatus.value = data[0].recordList[0].morningStatus > 0; // 早打卡状态
|
|
|
|
|
nightStatus.value = data[0].recordList[0].nightStatus > 0; // 晚打卡状态
|
|
|
|
|
} catch (error) {
|
|
|
|
|
message.info(`打卡失败,${error}`);
|
|
|
|
|
throw new Error(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
.task-today::-webkit-scrollbar {
|
|
|
|
|
width: 0 !important;
|
|
|
|
|
}
|
|
|
|
|
</style>
|