From 150ba60e3436b3e6a418b0a66723938b5dc2cfb8 Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Fri, 31 Jul 2026 17:17:14 +0800
Subject: [PATCH] feat:处置功能
---
uniapps/work-app/src/pages/work/index.vue | 643 +++++++++++++++++++++++++++++++--------------------------
1 files changed, 348 insertions(+), 295 deletions(-)
diff --git a/uniapps/work-app/src/pages/work/index.vue b/uniapps/work-app/src/pages/work/index.vue
index 31499da..205c21e 100644
--- a/uniapps/work-app/src/pages/work/index.vue
+++ b/uniapps/work-app/src/pages/work/index.vue
@@ -1,18 +1,23 @@
<template>
- <div class="eventTickets" :style="{ paddingTop: topMargin + 'px' }">
-
- <div class="searchTop">
- <up-search placeholder="请输入关键字搜索" :animation="true" v-model="listParams.keyword" :show-action="false" @search="handleSearch" @clear="handleClear"></up-search>
- </div>
- <div class="listBox">
- <div class="tabs-container">
- <up-tabs :list="tabList" @click="handleClick"></up-tabs>
- </div>
-<!-- @scrolltolower="loadMore" -->
- <scroll-view class="eventBox" scroll-y :lower-threshold="80" >
- <div class="eventList">
- <div class="eventItem" v-for="(item,index) in dataList" :key="index">
- <image
+ <div class="eventTickets" :style="{ paddingTop: topMargin + 'px' }">
+ <div class="searchTop">
+ <up-search
+ placeholder="请输入关键字搜索"
+ :animation="true"
+ v-model="listParams.keyword"
+ :show-action="false"
+ @search="handleSearch"
+ @clear="handleClear"
+ ></up-search>
+ </div>
+ <div class="listBox">
+ <div class="tabs-container">
+ <up-tabs :scrollable="true" :list="tabList" @click="handleClick"></up-tabs>
+ </div>
+ <scroll-view class="eventBox" scroll-y :lower-threshold="80" @scrolltolower="loadMore">
+ <div class="eventList">
+ <div class="eventItem" v-for="(item, index) in dataList" :key="index">
+ <image
v-if="[1, 2].includes(item.attachmentType)"
:src="item?.aiImg || item?.eventImageUrl"
mode="aspectFill"
@@ -21,88 +26,112 @@
<div v-if="item.attachmentType === 3" class="videoBox" @click="detailHandle(item)">
<div class="playIcon"></div>
</div>
- <div class="informationDisplay">
+ <div class="informationDisplay">
<div class="itemTitle">{{ item.eventName }}</div>
- <div class="itemContent">{{ formatDate(item.createTime) }}</div>
- </div>
- </div>
- </div>
+ <div class="itemContent">{{ formatDate(item.createTime) }}</div>
+ </div>
+ </div>
+ </div>
- <!-- 暂无数据提示 -->
- <div class="noData" v-if="!loading && dataList.length === 0">
- <text>暂无数据</text>
- </div>
+ <!-- 暂无数据提示 -->
+ <div class="noData" v-if="!loading && dataList.length === 0">
+ <text>暂无数据</text>
+ </div>
- <!-- 加载提示 -->
- <div class="loadingMore">
- <text v-if="loading">加载中...</text>
-
- </div>
- </scroll-view>
- </div>
+ <!-- 加载提示 -->
+ <div class="loadingMore">
+ <text v-if="loading">加载中...</text>
+ <text v-else-if="!hasMore">没有更多了</text>
+ </div>
+ </scroll-view>
+ </div>
<canvas
canvas-id="ai-image-canvas"
id="ai-image-canvas"
class="ai-image-canvas"
:style="{ width: canvasSize.width + 'px', height: canvasSize.height + 'px' }"
></canvas>
-
- </div>
-
+ </div>
</template>
<script setup>
-
import { getCurrentInstance, nextTick } from 'vue'
import { useUserStore } from '@/store/index.js'
-import {getGdList,getstatusCount} from '@/api/work/index.js'
-import dayjs from 'dayjs';
-import { getStatusBarHeight } from '@/utils/common';
+import { getGdList, getstatusCount } from '@/api/work/index.js'
+import dayjs from 'dayjs'
+import { getStatusBarHeight } from '@/utils/common'
const canvasOwner = getCurrentInstance()?.proxy
const userStore = useUserStore()
const userInfo = userStore.userInfo
const dataList = ref([])
-const currentTab=ref('all')
+const currentTab = ref('all')
const loading = ref(false)
const hasMore = ref(true)
const tabList = ref([
- {
- name: '全部工单',
- key: 'all',
- badge: {
- value: 0,
- showZero: true
- },
-
- },
- {
- name: '我的工单',
- key: 'myTickets',
- badge: {
- value: 0,
- showZero: true
- }
- }
-
-
+ {
+ name: '全部工单',
+ key: 'all',
+ badge: {
+ value: 0,
+ showZero: true,
+ },
+ },
+ {
+ name: '我的工单',
+ key: 'myTickets',
+ badge: {
+ value: 0,
+ showZero: true,
+ },
+ },
+ {
+ name: '处置中',
+ key: 'disposing',
+ badge: {
+ value: 0,
+ showZero: true,
+ },
+ },
+ {
+ name: '已处置',
+ key: 'handled',
+ badge: {
+ value: 0,
+ showZero: true,
+ },
+ },
+ {
+ name: '已完成',
+ key: 'completed',
+ badge: {
+ value: 0,
+ showZero: true,
+ },
+ },
])
-const formatDate = (dateString) => {
- return dayjs(dateString).format('MM/DD HH:mm');
-};
+// tab key 与事件状态码映射
+const tabStatusMap = {
+ disposing: 1,
+ handled: 3,
+ completed: 4,
+}
+const formatDate = dateString => {
+ return dayjs(dateString).format('MM/DD HH:mm')
+}
const listParams = ref({
-
- current: 1,
- size: 12,
- source: 1,
- department:'',
- keyword:''
-
+ current: 1,
+ size: 12,
+ source: 1,
+ department: '',
+ keyword: '',
+ eventStatus: '',
})
-const mockGeojson = "[{\"score\":0.89990234375,\"bbox\":{\"x_cen\":195.5,\"y_cen\":326.5,\"width\":117.0,\"height\":265.0},\"class_name\":\"car\",\"algorithmId\":\"e71116098eeb1d60cfebd04d30653b151\"},{\"score\":0.89306640625,\"bbox\":{\"x_cen\":1194.5,\"y_cen\":559.5,\"width\":115.0,\"height\":261.0},\"class_name\":\"car\",\"algorithmId\":\"e71116098eeb1d60cfebd04d30653b151\"},{\"score\":0.88720703125,\"bbox\":{\"x_cen\":179.0,\"y_cen\":955.5,\"width\":124.0,\"height\":249.0},\"class_name\":\"car\",\"algorithmId\":\"e71116098eeb1d60cfebd04d30653b151\"},{\"score\":0.88330078125,\"bbox\":{\"x_cen\":1198.5,\"y_cen\":260.5,\"width\":115.0,\"height\":285.0},\"class_name\":\"car\",\"algorithmId\":\"e71116098eeb1d60cfebd04d30653b151\"},{\"score\":0.84716796875,\"bbox\":{\"x_cen\":204.5,\"y_cen\":71.5,\"width\":115.0,\"height\":143.0},\"class_name\":\"car\",\"algorithmId\":\"e71116098eeb1d60cfebd04d30653b151\"},{\"score\":0.83203125,\"bbox\":{\"x_cen\":186.0,\"y_cen\":657.5,\"width\":114.0,\"height\":269.0},\"class_name\":\"car\",\"algorithmId\":\"e71116098eeb1d60cfebd04d30653b151\"},{\"score\":0.78662109375,\"bbox\":{\"x_cen\":1205.5,\"y_cen\":49.5,\"width\":117.0,\"height\":99.0},\"class_name\":\"car\",\"algorithmId\":\"e71116098eeb1d60cfebd04d30653b151\"}]"
+const mockGeojson =
+ '[{"score":0.89990234375,"bbox":{"x_cen":195.5,"y_cen":326.5,"width":117.0,"height":265.0},"class_name":"car","algorithmId":"e71116098eeb1d60cfebd04d30653b151"},{"score":0.89306640625,"bbox":{"x_cen":1194.5,"y_cen":559.5,"width":115.0,"height":261.0},"class_name":"car","algorithmId":"e71116098eeb1d60cfebd04d30653b151"},{"score":0.88720703125,"bbox":{"x_cen":179.0,"y_cen":955.5,"width":124.0,"height":249.0},"class_name":"car","algorithmId":"e71116098eeb1d60cfebd04d30653b151"},{"score":0.88330078125,"bbox":{"x_cen":1198.5,"y_cen":260.5,"width":115.0,"height":285.0},"class_name":"car","algorithmId":"e71116098eeb1d60cfebd04d30653b151"},{"score":0.84716796875,"bbox":{"x_cen":204.5,"y_cen":71.5,"width":115.0,"height":143.0},"class_name":"car","algorithmId":"e71116098eeb1d60cfebd04d30653b151"},{"score":0.83203125,"bbox":{"x_cen":186.0,"y_cen":657.5,"width":114.0,"height":269.0},"class_name":"car","algorithmId":"e71116098eeb1d60cfebd04d30653b151"},{"score":0.78662109375,"bbox":{"x_cen":1205.5,"y_cen":49.5,"width":117.0,"height":99.0},"class_name":"car","algorithmId":"e71116098eeb1d60cfebd04d30653b151"}]'
const canvasSize = ref({
width: 1,
- height: 1
+ height: 1,
})
const parseAiFrame = aiFrameSource => {
@@ -125,26 +154,29 @@
fail: error => {
console.log(error)
resolve(null)
- }
+ },
})
})
const canvasToTempFilePath = (width, height) =>
new Promise(resolve => {
- uni.canvasToTempFilePath({
- canvasId: 'ai-image-canvas',
- width,
- height,
- destWidth: width,
- destHeight: height,
- fileType: 'jpg',
- quality: 0.92,
- success: res => resolve(res.tempFilePath),
- fail: error => {
- console.log(error)
- resolve('')
- }
- }, canvasOwner)
+ uni.canvasToTempFilePath(
+ {
+ canvasId: 'ai-image-canvas',
+ width,
+ height,
+ destWidth: width,
+ destHeight: height,
+ fileType: 'jpg',
+ quality: 0.92,
+ success: res => resolve(res.tempFilePath),
+ fail: error => {
+ console.log(error)
+ resolve('')
+ },
+ },
+ canvasOwner
+ )
})
const drawAiImage = async (url, aiFrameSource) => {
@@ -200,202 +232,224 @@
}
const getDataList = () => {
- if (loading.value || !hasMore.value) return
+ if (loading.value || !hasMore.value) return
- loading.value = true
- const params = {
- current: listParams.value.current,
- size: listParams.value.size,
- keyword:listParams.value.keyword,
- onlyMine:currentTab.value=== 'myTickets' ? 1 : 0
- }
- getGdList(params).then(async res => {
- const response = res.data.data
- const list = []
- for (const item of response) {
- // const aiImg = await drawAiImage(item.eventImageUrl, mockGeojson)
- if (item.attachmentType !== 2) {
- list.push(item)
- }else{
- const aiImg = await drawAiImage(item.eventImageUrl, item.geojson)
- list.push({ ...item, aiImg })
+ loading.value = true
+ const params = {
+ current: listParams.value.current,
+ size: listParams.value.size,
+ keyword: listParams.value.keyword,
+ onlyMine: currentTab.value === 'myTickets' ? 1 : 0,
+ eventStatus: listParams.value.eventStatus,
+ }
+ getGdList(params)
+ .then(async res => {
+ const resData = res.data.data
+ const response = resData.records
+ const list = []
+ for (const item of response) {
+ // const aiImg = await drawAiImage(item.eventImageUrl, mockGeojson)
+ if (item.attachmentType !== 2) {
+ list.push(item)
+ } else {
+ const aiImg = await drawAiImage(item.eventImageUrl, item.geojson)
+ list.push({ ...item, aiImg })
+ }
}
- }
- dataList.value = list
- // 根据当前页码决定是替换还是追加数据
- // if (listParams.value.current === 1) {
- // dataList.value = response
- // } else {
- // dataList.value = [...dataList.value, ...response]
- // }
-
- // // 判断是否还有更多数据
- // if (response.length < listParams.value.size || response.current >= response.pages) {
- // hasMore.value = false
- // } else {
- // hasMore.value = true
- // }
- }).finally(() => {
- loading.value = false
- })
-}
-const getstatusCountData=()=>{
- const params={
- keyword:listParams.value.keyword,
- }
- getstatusCount(params).then(res=>{
- const response = res.data.data
- const { totalCount,myCount } = response
- tabList.value.forEach(tab=>{
-
- if(tab.key === 'all'){
- tab.badge.value = (totalCount || 0).toString()
- tab.badge.showZero = true
-
- }else if(tab.key === 'myTickets'){
- tab.badge.value = (myCount || 0).toString()
- tab.badge.showZero = true
+ // 根据当前页码决定是替换还是追加数据
+ if (listParams.value.current === 1) {
+ dataList.value = list
+ } else {
+ dataList.value = [...dataList.value, ...list]
+ }
+ // 判断是否还有更多数据
+ if (list.length < listParams.value.size || resData.current >= resData.pages) {
+ hasMore.value = false
+ } else {
+ hasMore.value = true
}
})
-
+ .finally(() => {
+ loading.value = false
+ })
+}
+const getstatusCountData = () => {
+ const params = {
+ keyword: listParams.value.keyword,
+ }
+ getstatusCount(params).then(res => {
+ const response = res.data.data
+ const { totalCount, myCount, disposingCount, disposedCount, completedCount } = response
+ tabList.value.forEach(tab => {
+ if (tab.key === 'all') {
+ tab.badge.value = (totalCount || 0).toString()
+ tab.badge.showZero = true
+ } else if (tab.key === 'myTickets') {
+ tab.badge.value = (myCount || 0).toString()
+ tab.badge.showZero = true
+ } else if (tab.key === 'disposing') {
+ tab.badge.value = (disposingCount || 0).toString()
+ tab.badge.showZero = true
+ } else if (tab.key === 'handled') {
+ tab.badge.value = (disposedCount || 0).toString()
+ tab.badge.showZero = true
+ } else if (tab.key === 'completed') {
+ tab.badge.value = (completedCount || 0).toString()
+ tab.badge.showZero = true
+ }
+ })
})
}
-const handleClick = (item) => {
- currentTab.value = item.key
+const handleClick = item => {
+ currentTab.value = item.key
+ listParams.value.eventStatus = tabStatusMap[item.key] ?? ''
- listParams.value.current = 1
- hasMore.value = true
- dataList.value = []
- getDataList()
+ listParams.value.current = 1
+ hasMore.value = true
+ dataList.value = []
+ getDataList()
}
const loadMore = () => {
- if (loading.value || !hasMore.value) return
- listParams.value.current++
- getDataList()
+ if (loading.value || !hasMore.value) return
+ listParams.value.current++
+ getDataList()
}
-const detailHandle = (val) => {
- uni.navigateTo({
- url: `/subPackages/workDetail/index?id=${val.id}` + (val.aiImg ? `&aiImg=${val.aiImg}` : ''),
- })
+const detailHandle = val => {
+ uni.navigateTo({
+ url: `/subPackages/workDetail/index?id=${val.id}` + (val.aiImg ? `&aiImg=${val.aiImg}` : ''),
+ })
}
// 搜索功能
const handleSearch = () => {
- listParams.value.current = 1
- hasMore.value = true
- dataList.value = []
- getDataList()
- getstatusCountData()
+ listParams.value.current = 1
+ hasMore.value = true
+ dataList.value = []
+ getDataList()
+ getstatusCountData()
}
// 清除搜索
const handleClear = () => {
- listParams.value.keyword = ''
- listParams.value.current = 1
- hasMore.value = true
- dataList.value = []
- getDataList()
- getstatusCountData()
+ listParams.value.keyword = ''
+ listParams.value.current = 1
+ hasMore.value = true
+ dataList.value = []
+ getDataList()
+ getstatusCountData()
}
const topMargin = getStatusBarHeight()
onShow(() => {
- listParams.value.current = 1
- hasMore.value = true
- dataList.value = []
- getDataList()
- getstatusCountData()
+ listParams.value.current = 1
+ hasMore.value = true
+ dataList.value = []
+ getDataList()
+ getstatusCountData()
})
</script>
<style scoped lang="scss">
.eventTickets {
- padding: 0 20rpx;
- display: flex;
- flex-direction: column;
- height: 100%;
- box-sizing: border-box;
- width: 100%;
- overflow-x: hidden;
- .searchTop {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding-right: 24rpx;
- width: 100%;
- height: 108rpx;
- :deep(){
- .u-search__content{
- background: #fff !important;
- }
- .u-search__content__input{
- background: #fff !important;
- }
- }
- }
- :deep(){
+ padding: 0 20rpx;
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ box-sizing: border-box;
+ width: 100%;
+ overflow-x: hidden;
+ .searchTop {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding-right: 24rpx;
+ width: 100%;
+ height: 108rpx;
+ :deep() {
+ .u-search__content {
+ background: #fff !important;
+ }
+ .u-search__content__input {
+ background: #fff !important;
+ }
+ }
+ }
+ :deep() {
+ .u-tabs__wrapper__nav__line {
+ // width: 80rpx !important;
+ background: #1d6fe9 !important;
+ }
+ .u-badge {
+ background-color: #1d6fe9 !important;
+ margin-top: -14px !important;
+ margin-left: -5px !important;
+ }
+ }
+ tabs-container {
+ display: flex;
+ align-items: center;
+ height: 98rpx;
+ width: 100%;
+ overflow-x: auto; // 横向滚动
+ overflow-y: hidden;
+ white-space: nowrap; // 防止换行
+ -webkit-overflow-scrolling: touch; // 移动端平滑滚动
- .u-tabs__wrapper__nav__line{
- // width: 80rpx !important;
- background: #1D6FE9 !important;
- }
- .u-badge {
- background-color: #1d6fe9 !important;
- margin-top: -14px !important;
- margin-left: -5px !important;
- }
- }
+ // 隐藏滚动条(可选)
+ &::-webkit-scrollbar {
+ height: 0;
+ display: none;
+ }
+ }
+ // 子元素不压缩
+ .tabs-container > * {
+ flex-shrink: 0;
+ }
+ .listBox {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ width: 100%;
+ box-sizing: border-box;
+ }
+ .eventBox {
+ padding: 20rpx 0;
+ overflow-y: auto;
+ overflow-x: hidden;
+ height: 0;
+ flex-grow: 1;
+ align-content: flex-start;
+ width: 100%;
+ box-sizing: border-box;
+ }
- .tabs-container{
- display: flex;
- justify-content: center;
- height: 98rpx;
- }
- .listBox {
- position: relative;
- display: flex;
- flex-direction: column;
- flex: 1;
- width: 100%;
- box-sizing: border-box;
- }
- .eventBox {
- padding: 20rpx 0;
- overflow-y: auto;
- overflow-x: hidden;
- height: 0;
- flex-grow: 1;
- align-content: flex-start;
- width: 100%;
- box-sizing: border-box;
- }
+ .eventList {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20rpx;
+ width: 100%;
+ box-sizing: border-box;
+ justify-content: space-between;
- .eventList {
- display: flex;
- flex-wrap: wrap;
- gap: 20rpx;
- width: 100%;
- box-sizing: border-box;
- justify-content: space-between;
+ .eventItem {
+ width: calc(50% - 10rpx);
+ background-color: #fff;
+ border-radius: 12rpx;
+ overflow: hidden;
+ position: relative;
+ box-sizing: border-box;
+ max-width: 100%;
- .eventItem {
- width: calc(50% - 10rpx);
- background-color: #fff;
- border-radius: 12rpx;
- overflow: hidden;
- position: relative;
- box-sizing: border-box;
- max-width: 100%;
-
- image,
+ image,
.videoBox {
- width: 100%;
- height: 208rpx;
- border-radius: 12rpx;
- overflow: hidden;
+ width: 100%;
+ height: 208rpx;
+ border-radius: 12rpx;
+ overflow: hidden;
display: block;
- }
+ }
.videoBox {
background: linear-gradient(135deg, #eef4ff 0%, #dfe8f8 100%);
display: flex;
@@ -422,61 +476,60 @@
border-left: 22rpx solid #fff;
}
}
- .informationDisplay{
- width: 100%;
- position: absolute;
- bottom: 3px;
- background: rgba(11,11,11,0.35);
- border-radius: 0rpx 0rpx 12rpx 12rpx;
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 10rpx 14rpx;
+ .informationDisplay {
+ width: 100%;
+ position: absolute;
+ bottom: 3px;
+ background: rgba(11, 11, 11, 0.35);
+ border-radius: 0rpx 0rpx 12rpx 12rpx;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 10rpx 14rpx;
box-sizing: border-box;
- .itemTitle {
- flex: 1;
+ .itemTitle {
+ flex: 1;
min-width: 0;
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: 500;
- font-size: 24rpx;
- color: #FFFFFF;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- .itemContent {
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: 400;
- font-size: 24rpx;
- color: #FFFFFF;
- margin-left: 12rpx;
+ font-family: Source Han Sans CN, Source Han Sans CN;
+ font-weight: 500;
+ font-size: 24rpx;
+ color: #ffffff;
white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
- }
- }
- }
- }
+ .itemContent {
+ font-family: Source Han Sans CN, Source Han Sans CN;
+ font-weight: 400;
+ font-size: 24rpx;
+ color: #ffffff;
+ margin-left: 12rpx;
+ white-space: nowrap;
+ }
+ }
+ }
+ }
- .loadingMore {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 80rpx;
- font-size: 28rpx;
- color: #999;
- width: 100%;
- }
+ .loadingMore {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 80rpx;
+ font-size: 28rpx;
+ color: #999;
+ width: 100%;
+ }
- .noData {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 300rpx;
- font-size: 28rpx;
- color: #999;
- width: 100%;
- }
+ .noData {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 300rpx;
+ font-size: 28rpx;
+ color: #999;
+ width: 100%;
+ }
.ai-image-canvas {
position: fixed;
--
Gitblit v1.9.3