diff --git a/chatkit_ui/src/main/ets/viewmodel/ChatBaseViewModel.ets b/chatkit_ui/src/main/ets/viewmodel/ChatBaseViewModel.ets index 08b8da0..f9a9a3d 100644 --- a/chatkit_ui/src/main/ets/viewmodel/ChatBaseViewModel.ets +++ b/chatkit_ui/src/main/ets/viewmodel/ChatBaseViewModel.ets @@ -921,6 +921,18 @@ export class ChatBaseViewModel { // payload.put("apns-from-id", NimUIKit.getAccount());//ios需要 // msg.pushConfig = {} as V2NIMMessagePushConfig // msg.pushConfig.pushPayload='' + // 2. 设置推送负载(新增核心代码) + const pushPayload: Record | string> = { + "vivoField": {"classification":"1"}, + "apns-collapse-id": "321", + "apns-from-id": ChatKitClient.getLoginUserId() + }; + + if (!msg.pushConfig) { + msg.pushConfig = {} as V2NIMMessagePushConfig; + } + msg.pushConfig.pushPayload = JSON.stringify(pushPayload) + ChatRepo.sendMessage(this.beforeSendMessage(msg), this.conversationId!, params, progress) .catch((err: BusinessError) => { console.error("net ease send message error", err.code, err.message); diff --git a/commons/basic/Index.ets b/commons/basic/Index.ets index 48418af..6a19bc6 100644 --- a/commons/basic/Index.ets +++ b/commons/basic/Index.ets @@ -99,4 +99,6 @@ export { TripleOptionDialog } from './src/main//ets/Views/TripleOptionDialog' export { HdTwoNav } from './src/main/ets/components/HdTwoNav' -export { NotificationUtil } from './src/main/ets/utils/NotificationUtil' \ No newline at end of file +export { NotificationUtil } from './src/main/ets/utils/NotificationUtil' + +export { ScanUtil } from './src/main/ets/utils/ScanUtil' \ No newline at end of file diff --git a/commons/basic/src/main/ets/constants/BasicConstant.ets b/commons/basic/src/main/ets/constants/BasicConstant.ets index 8675586..49a8a13 100644 --- a/commons/basic/src/main/ets/constants/BasicConstant.ets +++ b/commons/basic/src/main/ets/constants/BasicConstant.ets @@ -50,6 +50,7 @@ export class BasicConstant { static readonly cancelRes = BasicConstant.urlExpert+'cancelRes' static readonly caseDetail = BasicConstant.urlExpert+'caseDetail' static readonly getFollowUp = BasicConstant.urlExpert+'getFollowUp' + static readonly sendWebsocketMsg = BasicConstant.wxUrl+'watchlive/sendWebsocketMsg' static readonly deleteFollowUp = BasicConstant.urlExpert+'deleteFollowUp' static readonly addFollowUps = BasicConstant.urlExpert+'addFollowUps' static readonly addFollowUp = BasicConstant.urlExpert+'addFollowUp' @@ -142,5 +143,7 @@ export class BasicConstant { //聊天类型普通聊天与公益咨询 static readonly general = "general"; static readonly consult = "consult"; + + static readonly ExpertAesKey = 'deoep09_klodLdAo' } diff --git a/commons/basic/src/main/ets/utils/AESEncryptionDecryption.ets b/commons/basic/src/main/ets/utils/AESEncryptionDecryption.ets index eb684d0..1dad307 100644 --- a/commons/basic/src/main/ets/utils/AESEncryptionDecryption.ets +++ b/commons/basic/src/main/ets/utils/AESEncryptionDecryption.ets @@ -4,6 +4,9 @@ import { buffer, util } from '@kit.ArkTS'; export const base = new util.Base64Helper(); +const kBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +const kBase64PaddingChar = '='; + export class AESEncryptionDecryption { // 字节流转成可理解的字符串 @@ -111,5 +114,98 @@ export class AESEncryptionDecryption { console.info(err.message); } } + + // 解密 + static async aes128Decrypt(data: Uint8Array, key: string): Promise { + try { + // 创建对称密钥生成器 + const symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES128'); + // 创建加密解密工具 + const cipher = cryptoFramework.createCipher('AES128|ECB|PKCS7'); + // 将字符串密钥转换为DataBlob格式 + const keyBlob: cryptoFramework.DataBlob = { + data: new Uint8Array(new util.TextEncoder().encodeInto(key)) + }; + // 生成对称密钥 + const symKey = await symKeyGenerator.convertKey(keyBlob); + // 初始化解密模式 + await cipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, null); + // 执行解密 + const decryptData = await cipher.doFinal({ data: data }); + return decryptData.data; + } catch (error) { + console.error("AES解密过程中出错:", JSON.stringify(error)); + return data + } + } + + //加密 + static async aes128Encrypt(data: Uint8Array, key: string): Promise { + const algorithm = 'AES128|ECB|PKCS7'; + try { + const symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES128'); + if (!symKeyGenerator) { + console.error('创建密钥生成器失败') + } + const textEncoder = new util.TextEncoder(); + const keyData: Uint8Array = textEncoder.encodeInto(key); + const keyBlob: cryptoFramework.DataBlob = { data: keyData }; + const symKey = await symKeyGenerator.convertKey(keyBlob); + if (!symKey) { + console.error('密钥转换失败') + } + const cipher = cryptoFramework.createCipher(algorithm) + if (!cipher) { + console.error('创建加密器失败') + } + await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, null); + const encryptResult = await cipher.doFinal({ data }); + return encryptResult.data; + } catch (error) { + console.error(`AES加密错误: ${JSON.stringify(error)}`); + const emptyBuffer = new Uint8Array(0); + return emptyBuffer + } + } + + static customBase64Encode(data: Uint8Array): string { + if (!data || data.length === 0) { + return ""; + } + const inputLength = data.length; + const maxLength = Math.floor((inputLength + 2) / 3) * 4; + + const resultChars: string[] = []; + let srcIndex = 0; + + while (inputLength - srcIndex >= 3) { + const byte1 = data[srcIndex++] & 0xFF; + const byte2 = data[srcIndex++] & 0xFF; + const byte3 = data[srcIndex++] & 0xFF; + + resultChars.push(kBase64EncodeChars.charAt(byte1 >>> 2)); + resultChars.push(kBase64EncodeChars.charAt(((byte1 & 0x03) << 4) | (byte2 >>> 4))); + resultChars.push(kBase64EncodeChars.charAt(((byte2 & 0x0F) << 2) | (byte3 >>> 6))); + resultChars.push(kBase64EncodeChars.charAt(byte3 & 0x3F)); + } + + if (inputLength - srcIndex > 0) { + const byte1 = data[srcIndex++] & 0xFF; + resultChars.push(kBase64EncodeChars.charAt(byte1 >>> 2)); + + if (inputLength - srcIndex === 0) { + resultChars.push(kBase64EncodeChars.charAt((byte1 & 0x03) << 4)); + resultChars.push(kBase64PaddingChar); + resultChars.push(kBase64PaddingChar); + } else { + const byte2 = data[srcIndex] & 0xFF; + resultChars.push(kBase64EncodeChars.charAt(((byte1 & 0x03) << 4) | (byte2 >>> 4))); + resultChars.push(kBase64EncodeChars.charAt((byte2 & 0x0F) << 2)); + resultChars.push(kBase64PaddingChar); + } + } + + return resultChars.join(''); + } } diff --git a/commons/basic/src/main/ets/utils/CharUtil.ets b/commons/basic/src/main/ets/utils/CharUtil.ets new file mode 100644 index 0000000..646422c --- /dev/null +++ b/commons/basic/src/main/ets/utils/CharUtil.ets @@ -0,0 +1,105 @@ +import { i18n } from '@kit.LocalizationKit'; + +export class CharUtil { + + + /** + * 判断字符串char是否是数字 + * @param char + * @returns + */ + static isDigit(char: string): boolean { + return i18n.Unicode.isDigit(char); + } + + /** + * 判断字符串char是否是字母 + * @param char + * @returns + */ + static isLetter(char: string): boolean { + return i18n.Unicode.isLetter(char); + } + + /** + * 判断字符串char是否是小写字母 + * @param char + * @returns + */ + static isLowerCase(char: string): boolean { + return i18n.Unicode.isLowerCase(char); + } + + /** + * 判断字符串char是否是大写字母 + * @param char + * @returns + */ + static isUpperCase(char: string): boolean { + return i18n.Unicode.isUpperCase(char); + } + + /** + * 判断字符串char是否是空格符 + * @param char + * @returns + */ + static isSpaceChar(char: string): boolean { + return i18n.Unicode.isSpaceChar(char); + } + + /** + * 判断字符串char是否是空白符 + * @param char + * @returns + */ + static isWhitespace(char: string): boolean { + return i18n.Unicode.isWhitespace(char); + } + + /** + * 判断字符串char是否是从右到左语言的字符 + * @param char + * @returns + */ + static isRTL(char: string): boolean { + return i18n.Unicode.isRTL(char); + } + + /** + * 判断字符串char是否是表意文字 + * @param char + * @returns + */ + static isIdeograph(char: string): boolean { + return i18n.Unicode.isIdeograph(char); + } + + + /** + * 判断是否空白符 空白符包括空格、制表符、全角空格和不间断空格 + * @param c + * @returns + */ + static isBlankChar(c: number): boolean { + return CharUtil.isWhitespace(c.toString()) + || CharUtil.isSpaceChar(c.toString()) + || c === 0xFEFF || c === 0x202A || c === 0x0000; + } + + + /** + * 判断字符是否位于ASCII范围内(其中0-31是控制字符,32-127表示从A到Z的字母字符) + * @param char 字符 + * @returns + */ + static isAscii(char: string): boolean { + if (char.length === 1) { //确保输入的是单个字符 + return char.charCodeAt(0) < 128; + } else { + return false; + } + } + + +} \ No newline at end of file diff --git a/commons/basic/src/main/ets/utils/ScanUtil.ets b/commons/basic/src/main/ets/utils/ScanUtil.ets new file mode 100644 index 0000000..7a80b31 --- /dev/null +++ b/commons/basic/src/main/ets/utils/ScanUtil.ets @@ -0,0 +1,95 @@ +import { detectBarcode, generateBarcode, scanBarcode, scanCore } from '@kit.ScanKit'; +import { image } from '@kit.ImageKit'; +import { AppUtil } from './AppUtil'; +// import { PhotoHelper } from '../photo/PhotoHelper'; +import { photoAccessHelper } from '@kit.MediaLibraryKit'; + +export class ScanUtil { + /** + * 调用默认界面扫码,使用Promise方式异步返回解码结果。 + * @param options + * scanTypes 设置扫码类型,默认扫码ALL(全部码类型)。 + * enableMultiMode 是否开启多码识别,默认false。true:多码识别、false:单码识别。 + * enableAlbum 是否开启相册,默认true。true-开启相册扫码、false-关闭相册扫码。 + * @returns ScanResult 扫码结果: + * scanType 码类型。 + * originalValue 码识别内容结果。 + * scanCodeRect 码识别位置信息。 + */ + static startScanForResult(options?: scanBarcode.ScanOptions): Promise { + if (options === undefined) { + options = { scanTypes: [scanCore.ScanType.ALL], enableMultiMode: true, enableAlbum: false }; + } + return scanBarcode.startScanForResult(AppUtil.getContext(), options); //启动扫码,拉起扫码界面 + } + + + /** + * 码图生成,使用Promise异步返回生成的码图。 + * @param content 码内容字符串 + * @param options 用于设置生成码图的参数: + * scanType 码类型。 + * width 码图宽,单位:px。取值范围:[200, 4096]。 + * height 码图高,单位:px。取值范围:[200, 4096]。 + * margin 边距,单位:px,默认值为1,取值范围:[1, 10]。 + * level 纠错水平,默认值为LEVEL_H。此参数只在生成QR码时有效。 + * backgroundColor 生成码图背景颜色,HEX格式颜色,默认为白色(0xffffff)。 + * pixelMapColor 生成码图颜色,HEX格式颜色,默认为黑色(0x000000)。 + * @returns + */ + static generateBarcode(content: string, options?: generateBarcode.CreateOptions): Promise { + if (options === undefined) { + options = { scanType: scanCore.ScanType.QR_CODE, height: 800, width: 800, margin: 5 }; + } + return generateBarcode.createBarcode(content, options); + } + + + /** + * 通过picker拉起图库并选择图片,并调用图片识码 + * @param options + * @returns + */ + // static async onPickerScanForResult(options?: scanBarcode.ScanOptions): Promise> { + // const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); + // photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; + // photoSelectOptions.maxSelectNumber = 1; //单选 + // photoSelectOptions.isPhotoTakingSupported = true; //支持拍照。 + // photoSelectOptions.isEditSupported = false; + // photoSelectOptions.isOriginalSupported = false; + // let uris = await PhotoHelper.select(photoSelectOptions); + // return ScanUtil.onDetectBarCode(uris[0], options); + // } + + + /** + * 调用图片识码,使用Promise方式异步返回识码结果。 + * @param uri 图片路径。 + * @param options + * scanTypes 设置扫码类型,默认扫码ALL(全部码类型)。 + * enableMultiMode 是否开启多码识别,默认false。true:多码识别、false:单码识别。 + * enableAlbum 是否开启相册,默认true。true-开启相册扫码、false-关闭相册扫码。 + * @returns ScanResult 扫码结果: + * scanType 码类型。 + * originalValue 码识别内容结果。 + * scanCodeRect 码识别位置信息。 + */ + static onDetectBarCode(uri: string, options?: scanBarcode.ScanOptions): Promise> { + const inputImage: detectBarcode.InputImage = { uri: uri }; + if (options === undefined) { + options = { scanTypes: [scanCore.ScanType.ALL], enableMultiMode: true, enableAlbum: true }; + } + return detectBarcode.decode(inputImage, options); + } + + + /** + * 判断当前设备是否支持码能力 + * @returns + */ + static canIUseScan() { + return canIUse('SystemCapability.Multimedia.Scan.ScanBarcode'); + } + + +} \ No newline at end of file diff --git a/commons/basic/src/main/ets/utils/StrUtil.ets b/commons/basic/src/main/ets/utils/StrUtil.ets new file mode 100644 index 0000000..e5a5669 --- /dev/null +++ b/commons/basic/src/main/ets/utils/StrUtil.ets @@ -0,0 +1,335 @@ +import { CharUtil } from './CharUtil'; +import util from '@ohos.util'; +import { buffer } from '@kit.ArkTS'; +import { Base64Util } from './Base64Util'; + +export class StrUtil { + + + /** + * 判断字符串是否为空(undefined、null) + * @param str 被检测的字符串 + * @returns 是否为空 + */ + static isNull(str: string | undefined | null): boolean { + return str === undefined || str === null; + } + + /** + * 判断字符串是否为非空。true为非空空,否则false + * @param str + * @returns + */ + static isNotNull(str: string | undefined | null): boolean { + return false === StrUtil.isNull(str); + } + + + /** + * 判断字符串是否为空(undefined、null、字符串长度为0) + * @param str 被检测的字符串 + * @return 是否为空 + */ + static isEmpty(str: string | undefined | null): boolean { + return str === undefined || str === null || str.length === 0; + } + + /** + * 判断字符串是否为非空。true为非空空,否则false + * @param str + * @returns + */ + static isNotEmpty(str: string | undefined | null): boolean { + return false === StrUtil.isEmpty(str); + } + + + /** + * 判断字符串是否为空和空白符(空白符包括空格、制表符、全角空格和不间断空格)。true为空,否则false + * @param str + * @returns + */ + static isBlank(str: string | undefined | null): boolean { + let length: number = 0; + if ((str === undefined) || (str === null) || ((length = str.length) === 0)) { + return true; + } + for (let i = 0; i < length; i++) { + if (false == CharUtil.isBlankChar(str.charCodeAt(i))) { + return false; //只要有一个非空字符即为非空字符串 + } + } + return true; + } + + /** + * 判断字符串是否为非空和空白符(空白符包括空格、制表符、全角空格和不间断空格)true为非空,否则false + * @param str + * @returns + */ + static isNotBlank(str: string | undefined | null): boolean { + return false === StrUtil.isBlank(str); + } + + + /** + * 格式化字符串 + * @param source + * @param defaultValue + * @returns + */ + static toStr(source: string | null | undefined, defaultValue = ""): string { + if (source === null || source === undefined) { + return defaultValue; + } + return String(source); + } + + + /** + * 替换字符串中匹配的正则为给定的字符串 + * @param str 待替换的字符串 + * @param pattern 要匹配的内容正则或字符串 + * @param replaceValue 替换的内容 + * @returns + */ + static replace(str: string, pattern: RegExp | string, replaceValue: string = ''): string { + return str.replace(pattern, replaceValue); + } + + /** + * 替换字符串中所有匹配的正则为给定的字符串 + * @param str 待替换的字符串 + * @param pattern 要匹配的内容正则或字符串 + * @param replaceValue 替换的内容 + * @returns 返回替换后的字符串 + */ + static replaceAll(str: string, pattern: RegExp | string, replaceValue: string = ''): string { + return str.replaceAll(pattern, replaceValue); + } + + /** + * 判断字符串是否以给定的字符串开头 + * @param string 要检索的字符串 + * @param target 要检索字符 + * @param position 检索的位置 + * @returns + */ + static startsWith(string: string = '', target: string, position: number = 0): boolean { + return string.startsWith(target, position); + } + + + /** + * 判断字符串是否以给定的字符串结尾 + * @param str 要检索的字符串 + * @param target 要检索字符 + * @param position 检索的位置 + * @returns + */ + static endsWith(str: string = '', target: string, position: number = str.length): boolean { + return str.endsWith(target, position); + } + + + /** + * 将字符串重复指定次数 + * @param str 要重复的字符串 + * @param n 重复的次数 + * @returns + */ + static repeat(str: string = '', n: number = 1): string { + return str.repeat(n); + } + + + /** + * 将整个字符串转换为小写 + * @param str 要转换的字符串 + * @returns 返回小写的字符串 + */ + static toLower(str: string = ''): string { + return str.toLowerCase(); + } + + + /** + * 将整个字符串转换为大写 + * @param str 要转换的字符串 + * @returns 返回小写的字符串 + */ + static toUpper(str: string = ''): string { + return str.toUpperCase(); + } + + + /** + * 将字符串首字母转换为大写,剩下为小写 + * @param str 待转换的字符串 + * @returns 转换后的 + */ + static capitalize(str: string = ''): string { + if (StrUtil.isNotEmpty(str)) { + const firstChar = str.charAt(0).toUpperCase(); + const restChars = str.slice(1).toLowerCase(); + return firstChar + restChars; + } + return ''; + } + + + /** + * 判断两个传入的数值或者是字符串是否相等 + * @param source + * @param target + * @returns + */ + static equal(source: string | number, target: string | number): boolean { + return source === target; + } + + /** + * 判断两个传入的数值或者是字符串是否不相等 + * @param source + * @param target + * @returns + */ + static notEqual(source: string | number, target: string | number): boolean { + return false === StrUtil.equal(source, target); + } + + + /** + * 字符串转Uint8Array + * @param src 字符串 + * @returns Uint8Array + */ + public static strToUint8Array(src: string, encoding: buffer.BufferEncoding = 'utf-8'): Uint8Array { + const textEncoder = new util.TextEncoder(encoding); + const result = textEncoder.encodeInto(src); + return result; + } + + /** + * Uint8Array转字符串 + * @param src Uint8Array + * @returns 字符串 + */ + static unit8ArrayToStr(src: Uint8Array, encoding: buffer.BufferEncoding = 'utf-8'): string { + const textDecoder = util.TextDecoder.create(encoding, { ignoreBOM: true }) + const result = textDecoder.decodeToString(src, { stream: true }); + return result; + } + + + /** + * 16进制字符串转换unit8Array + * @param hexStr + * @returns + */ + static strToHex(hexStr: string): Uint8Array { + return new Uint8Array(buffer.from(hexStr, 'hex').buffer); + } + + /** + * 16进制unit8Array转字符串 + * @param arr + * @returns + */ + static hexToStr(arr: Uint8Array): string { + return buffer.from(arr).toString('hex'); + } + + + /** + * Bytes转字符串 + * @param bytes + * @returns + */ + public static bytesToStr(bytes: Uint8Array): string { + let str = "" + for (let i = 0; i < bytes.length; i++) { + str += String.fromCharCode(bytes[i]); + + } + return str; + } + + /** + * 字符串转Bytes + * @param str + * @returns + */ + public static strToBytes(str: string): Uint8Array { + let bytes: number[] = new Array(); + for (let i = 0; i < str.length; i++) { + bytes.push(str.charCodeAt(i)) + } + return new Uint8Array(bytes); + } + + /** + * Base64字符串转字符串 + * @param base64Str Base64字符串 + * @returns + */ + static base64ToStr(base64Str: string): string { + const uint8Array = Base64Util.decodeSync(base64Str); + const result = StrUtil.unit8ArrayToStr(uint8Array); + return result; + } + + + /** + * 字符串转ArrayBuffer + * @param str + * @returns + */ + static strToBuffer(src: string, encoding: buffer.BufferEncoding = 'utf-8'): ArrayBuffer { + const buf = buffer.from(src, encoding); + return buf.buffer; + } + + /** + * ArrayBuffer转字符串 + * @param str + * @returns + */ + static bufferToStr(src: ArrayBuffer, encoding: buffer.BufferEncoding = 'utf-8'): string { + const buf = buffer.from(src); + const result = buf.toString(encoding); + return result; + } + + + /** + * ArrayBuffer转Uint8Array + * @param str + * @returns + */ + static bufferToUint8Array(src: ArrayBuffer): Uint8Array { + return new Uint8Array(src); + } + + /** + * Uint8Array转ArrayBuffer + * @param str + * @returns + */ + static unit8ArrayToBuffer(src: Uint8Array): ArrayBuffer { + // return buffer.from(src).buffer; + return src.buffer as ArrayBuffer; + } + + + /** + * 获取系统错误码对应的详细信息 + * @param errno 错误码 + * @returns + */ + static getErrnoToString(errno: number): string { + return util.errnoToString(errno); + } + + +} diff --git a/features/Home/Index.ets b/features/Home/Index.ets index 0a93765..2c7c728 100644 --- a/features/Home/Index.ets +++ b/features/Home/Index.ets @@ -28,4 +28,6 @@ export { MeetingItemModel,MeetingModel,MeetingModels,ItemModel } from './src/mai export { VideoSelected } from './src/main/ets/pages/VideoSelected' -export { videoTools } from './src/main/ets/polyv/VideoUtil' \ No newline at end of file +export { videoTools } from './src/main/ets/polyv/VideoUtil' + +export { CustomScanResultComp }from './src/main/ets/components/CustomScanResultComp' \ No newline at end of file diff --git a/features/Home/src/main/ets/components/CustomScanResultComp.ets b/features/Home/src/main/ets/components/CustomScanResultComp.ets new file mode 100644 index 0000000..5ae52b0 --- /dev/null +++ b/features/Home/src/main/ets/components/CustomScanResultComp.ets @@ -0,0 +1,15 @@ +import { HdNav, ScanUtil } from '@itcast/basic' +import { promptAction } from '@kit.ArkUI' + +@Component +export struct CustomScanResultComp { + + aboutToAppear(): void { + } + + build() { + Column() { + HdNav({isLeftAction:false,title:'扫描二维码',showRightIcon:false,showRightText:false}) + } + } +} diff --git a/features/Home/src/main/ets/pages/HomePage.ets b/features/Home/src/main/ets/pages/HomePage.ets index f1e1683..7e5c157 100644 --- a/features/Home/src/main/ets/pages/HomePage.ets +++ b/features/Home/src/main/ets/pages/HomePage.ets @@ -117,7 +117,7 @@ export struct HomePage { Scroll(this.scroller) { Column() { if (this.homeData.news_list && this.homeData.news_list.length > 0) { - HomeSwiperComp({ newslist: this.homeData.news_list, expertData: this.homeData.expertDetail }) + HomeSwiperComp({ newslist: this.homeData.news_list?this.homeData.news_list:[], expertData: this.homeData.expertDetail }) .height(getDisplayWindowWidth().vp / 16 * 9) } if (this.homeData.icons_list && this.homeData.icons_list.length > 0) { diff --git a/features/Home/src/main/ets/pages/VideoPage.ets b/features/Home/src/main/ets/pages/VideoPage.ets index 4e8d206..a069492 100644 --- a/features/Home/src/main/ets/pages/VideoPage.ets +++ b/features/Home/src/main/ets/pages/VideoPage.ets @@ -1,7 +1,13 @@ -import { HdNav,BasicConstant } from '@itcast/basic' +import { HdNav,BasicConstant, ScanUtil, AESEncryptionDecryption, hdHttp, HdResponse, authStore, + Base64Util } from '@itcast/basic' import { ListComp } from '../components/ListComp' -import { router } from '@kit.ArkUI' +import { promptAction, router } from '@kit.ArkUI' +import cryptoFramework from '@ohos.security.cryptoFramework'; +import util from '@ohos.util'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { rcp } from '@kit.RemoteCommunicationKit'; + @Entry @Component export struct VideoPage { @@ -35,7 +41,15 @@ export struct VideoPage { { Column() { - HdNav({ title: '肝胆会议', showRightIcon: false, showLeftIcon: false,showRightText:false,rightText:'扫一扫' }) + HdNav({ title: '肝胆会议', showRightIcon: false, showLeftIcon: false,showRightText:true,rightText:'扫一扫',rightTextColor:$r('app.color.main_color'),rightItemAction:()=>{ + if (ScanUtil.canIUseScan()) { + ScanUtil.startScanForResult().then((scanResult) => { + decryptString(scanResult.originalValue) + }) + } else { + promptAction.showToast({message:'当前设备不支持扫码能力!',duration:1500}) + } + } }) Row() { Row() { @@ -230,4 +244,78 @@ function Line() { .height(0.5).width('100%').backgroundColor($r('app.color.devider_line')) } +async function decryptString(str:string) { + try { + const decodedData = Base64Util.decodeSync(str) + const decryptedData = await AESEncryptionDecryption.aes128Decrypt(decodedData, BasicConstant.ExpertAesKey) + const textDecoder = new util.TextDecoder() + const decryptedStr = textDecoder.decodeToString(decryptedData) + if (decryptedStr.includes("watchliveFrom:") || decryptedStr.includes("watchvideoFrom:")) { + const arrB = decryptedStr.split(":") + if (arrB.length === 2) { + const secondStr = arrB[1] + console.log("解密成功,第二部分字符串:", secondStr) + pushScanPage(secondStr) + } + } else { + console.error("您扫描的不是有效的肝胆相照平台二维码") + promptAction.showToast({message:'您扫描的不是有效的肝胆相照平台二维码',duration:1500}) + } + } catch (error) { + console.error("解密失败:", error) + } +} +//liveScanSuccess}8c30fb02189a44ed95d856f39a1fe792}1CBMDQbuOX3xbxAcxE5,Ios测试,expert/2025-07-09/7a4e8aa78bcb495b87ede343b7763ef9.jpg +//liveScanSuccess}8c30fb02189a44ed95d856f39a1fe792}1CBMDQbuOX3xbxAcxE5,Ios测试,expert/2025-07-09/7a4e8aa78bcb495b87ede343b7763ef9.jpg +//liveScanSuccess}8c30fb02189a44ed95d856f39a1fe792}1CBMDQbuOX3xbxAcxE5,Ios测试,expert/2025-07-09/7a4e8aa78bcb495b87ede343b7763ef9.jpg +// PfLvaZPedZHfbA0uwxOiOF76Du652Bsm89X1x1BlPoADdXYM1Tvg4PHHXXhK7BP1XSBDBc5aQbgw9+K9+Vr4HZfYQ9BKFtpz1bDPF+FiIsb+P6hXUwIYu5dy9EJjZUZBFJr8GQibSH3XwyqjqmsHAW3AVOWYZY6qvNenjoGjmjR0Msts21E+E31RBCK3Kvaj +// PfLvaZPedZHfbA0uwxOiOF76Du652Bsm89X1x1BlPoADdXYM1Tvg4PHHXXhK7BP1XSBDBc5aQbgw9+K9+Vr4HZfYQ9BKFtpz1bDPF+FiIsb+P6hXUwIYu5dy9EJjZUZBFJr8GQibSH3XwyqjqmsHAW3AVOWYZY6qvNenjoGjmjR0Msts21E+E31RBCK3Kvaj +// PfLvaZPedZHfbA0uwxOiOF76Du652Bsm89X1x1BlPoADdXYM1Tvg4PHHXXhK7BP1XSBDBc5aQbgw9%2BK9%2BVr4HZfYQ9BKFtpz1bDPF%2BFiIsb%2BP6hXUwIYu5dy9EJjZUZBFJr8GQibSH3XwyqjqmsHAW3AVOWYZY6qvNenjoGjmjR0Msts21E%2BE31RBCK3Kvaj +// B2e%2B96mEodDQ5EIsmcpfh6cJbH7WhjSkXrIz8JtGf2gREqwSckolodE2%2FdNTTssxvwLTAltHlphKiSYWT91IpBUkt30diwj0VF1elbS193JwyOF4AU%2FhJ%2FRYQtxUHrB%2BlRo65QEhktb7z79lsRuJwUKISPEbTkrCVzRx9QDGcihdsOe44ABgLH%2BmyFhgEsMC +// B2e%2B96mEodDQ5EIsmcpfh6cJbH7WhjSkXrIz8JtGf2gREqwSckolodE2%2FdNTTssxvwLTAltHlphKiSYWT91IpBUkt30diwj0VF1elbS193JwyOF4AU%2FhJ%2FRYQtxUHrB%2BlRo65QEhktb7z79lsRuJwUKISPEbTkrCVzRx9QDGcihdsOe44ABgLH%2BmyFhgEsMC +// B2e+96mEodDQ5EIsmcpfh6cJbH7WhjSkXrIz8JtGf2gREqwSckolodE2/dNTTssxvwLTAltHlphKiSYWT91IpBUkt30diwj0VF1elbS193JwyOF4AU/hJ/RYQtxUHrB+lRo65QEhktb7z79lsRuJwUKISPEbTkrCVzRx9QDGcihdsOe44ABgLH+myFhgEsMC +async function pushScanPage(str:string) { + const liceScanSuccess = `liveScanSuccess}${str}}${authStore.getUser().uuid},${authStore.getUser().realName},${authStore.getUser().photo}` + const textEncoder = new util.TextEncoder() + const inputData: Uint8Array = textEncoder.encodeInto(liceScanSuccess) + const scanData = await AESEncryptionDecryption.aes128Encrypt(inputData,BasicConstant.ExpertAesKey) + const base64Data = AESEncryptionDecryption.customBase64Encode(scanData) + const encodedString = encodeURIComponent(base64Data) + const postContent = new rcp.MultipartForm({ + 'message': encodedString + }) + const session = rcp.createSession() + session.post(BasicConstant.sendWebsocketMsg, { + data: postContent, + headers: { + 'Content-Type': 'application/json' + } + }) + .then((response) => { + let json:Record = JSON.parse(response+'') as Record + if(json.code == '1') { + router.pushUrl({url:'pages/VideoPage/CustomScanPage'}) + } else { + promptAction.showToast({ message: String(json.message), duration: 1000 }) + } + }) + .catch((err: BusinessError) => { + console.error(`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`); + }) + // hdHttp.post(BasicConstant.sendWebsocketMsg, { + // "message":base64Data + // } as Record).then(async (res: HdResponse) => { + // console.info('Response caseUuid'+res); + // let json:Record | Array>> = JSON.parse(res+'') as Record | Array>>; + // if(json.code == '1') { + // + // } else { + // console.error('获取患者信息失败:'+json.message) + // promptAction.showToast({ message: String(json.message), duration: 1000 }) + // } + // }).catch((err: BusinessError) => { + // console.error(`Response fails: ${err}`); + // }) +} + diff --git a/features/register/src/main/ets/view/LoginComp.ets b/features/register/src/main/ets/view/LoginComp.ets index 1a6978a..2975c4d 100644 --- a/features/register/src/main/ets/view/LoginComp.ets +++ b/features/register/src/main/ets/view/LoginComp.ets @@ -125,7 +125,9 @@ export struct LoginComp { } }) } else { + this.loadPatients()//登录成功后获取患者数据存入数据库 + this.loginstatus=true authStore.setUser(objs.data) // emitter.emit({ eventId: 100401 }) logger.info('Response state'+state); @@ -170,6 +172,14 @@ export struct LoginComp { console.info(`Response login succeeded: ${err}`); }) } + + async loadPatients() { + try { + await patientDbManager.patientsToFMDB(); + } catch (error) { + console.error('加载患者数据失败:', error); + } + } build() { Column() { HdNav({ title: '登录', showRightIcon: false,showLeftIcon:false }) diff --git a/products/expert/src/main/ets/pages/Home.ets b/products/expert/src/main/ets/pages/Home.ets index 7de868a..b2761ca 100644 --- a/products/expert/src/main/ets/pages/Home.ets +++ b/products/expert/src/main/ets/pages/Home.ets @@ -57,7 +57,7 @@ struct Home { emitter.emit('notification_status_changed') this.onChangeIndex() // emitter.emit({eventId:BasicConstant.notification_home_tab_change},{data:{'changeIndex':this.activeIndex}}) - this.loadPatients(); + // this.loadPatients(); } onPageHide(): void { diff --git a/products/expert/src/main/ets/pages/VideoPage/CustomScanResultPage.ets b/products/expert/src/main/ets/pages/VideoPage/CustomScanResultPage.ets new file mode 100644 index 0000000..147bbfe --- /dev/null +++ b/products/expert/src/main/ets/pages/VideoPage/CustomScanResultPage.ets @@ -0,0 +1,13 @@ +import { CustomScanResultComp } from 'home' + +@Entry +@Component +struct CustomScanPage { + build() { + RelativeContainer() { + CustomScanResultComp() + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/products/expert/src/main/resources/base/profile/main_pages.json b/products/expert/src/main/resources/base/profile/main_pages.json index 1fb6b96..0bc446b 100644 --- a/products/expert/src/main/resources/base/profile/main_pages.json +++ b/products/expert/src/main/resources/base/profile/main_pages.json @@ -45,6 +45,7 @@ "pages/WebView/WebPageSnapshot", "pages/VideoPage/PLVMediaPlayerOnlyVideoPage", "pages/Netease/OutpatientPage", - "pages/PatientsPage/GroupSendMessagePage" + "pages/PatientsPage/GroupSendMessagePage", + "pages/VideoPage/CustomScanResultPage" ] } \ No newline at end of file