|
|
@ -4,115 +4,182 @@ |
|
|
|
<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">早打卡</a-button> |
|
|
|
<a-button class="mx-5" type="primary">晚打卡</a-button> |
|
|
|
<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="isFullScreen = !isFullScreen" /> |
|
|
|
<FullscreenOutlined v-else class="text-lg" style="color: #777" @click="isFullScreen = !isFullScreen" /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 筛选 --> |
|
|
|
<a-form class="flex flex-wrap" :model="formState" name="basic" autocomplete="off"> |
|
|
|
<a-form-item name="timeRange" label="时间" style="width: 250px; margin-right: 20px; margin-bottom: 12px"> |
|
|
|
<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: 250px; margin-right: 20px; margin-bottom: 12px"> |
|
|
|
<a-select v-model:value="formState.staffRange" :options="options" mode="multiple" placeholder="请选择员工"></a-select> |
|
|
|
<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: 250px; margin-right: 20px; margin-bottom: 12px"> |
|
|
|
<a-select v-model:value="formState.programName" :options="options" mode="multiple" placeholder="请输入项目名称"></a-select> |
|
|
|
<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">筛选</a-button> |
|
|
|
<a-button type="primary" html-type="submit" @click="handleSubmit">筛选</a-button> |
|
|
|
<a-button class="mx-3" type="primary">导出</a-button> |
|
|
|
<a-button>重置</a-button> |
|
|
|
<a-button @click="resetData">重置</a-button> |
|
|
|
</div> |
|
|
|
</a-form> |
|
|
|
|
|
|
|
<!-- 表格 --> |
|
|
|
<a-table class="mt-6" :columns="columns" :data-source="data" bordered :scroll="{ x: 1400 }"> |
|
|
|
<template #bodyCell="{ column, text }"> |
|
|
|
<div style="height: 100px" :class="{ 'text-left': column.dataIndex === 'program' }" @dblclick="showModal">{{ text }}</div> |
|
|
|
<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 v-if="task.cooperation === 1" title="协作任务" /> |
|
|
|
<span class="ml-2"> |
|
|
|
我今日计划结果{{ 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"> |
|
|
|
<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"> |
|
|
|
<a-form :model="modalFormState" name="basic" autocomplete="off"> |
|
|
|
<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="planValue" style="margin-bottom: 20px"> |
|
|
|
<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>今日计划结果1: |
|
|
|
<span style="color: #ff5353; margin-right: 5px">*</span>今日计划结果{{ index + 1 }}: |
|
|
|
</label> |
|
|
|
<a-textarea v-model:value="item.planValue" placeholder="请输入今日计划" /> |
|
|
|
<a-textarea v-model:value="item.taskName" :disabled="isDisabled" placeholder="请输入今日计划" /> |
|
|
|
</div> |
|
|
|
</a-form-item> |
|
|
|
|
|
|
|
<a-form-item name="deliverable" style="margin-bottom: 20px"> |
|
|
|
<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.deliverable" placeholder="请输入交付物" /> |
|
|
|
<a-input v-model:value="item.deliverName" :disabled="isDisabled" placeholder="请输入交付物" /> |
|
|
|
</div> |
|
|
|
</a-form-item> |
|
|
|
|
|
|
|
<a-form-item name="deadline" style="margin-bottom: 20px"> |
|
|
|
<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.deadline" /> |
|
|
|
<a-date-picker class="w-full" v-model:value="item.showDeadLine" /> |
|
|
|
</div> |
|
|
|
</a-form-item> |
|
|
|
|
|
|
|
<a-form-item name="duration" style="margin-bottom: 20px"> |
|
|
|
<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-select |
|
|
|
v-model:value="item.duration" |
|
|
|
:options="workDurations" |
|
|
|
placeholder="请输入工作时长" |
|
|
|
@change="handleDuration($event, index)" |
|
|
|
></a-select> |
|
|
|
|
|
|
|
<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="inspector" style="margin-bottom: 20px"> |
|
|
|
<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.inspector" |
|
|
|
:options="members" |
|
|
|
v-model:value="item.checker" |
|
|
|
:options="memberList" |
|
|
|
:field-names="{ label: 'empName', value: 'empName' }" |
|
|
|
show-search |
|
|
|
placeholder="请选择检查人" |
|
|
|
:field-names="{ label: 'name', value: 'memberId' }" |
|
|
|
:disabled="isDisabled" |
|
|
|
:filter-option="filterOption" |
|
|
|
@change="handleInspector($event, index)" |
|
|
|
></a-select> |
|
|
|
</div> |
|
|
|
</a-form-item> |
|
|
|
|
|
|
|
<a-form-item name="address" style="margin-bottom: 20px"> |
|
|
|
<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"> |
|
|
|
<span style="color: #ff5353; margin-right: 5px">*</span>交付物地址: |
|
|
|
</label> |
|
|
|
<a-textarea v-model:value="item.address" placeholder="请输入交付物地址" /> |
|
|
|
<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">是</a-radio> |
|
|
|
<a-radio class="items-center" style="display: flex" :value="0">否</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> |
|
|
@ -138,105 +205,215 @@ |
|
|
|
|
|
|
|
<script setup> |
|
|
|
import { useStore } from 'vuex'; |
|
|
|
import { reactive, ref, computed } from 'vue'; |
|
|
|
import { reactive, ref, onMounted, computed, watch } from 'vue'; |
|
|
|
import dayjs from 'dayjs'; |
|
|
|
import { FullscreenExitOutlined, FullscreenOutlined, DeleteOutlined } from '@ant-design/icons-vue'; |
|
|
|
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 isFullScreen = ref(false); |
|
|
|
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 isFullScreen = ref(false); // 是否全屏 |
|
|
|
const visible = ref(false); // 是否显示弹框表单 |
|
|
|
const members = computed(() => store.state.role.members); // 项目成员 |
|
|
|
const isDisabled = ref(false); // 是否允许编辑 |
|
|
|
const morningStatus = ref(false); // 早打卡 |
|
|
|
const nightStatus = ref(false); // 晚打卡 |
|
|
|
const checkerId = ref(null); // 打卡审核人id |
|
|
|
|
|
|
|
// 筛选表单 |
|
|
|
const formState = reactive({ |
|
|
|
timeRange: [], // 时间范围 |
|
|
|
staffRange: ['a1', 'b2'], // 员工 |
|
|
|
programName: ['a1', 'b2'], // 项目名称 |
|
|
|
timeRange: [dayjs(+new Date().getTime()), dayjs(+new Date().getTime()).add(1, 'day')], // 时间范围 |
|
|
|
staffRange: [], // 员工 |
|
|
|
programName: [], // 项目名称 |
|
|
|
}); |
|
|
|
|
|
|
|
// 下拉选选项 |
|
|
|
const options = [...Array(25)].map((_, i) => ({ value: (i + 10).toString(36) + (i + 1) })); |
|
|
|
const memberList = ref([]); // 成员列表 |
|
|
|
const proList = ref([]); // 项目列表 |
|
|
|
const emps = ref([]); // 选中的筛选成员 |
|
|
|
const proDatas = ref([]); // 选中的筛选项目 |
|
|
|
|
|
|
|
// 表格元素 |
|
|
|
const columns = [ |
|
|
|
{ |
|
|
|
title: '时间', |
|
|
|
width: 100, |
|
|
|
dataIndex: 'time', |
|
|
|
key: 'time', |
|
|
|
fixed: 'left', |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '员工', |
|
|
|
width: 100, |
|
|
|
dataIndex: 'staff', |
|
|
|
key: 'staff', |
|
|
|
fixed: 'left', |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '项目1', |
|
|
|
dataIndex: 'program', |
|
|
|
key: '1', |
|
|
|
width: 300, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '项目2', |
|
|
|
dataIndex: 'program', |
|
|
|
key: '2', |
|
|
|
width: 300, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '项目3', |
|
|
|
dataIndex: 'program', |
|
|
|
key: '3', |
|
|
|
width: 300, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '项目4', |
|
|
|
dataIndex: 'program', |
|
|
|
key: '4', |
|
|
|
width: 300, |
|
|
|
align: 'center', |
|
|
|
}, |
|
|
|
]; |
|
|
|
const columns = ref(); |
|
|
|
const current = ref(1); // 当前页数 |
|
|
|
const pageSize = ref(10); // 每页条数 |
|
|
|
const dataTotal = ref(0); // 数据总量 |
|
|
|
|
|
|
|
// 表格数据 |
|
|
|
const data = []; |
|
|
|
for (let i = 0; i < 100; i++) { |
|
|
|
data.push({ |
|
|
|
key: i, |
|
|
|
time: dayjs(+new Date().getTime()).format('MM-DD'), |
|
|
|
staff: `成员 ${i}`, |
|
|
|
program: `我今日计划结果1是XXXXXX,交付物是XXXXXXX方法论,截止时间是:4/25,检查人是:卫老师`, |
|
|
|
}); |
|
|
|
} |
|
|
|
const columnDatas = ref([]); |
|
|
|
|
|
|
|
// 今日计划表单 |
|
|
|
const modalFormState = ref([ |
|
|
|
{ |
|
|
|
planValue: '', |
|
|
|
deliverable: '', |
|
|
|
deadline: dayjs(+new Date().getTime()), |
|
|
|
taskName: '', |
|
|
|
deliverName: '', |
|
|
|
showDeadLine: dayjs(+new Date().getTime()), |
|
|
|
deadline: '', |
|
|
|
showDuration: '2', |
|
|
|
duration: '', |
|
|
|
inspector: '', |
|
|
|
address: '', |
|
|
|
checker: '', |
|
|
|
cooperation: 0, |
|
|
|
deliverLink: '', |
|
|
|
sequence: 0, |
|
|
|
}, |
|
|
|
]); |
|
|
|
// 工作时长 |
|
|
|
const workDurations = [...Array(8)].map((_, i) => ({ value: `${i + 1}小时` })); |
|
|
|
const workDurations = [...Array(8)].map((_, i) => ({ value: `${i + 1}` })); |
|
|
|
const isSubmitDeliver = ref(false); // 是否提交交付物 |
|
|
|
|
|
|
|
onMounted(async () => { |
|
|
|
getClockQuery(); |
|
|
|
await getInfo(); |
|
|
|
await getQueryTasks({}); |
|
|
|
}); |
|
|
|
|
|
|
|
// 获取基本信息(成员列表、项目列表) |
|
|
|
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) { |
|
|
|
throw new Error(error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 获取任务列表 |
|
|
|
async function getQueryTasks(query) { |
|
|
|
try { |
|
|
|
const { url } = store.state.projects.project; |
|
|
|
const params = { |
|
|
|
param: { |
|
|
|
startTime: query.startTime || formState.timeRange[0].startOf('day').valueOf(), |
|
|
|
endTime: query.endTime || 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(+new Date().getTime()).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) { |
|
|
|
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 endTime = dayjs(+formState.timeRange[0].startOf('day')).add(1, 'day'); |
|
|
|
getQueryTasks({ endTime: dayjs(+endTime).valueOf() }); |
|
|
|
} |
|
|
|
|
|
|
|
// 重置 |
|
|
|
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 startTime = dayjs(+formState.timeRange[0].startOf('day')).add(e - 1, 'day'); |
|
|
|
const endTime = dayjs(+startTime).add(1, 'day'); |
|
|
|
getQueryTasks({ startTime: dayjs(+startTime).valueOf(), endTime: dayjs(+endTime).valueOf() }); |
|
|
|
} |
|
|
|
|
|
|
|
// 打开今日计划编辑框 |
|
|
|
function showModal() { |
|
|
|
function showModal(data, proId) { |
|
|
|
console.log('data', data, proId); |
|
|
|
isDisabled.value = dayjs(+new Date().getTime()).format('MM-DD') !== data.time; |
|
|
|
visible.value = true; |
|
|
|
|
|
|
|
data.program.forEach(item => { |
|
|
|
if (proId === item.proId) { |
|
|
|
modalFormState.value = [...item.tasks]; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
modalFormState.value.forEach((item, index) => { |
|
|
|
item.showDeadLine = dayjs(+item.deadline); |
|
|
|
item.showDuration = `${item.duration / 3600000}`; |
|
|
|
item.sequence = index; |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// 检查人筛选 |
|
|
|
function filterOption(input, option) { |
|
|
|
return option.name.indexOf(input) >= 0; |
|
|
|
return option.emp_name.indexOf(input) >= 0; |
|
|
|
} |
|
|
|
|
|
|
|
// 选择工作时长 |
|
|
@ -245,28 +422,145 @@ function handleDuration(e, index) { |
|
|
|
modalFormState.value[index].duration = e; |
|
|
|
} |
|
|
|
|
|
|
|
// 选择检查人 |
|
|
|
function handleInspector(e, index) { |
|
|
|
modalFormState.value[index].inspector = e; |
|
|
|
} |
|
|
|
|
|
|
|
// 添加计划 |
|
|
|
function addFormItem() { |
|
|
|
const len = modalFormState.value.length; |
|
|
|
modalFormState.value.push({ |
|
|
|
planValue: '', |
|
|
|
deliverable: '', |
|
|
|
deadline: dayjs(+new Date().getTime()), |
|
|
|
taskName: '', |
|
|
|
deliverName: '', |
|
|
|
showDeadLine: dayjs(+new Date().getTime()), |
|
|
|
deadline: '', |
|
|
|
showDuration: '2', |
|
|
|
duration: '', |
|
|
|
inspector: '', |
|
|
|
address: '', |
|
|
|
checker: '', |
|
|
|
cooperation: 0, |
|
|
|
deliverLink: '', |
|
|
|
sequence: len, |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// 删除计划 |
|
|
|
const delFormItem = index => { |
|
|
|
modalFormState.value.splice(index, 1); |
|
|
|
}; |
|
|
|
|
|
|
|
// 取消任务弹框 |
|
|
|
function cancleModal() { |
|
|
|
visible.value = false; |
|
|
|
} |
|
|
|
|
|
|
|
function submitForm() {} |
|
|
|
// 提交表单 |
|
|
|
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: 1, |
|
|
|
proId: 1, |
|
|
|
tasks: modalFormState.value, |
|
|
|
}, |
|
|
|
}; |
|
|
|
|
|
|
|
try { |
|
|
|
const { url } = store.state.projects.project; |
|
|
|
const data = await submitTask(params, url); |
|
|
|
visible.value = false; |
|
|
|
punch(); |
|
|
|
getQueryTasks(); |
|
|
|
} catch (error) { |
|
|
|
throw new Error(error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 获取当前打卡信息 |
|
|
|
async function getClockQuery() { |
|
|
|
const startTime = dayjs(+new Date().getTime()).valueOf(); |
|
|
|
const endTime = dayjs(+new Date().getTime()) |
|
|
|
.add(1, 'day') |
|
|
|
.valueOf(); |
|
|
|
|
|
|
|
const params = { param: { projectId: projectId.value || sessionProjectId, roleId: roleId.value, memberIdList: [], startTime, endTime } }; |
|
|
|
|
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
morningStatus.value = data[0].recordList[0].morningStatus > 0; // 早打卡状态 |
|
|
|
nightStatus.value = data[0].recordList[0].nightStatus > 0; // 晚打卡状态 |
|
|
|
} catch (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: { 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) { |
|
|
|
throw new Error(error); |
|
|
|
} |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<style scoped> |
|
|
|
.task-today::-webkit-scrollbar { |
|
|
|
width: 0 !important; |
|
|
|
} |
|
|
|
</style> |
|
|
|