完善视频转文字,音频转文字,音频播放器(待完善)

This commit is contained in:
wangyu 2026-03-19 19:01:16 +08:00
parent c6797fd97b
commit 4a30c53eda
52 changed files with 1473 additions and 1725 deletions

View File

@ -55,30 +55,10 @@ export class RouterUrls {
static readonly MD5_RESET_PAGE = "pages/main/home/tools/MD5ResetPage"
/**
* 视频倒放页
*/
static readonly VIDEO_REVERSE_PAGE = "pages/main/home/tools/VideoReversePage"
/**
* 视频裁剪页
*/
static readonly VIDEO_MIRROR_PAGE = "pages/main/home/tools/VideoMirrorPage"
/**
* 视频裁剪页
*/
static readonly CLIP_VIDEO_PAGE = "pages/main/home/tools/ClipVideoPage"
/**
* 去除音乐页
* 视频去原声页
*/
static readonly REMOVE_AUDIO_PAGE = "pages/main/home/tools/RemoveAudioPage"
/**
* 添加音乐页
*/
static readonly ADD_AUDIO_PAGE = "pages/main/home/tools/AddAudioPage"
/**
* 视频转音频页
*/

View File

@ -0,0 +1,271 @@
import { media } from "@kit.MediaKit";
import { fileIo } from "@kit.CoreFileKit";
import { avSessionManager } from "../manager/AVSessionManager";
import { MediaRecordEntity } from "../entity/MediaRecordEntity";
import { MediaManager } from "../manager/MediaManager";
@CustomDialog
export struct AudioPlayerDialog {
controller: CustomDialogController;
@State index: number = 0
@State uri?: string = undefined
@State title?: string = undefined
@State currentTime: number = 0
@State durationTime: number = 0
@State isPlaying: boolean = false
@State mediaList: Array<MediaRecordEntity> = [];
private avPlayer?: media.AVPlayer;
aboutToAppear(): void {
this.initPlayer()
this.initParams()
}
aboutToDisappear(): void {
if (this.avPlayer) {
this.avPlayer.release()
}
}
async initPlayer() {
this.avPlayer = await media.createAVPlayer()
// 创建状态机变化回调函数
this.setAVPlayerCallback()
}
async initParams() {
this.mediaList = await MediaManager.getAudioList()
if (this.mediaList.length > this.index) {
this.uri = this.mediaList[this.index].uri
this.title = this.mediaList[this.index].name
if (this.uri) {
// 打开相应的资源文件地址获取fd
let file = await fileIo.open(this.uri!!)
this.avPlayer!!.url = 'fd://' + file.fd
}
}
}
formatTime(time: number): string {
let minute: number = 0
let second: number = 0
if (time > 60) {
minute = Math.trunc(time / 60)
second = time % 60
if (minute < 10) {
if (second < 10) {
return `0${minute}:0${second}`
} else {
return `0${minute}:${second}`
}
} else {
if (second < 10) {
return `${minute}:0${second}`
} else {
return `${minute}:${second}`
}
}
} else {
second = time
if (second < 10) {
return `00:0${second}`
} else {
return `00:${second}`
}
}
}
// 注册avplayer回调函数
setAVPlayerCallback() {
this.avPlayer!!.on('error', (err) => {
console.error(`播放器发生错误,错误码:${err.code}, 错误信息:${err.message}`);
// 调用reset重置资源触发idle状态
this.isPlaying = false
this.avPlayer!!.reset();
avSessionManager.deactivate()
})
// 状态机变化回调函数
this.avPlayer!!.on('stateChange', async (state, reason) => {
switch (state) {
case 'initialized':
console.info('资源初始化完成');
// 资源初始化完成,开始准备文件
this.avPlayer!!.prepare();
break;
case 'prepared':
console.info('资源准备完成');
// 资源准备完成,开始准备文件
this.durationTime = Math.trunc(this.avPlayer!!.duration / 1000)
this.currentTime = this.avPlayer!!.currentTime;
await avSessionManager.activate()
this.avPlayer!!.play();
break;
case 'completed':
console.info('播放完成');
this.isPlaying = false
this.avPlayer!!.off('bufferingUpdate')
AppStorage.setOrCreate('currentTime', this.durationTime);
avSessionManager.deactivate()
break;
case 'playing':
console.info('播放开始');
this.isPlaying = true
break;
case 'released':
case 'stopped':
case 'error':
case 'paused':
console.info('播放暂停');
this.isPlaying = false
avSessionManager.deactivate()
break;
}
})
// 时间上报监听函数
this.avPlayer!!.on('timeUpdate', (time: number) => {
this.currentTime = Math.trunc(time / 1000);
});
}
build() {
RelativeContainer() {
Image($r('app.media.ic_close_dialog')).width(20).height(20)
.alignRules({
right: {anchor: '__container__', align: HorizontalAlign.End}
})
.margin({top: 12, right: 12})
.onClick(() => {
this.controller.close()
})
.id('iv_close')
Text(this.title).fontColor($r('app.color.color_212226')).fontSize(16)
.alignRules({
top: {anchor: 'iv_close', align: VerticalAlign.Bottom}
})
.margin({left: 16, top: 6})
.id('tv_name')
Row() {
Text(this.formatTime(this.currentTime)).width(35).fontColor($r('app.color.color_212226')).fontSize(12)
Slider({
value: this.currentTime,
min: 0,
max: this.durationTime
})
.blockColor(Color.White)
.trackColor($r('app.color.color_60ffffff'))
.onChange((value: number, mode: SliderChangeMode) => {
this.avPlayer!!.seek(value * 1000, 2); // 设置视频播放的进度跳转到value处
this.currentTime = value;
})
.layoutWeight(1)
Text(this.formatTime(this.durationTime)).width(35).fontColor($r('app.color.color_212226')).fontSize(12)
}
.alignRules({
top: {anchor: 'tv_name', align: VerticalAlign.Bottom}
})
.width('100%')
.padding({left:16, right: 16})
.margin({top: 20})
.id('row_progress')
Row() {
Image(this.index > 0 ? $r('app.media.ic_last_audio_enable') : $r('app.media.ic_last_audio_disable')).width(20).height(20)
.onClick(async () => {
if (this.index > 0) {
await this.avPlayer!!.stop()
this.index--
this.uri = this.mediaList[this.index].uri
this.title = this.mediaList[this.index].name
if (this.uri) {
// 打开相应的资源文件地址获取fd
let file = await fileIo.open(this.uri!!)
this.avPlayer!!.url = 'fd://' + file.fd
}
}
})
.visibility(Visibility.None)
Image(this.isPlaying ? $r('app.media.ic_audio_pause') : $r('app.media.ic_audio_play')).width(30).height(30)
.margin({left: 50, right: 50})
.onClick(async () => {
if (this.isPlaying) {
this.avPlayer!!.pause()
} else {
await avSessionManager.activate()
this.avPlayer!!.play()
}
})
Image(this.index < this.mediaList.length - 1 ? $r('app.media.ic_last_audio_enable') : $r('app.media.ic_last_audio_disable')).width(20).height(20)
.rotate({angle: 180})
.onClick(async () => {
if (this.index < this.mediaList.length - 1) {
await this.avPlayer!!.stop()
this.index++
this.uri = this.mediaList[this.index].uri
this.title = this.mediaList[this.index].name
if (this.uri) {
// 打开相应的资源文件地址获取fd
let file = await fileIo.open(this.uri!!)
this.avPlayer!!.url = 'fd://' + file.fd
}
}
})
.visibility(Visibility.None)
}
.width('100%')
.justifyContent(FlexAlign.Center)
.alignRules({
top: {anchor: 'row_progress', align: VerticalAlign.Bottom}
})
.margin({top: 26})
.id('row_controller')
Row() {
Button({ type: ButtonType.Capsule, stateEffect: true }) {
Row() {
Image($r('app.media.ic_share_audio')).width(20).height(20)
Text('分享').fontColor($r('app.color.color_466afd')).fontSize(15).fontWeight(FontWeight.Medium)
}
}
.height(46)
.layoutWeight(1)
.borderWidth(1)
.borderColor($r('app.color.color_466afd'))
.backgroundColor(Color.Transparent)
.onClick(() => {
})
Blank().width(9)
Button({ type: ButtonType.Capsule, stateEffect: true }) {
Row() {
Image($r('app.media.ic_delete_material')).width(20).height(20)
Text('删除').fontColor(Color.White).fontSize(15).fontWeight(FontWeight.Medium)
}
}
.height(46)
.layoutWeight(1)
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
})
}
.alignRules({
top: {anchor: 'row_controller', align: VerticalAlign.Bottom}
})
.padding({left: 16, top: 9, right: 16, bottom: 30})
.margin({top: 38})
.backgroundColor(Color.White)
}
.width('100%')
.height('auto')
.backgroundColor($r('app.color.window_background'))
}
}

View File

@ -12,10 +12,10 @@ export struct BindPhoneDialog {
success: () => void = () => {}
phone: string = '';
code: string = '';
timestamp: string = '';
intervalId: number = -1;
private phone: string = '';
private code: string = '';
private timestamp: string = '';
private intervalId: number = -1;
@State countDownTime: number = 0;

View File

@ -59,4 +59,7 @@ export class ConfigEntity {
@Expose({ name: 'client.challenge.enable' })
challengeEnable?: boolean = true; //0元挑战
@Expose({ name: 'client.AI.startEnd' })
aiAuthEnable: boolean = true; //ai功能是否需要鉴权
}

View File

@ -1,4 +1,4 @@
export class VipPermissionEntity {
export class VipAuthEntity {
auth: boolean = false
auth_ad: boolean = false
scene: string = ''

View File

@ -1,6 +1,6 @@
import { apiService } from "../net/ApiService"
export class EventReportGlobalManager {
export class EventReportManager {
static async eventReport(key: string, value: string = '', extra: string = '') {
try {
apiService.eventReport(key, value, extra)

View File

@ -78,6 +78,7 @@ class UserConfigManager {
this.saveDomainMap(config.config.domainMap);
this.saveCopyContainsList(config.config.copyContainsList);
this.saveHomeBanner(config.config.homeBanners);
this.saveAiAuthEnable(config.config.aiAuthEnable);
}
}
@ -379,6 +380,18 @@ class UserConfigManager {
}
return new Array();
}
/**
* ai功能是否需要鉴权
* @param enable
*/
saveAiAuthEnable(enable: boolean) {
PrefUtils.put("ai_auth_enable", enable)
}
isAiAuthEnable(): boolean {
return PrefUtils.getBoolean('ai_auth_enable', true)
}
}
export const ConfigManager = new UserConfigManager()

View File

@ -4,7 +4,7 @@ import systemDateTime from '@ohos.systemDateTime';
import { router } from '@kit.ArkUI';
import { AppUtil } from '@pura/harmony-utils';
import { ConfigManager } from '../../manager/UserConfigManager';
import { EventReportGlobalManager } from '../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../manager/EventReportManager';
import { EventConstants } from '../../common/EventConstants';
@Entry
@ -23,7 +23,7 @@ struct GuidePage {
@Local showHomePage: boolean = true
aboutToAppear(): void {
EventReportGlobalManager.eventReport(EventConstants.GUIDE_LAUNCH)
EventReportManager.eventReport(EventConstants.GUIDE_LAUNCH)
}
build() {
@ -59,7 +59,7 @@ struct GuidePage {
.indicator(false)
.onChange((index: number) => {
this.currentIndex = index;
EventReportGlobalManager.eventReport(EventConstants.GUIDE_OPPORTUNITY_SCROLL, `${index + 1}`)
EventReportManager.eventReport(EventConstants.GUIDE_OPPORTUNITY_SCROLL, `${index + 1}`)
})
.onGestureSwipe((index: number, extraInfo: SwiperAnimationEvent) => {
if (index === this.child.length - 1 && extraInfo.currentOffset < -60) {

View File

@ -18,7 +18,7 @@ import { ErrCode, SendAuthResp } from '@tencent/wechat_open_sdk';
import BuildProfile from 'BuildProfile';
import { LoadingDialog } from '../../dialog/LoadingDialog';
import { EventConstants } from '../../common/EventConstants';
import { EventReportGlobalManager } from '../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../manager/EventReportManager';
@Entry
@ComponentV2
@ -71,7 +71,7 @@ struct LoginPage {
@Monitor('viewModel.phoneLoginEntity')
onPhoneLogin(monitor: IMonitor) {
const loginEntity = monitor.value()?.now as LoginEntity;
EventReportGlobalManager.eventReport(EventConstants.LOGIN, 'phone', this.phone)
EventReportManager.eventReport(EventConstants.LOGIN, 'phone', this.phone)
LoginManager.saveToken(loginEntity.token);
LoginManager.saveLastLoginType('phone')
ConfigManager.userConfig()
@ -87,7 +87,7 @@ struct LoginPage {
@Monitor('viewModel.wxLoginEntity')
onWxLogin(monitor: IMonitor) {
const loginEntity = monitor.value()?.now as LoginEntity;
EventReportGlobalManager.eventReport(EventConstants.LOGIN, 'weixin')
EventReportManager.eventReport(EventConstants.LOGIN, 'weixin')
LoginManager.saveToken(loginEntity.token);
LoginManager.saveLastLoginType('weixin')
ConfigManager.userConfig()
@ -127,7 +127,7 @@ struct LoginPage {
return;
}
this.viewModel.sendCode(this.phone);
EventReportGlobalManager.eventReport(EventConstants.GET_CODE, "code_login", this.phone)
EventReportManager.eventReport(EventConstants.GET_CODE, "code_login", this.phone)
}
toMainPage() {
@ -177,7 +177,7 @@ struct LoginPage {
if (systemDateTime.getTime() - this.clickTime < 1500) {
(this.getUIContext().getHostContext() as common.UIAbilityContext).terminateSelf();
} else {
EventReportGlobalManager.eventReport(EventConstants.EXIT_APP, 'login')
EventReportManager.eventReport(EventConstants.EXIT_APP, 'login')
this.clickTime = systemDateTime.getTime();
ToastUtils.show('双击退出应用');
}

View File

@ -11,7 +11,7 @@ import { SimpleTipDialog } from '../../dialog/SimpleTipDialog';
import { RouterUrls } from '../../common/RouterUrls';
import { TipDialog } from '../../dialog/TipDialog';
import { ConfigManager } from '../../manager/UserConfigManager';
import { EventReportGlobalManager } from '../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../manager/EventReportManager';
import { PasteboardUtils } from '../../utils/PasteboardUtils';
import { MaterialPage } from './material/MaterialPage';
import { ToolsPage } from './mine/tool/ToolsPage';
@ -133,7 +133,7 @@ struct MainPage {
AppUtil.getContext().eventHub.emit(EventConstants.MineRefreshEvent);
}
this.showLoginTip();
EventReportGlobalManager.eventReport(EventConstants.HOME_BOTTOM_TAB_CHECK, this.titles[index], '')
EventReportManager.eventReport(EventConstants.HOME_BOTTOM_TAB_CHECK, this.titles[index], '')
})
.padding({ bottom: 20 })
.backgroundColor(Color.White)
@ -172,7 +172,7 @@ struct MainPage {
if (systemDateTime.getTime() - this.clickTime < 1500) {
AppUtil.getContext().terminateSelf();
} else {
EventReportGlobalManager.eventReport(EventConstants.EXIT_APP, 'main')
EventReportManager.eventReport(EventConstants.EXIT_APP, 'main')
this.clickTime = systemDateTime.getTime();
ToastUtils.show('双击退出应用');
}

View File

@ -9,7 +9,7 @@ import { ConfigManager } from '../../../manager/UserConfigManager';
import { LoginManager } from '../../../manager/LoginGlobalManager';
import { RouterUrls } from '../../../common/RouterUrls';
import { TipDialog } from '../../../dialog/TipDialog';
import { EventReportGlobalManager } from '../../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../../manager/EventReportManager';
import { Constants } from '../../../common/Constants';
import { MaterialEntity } from '../../../entity/MaterialEntity';
import { DownSamplingStrategy, ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknifepro';
@ -139,7 +139,7 @@ export struct HomePage {
case 'vip': {
if (LoginManager.getUserInfo()?.vip !== 3) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'banner'}})
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'banner')
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'banner')
}
break;
}
@ -253,7 +253,7 @@ export struct HomePage {
.onClick(() => {
// let info = AppUtil.getSignatureInfoSync()
this.getUIContext().getRouter().pushUrl({url: RouterUrls.TAKE_MATERIAL_PAGE})
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_LINK_EXTRACT)
EventReportManager.eventReport(EventConstants.JUMP_TO_LINK_EXTRACT)
})
Column() {
@ -281,7 +281,7 @@ export struct HomePage {
.id('layout_wx_video')
.onClick(() => {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.WX_VIDEO_PAGE, params: { isPlayback: false }})
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_WECHAT_VIDEO)
EventReportManager.eventReport(EventConstants.JUMP_TO_WECHAT_VIDEO)
})
Column() {
@ -310,7 +310,7 @@ export struct HomePage {
TipDialog.show(this.getUIContext(), {title: '提示', content: '仅限微信直播回放视频提取,是否前往?', callback: {
confirm: () => {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.WX_VIDEO_PAGE, params: { isPlayback: true }})
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_WECHAT_PLAYBACK)
EventReportManager.eventReport(EventConstants.JUMP_TO_WECHAT_PLAYBACK)
}
}})
})

View File

@ -10,7 +10,7 @@ import {
TextMaterial,
VideoMaterial
} from '../../../../entity/MaterialInfoEntity';
import { VipPermissionEntity } from '../../../../entity/VipPermissionEntity';
import { VipAuthEntity } from '../../../../entity/VipAuthEntity';
import { LoginManager } from '../../../../manager/LoginGlobalManager';
import { ToastUtils } from '../../../../utils/ToastUtils';
import { TakeMaterialViewModel } from '../../../../viewModel/TakeMaterialViewModel';
@ -26,7 +26,7 @@ import { SaveUtils } from '../../../../utils/SaveUtils';
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog';
import { EventConstants } from '../../../../common/EventConstants';
import { SimpleTipDialog } from '../../../../dialog/SimpleTipDialog';
import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../../../manager/EventReportManager';
import { PasteboardUtils } from '../../../../utils/PasteboardUtils';
import { TipDialog } from '../../../../dialog/TipDialog';
import { PrefUtils } from '../../../../utils/PrefUtils';
@ -97,9 +97,9 @@ struct TakeMaterialPage {
}
}
@Monitor('viewModel.permissionInfo')
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipPermissionEntity;
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single)
@ -109,7 +109,7 @@ struct TakeMaterialPage {
} else {
if (!info.auth_ad) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'download_material'}})
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_material')
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_material')
return;
}
}
@ -120,7 +120,7 @@ struct TakeMaterialPage {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_material')
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_material')
ToastUtils.show('M币已用完')
}
}
@ -344,7 +344,7 @@ struct TakeMaterialPage {
DownloadDialog.show(this.getUIContext(), { status: status, totalSize: 0, progress: 0, totalCount: this.selectedList.length, index: this.downloadIndex, callback: {
confirm: () => {
if (this.downloadStatus === DownloadStatus.COMPLETED) {
EventReportGlobalManager.eventReport(EventConstants.DIALOG_GO_TO_VIEW, this.titles[this.currentIndex])
EventReportManager.eventReport(EventConstants.DIALOG_GO_TO_VIEW, this.titles[this.currentIndex])
AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, this.currentIndex)
this.getUIContext().getRouter().back()
} else {
@ -355,10 +355,10 @@ struct TakeMaterialPage {
if (this.downloadStatus !== DownloadStatus.COMPLETED) {
if (this.mediaDownloader) {
this.mediaDownloader.cancel()
EventReportGlobalManager.eventReport(EventConstants.CANCEL_DOWNLOAD_VIDEO, this.selectedList[this.downloadIndex].url)
EventReportManager.eventReport(EventConstants.CANCEL_DOWNLOAD_VIDEO, this.selectedList[this.downloadIndex].url)
}
} else {
EventReportGlobalManager.eventReport(EventConstants.DIALOG_CONFIRM_SAVE_FILE, this.titles[this.currentIndex])
EventReportManager.eventReport(EventConstants.DIALOG_CONFIRM_SAVE_FILE, this.titles[this.currentIndex])
}
}
} })
@ -449,11 +449,11 @@ struct TakeMaterialPage {
reportErrorEvent(media: MediaEntity, message: string) {
if (media instanceof VideoMaterial) {
EventReportGlobalManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_VIDEO, media.url, message)
EventReportManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_VIDEO, media.url, message)
} else if (media instanceof ImageMaterial) {
EventReportGlobalManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_IMG, media.url, message)
EventReportManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_IMG, media.url, message)
} else if (media instanceof AudioMaterial) {
EventReportGlobalManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_AUDIO, media.url, message)
EventReportManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_AUDIO, media.url, message)
}
}
@ -501,7 +501,7 @@ struct TakeMaterialPage {
.onClick(() => {
if (StrUtil.isNotEmpty(this.inputText)) {
this.parseUrl(this.inputText)
EventReportGlobalManager.eventReport(EventConstants.GET_MATERIAL, "material-button", this.inputText)
EventReportManager.eventReport(EventConstants.GET_MATERIAL, "material-button", this.inputText)
} else {
ToastUtils.show('请输入链接地址')
}

View File

@ -8,10 +8,10 @@ import { BusinessError, request, systemDateTime } from '@kit.BasicServicesKit';
import { ToastUtils } from '../../../../utils/ToastUtils';
import { SaveUtils } from '../../../../utils/SaveUtils';
import { AuthViewModel } from '../../../../viewModel/AuthViewModel';
import { VipPermissionEntity } from '../../../../entity/VipPermissionEntity';
import { VipAuthEntity } from '../../../../entity/VipAuthEntity';
import { LoginManager } from '../../../../manager/LoginGlobalManager';
import { RouterUrls } from '../../../../common/RouterUrls';
import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../../../manager/EventReportManager';
import { EventConstants } from '../../../../common/EventConstants';
import { LoadingDialog } from '../../../../dialog/LoadingDialog';
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog';
@ -27,9 +27,9 @@ struct MaterialDetailPage {
private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext())
private imageSize: media.PixelMapParams = {}
@Monitor('viewModel.permissionInfo')
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipPermissionEntity;
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single)
@ -39,7 +39,7 @@ struct MaterialDetailPage {
} else {
if (!info.auth_ad) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'download_material'}})
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_material')
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_material')
return;
}
}
@ -50,7 +50,7 @@ struct MaterialDetailPage {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_material')
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_material')
ToastUtils.show('M币已用完')
}
}

