修复禅道上的bug

This commit is contained in:
wangyu 2026-03-23 18:25:22 +08:00
parent 40e0c9f3e1
commit a1c33b320e
28 changed files with 1103 additions and 218 deletions

View File

@ -0,0 +1,147 @@
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { PhotoHelper } from '@pura/picker_utils';
import { ToastUtils } from '../utils/ToastUtils';
import { DatePickerDialog } from './DatePickerDialog';
@CustomDialog
export struct CustomWatermarkDialog {
confirm: (uri: string, title: string, date: Date, address: string) => void = () => {};
@State imageUri?: string = undefined
@State date?: Date = undefined
private title?: string = undefined
private address?: string = undefined
private controller: CustomDialogController;
getFormatData(date: Date): string {
let year = date.getFullYear()
let month = date.getMonth() + 1
let day = date.getDate()
return `${year}.${month}.${day}`
}
build() {
Column() {
RelativeContainer() {
Text('加水印')
.width('auto')
.fontColor($r('app.color.color_212226'))
.fontSize(18)
.fontWeight(FontWeight.Medium)
.alignRules( {
left: {anchor: '__container__', align: HorizontalAlign.Start},
right: {anchor: '__container__', align: HorizontalAlign.End}
})
Image($r('app.media.ic_close')).width(20).height(20)
.alignRules( {
top: {anchor: '__container__', align: VerticalAlign.Top},
right: {anchor: '__container__', align: HorizontalAlign.End}
})
.margin({ right: 16 })
.onClick(() => {
this.controller.close()
})
}
.width('100%')
.height(30)
Column() {
Row() {
Text('图片').fontColor($r('app.color.color_666666')).fontSize(15)
Blank().layoutWeight(1)
Image(this.imageUri ? this.imageUri : $r('app.media.ic_add_watermark_image')).width(30).height(30)
Image($r('app.media.ic_arrow_dp22')).width(22).height(22)
}.height(54)
.onClick(() => {
PhotoHelper.selectEasy({
MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE,
maxSelectNumber: 1,
isPhotoTakingSupported: false,
isEditSupported: false,
isOriginalSupported: false
})
.then((uris) => {
if (uris.length != 0) {
this.imageUri = uris[0]
}
})
})
Divider().strokeWidth(1).color($r('app.color.color_eeeeee'))
Row() {
Text('标题').fontColor($r('app.color.color_666666')).fontSize(15)
TextInput({placeholder: '请输入'}).fontColor($r('app.color.color_1a1a1a')).fontSize(15).placeholderColor('#A6A8B2')
.layoutWeight(1)
.backgroundColor(Color.Transparent)
.textAlign(TextAlign.End)
.padding({right: 5})
.onChange((text) => {
this.title = text
})
Image($r('app.media.ic_arrow_dp22')).width(22).height(22)
}.height(54)
Divider().strokeWidth(1).color($r('app.color.color_eeeeee'))
Row() {
Text('时间').fontColor($r('app.color.color_666666')).fontSize(15)
Blank().layoutWeight(1)
Text(this.date ? this.getFormatData(this.date) : '请选择').fontColor(this.date ? $r('app.color.color_1a1a1a') : '#A6A8B2').fontSize(15).padding({right: 5})
Image($r('app.media.ic_arrow_dp22')).width(22).height(22)
}.height(54)
.onClick(() => {
DatePickerDialog.show(this.getUIContext(), {selectedDate: new Date(), confirm: (date) => {
this.date = date
}})
})
Divider().strokeWidth(1).color($r('app.color.color_eeeeee'))
Row() {
Text('地点').fontColor($r('app.color.color_666666')).fontSize(15)
TextInput({placeholder: '请输入'}).fontColor($r('app.color.color_1a1a1a')).fontSize(15).placeholderColor('#A6A8B2')
.layoutWeight(1)
.backgroundColor(Color.Transparent)
.textAlign(TextAlign.End)
.padding({right: 5})
.onChange((text) => {
this.address = text
})
Image($r('app.media.ic_arrow_dp22')).width(22).height(22)
}.height(54)
}
.padding({left: 16, right: 16})
.margin({top: 20, bottom: 50})
Button('确定', { type: ButtonType.Capsule, stateEffect: true })
.fontColor(Color.White)
.fontSize(16)
.width('90%')
.height(46)
.margin({ top: 30 })
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
if (!this.imageUri) {
ToastUtils.show('请选择图片')
return
}
if (!this.title) {
ToastUtils.show('请输入标题')
return
}
if (!this.date) {
ToastUtils.show('请选择时间')
return
}
if (!this.address) {
ToastUtils.show('请输入地点')
return
}
if (this.confirm) {
this.confirm(this.imageUri, this.title, this.date, this.address)
}
this.controller.close()
})
}
.padding({ top: 30, bottom: 22 })
.backgroundColor(Color.White)
.width('100%')
}
}

View File

@ -0,0 +1,90 @@
import { ComponentContent } from '@kit.ArkUI';
import { StrUtil } from '@pura/harmony-utils';
import { DialogCallback } from '../callback/DialogCallback';
import { ToastUtils } from '../utils/ToastUtils';
export declare class DatePickerDialogOption {
selectedDate: Date;
confirm?: (date: Date) => void;
}
@Builder
function defaultBuilder(option: DatePickerDialogOption) {
Column() {
Row() {
Text('取消').fontColor($r('app.color.color_999999')).fontSize(14)
.onClick(() => {
DatePickerDialog.dismiss()
})
Blank().layoutWeight(1)
Text('确定').fontColor($r('app.color.color_466afd')).fontSize(14)
.onClick(() => {
if (option.confirm) {
option.confirm(option.selectedDate)
}
DatePickerDialog.dismiss()
})
}.padding({ left: 16, right: 16 })
DatePicker({
start: new Date('1970-1-1'),
end: new Date('2100-1-1'),
selected: option.selectedDate
})
.onDateChange((value: Date) => {
option.selectedDate = value
})
.margin({ top: 20, bottom: 30 })
}
.padding({ top: 22, bottom: 22 })
.borderRadius(20)
.backgroundColor($r('app.color.window_background'))
.width('100%')
}
export class DatePickerDialog {
context: UIContext | null = null;
contentNode: ComponentContent<Object> | null = null;
private static instance: DatePickerDialog | null = null;
static show(context: UIContext, option: DatePickerDialogOption) {
if (DatePickerDialog.instance === null) {
DatePickerDialog.instance = new DatePickerDialog(context, option);
}
DatePickerDialog.instance?.openDialog();
}
static dismiss() {
if (DatePickerDialog.instance !== null) {
DatePickerDialog.instance.closeDialog();
DatePickerDialog.instance = null;
}
}
constructor(context: UIContext, option: DatePickerDialogOption) {
this.context = context;
this.contentNode = new ComponentContent(context, wrapBuilder(defaultBuilder), option);
}
openDialog() {
if (this.context !== null && this.contentNode !== null) {
this.context.getPromptAction().openCustomDialog(this.contentNode, {
maskColor: '#CC000000',
autoCancel: false,
alignment: DialogAlignment.Bottom
})
.then(() => {
console.info('OpenCustomDialog complete.');
})
}
}
closeDialog() {
if (this.context !== null && this.contentNode !== null) {
this.context.getPromptAction().closeCustomDialog(this.contentNode)
.then(() => {
console.info('CloseCustomDialog complete.');
})
}
}
}

View File

