DelPhotoPage.ets 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import {
  2. CropController,
  3. CropView,
  4. IBestToast,
  5. YTAvoid,
  6. YTLog,
  7. YTPhotoHelper,
  8. YTRequest,
  9. yTRouter,
  10. YTUserRequest
  11. } from 'basic'
  12. import { fileIo } from '@kit.CoreFileKit'
  13. import { util } from '@kit.ArkTS'
  14. import { emitter } from '@kit.BasicServicesKit'
  15. @Builder
  16. function delPhotoPageBuilder() {
  17. NavDestination() {
  18. DelPhotoPage()
  19. }
  20. .hideTitleBar(true)
  21. }
  22. @Component
  23. struct DelPhotoPage {
  24. @StorageProp(YTAvoid.SAFE_BOTTOM_KEY) private safeBottom: number = 0
  25. @State private selectPhoto: string = ''
  26. @State private frameWidth: number = 220
  27. @State private frameHeight: number = 220
  28. @State private startWidth: number = 220
  29. @State private startHeight: number = 220
  30. private declare type: 'bill' | 'header' | 'image'
  31. private controller: CropController = new CropController()
  32. private declare context: Context
  33. aboutToAppear(): void {
  34. this.selectPhoto = yTRouter.getDelPhotoParam().src
  35. this.type = yTRouter.getDelPhotoParam().type
  36. const tempContext = this.getUIContext().getHostContext()
  37. if (tempContext === undefined) {
  38. //抛出异常
  39. throw new Error('DelPhotoPage context is null')
  40. } else {
  41. this.context = tempContext
  42. }
  43. YTAvoid.setStatusBarContentColor('#FFFFFFFF', this.context)
  44. }
  45. aboutToDisappear(): void {
  46. YTAvoid.setStatusBarContentColor('#FF000000', this.context)
  47. }
  48. build() {
  49. Column() {
  50. Stack({ alignContent: Alignment.Center }) {
  51. CropView({
  52. src: this.selectPhoto,
  53. controller: this.controller, // 控制器必须设置
  54. maskColor: '#4D000000',
  55. frameWidth: this.frameWidth,
  56. frameHeight: this.frameHeight
  57. })
  58. .width("100%")
  59. .layoutWeight(1)
  60. .backgroundColor(Color.Black)
  61. Column() {
  62. Row() {
  63. Text()
  64. .height(30)
  65. .aspectRatio(1)
  66. .border({ width: { left: 8, top: 8 }, color: Color.White })
  67. .offset({ x: -8, y: -8 })
  68. .borderRadius({ topLeft: 5 })
  69. .gesture(
  70. PanGesture({ distance: 1 })
  71. .onActionStart(() => {
  72. // 记录拖拽开始时的初始尺寸
  73. this.startWidth = this.frameWidth
  74. this.startHeight = this.frameHeight
  75. })
  76. .onActionUpdate(event => {
  77. // 基于初始尺寸计算新尺寸
  78. const newWidth = Math.max(220, this.startWidth - event.offsetX)
  79. const newHeight = Math.max(220, this.startHeight - event.offsetY)
  80. // 同时更新两个维度
  81. this.frameWidth = newWidth
  82. this.frameHeight = newHeight
  83. })
  84. )
  85. Text()
  86. .height(30)
  87. .aspectRatio(1)
  88. .border({ width: { right: 8, top: 8 }, color: Color.White })
  89. .offset({ x: 8, y: -8 })
  90. .borderRadius({ topRight: 5 })
  91. .gesture(
  92. PanGesture({ distance: 1 })
  93. .onActionStart(() => {
  94. // 记录拖拽开始时的初始尺寸
  95. this.startWidth = this.frameWidth
  96. this.startHeight = this.frameHeight
  97. })
  98. .onActionUpdate(event => {
  99. // 基于初始尺寸计算新尺寸
  100. const newWidth = Math.max(220, this.startWidth + event.offsetX)
  101. const newHeight = Math.max(220, this.startHeight - event.offsetY)
  102. // 同时更新两个维度
  103. this.frameWidth = newWidth
  104. this.frameHeight = newHeight
  105. })
  106. )
  107. }
  108. .width('100%')
  109. .height(25)
  110. .justifyContent(FlexAlign.SpaceBetween)
  111. .borderRadius(8)
  112. Row() {
  113. Text()
  114. .height(30)
  115. .aspectRatio(1)
  116. .border({ width: { left: 8, bottom: 8 }, color: Color.White })
  117. .offset({ x: -8, y: 8 })
  118. .borderRadius({ bottomLeft: 5 })
  119. .gesture(
  120. PanGesture({ distance: 1 })
  121. .onActionStart(() => {
  122. // 记录拖拽开始时的初始尺寸
  123. this.startWidth = this.frameWidth
  124. this.startHeight = this.frameHeight
  125. })
  126. .onActionUpdate(event => {
  127. // 基于初始尺寸计算新尺寸
  128. const newWidth = Math.max(220, this.startWidth - event.offsetX)
  129. const newHeight = Math.max(220, this.startHeight + event.offsetY)
  130. // 同时更新两个维度
  131. this.frameWidth = newWidth
  132. this.frameHeight = newHeight
  133. })
  134. )
  135. Text()
  136. .height(30)
  137. .aspectRatio(1)
  138. .border({ width: { right: 8, bottom: 8 }, color: Color.White })
  139. .borderRadius({ bottomRight: 5 })
  140. .offset({ x: 8, y: 8 })
  141. .gesture(
  142. PanGesture({ distance: 1 })
  143. .onActionStart(() => {
  144. // 记录拖拽开始时的初始尺寸
  145. this.startWidth = this.frameWidth
  146. this.startHeight = this.frameHeight
  147. })
  148. .onActionUpdate(event => {
  149. // 基于初始尺寸计算新尺寸
  150. const newWidth = Math.max(220, this.startWidth + event.offsetX)
  151. const newHeight = Math.max(220, this.startHeight + event.offsetY)
  152. // 同时更新两个维度
  153. this.frameWidth = newWidth
  154. this.frameHeight = newHeight
  155. })
  156. )
  157. }
  158. .width('100%')
  159. .height(25)
  160. .justifyContent(FlexAlign.SpaceBetween)
  161. }
  162. .width(this.frameWidth)
  163. .height(this.frameHeight)
  164. .justifyContent(FlexAlign.SpaceBetween)
  165. .hitTestBehavior(HitTestMode.Transparent)
  166. }
  167. .layoutWeight(1)
  168. Row() {
  169. Image($r('app.media.back'))
  170. .width(36)
  171. .aspectRatio(1)
  172. .onClick(() => {
  173. yTRouter.routerBack()
  174. })
  175. Image($r('app.media.make_sure'))
  176. .height(56)
  177. .aspectRatio(1)
  178. .onClick(() => {
  179. //使用 controller 获取裁剪图片
  180. this.controller.cropWithPath({ format: 'image/jpeg', quality: 100 })
  181. .then(async (path) => {
  182. // path 为裁剪后的文件路径
  183. try {
  184. const photoName = util.generateRandomUUID()
  185. const photoType = '.jpeg'
  186. const fullpath = this.context.cacheDir + '/' + photoName + photoType
  187. const photo = fileIo.openSync(path)
  188. await fileIo.copyFile(photo.fd, fullpath)
  189. if (this.type == 'header') {
  190. IBestToast.showLoading({ message: '上传中...' })
  191. new YTPhotoHelper().manualCompression(fullpath, (fullpath) => {
  192. YTUserRequest.uploadHeadImg(fullpath, () => {
  193. YTUserRequest.refreshUserInfo(() => {
  194. IBestToast.hide()
  195. setTimeout(() => {
  196. IBestToast.show({ message: '头像修改成功', type: 'success' })
  197. }, 100)
  198. })
  199. })
  200. yTRouter.routerBack()
  201. })
  202. }
  203. if (this.type == 'image') {
  204. IBestToast.showLoading({ message: '上传中...' })
  205. YTRequest.uploadFile(fullpath, (url) => {
  206. emitter.emit('upLoadEnd', { data: url })
  207. IBestToast.hide()
  208. yTRouter.routerBack()
  209. })
  210. }
  211. } catch (e) {
  212. YTLog.error(e)
  213. }
  214. })
  215. })
  216. Image($r('app.media.rotate'))
  217. .height(36)
  218. .aspectRatio(1)
  219. .onClick(() => {
  220. this.controller.rotate()
  221. })
  222. }
  223. .width('100%')
  224. .height(84)
  225. .justifyContent(FlexAlign.SpaceAround)
  226. }
  227. .padding({ bottom: this.safeBottom })
  228. }
  229. }