You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
317 lines
8.2 KiB
317 lines
8.2 KiB
<template>
|
|
<view class="u-font-14">
|
|
<view
|
|
class="flex items-center justify-center rounded-full icon-column"
|
|
:style="{ color: orderStyle.color }"
|
|
@click="changeStatus(task.process, $event)"
|
|
>
|
|
<!-- 1进行中 2暂停中 3已完成 -->
|
|
<u-circle-progress
|
|
:percent="orderStyle.persent - 0"
|
|
:active-color="orderStyle.color"
|
|
bg-color="rgba(255,255,255,0)"
|
|
border-width="4"
|
|
:width="task.process !== 4 ? 66 : 50"
|
|
v-if="task.process === 1 || task.process === 2 || task.process === 3"
|
|
>
|
|
<view class="u-progress-content">
|
|
<view class="u-progress-dot"></view>
|
|
<view class="u-progress-info">
|
|
<u-icon :name="orderStyle.icon" v-if="orderStyle.icon" size="15px"></u-icon>
|
|
<template v-else>{{ data.durationText }}</template>
|
|
</view>
|
|
</view>
|
|
</u-circle-progress>
|
|
<!-- 0未开始 4添加任务 -->
|
|
<view class="flex items-center justify-center rounded-full progress-box" v-else :class="task.process === 4 ? 'progress-box-4' : ''">
|
|
<view class="u-progress-content">
|
|
<view class="u-progress-dot"></view>
|
|
<view class="u-progress-info">
|
|
<span v-if="orderStyle.icon">
|
|
<u-icon :name="orderStyle.icon" v-if="task.process !== 4" size="15px"></u-icon>
|
|
<u-icon :name="orderStyle.icon" v-else size="15px"></u-icon>
|
|
</span>
|
|
<template v-else>{{ data.durationText }}</template>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 遮罩 -->
|
|
<view class="mask" v-if="data.maskShow" @click="closeMask"></view>
|
|
<!-- 新建任务弹窗 -->
|
|
<CreateTask
|
|
:startTime="data.startTime"
|
|
:endTime="data.endTime"
|
|
:task="task"
|
|
:source="'regular'"
|
|
@showTime="showTime"
|
|
@closeMask="closeMask"
|
|
class="thirdPopup flex transition-transform"
|
|
v-if="data.createTaskShow"
|
|
/>
|
|
|
|
<u-picker title="开始时间" mode="time" v-model="data.showStart" :params="data.params" @confirm="confirmStartTime"></u-picker>
|
|
<u-picker title="结束时间" mode="time" v-model="data.showEnd" :params="data.params" @confirm="confirmEndTime"></u-picker>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { reactive, onMounted, computed } from 'vue';
|
|
import { useStore } from 'vuex';
|
|
import dayjs from 'dayjs';
|
|
import CreateTask from '../../Title/components/CreateTask.vue';
|
|
|
|
const props = defineProps({ task: { type: Object, default: () => {} } });
|
|
|
|
const data = reactive({
|
|
time: '',
|
|
start: [{ text: '确认开始任务', color: 'blue' }],
|
|
pause: [{ text: '继续' }, { text: '重新开始任务', color: 'blue' }, { text: '结束' }],
|
|
proceed: [{ text: '暂停' }, { text: '重新开始任务', color: 'blue' }, { text: '结束' }],
|
|
again: [{ text: '重新开始任务', color: 'blue' }],
|
|
timer: null,
|
|
durationText: 0,
|
|
maskShow: false, // 遮罩显示
|
|
createTaskShow: false, // 新建项目显示
|
|
startTime: '', // 新建任务的开始时间
|
|
endTime: '', // 新建任务的截止时间
|
|
showStart: false,
|
|
showEnd: false,
|
|
params: {
|
|
year: true,
|
|
month: true,
|
|
day: true,
|
|
hour: true,
|
|
minute: true,
|
|
second: true,
|
|
},
|
|
});
|
|
|
|
const store = useStore();
|
|
const tip = computed(() => store.state.task.tip);
|
|
const status = computed(() => props.task ? props.task.process : 0);
|
|
const taskName = computed(() => props.task ? props.task.name : '');
|
|
const taskId = computed(() => props.task ? props.task.id : '');
|
|
|
|
// 计算圆环的弧度百分比
|
|
function computeCyclePersent() {
|
|
if (!props.task || !props.task.realStart || !props.task.planDuration) return 100;
|
|
const { realStart, planDuration } = props.task;
|
|
return (((Date.now() - +realStart) * 100) / +planDuration).toFixed(2);
|
|
}
|
|
|
|
const orderStyle = computed(() => {
|
|
// 图标文本颜色
|
|
// 任务状态 0未开始 1进行中 2暂停中 3已完成
|
|
let color = '#9CA3AF';
|
|
let icon = 'play-right-fill';
|
|
let persent = 100;
|
|
switch (status.value) {
|
|
case 1: // 进行中
|
|
color = '#60A5FA';
|
|
icon = '';
|
|
if (+computeCyclePersent() > 100) {
|
|
persent = 96;
|
|
} else {
|
|
persent = computeCyclePersent();
|
|
}
|
|
break;
|
|
case 2: // 暂停中
|
|
color = '#F87171';
|
|
icon = 'pause';
|
|
persent = 50; // TODO: 暂时这样 暂停状态没有计算剩余多少时间
|
|
break;
|
|
case 3: // 已结束
|
|
color = '#34D399';
|
|
icon = 'checkmark';
|
|
persent = 100;
|
|
break;
|
|
case 4: // 添加任务
|
|
color = '#60A5FA';
|
|
icon = 'plus';
|
|
persent = 100;
|
|
break;
|
|
default:
|
|
// 未开始
|
|
color = '#9CA3AF';
|
|
icon = 'play-right';
|
|
persent = 100;
|
|
break;
|
|
}
|
|
return { color, icon, persent };
|
|
});
|
|
|
|
// unMounted(() => {
|
|
// if (data.timer) {
|
|
// clearInterval(data.timer);
|
|
// data.timer = null;
|
|
// }
|
|
// });
|
|
|
|
/**
|
|
* 计算tip的标题内容
|
|
*/
|
|
function genetateTips(type, content) {
|
|
if (type === 0) {
|
|
return `确认开始任务"${content}"吗?`;
|
|
}
|
|
if (type === 3) {
|
|
return '是否要重新开始此任务';
|
|
}
|
|
return '请选择要执行的操作';
|
|
}
|
|
|
|
// 新建任务
|
|
function addTask() {
|
|
// uni.$ui.showToast('新建任务');
|
|
// 打开遮罩
|
|
data.maskShow = true;
|
|
// 打开新建项目弹窗
|
|
data.createTaskShow = true;
|
|
}
|
|
|
|
/**
|
|
* 点击了图标 修改任务状态
|
|
* @param {object} event
|
|
*/
|
|
function changeStatus(process, event) {
|
|
if (process === 4) {
|
|
addTask();
|
|
return;
|
|
}
|
|
// return false;
|
|
tip.status = status;
|
|
tip.taskId = taskId;
|
|
tip.left = event.target.x;
|
|
tip.top = event.target.y;
|
|
tip.show = true;
|
|
tip.text = genetateTips(status, taskName);
|
|
store.commit('task/setTip', tip);
|
|
}
|
|
|
|
// 点击遮罩,关闭弹窗
|
|
function closeMask() {
|
|
// 关闭遮罩
|
|
data.maskShow = false;
|
|
// 关闭新建项目弹窗
|
|
data.createTaskShow = false;
|
|
}
|
|
|
|
function showTime(type) {
|
|
if (type === 1) {
|
|
data.showStart = !data.showStart;
|
|
} else {
|
|
data.showEnd = !data.showEnd;
|
|
}
|
|
}
|
|
|
|
// 选择开始时间
|
|
function confirmStartTime(e) {
|
|
data.startTime = `${e.year}-${e.month}-${e.day} ${e.hour}:${e.minute}:${e.second}`;
|
|
data.showEnd = true;
|
|
}
|
|
|
|
// 选择结束时间
|
|
function confirmEndTime(e) {
|
|
data.endTime = `${e.year}-${e.month}-${e.day} ${e.hour}:${e.minute}:${e.second}`;
|
|
}
|
|
|
|
// 计算进行中状态剩余时间
|
|
// 预计结束时间 = realStart(实际开始) + planDuration(计划时长)
|
|
// 剩余时间 = 预计结束时间 - 当前时间
|
|
// 剩余时间 = realStart + planDuration - Date.now()
|
|
function computeDurationText() {
|
|
const { realStart, planDuration } = props.task;
|
|
const leftTime = (realStart-0 || 0) + (planDuration-0 || 0) - Date.now(); // 剩余时间
|
|
const { num, time } = uni.$time.computeDurationText(leftTime);
|
|
if (num <= 0) {
|
|
clearInterval(data.timer);
|
|
data.timer = null;
|
|
}
|
|
data.durationText = num;
|
|
return time;
|
|
}
|
|
|
|
function updateDurationText(time) {
|
|
if (data.timer) {
|
|
clearInterval(data.timer);
|
|
data.timer = null;
|
|
}
|
|
if (!time) return;
|
|
setInterval(() => {
|
|
computeDurationText();
|
|
}, time);
|
|
}
|
|
|
|
onMounted(() => {
|
|
// TODO: 计算在不在窗口内显示
|
|
const time = computeDurationText();
|
|
updateDurationText(time);
|
|
});
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.icon-column {
|
|
height: 33px;
|
|
width: 33px;
|
|
}
|
|
.one {
|
|
height: 33px;
|
|
width: 33px;
|
|
}
|
|
|
|
.progress-box {
|
|
background: rgba(255, 255, 255, 0);
|
|
width: 33px;
|
|
height: 33px;
|
|
border: 2px solid #9ca3af;
|
|
}
|
|
|
|
.progress-box-4 {
|
|
width: 25px;
|
|
height: 25px;
|
|
border: 2px solid #60a5fa;
|
|
}
|
|
|
|
.mask {
|
|
width: 100%;
|
|
height: 100vh;
|
|
z-index: 21;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
background: rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.thirdPopup {
|
|
background: #ffffff;
|
|
position: fixed;
|
|
left: 50%;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%);
|
|
z-index: 33;
|
|
border-radius: 5px;
|
|
width: 90%;
|
|
}
|
|
|
|
::v-deep .u-dropdown__content {
|
|
min-height: 120px !important;
|
|
height: auto !important;
|
|
overflow-y: auto;
|
|
background: #fff !important;
|
|
transition: none !important;
|
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
|
}
|
|
::v-deep .u-dropdown__menu__item .u-flex {
|
|
justify-content: space-between;
|
|
width: 100%;
|
|
height: 100%;
|
|
flex-wrap: nowrap;
|
|
border: 1px solid #afbed1;
|
|
padding: 0 8px;
|
|
}
|
|
::v-deep .u-dropdown__content__mask {
|
|
display: none;
|
|
}
|
|
</style>
|
|
|