|
|
@@ -0,0 +1,239 @@
|
|
|
+import { CropController, CropView, IBestToast, YtAvoid, YTLog, yTRequest, yTRouter } from 'basic'
|
|
|
+import { fileIo } from '@kit.CoreFileKit'
|
|
|
+import { util } from '@kit.ArkTS'
|
|
|
+import { emitter } from '@kit.BasicServicesKit'
|
|
|
+
|
|
|
+@Builder
|
|
|
+function delPhotoPageBuilder() {
|
|
|
+ NavDestination() {
|
|
|
+ DelPhotoPage()
|
|
|
+ }
|
|
|
+ .hideTitleBar(true)
|
|
|
+}
|
|
|
+
|
|
|
+@Component
|
|
|
+struct DelPhotoPage {
|
|
|
+ @StorageProp(YtAvoid.safeBottomKey) private safeBottom: number = 0
|
|
|
+ @State private selectPhoto: string = ''
|
|
|
+ @State private frameWidth: number = 220
|
|
|
+ @State private frameHeight: number = 220
|
|
|
+ @State private startWidth: number = 220
|
|
|
+ @State private startHeight: number = 220
|
|
|
+ private declare type: 'bill' | 'header' | 'image'
|
|
|
+ private controller: CropController = new CropController()
|
|
|
+ private declare context: Context
|
|
|
+
|
|
|
+ aboutToAppear(): void {
|
|
|
+ this.selectPhoto = yTRouter.getDelPhotoParam().src
|
|
|
+ this.type = yTRouter.getDelPhotoParam().type
|
|
|
+ const tempContext = this.getUIContext().getHostContext()
|
|
|
+ if (tempContext === undefined) {
|
|
|
+ //抛出异常
|
|
|
+ throw new Error('DelPhotoPage context is null')
|
|
|
+ } else {
|
|
|
+ this.context = tempContext
|
|
|
+ }
|
|
|
+
|
|
|
+ YtAvoid.setStatusBarContentColor('#FFFFFF', this.context)
|
|
|
+ }
|
|
|
+
|
|
|
+ aboutToDisappear(): void {
|
|
|
+ YtAvoid.setStatusBarContentColor('#000000', this.context)
|
|
|
+ }
|
|
|
+
|
|
|
+ build() {
|
|
|
+ Column() {
|
|
|
+ Stack({ alignContent: Alignment.Center }) {
|
|
|
+ CropView({
|
|
|
+ src: this.selectPhoto,
|
|
|
+ controller: this.controller, // 控制器必须设置
|
|
|
+ maskColor: '#4D000000',
|
|
|
+ frameWidth: this.frameWidth,
|
|
|
+ frameHeight: this.frameHeight
|
|
|
+ })
|
|
|
+ .width("100%")
|
|
|
+ .layoutWeight(1)
|
|
|
+ .backgroundColor(Color.Black)
|
|
|
+ Column() {
|
|
|
+ Row() {
|
|
|
+ Text()
|
|
|
+ .height(30)
|
|
|
+ .aspectRatio(1)
|
|
|
+ .border({ width: { left: 8, top: 8 }, color: Color.White })
|
|
|
+ .offset({ x: -8, y: -8 })
|
|
|
+ .borderRadius({ topLeft: 5 })
|
|
|
+ .gesture(
|
|
|
+ PanGesture({ distance: 1 })
|
|
|
+ .onActionStart(() => {
|
|
|
+ // 记录拖拽开始时的初始尺寸
|
|
|
+ this.startWidth = this.frameWidth
|
|
|
+ this.startHeight = this.frameHeight
|
|
|
+ })
|
|
|
+ .onActionUpdate(event => {
|
|
|
+ // 基于初始尺寸计算新尺寸
|
|
|
+ const newWidth = Math.max(220, this.startWidth - event.offsetX)
|
|
|
+ const newHeight = Math.max(220, this.startHeight - event.offsetY)
|
|
|
+
|
|
|
+ // 同时更新两个维度
|
|
|
+ this.frameWidth = newWidth
|
|
|
+ this.frameHeight = newHeight
|
|
|
+ })
|
|
|
+ )
|
|
|
+
|
|
|
+ Text()
|
|
|
+ .height(30)
|
|
|
+ .aspectRatio(1)
|
|
|
+ .border({ width: { right: 8, top: 8 }, color: Color.White })
|
|
|
+ .offset({ x: 8, y: -8 })
|
|
|
+ .borderRadius({ topRight: 5 })
|
|
|
+ .gesture(
|
|
|
+ PanGesture({ distance: 1 })
|
|
|
+ .onActionStart(() => {
|
|
|
+ // 记录拖拽开始时的初始尺寸
|
|
|
+ this.startWidth = this.frameWidth
|
|
|
+ this.startHeight = this.frameHeight
|
|
|
+ })
|
|
|
+ .onActionUpdate(event => {
|
|
|
+ // 基于初始尺寸计算新尺寸
|
|
|
+ const newWidth = Math.max(220, this.startWidth + event.offsetX)
|
|
|
+ const newHeight = Math.max(220, this.startHeight - event.offsetY)
|
|
|
+
|
|
|
+ // 同时更新两个维度
|
|
|
+ this.frameWidth = newWidth
|
|
|
+ this.frameHeight = newHeight
|
|
|
+ })
|
|
|
+ )
|
|
|
+ }
|
|
|
+ .width('100%')
|
|
|
+ .height(25)
|
|
|
+ .justifyContent(FlexAlign.SpaceBetween)
|
|
|
+ .borderRadius(8)
|
|
|
+
|
|
|
+
|
|
|
+ Row() {
|
|
|
+ Text()
|
|
|
+ .height(30)
|
|
|
+ .aspectRatio(1)
|
|
|
+ .border({ width: { left: 8, bottom: 8 }, color: Color.White })
|
|
|
+ .offset({ x: -8, y: 8 })
|
|
|
+ .borderRadius({ bottomLeft: 5 })
|
|
|
+ .gesture(
|
|
|
+ PanGesture({ distance: 1 })
|
|
|
+ .onActionStart(() => {
|
|
|
+ // 记录拖拽开始时的初始尺寸
|
|
|
+ this.startWidth = this.frameWidth
|
|
|
+ this.startHeight = this.frameHeight
|
|
|
+ })
|
|
|
+ .onActionUpdate(event => {
|
|
|
+ // 基于初始尺寸计算新尺寸
|
|
|
+ const newWidth = Math.max(220, this.startWidth - event.offsetX)
|
|
|
+ const newHeight = Math.max(220, this.startHeight + event.offsetY)
|
|
|
+
|
|
|
+ // 同时更新两个维度
|
|
|
+ this.frameWidth = newWidth
|
|
|
+ this.frameHeight = newHeight
|
|
|
+ })
|
|
|
+ )
|
|
|
+
|
|
|
+ Text()
|
|
|
+ .height(30)
|
|
|
+ .aspectRatio(1)
|
|
|
+ .border({ width: { right: 8, bottom: 8 }, color: Color.White })
|
|
|
+ .borderRadius({ bottomRight: 5 })
|
|
|
+ .offset({ x: 8, y: 8 })
|
|
|
+ .gesture(
|
|
|
+ PanGesture({ distance: 1 })
|
|
|
+ .onActionStart(() => {
|
|
|
+ // 记录拖拽开始时的初始尺寸
|
|
|
+ this.startWidth = this.frameWidth
|
|
|
+ this.startHeight = this.frameHeight
|
|
|
+ })
|
|
|
+ .onActionUpdate(event => {
|
|
|
+ // 基于初始尺寸计算新尺寸
|
|
|
+ const newWidth = Math.max(220, this.startWidth + event.offsetX)
|
|
|
+ const newHeight = Math.max(220, this.startHeight + event.offsetY)
|
|
|
+
|
|
|
+ // 同时更新两个维度
|
|
|
+ this.frameWidth = newWidth
|
|
|
+ this.frameHeight = newHeight
|
|
|
+ })
|
|
|
+ )
|
|
|
+ }
|
|
|
+ .width('100%')
|
|
|
+ .height(25)
|
|
|
+
|
|
|
+ .justifyContent(FlexAlign.SpaceBetween)
|
|
|
+ }
|
|
|
+ .width(this.frameWidth)
|
|
|
+ .height(this.frameHeight)
|
|
|
+ .justifyContent(FlexAlign.SpaceBetween)
|
|
|
+ .hitTestBehavior(HitTestMode.Transparent)
|
|
|
+
|
|
|
+ }
|
|
|
+ .layoutWeight(1)
|
|
|
+
|
|
|
+ Row() {
|
|
|
+ Image($r('app.media.back'))
|
|
|
+ .width(36)
|
|
|
+ .aspectRatio(1)
|
|
|
+ .onClick(() => {
|
|
|
+ yTRouter.routerBack()
|
|
|
+ })
|
|
|
+
|
|
|
+ Image($r('app.media.make_sure'))
|
|
|
+ .height(56)
|
|
|
+ .aspectRatio(1)
|
|
|
+ .onClick(() => {
|
|
|
+ //使用 controller 获取裁剪图片
|
|
|
+ this.controller.cropWithPath({ format: 'image/jpeg', quality: 100 })
|
|
|
+ .then(async (path) => {
|
|
|
+ // path 为裁剪后的文件路径
|
|
|
+ try {
|
|
|
+ const photoName = util.generateRandomUUID()
|
|
|
+ const photoType = '.jpeg'
|
|
|
+ const fullpath = this.context.cacheDir + '/' + photoName + photoType
|
|
|
+ const photo = fileIo.openSync(path)
|
|
|
+ await fileIo.copyFile(photo.fd, fullpath)
|
|
|
+
|
|
|
+ if (this.type == 'header') {
|
|
|
+ IBestToast.showLoading({ message: '上传中...' })
|
|
|
+ yTRequest.uploadHeadImg(this.getUIContext().getHostContext()!, fullpath, () => {
|
|
|
+ yTRequest.refreshUserInfo(() => {
|
|
|
+ IBestToast.hide()
|
|
|
+ setTimeout(() => {
|
|
|
+ IBestToast.show({ message: '头像修改成功', type: 'success' })
|
|
|
+ }, 100)
|
|
|
+ })
|
|
|
+ })
|
|
|
+ yTRouter.routerBack()
|
|
|
+ }
|
|
|
+ if (this.type == 'image') {
|
|
|
+ IBestToast.showLoading({ message: '上传中...' })
|
|
|
+ yTRequest.uploadFile(this.getUIContext().getHostContext()!, fullpath, (url) => {
|
|
|
+ emitter.emit('upLoadEnd', { data: url })
|
|
|
+ IBestToast.hide()
|
|
|
+ yTRouter.routerBack()
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (e) {
|
|
|
+ YTLog.error(e)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ Image($r('app.media.rotate'))
|
|
|
+ .height(36)
|
|
|
+ .aspectRatio(1)
|
|
|
+ .onClick(() => {
|
|
|
+ this.controller.rotate()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ .width('100%')
|
|
|
+ .height(84)
|
|
|
+ .justifyContent(FlexAlign.SpaceAround)
|
|
|
+ }
|
|
|
+
|
|
|
+ .padding({ bottom: this.safeBottom })
|
|
|
+ }
|
|
|
+}
|