feat(app): 新增版本更新和错误日志功能

- 新增 AppUpdateView 组件用于显示版本更新提示
- 实现版本检查和更新逻辑
- 添加错误日志收集和上传功能
- 新增 FeedbackView 组件用于用户反馈问题
- 优化 CrashHelper 类,支持错误日志格式化
这个提交包含在:
徐勤民 2024-11-07 19:59:52 +08:00
父节点 8ed43fb4c6
当前提交 1e25ca295d
共有 3 个文件被更改,包括 14 次插入7 次删除

查看文件

@ -214,7 +214,7 @@ export struct XWebview {
}) })
.onShowFileSelector((event) => { // 选择文件 .onShowFileSelector((event) => { // 选择文件
console.log('MyFileUploader onShowFileSelector invoked') console.log('MyFileUploader onShowFileSelector invoked')
const documentSelectOptions = new picker.DocumentSelectOptions(); const documentSelectOptions = new picker.DocumentSelectOptions()
let uri: string | null = null; let uri: string | null = null;
const documentViewPicker = new picker.DocumentViewPicker(); const documentViewPicker = new picker.DocumentViewPicker();
documentViewPicker.select(documentSelectOptions).then((documentSelectResult) => { documentViewPicker.select(documentSelectOptions).then((documentSelectResult) => {

查看文件

@ -17,6 +17,11 @@ export class CrashHelper {
private static observerId: number = -100; private static observerId: number = -100;
private static ErrorFilePath: string = ''; //错误日志文件路径 private static ErrorFilePath: string = ''; //错误日志文件路径
// 多条报错直接的分隔符
static separatorError = '--------------------------------------------------------\n'
// 单个报错信息的分隔符
// 报错信息格式 yyyy-MM-dd HH:mm:ss- 异常信息:\n'报错信息'
static separatorLine = '- 异常信息:\n'
/** /**
* 注册错误观测器。注册后可以捕获到应用产生的js crash,应用崩溃时进程不会退出。将异常信息写入本地文件。 * 注册错误观测器。注册后可以捕获到应用产生的js crash,应用崩溃时进程不会退出。将异常信息写入本地文件。
@ -29,7 +34,7 @@ export class CrashHelper {
} }
CrashHelper.observerId = errorManager.on('error', { CrashHelper.observerId = errorManager.on('error', {
onUnhandledException(errMsg) { onUnhandledException(errMsg) {
let errStr = `${TimeHelper.getTime()} - 异常信息:\n${errMsg}\n\n\n`; let errStr = `${CrashHelper.separatorError}${TimeHelper.getTime()} ${CrashHelper.separatorLine}${errMsg}\n\n\n`;
LogHelper.error(errMsg) LogHelper.error(errMsg)
CrashHelper.ErrorFilePath = FileHelper.getFilesDirPath("ErrorLog", "errorLog.txt") CrashHelper.ErrorFilePath = FileHelper.getFilesDirPath("ErrorLog", "errorLog.txt")
FileHelper.writeEasy(CrashHelper.ErrorFilePath, errStr); FileHelper.writeEasy(CrashHelper.ErrorFilePath, errStr);

查看文件

@ -3,6 +3,7 @@ import { camera, cameraPicker } from '@kit.CameraKit';
import { common } from '@kit.AbilityKit'; import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit'; import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit'; import { hilog } from '@kit.PerformanceAnalysisKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
const DOCUMENT_DEFAULT_SELECT_NUMBER: number = 9; //数量 const DOCUMENT_DEFAULT_SELECT_NUMBER: number = 9; //数量
@ -50,19 +51,20 @@ export class PickerHelper {
* @param options * @param options
* @returns * @returns
*/ */
static async selectPhoto(options?: picker.PhotoSelectOptions): Promise<Array<string>> { static async selectPhoto(options?: photoAccessHelper.PhotoSelectOptions): Promise<Array<string>> {
try { try {
if (!options) { if (!options) {
options = new picker.PhotoSelectOptions(); options = new photoAccessHelper.PhotoSelectOptions();
} }
if (!options.MIMEType) { //可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。 if (!options.MIMEType) { //可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。
options.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; options.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
} }
if (!options.maxSelectNumber) { //选择媒体文件数量的最大值,默认9 if (!options.maxSelectNumber) { //选择媒体文件数量的最大值,默认9
options.maxSelectNumber = DOCUMENT_DEFAULT_SELECT_NUMBER; options.maxSelectNumber = DOCUMENT_DEFAULT_SELECT_NUMBER;
} }
let photoPicker = new picker.PhotoViewPicker(); let photoPicker = new photoAccessHelper.PhotoViewPicker();
let photoSelectResult: picker.PhotoSelectResult = await photoPicker.select(options);
let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoPicker.select(options);
if (photoSelectResult && photoSelectResult.photoUris && photoSelectResult.photoUris.length > 0) { if (photoSelectResult && photoSelectResult.photoUris && photoSelectResult.photoUris.length > 0) {
return photoSelectResult.photoUris; return photoSelectResult.photoUris;
} else { } else {