From 4b3c357f2fa24a27eac3fe59cbf64e34255ab212 Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Tue, 30 Jun 2026 11:56:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
uniapps/work-app/src/pages/work/index.vue | 193 ++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 179 insertions(+), 14 deletions(-)
diff --git a/uniapps/work-app/src/pages/work/index.vue b/uniapps/work-app/src/pages/work/index.vue
index d0a0221..31499da 100644
--- a/uniapps/work-app/src/pages/work/index.vue
+++ b/uniapps/work-app/src/pages/work/index.vue
@@ -12,10 +12,18 @@
<scroll-view class="eventBox" scroll-y :lower-threshold="80" >
<div class="eventList">
<div class="eventItem" v-for="(item,index) in dataList" :key="index">
- <img :src="item.eventImageUrl" alt="" @click="detailHandle(item)" />
+ <image
+ v-if="[1, 2].includes(item.attachmentType)"
+ :src="item?.aiImg || item?.eventImageUrl"
+ mode="aspectFill"
+ @click="detailHandle(item)"
+ />
+ <div v-if="item.attachmentType === 3" class="videoBox" @click="detailHandle(item)">
+ <div class="playIcon"></div>
+ </div>
<div class="informationDisplay">
- <!-- <div class="itemTitle">{{item.event_name}}</div>-->
- <div class="itemContent">{{formatDate(item.createTime) }}</div>
+ <div class="itemTitle">{{ item.eventName }}</div>
+ <div class="itemContent">{{ formatDate(item.createTime) }}</div>
</div>
</div>
</div>
@@ -32,6 +40,12 @@
</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>
@@ -39,10 +53,13 @@
<script setup>
+import { getCurrentInstance, nextTick } from 'vue'
import { useUserStore } from '@/store/index.js'
-import {getGdList,getstatusCount} from '/src/api/work/index.js'
+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([])
@@ -82,6 +99,106 @@
keyword:''
})
+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
+})
+
+const parseAiFrame = aiFrameSource => {
+ if (!aiFrameSource) return []
+ if (Array.isArray(aiFrameSource)) return aiFrameSource
+
+ try {
+ return JSON.parse(aiFrameSource)
+ } catch (error) {
+ console.log(error)
+ return []
+ }
+}
+
+const getImageInfo = src =>
+ new Promise(resolve => {
+ uni.getImageInfo({
+ src,
+ success: resolve,
+ 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)
+ })
+
+const drawAiImage = async (url, aiFrameSource) => {
+ if (!url) return url
+
+ const aiFrame = parseAiFrame(aiFrameSource)
+ if (!aiFrame.length) return url
+
+ const imageInfo = await getImageInfo(url)
+ if (!imageInfo?.path || !imageInfo.width || !imageInfo.height) return url
+
+ const width = Math.round(imageInfo.width)
+ const height = Math.round(imageInfo.height)
+ canvasSize.value = { width, height }
+ await nextTick()
+
+ const ctx = uni.createCanvasContext('ai-image-canvas', canvasOwner)
+ ctx.drawImage(imageInfo.path, 0, 0, width, height)
+
+ aiFrame.forEach(item => {
+ const { x_cen, y_cen, width: boxWidth, height: boxHeight } = item.bbox || {}
+ if ([x_cen, y_cen, boxWidth, boxHeight].some(value => typeof value !== 'number')) return
+
+ const x = x_cen - boxWidth / 2
+ const y = y_cen - boxHeight / 2
+ const label = item.class_name || ''
+ const fontSize = Math.max(18, Math.round(width / 80))
+ const labelHeight = fontSize + 10
+ const labelY = y - labelHeight >= 0 ? y - labelHeight : y
+ const lineWidth = Math.max(3, Math.round(width / 640))
+
+ ctx.setStrokeStyle('#FF3B30')
+ ctx.setLineWidth(lineWidth)
+ ctx.strokeRect(x, y, boxWidth, boxHeight)
+
+ if (label) {
+ ctx.setFontSize(fontSize)
+ const labelWidth = label.length * fontSize + 16
+ ctx.setFillStyle('#FF3B30')
+ ctx.fillRect(x, labelY, labelWidth, labelHeight)
+ ctx.setFillStyle('#FFFFFF')
+ ctx.setTextBaseline('middle')
+ ctx.fillText(label, x + 8, labelY + labelHeight / 2)
+ }
+ })
+
+ return new Promise(resolve => {
+ ctx.draw(false, async () => {
+ const tempFilePath = await canvasToTempFilePath(width, height)
+ resolve(tempFilePath || url)
+ })
+ })
+}
+
const getDataList = () => {
if (loading.value || !hasMore.value) return
@@ -92,9 +209,19 @@
keyword:listParams.value.keyword,
onlyMine:currentTab.value=== 'myTickets' ? 1 : 0
}
- getGdList(params).then(res => {
+ getGdList(params).then(async res => {
const response = res.data.data
- dataList.value = response
+ 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
@@ -150,7 +277,7 @@
const detailHandle = (val) => {
uni.navigateTo({
- url: `/subPackages/workDetail/index?id=${val.id}`,
+ url: `/subPackages/workDetail/index?id=${val.id}` + (val.aiImg ? `&aiImg=${val.aiImg}` : ''),
})
}
@@ -261,12 +388,40 @@
box-sizing: border-box;
max-width: 100%;
- img {
+ image,
+ .videoBox {
width: 100%;
height: 208rpx;
border-radius: 12rpx;
overflow: hidden;
+ display: block;
}
+ .videoBox {
+ background: linear-gradient(135deg, #eef4ff 0%, #dfe8f8 100%);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ .playIcon {
+ width: 72rpx;
+ height: 72rpx;
+ border-radius: 50%;
+ background: rgba(29, 111, 233, 0.9);
+ position: relative;
+ box-shadow: 0 8rpx 18rpx rgba(29, 111, 233, 0.24);
+
+ &::after {
+ content: '';
+ position: absolute;
+ left: 29rpx;
+ top: 20rpx;
+ width: 0;
+ height: 0;
+ border-top: 16rpx solid transparent;
+ border-bottom: 16rpx solid transparent;
+ border-left: 22rpx solid #fff;
+ }
+ }
.informationDisplay{
width: 100%;
position: absolute;
@@ -275,14 +430,16 @@
border-radius: 0rpx 0rpx 12rpx 12rpx;
display: flex;
align-items: center;
- justify-content: flex-end;
- padding: 10rpx 0rpx 10rpx 0rpx;
+ justify-content: space-between;
+ padding: 10rpx 14rpx;
+ box-sizing: border-box;
.itemTitle {
- width: 144rpx;
+ flex: 1;
+ min-width: 0;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
- font-size: 28rpx;
- color: #000000;
+ font-size: 24rpx;
+ color: #FFFFFF;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -293,7 +450,8 @@
font-weight: 400;
font-size: 24rpx;
color: #FFFFFF;
- padding-right: 14rpx;
+ margin-left: 12rpx;
+ white-space: nowrap;
}
}
@@ -319,5 +477,12 @@
color: #999;
width: 100%;
}
+
+ .ai-image-canvas {
+ position: fixed;
+ left: -9999px;
+ top: -9999px;
+ pointer-events: none;
+ }
}
</style>
--
Gitblit v1.9.3