优化了代码

This commit is contained in:
Teng 2026-03-13 16:15:05 +08:00
parent 657ca24410
commit 2462b1b124
8 changed files with 261 additions and 170 deletions

View File

@ -21,130 +21,205 @@
)) -->
<template>
<view>
<image :src="isError ? defaultImage : links[currentIndex]" :style="{ width: width, height: height }"
:mode="objectFit" @error="isError = true" @load="isError = false" />
<button v-if="showButton" @click="$emit('update:playing', !playing)">
<image :src="displaySrc" :style="{ width: width, height: height }" :mode="objectFit" @error="handleError"
@load="handleLoad" />
<button v-if="showButton" @click="togglePlaying">
{{ playing ? '停止播放' : '开始播放' }}
</button>
</view>
</template>
<script setup>
import {
ref,
watch,
onUnmounted
} from 'vue'
<script setup lang="ts">
import { ref, computed, watch, onUnmounted } from 'vue'
// props
/* ---------------- props ---------------- */
const props = defineProps({
// links
links: {
type: Array,
type: Array as () => string[],
default: () => []
},
//
width: {
type: String,
default: '65rpx'
},
height: {
type: String,
default: '65rpx'
},
//
objectFit: {
type: String,
default: 'aspectFill'
},
//
defaultImage: {
type: String,
default: ''
},
//
interval: {
type: Number,
default: 80
},
// falsemountedtrue
playing: {
type: Boolean,
default: false
},
//
showButton: {
type: Boolean,
default: false
},
//
loop: {
type: Boolean,
default: false
}
width: { type: String, default: '65rpx' },
height: { type: String, default: '65rpx' },
objectFit: { type: String, default: 'aspectFill' },
defaultImage: { type: String, default: '' },
interval: { type: Number, default: 80 }, // ms
playing: { type: Boolean, default: false },
showButton: { type: Boolean, default: false },
loop: { type: Boolean, default: false },
//
maxRetryPerFrame: { type: Number, default: 1 }
})
//
const emit = defineEmits(['update:playing'])
//
const currentIndex = ref(0) //
const isPlaying = ref(false) //
const isError = ref(false) //
let timer = null //
/* ---------------- local state ---------------- */
const currentIndex = ref(0)
const internalPlaying = ref(false) // props.playing
const timer : { id : number | null } = { id: null } // 使便
//
const frameRetries = new Map<number, number>()
//
const failedFrames = new Set<number>()
/* ---------------- helpers / computed ---------------- */
const hasLinks = computed(() => Array.isArray(props.links) && props.links.length > 0)
const displaySrc = computed(() => {
if (!hasLinks.value) {
return props.defaultImage || ''
}
// defaultImage
if (failedFrames.has(currentIndex.value) && props.defaultImage) {
return props.defaultImage
}
// defaultImage
const idx = currentIndex.value
return props.links[idx] || props.defaultImage || ''
})
/* ---------------- play control (使用递归 setTimeout) ---------------- */
function clearTimer() {
if (timer.id !== null) {
clearTimeout(timer.id)
timer.id = null
}
}
function scheduleNextTick() {
// schedule
if (timer.id !== null) return
timer.id = setTimeout(() => {
timer.id = null
tickFrame()
//
if (props.playing) {
// links schedule
if (hasLinks.value) {
scheduleNextTick()
}
}
}, Math.max(16, props.interval)) as unknown as number
}
function startPlay() {
if (!hasLinks.value) return
if (timer.id !== null) return
internalPlaying.value = true
scheduleNextTick()
}
function stopPlay() {
internalPlaying.value = false
clearTimer()
}
function tickFrame() {
//
if (!hasLinks.value) return
const len = props.links.length
if (len === 0) return
//
const startPlay = () => {
if (isPlaying.value) return
isPlaying.value = true
timer = setInterval(() => {
if (props.loop) {
// 使
currentIndex.value = (currentIndex.value + 1) % props.links.length
isError.value = false
//
currentIndex.value = (currentIndex.value + 1) % len
} else {
//
if (currentIndex.value < props.links.length - 1) {
//
if (currentIndex.value < len - 1) {
currentIndex.value++
isError.value = false
} else {
//
stopPlay()
// playing
emit('update:playing', false)
}
}
}
/* ---------------- image event handlers ---------------- */
function handleError() {
//
const idx = currentIndex.value
const prev = frameRetries.get(idx) || 0
const nextCount = prev + 1
frameRetries.set(idx, nextCount)
if (nextCount > (props.maxRetryPerFrame || 0)) {
// defaultImage
failedFrames.add(idx)
// schedule scheduleNextTick
// tickFrame()
if (hasLinks.value) {
// loop loop advance stop
if (props.loop || currentIndex.value < props.links.length - 1) {
// advance scheduletickFrame timer
tickFrame()
} else {
stopPlay()
emit('update:playing', false)
}
}
} else {
//
if (hasLinks.value) {
if (props.loop || currentIndex.value < props.links.length - 1) {
tickFrame()
} else {
stopPlay()
emit('update:playing', false)
}
}
}
}, props.interval)
}
//
const stopPlay = () => {
isPlaying.value = false
clearInterval(timer)
function handleLoad() {
//
const idx = currentIndex.value
frameRetries.delete(idx)
failedFrames.delete(idx)
}
// playing
/* ---------------- watch props ---------------- */
// props.playing props.playing /
watch(() => props.playing, (val) => {
currentIndex.value = 0
if (val) {
// reset index 0
// currentIndex.value = 0
startPlay()
} else {
stopPlay()
setTimeout(() => currentIndex.value = 0, 50)
}
})
// links
watch(() => props.links, () => {
//
setTimeout(() => {
currentIndex.value = 0
isError.value = false
if (isPlaying.value) {
stopPlay()
}, 50)
}
}, {
deep: true
})
//
onUnmounted(() => {
// links deep watch
// retry/failed
watch(() => props.links, (newLinks, oldLinks) => {
//
if (newLinks === oldLinks) return
//
currentIndex.value = 0
frameRetries.clear()
failedFrames.clear()
// props.playing true timer
if (props.playing) {
stopPlay()
// schedule
setTimeout(() => {
if (props.playing) startPlay()
}, 30)
}
}, { immediate: false })
/* ---------------- toggle via internal button ---------------- */
function togglePlaying() {
emit('update:playing', !props.playing)
}
/* ---------------- cleanup ---------------- */
onUnmounted(() => {
clearTimer()
})
</script>

View File

@ -1577,7 +1577,7 @@
.message-view {
display: flex;
font-size: 25rpx;
.message-shu {
width: 3rpx;
height: 1.5vw;

View File

@ -1453,20 +1453,6 @@
margin-left: -5rpx;
display: flex;
align-items: center;
.target-gray {
background-color: #F8F8FA;
border: 1rpx solid #D5D5D5;
display: flex;
height: 100%;
align-items: center;
padding: 0 18rpx;
border-radius: 10rpx;
font-size: 28rpx;
color: #222222;
}
}
.target-contain {
@ -1550,7 +1536,7 @@
top: 310rpx;
left: 0;
width: 100%;
height: 472rpx;
height: 490rpx;
background-color: #fff;
border: 2rpx solid rgba(0, 137, 254, 0.29);
border-radius: 35rpx;
@ -1800,7 +1786,7 @@
right: 20rpx;
top: 50%;
transform: translateY(-50%);
width: 200rpx;
width: 220rpx;
height: 70%;
background-color: #0089FE;
border-radius: 20rpx;
@ -1809,6 +1795,13 @@
align-items: center;
color: #fff;
font-size: 35rpx;
.white-imge {
width: 40rpx;
height: 40rpx;
margin-right: 5rpx;
}
}
}
@ -2128,16 +2121,17 @@
.packtarget-end {
width: 100%;
height: 200rpx;
height: 240rpx;
display: flex;
padding-top: 15rpx;
position: relative;
/* background-color: red; */
.target-edit {
position: absolute;
right: 5rpx;
bottom: -20rpx;
bottom: 0rpx;
width: 130rpx;
height: 60rpx;
display: flex;
@ -2151,8 +2145,8 @@
}
.end-icon {
width: 100rpx;
height: 100rpx;
width: 80rpx;
height: 80rpx;
margin-left: 20rpx;
margin-top: 5rpx;
margin-right: 20rpx;
@ -2165,15 +2159,12 @@
border: 1rpx solid #D5D5D5;
display: flex;
height: 35rpx;
width: 100%;
/* align-items: center; */
/* padding: 0 10rpx; */
padding: 0 10rpx;
border-radius: 10rpx;
font-size: 23rpx;
color: #222222;
font-size: 25rpx;
color: #7a7a7a;
justify-content: center;
align-items: center;
margin-top: 10rpx;
}
.packtarget-title {
@ -2186,7 +2177,7 @@
position: absolute;
top: 2.5rpx;
left: 0;
font-size: 31rpx;
font-size: 32rpx;
/* margin-top: 3rpx; */
}
@ -2199,7 +2190,10 @@
}
.packtarget-serviceContent {
width: 350rpx;
position: absolute;
left: 0;
top: 100rpx;
width: 530rpx;
height: 70rpx;
margin-top: 10rpx;
font-size: 25rpx;
@ -2406,11 +2400,13 @@
width: 100%;
height: 100%;
}
.includestwo-father {
display: flex;
align-items: center;
margin-top: 5rpx;
}
.includestwo {
width: 110rpx;
@ -2423,26 +2419,32 @@
align-items: center;
color: #fff;
}
.includestwo-detail {
font-size: 25rpx;
margin-left: 10rpx;
}
.includestwo-image {
width: 12rpx;
height: 11rpx;
margin-left: 6rpx;
}
.target-gray-spec {
background-color: #F8F8FA;
border: 1rpx solid #D5D5D5;
display: flex;
height: 35rpx;
/* align-items: center; */
padding: 0 10rpx;
border-radius: 10rpx;
font-size: 25rpx;
color: #222222;
justify-content: center;
align-items: center;
/* margin-top: 10rpx; */
}
.gray-view{
display: flex;
align-items: center;
margin-top: 7rpx;
}

View File

@ -82,14 +82,16 @@
class="title-time-font-tags">
({{ item1.directiveName?splitString(item1.directiveName)[1]:""}})
</view>
<view class="includestwo-father" v-if="item1.includesarray && item1.includesarray.length>1">
<view class="includestwo-father"
v-if="item1.includesarray && item1.includesarray.length>1">
<view class="includestwo">
指令集合
</view>
<view class="includestwo-detail">
详情
</view>
<image class="includestwo-image" src="/static/index/rightmore.png" />
<image class="includestwo-image"
src="/static/index/rightmore.png" />
</view>
<view v-if="item1.startTime" class="card-time">
@ -307,7 +309,7 @@
{{ bottomItems[moreindex]?.directiveName }}
</view>
<view class="detail-contain">
{{ bottomItems[moreindex]?.serviceContent }}
{{ bottomItems[moreindex]?.serviceContent || `暂无指令详细信息` }}
</view>
</view>
</view>
@ -349,10 +351,12 @@
<!-- <view class="servers-heng" :style="ruleritem.izPackage==`Y`?{left:`114rpx`}:{}"
v-show="ruleritem.directiveName"></view> -->
<image class="explain-icon" @click.stop="clickexplainopen" style="top: 25rpx;" v-if="ruleritem.includesarray?.length !== 1 "
<image class="explain-icon" @click.stop="clickexplainopen" style="top: 25rpx;"
v-if="ruleritem.includesarray?.length !== 1 "
src="/static/index/procurement/explain.png" mode="aspectFill"></image>
<view class="explain-text" v-show="explainopen" style="top: 78rpx;" :style="ruleritem.includesarray?.length >1?{height:`80rpx`}:{height:`160rpx`}">
<view class="explain-text" v-show="explainopen" style="top: 78rpx;"
:style="ruleritem.includesarray?.length >1?{height:`80rpx`}:{height:`160rpx`}">
<view class="triangle">
<view class="triangle-small"></view>
</view>
@ -473,7 +477,7 @@
{{ savePackagelist[packnumber]?.directives[packdetail]?.directiveName }}
</view>
<view class="detail-contain">
{{ savePackagelist[packnumber]?.directives[packdetail]?.serviceContent }}
{{ savePackagelist[packnumber]?.directives[packdetail]?.serviceContent || `暂无指令详细信息` }}
</view>
</view>
</view>
@ -529,7 +533,7 @@
</view>
</view>
<view class="target-smalltext">
{{ ruleritem.serviceContent }}
{{ ruleritem.serviceContent || `暂无指令详细信息` }}
</view>
<view class="target-edit" style="right: 150rpx;" @click.stop="editcardname(0)"
v-show="editingmode">
@ -561,7 +565,7 @@
<text v-if="!editingmode">
{{ ruleritem?.includesarray[packtargetindex]?.newtypename }}
</text>
<text class="packtarget-blue" v-else @click.stop="edititems(ruleritem,true)">
<text class="packtarget-blue" v-else @click.stop="edititems(ruleritem?.includesarray[packtargetindex],true)">
{{ ruleritem?.includesarray[packtargetindex]?.newtypename }}
</text>
@ -579,7 +583,8 @@
<view class="details" :style="packtargetindex==index?{color:`#0089FE`}:{}"
v-for="(item,index) in ruleritem?.includesarray"
@touchstart="startdeletedetail" @touchend="enddeletedetail"
@click.stop="cleanallopen();packtargetindex=index;killbaddata = true" :key="index">
@click.stop="cleanallopen();packtargetindex=index;killbaddata = true"
:key="index">
<image class="detail-icon" :class="detailshake?`wiggle`:``" :src="
index === packtargetindex
? (item.immediateFileFocus ? serverUrl + item.immediateFileFocus : noimageshowtarget)
@ -610,17 +615,19 @@
: noimageshow
" mode="aspectFill">
</image>
<view class="target-gray">
{{ ruleritem?.includesarray[packtargetindex]?.categoryName }}
</view>
<view class="target-gray">
{{ ruleritem?.includesarray[packtargetindex]?.typeName }}
</view>
</view>
<view class="">
<view class="packtarget-title">
<!-- <view class="target-gray">
<view class="target-black">
{{ splitString(ruleritem?.includesarray[packtargetindex]?.directiveName)[0] + (splitString(ruleritem?.includesarray[packtargetindex]?.directiveName)[1]?`(${splitString(ruleritem?.includesarray[packtargetindex]?.directiveName)[1]})`:"") }}
</view>
<view class="target-black"
v-if="splitString(ruleritem?.includesarray[packtargetindex]?.directiveName)[1] ">
</view>
</view>
<view class="gray-view">
<view class="target-gray">
{{ ruleritem?.includesarray[packtargetindex]?.categoryName }}
</view>
<view class="target-shu">
@ -628,23 +635,18 @@
</view>
<view class="target-gray">
{{ ruleritem?.includesarray[packtargetindex]?.typeName }}
</view> -->
<view class="target-black">
{{ splitString(ruleritem?.includesarray[packtargetindex]?.directiveName)[0] + (splitString(ruleritem?.includesarray[packtargetindex]?.directiveName)[1]?`(${splitString(ruleritem?.includesarray[packtargetindex]?.directiveName)[1]})`:"") }}
</view>
<view class="target-black"
v-if="splitString(ruleritem?.includesarray[packtargetindex]?.directiveName)[1] ">
</view>
</view>
</view>
<view class="packtarget-serviceContent">
{{ ruleritem?.includesarray[packtargetindex]?.serviceContent }}
</view>
</view>
<!-- <view class="target-edit" style="right: 150rpx;" @click.stop="editcardname(1)"
v-show="editingmode">
修改
</view> -->
<view class="packtarget-serviceContent">
{{ ruleritem?.includesarray[packtargetindex]?.serviceContent || `暂无指令详细信息` }}
</view>
<view class="target-edit" @click.stop="editcardname(0)" v-show="editingmode">
添加
</view>
@ -656,9 +658,9 @@
</view>
</view>
<view class="edit-open" v-show="editopen" @click.stop>
<view class="edit-open" :style="whitetou?{top:`160rpx`}:{}" v-show="editopen" @click.stop>
<view class="edit-menu">
<view class="triangle" v-show="!whitetou">
<view class="triangle" :style="whitetou?{right:`390rpx`}:{}">
<view class="triangle-small"></view>
</view>
<view class="edit-tags" :style="edittype===index?{fontWeight:`800`}:{}"
@ -742,7 +744,8 @@
</view>
</view>
<view class="blue-right" @click="cleanallopen();editingmode = !editingmode">
{{ editingmode?"确定":"+编辑" }}
<image class="white-imge" src="/static/index/changemode.png" />
{{ editingmode?"只读模式":"编辑模式" }}
</view>
</view>
@ -1017,7 +1020,13 @@
nosave.value.cycleValue = Number(inputnum.value).toString()
}
isclickright.value = true
let allobject = ruleritem.value
let allobject = {}
if(whitetou.value){
allobject = smallcard.value
}else{
allobject = ruleritem.value
}
const now = new Date();
const ts = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')} ${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
let data = {
@ -1034,10 +1043,10 @@
optCount: nosave.value.optCount,
optTime: ts,
}
console.log("啥情况", data)
// return
// console.log("", data)
editDirective(data).then((res) => {
console.log("啥情况", res)
// console.log("1111", res)
if (res.success) {
geteverything()
setTimeout(() => {
@ -1084,8 +1093,13 @@
optCount: "",
})
const whitetou = ref(false);
const smallcard = ref({});
const edititems = (item : any, whitetoushow : boolean) => {
if(whitetoushow){
smallcard.value = item;
}
whitetou.value = whitetoushow
nosave.value.cycleTypeId = item.cycleTypeId;
nosave.value.cycleValue = item.cycleValue
nosave.value.optCount = item.optCount

View File

@ -484,7 +484,7 @@
margin-top: 2vw;
margin-bottom: 0.8vw;
margin-left: 1.2vw;
background: red;
// background: red;
// padding: 0.2vw;
// padding: 0.5vw;
// margin: 0.7vw auto 0.3vw;

View File

@ -249,7 +249,7 @@
// console.log("???????????????",res.result.records[0].permissionList)
arrlist.value = [{ name: '首页', url: '/static/shouye/sy/h0.png', urls: '/static/shouye/sy/h1.png', type: 'hldy' }];
let tbr = [];
console.log("xxxx",res)
// console.log("xxxx",res)
if (arr) {
arr.forEach((v, i) => {
let obj = arrs.find(item =>

View File

@ -158,7 +158,7 @@
onShow(() => {
setTimeout(() => {
playall.value = true;
}, 2000)
}, 300)
zyupgrade.value?.check_update();
queryPadPageList().then((res => {
@ -370,11 +370,11 @@
}
const ceshijump = () => {
ceshiopen.value = true
// ceshiopen.value = true
// uni.navigateTo({
// url:"/pages/login/ceshi"
// })
console.log("wtf")
// console.log("wtf")
// try {
// const Intent = plus.android.importClass('android.content.Intent')
// const Uri = plus.android.importClass('android.net.Uri')

BIN
static/index/changemode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB