| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- <template>
- <view class="app-container pb-24">
- <TopBar title="任务详情" showBack />
- <view v-if="task" class="px-4 py-4 gap-y-4">
- <!-- 施工流程进度 -->
- <ConstructionFlowBar :status="task.status" :timeline="task.timeline" />
- <!-- 操作按钮区 -->
- <view class="card p-4">
- <!-- 待确认 -->
- <view v-if="task.status === 'pending'" class="gap-y-3">
- <view class="bg-blue-50 rounded-xl p-4 mb-4 text-center">
- <text class="uni-icons uniui-compose text-4xl block mb-2 text-blue-500"></text>
- <text class="text-lg font-semibold text-gray-800 block">待确认任务</text>
- <text class="text-gray-500 text-sm mt-1 block">请查看任务详情,确认是否接受</text>
- </view>
- <button class="w-full py-3 btn-success rounded-xl font-medium flex items-center justify-center gap-2" @click="onConfirm">
- <text>确认任务</text>
- </button>
- <button class="w-full py-3 bg-orange-50 border border-orange-200 text-orange-600 rounded-xl font-medium flex items-center justify-center gap-2" @click="onFeedback">
- <text>反馈问题</text>
- </button>
- <button class="w-full py-3 bg-red-50 border border-red-200 text-red-500 rounded-xl font-medium flex items-center justify-center gap-2" @click="onReject">
- <text>拒绝任务</text>
- </button>
- </view>
- <!-- 待出车 -->
- <view v-else-if="task.status === 'scheduled'" class="gap-y-3">
- <view class="bg-orange-50 rounded-xl p-4 mb-4 text-center">
- <text class="uni-icons uniui-cart-filled text-4xl block mb-2 text-orange-500"></text>
- <text class="text-lg font-semibold text-gray-800 block">准备出发</text>
- <text class="text-gray-500 text-sm mt-1 block">请确认设备准备完毕后出发</text>
- </view>
- <view class="bg-white rounded-lg p-3 border border-gray-100 mb-3">
- <view class="flex justify-between text-sm">
- <text class="text-gray-400">目的地</text>
- <text class="text-gray-800">{{ task.projectName }}</text>
- </view>
- <view v-if="task.vehicle" class="flex justify-between text-sm mt-2">
- <text class="text-gray-400">车辆</text>
- <text class="text-gray-800">{{ task.vehicle }}</text>
- </view>
- </view>
- <button class="w-full py-3 btn-primary rounded-xl font-semibold flex items-center justify-center gap-2" @click="onDepart">
- <text>出发</text>
- </button>
- </view>
- <!-- 已出车 -->
- <view v-else-if="task.status === 'departed'" class="gap-y-3">
- <view class="bg-purple-50 rounded-xl p-4 mb-4 text-center">
- <text class="uni-icons uniui-location-filled text-4xl block mb-2 text-purple-500"></text>
- <text class="text-lg font-semibold text-gray-800 block">前往现场</text>
- <text class="text-gray-500 text-sm mt-1 block">正在前往施工地点</text>
- </view>
- <button class="w-full py-3 btn-success rounded-xl font-semibold flex items-center justify-center gap-2" @click="onArrive">
- <text>到达现场</text>
- </button>
- </view>
- <!-- 已到达(勘验) -->
- <view v-else-if="task.status === 'arrived'" class="gap-y-3">
- <view class="bg-green-50 rounded-xl p-4 mb-4 text-center">
- <text class="uni-icons uniui-location text-4xl block mb-2 text-green-500"></text>
- <text class="text-lg font-semibold text-gray-800 block">已到达现场</text>
- <text class="text-gray-500 text-sm mt-1 block">请完成现场勘验后开始施工作业</text>
- </view>
- <button class="w-full py-3 btn-primary rounded-xl font-semibold flex items-center justify-center gap-2" @click="onStartWork">
- <text>开始施工</text>
- </button>
- </view>
- <!-- 施工中 -->
- <view v-else-if="task.status === 'constructing'" class="gap-y-3">
- <view class="bg-blue-50 rounded-xl p-4 mb-4 text-center">
- <text class="uni-icons uniui-gear-filled text-4xl block mb-2 text-blue-500"></text>
- <text class="text-lg font-semibold text-gray-800 block">施工中</text>
- <text class="text-gray-500 text-sm mt-1 block">请按规范完成施工作业</text>
- </view>
- <button class="w-full py-3 btn-success rounded-xl font-semibold flex items-center justify-center gap-2" @click="onComplete">
- <text>完成施工</text>
- </button>
- </view>
- <!-- 待验收 -->
- <view v-else-if="task.status === 'inspecting'" class="gap-y-3">
- <view class="bg-warning-light rounded-xl p-4 mb-4 text-center">
- <text class="uni-icons uniui-person-filled text-4xl block mb-2 text-warning"></text>
- <text class="text-lg font-semibold text-gray-800 block">等待验收</text>
- <text class="text-gray-500 text-sm mt-1 block">请等待客户或调度验收</text>
- </view>
- <button class="w-full py-3 btn-success rounded-xl font-semibold flex items-center justify-center gap-2" @click="onAccept">
- <text>完成验收</text>
- </button>
- </view>
- <!-- 已完成 -->
- <view v-else-if="task.status === 'completed'" class="gap-y-3">
- <view class="bg-green-50 rounded-xl p-4 text-center">
- <text class="uni-icons uniui-checkmarkempty text-4xl block mb-2 text-green-500"></text>
- <text class="text-lg font-semibold text-green-700 block">任务已完成</text>
- <text class="text-gray-500 text-sm mt-1 block">该任务已验收通过</text>
- </view>
- </view>
- </view>
- <!-- 任务信息 -->
- <view class="card p-4">
- <view class="detail-section-title mb-4">
- <text class="uni-icons uniui-flag-filled text-primary mr-2"></text>
- <text>{{ task.projectName }}</text>
- <StatusTag :status="task.status" class="ml-auto" />
- </view>
- <view class="space-y-3">
- <view class="detail-row">
- <text class="detail-label">任务类型</text>
- <text class="detail-value">{{ getTypeText(task.type) }}</text>
- </view>
- <view class="detail-row">
- <text class="detail-label">紧急程度</text>
- <text :class="task.urgent === 'high' ? 'text-danger' : 'text-gray-800'">{{ getUrgentText(task.urgent) }}</text>
- </view>
- <view v-if="task.serviceType" class="detail-row">
- <text class="detail-label">施工类型</text>
- <text class="detail-value">{{ task.serviceType }}</text>
- </view>
- <view v-if="task.facilityType" class="detail-row">
- <text class="detail-label">设施类型</text>
- <text class="detail-value">{{ task.facilityType }}</text>
- </view>
- <view v-if="task.faultLocation" class="detail-row">
- <text class="detail-label">故障位置</text>
- <text class="detail-value">{{ task.faultLocation }}</text>
- </view>
- <view v-if="task.faultDesc" class="detail-row">
- <text class="detail-label">故障描述</text>
- <text class="detail-value">{{ task.faultDesc }}</text>
- </view>
- <view v-if="task.assignee" class="detail-row">
- <text class="detail-label">负责人</text>
- <text class="detail-value">{{ task.assignee }}</text>
- </view>
- <view v-if="task.vehicle" class="detail-row">
- <text class="detail-label">车辆</text>
- <text class="detail-value">{{ task.vehicle }}</text>
- </view>
- <view v-if="task.team" class="detail-row">
- <text class="detail-label">班组</text>
- <text class="detail-value">{{ task.team }}</text>
- </view>
- <view v-if="task.scheduledDate" class="detail-row">
- <text class="detail-label">计划日期</text>
- <text class="detail-value">{{ task.scheduledDate }}</text>
- </view>
- <view v-if="task.address" class="detail-row">
- <text class="detail-label">项目地址</text>
- <text class="detail-value text-right flex-1">{{ task.address }}</text>
- </view>
- <view class="detail-row">
- <text class="detail-label">创建时间</text>
- <text class="detail-value">{{ formatDate(task.createTime, 'YYYY-MM-DD HH:mm') }}</text>
- </view>
- </view>
- </view>
- <!-- 时间轴 -->
- <view class="card p-4">
- <view class="detail-section-title mb-4">
- <text class="uni-icons uniui-time-filled text-primary mr-2"></text>
- <text>操作记录</text>
- </view>
- <Timeline :records="sortedTimeline" />
- </view>
- </view>
- <EmptyState v-else message="任务不存在" />
- </view>
- </template>
- <script setup lang="ts">
- import { computed } from 'vue'
- import { onLoad } from '@dcloudio/uni-app'
- import TopBar from '../../components/common/TopBar.vue'
- import StatusTag from '../../components/common/StatusTag.vue'
- import EmptyState from '../../components/common/EmptyState.vue'
- import Timeline from '../../components/common/Timeline.vue'
- import ConstructionFlowBar from '../../components/common/ConstructionFlowBar.vue'
- import { useTaskStore } from '../../stores/task'
- import { formatDate, getTypeText, getUrgentText, showToast, showModal, goBack } from '../../utils'
- import { updateTask } from '../../api/task'
- const taskStore = useTaskStore()
- const task = computed(() => taskStore.currentTask)
- const sortedTimeline = computed(() => {
- if (!task.value?.timeline) return []
- return [...task.value.timeline].sort((a, b) => new Date(b.time).getTime() - new Date(a.time).getTime())
- })
- async function advanceStatus(step: number, successMsg: string) {
- if (!task.value) return
- try {
- await taskStore.advanceStep(Number(task.value.id), step)
- showToast(successMsg)
- await taskStore.fetchTaskDetail(Number(task.value.id))
- } catch (error) {
- showToast('操作失败')
- }
- }
- function onConfirm() {
- advanceStatus(1, '任务已确认')
- }
- function onDepart() {
- advanceStatus(3, '已出车')
- }
- function onArrive() {
- advanceStatus(4, '已到达现场')
- }
- function onStartWork() {
- advanceStatus(5, '开始施工')
- }
- function onComplete() {
- advanceStatus(6, '施工完成')
- }
- function onAccept() {
- advanceStatus(7, '验收完成')
- }
- async function onReject() {
- const res = await showModal({
- title: '拒绝任务',
- content: '确定要拒绝此任务吗?',
- showCancel: true,
- confirmText: '确认拒绝',
- })
- if (res.confirm && task.value) {
- try {
- await updateTask(Number(task.value.id), { status: 'rejected' } as any)
- showToast('已拒绝任务')
- goBack()
- } catch {
- showToast('操作失败')
- }
- }
- }
- function onFeedback() {
- showModal({
- title: '反馈问题',
- content: '请描述遇到的问题,将提交给调度中心处理',
- showCancel: true,
- confirmText: '提交',
- success: (res) => {
- if (res.confirm) {
- showToast('反馈已提交')
- }
- }
- })
- }
- onLoad((options) => {
- if (options?.id) {
- taskStore.setCurrentTask(options.id)
- }
- })
- </script>
|