@ -24,131 +24,136 @@ export declare class DownloadDialogOption {
@Builder @Builder
function defaultBuilder(option: DownloadDialogOption) { function defaultBuilder(option: DownloadDialogOption) {
Column() { Stack({alignContent: Alignment.Top}) {
Text((option.status === DownloadStatus.DOWNLOADING ? '下载中' : Image($r('app.media.ic_tip_dialog_top_bg')).width('100%').aspectRatio(2.72)
option.status === DownloadStatus.VIDEO_DOWNLOADING ? '视频下载中' :
option.status === DownloadStatus.AUDIO_DOWNLOADING ? '音频下载中' : '处理中') +
(option.totalCount > 1 ? ` ${option.index + 1}/${option.totalCount}` : ''))
.fontColor($r('app.color.color_212226'))
.fontSize(16)
.visibility(option.status === DownloadStatus.COMPLETED ? Visibility.None : Visibility.Visible)
Image(option.status === DownloadStatus.COMPLETED ? $r('app.media.ic_completed') : $r('app.media.ic_downloading')) Column() {
.width(80) Text((option.status === DownloadStatus.DOWNLOADING ? '下载中' :
.height(80) option.status === DownloadStatus.VIDEO_DOWNLOADING ? '视频下载中' :
.margin({ top: 20 }) option.status === DownloadStatus.AUDIO_DOWNLOADING ? '音频下载中' : '处理中') +
(option.totalCount > 1 ? ` ${option.index + 1}/${option.totalCount}` : ''))
.fontColor($r('app.color.color_212226'))
.fontSize(24)
.fontFamily('ysbth')
.visibility(option.status === DownloadStatus.COMPLETED ? Visibility.None : Visibility.Visible)
Stack() { Image(option.status === DownloadStatus.COMPLETED ? $r('app.media.ic_completed') : $r('app.media.ic_downloading'))
Column() { .width(80)
Stack({ alignContent: Alignment.Start }) { .height(80)
Progress({ value: option.progress, total: option.totalSize, type: ProgressType.Linear }) .margin({ top: 20 })
.width('100%')
.style({ strokeWidth: 12, strokeRadius: 6 })
.color($r('app.color.color_466afd'))
// .colorBlend('#F1F2F6')
.borderRadius(6)
Text(FormatUtil.getFormatPercentage(option.progress / option.totalSize, 1)) Stack() {
.width(40) Column() {
.height(18) Stack({ alignContent: Alignment.Start }) {
.textAlign(TextAlign.Center) Progress({ value: option.progress, total: option.totalSize, type: ProgressType.Linear })
.fontColor(Color.White) .width('100%')
.fontSize(10) .style({ strokeWidth: 12, strokeRadius: 6 })
.borderRadius(10) .color($r('app.color.color_466afd'))
.borderWidth(1) // .colorBlend('#F1F2F6')
.borderColor(Color.White) .borderRadius(6)
.backgroundColor($r("app.color.color_466afd"))
.translate({ x: (AppUtil.getUIContext().px2vp(DisplayUtil.getWidth()) * 0.8 - 80) * option.progress / option.totalSize })
}
Text(`${FileUtil.getFormatFileSize(option.progress)}/${option.totalSize !== 0 ? Text(FormatUtil.getFormatPercentage(option.progress / option.totalSize, 1))
FileUtil.getFormatFileSize(option.totalSize) : '获取中'}`) .width(40)
.fontColor($r('app.color.color_727686')) .height(18)
.fontSize(12) .textAlign(TextAlign.Center)
.fontColor(Color.White)
.fontSize(10)
.borderRadius(10)
.borderWidth(1)
.borderColor(Color.White)
.backgroundColor($r("app.color.color_466afd"))
.translate({ x: (AppUtil.getUIContext().px2vp(DisplayUtil.getWidth()) * 0.8 - 80) * option.progress / option.totalSize })
}
Text(`${FileUtil.getFormatFileSize(option.progress)}/${option.totalSize !== 0 ?
FileUtil.getFormatFileSize(option.totalSize) : '获取中'}`)
.fontColor($r('app.color.color_727686'))
.fontSize(12)
.margin({ top: 16 })
.visibility(option.status === DownloadStatus.PROCESSING ? Visibility.Hidden : Visibility.Visible)
Row() {
Button('取消下载', { type: ButtonType.Capsule, stateEffect: true })
.width(110)
.height(36)
.backgroundColor('#F1F2F6')
.fontColor('#80859B')
.fontSize(15)
.onClick(() => {
if (option.callback?.cancel) {
option.callback.cancel()
}
DownloadDialog.dismiss()
})
Button('后台下载', { type: ButtonType.Capsule, stateEffect: true })
.width(110)
.height(36)
.backgroundColor($r('app.color.color_466afd'))
.fontColor(Color.White)
.fontSize(15)
.margin({ left: 10 })
.onClick(() => {
if (option.callback?.confirm) {
option.callback.confirm()
}
DownloadDialog.dismiss()
})
.visibility(Visibility.None)
}
.margin({ top: 16 }) .margin({ top: 16 })
.visibility(option.status === DownloadStatus.PROCESSING ? Visibility.Hidden : Visibility.Visible)
Row() {
Button('取消下载', { type: ButtonType.Capsule, stateEffect: true })
.width(110)
.height(36)
.backgroundColor('#F1F2F6')
.fontColor('#80859B')
.fontSize(15)
.onClick(() => {
if (option.callback?.cancel) {
option.callback.cancel()
}
DownloadDialog.dismiss()
})
Button('后台下载', { type: ButtonType.Capsule, stateEffect: true })
.width(110)
.height(36)
.backgroundColor($r('app.color.color_466afd'))
.fontColor(Color.White)
.fontSize(15)
.margin({ left: 10 })
.onClick(() => {
if (option.callback?.confirm) {
option.callback.confirm()
}
DownloadDialog.dismiss()
})
.visibility(Visibility.None)
} }
.margin({ top: 16 }) .margin({ top: 20 })
} .visibility(option.status === DownloadStatus.COMPLETED ? Visibility.None : Visibility.Visible)
.margin({ top: 20 })
.visibility(option.status === DownloadStatus.COMPLETED ? Visibility.None : Visibility.Visible)
Column() { Column() {
Text(option.isAudio ? '已保存到本地' : '已保存到系统相册中').fontColor($r('app.color.color_466afd')).fontSize(16) Text(option.isAudio ? '已保存到本地' : '已保存到系统相册中').fontColor($r('app.color.color_466afd')).fontSize(16)
Text(option.isAudio ? '文件管理/我的手机/Download/素材魔方' : '文件管理/我的手机/Download/图库') Text(option.isAudio ? '文件管理/我的手机/Download/素材魔方' : '文件管理/我的手机/Download/图库')
.fontColor($r('app.color.color_727686')) .fontColor($r('app.color.color_727686'))
.fontSize(12) .fontSize(12)
.margin({ top: 10 }) .margin({ top: 10 })
Row() { Row() {
Button('取消', { type: ButtonType.Capsule, stateEffect: true }) Button('取消', { type: ButtonType.Capsule, stateEffect: true })
.width(110) .width(110)
.height(36) .height(36)
.backgroundColor('#F1F2F6') .backgroundColor('#F1F2F6')
.fontColor('#80859B') .fontColor('#80859B')
.fontSize(15) .fontSize(15)
.onClick(() => { .onClick(() => {
if (option.callback?.cancel) { if (option.callback?.cancel) {
option.callback.cancel() option.callback.cancel()
} }
DownloadDialog.dismiss() DownloadDialog.dismiss()
}) })
Blank().width(10) Blank().width(10)
Button('前往查看', { type: ButtonType.Capsule, stateEffect: true }) Button('前往查看', { type: ButtonType.Capsule, stateEffect: true })
.width(110) .width(110)
.height(36) .height(36)
.backgroundColor($r('app.color.color_466afd')) .backgroundColor($r('app.color.color_466afd'))
.fontColor(Color.White) .fontColor(Color.White)
.fontSize(15) .fontSize(15)
.onClick(() => { .onClick(() => {
if (option.callback?.confirm) { if (option.callback?.confirm) {
option.callback.confirm() option.callback.confirm()
} }
DownloadDialog.dismiss() DownloadDialog.dismiss()
}) })
}
.margin({ top: 16 })
} }
.margin({ top: 16 }) .margin({ top: 20 })
.visibility(option.status === DownloadStatus.COMPLETED ? Visibility.Visible : Visibility.None)
} }
.margin({ top: 20 })
.visibility(option.status === DownloadStatus.COMPLETED ? Visibility.Visible : Visibility.None)
} }
.padding(20)
} }
.width('80%') .width('80%')
.borderRadius(10) .borderRadius(16)
.backgroundColor(Color.White) .backgroundColor(Color.White)
.padding(20)
} }
export class DownloadDialog { export class DownloadDialog {

View File

@ -0,0 +1,77 @@
@CustomDialog
export struct ImageWatermarkDialog {
onRadiusChanged: (radius: number) => void = () => {};
confirm: (radius: number) => void = () => {};
private controller: CustomDialogController;
@State radius: number = 0;
build() {
Column() {
RelativeContainer() {
Text('加图片')
.width('auto')
.fontColor($r('app.color.color_212226'))
.fontSize(18)
.fontWeight(FontWeight.Medium)
.alignRules( {
left: {anchor: '__container__', align: HorizontalAlign.Start},
right: {anchor: '__container__', align: HorizontalAlign.End}
})
Image($r('app.media.ic_close')).width(20).height(20)
.alignRules( {
top: {anchor: '__container__', align: VerticalAlign.Top},
right: {anchor: '__container__', align: HorizontalAlign.End}
})
.margin({ right: 16 })
.onClick(() => {
this.controller.close()
})
}
.width('100%')
.height(30)
Row() {
Text('圆角').fontColor($r('app.color.color_212226')).fontSize(14).margin({left: 16})
Slider({
value: this.radius,
min: 0,
max: 100
})
.blockColor($r('app.color.color_466afd'))
.trackColor($r('app.color.color_eeeeee'))
.onChange((value: number, mode: SliderChangeMode) => {
this.radius = value
if (this.onRadiusChanged) {
this.onRadiusChanged(value)
}
})
.layoutWeight(1)
Text(`${this.radius}`).width(25).fontColor($r('app.color.color_999999')).fontSize(14).margin({right: 16})
}
.width('100%')
.margin({top: 75, bottom: 100})
Button('确定', { type: ButtonType.Capsule, stateEffect: true })
.fontColor(Color.White)
.fontSize(16)
.width('90%')
.height(46)
.margin({ top: 30 })
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
if (this.confirm) {
this.confirm(this.radius)
}
this.controller.close()
})
}
.padding({ top: 30, bottom: 22 })
.backgroundColor(Color.White)
.width('100%')
}
}

View File

@ -10,71 +10,78 @@ export struct LoginTipDialog {
} }
build() { build() {
RelativeContainer() { Stack({alignContent: Alignment.TopStart}) {
Image($r('app.media.ic_tip_dialog_top_bg')).width('100%').aspectRatio(2.72) RelativeContainer() {
Image($r('app.media.ic_tip_dialog_top_bg')).width('100%').aspectRatio(2.72)
Column() { Column() {
Text('温馨提示') Text('温馨提示')
.fontColor($r('app.color.color_212226')) .fontColor($r('app.color.color_212226'))
.fontSize(24) .fontSize(24)
.fontFamily('ysbth') .fontFamily('ysbth')
.margin({ top: 20 }) .margin({ top: 20 })
Text() { Text() {
Span('登录之前需查看并同意') Span('登录之前需查看并同意')
Span('《用户协议》') Span('《用户协议》')
.fontColor($r("app.color.color_466afd")) .fontColor($r("app.color.color_466afd"))
.onClick(() => { .onClick(() => {
this.getUIContext().getRouter().pushUrl({ this.getUIContext().getRouter().pushUrl({
url: RouterUrls.WEB_PAGE, params: { url: RouterUrls.WEB_PAGE, params: {
title: '用户协议', title: '用户协议',
url: Constants.USER_AGREEMENT url: Constants.USER_AGREEMENT
} }
})
}) })
}) Span('和')
Span('和') Span('《隐私政策》')
Span('《隐私政策》') .fontColor($r("app.color.color_466afd"))
.fontColor($r("app.color.color_466afd")) .onClick(() => {
.onClick(() => { this.getUIContext().getRouter().pushUrl({
this.getUIContext().getRouter().pushUrl({ url: RouterUrls.WEB_PAGE, params: {
url: RouterUrls.WEB_PAGE, params: { title: '隐私政策',
title: '隐私政策', url: Constants.PRIVACY_POLICY
url: Constants.PRIVACY_POLICY }
} })
}) })
}
.fontColor($r('app.color.color_727686'))
.fontSize(14)
.textAlign(TextAlign.Center)
.margin({ top: 20, left: 20, right: 20 })
Button('同意', { type: ButtonType.Capsule, stateEffect: true })
.width(110)
.height(40)
.fontColor(Color.White)
.fontSize(16)
.backgroundColor($r("app.color.color_466afd"))
.margin({ top: 20, bottom: 20 })
.onClick(() => {
this.controller.close();
if (this.confirm) {
this.confirm();
}
}) })
} }
.fontColor($r('app.color.color_727686')) .width('100%')
.fontSize(14)
.textAlign(TextAlign.Center)
.margin({ top: 20, left: 20, right: 20 })
Button('同意', { type: ButtonType.Capsule, stateEffect: true }) Image($r('app.media.ic_close_dialog')).width(18).height(18)
.width(110) .margin({top: 10, right: 10})
.height(40) .alignRules({
.fontColor(Color.White) right: {anchor: '__container__', align: HorizontalAlign.End}
.fontSize(16) })
.backgroundColor($r("app.color.color_466afd"))
.margin({ top: 20, bottom: 20 })
.onClick(() => { .onClick(() => {
this.controller.close(); this.controller.close()
if (this.confirm) {
this.confirm();
}
}) })
} }
.width('100%')
.height('auto')
.borderRadius(20)
.backgroundColor(Color.White)
.margin({top: 26})
Image($r('app.media.ic_close_dialog')).width(18).height(18) Image($r('app.media.ic_notify_icon')).width(87).height(66).margin({left: 4})
.margin({top: 10, right: 10})
.alignRules({
right: {anchor: '__container__', align: HorizontalAlign.End}
})
.onClick(() => {
this.controller.close()
})
} }
.height('auto')
.borderRadius(20)
.backgroundColor(Color.White)
} }
} }

