2025-08-06 14:57:59 +08:00

243 lines
7.6 KiB
Plaintext

import { VideoConfigData } from '../mock'
import { RecordHandleType, VideoConfig, VideoItemType } from '../model'
import FileUtils from '../utils/FileUtils'
import HeaderComponent from './compontents/Header'
import VideoConfigComponent from './VideoConfig/Config'
import common from '@ohos.app.ability.common'
import { GlobalConfig } from '../config'
import Prompt from '@system.prompt'
import { endRecordVideo, startRecordVideo, takePhoto } from '../utils/Video'
import { dConsole } from '../utils/LogWorker'
@Entry
@Component
struct VideoConfigPage {
@State videoConfig: VideoConfig = VideoConfigData
@State oldVideoConfig: VideoConfig = VideoConfigData
@State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X
@State openFlag: boolean = true
// 是否自动播放
@State isAutoPlay: boolean = true
@State showControls: boolean = false
// 弹窗
dialogController: CustomDialogController = new CustomDialogController({
builder: VideoConfigComponent({
videoConfig: this.videoConfig,
back: () => {
dConsole.log("返回")
this.videoConfig = this.oldVideoConfig
},
save: (config: VideoConfig) => {
dConsole.log("保存", config)
this.videoConfig = config
this.saveVideoConfig()
},
}),
alignment: DialogAlignment.Bottom,
customStyle: true
})
@State recordHandleObj: RecordHandleType = {
rocord_handle1: 0,
rocord_handle2: 0,
rocord_handle3: 0,
rocord_handle4: 0
}
// 文件操作
private fileUtil!: FileUtils
private context = getContext(this) as common.UIAbilityContext;
// 视频控制器
private controller1: VideoController = new VideoController()
private controller2: VideoController = new VideoController()
private controller3: VideoController = new VideoController()
private controller4: VideoController = new VideoController()
// 视频列表
@State videoList: Array<VideoItemType> = [
{ td: 'td1', controller: this.controller1, src: '' },
{ td: 'td2', controller: this.controller2, src: '' },
{ td: 'td3', controller: this.controller3, src: '' },
{ td: 'td4', controller: this.controller4, src: '' },
]
aboutToAppear(): void {
this.fileUtil = new FileUtils(this.context)
this.readVideoConfig()
}
// 读取视频配置
async readVideoConfig() {
const data = await this.fileUtil.readFile(GlobalConfig.commonFileWriteAddress + '/config/config3.txt');
this.videoConfig = JSON.parse(data)
this.oldVideoConfig = JSON.parse(data);
}
// 保存视频配置
async saveVideoConfig() {
const folderPath = await this.fileUtil.initFolder(`/config`);
dConsole.log(this.oldVideoConfig.videoNum, this.videoConfig.videoNum, "查看")
this.fileUtil.addFile(`${folderPath}/config3.txt`, JSON.stringify(this.videoConfig))
AppStorage.setOrCreate<VideoConfig>("VideoConfig", this.videoConfig)
this.fileUtil.closeFile(`${folderPath}/config3.txt`)
}
async getFileHandleCode(td: number): Promise<Boolean> {
return new Promise(async (resolve, reject) => {
try {
const record_handle = await startRecordVideo(this.videoConfig, td, this.context, 'lp')
Reflect.set(this.recordHandleObj, 'rocord_handle' + td, record_handle)
resolve(true)
} catch (error) {
reject(false)
}
})
}
build() {
Flex({
justifyContent: FlexAlign.SpaceBetween,
direction: FlexDirection.Column
}) {
HeaderComponent({
shortLogo: true,
shouBackArea: true
})
Flex() {
// 左边视频监控区域
Flex({
wrap: FlexWrap.Wrap
}) {
ForEach(this.videoList, (item: VideoItemType) => {
Row() {
Video({
src: this.openFlag ?
`rtsp://${this.videoConfig.userName}:${this.videoConfig.pwd}@${this.videoConfig.ip}:${this.videoConfig.port}/h264/ch${Reflect.get(this.videoConfig,
item.td)}/main/av_stream` : '',
currentProgressRate: this.curRate,
controller: item.controller
})
.muted(true)
.autoPlay(this.isAutoPlay)
.controls(this.showControls)
.width("100%")
.height("100%")
}.width("50%").height("50%").padding(20)
})
}.width("70%").height("100%").padding(40)
// 右边视频配置区域
Column() {
// 设置
ButtonComponent({
type: "0",
click: () => {
this.dialogController.open()
}
})
// 录像
ButtonComponent({
type: "1",
click: async () => {
if (!this.videoConfig.videoRecord4 && !this.videoConfig.videoRecord3 && !this.videoConfig.videoRecord2 && !this.videoConfig.videoRecord1) {
Prompt.showToast({
message: '请选择录像通道',
duration: 3000
})
return
}
for (let i = 1; i <= 4; i++) {
if (Reflect.get(this.videoConfig, 'videoRecord' + i)) {
await this.getFileHandleCode(i)
}
}
// 录像开始
Prompt.showToast({
message: '录像开始!',
duration: 3000
})
}
})
// 停止
ButtonComponent({
type: "2",
click: () => {
for (let i = 1; i <= 4; i++) {
if (Reflect.get(this.recordHandleObj, 'rocord_handle' + i) !== 0) {
endRecordVideo(Reflect.get(this.recordHandleObj, 'rocord_handle' + i))
Reflect.set(this.recordHandleObj, 'rocord_handle' + i, 0)
}
}
Prompt.showToast({
message: '录像已停止!',
duration: 3000
})
}
})
// 抓图
ButtonComponent({
type: "3",
click: async () => {
const arr = ['1', '2', '3', '4']
if (!arr.includes(this.videoConfig?.pztd || "")) {
Prompt.showToast({
message: '请填写正确的拍照通道',
duration: 3000
})
return
}
try {
await takePhoto(this.videoConfig, this.context, 'pz/')
Prompt.showToast({
message: '抓图完成',
duration: 3000
})
} catch (error) {
dConsole.log("抓图失败", error)
}
}
})
}
.width("30%")
.height("100%")
.padding(100)
.justifyContent(FlexAlign.End)
.alignItems(HorizontalAlign.Center)
}
}
.width("100%")
.height("100%")
.backgroundImage($r('app.media.index_bg'))
.backgroundImageSize({
width: "100%",
height: "100%"
})
}
}
@Component
struct ButtonComponent {
@State type: string = "0"
click?: () => void
// 使用映射表来存储类型与图片资源的对应关系
private readonly imageResources: Record<string, Resource> = {
"3": $r('app.media.zhuatu'),
"2": $r('app.media.tingzhi'),
"1": $r('app.media.luxiang'),
"0": $r('app.media.shezhi')
}
build() {
Image(this.imageResources[this.type])
.width(500)
.height(100)
.objectFit(ImageFit.Contain)
.margin({
top: 20
})
.onClick(() => {
this.click && this.click()
})
}
}