View File

@ -1,331 +0,0 @@
import { PhotoHelper, PickerUtil } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar'
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, FileUtil } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo, picker } from '@kit.CoreFileKit'
import { SaveUtils } from '../../../../utils/SaveUtils'
import { MP4Parser } from '@ohos/mp4parser'
import { LoadingDialog } from '../../../../dialog/LoadingDialog'
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
import { EventConstants } from '../../../../common/EventConstants'
import { TipDialog } from '../../../../dialog/TipDialog'
import { avSessionManager } from '../../../../manager/AVSessionManager'
@Entry
@ComponentV2
struct AddAudioPage {
private controller: VideoController = new VideoController()
@Local videoUri?: string
@Local audioUri?: string
@Local currentTime: number = 0
@Local durationTime: number = 0
@Local isPlaying: boolean = false
@Local isSuccess: boolean = false
mirrorVideo() {
LoadingDialog.show(this.getUIContext())
this.isSuccess = false
let cacheVideoPath = FileUtil.getCacheDirPath() + FileUtil.separator + `cache_${systemDateTime.getTime()}.mp4`
if (FileUtil.accessSync(cacheVideoPath)) {
FileUtil.unlinkSync(cacheVideoPath)
}
let videoFile = FileUtil.openSync(this.videoUri!!, fileIo.OpenMode.READ_ONLY)
// 复制视频文件到缓存目录下
FileUtil.copyFileSync(videoFile.fd, cacheVideoPath)
FileUtil.closeSync(videoFile)
let cacheAudioPath = FileUtil.getCacheDirPath() + FileUtil.separator + `cache_${systemDateTime.getTime()}.mp3`
if (FileUtil.accessSync(cacheAudioPath)) {
FileUtil.unlinkSync(cacheAudioPath)
}
let audioFile = FileUtil.openSync(this.audioUri!!, fileIo.OpenMode.READ_ONLY)
// 复制音频文件到缓存目录下
FileUtil.copyFileSync(audioFile.fd, cacheAudioPath)
FileUtil.closeSync(audioFile)
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
let cmd = `ffmpeg -i ${cacheVideoPath} -stream_loop -1 -i ${cacheAudioPath} -c:v copy -c:a aac -shortest -map 0:v -map 1:a ${outputPath}`
MP4Parser.ffmpegCmd(cmd, {
callBackResult: (code: number) => {
if (code === 0) {
this.videoUri = FileUtil.getUriFromPath(outputPath)
this.isSuccess = true
this.isPlaying = false
ToastUtils.show('处理成功')
} else {
ToastUtils.show('处理失败')
}
LoadingDialog.dismiss()
}
})
}
selectVideo() {
PhotoHelper.selectEasy({
MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE,
maxSelectNumber: 1,
isPhotoTakingSupported: false,
isEditSupported: false,
isOriginalSupported: false
})
.then((uris) => {
if (uris.length != 0) {
this.isSuccess = false
this.videoUri = uris[0]
}
})
}
selectAudio() {
/*PickerUtil.selectAudio({maxSelectNumber: 1})
.then((uris) => {
if (uris.length != 0) {
this.audioUri = uris[0]
}
})*/
PickerUtil.selectDocument({maxSelectNumber: 1, fileSuffixFilters: ['.mp3']})
.then((uris) => {
if (uris.length != 0) {
this.audioUri = uris[0]
}
})
}
showDownloadDialog() {
DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: {
confirm: () => {
AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0)
this.getUIContext().getRouter().back()
}
} })
}
formatTime(time: number): string {
let minute: number = 0
let second: number = 0
if (time > 60) {
minute = Math.trunc(time / 60)
second = time % 60
if (minute < 10) {
if (second < 10) {
return `0${minute}:0${second}`
} else {
return `0${minute}:${second}`
}
} else {
if (second < 10) {
return `${minute}:0${second}`
} else {
return `${minute}:${second}`
}
}
} else {
second = time
if (second < 10) {
return `00:0${second}`
} else {
return `00:${second}`
}
}
}
onBackPress(): boolean | void {
if (this.isSuccess) {
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'视频尚未保存,是否确定退出?', callback: {
confirm: () => {
this.getUIContext().getRouter().back()
}
}})
return true
}
return false
}
build() {
Column() {
TitleBar({ title: '加音乐' })
Column() {
Row() {
Text('上传视频').fontColor($r('app.color.color_90ffffff')).fontSize(16).fontWeight(FontWeight.Medium)
Text('仅支持mp4格式').fontColor($r('app.color.color_50ffffff')).fontSize(12)
}.alignSelf(ItemAlign.Start)
RelativeContainer() {
Stack() {
Image($r('app.media.ic_add_video')).width(44).height(44)
}
.width(140)
.height(140)
.borderRadius(10)
.backgroundColor($r('app.color.color_333333'))
.alignRules({
start: { anchor: '__container__', align: HorizontalAlign.Start },
top: { anchor: '__container__', align: VerticalAlign.Top },
end: { anchor: '__container__', align: HorizontalAlign.End },
bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
})
.onClick(() => {
this.selectVideo()
})
}
.height(220)
.margin({ top: 12 })
.borderRadius(8)
.backgroundColor($r('app.color.color_222222'))
}.margin({ left: 16, top: 16, right: 16 })
.visibility(this.videoUri ? Visibility.None : Visibility.Visible)
Column() {
RelativeContainer() {
Video({
src: this.videoUri, // 设置视频源
controller: this.controller, //设置视频控制器,可以控制视频的播放状态
posterOptions: { showFirstFrame: true }
})
.width('100%')
.height('100%')
.backgroundColor($r('app.color.window_background'))
.controls(false) // 设置是否显示默认控制条
.autoPlay(false) // 设置是否自动播放
.loop(false) // 设置是否循环播放
.objectFit(ImageFit.Contain) // 设置视频填充模式
.onPrepared((event) => {
if (event) {
this.durationTime = event.duration
}
})
.onUpdate((event) => {
if (event) {
this.currentTime = event.time
}
})
.onStart(() => {
this.isPlaying = true
})
.onPause(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onStop(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onFinish(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onError(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onDisAppear(() => {
avSessionManager.deactivate()
})
Image($r('app.media.ic_play_video'))
.width(50)
.height(50)
.visibility(this.isPlaying ? Visibility.None : Visibility.Visible)
.onClick(async () => {
await avSessionManager.activate()
this.controller.start()
})
.alignRules({
left: { anchor: '__container__', align: HorizontalAlign.Start },
top: { anchor: '__container__', align: VerticalAlign.Top },
right: { anchor: '__container__', align: HorizontalAlign.End },
bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
})
Row() {
Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play'))
.width(20)
.height(20)
.margin({ right: 20 })
.onClick(async () => {
if (this.isPlaying) {
this.controller.pause()
} else {
await avSessionManager.activate()
this.controller.start()
}
})
Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12)
Slider({
value: this.currentTime,
min: 0,
max: this.durationTime
})
.blockColor(Color.White)
.trackColor($r('app.color.color_60ffffff'))
.onChange((value: number, mode: SliderChangeMode) => {
this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处
})
.layoutWeight(1)
Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12)
}
.opacity(0.8)
.width("100%")
.padding({ left: 30, right: 30 })
.alignRules({
bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
})
}
.layoutWeight(1)
Image($r('app.media.ic_add_audio')).width(50).height(50).margin({top: 20})
.onClick(() => {
this.selectAudio()
})
Text('音频').fontColor($r('app.color.color_90ffffff')).fontSize(14).margin({top: 10})
Row() {
Text(this.isSuccess ? '重新上传' : '取消').fontColor($r('app.color.color_90ffffff')).fontSize(17).margin({ left: 16 })
.onClick(() => {
this.controller.stop()
if (this.isSuccess) {
this.selectVideo()
} else {
this.getUIContext().getRouter().back()
}
})
Blank().layoutWeight(1)
Text(this.isSuccess ? '保存' : '确定').fontColor($r("app.color.color_466afd")).fontSize(17).margin({ right: 16 })
.onClick(() => {
this.controller.stop()
if (this.isSuccess) {
SaveUtils.saveImageVideoToAlbumDialog([this.videoUri!!])
.then((saved) => {
if (saved) {
this.videoUri = undefined
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
} else {
if (this.audioUri) {
this.mirrorVideo()
} else {
ToastUtils.show('请上传音频')
}
}
})
}
.margin({ top: 50, bottom: 30 })
}
.layoutWeight(1)
.visibility(this.videoUri ? Visibility.Visible : Visibility.None)
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.window_background'))
}
}

View File

@ -18,10 +18,21 @@ import { WaterMarkerView } from '../../../../view/WaterMarkerView'
import { EditTextDialog } from '../../../../dialog/EditTextDialog'
import { image } from '@kit.ImageKit'
import { avSessionManager } from '../../../../manager/AVSessionManager'
import { AuthViewModel } from '../../../../viewModel/AuthViewModel'
import { LoginManager } from '../../../../manager/LoginGlobalManager'
import { VipAuthEntity } from '../../../../entity/VipAuthEntity'
import { RouterUrls } from '../../../../common/RouterUrls'
import { router } from '@kit.ArkUI'
import { EventReportManager } from '../../../../manager/EventReportManager'
@Entry
@ComponentV2
struct AddWatermarkPage {
private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext())
private controller: VideoController = new VideoController()
private videoSize: media.PixelMapParams = { width: 0, height: 0 }
private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 }
@Local uri?: string
@Local currentTime: number = 0
@Local durationTime: number = 0
@ -33,9 +44,49 @@ struct AddWatermarkPage {
@Local textContent: string = ''
@Local imagePath: string = ''
private controller: VideoController = new VideoController()
private videoSize: media.PixelMapParams = { width: 0, height: 0 }
private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 }
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single)
return;
}
this.doSave()
} else {
if (!info.auth_ad) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'addWatermark'}})
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'addWatermark')
return;
}
}
}
@Monitor('viewModel.errorCode')
onErrorCodeChange(monitor: IMonitor) {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'addWatermark')
ToastUtils.show('M币已用完')
}
}
doSave() {
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.isSuccess = false
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
}
addWatermark() {
LoadingDialog.show(this.getUIContext())
@ -430,18 +481,7 @@ struct AddWatermarkPage {
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
this.controller.stop()
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
this.viewModel.checkVip()
})
}
.visibility(this.isSuccess ? Visibility.Visible : Visibility.None)

View File

@ -1,6 +1,427 @@
@ComponentV2
import { PickerUtil } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, FileUtil, JSONUtil, PasteboardUtil } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo } from '@kit.CoreFileKit'
import { LoadingDialog } from '../../../../dialog/LoadingDialog'
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
import { EventConstants } from '../../../../common/EventConstants'
import { TipDialog } from '../../../../dialog/TipDialog'
import { avSessionManager } from '../../../../manager/AVSessionManager'
import { MP4Parser } from '@ohos/mp4parser'
import { QCloud } from 'qcloudfileflash'
import { Constants } from '../../../../common/Constants'
import { VoiceRecognizeResultEntity } from '../../../../entity/VoiceRecognizeResultEntity'
import { AuthViewModel } from '../../../../viewModel/AuthViewModel'
import { VipAuthEntity } from '../../../../entity/VipAuthEntity'
import { LoginManager } from '../../../../manager/LoginGlobalManager'
import { RouterUrls } from '../../../../common/RouterUrls'
import { router } from '@kit.ArkUI'
import { EventReportManager } from '../../../../manager/EventReportManager'
import { ConfigManager } from '../../../../manager/UserConfigManager'
import { media } from '@kit.MediaKit'
@Entry
@ComponentV2
struct AudioToTextPage {
private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext())
private controller: VideoController = new VideoController()
private avPlayer?: media.AVPlayer = undefined
@Local resultText?: string
@Local audioUri?: string
@Local currentTime: number = 0
@Local durationTime: number = 0
@Local isPlaying: boolean = false
@Local isSuccess: boolean = false
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single)
return;
}
this.doSave()
} else {
if (!info.auth_ad) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'videoToText'}})
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'videoToText')
return;
}
}
}
@Monitor('viewModel.errorCode')
onErrorCodeChange(monitor: IMonitor) {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'videoToText')
ToastUtils.show('M币已用完')
}
}
aboutToAppear(): void {
this.initPlayer()
}
onPageHide(): void {
if (this.avPlayer) {
this.avPlayer.pause()
}
}
aboutToDisappear(): void {
if (this.avPlayer) {
this.avPlayer.release()
}
}
async initPlayer() {
this.avPlayer = await media.createAVPlayer();
// 创建状态机变化回调函数
this.setAVPlayerCallback();
}
doSave() {
if (this.resultText) {
PasteboardUtil.setDataTextSync(this.resultText)
this.isSuccess = false
ToastUtils.show('复制成功')
}
}
copyAudio() {
LoadingDialog.show(this.getUIContext())
this.isSuccess = false
let cachePath = FileUtil.getCacheDirPath() + FileUtil.separator + `cache_${systemDateTime.getTime()}.mp3`
if (FileUtil.accessSync(cachePath)) {
FileUtil.unlinkSync(cachePath)
}
let file = FileUtil.openSync(this.audioUri!!, fileIo.OpenMode.READ_ONLY)
// 复制文件到缓存目录下
FileUtil.copyFileSync(file.fd, cachePath)
FileUtil.closeSync(file)
this.recognizeAudio(cachePath)
.then((result) => {
if (result !== null) {
this.resultText = result.flash_result[0].text
this.isSuccess = true
this.isPlaying = false
ToastUtils.show('处理成功')
} else {
ToastUtils.show('处理失败')
}
LoadingDialog.dismiss()
})
.catch((e: BusinessError) => {
console.log(e.message)
ToastUtils.show('处理失败')
LoadingDialog.dismiss()
})
}
async recognizeAudio(uri: string): Promise<VoiceRecognizeResultEntity|null> {
let builder = new QCloud.FileFlash.Builder()
builder.appID = Constants.QCLOUD_APP_ID
builder.secretID = Constants.QCLOUD_SECRET_ID
builder.secretKey = Constants.QCLOUD_SECRET_KEY
// builder.token = this._token
builder.setApiParam(QCloud.FileFlash.kEngineType, '16k_zh')
builder.setApiParam(QCloud.FileFlash.kVoiceFormat, 'mp3')
builder.setApiParam(QCloud.FileFlash.kFilterDirty, 0)
builder.setApiParam(QCloud.FileFlash.kFilterModal, 0)
builder.setApiParam(QCloud.FileFlash.kFilterPunc, 0)
builder.setApiParam(QCloud.FileFlash.kConvertNumMode, 1)
builder.setApiParam(QCloud.FileFlash.kWordInfo, 0)
builder.setApiParam(QCloud.FileFlash.kSpeakerDiarization, 1)
try {
let file = FileUtil.openSync(uri, fileIo.OpenMode.READ_ONLY)
const stat = FileUtil.lstatSync(uri)
const buffer = new ArrayBuffer(stat.size)
FileUtil.readSync(file.fd, buffer)
FileUtil.closeSync(file)
let result = await builder.build(buffer).task
let voiceResult = JSONUtil.jsonToBean(result, VoiceRecognizeResultEntity)
return Promise.resolve(voiceResult)
} catch (e) {
console.error(e)
return Promise.reject(e)
}
}
selectAudio() {
PickerUtil.selectDocument({maxSelectNumber: 1, fileSuffixFilters: ['.mp3']})
.then(async (uris) => {
if (uris.length != 0) {
this.isSuccess = false
this.audioUri = uris[0]
this.resultText = undefined
// 打开相应的资源文件地址获取fd
let file = await fileIo.open(this.audioUri)
this.avPlayer!!.url = 'fd://' + file.fd
}
})
}
showDownloadDialog() {
DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: {
confirm: () => {
AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0)
this.getUIContext().getRouter().back()
}
} })
}
// 注册avplayer回调函数
setAVPlayerCallback() {
this.avPlayer!!.on('error', (err) => {
console.error(`播放器发生错误,错误码:${err.code}, 错误信息:${err.message}`);
// 调用reset重置资源触发idle状态
this.isPlaying = false
this.avPlayer!!.reset();
avSessionManager.deactivate()
})
// 状态机变化回调函数
this.avPlayer!!.on('stateChange', async (state, reason) => {
switch (state) {
case 'initialized':
console.info('资源初始化完成');
// 资源初始化完成,开始准备文件
this.avPlayer!!.prepare();
break;
case 'prepared':
console.info('资源准备完成');
// 资源准备完成,开始准备文件
this.durationTime = Math.trunc(this.avPlayer!!.duration / 1000)
this.currentTime = this.avPlayer!!.currentTime;
break;
case 'completed':
console.info('播放完成');
this.isPlaying = false
this.avPlayer!!.off('bufferingUpdate')
AppStorage.setOrCreate('currentTime', this.durationTime);
avSessionManager.deactivate()
break;
case 'playing':
console.info('播放开始');
this.isPlaying = true
break;
case 'released':
case 'stopped':
case 'error':
case 'paused':
console.info('播放暂停');
this.isPlaying = false
avSessionManager.deactivate()
break;
}
})
// 时间上报监听函数
this.avPlayer!!.on('timeUpdate', (time: number) => {
this.currentTime = Math.trunc(time / 1000);
});
}
formatTime(time: number): string {
let minute: number = 0
let second: number = 0
if (time > 60) {
minute = Math.trunc(time / 60)
second = time % 60
if (minute < 10) {
if (second < 10) {
return `0${minute}:0${second}`
} else {
return `0${minute}:${second}`
}
} else {
if (second < 10) {
return `${minute}:0${second}`
} else {
return `${minute}:${second}`
}
}
} else {
second = time
if (second < 10) {
return `00:0${second}`
} else {
return `00:${second}`
}
}
}
onBackPress(): boolean | void {
if (this.isSuccess) {
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未复制,是否确定退出?', callback: {
confirm: () => {
this.getUIContext().getRouter().back()
}
}})
return true
}
return false
}
build() {
Column() {
TitleBar({ title: '语音转文字' })
Stack() {
Stack() {
Column() {
Image($r('app.media.ic_add_audio')).width(40).height(40)
Text('请上传音频').fontColor($r('app.color.color_466afd')).fontSize(15).fontWeight(FontWeight.Medium).margin({ top: 8})
}
}
.width('100%')
.aspectRatio(1)
.borderRadius(20)
.backgroundColor(Color.White)
.shadow({radius: 10, color: '#1a9399a1'})
.onClick(() => {
this.selectAudio()
})
}
.width('100%')
.height('auto')
.padding({left: 32, right: 32})
.margin({top: 40})
.visibility(this.audioUri ? Visibility.None : Visibility.Visible)
Row() {
Image(this.isPlaying ? $r('app.media.ic_audio_pause2') : $r('app.media.ic_audio_play2'))
.width(40)
.height(40)
.margin({ right: 16 })
.onClick(async () => {
if (this.isPlaying) {
this.avPlayer!!.pause()
} else {
await avSessionManager.activate()
this.avPlayer!!.play()
}
})
Text(this.formatTime(this.currentTime)).width(45).fontColor($r('app.color.color_999999')).fontSize(16)
Slider({
value: this.currentTime,
min: 0,
max: this.durationTime
})
.blockColor(Color.White)
.trackColor($r('app.color.color_eeeeee'))
.onChange((value: number, mode: SliderChangeMode) => {
this.avPlayer!!.seek(value * 1000, 2); // 设置视频播放的进度跳转到value处
this.currentTime = value;
})
.layoutWeight(1)
Text(this.formatTime(this.durationTime)).width(45).fontColor($r('app.color.color_999999')).fontSize(16)
}
.height(60)
.borderRadius(30)
.borderWidth(1)
.borderColor('#DADEE5')
.backgroundColor(Color.White)
.margin({left: 12, top: 40, right: 12})
.padding({left: 16, right: 16})
.visibility(this.audioUri ? Visibility.Visible : Visibility.None)
Stack({alignContent: Alignment.Top}) {
Column() {
Row() {
Image($r('app.media.ic_star')).width(22).height(22)
Text('文本结果').fontColor($r('app.color.color_212226')).fontSize(15).fontWeight(FontWeight.Medium).margin({left: 4})
}
Divider().strokeWidth(1).color($r('app.color.color_eeeeee')).margin({top: 12})
Scroll() {
Text(this.resultText).width('100%').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 12})
}
.layoutWeight(1)
.align(Alignment.TopStart)
.scrollBar(BarState.Off)
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Start)
.borderRadius(10)
.borderWidth(1)
.borderColor('#DADEE5')
.backgroundColor(Color.White)
.padding(12)
}
.layoutWeight(1)
.margin({top: 30, bottom: 20})
.padding({left: 16, right: 16})
.visibility(this.resultText ? Visibility.Visible : Visibility.None)
Blank().layoutWeight(1).visibility(this.resultText ? Visibility.None : Visibility.Visible)
Stack() {
Button('确认处理', { type: ButtonType.Capsule, stateEffect: true })
.width('100%')
.height(46)
.fontColor(Color.White)
.fontSize(15)
.fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
if (this.audioUri) {
this.copyAudio()
} else {
ToastUtils.show('请上传音频')
}
})
.visibility(!this.resultText ? Visibility.Visible : Visibility.None)
Row() {
Button({ type: ButtonType.Capsule, stateEffect: true }) {
Row() {
Image($r('app.media.ic_reupload')).width(20).height(20)
Text('重新上传').fontColor($r('app.color.color_466afd')).fontSize(15).fontWeight(FontWeight.Medium)
}
}
.height(46)
.layoutWeight(1)
.borderWidth(1)
.borderColor($r('app.color.color_466afd'))
.backgroundColor(Color.Transparent)
.onClick(() => {
this.controller.stop()
this.selectAudio()
})
Blank().width(9)
Button({ type: ButtonType.Capsule, stateEffect: true }) {
Row() {
Image($r('app.media.ic_copy_text')).width(20).height(20)
Text('复制文本').fontColor(Color.White).fontSize(15).fontWeight(FontWeight.Medium)
}
}
.height(46)
.layoutWeight(1)
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
this.controller.stop()
if (ConfigManager.isAiAuthEnable() && this.durationTime > 60) {
this.viewModel.checkVip()
} else {
this.doSave()
}
})
}
.visibility(this.resultText ? Visibility.Visible : Visibility.None)
}
.padding({left: 16, top: 9, right: 16, bottom: 30 })
.backgroundColor(Color.White)
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.window_background'))
}
}

View File

@ -1,468 +0,0 @@
import { PhotoHelper } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar'
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, DisplayUtil, FileUtil } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo } from '@kit.CoreFileKit'
import { SaveUtils } from '../../../../utils/SaveUtils'
import { LoadingDialog } from '../../../../dialog/LoadingDialog'
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
import { EventConstants } from '../../../../common/EventConstants'
import { RectCropView, RectPosition } from '../../../../view/RectCropView'
import { media } from '@kit.MediaKit'
import { MediaUtils } from '../../../../utils/MediaUtils'
import { MP4Parser } from '@ohos/mp4parser'
import { TipDialog } from '../../../../dialog/TipDialog'
import { avSessionManager } from '../../../../manager/AVSessionManager'
@Entry
@ComponentV2
struct ClipVideoPage {
@Local uri?: string
@Local currentTime: number = 0
@Local durationTime: number = 0
@Local isPlaying: boolean = false
@Local isSuccess: boolean = false
@Local playerSize: media.PixelMapParams = { width: 0, height: 0 }
@Local currentIndex: number = 0
private controller: VideoController = new VideoController()
private rectArray : Array<string> = ['自由', '1:1', '4:3', '3:4', '16:9', '9:16']
private videoSize: media.PixelMapParams = { width: 0, height: 0 }
private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 }
clipVideo() {
LoadingDialog.show(this.getUIContext())
this.isSuccess = false
let cacheVideoPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
if (FileUtil.accessSync(cacheVideoPath)) {
FileUtil.unlinkSync(cacheVideoPath)
}
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
// 复制文件到缓存目录下
FileUtil.copyFileSync(file.fd, cacheVideoPath)
FileUtil.closeSync(file)
let clipWidth: number = 0
let clipHeight: number = 0
if (this.currentIndex === 0) {
clipWidth = (vp2px(this.rect.width * this.videoSize.width!!) / this.playerSize.width!!)
clipHeight = (vp2px(this.rect.height * this.videoSize.height!!) / this.playerSize.height!!)
} else {
const ratio = (DisplayUtil.getWidth() - 180) / this.videoSize.width!!
let originPlayerSize: media.PixelMapParams = {width: Math.ceil(this.videoSize.width!! * ratio), height: Math.ceil(this.videoSize.height!! * ratio)}
clipWidth = (this.playerSize.width!! * this.videoSize.width!!) / originPlayerSize.width!!
clipHeight = (this.playerSize.height!! * this.videoSize.height!!) / originPlayerSize.height!!
}
let clipX: number = 0
let clipY: number = 0
if (this.currentIndex === 0) {
clipX = (vp2px(this.rect.x) * this.videoSize.width!!) / this.playerSize.width!!
clipY = (vp2px(this.rect.y) * this.videoSize.width!!) / this.playerSize.height!!
} else {
const ratio = (DisplayUtil.getWidth() - 180) / this.videoSize.width!!
let originPlayerSize: media.PixelMapParams = {width: Math.ceil(this.videoSize.width!! * ratio), height: Math.ceil(this.videoSize.height!! * ratio)}
clipX = clipWidth === originPlayerSize.width ? 0 : (originPlayerSize.width!! - this.playerSize.width!!) / 2 * (this.videoSize.width!!) / originPlayerSize.width!!
clipY = clipHeight === originPlayerSize.height ? 0 : (originPlayerSize.height!! - this.playerSize.height!!) / 2 * (this.videoSize.height!!) / originPlayerSize.height!!
}
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
let cmd = `ffmpeg -i ${cacheVideoPath} -vf \"crop=${Math.ceil(clipWidth)}:${Math.ceil(clipHeight)}:${Math.ceil(clipX)}:${Math.ceil(clipY)}\" -c:v h264 -pix_fmt yuv420p -y ${outputPath}`
MP4Parser.ffmpegCmd(cmd, {
callBackResult: (code: number) => {
if (code === 0) {
this.uri = FileUtil.getUriFromPath(outputPath)
MediaUtils.getVideoSize(this.uri)
.then((size) => {
this.videoSize = size
if (size.width && size.height) {
const ratio = (DisplayUtil.getWidth() - 180) / size.width
this.playerSize = {width: Math.ceil(size.width * ratio), height: Math.ceil(size.height * ratio)}
}
})
this.isSuccess = true
this.isPlaying = false
ToastUtils.show('处理成功')
} else {
ToastUtils.show('处理失败')
}
LoadingDialog.dismiss()
}
})
}
setVideoRatio() {
if (this.videoSize.width && this.videoSize.height) {
const ratio = (DisplayUtil.getWidth() - 180) / this.videoSize.width
let originPlayerSize: media.PixelMapParams = {width: Math.ceil(this.videoSize.width * ratio), height: Math.ceil(this.videoSize.height * ratio)}
if (originPlayerSize.width && originPlayerSize.height) {
switch (this.currentIndex) {
case 0: {
this.playerSize = originPlayerSize
break
}
case 1: {
if (originPlayerSize.width >= originPlayerSize.height) {
this.playerSize = {width: originPlayerSize.height, height: originPlayerSize.height}
} else {
this.playerSize = {width: originPlayerSize.width, height: originPlayerSize.width}
}
break
}
case 2: {
if (originPlayerSize.width / originPlayerSize.height >= 4 / 3) {
this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 3 * 4), height: originPlayerSize.height}
} else {
this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 4 * 3)}
}
break
}
case 3: {
if (originPlayerSize.width / originPlayerSize.height <= 3 / 4) {
this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 3 * 4)}
} else {
this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 4 * 3), height: originPlayerSize.height}
}
break
}
case 4: {
if (originPlayerSize.width / originPlayerSize.height >= 16 / 9) {
this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 9 * 16), height: originPlayerSize.height}
} else {
this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 16 * 9)}
}
break
}
case 5: {
if (originPlayerSize.width / originPlayerSize.height <= 9 / 16) {
this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 9 * 16)}
} else {
this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 16 * 9), height: originPlayerSize.height}
}
break
}
}
}
}
}
selectVideo() {
PhotoHelper.selectEasy({
MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE,
maxSelectNumber: 1,
isPhotoTakingSupported: false,
isEditSupported: false,
isOriginalSupported: false
})
.then((uris) => {
if (uris.length != 0) {
this.isSuccess = false
this.uri = uris[0]
this.currentIndex = 0
MediaUtils.getVideoSize(this.uri)
.then((size) => {
this.videoSize = size
if (size.width && size.height) {
const ratio = (DisplayUtil.getWidth() - 180) / size.width
this.playerSize = {width: Math.ceil(size.width * ratio), height: Math.ceil(size.height * ratio)}
}
})
}
})
}
showDownloadDialog() {
DownloadDialog.show(this.getUIContext(), {
status: DownloadStatus.COMPLETED,
totalSize: 0,
progress: 0,
totalCount: 1,
index: 0,
callback: {
confirm: () => {
AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0)
this.getUIContext().getRouter().back()
}
}
})
}
formatTime(time: number): string {
let minute: number = 0
let second: number = 0
if (time > 60) {
minute = Math.trunc(time / 60)
second = time % 60
if (minute < 10) {
if (second < 10) {
return `0${minute}:0${second}`
} else {
return `0${minute}:${second}`
}
} else {
if (second < 10) {
return `${minute}:0${second}`
} else {
return `${minute}:${second}`
}
}
} else {
second = time
if (second < 10) {
return `00:0${second}`
} else {
return `00:${second}`
}
}
}
onBackPress(): boolean | void {
if (this.isSuccess) {
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'视频尚未保存,是否确定退出?', callback: {
confirm: () => {
this.getUIContext().getRouter().back()
}
}})
return true
}
return false
}
build() {
Column() {
TitleBar({ title: '视频裁剪' })
Column() {
Row() {
Text('上传视频').fontColor($r('app.color.color_90ffffff')).fontSize(16).fontWeight(FontWeight.Medium)
Text('仅支持mp4格式').fontColor($r('app.color.color_50ffffff')).fontSize(12)
}.alignSelf(ItemAlign.Start)
RelativeContainer() {
Stack() {
Image($r('app.media.ic_add_video')).width(44).height(44)
}
.width(140)
.height(140)
.borderRadius(10)
.backgroundColor($r('app.color.color_333333'))
.alignRules({
start: { anchor: '__container__', align: HorizontalAlign.Start },
top: { anchor: '__container__', align: VerticalAlign.Top },
end: { anchor: '__container__', align: HorizontalAlign.End },
bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
})
.onClick(() => {
this.selectVideo()
})
}
.height(220)
.margin({ top: 12 })
.borderRadius(8)
.backgroundColor($r('app.color.color_222222'))
}.margin({ left: 16, top: 16, right: 16 })
.visibility(this.uri ? Visibility.None : Visibility.Visible)
Column() {
RelativeContainer() {
Video({
src: this.uri, // 设置视频源
controller: this.controller, //设置视频控制器,可以控制视频的播放状态
posterOptions: { showFirstFrame: true }
})
.id('video')
.width(this.playerSize ? px2vp(this.playerSize.width) : '100%')
.height(this.playerSize ? px2vp(this.playerSize.height) : '100%')
.backgroundColor($r('app.color.window_background'))
.controls(false) // 设置是否显示默认控制条
.autoPlay(false) // 设置是否自动播放
.loop(false) // 设置是否循环播放
.objectFit(ImageFit.Cover) // 设置视频填充模式
.alignRules({
left: { anchor: '__container__', align: HorizontalAlign.Start },
top: { anchor: '__container__', align: VerticalAlign.Top },
right: { anchor: '__container__', align: HorizontalAlign.End },
bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
})
.onPrepared((event) => {
if (event) {
this.durationTime = event.duration
}
})
.onUpdate((event) => {
if (event) {
this.currentTime = event.time
}
})
.onStart(() => {
this.isPlaying = true
})
.onPause(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onStop(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onFinish(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onError(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onDisAppear(() => {
avSessionManager.deactivate()
})
Image($r('app.media.ic_play_video'))
.width(50)
.height(50)
.visibility(this.isPlaying ? Visibility.None : Visibility.Visible)
.onClick(async () => {
await avSessionManager.activate()
this.controller.start()
})
.alignRules({
left: { anchor: 'video', align: HorizontalAlign.Start },
top: { anchor: 'video', align: VerticalAlign.Top },
right: { anchor: 'video', align: HorizontalAlign.End },
bottom: { anchor: 'video', align: VerticalAlign.Bottom }
})
Row() {
Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play'))
.width(20)
.height(20)
.margin({ right: 20 })
.onClick(async () => {
if (this.isPlaying) {
this.controller.pause()
} else {
await avSessionManager.activate()
this.controller.start()
}
})
Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12)
Slider({
value: this.currentTime,
min: 0,
max: this.durationTime
})
.blockColor(Color.White)
.trackColor($r('app.color.color_60ffffff'))
.onChange((value: number, mode: SliderChangeMode) => {
this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处
})
.layoutWeight(1)
Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12)
}
.opacity(0.8)
.width(this.playerSize ? px2vp(this.playerSize.width) : "100%")
.alignRules({
left: { anchor: 'video', align: HorizontalAlign.Start },
right: { anchor: 'video', align: HorizontalAlign.End },
bottom: { anchor: 'video', align: VerticalAlign.Bottom }
})
RectCropView({
onRectChange: (rect) => {
this.rect = rect
}
})
.width(this.playerSize ? px2vp(this.playerSize.width) : '100%')
.height(this.playerSize ? px2vp(this.playerSize.height) : '100%')
.alignRules({
left: { anchor: 'video', align: HorizontalAlign.Start },
top: { anchor: 'video', align: VerticalAlign.Top },
right: { anchor: 'video', align: HorizontalAlign.End },
bottom: { anchor: 'video', align: VerticalAlign.Bottom }
})
.visibility(this.uri && this.currentIndex === 0 && !this.isSuccess ? Visibility.Visible : Visibility.None)
}
.layoutWeight(1)
Grid() {
ForEach(this.rectArray, (item: string, index) => {
GridItem() {
Text(item).width(50).height(50)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.borderRadius(4)
.borderWidth(1.5)
.borderColor(this.currentIndex === index ? '#D33952' : Color.Transparent)
.backgroundColor('#282828')
.onClick(() => {
this.currentIndex = index
this.controller.stop()
this.setVideoRatio()
})
}
.width('100%')
})
}
.height(50)
.columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr')
.layoutDirection(GridDirection.Row)
.visibility(this.uri && !this.isSuccess ? Visibility.Visible : Visibility.None)
Row() {
Text(this.isSuccess ? '重新上传' : '取消').fontColor($r('app.color.color_90ffffff'))
.fontSize(17)
.margin({ left: 16 })
.onClick(() => {
this.controller.stop()
if (this.isSuccess) {
this.selectVideo()
} else {
this.getUIContext().getRouter().back()
}
})
Blank().layoutWeight(1)
Text(this.isSuccess ? '保存' : '确定')
.fontColor($r("app.color.color_466afd"))
.fontSize(17)
.margin({ right: 16 })
.onClick(() => {
this.controller.stop()
if (this.isSuccess) {
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
} else {
this.clipVideo()
}
})
}
.margin({ top: 20, bottom: 30 })
}
.layoutWeight(1)
.visibility(this.uri ? Visibility.Visible : Visibility.None)
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.window_background'))
}
}

View File

@ -13,16 +13,70 @@ import { TipDialog } from '../../../../dialog/TipDialog'
import { image } from '@kit.ImageKit'
import { ImageUtils } from '../../../../utils/ImageUtils'
import { Luban } from '@ark/luban'
import { AuthViewModel } from '../../../../viewModel/AuthViewModel'
import { VipAuthEntity } from '../../../../entity/VipAuthEntity'
import { LoginManager } from '../../../../manager/LoginGlobalManager'
import { RouterUrls } from '../../../../common/RouterUrls'
import { router } from '@kit.ArkUI'
import { EventReportManager } from '../../../../manager/EventReportManager'
@Entry
@ComponentV2
struct ImageMergePage {
private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext())
private selectedImages: Array<string> = []
@Local pixelMap?: image.PixelMap = undefined
@Local selectedImage?: string = undefined
@Local imageUris: Array<string> = []
@Local isSuccess: boolean = false
private selectedImages: Array<string> = []
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single)
return;
}
this.doSave()
} else {
if (!info.auth_ad) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'imageMerge'}})
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'imageMerge')
return;
}
}
}
@Monitor('viewModel.errorCode')
onErrorCodeChange(monitor: IMonitor) {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'imageMerge')
ToastUtils.show('M币已用完')
}
}
doSave() {
SaveUtils.savePixelMapToAlbum(this.pixelMap!!)
.then((saved) => {
if (saved) {
this.pixelMap = undefined
this.selectedImage = undefined
this.imageUris = []
this.selectedImages = []
this.isSuccess = false
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
}
async mergeImage() {
LoadingDialog.show(this.getUIContext())
@ -293,21 +347,7 @@ struct ImageMergePage {
.layoutWeight(1)
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
SaveUtils.savePixelMapToAlbum(this.pixelMap!!)
.then((saved) => {
if (saved) {
this.pixelMap = undefined
this.selectedImage = undefined
this.imageUris = []
this.selectedImages = []
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
this.viewModel.checkVip()
})
}
.visibility(this.isSuccess ? Visibility.Visible : Visibility.None)

View File

@ -2,26 +2,84 @@ import { PhotoHelper } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar'
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, FileUtil } from '@pura/harmony-utils'
import { AppUtil, FileUtil, MD5 } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo } from '@kit.CoreFileKit'
import { fileIo, ReadOptions } from '@kit.CoreFileKit'
import { SaveUtils } from '../../../../utils/SaveUtils'
import { LoadingDialog } from '../../../../dialog/LoadingDialog'
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
import { EventConstants } from '../../../../common/EventConstants'
import { TipDialog } from '../../../../dialog/TipDialog'
import { avSessionManager } from '../../../../manager/AVSessionManager'
import { AuthViewModel } from '../../../../viewModel/AuthViewModel'
import { VipAuthEntity as VipAuthEntity } from '../../../../entity/VipAuthEntity'
import { LoginManager } from '../../../../manager/LoginGlobalManager'
import { RouterUrls } from '../../../../common/RouterUrls'
import { router } from '@kit.ArkUI'
import { EventReportManager } from '../../../../manager/EventReportManager'
import { cryptoFramework } from '@kit.CryptoArchitectureKit'
import { buffer } from '@kit.ArkTS'
@Entry
@ComponentV2
struct MD5ResetPage {
private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext())
private controller: VideoController = new VideoController()
@Local oldMd5?: string
@Local newMd5?: string
@Local uri?: string
@Local currentTime: number = 0
@Local durationTime: number = 0
@Local isPlaying: boolean = false
@Local isSuccess: boolean = false
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single)
return;
}
this.doSave()
} else {
if (!info.auth_ad) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'md5Reset'}})
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'md5Reset')
return;
}
}
}
@Monitor('viewModel.errorCode')
onErrorCodeChange(monitor: IMonitor) {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'md5Reset')
ToastUtils.show('M币已用完')
}
}
doSave() {
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.oldMd5 = undefined
this.newMd5 = undefined
this.isSuccess = false
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
}
modifyMD5() {
LoadingDialog.show(this.getUIContext())
this.isSuccess = false
@ -35,10 +93,16 @@ struct MD5ResetPage {
FileUtil.copyFileSync(file.fd, outputPath)
FileUtil.closeSync(file)
//在新文件追加空格
let newFile = FileUtil.openSync(outputPath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.APPEND)
FileUtil.writeSync(newFile.fd, buffer.from(' ').buffer)
FileUtil.closeSync(newFile)
if (FileUtil.accessSync(outputPath)) {
this.uri = FileUtil.getUriFromPath(outputPath)
this.isSuccess = true
this.isPlaying = false
this.newMd5 = this.fileMD5(outputPath)
ToastUtils.show('处理成功')
} else {
ToastUtils.show('处理失败')
@ -58,10 +122,40 @@ struct MD5ResetPage {
if (uris.length != 0) {
this.isSuccess = false
this.uri = uris[0]
this.oldMd5 = this.fileMD5(this.uri)
this.newMd5 = undefined
}
})
}
/**
* 获取文件的MD5值
*/
fileMD5(uri: string): string {
// 定义摘要类型
let md = cryptoFramework.createMd('MD5');
// 打开文件
let file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY);
let fileBufferSize = 4096;
let readSize = 0;
let fileBuffer = new ArrayBuffer(fileBufferSize);
let readOptions: ReadOptions = {
offset: readSize,
length: fileBufferSize
};
let readLength = fileIo.readSync(file.fd, fileBuffer, readOptions);
while (readLength > 0) {
// 更新摘要数据
md.updateSync({ data: new Uint8Array(fileBuffer.slice(0, readLength)) });
readSize += readLength;
readOptions.offset = readSize;
readLength = fileIo.readSync(file.fd, fileBuffer, readOptions);
}
// 计算摘要
let mdResult = md.digestSync();
return buffer.from(mdResult.data).toString('hex');
}
showDownloadDialog() {
DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: {
confirm: () => {
@ -244,6 +338,20 @@ struct MD5ResetPage {
.padding({left: 32, right: 32})
.margin({top: 40})
Text('旧-MD5' + this.oldMd5)
.textAlign(TextAlign.Center)
.fontColor($r('app.color.color_212226'))
.fontSize(15)
.margin({top: 30})
.visibility(this.oldMd5 ? Visibility.Visible : Visibility.None)
Text('新-MD5' + this.newMd5)
.textAlign(TextAlign.Center)
.fontColor($r('app.color.color_212226'))
.fontSize(15)
.margin({top: 15})
.visibility(this.newMd5 ? Visibility.Visible : Visibility.None)
Blank().layoutWeight(1)
Stack() {
@ -293,18 +401,7 @@ struct MD5ResetPage {
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
this.controller.stop()
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
this.viewModel.checkVip()
})
}
.visibility(this.isSuccess ? Visibility.Visible : Visibility.None)

View File

@ -12,17 +12,69 @@ import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialo
import { EventConstants } from '../../../../common/EventConstants'
import { TipDialog } from '../../../../dialog/TipDialog'
import { avSessionManager } from '../../../../manager/AVSessionManager'
import { AuthViewModel } from '../../../../viewModel/AuthViewModel'
import { VipAuthEntity } from '../../../../entity/VipAuthEntity'
import { LoginManager } from '../../../../manager/LoginGlobalManager'
import { RouterUrls } from '../../../../common/RouterUrls'
import { router } from '@kit.ArkUI'
import { EventReportManager } from '../../../../manager/EventReportManager'
@Entry
@ComponentV2
struct RemoveAudioPage {
private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext())
private controller: VideoController = new VideoController()
@Local uri?: string
@Local currentTime: number = 0
@Local durationTime: number = 0
@Local isPlaying: boolean = false
@Local isSuccess: boolean = false
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single)
return;
}
this.doSave()
} else {
if (!info.auth_ad) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'removeAudio'}})
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'removeAudio')
return;
}
}
}
@Monitor('viewModel.errorCode')
onErrorCodeChange(monitor: IMonitor) {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'removeAudio')
ToastUtils.show('M币已用完')
}
}
doSave() {
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.isSuccess = false
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
}
removeAudio() {
LoadingDialog.show(this.getUIContext())
this.isSuccess = false
@ -299,18 +351,7 @@ struct RemoveAudioPage {
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
this.controller.stop()
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
this.viewModel.checkVip()
})
}
.visibility(this.isSuccess ? Visibility.Visible : Visibility.None)

View File

@ -2,7 +2,7 @@ import { PhotoHelper } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar'
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, DisplayUtil, FileUtil, ImageUtil, StrUtil } from '@pura/harmony-utils'
import { AppUtil, DisplayUtil, FileUtil } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo } from '@kit.CoreFileKit'
import { SaveUtils } from '../../../../utils/SaveUtils'
@ -14,27 +14,74 @@ import { media } from '@kit.MediaKit'
import { MediaUtils } from '../../../../utils/MediaUtils'
import { MP4Parser } from '@ohos/mp4parser'
import { TipDialog } from '../../../../dialog/TipDialog'
import { WaterMarkerView } from '../../../../view/WaterMarkerView'
import { EditTextDialog } from '../../../../dialog/EditTextDialog'
import { image } from '@kit.ImageKit'
import { avSessionManager } from '../../../../manager/AVSessionManager'
import { SelectBoundsView } from '../../../../view/SelectBoundsView'
import { AuthViewModel } from '../../../../viewModel/AuthViewModel'
import { LoginManager } from '../../../../manager/LoginGlobalManager'
import { VipAuthEntity } from '../../../../entity/VipAuthEntity'
import { RouterUrls } from '../../../../common/RouterUrls'
import { router } from '@kit.ArkUI'
import { EventReportManager } from '../../../../manager/EventReportManager'
@Entry
@ComponentV2
struct RemoveWatermarkPage {
private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext())
private controller: VideoController = new VideoController()
private videoSize: media.PixelMapParams = { width: 0, height: 0 }
private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 }
@Local uri?: string
@Local currentTime: number = 0
@Local durationTime: number = 0
@Local isPlaying: boolean = false
@Local isSuccess: boolean = false
@Local playerSize: media.PixelMapParams = { width: 0, height: 0 }
@Local showBound: boolean = false
private controller: VideoController = new VideoController()
private videoSize: media.PixelMapParams = { width: 0, height: 0 }
private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 }
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single)
return;
}
this.doSave()
} else {
if (!info.auth_ad) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'removeWatermark'}})
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'removeWatermark')
return;
}
}
}
@Monitor('viewModel.errorCode')
onErrorCodeChange(monitor: IMonitor) {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'removeWatermark')
ToastUtils.show('M币已用完')
}
}
doSave() {
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.isSuccess = false
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
}
addWatermark() {
LoadingDialog.show(this.getUIContext())
@ -375,18 +422,7 @@ struct RemoveWatermarkPage {
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
this.controller.stop()
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
this.viewModel.checkVip()
})
}
.visibility(this.isSuccess ? Visibility.Visible : Visibility.None)

View File