View File

@ -0,0 +1,106 @@
import { getColorList, TextColorEntity } from '../entity/TextColorEntity';
import { ToastUtils } from '../utils/ToastUtils';
@CustomDialog
export struct TextWatermarkDialog {
confirm: (text: string, color: string) => void = () => {};
private controller: CustomDialogController;
private content?: string;
@State colorList: Array<TextColorEntity> = []
@State color?: string = undefined;
aboutToAppear(): void {
this.colorList = getColorList()
this.color = this.colorList[0].color
}
build() {
Column() {
RelativeContainer() {
Text('加文字')
.width('auto')
.fontColor($r('app.color.color_212226'))
.fontSize(18)
.fontWeight(FontWeight.Medium)
.alignRules( {
left: {anchor: '__container__', align: HorizontalAlign.Start},
right: {anchor: '__container__', align: HorizontalAlign.End}
})
Image($r('app.media.ic_close')).width(20).height(20)
.alignRules( {
top: {anchor: '__container__', align: VerticalAlign.Top},
right: {anchor: '__container__', align: HorizontalAlign.End}
})
.margin({ right: 16 })
.onClick(() => {
this.controller.close()
})
}
.width('100%')
.height(30)
TextInput({ placeholder: '请输入文字水印...' })
.width('90%')
.height(48)
.fontColor($r('app.color.color_1a1a1a'))
.fontSize(15)
.placeholderColor('#A6A8B2')
.placeholderFont({ size: 15 })
.maxLength(12)
.backgroundColor(Color.Transparent)
.borderWidth(1)
.borderColor('#C3C6D4')
.borderRadius(8)
.margin({ top: 16 })
.onChange((content) => {
this.content = content
})
List() {
ForEach(this.colorList, (item: TextColorEntity) => {
ListItem(){
Text()
.width('100%')
.height('100%')
.backgroundColor(item.color)
.borderWidth(1)
.borderColor(this.color === item.color ? $r('app.color.color_466afd') : item.color === '#FFFFFF' ? '#C3C6D4' : Color.Transparent)
}
.width(30)
.height(30)
.onClick(() => {
this.color = item.color
})
})
}
.width('auto')
.height(30)
.listDirection(Axis.Horizontal)
.margin({top: 40})
Button('确定', { type: ButtonType.Capsule, stateEffect: true })
.fontColor(Color.White)
.fontSize(16)
.width('90%')
.height(46)
.margin({ top: 30 })
.backgroundColor($r('app.color.color_466afd'))
.onClick(() => {
if (!this.content) {
ToastUtils.show('请输入文字')
} else {
if (this.confirm) {
this.confirm(this.content, this.color!!);
}
this.controller.close()
}
})
}
.padding({ top: 30, bottom: 22 })
.backgroundColor(Color.White)
.width('100%')
}
}

View File

@ -23,10 +23,10 @@ export function homeMenuList(): ArrayList<MenuEntity> {
return list; return list;
} }
export function mineMenuList(): ArrayList<MenuEntity> { export function mineMenuList(showDiamond: boolean): ArrayList<MenuEntity> {
let list = new ArrayList<MenuEntity>() let list = new ArrayList<MenuEntity>()
list.add(new MenuEntity($r('app.media.ic_mine_icon1'), "提取记录", "history")) list.add(new MenuEntity($r('app.media.ic_mine_icon1'), "提取记录", "history"))
if (LoginManager.getUserInfo()?.vip !== 1) { if (showDiamond) {
list.add(new MenuEntity($r('app.media.ic_mine_icon2'), "次数兑换", "diamond")) list.add(new MenuEntity($r('app.media.ic_mine_icon2'), "次数兑换", "diamond"))
} }
list.add(new MenuEntity($r('app.media.ic_mine_icon3'), "意见反馈", "feedback")) list.add(new MenuEntity($r('app.media.ic_mine_icon3'), "意见反馈", "feedback"))

View File

@ -0,0 +1,24 @@
export class TextColorEntity {
color: string = '';
isChecked: boolean = false;
constructor(color: string, isChecked: boolean = false) {
this.color = color
this.isChecked = isChecked
}
}
export function getColorList(): Array<TextColorEntity> {
const list = new Array<TextColorEntity>()
list.push(new TextColorEntity('#FF9600'))
list.push(new TextColorEntity('#F8F200'))
list.push(new TextColorEntity('#00EF00'))
list.push(new TextColorEntity('#00FFEB'))
list.push(new TextColorEntity('#0088FE'))
list.push(new TextColorEntity('#7E30FF'))
list.push(new TextColorEntity('#FF43BE'))
list.push(new TextColorEntity('#FF1B42'))
list.push(new TextColorEntity('#FFFFFF'))
list.push(new TextColorEntity('#000000'))
return list
}

View File

@ -44,6 +44,8 @@ instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
let method = config.method?.toLowerCase(); let method = config.method?.toLowerCase();
if (method === "post" || method === "put") { if (method === "post" || method === "put") {
config.headers.set("Content-Type", "application/json; charset=utf-8"); config.headers.set("Content-Type", "application/json; charset=utf-8");
} else if (method === 'delete') {
config.headers.set("Content-Type", "application/x-www-form-urlencoded");
} }
} }
return config; return config;
@ -123,6 +125,12 @@ instance.interceptors.response.use((response: AxiosResponse) => {
break; break;
} }
} }
} else {
let newResponse: Record<string, Object> = {
'code': 0,
'data': dataString
}
dataString = JSON.stringify(newResponse)
} }
} }
} }

View File

