CheckInDialog.vue
3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<template>
<van-popup
:show="show"
@update:show="$emit('update:show', $event)"
round
position="bottom"
:style="{ minHeight: '30%', maxHeight: '80%', width: '100%' }"
>
<div class="p-4">
<div class="flex justify-between items-center mb-3">
<h3 class="font-medium">
<span :class="{ 'text-green-500' : active_tab === 'today' }" @click="active_tab = 'today'">今日打卡</span>
<span v-if="has_history" :class="{ 'text-green-500' : active_tab === 'history' }" @click="active_tab = 'history'">历史打卡</span>
</h3>
<van-icon name="cross" @click="handleClose" />
</div>
<CheckInList :items="active_list" @submit-success="handleListSuccess" />
</div>
</van-popup>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import CheckInList from '@/components/ui/CheckInList.vue'
import { getTaskListAPI } from "@/api/checkin";
// 签到列表
const checkInTypes = ref([]);
const route = useRoute()
const router = useRouter()
const props = defineProps({
/** 弹窗显隐 */
show: { type: Boolean, required: true, default: false },
/** 今日打卡任务(外部传入,可选) */
items_today: { type: Array, default: () => [] },
/** 历史打卡任务(外部传入,可选) */
items_history: { type: Array, default: () => [] }
})
const emit = defineEmits(['update:show', 'check-in-success', 'check-in-data'])
/**
* @var {import('vue').Ref<'today'|'history'>} active_tab
* @description 当前选中的任务标签页:今日或历史。
*/
const active_tab = ref('today')
/**
* @function has_history
* @description 是否存在历史任务(用于显示“历史打卡”标签)。
* @returns {boolean}
*/
const has_history = computed(() => {
const list = Array.isArray(props.items_history) ? props.items_history : []
return list.length > 0
})
/**
* @function active_list
* @description 当前展示的任务列表:优先使用外部传入,未传时回退为组件内部获取的列表。
* @returns {Array}
*/
const active_list = computed(() => {
const today = Array.isArray(props.items_today) ? props.items_today : []
const history = Array.isArray(props.items_history) ? props.items_history : []
if (active_tab.value === 'today') {
return today.length ? today : checkInTypes.value
}
return history
})
/**
* @function refresh_checkin_list
* @description 重新获取打卡任务列表,用于提交成功后更新置灰状态;同时向父组件透出最新数据。
* @returns {Promise<void>}
*/
const refresh_checkin_list = async () => {
const task = await getTaskListAPI()
if (task?.code) {
// 重建本地签到任务列表(当未传入 props.items_today 时用于展示)
checkInTypes.value = (task.data || []).map(item => ({
id: item.id,
name: item.title,
task_type: item.task_type,
is_gray: item.is_gray
}))
// 向父组件透出最新数据,便于父组件自行刷新其持有的数据源
emit('check-in-data', task.data)
}
}
/**
* @function handleListSuccess
* @description 子组件提交成功后,刷新任务列表并通知外部,然后关闭弹窗。
* @returns {Promise<void>}
*/
const handleListSuccess = async () => {
await refresh_checkin_list()
emit('check-in-success')
setTimeout(() => emit('update:show', false), 1500)
}
const handleClose = () => {
emit('update:show', false)
}
onMounted(async () => {
// 当未从外部传入“今日任务”时,回退为组件内部获取的通用任务列表
if (!Array.isArray(props.items_today) || props.items_today.length === 0) {
await refresh_checkin_list()
}
})
</script>