@ -1,322 +0,0 @@
import { PhotoHelper } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar'
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, FileUtil } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo } from '@kit.CoreFileKit'
import { SaveUtils } from '../../../../utils/SaveUtils'
import { LoadingDialog } from '../../../../dialog/LoadingDialog'
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
import { EventConstants } from '../../../../common/EventConstants'
import { MP4Parser } from '@ohos/mp4parser'
import { TipDialog } from '../../../../dialog/TipDialog'
import { avSessionManager } from '../../../../manager/AVSessionManager'
@Entry
@ComponentV2
struct VideoMirrorPage {
private controller: VideoController = new VideoController()
@Local uri?: string
@Local currentTime: number = 0
@Local durationTime: number = 0
@Local isPlaying: boolean = false
@Local isSuccess: boolean = false
private orientation: number = 0
mirrorVideo() {
LoadingDialog.show(this.getUIContext())
this.isSuccess = false
let cacheVideoPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
if (FileUtil.accessSync(cacheVideoPath)) {
FileUtil.unlinkSync(cacheVideoPath)
}
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
// 复制文件到缓存目录下
FileUtil.copyFileSync(file.fd, cacheVideoPath)
FileUtil.closeSync(file)
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
let cmd = `ffmpeg -i ${cacheVideoPath} -vf ${this.orientation === 1 ? "hflip" : "vflip"} -c:v h264 -pix_fmt yuv420p -y ${outputPath}`
MP4Parser.ffmpegCmd(cmd, {
callBackResult: (code: number) => {
if (code === 0) {
this.uri = FileUtil.getUriFromPath(outputPath)
this.isSuccess = true
this.isPlaying = false
ToastUtils.show('处理成功')
} else {
ToastUtils.show('处理失败')
}
LoadingDialog.dismiss()
}
})
}
selectVideo() {
PhotoHelper.selectEasy({
MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE,
maxSelectNumber: 1,
isPhotoTakingSupported: false,
isEditSupported: false,
isOriginalSupported: false
})
.then((uris) => {
if (uris.length != 0) {
this.isSuccess = false
this.uri = uris[0]
}
})
}
showDownloadDialog() {
DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: {
confirm: () => {
AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0)
this.getUIContext().getRouter().back()
}
} })
}
formatTime(time: number): string {
let minute: number = 0
let second: number = 0
if (time > 60) {
minute = Math.trunc(time / 60)
second = time % 60
if (minute < 10) {
if (second < 10) {
return `0${minute}:0${second}`
} else {
return `0${minute}:${second}`
}
} else {
if (second < 10) {
return `${minute}:0${second}`
} else {
return `${minute}:${second}`
}
}
} else {
second = time
if (second < 10) {
return `00:0${second}`
} else {
return `00:${second}`
}
}
}
onBackPress(): boolean | void {
if (this.isSuccess) {
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'视频尚未保存,是否确定退出?', callback: {
confirm: () => {
this.getUIContext().getRouter().back()
}
}})
return true
}
return false
}
build() {
Column() {
TitleBar({ title: '视频镜像' })
Column() {
Row() {
Text('上传视频').fontColor($r('app.color.color_90ffffff')).fontSize(16).fontWeight(FontWeight.Medium)
Text('仅支持mp4格式').fontColor($r('app.color.color_50ffffff')).fontSize(12)
}.alignSelf(ItemAlign.Start)
RelativeContainer() {
Stack() {
Image($r('app.media.ic_add_video')).width(44).height(44)
}
.width(140)
.height(140)
.borderRadius(10)
.backgroundColor($r('app.color.color_333333'))
.alignRules({
start: { anchor: '__container__', align: HorizontalAlign.Start },
top: { anchor: '__container__', align: VerticalAlign.Top },
end: { anchor: '__container__', align: HorizontalAlign.End },
bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
})
.onClick(() => {
this.selectVideo()
})
}
.height(220)
.margin({ top: 12 })
.borderRadius(8)
.backgroundColor($r('app.color.color_222222'))
}.margin({ left: 16, top: 16, right: 16 })
.visibility(this.uri ? Visibility.None : Visibility.Visible)
Column() {
RelativeContainer() {
Video({
src: this.uri, // 设置视频源
controller: this.controller, //设置视频控制器,可以控制视频的播放状态
posterOptions: { showFirstFrame: true }
})
.width('100%')
.height('100%')
.backgroundColor($r('app.color.window_background'))
.controls(false) // 设置是否显示默认控制条
.autoPlay(false) // 设置是否自动播放
.loop(false) // 设置是否循环播放
.objectFit(ImageFit.Contain) // 设置视频填充模式
.onPrepared((event) => {
if (event) {
this.durationTime = event.duration
}
})
.onUpdate((event) => {
if (event) {
this.currentTime = event.time
}
})
.onStart(() => {
this.isPlaying = true
})
.onPause(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onStop(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onFinish(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onError(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onDisAppear(() => {
avSessionManager.deactivate()
})
Image($r('app.media.ic_play_video'))
.width(50)
.height(50)
.visibility(this.isPlaying ? Visibility.None : Visibility.Visible)
.onClick(async () => {
await avSessionManager.activate()
this.controller.start()
})
.alignRules({
left: { anchor: '__container__', align: HorizontalAlign.Start },
top: { anchor: '__container__', align: VerticalAlign.Top },
right: { anchor: '__container__', align: HorizontalAlign.End },
bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
})
Row() {
Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play'))
.width(20)
.height(20)
.margin({ right: 20 })
.onClick(async () => {
if (this.isPlaying) {
this.controller.pause()
} else {
await avSessionManager.activate()
this.controller.start()
}
})
Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12)
Slider({
value: this.currentTime,
min: 0,
max: this.durationTime
})
.blockColor(Color.White)
.trackColor($r('app.color.color_60ffffff'))
.onChange((value: number, mode: SliderChangeMode) => {
this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处
})
.layoutWeight(1)
Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12)
}
.opacity(0.8)
.width("100%")
.padding({ left: 30, right: 30 })
.alignRules({
bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
})
}
.layoutWeight(1)
Row() {
Column(){
Image($r('app.media.ic_mirror_h')).width(50).height(50)
Text('水平').fontColor($r('app.color.color_90ffffff')).fontSize(14).margin({ top: 8 })
}
.onClick(() => {
this.orientation = 1
this.controller.stop()
this.mirrorVideo()
})
Column(){
Image($r('app.media.ic_mirror_v')).width(50).height(50)
Text('垂直').fontColor($r('app.color.color_90ffffff')).fontSize(14).margin({ top: 8 })
}
.margin({ left: 50 })
.onClick(() => {
this.orientation = 2
this.controller.stop()
this.mirrorVideo()
})
.visibility(Visibility.None)
}
.margin({ top: 20 })
Row() {
Text(this.isSuccess ? '重新上传' : '取消').fontColor($r('app.color.color_90ffffff')).fontSize(17).margin({ left: 16 })
.onClick(() => {
this.controller.stop()
if (this.isSuccess) {
this.selectVideo()
} else {
this.getUIContext().getRouter().back()
}
})
Blank().layoutWeight(1)
Text('保存').fontColor($r("app.color.color_466afd")).fontSize(17).margin({ right: 16 })
.onClick(() => {
this.controller.stop()
if (this.orientation !== 0) {
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
} else {
ToastUtils.show('请选择镜像方向')
}
})
}
.margin({ top: 20, bottom: 30 })
}
.layoutWeight(1)
.visibility(this.uri ? Visibility.Visible : Visibility.None)
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.window_background'))
}
}

View File

@ -1,297 +0,0 @@
import { PhotoHelper } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar'
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, FileUtil } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo } from '@kit.CoreFileKit'
import { SaveUtils } from '../../../../utils/SaveUtils'
import { LoadingDialog } from '../../../../dialog/LoadingDialog'
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
import { EventConstants } from '../../../../common/EventConstants'
import { MP4Parser } from '@ohos/mp4parser'
import { TipDialog } from '../../../../dialog/TipDialog'
import { avSessionManager } from '../../../../manager/AVSessionManager'
@Entry
@ComponentV2
struct VideoReversePage {
private controller: VideoController = new VideoController()
@Local uri?: string
@Local currentTime: number = 0
@Local durationTime: number = 0
@Local isPlaying: boolean = false
@Local isSuccess: boolean = false
videoReverse() {
LoadingDialog.show(this.getUIContext())
this.isSuccess = false
let cacheVideoPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
if (FileUtil.accessSync(cacheVideoPath)) {
FileUtil.unlinkSync(cacheVideoPath)
}
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
// 复制文件到缓存目录下
FileUtil.copyFileSync(file.fd, cacheVideoPath)
FileUtil.closeSync(file)
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
let cmd = `ffmpeg -i ${cacheVideoPath} -vf reverse -af areverse -c:v h264 -pix_fmt yuv420p -y ${outputPath}`
MP4Parser.ffmpegCmd(cmd, {
callBackResult: (code: number) => {
if (code === 0) {
this.uri = FileUtil.getUriFromPath(outputPath)
this.isSuccess = true
this.isPlaying = false
ToastUtils.show('处理成功')
} else {
ToastUtils.show('处理失败')
}
LoadingDialog.dismiss()
}
})
}
selectVideo() {
PhotoHelper.selectEasy({
MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE,
maxSelectNumber: 1,
isPhotoTakingSupported: false,
isEditSupported: false,
isOriginalSupported: false
})
.then((uris) => {
if (uris.length != 0) {
this.isSuccess = false
this.uri = uris[0]
}
})
}
showDownloadDialog() {
DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: {
confirm: () => {
AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0)
this.getUIContext().getRouter().back()
}
} })
}
formatTime(time: number): string {
let minute: number = 0
let second: number = 0
if (time > 60) {
minute = Math.trunc(time / 60)
second = time % 60
if (minute < 10) {
if (second < 10) {
return `0${minute}:0${second}`
} else {
return `0${minute}:${second}`
}
} else {
if (second < 10) {
return `${minute}:0${second}`
} else {
return `${minute}:${second}`
}
}
} else {
second = time
if (second < 10) {
return `00:0${second}`
} else {
return `00:${second}`
}
}
}
onBackPress(): boolean | void {
if (this.isSuccess) {
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'视频尚未保存,是否确定退出?', callback: {
confirm: () => {
this.getUIContext().getRouter().back()
}
}})
return true
}
return false
}
build() {
Column() {
TitleBar({ title: '视频倒放' })
Column() {
Row() {
Text('上传视频').fontColor($r('app.color.color_90ffffff')).fontSize(16).fontWeight(FontWeight.Medium)
Text('仅支持mp4格式').fontColor($r('app.color.color_50ffffff')).fontSize(12)
}.alignSelf(ItemAlign.Start)
RelativeContainer() {
Stack() {
Image($r('app.media.ic_add_video')).width(44).height(44)
}
.width(140)
.height(140)
.borderRadius(10)
.backgroundColor($r('app.color.color_333333'))
.alignRules({
start: { anchor: '__container__', align: HorizontalAlign.Start },
top: { anchor: '__container__', align: VerticalAlign.Top },
end: { anchor: '__container__', align: HorizontalAlign.End },
bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
})
.onClick(() => {
this.selectVideo()
})
}
.height(220)
.margin({ top: 12 })
.borderRadius(8)
.backgroundColor($r('app.color.color_222222'))
}.margin({ left: 16, top: 16, right: 16 })
.visibility(this.uri ? Visibility.None : Visibility.Visible)
Column() {
RelativeContainer() {
Video({
src: this.uri, // 设置视频源
controller: this.controller, //设置视频控制器,可以控制视频的播放状态
posterOptions: { showFirstFrame: true }
})
.width('100%')
.height('100%')
.backgroundColor($r('app.color.window_background'))
.controls(false) // 设置是否显示默认控制条
.autoPlay(false) // 设置是否自动播放
.loop(false) // 设置是否循环播放
.objectFit(ImageFit.Contain) // 设置视频填充模式
.onPrepared((event) => {
if (event) {
this.durationTime = event.duration
}
})
.onUpdate((event) => {
if (event) {
this.currentTime = event.time
}
})
.onStart(() => {
this.isPlaying = true
})
.onPause(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onStop(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onFinish(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onError(() => {
this.isPlaying = false
avSessionManager.deactivate()
})
.onDisAppear(() => {
avSessionManager.deactivate()
})
Image($r('app.media.ic_play_video'))
.width(50)
.height(50)
.visibility(this.isPlaying ? Visibility.None : Visibility.Visible)
.onClick(async () => {
await avSessionManager.activate()
this.controller.start()
})
.alignRules({
left: { anchor: '__container__', align: HorizontalAlign.Start },
top: { anchor: '__container__', align: VerticalAlign.Top },
right: { anchor: '__container__', align: HorizontalAlign.End },
bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
})
Row() {
Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play'))
.width(20)
.height(20)
.margin({ right: 20 })
.onClick(async () => {
if (this.isPlaying) {
this.controller.pause()
} else {
await avSessionManager.activate()
this.controller.start()
}
})
Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12)
Slider({
value: this.currentTime,
min: 0,
max: this.durationTime
})
.blockColor(Color.White)
.trackColor($r('app.color.color_60ffffff'))
.onChange((value: number, mode: SliderChangeMode) => {
this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处
})
.layoutWeight(1)
Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12)
}
.opacity(0.8)
.width("100%")
.padding({ left: 30, right: 30 })
.alignRules({
bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
})
}
.layoutWeight(1)
Row() {
Text(this.isSuccess ? '重新上传' : '取消').fontColor($r('app.color.color_90ffffff')).fontSize(17).margin({ left: 16 })
.onClick(() => {
this.controller.stop()
if (this.isSuccess) {
this.selectVideo()
} else {
this.getUIContext().getRouter().back()
}
})
Blank().layoutWeight(1)
Text(this.isSuccess ? '保存' : '确定').fontColor($r("app.color.color_466afd")).fontSize(17).margin({ right: 16 })
.onClick(() => {
this.controller.stop()
if (this.isSuccess) {
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => {
if (saved) {
this.uri = undefined
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
} else {
this.videoReverse()
}
})
}
.margin({ top: 140, bottom: 30 })
}
.layoutWeight(1)
.visibility(this.uri ? Visibility.Visible : Visibility.None)
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.window_background'))
}
}

View File

@ -11,18 +11,97 @@ import { LoadingDialog } from '../../../../dialog/LoadingDialog'
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
import { EventConstants } from '../../../../common/EventConstants'
import { avSessionManager } from '../../../../manager/AVSessionManager'
import { AuthViewModel } from '../../../../viewModel/AuthViewModel'
import { LoginManager } from '../../../../manager/LoginGlobalManager'
import { VipAuthEntity } from '../../../../entity/VipAuthEntity'
import { RouterUrls } from '../../../../common/RouterUrls'
import { router } from '@kit.ArkUI'
import { EventReportManager } from '../../../../manager/EventReportManager'
import { media } from '@kit.MediaKit'
@Entry
@ComponentV2
struct VideoToAudioPage {
private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext())
private controller: VideoController = new VideoController()
private avPlayer?: media.AVPlayer = undefined
@Local videoUri?: string
@Local audioUri?: string
@Local currentTime: number = 0
@Local durationTime: number = 0
@Local isPlaying: boolean = false
@Local videoCurrentTime: number = 0
@Local audioCurrentTime: number = 0
@Local videoDurationTime: number = 0
@Local audioDurationTime: number = 0
@Local isVideoPlaying: boolean = false
@Local isAudioPlaying: boolean = false
@Local isSuccess: boolean = false
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single)
return;
}
this.doSave()
} else {
if (!info.auth_ad) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'videoToAudio'}})
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'videoToAudio')
return;
}
}
}
@Monitor('viewModel.errorCode')
onErrorCodeChange(monitor: IMonitor) {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'videoToAudio')
ToastUtils.show('M币已用完')
}
}
aboutToAppear(): void {
this.initPlayer()
}
onPageHide(): void {
if (this.avPlayer) {
this.avPlayer.pause()
}
}
aboutToDisappear(): void {
if (this.avPlayer) {
this.avPlayer.release()
}
}
async initPlayer() {
this.avPlayer = await media.createAVPlayer();
// 创建状态机变化回调函数
this.setAVPlayerCallback();
}
doSave() {
SaveUtils.saveAudioToMusic([this.audioUri!!])
.then((saved) => {
if (saved) {
this.videoUri = undefined
this.isSuccess = false
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
}
videoToAudio() {
LoadingDialog.show(this.getUIContext())
this.isSuccess = false
@ -42,7 +121,10 @@ struct VideoToAudioPage {
if (code === 0) {
this.audioUri = outputPath
this.isSuccess = true
this.isPlaying = false
this.isVideoPlaying = false
// 打开相应的资源文件地址获取fd
let file = fileIo.openSync(this.audioUri)
this.avPlayer!!.url = 'fd://' + file.fd
ToastUtils.show('处理成功')
} else {
ToastUtils.show('处理失败')
@ -78,6 +160,56 @@ struct VideoToAudioPage {
} })
}
// 注册avplayer回调函数
setAVPlayerCallback() {
this.avPlayer!!.on('error', (err) => {
console.error(`播放器发生错误,错误码:${err.code}, 错误信息:${err.message}`);
// 调用reset重置资源触发idle状态
this.isAudioPlaying = false
this.avPlayer!!.reset();
avSessionManager.deactivate()
})
// 状态机变化回调函数
this.avPlayer!!.on('stateChange', async (state, reason) => {
switch (state) {
case 'initialized':
console.info('资源初始化完成');
// 资源初始化完成,开始准备文件
this.avPlayer!!.prepare();
break;
case 'prepared':
console.info('资源准备完成');
// 资源准备完成,开始准备文件
this.audioDurationTime = Math.trunc(this.avPlayer!!.duration / 1000)
this.audioCurrentTime = this.avPlayer!!.currentTime;
break;
case 'completed':
console.info('播放完成');
this.isAudioPlaying = false
this.avPlayer!!.off('bufferingUpdate')
AppStorage.setOrCreate('currentTime', this.videoDurationTime);
avSessionManager.deactivate()
break;
case 'playing':
console.info('播放开始');
this.isAudioPlaying = true
break;
case 'released':
case 'stopped':
case 'error':
case 'paused':
console.info('播放暂停');
this.isAudioPlaying = false
avSessionManager.deactivate()
break;
}
})
// 时间上报监听函数
this.avPlayer!!.on('timeUpdate', (time: number) => {
this.audioCurrentTime = Math.trunc(time / 1000);
});
}
formatTime(time: number): string {
let minute: number = 0
let second: number = 0
@ -142,31 +274,31 @@ struct VideoToAudioPage {
.objectFit(ImageFit.Contain) // 设置视频填充模式
.onPrepared((event) => {
if (event) {
this.durationTime = event.duration
this.videoDurationTime = event.duration
}
})
.onUpdate((event) => {
if (event) {
this.currentTime = event.time
this.videoCurrentTime = event.time
}
})
.onStart(() => {
this.isPlaying = true
this.isVideoPlaying = true
})
.onPause(() => {
this.isPlaying = false
this.isVideoPlaying = false
avSessionManager.deactivate()
})
.onStop(() => {
this.isPlaying = false
this.isVideoPlaying = false
avSessionManager.deactivate()
})
.onFinish(() => {
this.isPlaying = false
this.isVideoPlaying = false
avSessionManager.deactivate()
})
.onError(() => {
this.isPlaying = false
this.isVideoPlaying = false
avSessionManager.deactivate()
})
.onDisAppear(() => {
@ -176,7 +308,7 @@ struct VideoToAudioPage {
Image($r('app.media.ic_play_video'))
.width(50)
.height(50)
.visibility(this.isPlaying ? Visibility.None : Visibility.Visible)
.visibility(this.isVideoPlaying ? Visibility.None : Visibility.Visible)
.onClick(async () => {
await avSessionManager.activate()
this.controller.start()
@ -189,23 +321,23 @@ struct VideoToAudioPage {
})
Row() {
Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play'))
Image(this.isVideoPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play'))
.width(20)
.height(20)
.margin({ right: 20 })
.onClick(async () => {
if (this.isPlaying) {
if (this.isVideoPlaying) {
this.controller.pause()
} else {
await avSessionManager.activate()
this.controller.start()
}
})
Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12)
Text(this.formatTime(this.videoCurrentTime)).width(35).fontColor(Color.White).fontSize(12)
Slider({
value: this.currentTime,
value: this.videoCurrentTime,
min: 0,
max: this.durationTime
max: this.videoDurationTime
})
.blockColor(Color.White)
.trackColor($r('app.color.color_60ffffff'))
@ -213,7 +345,7 @@ struct VideoToAudioPage {
this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处
})
.layoutWeight(1)
Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12)
Text(this.formatTime(this.videoDurationTime)).width(35).fontColor(Color.White).fontSize(12)
}
.opacity(0.8)
.width("100%")
@ -239,6 +371,43 @@ struct VideoToAudioPage {
.padding({left: 32, right: 32})
.margin({top: 40})
Row() {
Image(this.isAudioPlaying ? $r('app.media.ic_audio_pause2') : $r('app.media.ic_audio_play2'))
.width(40)
.height(40)
.margin({ right: 16 })
.onClick(async () => {
if (this.isAudioPlaying) {
this.avPlayer!!.pause()
} else {
await avSessionManager.activate()
this.avPlayer!!.play()
}
})
Text(this.formatTime(this.audioCurrentTime)).width(45).fontColor($r('app.color.color_999999')).fontSize(16)
Slider({
value: this.audioCurrentTime,
min: 0,
max: this.audioDurationTime
})
.blockColor(Color.White)
.trackColor($r('app.color.color_eeeeee'))
.onChange((value: number, mode: SliderChangeMode) => {
this.avPlayer!!.seek(value * 1000, 2); // 设置视频播放的进度跳转到value处
this.audioCurrentTime = value;
})
.layoutWeight(1)
Text(this.formatTime(this.audioDurationTime)).width(45).fontColor($r('app.color.color_999999')).fontSize(16)
}
.height(60)
.borderRadius(30)
.borderWidth(1)
.borderColor('#DADEE5')
.backgroundColor(Color.White)
.margin({left: 12, top: 40, right: 12})
.padding({left: 16, right: 16})
.visibility(this.audioUri ? Visibility.Visible : Visibility.None)
Blank().layoutWeight(1)
Stack() {
@ -288,18 +457,7 @@ struct VideoToAudioPage {
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
this.controller.stop()
SaveUtils.saveAudioToMusic([this.audioUri!!])
.then((saved) => {
if (saved) {
this.videoUri = undefined
this.showDownloadDialog()
} else {
ToastUtils.show('保存失败')
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
this.viewModel.checkVip()
})
}
.visibility(this.isSuccess ? Visibility.Visible : Visibility.None)

View File

@ -2,10 +2,9 @@ import { PhotoHelper } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar'
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, FileUtil } from '@pura/harmony-utils'
import { AppUtil, FileUtil, JSONUtil, PasteboardUtil } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo } from '@kit.CoreFileKit'
import { SaveUtils } from '../../../../utils/SaveUtils'
import { LoadingDialog } from '../../../../dialog/LoadingDialog'
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
import { EventConstants } from '../../../../common/EventConstants'
@ -15,12 +14,20 @@ import { MP4Parser } from '@ohos/mp4parser'
import { QCloud } from 'qcloudfileflash'
import { Constants } from '../../../../common/Constants'
import { VoiceRecognizeResultEntity } from '../../../../entity/VoiceRecognizeResultEntity'
import { plainToInstance } from 'class-transformer'
import { AuthViewModel } from '../../../../viewModel/AuthViewModel'
import { VipAuthEntity } from '../../../../entity/VipAuthEntity'
import { LoginManager } from '../../../../manager/LoginGlobalManager'
import { RouterUrls } from '../../../../common/RouterUrls'
import { router } from '@kit.ArkUI'
import { EventReportManager } from '../../../../manager/EventReportManager'
import { ConfigManager } from '../../../../manager/UserConfigManager'
@Entry
@ComponentV2
struct VideoToTextPage {
private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext())
private controller: VideoController = new VideoController()
@Local resultText?: string
@Local videoUri?: string
@Local currentTime: number = 0
@ -28,6 +35,42 @@ struct VideoToTextPage {
@Local isPlaying: boolean = false
@Local isSuccess: boolean = false
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single)
return;
}
this.doSave()
} else {
if (!info.auth_ad) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'videoToText'}})
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'videoToText')
return;
}
}
}
@Monitor('viewModel.errorCode')
onErrorCodeChange(monitor: IMonitor) {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'videoToText')
ToastUtils.show('M币已用完')
}
}
doSave() {
if (this.resultText) {
PasteboardUtil.setDataTextSync(this.resultText)
this.isSuccess = false
ToastUtils.show('复制成功')
}
}
videoToAudio() {
LoadingDialog.show(this.getUIContext())
this.isSuccess = false
@ -46,11 +89,15 @@ struct VideoToTextPage {
callBackResult: (code: number) => {
if (code === 0) {
this.recognizeAudio(outputPath)
.then((result: VoiceRecognizeResultEntity) => {
.then((result) => {
if (result !== null) {
this.resultText = result.flash_result[0].text
this.isSuccess = true
this.isPlaying = false
ToastUtils.show('处理成功')
} else {
ToastUtils.show('处理失败')
}
LoadingDialog.dismiss()
})
.catch((e: BusinessError) => {
@ -66,7 +113,7 @@ struct VideoToTextPage {
})
}
async recognizeAudio(uri: string): Promise<VoiceRecognizeResultEntity> {
async recognizeAudio(uri: string): Promise<VoiceRecognizeResultEntity|null> {
let builder = new QCloud.FileFlash.Builder()
builder.appID = Constants.QCLOUD_APP_ID
builder.secretID = Constants.QCLOUD_SECRET_ID
@ -87,7 +134,7 @@ struct VideoToTextPage {
FileUtil.readSync(file.fd, buffer)
FileUtil.closeSync(file)
let result = await builder.build(buffer).task
const voiceResult = plainToInstance(VoiceRecognizeResultEntity, result)
let voiceResult = JSONUtil.jsonToBean(result, VoiceRecognizeResultEntity)
return Promise.resolve(voiceResult)
} catch (e) {
console.error(e)
@ -107,6 +154,7 @@ struct VideoToTextPage {
if (uris.length != 0) {
this.isSuccess = false
this.videoUri = uris[0]
this.resultText = undefined
}
})
}
@ -151,7 +199,7 @@ struct VideoToTextPage {
onBackPress(): boolean | void {
if (this.isSuccess) {
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未保存,是否确定退出?', callback: {
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未复制,是否确定退出?', callback: {
confirm: () => {
this.getUIContext().getRouter().back()
}
@ -293,22 +341,32 @@ struct VideoToTextPage {
.padding({left: 32, right: 32})
.margin({top: 40})
Stack({alignContent: Alignment.Top}) {
Column() {
Row() {
Image($r('app.media.ic_star')).width(22).height(22)
Text('文本结果').fontColor($r('app.color.color_212226')).fontSize(15).fontWeight(FontWeight.Medium).margin({left: 4})
}
Divider().strokeWidth(1).color($r('app.color.color_eeeeee')).margin({top: 12})
Text(this.resultText).width('100%').height('auto').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 14})
Scroll() {
Text(this.resultText).width('100%').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 12})
}
.width('90%')
.layoutWeight(1)
.align(Alignment.TopStart)
.scrollBar(BarState.Off)
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Start)
.borderRadius(10)
.borderWidth(1)
.borderColor('#DADEE5')
.backgroundColor(Color.White)
.margin({top: 30, bottom: 20})
.padding(12)
}
.layoutWeight(1)
.margin({top: 30, bottom: 20})
.padding({left: 16, right: 16})
.visibility(this.resultText ? Visibility.Visible : Visibility.None)
Blank().layoutWeight(1).visibility(this.resultText ? Visibility.None : Visibility.Visible)
@ -328,7 +386,7 @@ struct VideoToTextPage {
ToastUtils.show('请上传视频')
}
})
.visibility(!this.isSuccess ? Visibility.Visible : Visibility.None)
.visibility(!this.resultText ? Visibility.Visible : Visibility.None)
Row() {
Button({ type: ButtonType.Capsule, stateEffect: true }) {
@ -360,21 +418,14 @@ struct VideoToTextPage {
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
this.controller.stop()
SaveUtils.saveImageVideoToAlbumDialog([this.videoUri!!])
.then((saved) => {
if (saved) {
this.videoUri = undefined
this.showDownloadDialog()
if (ConfigManager.isAiAuthEnable() && this.durationTime > 60) {
this.viewModel.checkVip()
} else {
ToastUtils.show('保存失败')
this.doSave()
}
})
.catch((e: BusinessError) => {
ToastUtils.show('保存失败:' + e.message)
})
})
}
.visibility(this.isSuccess ? Visibility.Visible : Visibility.None)
.visibility(this.resultText ? Visibility.Visible : Visibility.None)
}
.padding({left: 16, top: 9, right: 16, bottom: 30 })
.backgroundColor(Color.White)

View File

@ -5,7 +5,7 @@ import { EventConstants } from '../../../../common/EventConstants';
import { RouterUrls } from '../../../../common/RouterUrls';
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog';
import { ImageMaterial, MaterialInfoEntity, MediaEntity, VideoMaterial } from '../../../../entity/MaterialInfoEntity';
import { VipPermissionEntity } from '../../../../entity/VipPermissionEntity';
import { VipAuthEntity } from '../../../../entity/VipAuthEntity';
import { LoginManager } from '../../../../manager/LoginGlobalManager';
import { ShareManager } from '../../../../manager/ShareManager';
import { ConfigManager } from '../../../../manager/UserConfigManager';
@ -24,7 +24,7 @@ import { ErrCode, SendAuthResp } from '@tencent/wechat_open_sdk';
import { LoadingDialog } from '../../../../dialog/LoadingDialog';
import BuildProfile from 'BuildProfile';
import { Constants } from '../../../../common/Constants';
import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../../../manager/EventReportManager';
import { TipDialog } from '../../../../dialog/TipDialog';
import { SimpleTipDialog } from '../../../../dialog/SimpleTipDialog';
import { JoinWxGroupCourseDialog } from '../../../../dialog/JoinWxGroupCourseDialog';
@ -87,9 +87,9 @@ struct WxVideoPage {
this.isRefreshing = false
}
@Monitor('viewModel.permissionInfo')
@Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) {
const info = monitor.value()?.now as VipPermissionEntity;
const info = monitor.value()?.now as VipAuthEntity;
if (info.auth) {
if (!LoginManager.isLogin()) {
this.getUIContext()
@ -103,7 +103,7 @@ struct WxVideoPage {
this.getUIContext()
.getRouter()
.pushUrl({ url: RouterUrls.VIP_PAGE, params: { origin: 'download_wechat_video' } })
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_wechat_video')
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_wechat_video')
return;
}
}
@ -114,7 +114,7 @@ struct WxVideoPage {
const errorCode = monitor.value()?.now as number;
if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) {
this.getUIContext().getRouter().pushUrl({ url: RouterUrls.RECHARGE_DIAMOND_PAGE });
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_wechat_video')
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_wechat_video')
ToastUtils.show('M币已用完')
}
}
@ -328,7 +328,7 @@ struct WxVideoPage {
callback: {
confirm: () => {
if (this.downloadStatus === DownloadStatus.COMPLETED) {
EventReportGlobalManager.eventReport(EventConstants.DIALOG_GO_TO_VIEW, this.titles[this.currentIndex])
EventReportManager.eventReport(EventConstants.DIALOG_GO_TO_VIEW, this.titles[this.currentIndex])
AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, this.currentIndex)
this.getUIContext().getRouter().back()
} else {
@ -339,11 +339,11 @@ struct WxVideoPage {
if (this.downloadStatus !== DownloadStatus.COMPLETED) {
if (this.mediaDownloader) {
this.mediaDownloader.cancel()
EventReportGlobalManager.eventReport(EventConstants.CANCEL_DOWNLOAD_VIDEO,
EventReportManager.eventReport(EventConstants.CANCEL_DOWNLOAD_VIDEO,
this.selectedList[this.downloadIndex].url)
}
} else {
EventReportGlobalManager.eventReport(EventConstants.DIALOG_CONFIRM_SAVE_FILE,
EventReportManager.eventReport(EventConstants.DIALOG_CONFIRM_SAVE_FILE,
this.titles[this.currentIndex])
}
}
@ -469,7 +469,7 @@ struct WxVideoPage {
req.transaction = '';
await WXApi.sendReq(AppUtil.getContext(), req)
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_SHARE_WX_PLAYBACK, '前往微信分享直播回放')
EventReportManager.eventReport(EventConstants.JUMP_TO_SHARE_WX_PLAYBACK, '前往微信分享直播回放')
LoadingDialog.dismiss();
}
@ -501,7 +501,7 @@ struct WxVideoPage {
return;
}
this.viewModel.wxServiceInfo()
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_SHARE_WX_VIDEO, "前往微信分享视频号", '')
EventReportManager.eventReport(EventConstants.JUMP_TO_SHARE_WX_VIDEO, "前往微信分享视频号", '')
}
/**
@ -517,9 +517,9 @@ struct WxVideoPage {
reportErrorEvent(media: MediaEntity, message: string) {
if (media instanceof VideoMaterial) {
EventReportGlobalManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_VIDEO, media.url, message)
EventReportManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_VIDEO, media.url, message)
} else if (media instanceof ImageMaterial) {
EventReportGlobalManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_IMG, media.url, message)
EventReportManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_IMG, media.url, message)
}
}

View File

@ -10,7 +10,7 @@ import { fileIo, storageStatistics } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { LoadingDialog } from '../../../dialog/LoadingDialog';
import { DiamondDetailEntity } from '../../../entity/DiamondDetailEntity';
import { EventReportGlobalManager } from '../../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../../manager/EventReportManager';
import { WxServiceEntity } from '../../../entity/WxServiceEntity';
import { WXApi } from '../../../utils/wechat/WXApiEventHandlerImpl';
import * as WxOpenSdk from '@tencent/wechat_open_sdk';
@ -107,7 +107,7 @@ export struct MinePage {
.onClick(() => {
if (!LoginManager.isLogin()) {
this.getUIContext().getRouter().pushUrl({ url: RouterUrls.LOGIN_PAGE, params: { from : 1 }}, router.RouterMode.Single)
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_LOGIN, 'center')
EventReportManager.eventReport(EventConstants.JUMP_TO_LOGIN, 'center')
} else {
this.getUIContext().getRouter().pushUrl({ url: RouterUrls.USER_SETTINGS_PAGE })
}
@ -193,7 +193,7 @@ export struct MinePage {
Image($r('app.media.ic_mine_setting')).width(26).height(26)
.onClick(() => {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.SETTING_PAGE});
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_SYSTEM_SETTING)
EventReportManager.eventReport(EventConstants.JUMP_TO_SYSTEM_SETTING)
})
}
.alignRules({
@ -267,7 +267,7 @@ export struct MinePage {
.id('btn_to_vip')
.onClick(() => {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'center'}})
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'center')
EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'center')
})
}
.width('100%')
@ -305,17 +305,17 @@ export struct MinePage {
switch (item.alias) {
case 'history': {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.DOWNLOAD_HISTORY_PAGE});
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_DOWNLOAD_HISTORY, 'center')
EventReportManager.eventReport(EventConstants.JUMP_TO_DOWNLOAD_HISTORY, 'center')
break
}
case 'diamond': {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE});
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'center')
EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'center')
break
}
case 'feedback': {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.FEEDBACK_PAGE});
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_FEEDBACK, 'center')
EventReportManager.eventReport(EventConstants.JUMP_TO_FEEDBACK, 'center')
break
}
case 'service': {
@ -405,6 +405,7 @@ export struct MinePage {
})
.visibility(this.currentIndex === 2 ? Visibility.Visible : Visibility.None)
}
.layoutWeight(1)
}
.width('100%')
.height('100%')

View File

@ -16,7 +16,7 @@ import { LoadingDialog } from '../../../../dialog/LoadingDialog';
import { DiamondDetailEntity } from '../../../../entity/DiamondDetailEntity';
import { DiamondItemView } from '../../../../view/DiamondItemView';
import { DiamondRuleDialog } from '../../../../dialog/DiamondRuleDialog';
import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../../../manager/EventReportManager';
import { EventConstants } from '../../../../common/EventConstants';
import { OrderEntity } from '../../../../entity/OrderEntity';
import { TipDialog } from '../../../../dialog/TipDialog';
@ -49,7 +49,7 @@ struct DiamondPage {
this.viewModel.getOrderInfo(this.orderEntity!!.orderId)
} else {
ToastUtils.show(JSON.parse(payResult).errStr);
EventReportGlobalManager.eventReport(
EventReportManager.eventReport(
EventConstants.PAY_CANCEL,
`weixin:${this.origin}`, `{type:\"diamond\", orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.diamondInfo)}}`
)
@ -107,7 +107,7 @@ struct DiamondPage {
const orderEntity = monitor.value()?.now as OrderEntity;
if (orderEntity.status == "2") {
ToastUtils.show('支付成功');
EventReportGlobalManager.eventReport(
EventReportManager.eventReport(
EventConstants.PAY_SUCCESS,
`alipay:${this.origin}`, `{type:\"diamond\", orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.diamondInfo)}}`
)
@ -173,13 +173,13 @@ struct DiamondPage {
this.viewModel.getOrderInfo(this.orderEntity!!.orderId)
} else if (resultStatus === '6001') {
ToastUtils.show('支付取消');
EventReportGlobalManager.eventReport(
EventReportManager.eventReport(
EventConstants.PAY_CANCEL,
`alipay:${this.origin}`, `{type:\"diamond\", orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.diamondInfo)}}`
)
} else {
ToastUtils.show('支付失败');
EventReportGlobalManager.eventReport(
EventReportManager.eventReport(
EventConstants.ERROR_CLIENT_ALIPAY_ERR,
`{orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.diamondInfo)}}`, resultStatus
)

View File

@ -64,10 +64,10 @@ export struct AudioRecordPage {
build() {
Stack() {
Column() {
List() {
List({space: 10}) {
ForEach(this.mediaList, (item: MediaRecordEntity, index) => {
ListItem() {
AudioRecordItemView({ media: item })
AudioRecordItemView({ media: item, index: index })
}
.swipeAction({
end: this.itemEnd(item)
@ -79,7 +79,7 @@ export struct AudioRecordPage {
.width('auto')
.layoutWeight(1)
.scrollBar(BarState.Off)
.margin({ left: 16, right: 16, bottom: 15 })
.margin({ left: 16, right: 16 })
}
EmptyView({

View File

@ -75,7 +75,6 @@ export struct ImageRecordPage {
build() {
Stack() {
Column() {
Grid() {
ForEach(this.mediaList, (item: MediaRecordEntity, index) => {
GridItem() {
@ -83,13 +82,12 @@ export struct ImageRecordPage {
}
})
}
.height('100%')
.scrollBar(BarState.Off)
.columnsTemplate(this.rowCount === 1 ? '1fr' : this.rowCount === 2 ? '1fr 1fr' : '1fr 1fr 1fr')
.rowsGap(10)
.columnsGap(10)
.margin({ left: 16, right: 16, bottom: 15 })
.layoutWeight(1)
}
.margin({ left: 16, right: 16 })
EmptyView({
status: this.mediaList.length > 0 ? PageStatus.GONE : PageStatus.NO_DATA,

View File

@ -75,7 +75,6 @@ export struct VideoRecordPage {
build() {
Stack() {
Column() {
Grid() {
ForEach(this.mediaList, (item: MediaRecordEntity, index) => {
GridItem() {
@ -83,13 +82,12 @@ export struct VideoRecordPage {
}
})
}
.height('100%')
.scrollBar(BarState.Off)
.columnsTemplate(this.rowCount === 1 ? '1fr' : this.rowCount === 2 ? '1fr 1fr' : '1fr 1fr 1fr')
.rowsGap(10)
.columnsGap(10)
.margin({ left: 16, right: 16, bottom: 15 })
.layoutWeight(1)
}
.margin({ left: 16, right: 16 })
EmptyView({
status: this.mediaList.length > 0 ? PageStatus.GONE : PageStatus.NO_DATA,
@ -97,5 +95,6 @@ export struct VideoRecordPage {
noDataText: '暂无数据'
})
}
.height('100%')
}
}

View File

@ -9,7 +9,7 @@ import { TextItemChildView } from '../../../../view/TextItemChildView'
import { TitleBar } from '../../../../view/TitleBar'
import { SettingsViewModel } from '../../../../viewModel/SettingsViewModel'
import { router } from '@kit.ArkUI'
import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager'
import { EventReportManager } from '../../../../manager/EventReportManager'
import { fileIo, storageStatistics } from '@kit.CoreFileKit'
import { BusinessError } from '@kit.BasicServicesKit'
import { LoadingDialog } from '../../../../dialog/LoadingDialog'
@ -24,14 +24,14 @@ struct SettingsPage {
@Monitor('viewModel.destroy')
onDestroy(monitor: IMonitor) {
EventReportGlobalManager.eventReport(EventConstants.CANCEL_ACCOUNT)
EventReportManager.eventReport(EventConstants.CANCEL_ACCOUNT)
this.logout();
ToastUtils.show('账户已注销');
}
@Monitor('viewModel.logout')
onLogout(monitor: IMonitor) {
EventReportGlobalManager.eventReport(EventConstants.EXIT_LOGIN)
EventReportManager.eventReport(EventConstants.EXIT_LOGIN)
this.logout();
}
@ -93,13 +93,13 @@ struct SettingsPage {
.backgroundColor(Color.White)
.onClick(() => {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.BIND_ACCOUNT_PAGE});
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_ACCOUNT_BIND)
EventReportManager.eventReport(EventConstants.JUMP_TO_ACCOUNT_BIND)
})
TextItemChildView({ text: '账号管理' }).height(60).padding({ left: 16, right: 16 })
.backgroundColor(Color.White)
.onClick(() => {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.MANAGE_ACCOUNT_PAGE});
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_ACCOUNT_MANAGE)
EventReportManager.eventReport(EventConstants.JUMP_TO_ACCOUNT_MANAGE)
})
Divider().strokeWidth(10).color($r('app.color.color_eff2f7'))
TextItemChildView({ text: '清除缓存', rightText: FileUtil.getFormatFileSize(this.cacheSize) }).height(60)
@ -118,7 +118,7 @@ struct SettingsPage {
.backgroundColor(Color.White)
.onClick(() => {
this.getUIContext().getRouter().pushUrl({url: RouterUrls.ABOUT_PAGE});
EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_ABOUT_US)
EventReportManager.eventReport(EventConstants.JUMP_TO_ABOUT_US)
})
TextItemChildView({ text: '注销账号' }).height(60).padding({ left: 16, right: 16 })
.backgroundColor(Color.White)

View File

@ -13,7 +13,7 @@ import { BindPhoneDialog } from '../../../../../dialog/BindPhoneDialog';
import { LevelMode } from '@kit.ArkUI';
import { EventConstants } from '../../../../../common/EventConstants';
import { LoadingDialog } from '../../../../../dialog/LoadingDialog';
import { EventReportGlobalManager } from '../../../../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../../../../manager/EventReportManager';
@Entry
@ComponentV2
@ -48,7 +48,7 @@ struct BindAccountPage {
onBindInfoChange(monitor: IMonitor) {
ToastUtils.show('绑定成功');
this.refreshData();
EventReportGlobalManager.eventReport(EventConstants.ACCOUNT_BIND)
EventReportManager.eventReport(EventConstants.ACCOUNT_BIND)
}
@Monitor('viewModel.unbindInfo')

View File

@ -4,7 +4,7 @@ import { LoadingDialog } from '../../../../../dialog/LoadingDialog';
import { TipDialog } from '../../../../../dialog/TipDialog';
import { AccountEntity } from '../../../../../entity/AccountEntity';
import { LoginEntity } from '../../../../../entity/LoginEntity';
import { EventReportGlobalManager } from '../../../../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../../../../manager/EventReportManager';
import { LoginManager } from '../../../../../manager/LoginGlobalManager';
import { ConfigManager } from '../../../../../manager/UserConfigManager';
import { ToastUtils } from '../../../../../utils/ToastUtils';
@ -94,7 +94,7 @@ struct ManageAccountPage {
confirm: () => {
LoginManager.saveToken('');
this.viewModel.changeAccount(item.user_id);
EventReportGlobalManager.eventReport(EventConstants.SWITCH_ACCOUNT,item.user_id)
EventReportManager.eventReport(EventConstants.SWITCH_ACCOUNT,item.user_id)
}
}})
})

View File

@ -16,7 +16,7 @@ import { VipViewModel } from '../../../../viewModel/VipViewModel';
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit';
import router from '@ohos.router';
import { EventConstants } from '../../../../common/EventConstants';
import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../../../manager/EventReportManager';
import { SimpleTipDialog } from '../../../../dialog/SimpleTipDialog';
import { OrderEntity } from '../../../../entity/OrderEntity';
import { TipDialog } from '../../../../dialog/TipDialog';
@ -52,7 +52,7 @@ struct VipPage {
this.viewModel.getOrderInfo(this.orderEntity!!.orderId)
} else {
ToastUtils.show(JSON.parse(payResult).errStr);
EventReportGlobalManager.eventReport(
EventReportManager.eventReport(
EventConstants.ERROR_CLIENT_WXPAY_ERR,
`{isGuide:${this.isGuide}, orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.vipMeal)}}`,
JSON.parse(payResult).errStr
@ -106,7 +106,7 @@ struct VipPage {
const orderEntity = monitor.value()?.now as OrderEntity;
if (orderEntity.status == "2") {
ToastUtils.show('支付成功');
EventReportGlobalManager.eventReport(
EventReportManager.eventReport(
EventConstants.PAY_SUCCESS,
'alipay', `{isGuide:${this.isGuide}, orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.vipMeal)}}`
)
@ -179,13 +179,13 @@ struct VipPage {
this.viewModel.getOrderInfo(this.orderEntity!!.orderId)
} else if (resultStatus === '6001') {
ToastUtils.show('支付取消');
EventReportGlobalManager.eventReport(
EventReportManager.eventReport(
EventConstants.PAY_CANCEL,
'alipay', `{isGuide:${this.isGuide}, orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.vipMeal)}}`
)
} else {
ToastUtils.show('支付失败');
EventReportGlobalManager.eventReport(
EventReportManager.eventReport(
EventConstants.ERROR_CLIENT_ALIPAY_ERR,
`{orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.vipMeal)}}`, resultStatus
)
@ -240,7 +240,7 @@ struct VipPage {
onBackPress(): boolean | void {
if (this.isGuide) {
EventReportGlobalManager.eventReport(EventConstants.GUIDE_SKIP, "back", this.pageDuration())
EventReportManager.eventReport(EventConstants.GUIDE_SKIP, "back", this.pageDuration())
this.getUIContext().getRouter().replaceUrl({ url: RouterUrls.MAIN_PAGE }, router.RouterMode.Single)
return true;
}
@ -274,7 +274,7 @@ struct VipPage {
this.vipMeal = item;
this.totalPrice = NumberUtil.toNumber(item.price);
this.releasePayType();
EventReportGlobalManager.eventReport(EventConstants.GOODS_SELECT, `${this.origin}:${item.goods_name}`, JSON.stringify(item))
EventReportManager.eventReport(EventConstants.GOODS_SELECT, `${this.origin}:${item.goods_name}`, JSON.stringify(item))
})
})
}
@ -377,7 +377,7 @@ struct VipPage {
.visibility(this.vipMeal?.pay_type.includes('weixin') ? Visibility.Visible : Visibility.None)
.onClick(() => {
this.payType = 0;
EventReportGlobalManager.eventReport(EventConstants.PAY_SELECT, 'weixin', this.origin)
EventReportManager.eventReport(EventConstants.PAY_SELECT, 'weixin', this.origin)
})
Divider().color($r('app.color.color_10ffffff')).strokeWidth(1)
@ -395,7 +395,7 @@ struct VipPage {
.visibility(this.vipMeal?.pay_type.includes('alipay') ? Visibility.Visible : Visibility.None)
.onClick(() => {
this.payType = 1;
EventReportGlobalManager.eventReport(EventConstants.PAY_SELECT, "alipay", this.origin)
EventReportManager.eventReport(EventConstants.PAY_SELECT, "alipay", this.origin)
})
Divider().color($r('app.color.color_10ffffff')).strokeWidth(1)
@ -481,12 +481,12 @@ struct VipPage {
confirm: () => {
this.isAgree = true
this.createOrder();
EventReportGlobalManager.eventReport(EventConstants.PAY_PAY, this.payType === 0 ? 'weixin' : 'alipay', JSON.stringify(this.vipMeal))
EventReportManager.eventReport(EventConstants.PAY_PAY, this.payType === 0 ? 'weixin' : 'alipay', JSON.stringify(this.vipMeal))
}
}})
} else {
this.createOrder();
EventReportGlobalManager.eventReport(EventConstants.PAY_PAY, this.payType === 0 ? 'weixin' : 'alipay', JSON.stringify(this.vipMeal))
EventReportManager.eventReport(EventConstants.PAY_PAY, this.payType === 0 ? 'weixin' : 'alipay', JSON.stringify(this.vipMeal))
}
}
})
@ -507,7 +507,7 @@ struct VipPage {
isDark: true,
onBackClick: () => {
if (this.isGuide) {
EventReportGlobalManager.eventReport(EventConstants.GUIDE_SKIP, "icon", this.pageDuration())
EventReportManager.eventReport(EventConstants.GUIDE_SKIP, "icon", this.pageDuration())
}
this.doBack();
}

View File

@ -6,7 +6,7 @@ import { LevelMode, router } from '@kit.ArkUI';
import { LoginManager } from '../../manager/LoginGlobalManager';
import { LoadingDialog } from '../../dialog/LoadingDialog';
import { AppUtil, StrUtil } from '@pura/harmony-utils';
import { EventReportGlobalManager } from '../../manager/EventReportGlobalManager';
import { EventReportManager } from '../../manager/EventReportManager';
import { EventConstants } from '../../common/EventConstants';
import { GyConfig, GyManager } from '@getui/gysdk';
import { hilog } from '@kit.PerformanceAnalysisKit';
@ -51,7 +51,7 @@ struct SplashPage {
this.privacyDialogController = new CustomDialogController({
builder: PrivacyPolicyDialog({
confirm: () => {
EventReportGlobalManager.eventReport(EventConstants.APP_LAUNCH, '', '')
EventReportManager.eventReport(EventConstants.APP_LAUNCH, '', '')
LoadingDialog.show(this.getUIContext());
ConfigManager.saveIsAgreePrivacy(true);
ConfigManager.getOaid()

View File

@ -1,6 +1,6 @@
import { RouterUrls } from '../common/RouterUrls';
import { MediaRecordEntity } from '../entity/MediaRecordEntity';
import { router } from '@kit.ArkUI';
import { LevelMode, router } from '@kit.ArkUI';
import { AppUtil, DateUtil, DisplayUtil, StrUtil } from '@pura/harmony-utils';
import { ShareManager } from '../manager/ShareManager';
import { Want } from '@kit.AbilityKit';
@ -10,6 +10,7 @@ import { WantUtils } from '../utils/WantUtils';
import { media } from '@kit.MediaKit';
import { fileIo } from '@kit.CoreFileKit';
import { image } from '@kit.ImageKit';
import { AudioPlayerDialog } from '../dialog/AudioPlayerDialog';
@ComponentV2
export struct VideoRecordItemView {
@ -158,6 +159,29 @@ export struct ImageRecordItemView {
@ComponentV2
export struct AudioRecordItemView {
@Param media?: MediaRecordEntity = undefined;
@Param index: number = 0;
private audioPlayerDialogController?: CustomDialogController | null;
aboutToDisappear() {
this.audioPlayerDialogController = null
}
showBindPhoneDialog(index: number) {
this.audioPlayerDialogController = new CustomDialogController({
builder: AudioPlayerDialog({
index: index
}),
width: '100%',
cornerRadius: { topLeft: 16, topRight: 16 },
autoCancel: false,
maskColor: '#CC000000',
levelMode: LevelMode.EMBEDDED,
backgroundBlurStyle: BlurStyle.NONE,
alignment: DialogAlignment.Bottom
})
this.audioPlayerDialogController.open();
}
formatTime(time: number): string {
let minute: number = 0
@ -235,12 +259,7 @@ export struct AudioRecordItemView {
.height(74)
.padding({left: 14, right: 14})
.onClick(() => {
this.getUIContext()
.getRouter()
.pushUrl({
url: RouterUrls.AUDIO_PLAYER_PAGE,
params: { title: this.media?.name, uri: this.media?.uri, showActions: true }
}, router.RouterMode.Single)
this.showBindPhoneDialog(this.index)
})
}
}

View File

@ -1,12 +1,12 @@
import { plainToInstance } from "class-transformer";
import { VipPermissionEntity } from "../entity/VipPermissionEntity";
import { VipAuthEntity } from "../entity/VipAuthEntity";
import { apiService } from "../net/ApiService";
import { ToastUtils } from "../utils/ToastUtils";
import { BaseViewModel } from "./BaseViewModel";
@ObservedV2
export class AuthViewModel extends BaseViewModel {
@Trace permissionInfo?: VipPermissionEntity
@Trace authInfo?: VipAuthEntity
@Trace errorCode: number = 0;
async checkVip() {
@ -14,7 +14,7 @@ export class AuthViewModel extends BaseViewModel {
try {
const result = await apiService.checkPermission('download');
if (result.isSuccess()) {
this.permissionInfo = plainToInstance(VipPermissionEntity, result.data);
this.authInfo = plainToInstance(VipAuthEntity, result.data);
} else {
this.errorCode = result.code
ToastUtils.show(result.message, true);

View File

@ -60,6 +60,7 @@ export class FeedbackViewModel extends BaseViewModel {
FileUtil.readSync(file2.fd, buffer);
FileUtil.fsyncSync(file2.fd);
FileUtil.closeSync(file2.fd);
FileUtil.closeSync(file);
const base64Str = Base64Util.encodeToStrSync(new Uint8Array(buffer))

View File

@ -1,6 +1,6 @@
import { plainToInstance } from 'class-transformer';
import { MaterialInfoEntity } from '../entity/MaterialInfoEntity';
import { VipPermissionEntity } from '../entity/VipPermissionEntity';
import { VipAuthEntity } from '../entity/VipAuthEntity';
import { apiService } from '../net/ApiService';
import { ToastUtils } from '../utils/ToastUtils';
import { BaseViewModel } from './BaseViewModel';
@ -9,7 +9,7 @@ import { BaseViewModel } from './BaseViewModel';
export class TakeMaterialViewModel extends BaseViewModel {
@Trace materialInfo?: MaterialInfoEntity;
@Trace analysisInfo?: MaterialInfoEntity;
@Trace permissionInfo?: VipPermissionEntity;
@Trace permissionInfo?: VipAuthEntity;
@Trace errorCode: number = 0;
private intervalId = 0
@ -74,7 +74,7 @@ export class TakeMaterialViewModel extends BaseViewModel {
try {
const result = await apiService.checkPermission('download');
if (result.isSuccess()) {
this.permissionInfo = plainToInstance(VipPermissionEntity, result.data);
this.permissionInfo = plainToInstance(VipAuthEntity, result.data);
} else {
this.errorCode = result.code
ToastUtils.show(result.message, true);

View File

@ -63,6 +63,7 @@ export class UserSettingsViewModel extends BaseViewModel {
FileUtil.readSync(file2.fd, buffer);
FileUtil.fsyncSync(file2.fd);
FileUtil.closeSync(file2.fd);
FileUtil.closeSync(file);
const base64Str = Base64Util.encodeToStrSync(new Uint8Array(buffer))

View File

@ -1,5 +1,5 @@
import { plainToInstance } from 'class-transformer';
import { VipPermissionEntity } from '../entity/VipPermissionEntity';
import { VipAuthEntity } from '../entity/VipAuthEntity';
import { WxVideoEntity } from '../entity/WxVideoEntity';
import { WxVideoServiceEntity } from '../entity/WxVideoServiceEntity';
import { apiService } from '../net/ApiService';
@ -10,7 +10,7 @@ import { BaseViewModel } from './BaseViewModel';
export class WxVideoViewModel extends BaseViewModel {
@Trace wxVideo?: WxVideoEntity;
@Trace deleteVideo?: object;
@Trace permissionInfo?: VipPermissionEntity;
@Trace permissionInfo?: VipAuthEntity;
@Trace errorCode: number = 0;
@Trace wxService?: WxVideoServiceEntity
@Trace wxUserinfo?: object
@ -63,7 +63,7 @@ export class WxVideoViewModel extends BaseViewModel {
try {
const result = await apiService.checkPermission('download');
if (result.isSuccess()) {
this.permissionInfo = plainToInstance(VipPermissionEntity, result.data);
this.permissionInfo = plainToInstance(VipAuthEntity, result.data);
} else {
this.errorCode = result.code
ToastUtils.show(result.message, true);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -12,11 +12,7 @@
"pages/main/home/tools/AddWatermarkPage",
"pages/main/home/tools/RemoveWatermarkPage",
"pages/main/home/tools/MD5ResetPage",
"pages/main/home/tools/VideoReversePage",
"pages/main/home/tools/VideoMirrorPage",
"pages/main/home/tools/ClipVideoPage",
"pages/main/home/tools/RemoveAudioPage",
"pages/main/home/tools/AddAudioPage",
"pages/main/home/tools/VideoToAudioPage",
"pages/main/home/tools/ImageMergePage",
"pages/main/home/tools/VideoToTextPage",