@ -14,21 +14,25 @@ import { media } from '@kit.MediaKit'
import { MediaUtils } from '../../../../utils/MediaUtils' import { MediaUtils } from '../../../../utils/MediaUtils'
import { MP4Parser } from '@ohos/mp4parser' import { MP4Parser } from '@ohos/mp4parser'
import { TipDialog } from '../../../../dialog/TipDialog' import { TipDialog } from '../../../../dialog/TipDialog'
import { WaterMarkerView } from '../../../../view/WaterMarkerView' import { WatermarkView } from '../../../../view/WatermarkView'
import { EditTextDialog } from '../../../../dialog/EditTextDialog'
import { image } from '@kit.ImageKit' import { image } from '@kit.ImageKit'
import { avSessionManager } from '../../../../manager/AVSessionManager' import { avSessionManager } from '../../../../manager/AVSessionManager'
import { AuthViewModel } from '../../../../viewModel/AuthViewModel' import { AuthViewModel } from '../../../../viewModel/AuthViewModel'
import { LoginManager } from '../../../../manager/LoginGlobalManager' import { LoginManager } from '../../../../manager/LoginGlobalManager'
import { VipAuthEntity } from '../../../../entity/VipAuthEntity' import { VipAuthEntity } from '../../../../entity/VipAuthEntity'
import { RouterUrls } from '../../../../common/RouterUrls' import { RouterUrls } from '../../../../common/RouterUrls'
import { router } from '@kit.ArkUI' import { LevelMode, router } from '@kit.ArkUI'
import { EventReportManager } from '../../../../manager/EventReportManager' import { EventReportManager } from '../../../../manager/EventReportManager'
import { TextWatermarkDialog } from '../../../../dialog/TextWatermarkDialog'
import { ImageWatermarkDialog } from '../../../../dialog/ImageWatermarkDialog'
import { CustomWatermarkDialog } from '../../../../dialog/CustomWatermarkDialog'
import { CustomWatermarkView } from '../../../../view/CustomWatermarkView'
@Entry @Entry
@ComponentV2 @ComponentV2
struct AddWatermarkPage { struct AddWatermarkPage {
private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext())
private watermarkDialogController?: CustomDialogController | null;
private controller: VideoController = new VideoController() private controller: VideoController = new VideoController()
private videoSize: media.PixelMapParams = { width: 0, height: 0 } private videoSize: media.PixelMapParams = { width: 0, height: 0 }
private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 } private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 }
@ -41,8 +45,16 @@ struct AddWatermarkPage {
@Local playerSize: media.PixelMapParams = { width: 0, height: 0 } @Local playerSize: media.PixelMapParams = { width: 0, height: 0 }
@Local showWatermark: boolean = false @Local showWatermark: boolean = false
@Local watermarkType: number = 0
@Local textContent: string = '' @Local textContent: string = ''
@Local textColor: string = ''
@Local imagePath: string = '' @Local imagePath: string = ''
@Local imageRadius: number = 0
@Local imageUri?: string = undefined
@Local date?: Date = undefined
@Local title?: string = undefined
@Local address?: string = undefined
@Monitor('viewModel.authInfo') @Monitor('viewModel.authInfo')
onPermissionInfoChange(monitor: IMonitor) { onPermissionInfoChange(monitor: IMonitor) {
@ -72,6 +84,10 @@ struct AddWatermarkPage {
} }
} }
aboutToDisappear(): void {
this.watermarkDialogController = null
}
doSave() { doSave() {
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
.then((saved) => { .then((saved) => {
@ -107,7 +123,7 @@ struct AddWatermarkPage {
let imageWidth = (vp2px(this.rect.width * this.videoSize.width!!) / this.playerSize.width!!) let imageWidth = (vp2px(this.rect.width * this.videoSize.width!!) / this.playerSize.width!!)
let imageHeight = (vp2px(this.rect.height * this.videoSize.height!!) / this.playerSize.height!!) let imageHeight = (vp2px(this.rect.height * this.videoSize.height!!) / this.playerSize.height!!)
this.getUIContext().getComponentSnapshot().get(StrUtil.isNotEmpty(this.textContent) ? 'textWaterMarker' : 'imageWaterMarker') this.getUIContext().getComponentSnapshot().get(this.watermarkType === 1 ? 'customWatermark' : this.watermarkType === 2 ? 'textWatermark' : 'imageWatermark')
.then(async (image: image.PixelMap) => { .then(async (image: image.PixelMap) => {
let imagePath = await ImageUtil.savePixelMap(image, FileUtil.getCacheDirPath(), `cache_${systemDateTime.getTime()}.png`) let imagePath = await ImageUtil.savePixelMap(image, FileUtil.getCacheDirPath(), `cache_${systemDateTime.getTime()}.png`)
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4` let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
@ -143,11 +159,20 @@ struct AddWatermarkPage {
.then((uris) => { .then((uris) => {
if (uris.length != 0) { if (uris.length != 0) {
this.isSuccess = false this.isSuccess = false
this.watermarkType = 0
this.controller.reset()
this.uri = uris[0] this.uri = uris[0]
this.showWatermark = false this.showWatermark = false
this.textContent = '' this.textContent = ''
this.textColor = ''
this.imagePath = '' this.imagePath = ''
this.imageRadius = 0
this.imageUri = ''
this.title = ''
this.date = undefined
this.address = ''
MediaUtils.getVideoSize(this.uri) MediaUtils.getVideoSize(this.uri)
.then((size) => { .then((size) => {
@ -161,6 +186,68 @@ struct AddWatermarkPage {
}) })
} }
showCustomWatermarkDialog() {
this.watermarkDialogController = new CustomDialogController({
builder: CustomWatermarkDialog({
confirm: (uri, title, date, address) => {
this.imageUri = uri
this.title = title
this.date = date
this.address = address
this.watermarkType = 1
this.showWatermark = true
}
}),
width: '100%',
cornerRadius: {topLeft: 20, topRight: 20},
autoCancel: false,
maskColor: '#CC000000',
levelMode: LevelMode.EMBEDDED,
backgroundBlurStyle: BlurStyle.NONE,
alignment: DialogAlignment.Bottom
})
this.watermarkDialogController.open();
}
showTextWatermarkDialog() {
this.watermarkDialogController = new CustomDialogController({
builder: TextWatermarkDialog({
confirm: (text, color) => {
this.textContent = text
this.textColor = color
this.watermarkType = 2
this.showWatermark = true
}
}),
width: '100%',
cornerRadius: {topLeft: 20, topRight: 20},
autoCancel: false,
maskColor: '#CC000000',
levelMode: LevelMode.EMBEDDED,
backgroundBlurStyle: BlurStyle.NONE,
alignment: DialogAlignment.Bottom
})
this.watermarkDialogController.open();
}
showImageWatermarkDialog() {
this.watermarkDialogController = new CustomDialogController({
builder: ImageWatermarkDialog({
onRadiusChanged: (radius) => {
this.imageRadius = radius
}
}),
width: '100%',
cornerRadius: {topLeft: 20, topRight: 20},
autoCancel: false,
maskColor: '#CC000000',
levelMode: LevelMode.EMBEDDED,
backgroundBlurStyle: BlurStyle.NONE,
alignment: DialogAlignment.Bottom
})
this.watermarkDialogController.open();
}
showDownloadDialog() { showDownloadDialog() {
DownloadDialog.show(this.getUIContext(), { DownloadDialog.show(this.getUIContext(), {
status: DownloadStatus.COMPLETED, status: DownloadStatus.COMPLETED,
@ -349,26 +436,59 @@ struct AddWatermarkPage {
}) })
if (this.showWatermark && this.uri && !this.isSuccess) { if (this.showWatermark && this.uri && !this.isSuccess) {
WaterMarkerView({ if (this.watermarkType === 1) {
content: this.textContent, CustomWatermarkView({
imagePath: this.imagePath, imageUri: this.imageUri,
onRectChange: (rect) => { title: this.title,
this.rect = rect date: this.date,
}, address: this.address,
onClose: () => { onRectChange: (rect) => {
this.showWatermark = false this.rect = rect
this.textContent = '' },
this.imagePath = '' onClose: () => {
} this.showWatermark = false
}) this.watermarkType = 0
.width(this.playerSize ? px2vp(this.playerSize.width) : '100%') this.imageUri = ''
.height(this.playerSize ? px2vp(this.playerSize.height) : '100%') this.title = ''
.alignRules({ this.date = undefined
left: { anchor: 'video', align: HorizontalAlign.Start }, this.address = ''
top: { anchor: 'video', align: VerticalAlign.Top }, }
right: { anchor: 'video', align: HorizontalAlign.End },
bottom: { anchor: 'video', align: VerticalAlign.Bottom }
}) })
.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 }
})
} else {
WatermarkView({
content: this.textContent,
textColor: this.textColor,
imagePath: this.imagePath,
imageRadius: this.imageRadius,
onRectChange: (rect) => {
this.rect = rect
},
onClose: () => {
this.showWatermark = false
this.watermarkType = 0
this.textContent = ''
this.textColor = ''
this.imagePath = ''
this.imageRadius = 0
}
})
.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 }
})
}
} }
} }
.layoutWeight(1) .layoutWeight(1)
@ -380,7 +500,10 @@ struct AddWatermarkPage {
} }
.layoutWeight(1) .layoutWeight(1)
.onClick(() => { .onClick(() => {
if (!this.showWatermark) {
this.controller.stop()
this.showCustomWatermarkDialog()
}
}) })
Column(){ Column(){
@ -391,10 +514,7 @@ struct AddWatermarkPage {
.onClick(() => { .onClick(() => {
if (!this.showWatermark) { if (!this.showWatermark) {
this.controller.stop() this.controller.stop()
EditTextDialog.show(this.getUIContext(), {title: '添加水印', hintText: '请输入文字', confirm: (text) => { this.showTextWatermarkDialog()
this.textContent = text
this.showWatermark = true
}})
} }
}) })
@ -417,7 +537,9 @@ struct AddWatermarkPage {
if (uris.length != 0) { if (uris.length != 0) {
this.isSuccess = false this.isSuccess = false
this.imagePath = uris[0] this.imagePath = uris[0]
this.watermarkType = 3
this.showWatermark = true this.showWatermark = true
this.showImageWatermarkDialog()
} }
}) })
} }
@ -443,6 +565,7 @@ struct AddWatermarkPage {
.fontWeight(FontWeight.Medium) .fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.color_466afd')) .backgroundColor($r('app.color.color_466afd'))
.onClick(() => { .onClick(() => {
this.controller.stop()
if (this.uri) { if (this.uri) {
if (this.showWatermark) { if (this.showWatermark) {
this.addWatermark() this.addWatermark()

View File

@ -1,7 +1,7 @@
import { PickerUtil } from '@pura/picker_utils' import { PickerUtil } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar' import { TitleBar } from '../../../../view/TitleBar'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit' import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, FileUtil, JSONUtil, PasteboardUtil } from '@pura/harmony-utils' import { AppUtil, FileUtil, JSONUtil, PasteboardUtil, StrUtil } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils' import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo } from '@kit.CoreFileKit' import { fileIo } from '@kit.CoreFileKit'
import { LoadingDialog } from '../../../../dialog/LoadingDialog' import { LoadingDialog } from '../../../../dialog/LoadingDialog'
@ -159,6 +159,7 @@ struct AudioToTextPage {
.then(async (uris) => { .then(async (uris) => {
if (uris.length != 0) { if (uris.length != 0) {
this.isSuccess = false this.isSuccess = false
await this.avPlayer?.reset()
this.audioUri = uris[0] this.audioUri = uris[0]
this.resultText = undefined this.resultText = undefined
// 打开相应的资源文件地址获取fd // 打开相应的资源文件地址获取fd
@ -257,7 +258,7 @@ struct AudioToTextPage {
} }
onBackPress(): boolean | void { onBackPress(): boolean | void {
if (this.isSuccess) { if (this.isSuccess && this.resultText) {
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未复制,是否确定退出?', callback: { TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未复制,是否确定退出?', callback: {
confirm: () => { confirm: () => {
this.getUIContext().getRouter().back() this.getUIContext().getRouter().back()
@ -338,6 +339,9 @@ struct AudioToTextPage {
Text('文本结果').fontColor($r('app.color.color_212226')).fontSize(15).fontWeight(FontWeight.Medium).margin({left: 4}) 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}) Divider().strokeWidth(1).color($r('app.color.color_eeeeee')).margin({top: 12})
Text('暂无数据').width('100%').layoutWeight(1).textAlign(TextAlign.Center).fontSize(14).fontColor($r('app.color.color_1a1a1a'))
.margin({top: 12})
.visibility(this.resultText === '' ? Visibility.Visible : Visibility.None)
Scroll() { Scroll() {
Text(this.resultText).width('100%').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 12}) Text(this.resultText).width('100%').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 12})
} }
@ -357,9 +361,9 @@ struct AudioToTextPage {
.layoutWeight(1) .layoutWeight(1)
.margin({top: 30, bottom: 20}) .margin({top: 30, bottom: 20})
.padding({left: 16, right: 16}) .padding({left: 16, right: 16})
.visibility(this.resultText ? Visibility.Visible : Visibility.None) .visibility(StrUtil.isNotNull(this.resultText) ? Visibility.Visible : Visibility.None)
Blank().layoutWeight(1).visibility(this.resultText ? Visibility.None : Visibility.Visible) Blank().layoutWeight(1).visibility(StrUtil.isNotNull(this.resultText) ? Visibility.None : Visibility.Visible)
Stack() { Stack() {
Button('确认处理', { type: ButtonType.Capsule, stateEffect: true }) Button('确认处理', { type: ButtonType.Capsule, stateEffect: true })
@ -370,13 +374,14 @@ struct AudioToTextPage {
.fontWeight(FontWeight.Medium) .fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.color_466afd')) .backgroundColor($r('app.color.color_466afd'))
.onClick(() => { .onClick(() => {
this.avPlayer?.pause()
if (this.audioUri) { if (this.audioUri) {
this.copyAudio() this.copyAudio()
} else { } else {
ToastUtils.show('请上传音频') ToastUtils.show('请上传音频')
} }
}) })
.visibility(!this.resultText ? Visibility.Visible : Visibility.None) .visibility(StrUtil.isNull(this.resultText) ? Visibility.Visible : Visibility.None)
Row() { Row() {
Button({ type: ButtonType.Capsule, stateEffect: true }) { Button({ type: ButtonType.Capsule, stateEffect: true }) {
@ -415,7 +420,7 @@ struct AudioToTextPage {
} }
}) })
} }
.visibility(this.resultText ? Visibility.Visible : Visibility.None) .visibility(StrUtil.isNotNull(this.resultText) ? Visibility.Visible : Visibility.None)
} }
.padding({left: 16, top: 9, right: 16, bottom: 30 }) .padding({left: 16, top: 9, right: 16, bottom: 30 })
.backgroundColor(Color.White) .backgroundColor(Color.White)

View File

@ -88,7 +88,7 @@ struct ImageMergePage {
const imageSource: image.ImageSource = image.createImageSource(compressedUri[0]) const imageSource: image.ImageSource = image.createImageSource(compressedUri[0])
let decodingOptions: image.DecodingOptions = { let decodingOptions: image.DecodingOptions = {
editable: true, editable: true,
desiredPixelFormat: image.PixelMapFormat.RGB_565, desiredPixelFormat: image.PixelMapFormat.RGBA_8888,
} }
let pixelMap = imageSource.createPixelMapSync(decodingOptions) let pixelMap = imageSource.createPixelMapSync(decodingOptions)
if (pixelMap) { if (pixelMap) {
@ -97,6 +97,7 @@ struct ImageMergePage {
pixelArray.push(pixelMap) pixelArray.push(pixelMap)
} else { } else {
ToastUtils.show('处理失败') ToastUtils.show('处理失败')
LoadingDialog.dismiss()
return return
} }
} }

View File

@ -121,6 +121,7 @@ struct MD5ResetPage {
.then((uris) => { .then((uris) => {
if (uris.length != 0) { if (uris.length != 0) {
this.isSuccess = false this.isSuccess = false
this.controller.reset()
this.uri = uris[0] this.uri = uris[0]
this.oldMd5 = this.fileMD5(this.uri) this.oldMd5 = this.fileMD5(this.uri)
this.newMd5 = undefined this.newMd5 = undefined
@ -363,6 +364,7 @@ struct MD5ResetPage {
.fontWeight(FontWeight.Medium) .fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.color_466afd')) .backgroundColor($r('app.color.color_466afd'))
.onClick(() => { .onClick(() => {
this.controller.stop()
if (this.uri) { if (this.uri) {
this.modifyMD5() this.modifyMD5()
} else { } else {

View File

@ -115,6 +115,7 @@ struct RemoveAudioPage {
.then((uris) => { .then((uris) => {
if (uris.length != 0) { if (uris.length != 0) {
this.isSuccess = false this.isSuccess = false
this.controller.reset()
this.uri = uris[0] this.uri = uris[0]
} }
}) })
@ -313,6 +314,7 @@ struct RemoveAudioPage {
.fontWeight(FontWeight.Medium) .fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.color_466afd')) .backgroundColor($r('app.color.color_466afd'))
.onClick(() => { .onClick(() => {
this.controller.stop()
if (this.uri) { if (this.uri) {
this.removeAudio() this.removeAudio()
} else { } else {

View File

@ -130,6 +130,7 @@ struct RemoveWatermarkPage {
.then((uris) => { .then((uris) => {
if (uris.length != 0) { if (uris.length != 0) {
this.isSuccess = false this.isSuccess = false
this.controller.reset()
this.uri = uris[0] this.uri = uris[0]
this.showBound = false this.showBound = false
MediaUtils.getVideoSize(this.uri) MediaUtils.getVideoSize(this.uri)
@ -384,6 +385,7 @@ struct RemoveWatermarkPage {
.fontWeight(FontWeight.Medium) .fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.color_466afd')) .backgroundColor($r('app.color.color_466afd'))
.onClick(() => { .onClick(() => {
this.controller.stop()
if (this.uri) { if (this.uri) {
this.addWatermark() this.addWatermark()
} else { } else {

View File

@ -18,6 +18,7 @@ import { RouterUrls } from '../../../../common/RouterUrls'
import { router } from '@kit.ArkUI' import { router } from '@kit.ArkUI'
import { EventReportManager } from '../../../../manager/EventReportManager' import { EventReportManager } from '../../../../manager/EventReportManager'
import { media } from '@kit.MediaKit' import { media } from '@kit.MediaKit'
import { TipDialog } from '../../../../dialog/TipDialog'
@Entry @Entry
@ComponentV2 @ComponentV2
@ -91,6 +92,7 @@ struct VideoToAudioPage {
.then((saved) => { .then((saved) => {
if (saved) { if (saved) {
this.videoUri = undefined this.videoUri = undefined
this.audioUri = undefined
this.isSuccess = false this.isSuccess = false
this.showDownloadDialog() this.showDownloadDialog()
} else { } else {
@ -142,9 +144,11 @@ struct VideoToAudioPage {
isEditSupported: false, isEditSupported: false,
isOriginalSupported: false isOriginalSupported: false
}) })
.then((uris) => { .then(async (uris) => {
if (uris.length != 0) { if (uris.length != 0) {
this.isSuccess = false this.isSuccess = false
this.controller.reset()
await this.avPlayer?.reset()
this.videoUri = uris[0] this.videoUri = uris[0]
this.audioUri = undefined this.audioUri = undefined
} }
@ -193,6 +197,7 @@ struct VideoToAudioPage {
case 'playing': case 'playing':
console.info('播放开始'); console.info('播放开始');
this.isAudioPlaying = true this.isAudioPlaying = true
this.controller.pause()
break; break;
case 'released': case 'released':
case 'stopped': case 'stopped':
@ -239,6 +244,18 @@ struct VideoToAudioPage {
} }
} }
onBackPress(): boolean | void {
if (this.isSuccess) {
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'音频尚未保存,是否确定退出?', callback: {
confirm: () => {
this.getUIContext().getRouter().back()
}
}})
return true
}
return false
}
build() { build() {
Column() { Column() {
TitleBar({ title: '视频转音频' }) TitleBar({ title: '视频转音频' })
@ -284,6 +301,7 @@ struct VideoToAudioPage {
}) })
.onStart(() => { .onStart(() => {
this.isVideoPlaying = true this.isVideoPlaying = true
this.avPlayer?.pause()
}) })
.onPause(() => { .onPause(() => {
this.isVideoPlaying = false this.isVideoPlaying = false
@ -419,6 +437,7 @@ struct VideoToAudioPage {
.fontWeight(FontWeight.Medium) .fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.color_466afd')) .backgroundColor($r('app.color.color_466afd'))
.onClick(() => { .onClick(() => {
this.controller.stop()
if (this.videoUri) { if (this.videoUri) {
this.videoToAudio() this.videoToAudio()
} else { } else {
@ -441,6 +460,7 @@ struct VideoToAudioPage {
.backgroundColor(Color.Transparent) .backgroundColor(Color.Transparent)
.onClick(() => { .onClick(() => {
this.controller.stop() this.controller.stop()
this.avPlayer?.pause()
this.selectVideo() this.selectVideo()
}) })

View File

@ -2,7 +2,7 @@ import { PhotoHelper } from '@pura/picker_utils'
import { TitleBar } from '../../../../view/TitleBar' import { TitleBar } from '../../../../view/TitleBar'
import { photoAccessHelper } from '@kit.MediaLibraryKit' import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit' import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
import { AppUtil, FileUtil, JSONUtil, PasteboardUtil } from '@pura/harmony-utils' import { AppUtil, FileUtil, JSONUtil, PasteboardUtil, StrUtil } from '@pura/harmony-utils'
import { ToastUtils } from '../../../../utils/ToastUtils' import { ToastUtils } from '../../../../utils/ToastUtils'
import { fileIo } from '@kit.CoreFileKit' import { fileIo } from '@kit.CoreFileKit'
import { LoadingDialog } from '../../../../dialog/LoadingDialog' import { LoadingDialog } from '../../../../dialog/LoadingDialog'
@ -153,6 +153,7 @@ struct VideoToTextPage {
.then((uris) => { .then((uris) => {
if (uris.length != 0) { if (uris.length != 0) {
this.isSuccess = false this.isSuccess = false
this.controller.reset()
this.videoUri = uris[0] this.videoUri = uris[0]
this.resultText = undefined this.resultText = undefined
} }
@ -198,7 +199,7 @@ struct VideoToTextPage {
} }
onBackPress(): boolean | void { onBackPress(): boolean | void {
if (this.isSuccess) { if (this.isSuccess && this.resultText) {
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未复制,是否确定退出?', callback: { TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未复制,是否确定退出?', callback: {
confirm: () => { confirm: () => {
this.getUIContext().getRouter().back() this.getUIContext().getRouter().back()
@ -348,6 +349,9 @@ struct VideoToTextPage {
Text('文本结果').fontColor($r('app.color.color_212226')).fontSize(15).fontWeight(FontWeight.Medium).margin({left: 4}) 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}) Divider().strokeWidth(1).color($r('app.color.color_eeeeee')).margin({top: 12})
Text('暂无数据').width('100%').layoutWeight(1).textAlign(TextAlign.Center).fontSize(14).fontColor($r('app.color.color_1a1a1a'))
.margin({top: 12})
.visibility(this.resultText === '' ? Visibility.Visible : Visibility.None)
Scroll() { Scroll() {
Text(this.resultText).width('100%').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 12}) Text(this.resultText).width('100%').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 12})
} }
@ -367,9 +371,9 @@ struct VideoToTextPage {
.layoutWeight(1) .layoutWeight(1)
.margin({top: 30, bottom: 20}) .margin({top: 30, bottom: 20})
.padding({left: 16, right: 16}) .padding({left: 16, right: 16})
.visibility(this.resultText ? Visibility.Visible : Visibility.None) .visibility(StrUtil.isNotNull(this.resultText) ? Visibility.Visible : Visibility.None)
Blank().layoutWeight(1).visibility(this.resultText ? Visibility.None : Visibility.Visible) Blank().layoutWeight(1).visibility(StrUtil.isNotNull(this.resultText) ? Visibility.None : Visibility.Visible)
Stack() { Stack() {
Button('确认处理', { type: ButtonType.Capsule, stateEffect: true }) Button('确认处理', { type: ButtonType.Capsule, stateEffect: true })
@ -380,13 +384,14 @@ struct VideoToTextPage {
.fontWeight(FontWeight.Medium) .fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.color_466afd')) .backgroundColor($r('app.color.color_466afd'))
.onClick(() => { .onClick(() => {
this.controller.stop()
if (this.videoUri) { if (this.videoUri) {
this.videoToAudio() this.videoToAudio()
} else { } else {
ToastUtils.show('请上传视频') ToastUtils.show('请上传视频')
} }
}) })
.visibility(!this.resultText ? Visibility.Visible : Visibility.None) .visibility(StrUtil.isNull(this.resultText) ? Visibility.Visible : Visibility.None)
Row() { Row() {
Button({ type: ButtonType.Capsule, stateEffect: true }) { Button({ type: ButtonType.Capsule, stateEffect: true }) {
@ -425,7 +430,7 @@ struct VideoToTextPage {
} }
}) })
} }
.visibility(this.resultText ? Visibility.Visible : Visibility.None) .visibility(StrUtil.isNotNull(this.resultText) ? Visibility.Visible : Visibility.None)
} }
.padding({left: 16, top: 9, right: 16, bottom: 30 }) .padding({left: 16, top: 9, right: 16, bottom: 30 })
.backgroundColor(Color.White) .backgroundColor(Color.White)

View File

@ -131,9 +131,9 @@ export struct WxImageMaterialPage {
}) })
Column() { Column() {
Text('操作步骤:').fontColor($r('app.color.color_90ffffff')).fontSize(14) Text('操作步骤:').fontColor($r('app.color.color_212226')).fontSize(14)
Text(this.isPlayback ? $r('app.string.wx_playback_course') : $r('app.string.wx_video_course')) Text(this.isPlayback ? $r('app.string.wx_playback_course') : $r('app.string.wx_video_course'))
.fontColor($r('app.color.color_50ffffff')) .fontColor('#4D4F57')
.fontSize(12) .fontSize(12)
.lineHeight(20) .lineHeight(20)
.margin({ top: 9 }) .margin({ top: 9 })

View File

@ -40,7 +40,6 @@ export struct MinePage {
@Monitor('viewModel.userEntity') @Monitor('viewModel.userEntity')
onUserinfoChange(monitor: IMonitor) { onUserinfoChange(monitor: IMonitor) {
this.userinfo = monitor.value()?.now as UserEntity; this.userinfo = monitor.value()?.now as UserEntity;
this.menuList = mineMenuList().convertToArray()
} }
@Monitor('viewModel.wxService') @Monitor('viewModel.wxService')
@ -56,6 +55,7 @@ export struct MinePage {
@Monitor('viewModel.diamondInfo') @Monitor('viewModel.diamondInfo')
onDiamondInfoChange(monitor: IMonitor) { onDiamondInfoChange(monitor: IMonitor) {
this.diamondInfo = monitor.value()?.now as DiamondDetailEntity; this.diamondInfo = monitor.value()?.now as DiamondDetailEntity;
this.menuList = mineMenuList(this.diamondInfo && this.diamondInfo.buy_total > 0).convertToArray()
} }
aboutToAppear(): void { aboutToAppear(): void {

View File

@ -31,6 +31,7 @@ struct DiamondPage {
@Local isAgree: boolean = false; @Local isAgree: boolean = false;
@Local payType: number = 0; //0微信支付 1支付宝支付 @Local payType: number = 0; //0微信支付 1支付宝支付
@Local totalPrice: number = 0; @Local totalPrice: number = 0;
@Local offsetY: number = 0
showQueryTip: boolean = false //是否显示支付状态查询提示 showQueryTip: boolean = false //是否显示支付状态查询提示
@ -378,6 +379,9 @@ struct DiamondPage {
} }
.layoutWeight(1) .layoutWeight(1)
.scrollBar(BarState.Off) .scrollBar(BarState.Off)
.onWillScroll((_xOffset, yOffset) => {
this.offsetY += yOffset
})
Column() { Column() {
Row() { Row() {
@ -430,7 +434,9 @@ struct DiamondPage {
onRightClick: () => { onRightClick: () => {
this.showRuleDialog() this.showRuleDialog()
} }
}).id('titleBar') })
.opacity(Math.min(Math.max(1 - this.offsetY / 300, 0), 1))
.id('titleBar')
} }
.width('100%') .width('100%')
.height('100%') .height('100%')

View File

@ -17,10 +17,10 @@ export class ImageUtils {
const height: number = imageInfo.size.height; const height: number = imageInfo.size.height;
const scaleWidth: number = w / width; const scaleWidth: number = w / width;
const scaleHeight: number = h / height; const scaleHeight: number = h / height;
const pixelMapColor: ArrayBuffer = new ArrayBuffer(w * h * 2); const pixelMapColor: ArrayBuffer = new ArrayBuffer(w * h * 4);
const options: image.InitializationOptions = { const options: image.InitializationOptions = {
editable: true, editable: true,
pixelFormat: image.PixelMapFormat.RGB_565, pixelFormat: image.PixelMapFormat.RGBA_8888,
size: { height: h, width: w } size: { height: h, width: w }
}; };
// 采用RGB_565格式创建画布PixelMap // 采用RGB_565格式创建画布PixelMap

View File

@ -0,0 +1,251 @@
import { ActionType, Position, RectPosition } from './RectCropView';
@ComponentV2
export struct CustomWatermarkView {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private canvasContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
private actionType: ActionType = ActionType.move;
private touchPosition: Position = { x: 0, y: 0 };
private sw: number = 0; //图片展示框固定宽度
private sh: number = 0; //图片展示框固定高度
private offsetW: number = 10
@Param onRectChange?: (rect: RectPosition) => void = undefined
@Param onClose?: () => void = undefined
@Param imageUri?: string = undefined
@Param date: Date = new Date()
@Param title?: string = undefined
@Param address?: string = undefined
@Local clipRect: RectPosition = {
x: 0,
y: 0,
width: 150,
height: 60
};
@Local initPosition: Position = {
x: 0,
y: 0
}
@Local fontSize: number = 15
getFormatData(date: Date): string {
let year = date.getFullYear()
let month = date.getMonth() + 1
let day = date.getDate()
return `${year}.${month}.${day}`
}
build() {
Stack() {
Row() {
Image(this.imageUri)
.width(this.clipRect.width / 2 - 2 * this.offsetW)
.height(this.clipRect.height - 2 * this.offsetW)
.borderRadius(6)
.margin({ left: this.offsetW })
Column() {
Text(this.title).fontColor(Color.White).fontSize(this.fontSize)
Text(this.getFormatData(this.date)).fontColor(Color.White).fontSize(this.fontSize)
Text(this.address).fontColor(Color.White).fontSize(this.fontSize)
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
.margin({ left: 8, top: this.offsetW, right: this.offsetW, bottom: this.offsetW })
}
.position({
x: this.clipRect.x,
y: this.clipRect.y
})
.width(this.clipRect.width)
.height(this.clipRect.height)
.onSizeChange(() => {
this.caleTextSize()
})
.id('customWatermark')
Image($r('app.media.ic_right_bottom_rect'))
.position({
x: this.clipRect.x + this.clipRect.width - 9,
y: this.clipRect.y + this.clipRect.height - 9
})
.width(15)
.height(15)
// 裁剪框
Canvas(this.canvasContext)
.position({
x: this.clipRect.x,
y: this.clipRect.y
})
.width(this.clipRect.width)
.height(this.clipRect.height)
.onReady(() => {
this.drawClipImage()
})
.onTouch(event => {
if (event.type === TouchType.Down) {
this.isMove(event.target.area, event.touches[0]);
this.touchPosition = {
x: event.touches[0].screenX,
y: event.touches[0].screenY
}
} else if (event.type === TouchType.Move) {
let moveX = event.changedTouches[0].screenX - this.touchPosition.x;
let moveY = event.changedTouches[0].screenY - this.touchPosition.y;
this.touchPosition = {
x: event.changedTouches[0].screenX,
y: event.changedTouches[0].screenY
}
this.moveClipCanvas(moveX, moveY);
}
})
Image($r('app.media.ic_left_top_rect'))
.position({
x: this.clipRect.x - 7,
y: this.clipRect.y - 7
})
.width(16)
.height(16)
.onClick(() => {
if (this.onClose) {
this.onClose()
}
})
}
.width('100%')
.height('100%')
.onAreaChange((_oldArea, newArea) => {
this.sw = newArea.width as number
this.sh = newArea.height as number
this.clipRect.width = 150
this.clipRect.height = 60
this.moveClipCanvas(0, 0)
})
}
// 绘制裁剪框
drawClipImage() {
this.canvasContext.clearRect(0, 0, this.clipRect.width, this.clipRect.height);
this.canvasContext.lineWidth = 2
this.canvasContext.strokeStyle = Color.White
this.canvasContext.beginPath()
this.canvasContext.rect(0, 0, this.clipRect.width, this.clipRect.height)
this.canvasContext.stroke()
}
// 裁剪框位置和大小变化 初始位置为图片的初始坐标 移动的坐标
moveClipCanvas(moveX: number, moveY: number) {
let clipRect: RectPosition = {
x: this.clipRect.x,
y: this.clipRect.y,
width: this.clipRect.width,
height: this.clipRect.height
}
switch (this.actionType) {
case ActionType.move:
clipRect.x += moveX;
clipRect.y += moveY;
break;
case ActionType.topLeft:
clipRect.x += moveX;
clipRect.y += moveY;
clipRect.width += -moveX;
clipRect.height += -moveY;
break;
case ActionType.topRight:
clipRect.y += moveY;
clipRect.width += moveX;
clipRect.height += -moveY;
break;
case ActionType.bottomLeft:
clipRect.x += moveX;
clipRect.width += -moveX;
clipRect.height += moveY;
break;
case ActionType.bottomRight:
clipRect.width += moveX;
clipRect.height += moveY;
break;
default:
break;
}
// 偏移坐标小于初始位置
if (clipRect.x < this.initPosition.x) {
clipRect.x = this.initPosition.x;
}
if (clipRect.y < this.initPosition.y) {
clipRect.y = this.initPosition.y;
}
// 横坐标限制位置
if (clipRect.width + clipRect.x > this.sw + this.initPosition.x) {
if (this.actionType === ActionType.move) {
clipRect.x = this.sw + this.initPosition.x - clipRect.width;
} else {
clipRect.width = this.sw + this.initPosition.x - clipRect.x;
}
}
// 纵坐标限制
if (clipRect.height + clipRect.y > this.sh + this.initPosition.y) {
if (this.actionType === ActionType.move) {
clipRect.y = this.sh + this.initPosition.y - clipRect.height;
} else {
clipRect.height = this.sh + this.initPosition.y - clipRect.y;
}
}
//裁剪框位置大小
this.clipRect = {
x: Math.round(clipRect.x),
y: Math.round(clipRect.y),
width: Math.max(Math.round(clipRect.width), 150),
height: Math.max(Math.round(clipRect.height), 60)
};
if (this.onRectChange) {
this.onRectChange(this.clipRect)
}
}
// 判断操作类型
isMove(area: Area, touch: TouchObject) {
if (touch.x < 30 && touch.y < 30) { // 左上角
this.actionType = ActionType.topLeft
} else if (touch.x < 30 && touch.y > (Number(area.height) - 30)) { // 左下
this.actionType = ActionType.bottomLeft
} else if (touch.x > Number(area.width) - 30 && touch.y < 30) { // 右上
this.actionType = ActionType.topRight
} else if (touch.x > Number(area.width) - 30 && touch.y > (Number(area.height) - 30)) { // 右下
this.actionType = ActionType.bottomRight
} else {
this.actionType = ActionType.move
}
}
// 缩放文字大小
caleTextSize() {
let titleSize = this.getUIContext().getMeasureUtils().measureTextSize({
textContent: this.title,
fontSize: this.fontSize
})
let dateSize = this.getUIContext().getMeasureUtils().measureTextSize({
textContent: this.getFormatData(this.date),
fontSize: this.fontSize
})
let addressSize = this.getUIContext().getMeasureUtils().measureTextSize({
textContent: this.address,
fontSize: this.fontSize
})
let textWidth = Math.max(titleSize.width as number, dateSize.width as number, addressSize.width as number)
let textHeight = titleSize.height
let ratioW = vp2px(this.clipRect.width / 2 - 2 * this.offsetW - 8) / (textWidth as number)
let ratioH = vp2px((this.clipRect.height - 2 * this.offsetW) / 3) / (textHeight as number)
let fontSize = Math.floor(this.fontSize * Math.min(ratioW, ratioH))
if (fontSize > 8) {
this.fontSize = fontSize
}
}
}

View File

@ -14,7 +14,7 @@ export struct VideoMaterialItemView {
Image(this.media?.thumb) Image(this.media?.thumb)
.width('100%') .width('100%')
.height('100%') .height('100%')
.borderRadius({topLeft: 10, topRight: 10}) .borderRadius({topLeft: 10, topRight: 10, bottomLeft: !this.media?.title ? 10: 0, bottomRight: !this.media?.title ? 10: 0})
.backgroundColor($r('app.color.color_222222')) .backgroundColor($r('app.color.color_222222'))
.id('iv_thumb') .id('iv_thumb')
@ -68,6 +68,7 @@ export struct VideoMaterialItemView {
.textOverflow({ overflow: TextOverflow.Ellipsis }) .textOverflow({ overflow: TextOverflow.Ellipsis })
.ellipsisMode(EllipsisMode.END) .ellipsisMode(EllipsisMode.END)
.padding({left: 8, top: 10, right: 8, bottom: 10}) .padding({left: 8, top: 10, right: 8, bottom: 10})
.visibility(this.media?.title ? Visibility.Visible : Visibility.None)
} }
.backgroundColor(Color.White) .backgroundColor(Color.White)
.borderRadius(10) .borderRadius(10)

View File

@ -2,7 +2,7 @@ import { StrUtil } from '@pura/harmony-utils';
import { ActionType, Position, RectPosition } from './RectCropView'; import { ActionType, Position, RectPosition } from './RectCropView';
@ComponentV2 @ComponentV2
export struct WaterMarkerView { export struct WatermarkView {
private settings: RenderingContextSettings = new RenderingContextSettings(true); private settings: RenderingContextSettings = new RenderingContextSettings(true);
private canvasContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private canvasContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
private actionType: ActionType = ActionType.move; private actionType: ActionType = ActionType.move;
@ -14,7 +14,9 @@ export struct WaterMarkerView {
@Param onClose?: () => void = undefined @Param onClose?: () => void = undefined
@Param content: string = '' @Param content: string = ''
@Param textColor: string = ''
@Param imagePath: string = '' @Param imagePath: string = ''
@Param imageRadius: number = 0
@Local clipRect: RectPosition = { @Local clipRect: RectPosition = {
x: 0, x: 0,
@ -38,13 +40,13 @@ export struct WaterMarkerView {
}) })
.width(this.clipRect.width) .width(this.clipRect.width)
.height(this.clipRect.height) .height(this.clipRect.height)
.fontColor(Color.White) .fontColor(this.textColor ? this.textColor : Color.White)
.fontSize(this.fontSize) .fontSize(this.fontSize)
.textAlign(TextAlign.Center) .textAlign(TextAlign.Center)
.onSizeChange(() => { .onSizeChange(() => {
this.caleTextSize() this.caleTextSize()
}) })
.id("textWaterMarker") .id('textWatermark')
} else if (StrUtil.isNotEmpty(this.imagePath)) { } else if (StrUtil.isNotEmpty(this.imagePath)) {
Image(this.imagePath) Image(this.imagePath)
.position({ .position({
@ -53,7 +55,8 @@ export struct WaterMarkerView {
}) })
.width(this.clipRect.width) .width(this.clipRect.width)
.height(this.clipRect.height) .height(this.clipRect.height)
.id("imageWaterMarker") .borderRadius(this.imageRadius)
.id('imageWatermark')
} }
Image($r('app.media.ic_right_bottom_rect')) Image($r('app.media.ic_right_bottom_rect'))

View File

@ -9,7 +9,7 @@ export class DownloadHistoryViewModel extends BaseViewModel {
@Trace getHistory?: Array<DownloadHistoryEntity>; @Trace getHistory?: Array<DownloadHistoryEntity>;
@Trace deleteHistory?: object; @Trace deleteHistory?: object;
async getHistoryList(page: string = '1', startTime: string, endTime: string) { async getHistoryList(page: string, startTime: string, endTime: string) {
this.showLoading(); this.showLoading();
try { try {
const result = await apiService.getDownloadHistoryList(page, startTime, endTime); const result = await apiService.getDownloadHistoryList(page, startTime, endTime);

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B