|
|
@@ -26,10 +26,16 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <view class="task-list-controls__date" @click="openDatePicker">
|
|
|
+ <view class="task-list-controls__date">
|
|
|
<view class="task-list-controls__divider" />
|
|
|
- <text class="task-list-controls__date-text">{{ selectedDateText }}</text>
|
|
|
- <wd-icon name="arrow-down" size="28rpx" />
|
|
|
+ <view v-if="!selectedDate" @click="openDatePicker">
|
|
|
+ <text class="task-list-controls__date-text">{{ selectedDateText }}</text>
|
|
|
+ <wd-icon name="caret-down" size="28rpx" />
|
|
|
+ </view>
|
|
|
+ <view v-else @click="clearDatePicker">
|
|
|
+ <text class="task-list-controls__date-text">{{ selectedDateText }}</text>
|
|
|
+ <wd-icon name="close-circle" size="28rpx" />
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -92,6 +98,17 @@
|
|
|
<text v-if="finished">没有更多了</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
+
|
|
|
+ <!-- 时间选择器 -->
|
|
|
+ <wd-datetime-picker
|
|
|
+ v-model:visible="datetimePickerShow"
|
|
|
+ v-model="datetimePickerValue"
|
|
|
+ type="year-month"
|
|
|
+ @confirm="datetimePickerHandleConfirm"
|
|
|
+ />
|
|
|
+ <!-- 领取积分包测试提示 -->
|
|
|
+ <wd-dialog />
|
|
|
+ <wd-toast />
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
@@ -99,13 +116,20 @@
|
|
|
import { computed, onBeforeMount, reactive, ref } from 'vue'
|
|
|
|
|
|
import { onReachBottom } from '@dcloudio/uni-app'
|
|
|
+import { useDialog, useToast } from '@wot-ui/ui'
|
|
|
+import dayjs from 'dayjs'
|
|
|
|
|
|
-import { getUserScorePackageListApi } from '@/services/modules/task/list'
|
|
|
+import { getDictTypeApi } from '@/services/modules/common'
|
|
|
+import type { DictItem } from '@/services/modules/common/type'
|
|
|
+import { getUserScorePackageListApi, pickupPackageApi } from '@/services/modules/task/list'
|
|
|
import type {
|
|
|
getUserScorePackageListRequest,
|
|
|
TaskPackageItem,
|
|
|
} from '@/services/modules/task/list/type'
|
|
|
|
|
|
+const dialog = useDialog()
|
|
|
+const toast = useToast()
|
|
|
+
|
|
|
enum TaskPackageTab {
|
|
|
Available = '1',
|
|
|
Received = '2',
|
|
|
@@ -158,6 +182,10 @@ const resetList = () => {
|
|
|
packageListArr.value = []
|
|
|
}
|
|
|
|
|
|
+const refreshTaskPackageList = () => {
|
|
|
+ resetList()
|
|
|
+ fetchTaskPackageList()
|
|
|
+}
|
|
|
const fetchTaskPackageList = async () => {
|
|
|
if (loading.value || finished.value) return
|
|
|
|
|
|
@@ -186,11 +214,6 @@ const fetchTaskPackageList = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const refreshTaskPackageList = () => {
|
|
|
- resetList()
|
|
|
- fetchTaskPackageList()
|
|
|
-}
|
|
|
-
|
|
|
const loadMoreTaskPackageList = () => {
|
|
|
if (loading.value || finished.value) return
|
|
|
params.current += 1
|
|
|
@@ -218,12 +241,123 @@ const handleTabChange = (value: TaskPackageTab) => {
|
|
|
refreshTaskPackageList()
|
|
|
}
|
|
|
|
|
|
+const datetimePickerValue = ref(dayjs().startOf('month').valueOf())
|
|
|
+const datetimePickerShow = ref(false)
|
|
|
+
|
|
|
const openDatePicker = () => {
|
|
|
- console.log('打开日期选择器')
|
|
|
+ datetimePickerShow.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const datetimePickerHandleConfirm = (e: { value: string }) => {
|
|
|
+ const d = dayjs(e.value)
|
|
|
+ params.selectedYear = d.format('YYYY')
|
|
|
+ params.selectedMonth = d.format('MM')
|
|
|
+ refreshTaskPackageList()
|
|
|
+}
|
|
|
+
|
|
|
+const clearDatePicker = () => {
|
|
|
+ datetimePickerValue.value = dayjs().startOf('month').valueOf()
|
|
|
+ params.selectedYear = ''
|
|
|
+ params.selectedMonth = ''
|
|
|
+ refreshTaskPackageList()
|
|
|
+}
|
|
|
+
|
|
|
+const GET_STATUS = {
|
|
|
+ UN_GET: {
|
|
|
+ value: '0',
|
|
|
+ desc: '未领取',
|
|
|
+ },
|
|
|
+ ING: {
|
|
|
+ value: '1',
|
|
|
+ desc: '审核中',
|
|
|
+ },
|
|
|
+ OK: {
|
|
|
+ value: '2',
|
|
|
+ desc: '审核通过',
|
|
|
+ },
|
|
|
+ NO: {
|
|
|
+ value: '3',
|
|
|
+ desc: '审核不通过',
|
|
|
+ },
|
|
|
+ OVER: {
|
|
|
+ value: '4',
|
|
|
+ desc: '已终止',
|
|
|
+ },
|
|
|
+} as const
|
|
|
+
|
|
|
+const currentPackage = ref<TaskPackageItem | null>(null)
|
|
|
+
|
|
|
+const hasRequiredQuiz = (item: TaskPackageItem) => {
|
|
|
+ return Array.isArray(item.quizRelations) && item.quizRelations.length > 0
|
|
|
+}
|
|
|
+
|
|
|
+const isUnreceived = (item: TaskPackageItem) => {
|
|
|
+ return item.status === GET_STATUS.UN_GET.value
|
|
|
}
|
|
|
|
|
|
-const handleReceive = (item: TaskPackageItem) => {
|
|
|
- console.log('立即领取:', item)
|
|
|
+const openTestValidationDialog = () => {
|
|
|
+ dialog
|
|
|
+ .confirm({
|
|
|
+ title: '提示',
|
|
|
+ msg: '该积分包需要通过测试才能领取,是否进行测试?',
|
|
|
+ confirmButtonText: '去测试',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ handleGoTest()
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ // 点击取消 / 关闭,不处理
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 点击立即领取
|
|
|
+ */
|
|
|
+const handleReceive = async (item: TaskPackageItem) => {
|
|
|
+ currentPackage.value = { ...item }
|
|
|
+
|
|
|
+ // 有测试要求,且当前状态不允许直接领取:弹出测试校验提示
|
|
|
+ if (hasRequiredQuiz(item) && !isUnreceived(item)) {
|
|
|
+ openTestValidationDialog()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ await submitReceiveAfterTestPassed(item)
|
|
|
+}
|
|
|
+const submitReceiveAfterTestPassed = async (item: TaskPackageItem) => {
|
|
|
+ const res = await pickupPackageApi({
|
|
|
+ pkgId: item.id,
|
|
|
+ })
|
|
|
+ if (res.code === 0) {
|
|
|
+ toast.success('领取成功')
|
|
|
+ removePackageFromList(item.id)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (res.code === 1) {
|
|
|
+ uni.showModal({
|
|
|
+ content: res.msg,
|
|
|
+ confirmText: '去认证',
|
|
|
+ success: (modalRes) => {
|
|
|
+ if (modalRes.confirm) {
|
|
|
+ console.log('认证页面')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+const removePackageFromList = (pkgId: string | number) => {
|
|
|
+ packageListArr.value = packageListArr.value.filter((item) => item.id !== pkgId)
|
|
|
+
|
|
|
+ if (params.activeTab === TaskPackageTab.Available && params.total > 0) {
|
|
|
+ params.total -= 1
|
|
|
+ }
|
|
|
+}
|
|
|
+const handleGoTest = () => {
|
|
|
+ if (!currentPackage.value) return
|
|
|
+ // uni.navigateTo({
|
|
|
+ // url: `/pages/xxx/test/index?id=${currentPackage.value.id}`,
|
|
|
+ // })
|
|
|
}
|
|
|
|
|
|
const getPackageTypeTag = (type: string | null) => {
|
|
|
@@ -238,12 +372,25 @@ const getPackageTypeTag = (type: string | null) => {
|
|
|
return type ? tagMap[type as keyof typeof tagMap] : undefined
|
|
|
}
|
|
|
|
|
|
-const getPackageStatusText = (status: string | null) => status || '-'
|
|
|
+const packageStatusMap = ref<DictItem[]>([])
|
|
|
+const getPackageStatus = async () => {
|
|
|
+ const res = await getDictTypeApi('package_new_status')
|
|
|
+ if (res.code === 0) {
|
|
|
+ packageStatusMap.value = res.data ?? []
|
|
|
+ }
|
|
|
+}
|
|
|
+const getPackageStatusText = (status: string | null) => {
|
|
|
+ const statusItem = packageStatusMap.value.find((item) => item.value === status)
|
|
|
+ return statusItem ? statusItem.label : '-'
|
|
|
+}
|
|
|
|
|
|
const formatDate = (value: string | null) => value?.slice(0, 10) || '-'
|
|
|
|
|
|
onReachBottom(loadMoreTaskPackageList)
|
|
|
-onBeforeMount(fetchTaskPackageList)
|
|
|
+onBeforeMount(() => {
|
|
|
+ fetchTaskPackageList()
|
|
|
+ getPackageStatus()
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
@@ -253,6 +400,12 @@ onBeforeMount(fetchTaskPackageList)
|
|
|
|
|
|
.task-filter-header {
|
|
|
background: #ffffff;
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ z-index: 99;
|
|
|
+ padding-bottom: 16rpx;
|
|
|
|
|
|
.task-filter-header__search {
|
|
|
margin-bottom: 6rpx;
|
|
|
@@ -262,6 +415,7 @@ onBeforeMount(fetchTaskPackageList)
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
height: 88rpx;
|
|
|
+ padding: 0 18rpx;
|
|
|
|
|
|
.task-list-controls__tabs {
|
|
|
display: flex;
|
|
|
@@ -301,7 +455,7 @@ onBeforeMount(fetchTaskPackageList)
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
- width: 220rpx;
|
|
|
+ width: 280rpx;
|
|
|
height: 100%;
|
|
|
color: #333333;
|
|
|
}
|
|
|
@@ -323,6 +477,7 @@ onBeforeMount(fetchTaskPackageList)
|
|
|
|
|
|
.task-list-content {
|
|
|
padding: 24rpx 32rpx;
|
|
|
+ margin-top: 200rpx;
|
|
|
|
|
|
.task-card {
|
|
|
margin-bottom: 24rpx;
|
|
|
@@ -423,7 +578,7 @@ onBeforeMount(fetchTaskPackageList)
|
|
|
}
|
|
|
|
|
|
.task-empty {
|
|
|
- padding-top: 160rpx;
|
|
|
+ padding-top: 360rpx;
|
|
|
}
|
|
|
}
|
|
|
</style>
|