| src/api/work/index.js | ●●●●● patch | view | raw | blame | history | |
| src/pages/work/index.vue | ●●●●● patch | view | raw | blame | history | |
| src/subPackages/workDetail/index.vue | ●●●●● patch | view | raw | blame | history |
src/api/work/index.js
New file @@ -0,0 +1,24 @@ import {request} from "@/utils/index.js"; export const getList = (data) => { return request({ url: '/drone-device-core/jobEvent/eventPage', method: 'post', data, }) } // 获取状态统计数据 export const getstatusCount = (params) => { return request({ url: '/drone-device-core/jobEvent/getstatusCount', method: 'get', params, }) } export const getStepInfo = (eventNum) => { return request({ url: '/drone-device-core/jobEvent/getStepInfo', method: 'get', params: { eventNum } }) } src/pages/work/index.vue
@@ -1,67 +1,208 @@ <!-- 事件工单 --> <template> <view class="min-h-screen flex flex-col items-center"> <image class="mb-50rpx mt-200rpx h-200rpx w-200rpx" src="@/static/images/logo.png" width="200rpx" height="200rpx" /> <view class="flex justify-center"> <text class="font-size-36rpx"> {{ $t("home.intro") }} </text> </view> <view class="mt-100rpx flex gap-30rpx"> <lang-select /> <view class="cursor-pointer" @click="toGithub"> <view class="i-mdi-github text-40rpx" /> </view> </view> <view class="flex flex-col eventTickets"> <view class="searchTop"> <up-search placeholder="请输入关键字搜索" :animation="true" v-model="listParams.keyword" :show-action="false"></up-search> <div>111</div> </view> <view> <up-tabs :list="tabList" @click="handleClick"></up-tabs> <view class="eventBox"> <view class="eventItem" v-for="(item,index) in dataList" :key="index"> <img :src="item.photo_url" alt="" @click="detailHandle(item)" /> <div class="itemTitle">{{item.event_name}}</div> <div class="itemContent"> <div class="itemStatus"> <span v-if="item.status === 0" style="background-color: #ff7411;"></span> <span v-else-if="item.status === 2" style="background-color: #ff472f;"></span> <span v-else-if="item.status === 3" style="background-color: #ffc300;"></span> <span v-else-if="item.status === 4" style="background-color: #06d957;"></span> <p>{{formatDate(item.create_time) }}</p> </div> <div>全屏</div> </div> </view> </view> </view> </view> <!-- #ifdef MP-WEIXIN --> <!-- 隐私协议组件 --> <agree-privacy v-model="showAgreePrivacy" :disable-check-privacy="false" @agree="handleAgree" /> <!-- #endif --> </view> </template> <script setup> // #ifdef MP-WEIXIN import { useShare } from "@/hooks"; // #endif // #ifdef MP-WEIXIN // 分享使用示例 const { onShareAppMessage, onShareTimeline } = useShare({ title: "首页", path: "pages/tab/map/index", imageUrl: "", }); onShareAppMessage(); onShareTimeline(); // #endif import {getList,getstatusCount} from '/src/api/work/index.js' import dayjs from 'dayjs'; const dataList = ref([]) const keyword = ref('') const tabList = ref([{ name: '我的工单', key: 'myTickets', badge: { value: 1 } }, { name: '全部状态', key: 'all', badge: { value: 2 }, status: null }, { name: '待审核', key: 'pending', badge: { value: 3 }, status: '2' }, { name: '待处理', key: 'processing', badge: { value: 4 }, status: '0' }, { name: '处理中', key: 'inProgress', badge: { value: 5 }, status: '3' }, { name: '已完成', key: 'completed', badge: { value: 6 }, status: '4' } ]) const formatDate = (dateString) => { return dayjs(dateString).format('MM/DD HH:mm'); }; const listParams = ref({ status: null, current: 1, size: 9999, source: 1, department:'', keyword:'' const title = ref(); title.value = import.meta.env.VITE_APP_TITLE; }) const getDataList = () => { const params = { current: 1, size: 9999, source: 1, status:listParams.value.status, event_name:listParams.value.keyword } getList(params).then(res => { const response = res.data.data.records dataList.value = response }) } const getstatusCountData=()=>{ getstatusCount().then(res=>{ const response = res.data.data const { statusCount, totalCount, userCount } = response tabList.value.forEach(tab=>{ if(tab.key === 'all'){ tab.badge.value = totalCount || 0 const showAgreePrivacy = ref(false); }else if(tab.key === 'myTickets'){ tab.badge.value = userCount || 0 }else{ tab.badge.value=statusCount[String(tab.status)] || 0 } }) }) } // 同意隐私协议 function handleAgree() { console.log("同意隐私政策"); } // 打开github function toGithub() { if (window?.open) { window.open("https://github.com/oyjt/uniapp-vue3-template"); } else { uni.$u.toast("请使用浏览器打开"); } } const handleClick = (item) => { listParams.value.status = item.status getDataList() } const detailHandle = (val) => { uni.navigateTo({ url: `/subPackages/workDetail/index?eventNum=${val.event_num}`, }) } onShow(() => { getDataList() getstatusCountData() }) </script> <style scoped lang="scss"> .eventTickets { padding: 0 10px; .searchTop { display: flex; align-items: center; margin-top: 10px; } :deep(.u-badge) { background-color: #1d6fe9 !important; } .eventBox { display: flex; flex-wrap: wrap; gap: 10px; padding: 10px 0; background-color: #ebeff2; .eventItem { width: calc(50% - 5px); background-color: #fff; border-radius: 5px; overflow: hidden; img { width: 100%; height: 100px; border-radius: 5px; overflow: hidden; } .itemTitle { padding: 0 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .itemContent { display: flex; justify-content: space-between; align-items: center; padding: 5px; .itemStatus { display: flex; align-items: center; span { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 5px; } } } } } } </style> src/subPackages/workDetail/index.vue
@@ -1,18 +1,239 @@ <!-- * @Author : yuan * @Date : 2025-09-29 13:52:16 * @LastEditors : yuan * @LastEditTime : 2025-09-29 13:53:32 * @FilePath : \src\subPackages\workDetail\index.vue * @Description : * Copyright 2025 OBKoro1, All Rights Reserved. * 2025-09-29 13:52:16 --> <!-- 工单详情 - 包含待审核、待处理、处理中、已完成 --> <template> <view> 基础 </view> <view class="workDetailContainer"> <div class="detailTop"> <div class="image-container"> <u-image class="detailImage" :src="workDetailData.photo_url" mode="cover" width="100%" height="200px" @click="previewImage(workDetailData.photo_url)"></u-image> <div class="detailTitle"> <div class="titleText"> <p>{{workDetailData.event_name}}</p> <p>{{workDetailData.create_time}}</p> </div> </div> </div> </div> <!-- 步骤条 --> <div class="stepContainer"> <up-steps :current="currentStep" direction="column"> <up-steps-item v-for="(step, index) in stepTitles" :key="index" > <template #title> <div class="horizontal-step"> <span class="step-title">{{ step.title }}</span> <div class="step-desc" v-if="stepResponse[index]"> <span>{{ stepResponse[index].name || '' }}</span> <span>{{ stepResponse[index].create_time || '' }}</span> </div> </div> </template> </up-steps-item> </up-steps> </div> <!-- 工单内容 --> <div class="workOrderContent"> <div class="workOrderTitle">工单内容</div> <div class="workOrderContainer"> <div>工单名称:{{workDetailData.event_name}}</div> <div>工单类型:{{workDetailData.$type}}</div> <div>关联任务:{{workDetailData.job_name}}</div> <div>工单创建人:{{workDetailData.creator}}</div> <div>事件地址:{{workDetailData.address}}</div> <div>关联算法:{{workDetailData.ai_types}}</div> <div>发起部门:{{workDetailData.dept_name}}</div> <div>发起任务时间:{{workDetailData.create_time}}</div> <div>工单内容:{{workDetailData.remark}}</div> </div> </div> <!-- 操作按钮 --> <div class="actionButton"> <div class="leftBtn" @click="leftClick"> 上一页 </div> <div class="btngroups"> <up-button type="primary" text="通过"></up-button> <up-button type="error" text="不通过"></up-button> </div> <div class="leftBtn" @click="rightClick"> 下一页 </div> </div> </view> </template> <script setup></script> <script setup> import {getStepInfo,getList} from '/src/api/work/index.js' const eventNum = ref(''); const currentStatus = ref('') const stepResponse = ref([]); const currentStep = ref(0); // 工单内容 const workDetailData = ref({}) const stepTitles =ref([ { title: '待审核', status: '2' }, { title: '待处理', status: '0' }, { title: '处理中', status: '3' },{ title: '已完成', status: '4' } ]) onLoad(async (options) => { eventNum.value = options.eventNum; await getDataList(eventNum.value); await getStepInfoData(eventNum.value); }); const getDataList = async (val) => { const params = { current: 1, size: 9999, source: 1, event_name: val } const res = await getList(params); const response = res.data.data.records; workDetailData.value = response[0]; currentStatus.value = workDetailData.value.status; } // 步骤条 const calculateCurrentStep = (status) => { const statusToStep = { '2': 0, // 待审核 -> 第0步 '0': 1, // 待处理 -> 第1步 '3': 2, // 处理中 -> 第2步 '4': 3 // 已完成 -> 第3步 } return statusToStep[String(status)] || 0 } const getStepInfoData = async (val) => { const res = await getStepInfo(val); stepResponse.value = res.data.data; currentStep.value = calculateCurrentStep(currentStatus.value); } // 图片预览 const previewImage = (url) => { uni.previewImage({ urls: [url], current: 0 }); }; </script> <style lang="scss" scoped></style> <style lang="scss" scoped> .workDetailContainer { padding: 0 10px; .detailTop { .image-container { position: relative; width: 100%; height: 200px; .detailImage { width: 100%; height: 100%; display: block; object-fit: cover } .detailTitle { position: absolute; left: 0; bottom: 0; width: 100%; } .titleText { display: flex; width: 100%; justify-content: space-between; align-items: center; } } } .stepContainer { margin-top: 10px; display: flex; background-color: aquamarine; border-radius: 5px; padding: 10px; .horizontal-step { display: flex; align-items: center; gap: 12px; .step-title { min-width: 60px; } .step-desc { display: flex; justify-content: space-around; gap: 8px; // color: #666; font-size: 14px; } } } .actionButton{ display: flex; justify-content: space-between; margin-bottom: 10px; .btngroups { display: flex; justify-content: space-between; .u-button { padding: 9px 20px; height: 32px; &:last-child { margin-left: 12px; margin-right: 12px; } } } .leftBtn { width: 70px; height: 32px; background-color: #999; border-radius: 5px; text-align: center; line-height: 32px; color: #fff; cursor: pointer; opacity: 0.8; } .disableds { background: #999 !important; cursor: not-allowed !important; pointer-events: none; opacity: 0.3 !important; } } .workOrderContent { margin-top: 15px; .workOrderContainer { div { margin-bottom: 10px; } } } } </style>