OnlineUpdateLog.ets 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /**
  2. * 在线更新日志弹窗组件
  3. * 参考WebIndex.ets的成功实现,确保WebView正常工作
  4. */
  5. import { webview } from '@kit.ArkWeb';
  6. import { UpdateConstants } from '../common/constants/UpdateConstants';
  7. import { UpdateLogManager } from '../common/util/UpdateLogManager';
  8. import { ConfigurationConstant } from '@kit.AbilityKit';
  9. import { AppUtil, PreferencesUtil } from '@pura/harmony-utils';
  10. import { CommonConstants } from '../common/constants/CommonConstants';
  11. @Component
  12. export default struct OnlineUpdateLog {
  13. /** 弹窗控制器 */
  14. controller?: CustomDialogController;
  15. /** 关闭回调 */
  16. onClose?: () => void;
  17. /** 更新日志URL */
  18. @State updateLogUrl: string = '';
  19. /** 当前应用版本 */
  20. @State currentVersion: string = '';
  21. /** WebView控制器 */
  22. private webViewController: webview.WebviewController = new webview.WebviewController();
  23. /** 是否加载完成 */
  24. @State isLoading: boolean = true;
  25. /** 加载错误信息 */
  26. @State errorMessage: string = '';
  27. /** 加载进度 */
  28. @State progressValue: number = 0;
  29. /** 进度条是否可见 */
  30. @State progressVisible: boolean = true;
  31. /** 深色模式 */
  32. @State isDarkMode: boolean = false;
  33. @StorageProp('currentColorMode') currentMode: number = ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
  34. @StorageProp('themeColor') themeColor: string = CommonConstants.DEFAULT_THEME_COLOR;
  35. aboutToAppear() {
  36. try {
  37. // 获取当前应用版本
  38. this.getCurrentVersion();
  39. // 设置更新日志URL - 直接使用在线URL
  40. this.updateLogUrl = UpdateConstants.UPDATE_LOG_URL;
  41. // 检查深色模式
  42. this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK;
  43. let themeColor = PreferencesUtil.getStringSync('THEME_COLOR', CommonConstants.DEFAULT_THEME_COLOR);
  44. AppStorage.setOrCreate('themeColor', themeColor);
  45. this.themeColor = themeColor
  46. console.info('OnlineUpdateLogDialog URL:', this.updateLogUrl);
  47. console.info('OnlineUpdateLogDialog 开始加载在线更新日志');
  48. // 确保WebView控制器已初始化
  49. if (!this.webViewController) {
  50. this.webViewController = new webview.WebviewController();
  51. }
  52. } catch (error) {
  53. console.error('OnlineUpdateLogDialog aboutToAppear error:', error);
  54. this.errorMessage = '初始化失败';
  55. this.isLoading = false;
  56. }
  57. }
  58. /**
  59. * 获取当前应用版本号
  60. */
  61. private getCurrentVersion() {
  62. try {
  63. this.currentVersion = AppUtil.getVersionName()//UpdateConstants.APP_VERSION;
  64. } catch (error) {
  65. this.currentVersion = '1.0.0';
  66. }
  67. }
  68. /**
  69. * 记录已显示的版本,避免重复显示
  70. */
  71. private markVersionShown() {
  72. try {
  73. UpdateLogManager.markCurrentVersionShown();
  74. } catch (error) {
  75. console.error('OnlineUpdateLogDialog markVersionShown error:', error);
  76. }
  77. }
  78. /**
  79. * 颜色变亮工具方法
  80. */
  81. private lightenColor(color: string, amount: number): string {
  82. try {
  83. // 移除 # 号
  84. const hex = color.replace('#', '');
  85. // 转换为 RGB
  86. const r = parseInt(hex.substring(0, 2), 16);
  87. const g = parseInt(hex.substring(2, 4), 16);
  88. const b = parseInt(hex.substring(4, 6), 16);
  89. // 增加亮度
  90. const newR = Math.min(255, Math.floor(r + (255 - r) * amount));
  91. const newG = Math.min(255, Math.floor(g + (255 - g) * amount));
  92. const newB = Math.min(255, Math.floor(b + (255 - b) * amount));
  93. // 转换回十六进制
  94. const newHex = '#' +
  95. newR.toString(16).padStart(2, '0') +
  96. newG.toString(16).padStart(2, '0') +
  97. newB.toString(16).padStart(2, '0');
  98. return newHex;
  99. } catch (error) {
  100. console.error('lightenColor error:', error);
  101. return color; // 出错时返回原色
  102. }
  103. }
  104. /**
  105. * 组件销毁时清理资源
  106. */
  107. aboutToDisappear() {
  108. try {
  109. console.info('OnlineUpdateLogDialog aboutToDisappear');
  110. // 清理WebView控制器
  111. if (this.webViewController) {
  112. // 这里可以添加WebView的清理逻辑,如果需要的话
  113. }
  114. } catch (error) {
  115. console.error('OnlineUpdateLogDialog aboutToDisappear error:', error);
  116. }
  117. }
  118. build() {
  119. Column() {
  120. // 版本信息和进度条
  121. Column() {
  122. Row() {
  123. Text('当前版本:')
  124. .fontSize(15)
  125. .fontColor(this.isDarkMode ? '#E0E0E0' : Color.Gray)
  126. Text(`v${this.currentVersion}`)
  127. .fontSize(15)
  128. .fontColor(this.themeColor)
  129. .fontWeight(FontWeight.Medium)
  130. }
  131. .alignSelf(ItemAlign.Start)
  132. .margin({ bottom: 8 })
  133. // 进度条 - 使用主题色
  134. if (this.progressVisible && this.progressValue < 100) {
  135. Column() {
  136. Progress({ value: this.progressValue, total: 100, type: ProgressType.Linear })
  137. .width('100%')
  138. .height(4)
  139. .color(this.themeColor)
  140. .backgroundColor(this.isDarkMode ? '#4A4A4A' : '#E0E0E0')
  141. .borderRadius(2)
  142. Text(`加载中... ${this.progressValue}%`)
  143. .fontSize(10)
  144. .fontColor(this.isDarkMode ? '#E0E0E0' : Color.Gray)
  145. .margin({ top: 4 })
  146. .alignSelf(ItemAlign.End)
  147. }
  148. .width('100%')
  149. }
  150. }
  151. .width('100%')
  152. .padding({ left: 20, right: 20, top: 12, bottom: 8 })
  153. .backgroundColor(this.isDarkMode ? '#3A3A3A' : '#F8F9FA')
  154. .borderRadius({
  155. topLeft: 0,
  156. topRight: 0,
  157. bottomLeft: 8,
  158. bottomRight: 8
  159. })
  160. // WebView内容区域 - 完全参考WebIndex.ets的实现
  161. if (this.errorMessage) {
  162. // 错误状态
  163. Column() {
  164. // 错误图标背景
  165. Column() {
  166. Text('❌')
  167. .fontSize(32)
  168. }
  169. .width(64)
  170. .height(64)
  171. .backgroundColor(this.isDarkMode ? '#4A4A4A' : '#FFF5F5')
  172. .borderRadius(32)
  173. .justifyContent(FlexAlign.Center)
  174. .alignItems(HorizontalAlign.Center)
  175. .border({
  176. width: 1,
  177. color: this.isDarkMode ? '#666666' : '#FED7D7'
  178. })
  179. Text('加载失败')
  180. .fontSize(16)
  181. .fontColor(this.isDarkMode ? Color.White : Color.Black)
  182. .fontWeight(FontWeight.Medium)
  183. .margin({ top: 16 })
  184. Text(this.errorMessage)
  185. .fontSize(12)
  186. .fontColor(this.isDarkMode ? '#E0E0E0' : Color.Gray)
  187. .margin({ top: 8, left: 20, right: 20 })
  188. .textAlign(TextAlign.Center)
  189. .maxLines(3)
  190. Button('重试')
  191. .fontSize(14)
  192. .backgroundColor(this.themeColor)
  193. .fontColor(Color.White)
  194. .borderRadius(8)
  195. .width(120)
  196. .height(40)
  197. .margin({ top: 20 })
  198. .onClick(() => {
  199. try {
  200. this.errorMessage = '';
  201. this.isLoading = true;
  202. this.progressValue = 0;
  203. this.progressVisible = true;
  204. // 重新加载
  205. if (this.webViewController) {
  206. this.webViewController.refresh();
  207. }
  208. } catch (error) {
  209. console.error('OnlineUpdateLogDialog 重试失败:', error);
  210. this.errorMessage = '重试失败,请稍后再试';
  211. }
  212. })
  213. }
  214. .width('100%')
  215. .height(350)
  216. .justifyContent(FlexAlign.Center)
  217. .alignItems(HorizontalAlign.Center)
  218. .padding(20)
  219. .backgroundColor(this.isDarkMode ? '#2C2C2C' : Color.White)
  220. } else {
  221. // WebView内容 - 完全按照WebIndex.ets的方式实现
  222. Web({
  223. src: this.updateLogUrl,
  224. controller: this.webViewController
  225. })
  226. .width('100%')
  227. .height(350)
  228. .borderRadius(8)
  229. .backgroundColor(this.isDarkMode ? '#2C2C2C' : Color.White)
  230. // .border({
  231. // width: 1,
  232. // color: this.isDarkMode ? '#333333' : '#E0E0E0'
  233. // })
  234. .margin({ left: 12, right: 12, bottom: 8 })
  235. .darkMode(this.isDarkMode ? WebDarkMode.On : WebDarkMode.Off)
  236. .forceDarkAccess(this.isDarkMode)
  237. .onProgressChange((event) => {
  238. if (event) {
  239. console.info('OnlineUpdateLogDialog WebView进度:', event.newProgress);
  240. this.progressValue = event.newProgress;
  241. // 进度完成时隐藏进度条
  242. if (event.newProgress >= 100) {
  243. setTimeout(() => {
  244. this.progressVisible = false;
  245. this.isLoading = false;
  246. }, 500);
  247. }
  248. }
  249. })
  250. .onPageBegin(() => {
  251. console.info('OnlineUpdateLogDialog WebView开始加载:', this.updateLogUrl);
  252. this.isLoading = true;
  253. this.errorMessage = '';
  254. this.progressValue = 0;
  255. this.progressVisible = true;
  256. })
  257. .onPageEnd(() => {
  258. console.info('OnlineUpdateLogDialog WebView加载完成');
  259. this.isLoading = false;
  260. setTimeout(() => {
  261. this.progressVisible = false;
  262. }, 1000);
  263. })
  264. .onErrorReceive((event) => {
  265. const errorInfo = event?.error?.getErrorInfo() || '网络错误';
  266. console.error('OnlineUpdateLogDialog WebView加载错误:', errorInfo);
  267. this.isLoading = false;
  268. this.progressVisible = false;
  269. this.errorMessage = `加载失败:${errorInfo}`;
  270. })
  271. }
  272. // 底部按钮
  273. Row() {
  274. Button('稍后查看')
  275. .fontSize(14)
  276. .backgroundColor(this.isDarkMode ? '#666666' : '#9E9E9E')
  277. .fontColor(Color.White)
  278. .borderRadius(8)
  279. .layoutWeight(1)
  280. .height(44)
  281. .onClick(() => {
  282. try {
  283. if (this.onClose) {
  284. this.onClose();
  285. } else {
  286. this.controller?.close();
  287. }
  288. } catch (error) {
  289. console.error('OnlineUpdateLogDialog 稍后查看按钮失败:', error);
  290. }
  291. })
  292. Blank().width(12)
  293. Button('知道了')
  294. .fontSize(14)
  295. .backgroundColor(this.themeColor)
  296. .fontColor(Color.White)
  297. .borderRadius(8)
  298. .layoutWeight(1)
  299. .height(44)
  300. .onClick(() => {
  301. try {
  302. this.markVersionShown();
  303. if (this.onClose) {
  304. this.onClose();
  305. } else {
  306. this.controller?.close();
  307. }
  308. } catch (error) {
  309. console.error('OnlineUpdateLogDialog 知道了按钮失败:', error);
  310. }
  311. })
  312. }
  313. .visibility(Visibility.Hidden)
  314. .width('100%')
  315. .padding({ left: 20, right: 20, top: 16, bottom: 16 })
  316. .backgroundColor(this.isDarkMode ? '#3A3A3A' : '#F8F9FA')
  317. .borderRadius({
  318. topLeft: 0,
  319. topRight: 0,
  320. bottomLeft: 12,
  321. bottomRight: 12
  322. })
  323. }
  324. .backgroundColor(this.isDarkMode ? '#2C2C2C' : Color.White)
  325. .borderRadius(12)
  326. .width('92%')
  327. .constraintSize({ maxHeight: '85%' })
  328. .shadow({
  329. radius: 16,
  330. color: this.isDarkMode ? 'rgba(0,0,0,0.8)' : 'rgba(0,0,0,0.15)',
  331. offsetX: 0,
  332. offsetY: 4
  333. })
  334. }
  335. }