diff --git a/entry/src/main/ets/dialog/CustomWatermarkDialog.ets b/entry/src/main/ets/dialog/CustomWatermarkDialog.ets new file mode 100644 index 0000000..6c8bcab --- /dev/null +++ b/entry/src/main/ets/dialog/CustomWatermarkDialog.ets @@ -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%') + } +} \ No newline at end of file diff --git a/entry/src/main/ets/dialog/DatePickerDialog.ets b/entry/src/main/ets/dialog/DatePickerDialog.ets new file mode 100644 index 0000000..5795f87 --- /dev/null +++ b/entry/src/main/ets/dialog/DatePickerDialog.ets @@ -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 | 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.'); + }) + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/dialog/DownloadDialog.ets b/entry/src/main/ets/dialog/DownloadDialog.ets index c43b60d..6096669 100644 --- a/entry/src/main/ets/dialog/DownloadDialog.ets +++ b/entry/src/main/ets/dialog/DownloadDialog.ets @@ -24,131 +24,136 @@ export declare class DownloadDialogOption { @Builder function defaultBuilder(option: DownloadDialogOption) { - Column() { - Text((option.status === DownloadStatus.DOWNLOADING ? '下载中' : - 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) + Stack({alignContent: Alignment.Top}) { + Image($r('app.media.ic_tip_dialog_top_bg')).width('100%').aspectRatio(2.72) - Image(option.status === DownloadStatus.COMPLETED ? $r('app.media.ic_completed') : $r('app.media.ic_downloading')) - .width(80) - .height(80) - .margin({ top: 20 }) + Column() { + Text((option.status === DownloadStatus.DOWNLOADING ? '下载中' : + 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(24) + .fontFamily('ysbth') + .visibility(option.status === DownloadStatus.COMPLETED ? Visibility.None : Visibility.Visible) - Stack() { - Column() { - Stack({ alignContent: Alignment.Start }) { - Progress({ value: option.progress, total: option.totalSize, type: ProgressType.Linear }) - .width('100%') - .style({ strokeWidth: 12, strokeRadius: 6 }) - .color($r('app.color.color_466afd')) - // .colorBlend('#F1F2F6') - .borderRadius(6) + Image(option.status === DownloadStatus.COMPLETED ? $r('app.media.ic_completed') : $r('app.media.ic_downloading')) + .width(80) + .height(80) + .margin({ top: 20 }) - Text(FormatUtil.getFormatPercentage(option.progress / option.totalSize, 1)) - .width(40) - .height(18) - .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 }) - } + Stack() { + Column() { + Stack({ alignContent: Alignment.Start }) { + Progress({ value: option.progress, total: option.totalSize, type: ProgressType.Linear }) + .width('100%') + .style({ strokeWidth: 12, strokeRadius: 6 }) + .color($r('app.color.color_466afd')) + // .colorBlend('#F1F2F6') + .borderRadius(6) - Text(`${FileUtil.getFormatFileSize(option.progress)}/${option.totalSize !== 0 ? - FileUtil.getFormatFileSize(option.totalSize) : '获取中'}`) - .fontColor($r('app.color.color_727686')) - .fontSize(12) + Text(FormatUtil.getFormatPercentage(option.progress / option.totalSize, 1)) + .width(40) + .height(18) + .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 }) - .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() { - Text(option.isAudio ? '已保存到本地' : '已保存到系统相册中').fontColor($r('app.color.color_466afd')).fontSize(16) + Column() { + Text(option.isAudio ? '已保存到本地' : '已保存到系统相册中').fontColor($r('app.color.color_466afd')).fontSize(16) - Text(option.isAudio ? '文件管理/我的手机/Download/素材魔方' : '文件管理/我的手机/Download/图库') - .fontColor($r('app.color.color_727686')) - .fontSize(12) - .margin({ top: 10 }) + Text(option.isAudio ? '文件管理/我的手机/Download/素材魔方' : '文件管理/我的手机/Download/图库') + .fontColor($r('app.color.color_727686')) + .fontSize(12) + .margin({ top: 10 }) - 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() - }) + 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() + }) - Blank().width(10) + Blank().width(10) - Button('前往查看', { type: ButtonType.Capsule, stateEffect: true }) - .width(110) - .height(36) - .backgroundColor($r('app.color.color_466afd')) - .fontColor(Color.White) - .fontSize(15) - .onClick(() => { - if (option.callback?.confirm) { - option.callback.confirm() - } - DownloadDialog.dismiss() - }) + Button('前往查看', { type: ButtonType.Capsule, stateEffect: true }) + .width(110) + .height(36) + .backgroundColor($r('app.color.color_466afd')) + .fontColor(Color.White) + .fontSize(15) + .onClick(() => { + if (option.callback?.confirm) { + option.callback.confirm() + } + 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%') - .borderRadius(10) + .borderRadius(16) .backgroundColor(Color.White) - .padding(20) } export class DownloadDialog { diff --git a/entry/src/main/ets/dialog/ImageWatermarkDialog.ets b/entry/src/main/ets/dialog/ImageWatermarkDialog.ets new file mode 100644 index 0000000..f0ee47c --- /dev/null +++ b/entry/src/main/ets/dialog/ImageWatermarkDialog.ets @@ -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%') + } +} \ No newline at end of file diff --git a/entry/src/main/ets/dialog/LoginTipDialog.ets b/entry/src/main/ets/dialog/LoginTipDialog.ets index df49359..db91193 100644 --- a/entry/src/main/ets/dialog/LoginTipDialog.ets +++ b/entry/src/main/ets/dialog/LoginTipDialog.ets @@ -10,71 +10,78 @@ export struct LoginTipDialog { } build() { - RelativeContainer() { - Image($r('app.media.ic_tip_dialog_top_bg')).width('100%').aspectRatio(2.72) + Stack({alignContent: Alignment.TopStart}) { + RelativeContainer() { + Image($r('app.media.ic_tip_dialog_top_bg')).width('100%').aspectRatio(2.72) - Column() { - Text('温馨提示') - .fontColor($r('app.color.color_212226')) - .fontSize(24) - .fontFamily('ysbth') - .margin({ top: 20 }) + Column() { + Text('温馨提示') + .fontColor($r('app.color.color_212226')) + .fontSize(24) + .fontFamily('ysbth') + .margin({ top: 20 }) - Text() { - Span('登录之前需查看并同意') - Span('《用户协议》') - .fontColor($r("app.color.color_466afd")) - .onClick(() => { - this.getUIContext().getRouter().pushUrl({ - url: RouterUrls.WEB_PAGE, params: { - title: '用户协议', - url: Constants.USER_AGREEMENT - } + Text() { + Span('登录之前需查看并同意') + Span('《用户协议》') + .fontColor($r("app.color.color_466afd")) + .onClick(() => { + this.getUIContext().getRouter().pushUrl({ + url: RouterUrls.WEB_PAGE, params: { + title: '用户协议', + url: Constants.USER_AGREEMENT + } + }) }) - }) - Span('和') - Span('《隐私政策》') - .fontColor($r("app.color.color_466afd")) - .onClick(() => { - this.getUIContext().getRouter().pushUrl({ - url: RouterUrls.WEB_PAGE, params: { - title: '隐私政策', - url: Constants.PRIVACY_POLICY - } + Span('和') + Span('《隐私政策》') + .fontColor($r("app.color.color_466afd")) + .onClick(() => { + this.getUIContext().getRouter().pushUrl({ + url: RouterUrls.WEB_PAGE, params: { + title: '隐私政策', + 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')) - .fontSize(14) - .textAlign(TextAlign.Center) - .margin({ top: 20, left: 20, right: 20 }) + .width('100%') - 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 }) + Image($r('app.media.ic_close_dialog')).width(18).height(18) + .margin({top: 10, right: 10}) + .alignRules({ + right: {anchor: '__container__', align: HorizontalAlign.End} + }) .onClick(() => { - this.controller.close(); - if (this.confirm) { - this.confirm(); - } + this.controller.close() }) } + .width('100%') + .height('auto') + .borderRadius(20) + .backgroundColor(Color.White) + .margin({top: 26}) - Image($r('app.media.ic_close_dialog')).width(18).height(18) - .margin({top: 10, right: 10}) - .alignRules({ - right: {anchor: '__container__', align: HorizontalAlign.End} - }) - .onClick(() => { - this.controller.close() - }) + Image($r('app.media.ic_notify_icon')).width(87).height(66).margin({left: 4}) } - .height('auto') - .borderRadius(20) - .backgroundColor(Color.White) } } \ No newline at end of file diff --git a/entry/src/main/ets/dialog/TextWatermarkDialog.ets b/entry/src/main/ets/dialog/TextWatermarkDialog.ets new file mode 100644 index 0000000..c521ba1 --- /dev/null +++ b/entry/src/main/ets/dialog/TextWatermarkDialog.ets @@ -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 = [] + @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%') + } +} \ No newline at end of file diff --git a/entry/src/main/ets/entity/MenuEntity.ets b/entry/src/main/ets/entity/MenuEntity.ets index 526653e..7a74906 100644 --- a/entry/src/main/ets/entity/MenuEntity.ets +++ b/entry/src/main/ets/entity/MenuEntity.ets @@ -23,10 +23,10 @@ export function homeMenuList(): ArrayList { return list; } -export function mineMenuList(): ArrayList { +export function mineMenuList(showDiamond: boolean): ArrayList { let list = new ArrayList() 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_icon3'), "意见反馈", "feedback")) diff --git a/entry/src/main/ets/entity/TextColorEntity.ets b/entry/src/main/ets/entity/TextColorEntity.ets new file mode 100644 index 0000000..895a9e1 --- /dev/null +++ b/entry/src/main/ets/entity/TextColorEntity.ets @@ -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 { + const list = new Array() + 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 +} \ No newline at end of file diff --git a/entry/src/main/ets/net/AxiosRequest.ets b/entry/src/main/ets/net/AxiosRequest.ets index 217d1b3..36e970b 100644 --- a/entry/src/main/ets/net/AxiosRequest.ets +++ b/entry/src/main/ets/net/AxiosRequest.ets @@ -44,6 +44,8 @@ instance.interceptors.request.use((config: InternalAxiosRequestConfig) => { let method = config.method?.toLowerCase(); if (method === "post" || method === "put") { 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; @@ -123,6 +125,12 @@ instance.interceptors.response.use((response: AxiosResponse) => { break; } } + } else { + let newResponse: Record = { + 'code': 0, + 'data': dataString + } + dataString = JSON.stringify(newResponse) } } } diff --git a/entry/src/main/ets/pages/main/home/tools/AddWatermarkPage.ets b/entry/src/main/ets/pages/main/home/tools/AddWatermarkPage.ets index 7df1a81..a08e7bd 100644 --- a/entry/src/main/ets/pages/main/home/tools/AddWatermarkPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/AddWatermarkPage.ets @@ -14,21 +14,25 @@ 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 { WatermarkView } from '../../../../view/WatermarkView' 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 { LevelMode, router } from '@kit.ArkUI' 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 @ComponentV2 struct AddWatermarkPage { private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) + private watermarkDialogController?: CustomDialogController | null; private controller: VideoController = new VideoController() private videoSize: media.PixelMapParams = { 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 showWatermark: boolean = false + @Local watermarkType: number = 0 @Local textContent: string = '' + @Local textColor: 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') onPermissionInfoChange(monitor: IMonitor) { @@ -72,6 +84,10 @@ struct AddWatermarkPage { } } + aboutToDisappear(): void { + this.watermarkDialogController = null + } + doSave() { SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) .then((saved) => { @@ -107,7 +123,7 @@ struct AddWatermarkPage { let imageWidth = (vp2px(this.rect.width * this.videoSize.width!!) / this.playerSize.width!!) 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) => { let imagePath = await ImageUtil.savePixelMap(image, FileUtil.getCacheDirPath(), `cache_${systemDateTime.getTime()}.png`) let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4` @@ -143,11 +159,20 @@ struct AddWatermarkPage { .then((uris) => { if (uris.length != 0) { this.isSuccess = false + this.watermarkType = 0 + this.controller.reset() this.uri = uris[0] this.showWatermark = false this.textContent = '' + this.textColor = '' this.imagePath = '' + this.imageRadius = 0 + + this.imageUri = '' + this.title = '' + this.date = undefined + this.address = '' MediaUtils.getVideoSize(this.uri) .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() { DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, @@ -349,26 +436,59 @@ struct AddWatermarkPage { }) if (this.showWatermark && this.uri && !this.isSuccess) { - WaterMarkerView({ - content: this.textContent, - imagePath: this.imagePath, - onRectChange: (rect) => { - this.rect = rect - }, - onClose: () => { - this.showWatermark = false - this.textContent = '' - this.imagePath = '' - } - }) - .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 } + if (this.watermarkType === 1) { + CustomWatermarkView({ + imageUri: this.imageUri, + title: this.title, + date: this.date, + address: this.address, + onRectChange: (rect) => { + this.rect = rect + }, + onClose: () => { + this.showWatermark = false + this.watermarkType = 0 + this.imageUri = '' + this.title = '' + this.date = undefined + this.address = '' + } }) + .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) @@ -380,7 +500,10 @@ struct AddWatermarkPage { } .layoutWeight(1) .onClick(() => { - + if (!this.showWatermark) { + this.controller.stop() + this.showCustomWatermarkDialog() + } }) Column(){ @@ -391,10 +514,7 @@ struct AddWatermarkPage { .onClick(() => { if (!this.showWatermark) { this.controller.stop() - EditTextDialog.show(this.getUIContext(), {title: '添加水印', hintText: '请输入文字', confirm: (text) => { - this.textContent = text - this.showWatermark = true - }}) + this.showTextWatermarkDialog() } }) @@ -417,7 +537,9 @@ struct AddWatermarkPage { if (uris.length != 0) { this.isSuccess = false this.imagePath = uris[0] + this.watermarkType = 3 this.showWatermark = true + this.showImageWatermarkDialog() } }) } @@ -443,6 +565,7 @@ struct AddWatermarkPage { .fontWeight(FontWeight.Medium) .backgroundColor($r('app.color.color_466afd')) .onClick(() => { + this.controller.stop() if (this.uri) { if (this.showWatermark) { this.addWatermark() diff --git a/entry/src/main/ets/pages/main/home/tools/AudioToTextPage.ets b/entry/src/main/ets/pages/main/home/tools/AudioToTextPage.ets index 193d732..9fdb1a4 100644 --- a/entry/src/main/ets/pages/main/home/tools/AudioToTextPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/AudioToTextPage.ets @@ -1,7 +1,7 @@ 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 { AppUtil, FileUtil, JSONUtil, PasteboardUtil, StrUtil } from '@pura/harmony-utils' import { ToastUtils } from '../../../../utils/ToastUtils' import { fileIo } from '@kit.CoreFileKit' import { LoadingDialog } from '../../../../dialog/LoadingDialog' @@ -159,6 +159,7 @@ struct AudioToTextPage { .then(async (uris) => { if (uris.length != 0) { this.isSuccess = false + await this.avPlayer?.reset() this.audioUri = uris[0] this.resultText = undefined // 打开相应的资源文件地址获取fd @@ -257,7 +258,7 @@ struct AudioToTextPage { } onBackPress(): boolean | void { - if (this.isSuccess) { + if (this.isSuccess && this.resultText) { TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未复制,是否确定退出?', callback: { confirm: () => { 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}) } 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() { Text(this.resultText).width('100%').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 12}) } @@ -357,9 +361,9 @@ struct AudioToTextPage { .layoutWeight(1) .margin({top: 30, bottom: 20}) .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() { Button('确认处理', { type: ButtonType.Capsule, stateEffect: true }) @@ -370,13 +374,14 @@ struct AudioToTextPage { .fontWeight(FontWeight.Medium) .backgroundColor($r('app.color.color_466afd')) .onClick(() => { + this.avPlayer?.pause() if (this.audioUri) { this.copyAudio() } else { ToastUtils.show('请上传音频') } }) - .visibility(!this.resultText ? Visibility.Visible : Visibility.None) + .visibility(StrUtil.isNull(this.resultText) ? Visibility.Visible : Visibility.None) Row() { 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 }) .backgroundColor(Color.White) diff --git a/entry/src/main/ets/pages/main/home/tools/ImageMergePage.ets b/entry/src/main/ets/pages/main/home/tools/ImageMergePage.ets index b94018d..9777757 100644 --- a/entry/src/main/ets/pages/main/home/tools/ImageMergePage.ets +++ b/entry/src/main/ets/pages/main/home/tools/ImageMergePage.ets @@ -88,7 +88,7 @@ struct ImageMergePage { const imageSource: image.ImageSource = image.createImageSource(compressedUri[0]) let decodingOptions: image.DecodingOptions = { editable: true, - desiredPixelFormat: image.PixelMapFormat.RGB_565, + desiredPixelFormat: image.PixelMapFormat.RGBA_8888, } let pixelMap = imageSource.createPixelMapSync(decodingOptions) if (pixelMap) { @@ -97,6 +97,7 @@ struct ImageMergePage { pixelArray.push(pixelMap) } else { ToastUtils.show('处理失败') + LoadingDialog.dismiss() return } } diff --git a/entry/src/main/ets/pages/main/home/tools/MD5ResetPage.ets b/entry/src/main/ets/pages/main/home/tools/MD5ResetPage.ets index bbff3ec..476fa38 100644 --- a/entry/src/main/ets/pages/main/home/tools/MD5ResetPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/MD5ResetPage.ets @@ -121,6 +121,7 @@ struct MD5ResetPage { .then((uris) => { if (uris.length != 0) { this.isSuccess = false + this.controller.reset() this.uri = uris[0] this.oldMd5 = this.fileMD5(this.uri) this.newMd5 = undefined @@ -363,6 +364,7 @@ struct MD5ResetPage { .fontWeight(FontWeight.Medium) .backgroundColor($r('app.color.color_466afd')) .onClick(() => { + this.controller.stop() if (this.uri) { this.modifyMD5() } else { diff --git a/entry/src/main/ets/pages/main/home/tools/RemoveAudioPage.ets b/entry/src/main/ets/pages/main/home/tools/RemoveAudioPage.ets index 15135b7..3b842c2 100644 --- a/entry/src/main/ets/pages/main/home/tools/RemoveAudioPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/RemoveAudioPage.ets @@ -115,6 +115,7 @@ struct RemoveAudioPage { .then((uris) => { if (uris.length != 0) { this.isSuccess = false + this.controller.reset() this.uri = uris[0] } }) @@ -313,6 +314,7 @@ struct RemoveAudioPage { .fontWeight(FontWeight.Medium) .backgroundColor($r('app.color.color_466afd')) .onClick(() => { + this.controller.stop() if (this.uri) { this.removeAudio() } else { diff --git a/entry/src/main/ets/pages/main/home/tools/RemoveWatermarkPage.ets b/entry/src/main/ets/pages/main/home/tools/RemoveWatermarkPage.ets index ff834ca..5633fd7 100644 --- a/entry/src/main/ets/pages/main/home/tools/RemoveWatermarkPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/RemoveWatermarkPage.ets @@ -130,6 +130,7 @@ struct RemoveWatermarkPage { .then((uris) => { if (uris.length != 0) { this.isSuccess = false + this.controller.reset() this.uri = uris[0] this.showBound = false MediaUtils.getVideoSize(this.uri) @@ -384,6 +385,7 @@ struct RemoveWatermarkPage { .fontWeight(FontWeight.Medium) .backgroundColor($r('app.color.color_466afd')) .onClick(() => { + this.controller.stop() if (this.uri) { this.addWatermark() } else { diff --git a/entry/src/main/ets/pages/main/home/tools/VideoToAudioPage.ets b/entry/src/main/ets/pages/main/home/tools/VideoToAudioPage.ets index 1a6f354..53c0de1 100644 --- a/entry/src/main/ets/pages/main/home/tools/VideoToAudioPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/VideoToAudioPage.ets @@ -18,6 +18,7 @@ import { RouterUrls } from '../../../../common/RouterUrls' import { router } from '@kit.ArkUI' import { EventReportManager } from '../../../../manager/EventReportManager' import { media } from '@kit.MediaKit' +import { TipDialog } from '../../../../dialog/TipDialog' @Entry @ComponentV2 @@ -91,6 +92,7 @@ struct VideoToAudioPage { .then((saved) => { if (saved) { this.videoUri = undefined + this.audioUri = undefined this.isSuccess = false this.showDownloadDialog() } else { @@ -142,9 +144,11 @@ struct VideoToAudioPage { isEditSupported: false, isOriginalSupported: false }) - .then((uris) => { + .then(async (uris) => { if (uris.length != 0) { this.isSuccess = false + this.controller.reset() + await this.avPlayer?.reset() this.videoUri = uris[0] this.audioUri = undefined } @@ -193,6 +197,7 @@ struct VideoToAudioPage { case 'playing': console.info('播放开始'); this.isAudioPlaying = true + this.controller.pause() break; case 'released': 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() { Column() { TitleBar({ title: '视频转音频' }) @@ -284,6 +301,7 @@ struct VideoToAudioPage { }) .onStart(() => { this.isVideoPlaying = true + this.avPlayer?.pause() }) .onPause(() => { this.isVideoPlaying = false @@ -419,6 +437,7 @@ struct VideoToAudioPage { .fontWeight(FontWeight.Medium) .backgroundColor($r('app.color.color_466afd')) .onClick(() => { + this.controller.stop() if (this.videoUri) { this.videoToAudio() } else { @@ -441,6 +460,7 @@ struct VideoToAudioPage { .backgroundColor(Color.Transparent) .onClick(() => { this.controller.stop() + this.avPlayer?.pause() this.selectVideo() }) diff --git a/entry/src/main/ets/pages/main/home/tools/VideoToTextPage.ets b/entry/src/main/ets/pages/main/home/tools/VideoToTextPage.ets index 389c116..c433c2e 100644 --- a/entry/src/main/ets/pages/main/home/tools/VideoToTextPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/VideoToTextPage.ets @@ -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, FileUtil, JSONUtil, PasteboardUtil } from '@pura/harmony-utils' +import { AppUtil, FileUtil, JSONUtil, PasteboardUtil, StrUtil } from '@pura/harmony-utils' import { ToastUtils } from '../../../../utils/ToastUtils' import { fileIo } from '@kit.CoreFileKit' import { LoadingDialog } from '../../../../dialog/LoadingDialog' @@ -153,6 +153,7 @@ struct VideoToTextPage { .then((uris) => { if (uris.length != 0) { this.isSuccess = false + this.controller.reset() this.videoUri = uris[0] this.resultText = undefined } @@ -198,7 +199,7 @@ struct VideoToTextPage { } onBackPress(): boolean | void { - if (this.isSuccess) { + if (this.isSuccess && this.resultText) { TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未复制,是否确定退出?', callback: { confirm: () => { 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}) } 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() { Text(this.resultText).width('100%').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 12}) } @@ -367,9 +371,9 @@ struct VideoToTextPage { .layoutWeight(1) .margin({top: 30, bottom: 20}) .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() { Button('确认处理', { type: ButtonType.Capsule, stateEffect: true }) @@ -380,13 +384,14 @@ struct VideoToTextPage { .fontWeight(FontWeight.Medium) .backgroundColor($r('app.color.color_466afd')) .onClick(() => { + this.controller.stop() if (this.videoUri) { this.videoToAudio() } else { ToastUtils.show('请上传视频') } }) - .visibility(!this.resultText ? Visibility.Visible : Visibility.None) + .visibility(StrUtil.isNull(this.resultText) ? Visibility.Visible : Visibility.None) Row() { 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 }) .backgroundColor(Color.White) diff --git a/entry/src/main/ets/pages/main/home/wx/material/WxImageMaterialPage.ets b/entry/src/main/ets/pages/main/home/wx/material/WxImageMaterialPage.ets index e12349f..f5a1de6 100644 --- a/entry/src/main/ets/pages/main/home/wx/material/WxImageMaterialPage.ets +++ b/entry/src/main/ets/pages/main/home/wx/material/WxImageMaterialPage.ets @@ -131,9 +131,9 @@ export struct WxImageMaterialPage { }) 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')) - .fontColor($r('app.color.color_50ffffff')) + .fontColor('#4D4F57') .fontSize(12) .lineHeight(20) .margin({ top: 9 }) diff --git a/entry/src/main/ets/pages/main/mine/MinePage.ets b/entry/src/main/ets/pages/main/mine/MinePage.ets index 53866a6..05ea825 100644 --- a/entry/src/main/ets/pages/main/mine/MinePage.ets +++ b/entry/src/main/ets/pages/main/mine/MinePage.ets @@ -40,7 +40,6 @@ export struct MinePage { @Monitor('viewModel.userEntity') onUserinfoChange(monitor: IMonitor) { this.userinfo = monitor.value()?.now as UserEntity; - this.menuList = mineMenuList().convertToArray() } @Monitor('viewModel.wxService') @@ -56,6 +55,7 @@ export struct MinePage { @Monitor('viewModel.diamondInfo') onDiamondInfoChange(monitor: IMonitor) { this.diamondInfo = monitor.value()?.now as DiamondDetailEntity; + this.menuList = mineMenuList(this.diamondInfo && this.diamondInfo.buy_total > 0).convertToArray() } aboutToAppear(): void { diff --git a/entry/src/main/ets/pages/main/mine/diamond/DiamondPage.ets b/entry/src/main/ets/pages/main/mine/diamond/DiamondPage.ets index 68b550d..670c92e 100644 --- a/entry/src/main/ets/pages/main/mine/diamond/DiamondPage.ets +++ b/entry/src/main/ets/pages/main/mine/diamond/DiamondPage.ets @@ -31,6 +31,7 @@ struct DiamondPage { @Local isAgree: boolean = false; @Local payType: number = 0; //0微信支付 1支付宝支付 @Local totalPrice: number = 0; + @Local offsetY: number = 0 showQueryTip: boolean = false //是否显示支付状态查询提示 @@ -378,6 +379,9 @@ struct DiamondPage { } .layoutWeight(1) .scrollBar(BarState.Off) + .onWillScroll((_xOffset, yOffset) => { + this.offsetY += yOffset + }) Column() { Row() { @@ -430,7 +434,9 @@ struct DiamondPage { onRightClick: () => { this.showRuleDialog() } - }).id('titleBar') + }) + .opacity(Math.min(Math.max(1 - this.offsetY / 300, 0), 1)) + .id('titleBar') } .width('100%') .height('100%') diff --git a/entry/src/main/ets/utils/ImageUtils.ets b/entry/src/main/ets/utils/ImageUtils.ets index 7b1a159..c50bd72 100644 --- a/entry/src/main/ets/utils/ImageUtils.ets +++ b/entry/src/main/ets/utils/ImageUtils.ets @@ -17,10 +17,10 @@ export class ImageUtils { const height: number = imageInfo.size.height; const scaleWidth: number = w / width; 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 = { editable: true, - pixelFormat: image.PixelMapFormat.RGB_565, + pixelFormat: image.PixelMapFormat.RGBA_8888, size: { height: h, width: w } }; // 采用RGB_565格式创建画布PixelMap diff --git a/entry/src/main/ets/view/CustomWatermarkView.ets b/entry/src/main/ets/view/CustomWatermarkView.ets new file mode 100644 index 0000000..cc968e5 --- /dev/null +++ b/entry/src/main/ets/view/CustomWatermarkView.ets @@ -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 + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/view/MaterialItemView.ets b/entry/src/main/ets/view/MaterialItemView.ets index 2ebdc22..15ad32a 100644 --- a/entry/src/main/ets/view/MaterialItemView.ets +++ b/entry/src/main/ets/view/MaterialItemView.ets @@ -14,7 +14,7 @@ export struct VideoMaterialItemView { Image(this.media?.thumb) .width('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')) .id('iv_thumb') @@ -68,6 +68,7 @@ export struct VideoMaterialItemView { .textOverflow({ overflow: TextOverflow.Ellipsis }) .ellipsisMode(EllipsisMode.END) .padding({left: 8, top: 10, right: 8, bottom: 10}) + .visibility(this.media?.title ? Visibility.Visible : Visibility.None) } .backgroundColor(Color.White) .borderRadius(10) diff --git a/entry/src/main/ets/view/WaterMarkerView.ets b/entry/src/main/ets/view/WatermarkView.ets similarity index 96% rename from entry/src/main/ets/view/WaterMarkerView.ets rename to entry/src/main/ets/view/WatermarkView.ets index 7d915f0..6a7d0b5 100644 --- a/entry/src/main/ets/view/WaterMarkerView.ets +++ b/entry/src/main/ets/view/WatermarkView.ets @@ -2,7 +2,7 @@ import { StrUtil } from '@pura/harmony-utils'; import { ActionType, Position, RectPosition } from './RectCropView'; @ComponentV2 -export struct WaterMarkerView { +export struct WatermarkView { private settings: RenderingContextSettings = new RenderingContextSettings(true); private canvasContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private actionType: ActionType = ActionType.move; @@ -14,7 +14,9 @@ export struct WaterMarkerView { @Param onClose?: () => void = undefined @Param content: string = '' + @Param textColor: string = '' @Param imagePath: string = '' + @Param imageRadius: number = 0 @Local clipRect: RectPosition = { x: 0, @@ -38,13 +40,13 @@ export struct WaterMarkerView { }) .width(this.clipRect.width) .height(this.clipRect.height) - .fontColor(Color.White) + .fontColor(this.textColor ? this.textColor : Color.White) .fontSize(this.fontSize) .textAlign(TextAlign.Center) .onSizeChange(() => { this.caleTextSize() }) - .id("textWaterMarker") + .id('textWatermark') } else if (StrUtil.isNotEmpty(this.imagePath)) { Image(this.imagePath) .position({ @@ -53,7 +55,8 @@ export struct WaterMarkerView { }) .width(this.clipRect.width) .height(this.clipRect.height) - .id("imageWaterMarker") + .borderRadius(this.imageRadius) + .id('imageWatermark') } Image($r('app.media.ic_right_bottom_rect')) diff --git a/entry/src/main/ets/viewModel/DownloadHistoryViewModel.ets b/entry/src/main/ets/viewModel/DownloadHistoryViewModel.ets index d8d2469..de245bb 100644 --- a/entry/src/main/ets/viewModel/DownloadHistoryViewModel.ets +++ b/entry/src/main/ets/viewModel/DownloadHistoryViewModel.ets @@ -9,7 +9,7 @@ export class DownloadHistoryViewModel extends BaseViewModel { @Trace getHistory?: Array; @Trace deleteHistory?: object; - async getHistoryList(page: string = '1', startTime: string, endTime: string) { + async getHistoryList(page: string, startTime: string, endTime: string) { this.showLoading(); try { const result = await apiService.getDownloadHistoryList(page, startTime, endTime); diff --git a/entry/src/main/resources/base/media/ic_add_watermark_image.webp b/entry/src/main/resources/base/media/ic_add_watermark_image.webp new file mode 100644 index 0000000..0c886fe Binary files /dev/null and b/entry/src/main/resources/base/media/ic_add_watermark_image.webp differ diff --git a/entry/src/main/resources/base/media/ic_arrow_dp22.png b/entry/src/main/resources/base/media/ic_arrow_dp22.png deleted file mode 100644 index 63db46e..0000000 Binary files a/entry/src/main/resources/base/media/ic_arrow_dp22.png and /dev/null differ diff --git a/entry/src/main/resources/base/media/ic_arrow_dp22.webp b/entry/src/main/resources/base/media/ic_arrow_dp22.webp new file mode 100644 index 0000000..89d509b Binary files /dev/null and b/entry/src/main/resources/base/media/ic_arrow_dp22.webp differ