commit 36b6c794df8f48646a88a8877258a9e083e1e3a7 Author: 马超 <871197610@qq.com> Date: Sat Oct 25 18:20:38 2025 +0800 首次提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..66d763e --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer +/entry/.preview/ +/entry/build/ +/entry/oh_modules/ diff --git a/AppScope/app.json5 b/AppScope/app.json5 new file mode 100644 index 0000000..fd3d4c0 --- /dev/null +++ b/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.ruansee.macall.PersonalCenter", + "vendor": "example", + "versionCode": 1001, + "versionName": "1.0.1", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/AppScope/resources/base/element/string.json b/AppScope/resources/base/element/string.json new file mode 100644 index 0000000..1dcae41 --- /dev/null +++ b/AppScope/resources/base/element/string.json @@ -0,0 +1,22 @@ +{ + "string": [ + { + "name": "app_name", + "value": "个人中心" + }, + { + "name": "jiaMi_permission_reason", + "value": "需要加密服务支持" + }, + { + "name": "call_permission_reason", + "value": "应用需要电话权限" + }, + { + "name": "read_app_list_reason", + "value": "应用需要读取已安装应用列表权限" + } + + + ] +} diff --git a/AppScope/resources/base/media/background.png b/AppScope/resources/base/media/background.png new file mode 100644 index 0000000..923f2b3 Binary files /dev/null and b/AppScope/resources/base/media/background.png differ diff --git a/AppScope/resources/base/media/foreground.png b/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000..97014d3 Binary files /dev/null and b/AppScope/resources/base/media/foreground.png differ diff --git a/AppScope/resources/base/media/layered_image.json b/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000..fb49920 --- /dev/null +++ b/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/MdmTool.hap b/MdmTool.hap new file mode 100644 index 0000000..e9f727e Binary files /dev/null and b/MdmTool.hap differ diff --git a/build-profile.json5 b/build-profile.json5 new file mode 100644 index 0000000..cea3ee7 --- /dev/null +++ b/build-profile.json5 @@ -0,0 +1,69 @@ +{ + "app": { + "signingConfigs": [ + { + "name": "default", + "type": "HarmonyOS", + "material": { + "storeFile": "D:/HuaweiKey/ruansee.p12", + "storePassword": "000000194A79B357679283987E3A39F5A33CF415CCB392BCFD9BBDB86299490EEF3B09F21493711480", + "keyAlias": "ruansee", + "keyPassword": "00000019F91B99FBE167C23E51E1735C9B00302715D0E3C4200F7949A2F5B0C4CA699648E3FD946189", + "signAlg": "SHA256withECDSA", + "profile": "D:/HuaweiKey/pcenter/ah_pcenter_debug.p7b", + "certpath": "D:/HuaweiKey/pcenter/ah_pcenter_debug.cer" + } + }, + { + "name": "wlwDebug", + "type": "HarmonyOS", + "material": { + "storeFile": "D:/HuaweiKey/ruansee.p12", + "storePassword": "00000019C7374A8EC1E56A7A61CE4FDB3C3632C487B5E049DF5A9F29528D05CC94EADE7FB5FD42902A", + "keyAlias": "ruansee", + "keyPassword": "0000001941853B3D69EBECD6347D12C2632C37CC23FFFD6301518D3065E1D8F3256C3DEB6E6294FB6C", + "signAlg": "SHA256withECDSA", + "profile": "D:/HuaweiKey/pcenter/pcenter_debugDebug.p7b", + "certpath": "D:/HuaweiKey/pcenter/pcenter_debug.cer" + } + } + ], + "products": [ + { + "name": "default", + "signingConfig": "wlwDebug", + "targetSdkVersion": "5.0.5(17)", + "compatibleSdkVersion": "5.0.0(12)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/code-linter.json5 b/code-linter.json5 new file mode 100644 index 0000000..073990f --- /dev/null +++ b/code-linter.json5 @@ -0,0 +1,32 @@ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/entry/.gitignore b/entry/.gitignore new file mode 100644 index 0000000..e2713a2 --- /dev/null +++ b/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/entry/build-profile.json5 b/entry/build-profile.json5 new file mode 100644 index 0000000..4d61187 --- /dev/null +++ b/entry/build-profile.json5 @@ -0,0 +1,28 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/entry/hvigorfile.ts b/entry/hvigorfile.ts new file mode 100644 index 0000000..b0e3a1a --- /dev/null +++ b/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/entry/obfuscation-rules.txt b/entry/obfuscation-rules.txt new file mode 100644 index 0000000..272efb6 --- /dev/null +++ b/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/entry/oh-package.json5 b/entry/oh-package.json5 new file mode 100644 index 0000000..248c3b7 --- /dev/null +++ b/entry/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/entry/src/main/ets/app/AppCache.ets b/entry/src/main/ets/app/AppCache.ets new file mode 100644 index 0000000..bbc3cef --- /dev/null +++ b/entry/src/main/ets/app/AppCache.ets @@ -0,0 +1,318 @@ + +import { StringUtils } from "../util/StringUtils"; +import { geoLocationManager } from "@kit.LocationKit"; +import { UserCache } from "./UserCache"; +import { IdGeneratedUtils } from "../util/IdGeneratedUtils"; + +/** + * 统一认证系统的SysCode + */ +export const AUTH_SYSCODE = "11e8f9a0948a43d78f68c6af41c12242" + +export const BASE_IMAGE_URL = "http://20.90.2.2/pcenter_img_out"; + +export class AppCache { + private static appCache: AppCache = new AppCache(); + private idGeneratedUtils :IdGeneratedUtils|undefined=undefined; + + /*请求服务的Ip*/ + private ip: string | undefined = undefined + /*请求服务的端口*/ + private port: string | undefined = undefined + private serviceNodeName:string = "/pcenter_app_out/" + + //用于存放品高的Token + private pgToken :string| undefined = undefined; + + //权限状态 + private permissionsStatus: boolean = false; + + /* TODO 临时人员ID 用于避免每次查询都直接改变peopleId,导致查询失败后,之前查询的人员信息和ID对不上 */ + private peopleTemporarilyId: string = "" + /* TODO 人员ID 只有当查询成功时才将 tempPeopleId的值 赋给 peopleId */ + private peopleId: string = "" + /*车辆ID*/ + private carId: string = "" + /* TODO 主ID 由APP生成 传递给后端 */ + private historyId: string = "" + /*物品ID*/ + // private goodsId:string ="" + + /*缓存的物品数据*/ + private goodsJson: string = "" + //本机IP + private localIp: string |undefined= ""; + + /*任务id*/ + private taskId: string|undefined = "" + + private taskName:string|undefined = "" + /*卡点id*/ + private cardPointId: string|undefined = "" + private cardPointName :string|undefined= "" + + //定位的坐标 + private locationX: number = 0.0; + private locationY: number = 0.0; + + //卡点的坐标 + private cardPointX: string = "0.0"; + private cardPointY: string = "0.0"; + + private locationAddress:string|undefined=""; + private cardPointAddress:string|undefined=""; + + private constructor() { + + } + + // + public static getAppCache(): AppCache { + if (AppCache.appCache == null) { + AppCache.appCache = new AppCache() + } + return AppCache.appCache; + } + + /** + * 服务节点 + * @param ip + * @param port + * @param serviceName + */ + public setIpOrPort(ip:string,port:string,serviceNodeName:string){ + this.ip = ip; + this.port = port; + this.serviceNodeName = serviceNodeName; + } + + public getServiceAddress(){ + return `http://${this.ip}:${this.port}${this.serviceNodeName}` + } + + /** + * 获取一个随机ID 生存规则 四位随机数 + 随机UUID+ 四位随机数 + * @returns + */ + public getRandomId(): string { + if (this.idGeneratedUtils == undefined) { + this.idGeneratedUtils = IdGeneratedUtils.getInstance(UserCache.getUserCache().getIdCardNum) + } + return this.idGeneratedUtils.generatedRandomID(); + // return (Math.round(1000) + 1000) + util.generateRandomUUID(false) + (Math.round(1000) + 1000) + } + + /** + * 将临时人员ID设为ID + * 在查询人员成功后调用 + */ + public temporarilyPeopleIdEffect() { + this.peopleId = this.peopleTemporarilyId + this.peopleTemporarilyId = ""; + } + + /** + * TODO 创建一个临时的人员ID,用于查询人员信息时传参,当查询人员成功后,再赋值给{ peopleId } + * + */ + public createPeopleTemporarilyId() { + this.peopleTemporarilyId = this.getRandomId(); + } + + public getPeopleTemporarilyId(): string { + if (StringUtils.isNullOrEmpty(this.peopleTemporarilyId)) { + this.peopleTemporarilyId = this.getRandomId(); + } + return this.peopleTemporarilyId; + } + + public getPeopleId(): string { + if (StringUtils.isNullOrEmpty(this.peopleId)) { + this.peopleId = this.getPeopleTemporarilyId(); + } + return this.peopleId + } + + public getCarId(): string { + if (StringUtils.isNullOrEmpty(this.carId)) { + this.carId = this.getRandomId(); + } + return this.carId; + } + + public getHistoryId(): string { + if (StringUtils.isNullOrEmpty(this.historyId)) { + this.historyId = this.getRandomId(); + } + return this.historyId; + } + + /** + * TODO 仅在初始化页面和提交或移交完成后调用 + * 重置ID + */ + public resetIds(){ + this.historyId = this.getRandomId(); + this.peopleId = this.getRandomId(); + this.carId = this.getRandomId(); + this.createPeopleTemporarilyId() + } + + /** + * 提交成功重置id Submitted successfully + */ + public submitSuccessResetIDs(){ + this.peopleId = "" + this.peopleTemporarilyId = "" + this.carId = "" + this.historyId = "" + this.peopleId = "" + this.peopleId = "" + } + + + /** + * 权限状态 + * @returns + */ + get getPermissionsStatus(): boolean { + return this.permissionsStatus; + } + + set setPermissionsStatus(permissionsStatus: boolean) { + this.permissionsStatus = permissionsStatus; + } + + public setLocation(location :geoLocationManager.Location){ + if (location == null) return + this.locationX = location.longitude; + this.locationY = location.latitude; + } + + public getLocationX():number{ + return this.locationX; + } + public getLocationY():number{ + return this.locationY; + } + + public setCardLocation(cardPointX:string,cardPointY:string,address:string){ + this.cardPointX = cardPointX; + this.cardPointY = cardPointY; + this.cardPointAddress = address; + } + + public getCardPointLocationX():string{ + return this.cardPointX; + } + public getCardPointLocationY():string{ + return this.cardPointY; + } + + public set setLocalIp(localIp :string|undefined){ + this.localIp = localIp; + } + + public get getLocalIp():string|undefined{ + return this.localIp; + } + + public get getPgToken():string|undefined{ + return this.pgToken + } + + public set setPgToken(pgToken:string){ + this.pgToken = pgToken; + } + + public get getTaskId(){ + if(StringUtils.isNullOrEmpty(this.taskId)){ + return ""; + } + if (this.taskId != undefined){ + return this.taskId; + } + return '' + } + + public set setTaskId(taskId:string|undefined){ + this.taskId = taskId; + } + + public get getTaskName():string{ + if(StringUtils.isNullOrEmpty(this.taskName)){ + return ""; + } + if (this.taskName != undefined){ + return this.taskName; + } + return '' + } + + public set setTaskName(taskName:string|undefined){ + this.taskName = taskName; + } + + public get getCardPointIdId(){ + if(StringUtils.isNullOrEmpty(this.cardPointId)){ + return ""; + } + if (this.cardPointId != undefined){ + return this.cardPointId; + } + return '' + } + + public set setCardPointId(cardPointId:string|undefined){ + this.cardPointId = cardPointId; + } + + public get getCardPointName():string{ + if(StringUtils.isNullOrEmpty(this.cardPointName)){ + return ""; + } + if (this.cardPointName != undefined){ + return this.cardPointName; + } + return '' + } + + public set setCardPointName(cardPointName:string|undefined){ + this.cardPointName = cardPointName; + } + + public get getLocationAddress():string{ + if(StringUtils.isNullOrEmpty(this.locationAddress)){ + return ""; + } + if (this.locationAddress != undefined){ + return this.locationAddress; + } + return '' + } + + public set setLocationAddress(locationAddress:string|undefined){ + this.locationAddress = locationAddress; + } + + public get getCardPointAddress():string{ + if(StringUtils.isNullOrEmpty(this.cardPointAddress)){ + return ""; + } + if (this.cardPointAddress != undefined){ + return this.cardPointAddress; + } + return '' + } + + /** + * TODO 图片地址转换 + * @param photoUrl 原始图片地址 + * @returns + */ + convertPhotoUrl(photoUrl:string):string{ + if (StringUtils.isNullOrEmpty(photoUrl)) return"" + return photoUrl.replace("http://53.1.214.228:9000/ypc","http://20.90.2.2/rcwhy_image_out") + .replace("http://53.1.227.17:9000/ypc","http://20.90.2.2/rcwhy_image_out") + } +} \ No newline at end of file diff --git a/entry/src/main/ets/app/AppConstant.ets b/entry/src/main/ets/app/AppConstant.ets new file mode 100644 index 0000000..4e06f96 --- /dev/null +++ b/entry/src/main/ets/app/AppConstant.ets @@ -0,0 +1,46 @@ + +export class BaseUiModel { + baseType:number = 1 + baseMsg:string = "" +} + +export default class AppConstants { + + /** + * Maximum width. + */ + static readonly PERCENTAGE_MAX: string = '100%'; + + /** + * 品高的appID和secret + */ + static readonly PG_APP_KEY_SECRET='ksSt5bxNze8SBsPXGt6f:pkPaXjZCHTnzhZhMAhAn8YYbZ6r2H7' + + /** + * 盘查方式 - 输入 + */ + static readonly CHECK_TYPE_INPUT = 0; + /** + * 盘查方式 - NFC读卡 + */ + static readonly CHECK_TYPE_NFC = 1; + /** + * 盘查方式 - 人像识别 + */ + static readonly CHECK_TYPE_FACE = 2; + /** + * 盘查方式 - 语音 + */ + static readonly CHECK_TYPE_AUDIO = 3; + /** + * 盘查方式 - OCR识别 + */ + static readonly CHECK_TYPE_OCR = 4; + + /** + * 安徽地市 + */ + static readonly AN_HUI_CITY_NAMES :string[] = ["省厅:3400", "合肥:3401", "芜湖:3402", "蚌埠:3403", "淮南:3404", + "马鞍山:3405", "淮北:3406", "铜陵:3407", "安庆:3408", "黄山:3410", "滁州:3411", + "阜阳:3412", "宿州:3413", "六安:3415", "亳州:3416", "池州:3417", "宣城:3418"]; +} \ No newline at end of file diff --git a/entry/src/main/ets/app/RuanseeAbilityStag.ets b/entry/src/main/ets/app/RuanseeAbilityStag.ets new file mode 100644 index 0000000..d24bdfb --- /dev/null +++ b/entry/src/main/ets/app/RuanseeAbilityStag.ets @@ -0,0 +1,43 @@ +import { AbilityConstant, AbilityStage, Configuration, Want } from "@kit.AbilityKit"; +import { StringUtils } from "../util/StringUtils"; +import { hilog } from "@kit.PerformanceAnalysisKit"; +import { AppCache } from "./AppCache"; +import { UserCache } from "./UserCache"; +// import { tdvision } from "@kit.TdosVisionKit"; + +export class RuanseeAbilityStag extends AbilityStage{ + public static appCache:AppCache; + public static userCache:UserCache; + + + onCreate(): void { + hilog.info(0x0000, 'RuanseeAbitityStag', '%{public}s', 'AbilityStage onCreate()'); + RuanseeAbilityStag.appCache = AppCache.getAppCache(); + RuanseeAbilityStag.appCache.setIpOrPort("20.90.2.2", "80","/pcenter_app_out/"); + RuanseeAbilityStag.userCache = UserCache.getUserCache(); + // tdvision.setup() + } + + onAcceptWant(want: Want): string { + hilog.info(0x0000, 'RuanseeAbitityStag', '%{public}s', 'AbilityStage onAcceptWant()'); + return StringUtils.get(want.abilityName,""); + + } + + onNewProcessRequest(want: Want): string { + hilog.info(0x0000, 'RuanseeAbitityStag', '%{public}s', 'AbilityStage onNewProcessRequest()'); + return StringUtils.get(want.abilityName,""); + + } + + onMemoryLevel(level: AbilityConstant.MemoryLevel): void { + hilog.info(0x0000, 'RuanseeAbitityStag', '%{public}s', 'AbilityStage onMemoryLevel()'); + + } + + onConfigurationUpdate(newConfig: Configuration): void { + hilog.info(0x0000, 'RuanseeAbitityStag', '%{public}s', 'AbilityStage onConfigurationUpdate()'); + + } + +} \ No newline at end of file diff --git a/entry/src/main/ets/app/UserCache.ets b/entry/src/main/ets/app/UserCache.ets new file mode 100644 index 0000000..6646f7b --- /dev/null +++ b/entry/src/main/ets/app/UserCache.ets @@ -0,0 +1,189 @@ +import { StringUtils } from "../util/StringUtils"; +import { buffer, util } from "@kit.ArkTS"; +import { UserInfoModel } from "../model/cacheModel/UserInfoModel"; +import { AppCache } from "./AppCache"; + +export class UserCache { + public static userCache: UserCache = new UserCache(); + private userName: string = ""; + private userCode: string = ""; + private deptName: string = ""; + private deptCode: string = ""; + private idCardNum: string = ""; + private phoneNum: string = ""; + private userInfo: string = ""; + private authToken: string = "" + private profilePhoto: string = ""; + private workPhone: string = ""; + private email: string = "" + private age: number = 0 + private birthdate: string = "" + private policeTypeId: string = "" + private policeTypeName: string = "" + private departmentCode: string = "" + private departmentName: string = "" + + private constructor() { + + } + + public static getUserCache(): UserCache { + if (UserCache.userCache == null) { + UserCache.userCache = new UserCache(); + } + return UserCache.userCache; + } + + + get getDepartmentCode(): string { + return this.departmentCode; + } + + set setDepartmentCode(departmentCode: string) { + this.departmentCode = departmentCode; + } + get getDepartmentName(): string { + return this.departmentName; + } + + set setDepartmentName(departmentName: string) { + this.departmentName = departmentName; + } + + get getUserName(): string { + return this.userName; + } + + set setUserName(userName: string) { + this.userName = userName; + } + + get getUserCode(): string { + return this.userCode; + } + + set setUserCode(userCode: string) { + this.userCode = userCode; + } + + get getDeptName(): string { + return this.deptName; + } + + set setDeptName(deptName: string) { + this.deptName = deptName; + } + + get getDeptCode(): string { + return this.deptCode; + } + + set setDeptCode(deptCode: string) { + this.deptCode = deptCode; + } + + get getPhoneNum(): string { + return this.phoneNum; + } + + set setPhoneNum(phoneNum: string) { + this.phoneNum = phoneNum; + } + + get getIdCardNum(): string { + return this.idCardNum; + } + + set setIdCardNum(idCardNum: string) { + this.idCardNum = idCardNum; + } + + public getUserInfo(): string { + if (StringUtils.isNullOrEmpty(this.userInfo)) { + let cs: UserInfoModel = { + "userCode": UserCache.getUserCache().getUserCode, + "userName": UserCache.getUserCache().getUserName, + "deptName": UserCache.getUserCache().getDeptName, + "deptCode": UserCache.getUserCache().getDeptCode, + "idCardNum": UserCache.getUserCache().getIdCardNum, + "ip": AppCache.getAppCache().getLocalIp || "10.115.101.1", + "departmentCode": UserCache.getUserCache().getDepartmentCode, + "departmentName": UserCache.getUserCache().getDepartmentName, + } + let userInfo = JSON.stringify(cs) + let byte = new Uint8Array(buffer.from(userInfo, 'utf-8').buffer); + this.userInfo = new util.Base64Helper().encodeToStringSync(byte); + } + return this.userInfo + } + + public set setUserInfo(userInfo: string) { + this.userInfo = userInfo; + } + + + get getAuthToken(): string { + return this.authToken; + } + + set setAuthToken(authToken: string) { + this.authToken = authToken; + } + + get getProfilePhoto(): string { + return this.profilePhoto; + } + + set setProfilePhoto(profilePhoto: string) { + this.profilePhoto = profilePhoto; + } + + get getWorkPhone(): string { + return this.workPhone; + } + + set setWorkPhone(workPhone: string) { + this.workPhone = workPhone; + } + + get getEmail(): string { + return this.email; + } + + set setEmail(email: string) { + this.email = email; + } + + get getAge(): number { + return this.age; + } + + set setAge(age: number) { + this.age = age; + } + + get getBirthdate(): string { + return this.birthdate; + } + + set setBirthdate(birthdate: string) { + this.birthdate = birthdate; + } + + get getPoliceTypeId(): string { + return this.policeTypeId; + } + + set setPoliceTypeId(policeTypeId: string) { + this.policeTypeId = policeTypeId; + } + get getPoliceTypeName(): string { + return this.policeTypeName; + } + + set setPoliceTypeName(policeTypeName: string) { + this.policeTypeName = policeTypeName; + } + + +} \ No newline at end of file diff --git a/entry/src/main/ets/callback/DownLoadListener.ets b/entry/src/main/ets/callback/DownLoadListener.ets new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/entry/src/main/ets/callback/DownLoadListener.ets @@ -0,0 +1 @@ + diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000..c494d32 --- /dev/null +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,222 @@ +import { bundleManager,abilityAccessCtrl, AbilityConstant, ConfigurationConstant, + Permissions, + UIAbility, Want, + common } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; +import { HMRouterMgr } from '@hadss/hmrouter'; +import { } from '@kit.MDMKit'; +import { AppCache } from '../app/AppCache'; +import { UserCache } from '../app/UserCache'; +import { FileUtils } from '../util/FileUtils'; +import { DialogHelper } from '@pura/harmony-dialog'; +import { ToastUtils } from '../util/ToasUtils'; +import { UnauthorizedPermissionDialog } from '../ui/dialog/UnauthorizedPermissionDialog'; +import { AppUtil } from '@pura/harmony-utils'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + + /** + * TODO { + // "name": "ohos.permission.GET_INSTALLED_BUNDLE_LIST", + // "reason":"$string:read_app_list_reason", + // "usedScene":{ + // "abilities":[ + // ".EntryAbility" + // ], + // "when":"inuse" + // } + // }, + */ + + /** + * @param want + * @param launchParam + */ + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + HMRouterMgr.init({ + context: this.context + }) + AppUtil.init(this.context) + UserCache.getUserCache() + this.applyForPermission() + FileUtils.init(this.context) + //初始化数据库 + // DBUtils.getInstance().HOInit(this.context) + // 在Ability中监听事件 + this.context.eventHub.on('ui_event', (data:Array) => { + // console.log('Received UI event:', data); + if (data!=null) { + this.requestPermissionsFromUser(data) + } + }); + + //简单初始化(1.0.8版本及以后) + //必须在UIAbility的onCreate方法里初始化context。 + DialogHelper.setDefaultConfig((config) => { + config.uiAbilityContext = this.context; + }) + } + + onDestroy(): void { + this.context.eventHub.off("ui_event") + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + windowStage.getMainWindow().then((window=>{ + window.setWindowLayoutFullScreen(true) + })) + windowStage.loadContent('ui/pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + // set main window full screen + // this.setAppFullScreen(windowStage.getMainWindowSync()); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } + + + //申请权限 + applyForPermission() { + let permissions = new Array(); + permissions.push('ohos.permission.CAMERA') + permissions.push('ohos.permission.LOCATION') + permissions.push('ohos.permission.APPROXIMATELY_LOCATION') + // permissions.push('ohos.permission.GET_INSTALLED_BUNDLE_LIST') + this.checkPermissionGrant(permissions) + } + + checkPermissionGrant(permissionArray: Array) { + let uiContext :common.UIAbilityContext = this.context as common.UIAbilityContext; + let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager() + // 获取应用程序的accessTokenID + let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION) + let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo + let tokenId: number = appInfo.accessTokenId + let wsqPermissionArray = new Array() + for (let i = 0; i < permissionArray.length; i++) { + let grantStatus = atManager.checkAccessTokenSync(tokenId, permissionArray[i]) + if (grantStatus == abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) { + wsqPermissionArray.push(permissionArray[i]) + } + } + if (wsqPermissionArray.length>0) { + //有未申请的权限 + this.requestPermissionsFromUser(wsqPermissionArray) + }else { + //授权成功 + this.sendPermissionSuccess(uiContext) + } + } + + /** + *AUTHOR:AbnerMing + *INTRODUCE:向用户获取权限授权 + */ + requestPermissionsFromUser(permissions: Array) { + let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager() + let uiContext :common.UIAbilityContext = this.context as common.UIAbilityContext; + atManager.requestPermissionsFromUser(uiContext, permissions) + .then((data) => { + let grantStatus: Array = data.authResults; + let length: number = grantStatus.length; + let notPermissions: Array =new Array(); + for (let i = 0; i < length; i++) { + if (grantStatus[i] === 0) { + // 用户授权,可以继续访问目标操作 + console.log("===用户授权") + } else { + // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限 + notPermissions.push(permissions[i]) + } + } + if (notPermissions.length > 0) { + //授权失败 + this.applyPermissionAgain(uiContext,atManager, notPermissions) + }else { + //授权成功 + this.sendPermissionSuccess(uiContext) + } + console.log("===权限授权成功") + }) + .catch((err:Error) => { + console.error("===权限授权失败") + }) + } + + /** + * 重新申请授权 + * @param uiContext + * @param atManager + * @param notPermissions + */ + applyPermissionAgain(uiContext :common.UIAbilityContext,atManager: abilityAccessCtrl.AtManager,notPermissions: Array){ + ToastUtils.toastCenter("您拒绝了权限,请到设置里打开!") + atManager.requestPermissionOnSetting(uiContext,notPermissions) + .then((data) => { + let notAuthorizationCount = 0 + data.forEach((item) => { + if (item == -1) { + notAuthorizationCount++ + } + }) + if (notAuthorizationCount == 0) { + //授权成功 + this.sendPermissionSuccess(uiContext) + }else { + //授权失败 + this.sendPermissionFailed(uiContext) + } + }) + .catch((err:Error) => { + //授权失败 + this.sendPermissionFailed(uiContext) + console.error("===权限授权失败") + }) + + // HMRouterMgr.replace({navigationId:'startNavigation',pageUrl:"MainPage"}) + return + } + + sendPermissionFailed(uiContext: common.UIAbilityContext){ + setTimeout(()=>{ + let dat = "NotPermissions" + uiContext.eventHub.emit('NotPermissions',dat); + },1000) + } + + sendPermissionSuccess(uiContext: common.UIAbilityContext){ + setTimeout(()=>{ + let dat = "PermissionsSuccess" + uiContext.eventHub.emit('PermissionsSuccess',dat); + },1000) + } + + + + +} \ No newline at end of file diff --git a/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000..8e4de99 --- /dev/null +++ b/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,16 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/entry/src/main/ets/model/cacheModel/UserInfoModel.ets b/entry/src/main/ets/model/cacheModel/UserInfoModel.ets new file mode 100644 index 0000000..3d9b258 --- /dev/null +++ b/entry/src/main/ets/model/cacheModel/UserInfoModel.ets @@ -0,0 +1,19 @@ + +export interface UserInfoModel{ + "departmentCode": string; + "departmentName": string; + "userCode": string; + "userName": string; + "deptName": string; + "deptCode": string; + "idCardNum": string; + "ip": string; +} + +export class WebUserInfoModel{ + "userCode": string; + "userName": string; + "deptName": string; + "deptCode": string; + "idCardNum": string; +} \ No newline at end of file diff --git a/entry/src/main/ets/model/requestModel/AppRequestModel.ets b/entry/src/main/ets/model/requestModel/AppRequestModel.ets new file mode 100644 index 0000000..b1e1116 --- /dev/null +++ b/entry/src/main/ets/model/requestModel/AppRequestModel.ets @@ -0,0 +1,19 @@ + + +export interface GetAppListRequestModel{ + name:string; + page:number; + pageSize: number; +} + +export interface GetAppGuideRequestModel{ + name:string; + cityNumber:string; + page:number; + pageSize: number; +} + +export interface GuideRequest{ + applicationId:string +} + diff --git a/entry/src/main/ets/model/requestModel/MessageRequestModel.ets b/entry/src/main/ets/model/requestModel/MessageRequestModel.ets new file mode 100644 index 0000000..edfe6ff --- /dev/null +++ b/entry/src/main/ets/model/requestModel/MessageRequestModel.ets @@ -0,0 +1,44 @@ +import { BASE_IMAGE_URL } from "../../app/AppCache"; +import { StringUtils } from "../../util/StringUtils"; + +export interface GetMsgListRequestModel { + state: number; + page: number; + pageSize: number; +} + +export class AddFeedBackRequestModel { + applicationId: string = "" + alarmSignal: string = "" + alarmName: string = "" + type: string = "" + title: string = "" + content: string = "" + applicationName: string = "" +} + +export class FeedBackBean { + baseType: number = 1 + id: string = "" + type: number = 0 + createTime: string = "" + title: string = "" + content: string = "" + applicationName: string = "" + replyStatus: number = 0 + replyContent: string = "" + replier: string = "" + updateTime: string = "" + + getReplyContent() :string{ + if (StringUtils.isNullOrEmpty(this.replyContent)) { + return "" + } + let parts: string[] = []; + parts.push("

") + parts.push(this.replyContent.replaceAll("/prod-api/profile", BASE_IMAGE_URL+"/profile")) + parts.push("") + return parts.join("") + } + +} \ No newline at end of file diff --git a/entry/src/main/ets/model/requestModel/UserInfoRequestModel.ets b/entry/src/main/ets/model/requestModel/UserInfoRequestModel.ets new file mode 100644 index 0000000..ee8f4e4 --- /dev/null +++ b/entry/src/main/ets/model/requestModel/UserInfoRequestModel.ets @@ -0,0 +1,25 @@ + + +export interface GetUserPhotoModel{ + id:string; + token:string; + clientType:string; + imsi1:string; + deviceFlags:string; + sysCode:string; +} + +export interface UpdateUserInfoModel{ + + token:string; + clientType:string; + imsi1:string; + deviceFlags:string; + sysCode:string; + workPhone:string; +} + +export interface UploadFile{ + contentType:string; + filename:string +} \ No newline at end of file diff --git a/entry/src/main/ets/model/resultModel/ApplicationResultModel.ets b/entry/src/main/ets/model/resultModel/ApplicationResultModel.ets new file mode 100644 index 0000000..1548c87 --- /dev/null +++ b/entry/src/main/ets/model/resultModel/ApplicationResultModel.ets @@ -0,0 +1,122 @@ +import { FileUtil } from "@pura/harmony-utils" +import { StringUtils } from "../../util/StringUtils" + + +export class ApplicationTypeModel{ + "推荐应用":Array + "最新应用":Array +} + +export class ApplicationModel{ + baseType:number = 1 + + name:string = "" + id:string = "" + //应用等级 3 = 原生应用 其他 H5应用 + level:number=1 + link:string = "" + //应用所在区类 1 = II类区 2 == III类区 + type:number = 1 + + clientId:string = "" + clientSecret:string = "" + //图片地址 + icon:string = "" + + locationIcon:Resource=$r('app.media.icon_gd2') + + //应用分类 情指应用 经侦、刑侦等 + classification:string = "" + //应用厂商 + serviceProvider:string = "" + + packageName?:string + //运维人员 + operationPerson:string = "" + phoneNumber?:string + //应用上架时间 + applicationTime:string = "" +} + + +@Observed +export class AppDataModel{ + baseType:number = 1 + + id:string = "" + isSelect:boolean = false + + name:string = "" + //图片地址 + icon:string = "" + link:string = "" + packageName?:string + effectiveness:number = 0 + + //应用等级 3 = 原生应用 其他 H5应用 + level:number=1 + //应用所在区类 1 = II类区 2 == III类区 + type:number = 1 + + cityNumber:string = "" + //应用厂商 + serviceProvider:string = "" + //运维人员 + operationPerson:string = "" + //运维人员联系电话 + phoneNumber:string = "" + + clientId:string = "" + clientSecret:string = "" + state:string = "" + //备注 + remark:string = "" + //操作指南 + operationGuide:string = "" + isRecommend:number = 0 + label:string = "" + attribution:number = 0 + locationIcon:Resource=$r('app.media.icon_gd2') +} + +export class AppGuideDetailsBean{ + baseType:number = 1 + + id:string = "" + applicationId:string = "" + applicationName:string = "" + filePath:string = "" + type:number = 0 + remark:string = "" + + getName():string{ + if(StringUtils.isNullOrEmpty(this.filePath))return "" + let index = this.filePath.lastIndexOf('/'); + return this.filePath.substring(index+1) + } + + getFileIcon(filePath: string): Resource { + let i = filePath.lastIndexOf("/"); + let substring = filePath.substring(i + 1); + let flExt = FileUtil.getFileExtention(substring) + if (StringUtils.containsChar("doc,docx", flExt)) { + return $r('app.media.fileselect_img_doc') + } + if (StringUtils.containsChar("xls,xlsx", flExt)) { + return $r('app.media.fileselect_img_xls') + } + if (StringUtils.containsChar("rar,zip,7Z", flExt)) { + return $r('app.media.fileselect_img_zip') + } + if (flExt.endsWith("ppt")) { + return $r('app.media.fileselect_img_ppt') + } + if (flExt.endsWith("pfd")) { + return $r('app.media.fileselect_img_pfd') + } + if (flExt.endsWith("txt")) { + return $r('app.media.fileselect_img_txt') + } + return $r('app.media.fileselect_img_unknown') + } +} diff --git a/entry/src/main/ets/model/resultModel/BaseResultModel.ets b/entry/src/main/ets/model/resultModel/BaseResultModel.ets new file mode 100644 index 0000000..65dabcb --- /dev/null +++ b/entry/src/main/ets/model/resultModel/BaseResultModel.ets @@ -0,0 +1,20 @@ + + +export class BaseResultModel{ + msg?: string; + code?: number; + total?:number = 0; + data?:T; + rows?:T; +} + +export class PageModel{ + total:number = 0; + rows?:Array +} + +export class PagingModel{ + counts:number = 0; + items?:Array + +} \ No newline at end of file diff --git a/entry/src/main/ets/model/resultModel/MessageResultModel.ets b/entry/src/main/ets/model/resultModel/MessageResultModel.ets new file mode 100644 index 0000000..eb94c5b --- /dev/null +++ b/entry/src/main/ets/model/resultModel/MessageResultModel.ets @@ -0,0 +1,36 @@ + +export class MainMessageBean{ + baseType:number =1; + id:string = "" + msgId:string = "" + appName:string = "" + msgType:string = "" + appIcon:string = "" + state:string = "" + + /** + * 是否在个人中心APP内展示: + * 0 :跳转第三方应用内展示 + * 1 :直接在个人中心展示 + * 默认值0 + */ + appExhibition:number = 0; + /** + * ture 已读 false 未读 + */ + isRead:boolean = false; + // + // drawable:Resource + + applicationId:string = "" + + msgTitle:string = "" + + msgContent:string = "" + + appId:string = "" + appUrl:string = "" + appSecret:string = "" + sendingTime:string = "" + +} \ No newline at end of file diff --git a/entry/src/main/ets/model/resultModel/PgResultModel.ets b/entry/src/main/ets/model/resultModel/PgResultModel.ets new file mode 100644 index 0000000..a1407db --- /dev/null +++ b/entry/src/main/ets/model/resultModel/PgResultModel.ets @@ -0,0 +1,6 @@ + +export interface PgTokenModel{ + access_token:string + refresh_token:string + +} \ No newline at end of file diff --git a/entry/src/main/ets/model/resultModel/QuestionModel.ets b/entry/src/main/ets/model/resultModel/QuestionModel.ets new file mode 100644 index 0000000..011224d --- /dev/null +++ b/entry/src/main/ets/model/resultModel/QuestionModel.ets @@ -0,0 +1,17 @@ + +export class QuestionModel { + baseType:number = 1 + title: string = ''; + data:Array = [] +} + +export class QuestionBean { + baseType:number = 2 + problem:string = ''; + reply:string = ''; + extend:string = ''; + guidance:string = ''; + + isShowSheet :boolean =false + +} \ No newline at end of file diff --git a/entry/src/main/ets/model/uiModel/AnHuiAddressModel.ets b/entry/src/main/ets/model/uiModel/AnHuiAddressModel.ets new file mode 100644 index 0000000..f10f703 --- /dev/null +++ b/entry/src/main/ets/model/uiModel/AnHuiAddressModel.ets @@ -0,0 +1,32 @@ +export class AnHuiAddressModel { + address: string[][] = [ + ["省厅", "3400"], + ["合肥", "3401"], + ["芜湖", "3402"], + ["蚌埠", "3403"], + ["淮南", "3404"], + ["马鞍山", "3405"], + ["淮北", "3406"], + ["铜陵", "3407"], + ["安庆", "3408"], + ["黄山", "3410"], + ["滁州", "3411"], + ["阜阳", "3412"], + ["宿州", "3413"], + ["六安", "3415"], + ["亳州", "3416"], + ["池州", "3417"], + ["宣城", "3418"] + ]; + + getAddress(code: string): string { + for (let i = 0; i < this.address.length; i++) { + if (this.address[i][1] == code) { + return this.address[i][0]; + } + } + return ""; + } + + +} \ No newline at end of file diff --git a/entry/src/main/ets/model/uiModel/AppModel.ets b/entry/src/main/ets/model/uiModel/AppModel.ets new file mode 100644 index 0000000..3b0d8e1 --- /dev/null +++ b/entry/src/main/ets/model/uiModel/AppModel.ets @@ -0,0 +1,7 @@ +import { BaseUiModel } from "../../app/AppConstant"; + +export class AppModel extends BaseUiModel{ + + + +} \ No newline at end of file diff --git a/entry/src/main/ets/model/uiModel/IAuthTaskType.ets b/entry/src/main/ets/model/uiModel/IAuthTaskType.ets new file mode 100644 index 0000000..c79a39e --- /dev/null +++ b/entry/src/main/ets/model/uiModel/IAuthTaskType.ets @@ -0,0 +1,74 @@ +/** + * 统一认证 + */ +export enum IAuthTaskType { + /** + * 获取token模式 + */ + AUTH_TASK_TOKEN = 0, + /** + * token登录模式 + */ + AUTH_TASK_USER = 1, + /** + * 登录页面模式 + */ + AUTH_TASK_START_AUTH = 2, + /** + * 多因子绑定模式 + */ + AUTH_TASK_BIND = 3, + /** + * 多因子解绑模式 + */ + AUTH_TASK_UNBIND = 4, + /** + * 个人信息修改模式 + */ + AUTH_TASK_SET_UP = 5, +} + + +export class AuthUserModel { + age?: number; + birthdate?: string; + code: string = ''; + email?: string; + orderId: number; + orgId: string; + orgName: string; + phoneNum?: string; + policeTypeId: string; + policeTypeName: string; + profilePhoto?: string; + realName: string; + token: string; + userName: string; + userNum: string; + workPhone?: string; + sysTypeId: string; + + constructor(code: string, orderId: number, orgId: string, orgName: string, policeTypeId: string, + policeTypeName: string, realName: string, token: string, userName: string, userNum: string, + sysTypeId: string, age?: number, birthdate?: string, email?: string, phoneNum?: string, + profilePhoto?: string, workPhone?: string) { + + this.code = code; + this.orderId = orderId; + this.orgId = orgId; + this.orgName = orgName; + this.policeTypeId = policeTypeId; + this.policeTypeName = policeTypeName; + this.realName = realName; + this.token = token; + this.userName = userName; + this.userNum = userNum; + this.sysTypeId = sysTypeId; + this.age = age === undefined ? 0 : age; + this.birthdate = birthdate === undefined ? '' : birthdate; + this.email = email === undefined ? '' : email; + this.phoneNum = phoneNum === undefined ? '' : phoneNum; + this.profilePhoto = profilePhoto === undefined ? '' : profilePhoto; + this.workPhone = workPhone === undefined ? '' : workPhone; + } +} diff --git a/entry/src/main/ets/model/uiModel/PageResultModel.ets b/entry/src/main/ets/model/uiModel/PageResultModel.ets new file mode 100644 index 0000000..5bf0589 --- /dev/null +++ b/entry/src/main/ets/model/uiModel/PageResultModel.ets @@ -0,0 +1,11 @@ + + +export class BasePageResult{ + //标识类型 + type:number=0; + //第二标识 + what:number=0; + //传递的参数 + data?:ESObject; + +} diff --git a/entry/src/main/ets/model/uiModel/SelectFileOptions.ets b/entry/src/main/ets/model/uiModel/SelectFileOptions.ets new file mode 100644 index 0000000..8cf2490 --- /dev/null +++ b/entry/src/main/ets/model/uiModel/SelectFileOptions.ets @@ -0,0 +1,66 @@ + +export class SelectFileOptions { + /** + * 默认值:false + */ + isCamera: boolean = true; + /** + * 默认值:false + */ + isDCIM: boolean= true; + /** + * 默认值:false + */ + isFileSelection: boolean= true; + /** + * 是否由H5自己实现:false + */ + selfRealization: boolean = false; + + /** + * 构造函数 + * @param selfRealization 是否由H5自己实现 + * @param isCamera 是否显示相机选项 + * @param isDCIM 是否显示相册选项 + * @param isFileSelection 是否显示文件选项 + */ + constructor(selfRealization: boolean,isCamera: boolean, isDCIM: boolean, isFileSelection: boolean) { + this.isCamera = isCamera; + this.isDCIM = isDCIM; + this.isFileSelection = isFileSelection; + this.selfRealization = selfRealization; + } + /** + * + * @param selfRealization 是否由H5自己实现 + * @param isCamera 是否显示相机选项 + * @param isDCIM 是否显示相册选项 + * @param isFileSelection 是否显示文件选项 + */ + setConfig(selfRealization: boolean,isCamera: boolean, isDCIM: boolean, isFileSelection: boolean) { + this.isCamera = isCamera; + this.isDCIM = isDCIM; + this.isFileSelection = isFileSelection; + this.selfRealization = selfRealization; + } + + /** + * 是否只配置了一个选项 + * @return true 只配置了一个选项 + * false 配置了多个选项 + */ + onlyOneItemIsSelected():boolean{ + let count = 0; + if (this.isCamera){ + count++; + } + if (this.isDCIM){ + count++; + } + if (this.isFileSelection){ + count++; + } + return count==1; + } + +} \ No newline at end of file diff --git a/entry/src/main/ets/model/uiModel/WebAppPageParam.ets b/entry/src/main/ets/model/uiModel/WebAppPageParam.ets new file mode 100644 index 0000000..ec7e901 --- /dev/null +++ b/entry/src/main/ets/model/uiModel/WebAppPageParam.ets @@ -0,0 +1,23 @@ + +export enum H5OperationType{ + login, + readMessage, + search +} + +export class WebAppPageParam { + appName :string = ""; + appId:string = ""; + secret :string= ""; + linkUrl :string= ""; + msgId?:string= ""; + /*第三方应用对应的消息类型:当有的应用有多个消息类型时根据此参数判断*/ + msgType? :string= ""; + /*第三方应用的操作类型 默认为 :login ,查看消息为: readMessage 查看搜索内容为:search */ + operationType :H5OperationType= H5OperationType.login; + searchType? :string= ""; + searchJson? :string= ""; + ywry? :string= ""; + ywrylxdh? :string= ""; + +} \ No newline at end of file diff --git a/entry/src/main/ets/request/Api.ets b/entry/src/main/ets/request/Api.ets new file mode 100644 index 0000000..874da34 --- /dev/null +++ b/entry/src/main/ets/request/Api.ets @@ -0,0 +1,267 @@ +import { buffer, util } from "@kit.ArkTS"; +import axios, { AxiosHeaders, AxiosProgressEvent, AxiosResponse, FormData } from "@ohos/axios"; +import { PgTokenModel } from "../model/resultModel/PgResultModel"; +import AppConstants from "../app/AppConstant"; +import http from "../request/HttpUtils" +import { BaseResultModel, PagingModel } from "../model/resultModel/BaseResultModel"; +import { AppDataModel, AppGuideDetailsBean, ApplicationTypeModel } from "../model/resultModel/ApplicationResultModel"; +import { + AddFeedBackRequestModel, + FeedBackBean, + GetMsgListRequestModel +} from "../model/requestModel/MessageRequestModel"; +import { MainMessageBean } from "../model/resultModel/MessageResultModel"; +import { GetAppGuideRequestModel, GetAppListRequestModel, GuideRequest } from "../model/requestModel/AppRequestModel"; +import { RuanseeAbilityStag } from "../app/RuanseeAbilityStag"; +import { GetUserPhotoModel, UpdateUserInfoModel } from "../model/requestModel/UserInfoRequestModel"; +import { AUTH_SYSCODE } from "../app/AppCache"; +import fs from '@ohos.file.fs'; +import { QuestionModel } from "../model/resultModel/QuestionModel"; + +import { request } from '@kit.BasicServicesKit'; +import { BusinessError } from '@kit.BasicServicesKit'; + +/*获取品高认证*/ +export const getPgToken = (data?: ESObject) => { + let byte = new Uint8Array(buffer.from(AppConstants.PG_APP_KEY_SECRET, 'utf-8').buffer); + let ac = new util.Base64Helper().encodeToStringSync(byte); + return http.postFromBody("http://20.90.2.2/sso_out/oauth2/token?grant_type=client_credentials", data, + new AxiosHeaders({ + 'Authorization': 'Basic ' + ac, + 'Content-Type': 'application/x-www-form-urlencoded' + })) +} + +/** + * 获取推荐应用 + */ +export const getRecommendApplication = () => { + return http.get>("app/v1/zamh/recommendApplication") +} + +/** + * 获取消息列表 + */ +export const getMessageList = (state: number, page: number, pageSize: number) => { + let param: GetMsgListRequestModel = { + state: state, + page: page, + pageSize: pageSize + } + return http.get>>("app/v1/zamh/getMessage", param) +} + +/** + * 获取应用列表 + */ +export const getAppList = (name = "", page = 1, pageSize = 20) => { + let param: GetAppListRequestModel = { + name: name, + page: page, + pageSize: pageSize + } + return http.get>>("app/v1/zamh/getAllApplicationPage", param) +} + +/** + * 添加反馈 + */ +export const addFeedBack = (appId: string, appName: string, selectType: number, title: string, content: string) => { + let param: AddFeedBackRequestModel = { + applicationId: appId, + alarmSignal: RuanseeAbilityStag.userCache.getDepartmentCode, + alarmName: RuanseeAbilityStag.userCache.getDepartmentName, + type: selectType + "", + title: title, + content: content, + applicationName: appName + } + return http.post>("app/v1/zamh/addFeedBack", param) +} + +/** + * 获取我的反馈列表 + */ +export const getMyFeedBackList = (page = 1, pageSize = 20) => { + let param: GetAppListRequestModel = { + name: "", + page: page, + pageSize: pageSize + } + return http.get>>("app/v1/zamh/feedbackList", param) +} + +/** + * 获取应用指南列表 + */ +export const getAppGuideList = (appName: string, cityName: string, page = 1, pageSize = 20) => { + let param: GetAppGuideRequestModel = { + name: appName, + cityNumber: cityName, + page: page, + pageSize: pageSize + } + return http.get>>("app/v1/zamh/applicationHaveOperationGuide", param) +} + +/** + * 获取应用指南 + */ +export const operationGuideList = (applicationId: string) => { + let param: GuideRequest = { + applicationId: applicationId + } + return http.get>>("app/v1/zamh/operationGuideList", param) +} + +export const downLoadUserPhoto = (filePath: string) => { + try { + fs.accessSync(filePath); + fs.unlinkSync(filePath); + } catch (err) { + + } + let param: GetUserPhotoModel = { + id: RuanseeAbilityStag.userCache.getProfilePhoto, + token: RuanseeAbilityStag.userCache.getAuthToken, + clientType: "SERVER", //"SERVER", + imsi1: "", + deviceFlags: "", + sysCode: AUTH_SYSCODE + } + return axios({ + url: 'http://20.90.2.2/UniAuth/api/sso/v1/download', + method: 'post', + params: param, + headers: new AxiosHeaders({ + 'Content-Type': `application/x-www-form-urlencoded;` + }), + filePath: filePath, + onDownloadProgress: (progressEvent: AxiosProgressEvent) => { + console.info("progress: ", progressEvent && progressEvent.loaded && progressEvent.total ? + Math.ceil(progressEvent.total / progressEvent.total * 100) : 0); + } + }) +} + +/** + * 修改手机号 + */ +export const updateWorkPhone = (phone: string) => { + let param: UpdateUserInfoModel = { + token: RuanseeAbilityStag.userCache.getAuthToken, + clientType: "SERVER", //"SERVER", + imsi1: "", + deviceFlags: "", + sysCode: AUTH_SYSCODE, + workPhone: phone + } + return http.postFromBody>("http://20.90.2.2/UniAuth/api/sso/v1/updateUserInfo", param, + new AxiosHeaders({ + 'Content-Type': `application/x-www-form-urlencoded;` + }),) +} + +//上传文件 +export const uploadUserPhoto = (filePath: string) => { + let formData = new FormData(); + // 读取文件内容为ArrayBuffer + try { + let file = fs.openSync(filePath, fs.OpenMode.READ_ONLY); + let stat = fs.statSync(filePath); + let fileName: ESObject = {}; + fileName['filename'] = file.name; + fileName['contentType'] = 'image/jpeg'; + let arrayBuffer = new ArrayBuffer(stat.size); + fs.readSync(file.fd, arrayBuffer); + fs.closeSync(file); + formData.append('file', arrayBuffer, fileName); + } catch (e) { + console.info("上传文件失败", e); + } + formData.append('token', RuanseeAbilityStag.userCache.getAuthToken); + formData.append('clientType', 'SERVER'); + formData.append('sysCode', AUTH_SYSCODE); + + return http.post>("http://20.90.2.2/UniAuth/api/sso/v1/uploadPhoto", formData, + new AxiosHeaders({ + 'Content-Type': 'multipart/form-data' + })) +} + +/** + * 获取常见问题 + */ +export const getQuestion = () => { + return http.get>>("app/v1/question") +} + +/** + * 获取应用列表 + */ +export const applicationPage = (cityNumber: string, page: number, pageSize = 50, name?: string) => { + let param: ESObject = {} + param['cityNumber'] = cityNumber + param['page'] = page + param['pageSize'] = pageSize + param['name'] = name + param['attribution'] = 0 + return http.get>>("app/v1/zamh/applicationPage", param) +} + +/** + * 保存应用操作日志 + */ +export const saveAppOperationLog = (appId: string, appName: string, type: string) => { + let param: ESObject = {} + param['appId'] = new String(appId) + param['appName'] = appName + param['operatorName'] = RuanseeAbilityStag.userCache.getUserName + param['operatorPoliceNumber'] = RuanseeAbilityStag.userCache.getUserCode + param['operatorIdCard'] = RuanseeAbilityStag.userCache.getIdCardNum + param['deptId'] = RuanseeAbilityStag.userCache.getDeptCode + param['deptName'] = RuanseeAbilityStag.userCache.getDeptName + param['type'] = type + + let json = JSON.stringify(param) + return http.postFromJson>("app/v1/zamh/addOperationRecords", json) +} + +//发送消息已读 +export const readMessage = (messageId: string) => { + let param: ESObject = {} + param['id'] = new String(messageId) + return http.get>("app/v1/zamh/readMessage", param) +} + +/** + * 下载文件 + */ +export const downLoadFile = (url: string, filePath: string, callback: (progressEvent: AxiosProgressEvent) => void) => { + try { + fs.accessSync(filePath); + fs.unlinkSync(filePath); + } catch (err) { + console.error( err) + } + + // return http.download(url,filePath,callback); + return axios({ + url: url, + method: 'get', + headers: new AxiosHeaders({ + 'User-Agent': 'Mozilla/5.0 (兼容浏览器标识)', + 'Content-Type': `application/x-www-form-urlencoded;` + }), + readTimeout:60000, + responseType:"array_buffer", + // context:getContext(this), + filePath: filePath, + onDownloadProgress:callback + // onDownloadProgress: (progressEvent: AxiosProgressEvent) => { + // console.info("progress: ", progressEvent && progressEvent.loaded && progressEvent.total ? + // Math.ceil(progressEvent.total / progressEvent.total * 100) : 0); + // + // } + }) +} \ No newline at end of file diff --git a/entry/src/main/ets/request/HttpUtils.ets b/entry/src/main/ets/request/HttpUtils.ets new file mode 100644 index 0000000..344e200 --- /dev/null +++ b/entry/src/main/ets/request/HttpUtils.ets @@ -0,0 +1,208 @@ +import axios, { + AxiosError, + AxiosHeaders, + AxiosInstance, + AxiosProgressEvent, + AxiosRequestConfig, + AxiosResponse, + InternalAxiosRequestConfig, +} from "@ohos/axios"; +import { AppCache } from '../app/AppCache'; +import { UserCache } from '../app/UserCache'; +import { StringUtils } from '../util/StringUtils'; + +// private _baseUrl: string = "http://192.168.43.98:8080/hc/phone/"; + +// axios 请求配置 +const config: AxiosRequestConfig = { + // baseURL: AppCache.getAppCache().getServiceAddress(), + baseURL: "http://20.90.2.2/pcenter_app_out/", + timeout: 1000 * 30, + connectTimeout: 30 * 1000, + readTimeout: 30 * 1000, +} + +// 定义返回值类型 +interface Result { + code: number; + message: string; + data: T; +} + +class Http { + // axios 实例 + private instance: AxiosInstance; + + // 构造函数初始化 + constructor(config: AxiosRequestConfig) { + this.instance = axios.create(config); + //定义拦截器 + this.interceptors(); + } + + private interceptors() { + // axios 发送请求之前的处理 + this.instance.interceptors.request.use((config: InternalAxiosRequestConfig) => { + // 在请求头部携带token + let token = UserCache.getUserCache().getUserInfo(); + if (token) { + // 把 token 放到 headers 里面 + config.headers!['userInfo'] = token; + } + let pgToken = AppCache.getAppCache().getPgToken; + if (pgToken) { + config.headers!['Authorization'] = pgToken; + } + // 打印请求URL + console.log('请求URL: ' + config.url); + // 打印请求参数 + if (config.params) { + console.log('请求参数(params): ' + JSON.stringify(config.params)); + } + + if (config.data) { + console.log('请求参数(data): ' + JSON.stringify(config.data)); + } + if (config.headers) { + console.log('请求参数(data): ' + JSON.stringify(config.headers)); + } + console.log('请求参数', JSON.stringify(config)); + return config; + + }, (error: ESObject) => { + error.data = {}; + error.data.msg = '服务器异常,请联系管理员!' + return error; + }) + // axios 请求返回之后的处理 + // 请求返回处理 + this.instance.interceptors.response.use((res: AxiosResponse) => { + let config:InternalAxiosRequestConfig = res.config + // 打印请求URL + console.log(`code: ${res.status} |: ${config.url}`); + // 打印请求参数 + if (config.params) { + console.log('请求参数(params): ' + JSON.stringify(config.params)); + } + if (config.data) { + console.log('请求参数(data): ' + JSON.stringify(config.data)); + } + if (config.headers) { + console.log('请求参数(data): ' + JSON.stringify(config.headers)); + } + if (res.config.responseType == 'array_buffer' || res.config.responseType == 'ARRAY_BUFFER') { + return res; + } + let msg = JSON.stringify(res.data); + msg = StringUtils.toJsonParaphrase(msg); + console.info('获取到的数据:' + msg); + if (res.status != 200) { + console.log(res.data.msg || '服务器出错啦'); + return Promise.reject(res.data.msg || '服务器出错啦'); + } + return res.data; + }, (error: AxiosError) => { + console.log('进入错误!'); + // error.data = {}; + if (error.code == "2300028") { + error.message = "网络超时"; + } else { + if (error && error.response) { + switch (error.response.status) { + case 400: + error.message = "错误请求"; + break; + case 401: + error.message = "未授权,请登录"; + break; + case 403: + error.message = "拒绝访问"; + break; + case 404: + error.message = "请求错误,未找到该资源"; + break; + case 405: + error.message = "请求方法未允许"; + break; + case 408: + error.message = "请求超时"; + break; + case 500: + error.message = "服务器端出错"; + break; + case 501: + error.message = "网络未实现"; + break; + case 502: + error.message = "网络错误"; + break; + case 503: + error.message = "服务不可用"; + break; + case 504: + error.message = "网络超时"; + break; + case 505: + error.message = "http版本不支持该请求"; + break; + default: + error.message = `连接错误${error.response.status}`; + } + } else { + error.message = "连接到服务器失败"; + } + } + console.log(error.message) + return Promise.reject(error); + }) + } + + // GET方法 + get(url: string, params?: object, headers?: AxiosHeaders): Promise { + return this.instance.get(url, { params, headers: headers }); + } + + // POST方法 + post(url: string, data?: object, headers?: AxiosHeaders): Promise { + return this.instance.post(url, data, { headers: headers }); + } + + // POST方法 + postFromJson(url: string, data?: string): Promise { + return this.instance.post(url, data, + { headers: new AxiosHeaders({ 'Content-Type': 'application/json; charset=utf-8' }) }); + } + + // POST方法 + postFromBody(url: string, data?: object, headers?: AxiosHeaders): Promise { + return this.instance.post(url, null, { params: data, headers: headers }); + } + + // PUT方法 + put(url: string, data?: object): Promise { + return this.instance.put(url, data); + } + + // DELETE方法 + delete(url: string): Promise { + return this.instance.delete(url); + } + + /** + * 下载文件 + * @param url + * @returns A required parameter cannot follow an optional parameter. + */ + download(url: string, filePath: string, + callback?: (progressEvent: AxiosProgressEvent) => void): Promise { + return this.instance.post(url, null,{ filePath: filePath,responseType:'ARRAY_BUFFER', + headers:new AxiosHeaders({ + 'Content-Type': `application/x-www-form-urlencoded;`}), + onDownloadProgress: callback }); + } +} + +export default new Http(config); + + + diff --git a/entry/src/main/ets/style/BorderStyle.ets b/entry/src/main/ets/style/BorderStyle.ets new file mode 100644 index 0000000..e5f5e52 --- /dev/null +++ b/entry/src/main/ets/style/BorderStyle.ets @@ -0,0 +1,18 @@ + +export const cardRoundBorderStyle :BorderOptions={ + + width:$r('app.float.default_1'), + color:$r('app.color.white'), + radius:$r('app.float.default_5') + +} + + +export const cardRoundBorderGreyStyle :BorderOptions={ + width:$r('app.float.default_1'), + color:$r('app.color.colorGrey2'), + radius:$r('app.float.default_5') + +} + + diff --git a/entry/src/main/ets/ui/custom/BaseTopTar.ets b/entry/src/main/ets/ui/custom/BaseTopTar.ets new file mode 100644 index 0000000..46481c8 --- /dev/null +++ b/entry/src/main/ets/ui/custom/BaseTopTar.ets @@ -0,0 +1,88 @@ +import { HMRouterMgr } from "@hadss/hmrouter" +import { router } from "@kit.ArkUI" +import { StringUtils } from "../../util/StringUtils" + +@Component +export struct BaseTopBar{ + @State title:string|Resource='' + // @State subtitle:string|null=null + @State leftText:string|null=null + @State leftImage:Resource = $r('app.media.icon_back3') + + @State rightText:string|null=null + @State rightImage:Resource |null =null + @State isBackImag:boolean = true + + //回退 + leftClickEvent?:()=>void + //右边按钮 + rightClickEvent?:()=>void + + build() { + Row() { + Row(){ + Image(this.leftImage) + .width($r('app.float.default_24')) + .height($r('app.float.default_24')) + .visibility(this.isBackImag?Visibility.Visible:Visibility.None) + + Text(this.leftText) + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_14')) + .visibility(StringUtils.isNullOrEmpty(this.leftText)?Visibility.None:Visibility.Visible) + } + .height("100%") + .width($r('app.float.default_68')) + .alignItems(VerticalAlign.Bottom) + .padding({ left:$r('app.float.default_10') }) + .onTouch((event) => { + if (event.type === TouchType.Down) { + this.leftImage = $r('app.media.icon_back2'); + } else if (event.type === TouchType.Up) { + this.leftImage = $r('app.media.icon_back3'); + } + }) + .onClick(() => { + if (!this.isBackImag)return + if (this.leftClickEvent) { + this.leftClickEvent() + } + HMRouterMgr.pop() + }) + + Text(this.title) + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_18')) + .layoutWeight(1) + .textAlign(TextAlign.Center) + .margin({ bottom: $r('app.float.default_2'), left: $r('app.float.default_10') ,right: $r('app.float.default_10') }) + + Row(){ + Image(this.rightImage) + .width($r('app.float.default_24')) + .height($r('app.float.default_24')) + .visibility(this.rightImage == null?Visibility.None:Visibility.Visible) + + Text(this.rightText) + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_14')) + .visibility(StringUtils.isNullOrEmpty(this.rightText)?Visibility.None:Visibility.Visible) + + } + .alignItems(VerticalAlign.Bottom) + .height("100%") + .width($r('app.float.default_68')) + .padding({ right: $r('app.float.default_10') }) + .onClick(() => { + if (this.rightClickEvent) { + this.rightClickEvent() + } + }) + } + .alignItems(VerticalAlign.Bottom) + .padding({ bottom: 10 }) + .width('100%') + .backgroundColor($r('app.color.bull')) + .height($r('app.float.default_88')) + } +} diff --git a/entry/src/main/ets/ui/custom/EmptyOrErrorItemView.ets b/entry/src/main/ets/ui/custom/EmptyOrErrorItemView.ets new file mode 100644 index 0000000..6204f0e --- /dev/null +++ b/entry/src/main/ets/ui/custom/EmptyOrErrorItemView.ets @@ -0,0 +1,30 @@ +import AppConstants from "../../app/AppConstant" + +/** + * 空数据或者错误Item + */ +@Component +export struct EmptyOrErrorItemView { + @State type: number= 0 + @State msg: string= "暂无数据" + + + build() { + Column() { + Image(this.type == 0 ? $r('app.media.icon_empty') : $r('app.media.icon_error2')) + .width($r('app.float.default_80')) + .height($r('app.float.default_80')) + + Text(this.msg) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey6')) + .textAlign(TextAlign.Center) + .margin({ top: $r('app.float.default_10') }) + + } + .justifyContent(FlexAlign.Center) + .alignItems(HorizontalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/custom/Watermark.ets b/entry/src/main/ets/ui/custom/Watermark.ets new file mode 100644 index 0000000..1892bff --- /dev/null +++ b/entry/src/main/ets/ui/custom/Watermark.ets @@ -0,0 +1,51 @@ +import { UserCache } from "../../app/UserCache" +import { DateFormat, DateUtils } from "../../util/DateUtils" +import { StringUtils } from "../../util/StringUtils" + +/** + * 水印模块 + * 水印内容: + * 应用名称 + * 警号(姓名) + * 当前日期(yyyy年MM月dd日) + */ +@Component +export struct Watermark { + private settings: RenderingContextSettings = new RenderingContextSettings(true) + private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) + + build() { + Canvas(this.context) + .width("100%") + .height("100%") + .hitTestBehavior(HitTestMode.Transparent) + .onReady(() => { + this.context.fillStyle = '#50AEAEAE' + this.context.font = "14vp" + this.context.textAlign = "left" + this.context.textBaseline = "middle" + + // 在这里绘制文字水印,也可以是图片水印 + for (let i = 0; i < this.context.width / 100; i++) { + this.context.translate(100 + (i * 30), 0) + let j = 0 + for (; j < this.context.height / 100; j++) { + this.context.rotate(-Math.PI / 180 * 30) + // 此处水印数据是写死的,具体请替换为自己的水印 + this.context.fillText(StringUtils.getResourceString(getContext(this), $r('app.string.app_name')), -60, -60) + this.context.fillText(`${UserCache.getUserCache().getUserName}(${UserCache.getUserCache().getUserCode})`, -60, -40) + this.context.fillText(DateUtils.formatDateStr(null, DateFormat.YYYYnMMyDDr), -60, -20) + this.context.rotate(Math.PI / 180 * 30) + this.context.translate(0, 150) + } + this.context.translate(0, -180 * j) + } + }) + } +} + +@Builder +export function createWaterMark() { + Watermark() + .hitTestBehavior(HitTestMode.None) // 必须设置其触摸测试为None或Transparent,否则正常组件无法响应事件 +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/dialog/LoadingDialog.ets b/entry/src/main/ets/ui/dialog/LoadingDialog.ets new file mode 100644 index 0000000..5dfaf2f --- /dev/null +++ b/entry/src/main/ets/ui/dialog/LoadingDialog.ets @@ -0,0 +1,43 @@ + +import hilog from '@ohos.hilog' + +@CustomDialog +export struct LoadingDialog{ + + @Prop loadingTips: string|Resource + // @State rotateAngle: number = 0 + //弹窗控制器 + controller: CustomDialogController + private tag: string = 'LoadingDialog' + + aboutToAppear() { + hilog.debug(0xFFFF, this.tag ,"Loading展示》》》》》") + } + + build() { + Stack() { + Column() { + LoadingProgress() + .width($r('app.float.default_48')) + .width($r('app.float.default_48')) + // Image($r('app.media.ic_load')) + // .height(50) + // .width(50) + // .rotate({angle: this.rotateAngle }) + // .animation({ + // duration: 800, + // iterations: -1, + // curve: Curve.Friction + // }).onAppear(() => { + // this.rotateAngle = 360 + // }) + Text(this.loadingTips) + .fontSize($r('app.float.text_size_15')) + .margin({ top: $r('app.float.default_10') ,left: $r('app.float.default_24'),right: $r('app.float.default_24')}) + } + .justifyContent(FlexAlign.Center) + } + .height($r('app.float.default_150')) + .width($r('app.float.default_200')) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/dialog/UnauthorizedPermissionDialog.ets b/entry/src/main/ets/ui/dialog/UnauthorizedPermissionDialog.ets new file mode 100644 index 0000000..4ae4d87 --- /dev/null +++ b/entry/src/main/ets/ui/dialog/UnauthorizedPermissionDialog.ets @@ -0,0 +1,77 @@ +import AppConstants from "../../app/AppConstant" +import { cardRoundBorderStyle } from "../../style/BorderStyle" + +@CustomDialog +export struct UnauthorizedPermissionDialog { + controller: CustomDialogController + submit?: () => void + cancel?: () => void + + build() { + Column() { + Column() { + Text("提示信息") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + .width('95%') + .height($r('app.float.default_46')) + .textAlign(TextAlign.Center) + + Divider() + .width('95%') + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey2')) + + Text("由于您拒绝了应用的权限,应用无法正常运行,请前往设置页面授权!") + .fontColor($r('app.color.colorYellow8')) + .fontSize($r('app.float.text_size_16')) + .fontWeight(FontWeight.Bold) + .width('95%') + .textAlign(TextAlign.Center) + .margin({ + top: $r('app.float.default_10'), + bottom: $r('app.float.default_10'), + left: $r('app.float.default_12'), + right: $r('app.float.default_12') + }) + + Row() { + Button("设置", { type: ButtonType.Normal }) + .borderRadius(8) + .width($r('app.float.default_72')) + .height($r('app.float.default_40')) + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_14')) + .backgroundColor($r('app.color.bull')) + .onClick(() => { + if (this.submit) { + this.submit() + } + }) + + Button("退出APP", { type: ButtonType.Normal }) + .borderRadius(8) + .width($r('app.float.default_72')) + .height($r('app.float.default_40')) + .fontColor($r('app.color.white')) + .margin({ left: $r('app.float.default_20') }) + .fontSize($r('app.float.text_size_14')) + .backgroundColor($r('app.color.bull')) + .onClick(() => { + if (this.cancel) { + this.cancel() + } + }) + + } + .alignItems(VerticalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + } + + } + .width('95%') + .backgroundColor($r('app.color.white')) + .padding({ bottom: $r('app.float.default_12') }) + .border(cardRoundBorderStyle) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/dialog/WebAppErrorDialog.ets b/entry/src/main/ets/ui/dialog/WebAppErrorDialog.ets new file mode 100644 index 0000000..5a035b0 --- /dev/null +++ b/entry/src/main/ets/ui/dialog/WebAppErrorDialog.ets @@ -0,0 +1,63 @@ +import AppConstants from "../../app/AppConstant"; +import { common } from "@kit.AbilityKit"; + +@Component +export struct WebAppErrorDialog { + @State message: string = ""; + @State ywry: string = ""; + @State ywryPhone: string = ""; + + build() { + Column() { + Text(this.message) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + + Row() { + Text(this.ywry) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + Text(this.ywryPhone) + .fontColor($r('app.color.bull')) + .fontSize($r('app.float.text_size_14')) + .copyOption(CopyOptions.LocalDevice) + .decoration({ + type: TextDecorationType.Underline, + color: Color.Blue, + style: TextDecorationStyle.SOLID + }) + .onClick(()=>{ + this.callPhone(this.ywryPhone) + }) + } + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Center) + .height($r('app.float.default_38')) + .width(AppConstants.PERCENTAGE_MAX) + + } + .alignItems(HorizontalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + } + + callPhone(phone:string){ + let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; + // 构造拨号参数 + let want:Want = { + action: "ohos.intent.action.DIAL", + parameters: { + "uri": "tel:" + phone // 必须符合tel:协议格式 + } + }; + + try { + context.startAbility(want).then(() => { + console.info("成功跳转拨号界面"); + }).catch((err:Error) => { + console.error("跳转失败:" + JSON.stringify(err)); + }); + } catch (error) { + console.error("启动异常:" + JSON.stringify(error)); + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/fragment/HomeFragment.ets b/entry/src/main/ets/ui/fragment/HomeFragment.ets new file mode 100644 index 0000000..a6edd04 --- /dev/null +++ b/entry/src/main/ets/ui/fragment/HomeFragment.ets @@ -0,0 +1,564 @@ +import { AxiosError, AxiosResponse } from "@ohos/axios"; +import { FileUtil, JSONUtil, ToastUtil } from "@pura/harmony-utils"; +import { BASE_IMAGE_URL } from "../../app/AppCache"; +import AppConstants from "../../app/AppConstant"; +import { UserCache } from "../../app/UserCache"; +import { ApplicationModel } from "../../model/resultModel/ApplicationResultModel"; +import { MainMessageBean } from "../../model/resultModel/MessageResultModel"; +import { + downLoadUserPhoto, + getMessageList, + getRecommendApplication, + readMessage, + saveAppOperationLog +} from "../../request/Api"; +import { cardRoundBorderGreyStyle, cardRoundBorderStyle } from "../../style/BorderStyle"; +import { FileUtils } from "../../util/FileUtils"; +import { StringUtils } from "../../util/StringUtils"; +import { EmptyOrErrorItemView } from "../custom/EmptyOrErrorItemView"; +import { RuanseeAbilityStag } from "../../app/RuanseeAbilityStag"; +import { fileUri } from "@kit.CoreFileKit"; +import { HMRouterMgr } from "@hadss/hmrouter"; +import { common } from "@kit.AbilityKit"; +import { H5OperationType, WebAppPageParam } from "../../model/uiModel/WebAppPageParam"; + +/** + * 主页组件 + */ +@Preview({ + title: 'ContentTable' +}) +@Component +export struct HomeFragment { + @State appListData: Array = [] + @State tjyyHeight: Resource = $r('app.float.default_98'); + @State msgListData: Array = [] + @State userPhoto: string | Resource = $r('app.media.icon_police_woman') + context = getContext(this) as common.UIAbilityContext; + allMessage?: () => void + + aboutToAppear(): void { + setTimeout(() => { + this.getImage() + this.getRecommendApplicationList() + this.getMsgList(); + }, 800) + this.context.eventHub.on("updateUserPhoto", () => { + this.userPhoto = fileUri.getUriFromPath(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + }) + } + + aboutToDisappear(): void { + this.context.eventHub.off("updateUserPhoto") + } + + getImage() { + if (FileUtil.accessSync(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto)) { + this.userPhoto = fileUri.getUriFromPath(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + return + } + downLoadUserPhoto(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + .then((res: AxiosResponse) => { + console.info("result:" + JSON.stringify(res.data)); + if (res.status == 200) { + this.userPhoto = + fileUri.getUriFromPath(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + } + }) + .catch((error: AxiosError) => { + console.error("error:" + JSON.stringify(error)); + }) + } + + getMsgList() { + getMessageList(0, 1, 6) + .then((res) => { + console.log("get 消息列表成功", JSONUtil.beanToJsonStr(res)) + if (res.code == 20041) { + let data = res.data + if (data) { + data.counts; + let items = data.items; + if (items) { + this.msgListData = items; + } + if (!this.msgListData || this.msgListData.length < 1) { + this.handErrorOrEmPty(0, "暂无新消息!") + } + } else { + this.handErrorOrEmPty(0, "暂无新消息!") + } + } else { + this.handErrorOrEmPty(-1, StringUtils.get(res.msg, "")) + } + }) + .catch((err: AxiosError) => { + console.error("get 消息列表失败", err) + this.handErrorOrEmPty(-1, err.message) + }) + } + + /** + * 错误或空处理 + */ + handErrorOrEmPty(type: number, msg: string) { + let bean = new MainMessageBean() + bean.baseType = type; + bean.msgContent = msg; + this.msgListData = new Array(); + this.msgListData.push(bean) + } + + /** + * 获取推荐应用列表 + */ + getRecommendApplicationList() { + getRecommendApplication() + .then((res) => { + console.log("get 推荐应用列表成功", JSONUtil.beanToJsonStr(res)) + if (res.code == 20041) { + let data = res.data; + if (data) { + let listData = new Array() + + let tjyy = data.推荐应用; + if (tjyy) { + tjyy.forEach((item) => { + listData.push(item) + }) + } + let zxyy = data.最新应用; + if (zxyy) { + zxyy.forEach((item) => { + listData.push(item) + }) + } + if (listData.length < 1) { + let bean = new ApplicationModel() + bean.baseType = 91 + bean.name = "应用指南" + bean.locationIcon = $r('app.media.ic_zfjc') + this.appListData.push(bean) + let bean1 = new ApplicationModel() + bean1.baseType = 92 + bean1.name = "常见问题" + bean1.locationIcon = $r('app.media.ic_zazh') + this.appListData.push(bean1) + let bean2 = new ApplicationModel() + bean2.baseType = 93 + bean2.name = "意见反馈" + bean2.locationIcon = $r('app.media.ic_zazh') + this.appListData.push(bean2) + bean = new ApplicationModel() + bean.baseType = 99 + bean.name = "更多应用" + bean.locationIcon = $r('app.media.icon_gd2') + this.appListData.push(bean) + // ToastUtil.showToast("暂无推荐应用") + return + } + if (listData.length >= 8) { + this.appListData = listData.slice(8) + let bean = this.appListData[7] + bean.baseType = 99 + bean.name = "更多应用" + bean.locationIcon = $r('app.media.icon_gd2') + } else { + this.appListData = listData + let bean = new ApplicationModel() + bean.baseType = 99 + bean.name = "更多应用" + bean.locationIcon = $r('app.media.icon_gd2') + this.appListData.push(bean) + } + if (listData.length > 4) { + this.tjyyHeight = $r('app.float.default_160') + } else { + this.tjyyHeight = $r('app.float.default_105') + } + } + } + }) + .catch((err: AxiosError) => { + console.error("get 推荐应用列表失败", err) + }) + } + + skipMyUserInfo() { + HMRouterMgr.push({ navigationId: 'startNavigation', pageUrl: "MyUserInfoPage" }) + } + + readMsg(item: MainMessageBean) { + readMessage(item.id) + .then((res) => { + console.debug("发送点击:", JSONUtil.beanToJsonStr(res)) + if (res.code == 20041) { + this.getMsgList() + } + }) + .catch((error: AxiosError) => { + console.error("发送点击:", JSONUtil.beanToJsonStr(error)) + }) + } + + build() { + Stack({ alignContent: Alignment.TopStart }) { + this.underlyingBackground() + this.mainContent() + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.page_background')) + } + + /** + * 主界面 + */ + @Builder + mainContent() { + Column() { + this.userInfoUI() + this.recommendedApplicationUI() + this.pendingMessageUI() + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + + } + + /** + * 待办消息区域 + */ + @Builder + pendingMessageUI() { + Column() { + Row() { + Text("待办消息") + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.colorGrey8')) + .layoutWeight(1) + .textAlign(TextAlign.Start) + + Text("全部消息") + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey6')) + .textAlign(TextAlign.Start) + .onClick(() => { + if (this.allMessage) { + this.allMessage() + } + }) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_18')) + .height($r('app.float.default_18')) + .margin({ left: $r('app.float.default_8') }); + } + .alignItems(VerticalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .height($r('app.float.default_40')) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey2')) + + List() { + ForEach(this.msgListData, (item: MainMessageBean, index) => { + if (item.baseType == 0 || item.baseType == -1) { + ListItem() { + EmptyOrErrorItemView({ type: item.baseType, msg: item.msgContent }) + } + } else { + ListItem() { + this.msgItem(item) + } + .onClick(() => { + this.readMsg(item) + if (item.appExhibition == 0) { + let pageParam: WebAppPageParam = { + appName: item.appName, + appId: item.appId, + secret: item.appSecret, + linkUrl: item.appUrl, + operationType: H5OperationType.readMessage, + msgId: item.msgId, + msgType: item.msgType, + } + HMRouterMgr.push({ pageUrl: 'WebAppPages', param: pageParam }) + return + } + HMRouterMgr.push({ pageUrl: 'MessageDetailsPage', param: item }) + }) + } + }) + } + .margin({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .width("95%") + .layoutWeight(1) + + } + .margin($r('app.float.default_10')) + .width('95%') + .layoutWeight(1) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + } + + /** + * 消息列表 + * @param item + */ + @Builder + msgItem(item: MainMessageBean) { + Column() { + Row() { + Text(item.msgTitle) + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.colorGrey8')) + .textAlign(TextAlign.Start) + .maxLines(1) + .ellipsisMode(EllipsisMode.END) + .layoutWeight(1) + + Image($r('app.media.icon_not_record')) + .width($r('app.float.default_38')) + .height($r('app.float.default_30')) + .margin({ left: $r('app.float.default_8') }) + } + .alignItems(VerticalAlign.Center) + .height($r('app.float.default_32')) + .margin({ left: $r('app.float.default_8'), right: $r('app.float.default_8') }) + .width('95%') + + Text(item.msgContent) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey6')) + .textAlign(TextAlign.Start) + .maxLines(2) + .ellipsisMode(EllipsisMode.END) + .width('95%') + .margin({ top: $r('app.float.default_5'), left: $r('app.float.default_8'), right: $r('app.float.default_8') }) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .margin({ top: $r('app.float.default_10') }) + .backgroundColor($r('app.color.colorGrey2')) + + Row() { + RelativeContainer() { + Image(BASE_IMAGE_URL + item.appIcon) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + .alignRules({ + middle: { anchor: '__container__', align: HorizontalAlign.Center }, // 水平居中 + center: { anchor: '__container__', align: VerticalAlign.Center } // 垂直居中 + }) + .border({ + radius: $r('app.float.default_5'), + }) + Image($r('app.media.ic_unread_doit')) + .width($r('app.float.default_8')) + .height($r('app.float.default_8')) + .margin({ right: $r('app.float.default_2'), top: $r('app.float.default_2') }) + .alignRules({ + middle: { anchor: '__container__', align: HorizontalAlign.End }, // 水平居中 + center: { anchor: '__container__', align: VerticalAlign.Top } // 垂直居中 + }) + } + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + + Text(item.appName) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey8')) + .layoutWeight(1) + .margin({ left: $r('app.float.default_8') }) + + Text(item.sendingTime) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey6')) + .margin({ left: $r('app.float.default_5') }) + } + .alignItems(VerticalAlign.Center) + .height($r('app.float.default_26')) + .width('95%') + .margin({ top: $r('app.float.default_5'), left: $r('app.float.default_8'), right: $r('app.float.default_8') }) + } + .width("95%") + .height('auto') + .padding({ top: $r('app.float.default_10'), bottom: $r('app.float.default_10') }) + .backgroundColor($r('app.color.white')) + .margin({ top: $r('app.float.default_10') }) + .border(cardRoundBorderGreyStyle) + } + + /** + * 错误或者空的消息列表显示 + */ + @Builder + msgItemError(type: number, msg: string) { + Column() { + Image(type == 0 ? $r('app.media.icon_empty') : $r('app.media.icon_error2')) + .width($r('app.float.default_80')) + .height($r('app.float.default_80')) + + Text(msg) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey6')) + .textAlign(TextAlign.Center) + .margin({ top: $r('app.float.default_10') }) + + } + .justifyContent(FlexAlign.Center) + .alignItems(HorizontalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + } + + /** + * 推荐应用区域 + */ + @Builder + recommendedApplicationUI() { + Column() { + Grid() { + ForEach(this.appListData, (item: ApplicationModel, index) => { + GridItem() { + Column() { + Image((item.baseType == 99 || item.baseType == 91 || item.baseType == 92 || item.baseType == 93) ? + item.locationIcon : BASE_IMAGE_URL + item.icon) + .size({ + width: $r('app.float.default_36'), + height: $r('app.float.default_36') + }) + .margin({ top: $r('app.float.default_8') }); + Text(item.name) + .textAlign(TextAlign.Center) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey8')) + .margin({ top: $r('app.float.default_8') }); + } + .height('auto') + .alignItems(HorizontalAlign.Center); + } + .onClick(() => { + if (item.baseType == 99) { + HMRouterMgr.push({ pageUrl: 'ApplicationWorkbenchPage' }) + return + } + if (item.baseType == 91) { + HMRouterMgr.push({ pageUrl: 'ApplicationGuidePage' }) + return + } + if (item.baseType == 92) { + HMRouterMgr.push({ pageUrl: 'FrequentlyQuestionsPage' }) + return + } + if (item.baseType == 93) { + HMRouterMgr.push({ pageUrl: 'OpinionsSuggestionsPages' }) + return + } + let pageParam: WebAppPageParam = { + appName: item.name, + appId: item.clientId, + secret: item.clientSecret, + linkUrl: item.link, + operationType: H5OperationType.login, + } + HMRouterMgr.push({ pageUrl: 'WebAppPages', param: pageParam }) + }) + }); + } + .columnsTemplate('1fr 1fr 1fr 1fr') //一行有4列,等分 + .columnsGap($r('app.float.default_10')) //行间距 + .rowsGap($r('app.float.default_10')); //列间距 + + } + .padding($r('app.float.default_10')) + .margin({ top: $r('app.float.default_10'), right: $r('app.float.default_10'), left: $r('app.float.default_10') }) + .width('95%') + .height(this.tjyyHeight) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + } + + /** + * 用户信息区域 + */ + @Builder + userInfoUI() { + Row() { + Image(this.userPhoto) + .size({ + width: $r('app.float.default_63'), + height: $r('app.float.default_63') + }) + .border({ + radius: 50 + }) + .margin({ left: $r('app.float.default_15') }); + + Column() { + Row() { + Text(UserCache.getUserCache().getUserName) + .fontSize($r('app.float.default_16')) + .fontColor($r('app.color.white')); + + Text(UserCache.getUserCache().getUserCode) + .fontSize($r('app.float.text_size_12')) + .fontColor($r('app.color.colorBluen8')) + .padding({ + left: $r('app.float.default_8'), + right: $r('app.float.default_8'), + top: $r('app.float.default_2'), + bottom: $r('app.float.default_2') + }) + .backgroundColor('#E9F4F3') + .border({ + radius: 10 + }); + } + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Start) + .onClick(() => { + this.skipMyUserInfo() + }); + + Text(UserCache.getUserCache().getDeptName) + .fontSize($r('app.float.default_16')) + .fontColor($r('app.color.white')) + .margin({ top: $r('app.float.default_8') }) + .onClick(() => { + this.skipMyUserInfo() + }); + + } + .margin({ left: $r('app.float.default_10') }) + .alignItems(HorizontalAlign.Start) + .layoutWeight(1); + } + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Start) + .margin({ top: $r('app.float.default_28') }) + .width(AppConstants.PERCENTAGE_MAX) + .height('13%') + .onClick(() => { + this.skipMyUserInfo() + }) + } + + /** + * 背景图片 + */ + @Builder + underlyingBackground() { + Column() { + Image($r('app.media.bg_two')) + .width(AppConstants.PERCENTAGE_MAX) + .height('28%') + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/fragment/MessageListFragment.ets b/entry/src/main/ets/ui/fragment/MessageListFragment.ets new file mode 100644 index 0000000..856b050 --- /dev/null +++ b/entry/src/main/ets/ui/fragment/MessageListFragment.ets @@ -0,0 +1,277 @@ +import { LitheRefresh, RefreshController } from "@abner/lithe_refresh"; +import { AxiosError } from "@ohos/axios"; +import { JSONUtil, ToastUtil } from "@pura/harmony-utils"; +import AppConstants from "../../app/AppConstant" +import { MainMessageBean } from "../../model/resultModel/MessageResultModel"; +import { getMessageList, readMessage, saveAppOperationLog } from "../../request/Api"; +import { StringUtils } from "../../util/StringUtils"; +import { BASE_IMAGE_URL } from "../../app/AppCache"; +import { cardRoundBorderGreyStyle } from "../../style/BorderStyle"; +import { EmptyOrErrorItemView } from "../custom/EmptyOrErrorItemView"; +import { HMRouterMgr } from "@hadss/hmrouter"; +import { H5OperationType, WebAppPageParam } from "../../model/uiModel/WebAppPageParam"; + + +/** + * 主页组件 + */ +@Preview({ + title: 'ContentTable' +}) +@Component +export struct MessageListFragment { + @State type: number = 0; + @State msgListData: Array = [] + controller: RefreshController = new RefreshController() + scroller: Scroller = new Scroller() + total: number = 0; + pageNum: number = 1; + isRefreshStatus: number = 0; + + aboutToAppear(): void { + setTimeout(() => { + this.controller.isAutoRefresh = true; + }, 800) + } + + getMsgList() { + getMessageList(this.type, this.pageNum, 30) + .then((res) => { + console.log("get 消息列表成功", JSONUtil.beanToJsonStr(res)) + if (res.code == 20041) { + let data = res.data + if (data) { + let items = data.items; + if (items && items.length > 0) { + if (this.isRefreshStatus == 1) { + this.isRefreshStatus = 0 + this.controller.finishRefresh() + this.msgListData = items; + } + if (this.isRefreshStatus == 2) { + this.isRefreshStatus = 0 + this.controller.finishLoadMore() + items.forEach((item) => { + this.msgListData.push(item) + }) + } + } else { + this.handErrorOrEmPty(0, "暂无新消息!") + } + } else { + this.handErrorOrEmPty(0, "暂无新消息!") + } + } else if (res.code == 20040) { + this.handErrorOrEmPty(0, "暂无新消息!") + } else { + this.handErrorOrEmPty(-1, StringUtils.get(res.msg, "")) + } + }) + .catch((err: AxiosError) => { + console.error("get 消息列表失败", err) + this.handErrorOrEmPty(-1, err.message) + }) + } + + /** + * 错误或空处理 + */ + handErrorOrEmPty(type: number, msg: string) { + // ToastUtil.showToast(msg) + if (this.isRefreshStatus == 1) { + this.isRefreshStatus = 0 + this.controller.finishRefresh() + this.msgListData = new Array(); + let bean = new MainMessageBean() + bean.baseType = type; + bean.msgContent = msg; + this.msgListData.push(bean) + } + if (this.isRefreshStatus == 2) { + this.isRefreshStatus = 0 + this.controller.finishLoadMore() + } + } + + build() { + Column() { + LitheRefresh({ + scroller: this.scroller, + controller: this.controller, + itemLayout: () => { + this.listView() + }, + onRefresh: () => { + this.controller.closeLoadMore = false; + this.pageNum = 1; + this.isRefreshStatus = 1; + this.getMsgList() + }, + onLoadMore: () => { + if (this.pageNum * 30 >= this.total) { + this.controller.finishLoadMore() + this.controller.closeLoadMore = true; + ToastUtil.showToast("没有更多数据!") + return + } + this.pageNum++; + this.isRefreshStatus = 2; + this.getMsgList() + } + }) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + } + + @Builder + listView() { + List({ scroller: this.scroller, space: 10 }) { + ForEach(this.msgListData, (item: MainMessageBean) => { + if (item.baseType == 0 || item.baseType == -1) { + ListItem() { + EmptyOrErrorItemView({ type: item.baseType, msg: item.msgContent }) + } + } else { + ListItem() { + this.itemView(item) + } + .onClick(() => { + if (this.type == 0) { + this.readMsg(item) + } + if (item.appExhibition == 0) { + let pageParam: WebAppPageParam = { + appName: item.appName, + appId: item.appId, + secret: item.appSecret, + linkUrl: item.appUrl, + operationType: H5OperationType.readMessage, + msgId: item.msgId, + msgType: item.msgType, + } + HMRouterMgr.push({ pageUrl: 'WebAppPages', param: pageParam }) + return + } + HMRouterMgr.push({ pageUrl: 'MessageDetailsPage', param: item }) + }) + } + }) + } + .divider({ + strokeWidth: $r('app.float.default_1'), + color: $r('app.color.colorGrey2'), + startMargin: $r('app.float.default_63') + }) + .listDirection(Axis.Vertical) + .scrollBar(BarState.Off) + .edgeEffect(EdgeEffect.None) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .nestedScroll({ + scrollForward: NestedScrollMode.PARENT_FIRST, + scrollBackward: NestedScrollMode.PARENT_FIRST + }) + } + + readMsg(item: MainMessageBean) { + readMessage(item.id) + .then((res) => { + console.debug("发送点击:", JSONUtil.beanToJsonStr(res)) + //java.lang.Integer cannot be cast to java.lang.String + if (res.code == 20041) { + this.controller.autoRefresh(true) + } + }) + .catch((error: AxiosError) => { + console.error("发送点击:", JSONUtil.beanToJsonStr(error)) + }) + } + + @Builder + itemView(item: MainMessageBean) { + Column() { + Row() { + Text(item.msgTitle) + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.colorGrey8')) + .textAlign(TextAlign.Start) + .maxLines(1) + .ellipsisMode(EllipsisMode.END) + .layoutWeight(1) + + Image(this.type == 0 ? $r('app.media.icon_not_record') : $r('app.media.icon_record')) + .width($r('app.float.default_38')) + .height($r('app.float.default_30')) + .margin({ left: $r('app.float.default_8') }) + } + .alignItems(VerticalAlign.Center) + .height($r('app.float.default_32')) + .margin({ left: $r('app.float.default_8'), right: $r('app.float.default_8') }) + .width('95%') + + Text(item.msgContent) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey6')) + .textAlign(TextAlign.Start) + .maxLines(2) + .ellipsisMode(EllipsisMode.END) + .width('95%') + .margin({ top: $r('app.float.default_5'), left: $r('app.float.default_8'), right: $r('app.float.default_8') }) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .margin({ top: $r('app.float.default_10') }) + .backgroundColor($r('app.color.colorGrey2')) + + Row() { + RelativeContainer() { + Image(BASE_IMAGE_URL + item.appIcon) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + .alignRules({ + middle: { anchor: '__container__', align: HorizontalAlign.Center }, // 水平居中 + center: { anchor: '__container__', align: VerticalAlign.Center } // 垂直居中 + }) + .border({ + radius: $r('app.float.default_5'), + }) + Image($r('app.media.ic_unread_doit')) + .width($r('app.float.default_8')) + .height($r('app.float.default_8')) + .visibility(this.type == 0? Visibility.Visible: Visibility.None) + .margin({ right: $r('app.float.default_2'), top: $r('app.float.default_2') }) + .alignRules({ + middle: { anchor: '__container__', align: HorizontalAlign.End }, // 水平居中 + center: { anchor: '__container__', align: VerticalAlign.Top } // 垂直居中 + }) + } + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + Text(item.appName) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey8')) + .layoutWeight(1) + .margin({ left: $r('app.float.default_8') }) + + Text(item.sendingTime) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey6')) + .margin({ left: $r('app.float.default_5') }) + } + .alignItems(VerticalAlign.Center) + .height($r('app.float.default_26')) + .width('95%') + .margin({ top: $r('app.float.default_5'), left: $r('app.float.default_8'), right: $r('app.float.default_8') }) + } + .width("95%") + .height('auto') + .padding({ top: $r('app.float.default_10'), bottom: $r('app.float.default_10') }) + .backgroundColor($r('app.color.white')) + .margin({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .border(cardRoundBorderGreyStyle) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/fragment/MyFragment.ets b/entry/src/main/ets/ui/fragment/MyFragment.ets new file mode 100644 index 0000000..cec5172 --- /dev/null +++ b/entry/src/main/ets/ui/fragment/MyFragment.ets @@ -0,0 +1,370 @@ +import AppConstants from "../../app/AppConstant" +import { RuanseeAbilityStag } from "../../app/RuanseeAbilityStag" +import { HMRouterMgr } from "@hadss/hmrouter" +import { ToastUtil } from "@pura/harmony-utils/src/main/ets/action/ToastUtil" +import { FileUtil } from "@pura/harmony-utils" +import { FileUtils } from "../../util/FileUtils" +import { fileUri } from "@kit.CoreFileKit" +import { downLoadUserPhoto } from "../../request/Api" +import { AxiosError, AxiosResponse } from "@ohos/axios" +import { common } from "@kit.AbilityKit" +import { H5OperationType, WebAppPageParam } from "../../model/uiModel/WebAppPageParam" + +/** + * 主页组件 + */ +@Preview({ + title: 'ContentTable' +}) +@Component +export struct MyFragment { + @State userPhoto: string | Resource = $r('app.media.icon_police_woman') + context = getContext(this) as common.UIAbilityContext; + + aboutToAppear(): void { + this.getImage() + this.context.eventHub.on("updateUserPhoto",()=>{ + this.userPhoto = fileUri.getUriFromPath(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + }) + } + + aboutToDisappear(): void { + this.context.eventHub.off("updateUserPhoto") + } + + build() { + Stack({ alignContent: Alignment.TopStart }) { + this.underlyingBackground() + this.mainContent() + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.page_background')) + + } + + getImage() { + if (FileUtil.accessSync(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto)) { + this.userPhoto = fileUri.getUriFromPath(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + return + } + downLoadUserPhoto(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + .then((res:AxiosResponse)=>{ + console.info("result:"+ JSON.stringify(res.data)); + if(res.status == 200){ + this.userPhoto = fileUri.getUriFromPath(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + } + }) + .catch((error:AxiosError)=> { + console.error("error:" + JSON.stringify(error)); + }) + } + + skipMyUserInfo() { + HMRouterMgr.push({ navigationId: 'startNavigation', pageUrl: "MyUserInfoPage" }) + } + + /** + * 主内容 + */ + @Builder + mainContent() { + Column() { + Stack({ alignContent: Alignment.Top }) { + Column() { + Row() { + //警号 + Row() { + Text("NO·") + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_6')) + .backgroundColor($r('app.color.bull')) + .borderRadius(50)// 50是宽高的一半 + .padding(3) + .border({ radius: $r('app.float.default_50') }) + + Text(RuanseeAbilityStag.userCache.getUserCode) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorBluen6')) + .margin({ left: $r('app.float.default_5') }) + + } + .alignItems(VerticalAlign.Center) + .padding({ + left: $r('app.float.default_5'), + right: $r('app.float.default_5'), + top: $r('app.float.default_3'), + bottom: $r('app.float.default_3') + }) + .width('auto') + .height('auto') + .backgroundColor("#E9F4F3") + .border({ radius: $r('app.float.default_50') }) + + Blank() + .layoutWeight(1) + + //修改图标 + Image($r('app.media.icon_edit_info')) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + .onClick(() => { + this.skipMyUserInfo() + }) + + } + .width(AppConstants.PERCENTAGE_MAX) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .alignItems(VerticalAlign.Center) + .margin({ top: $r('app.float.default_10') }) + .height($r('app.float.default_40')) + .onClick(() => { + this.skipMyUserInfo() + }) + + Text(`姓名:${RuanseeAbilityStag.userCache.getUserName}`) + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_16')) + .margin({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_15') + }) + + Text(`工作号码:${RuanseeAbilityStag.userCache.getWorkPhone}`) + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_16')) + .margin({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_10') + }) + + Text(`单位:${RuanseeAbilityStag.userCache.getDeptName}`) + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_16')) + .margin({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_10') + }) + + + } + .alignItems(HorizontalAlign.Start) + .width(AppConstants.PERCENTAGE_MAX) + .margin({ + top: $r('app.float.default_80') + }) + .border({ radius: $r('app.float.default_10') }) + .borderRadius($r('app.float.default_10')) + .backgroundImageSize(ImageSize.FILL) + .height($r('app.float.default_160')) + .backgroundImagePosition(Alignment.Center) // 居中显示背景图 + .backgroundImage($r('app.media.icon_my_userbg')) + .onClick(() => { + this.skipMyUserInfo() + }) + + Column() { + Column() { + Image(this.userPhoto) + .width($r('app.float.default_88')) + .height($r('app.float.default_88')) + .borderRadius(50)// 50是宽高的一半 + .clip(true)// 裁剪超出圆角部分 + .aspectRatio(1) // 确保宽高比例一致 + } + .width($r('app.float.default_90')) + .height($r('app.float.default_90')) + .backgroundColor("#55e5e5e5") + .margin({ top: $r('app.float.default_48') }) + .onClick(() => { + this.skipMyUserInfo() + }) + .border({ + width: $r('app.float.default_2'), + radius: $r('app.float.default_50'), + color: "#66e5e5e5" + }) + + } + .width(AppConstants.PERCENTAGE_MAX) + } + .padding({ + left: $r('app.float.default_30'), + right: $r('app.float.default_30') + }) + .width(AppConstants.PERCENTAGE_MAX) + .height('auto') + + Column() { + Row() { + Column() { + Image($r('app.media.icon_operation_guide')) + .width($r('app.float.default_32')) + .height($r('app.float.default_32')) + + Text("应用指南") + .fontSize($r('app.float.text_size_12')) + .fontColor($r('app.color.colorGrey8')) + .textAlign(TextAlign.Center) + .margin({ top: $r('app.float.default_8') }) + + } + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .padding({ top: $r('app.float.default_10'), bottom: $r('app.float.default_10') }) + .height('auto') + .layoutWeight(1) + .onClick(() => { + HMRouterMgr.push({ navigationId: 'startNavigation', pageUrl: "ApplicationGuidePage" }) + }) + + Column() { + Image($r('app.media.icon_feedback')) + .width($r('app.float.default_32')) + .height($r('app.float.default_32')) + + Text("意见建议") + .fontSize($r('app.float.text_size_12')) + .fontColor($r('app.color.colorGrey8')) + .textAlign(TextAlign.Center) + .margin({ top: $r('app.float.default_8') }) + + } + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .padding({ top: $r('app.float.default_10'), bottom: $r('app.float.default_10') }) + .height('auto') + .layoutWeight(1) + .onClick(() => { + HMRouterMgr.push({ navigationId: 'startNavigation', pageUrl: "OpinionsSuggestionsPages" }) + }) + + Column() { + Image($r('app.media.icon_problen')) + .width($r('app.float.default_32')) + .height($r('app.float.default_32')) + + Text("常见问题") + .fontSize($r('app.float.text_size_12')) + .fontColor($r('app.color.colorGrey8')) + .textAlign(TextAlign.Center) + .margin({ top: $r('app.float.default_8') }) + + } + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .padding({ top: $r('app.float.default_10'), bottom: $r('app.float.default_10') }) + .height('auto') + .layoutWeight(1) + .onClick(() => { + HMRouterMgr.push({ navigationId: 'startNavigation', pageUrl: "FrequentlyQuestionsPage" }) + }) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height('auto') + .margin({ top: $r('app.float.default_10') }) + + Blank() + .backgroundColor($r('app.color.colorGrey2')) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_10')) + .margin({ top: $r('app.float.default_10') }) + + Row() { + Image($r('app.media.icon_authen')) + .width($r('app.float.default_28')) + .height($r('app.float.default_28')) + + Text("认证管理") + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.colorGrey8')) + .textAlign(TextAlign.Start) + .layoutWeight(1) + .margin({ left: $r('app.float.default_10') }) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + } + .alignItems(VerticalAlign.Center) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .height($r('app.float.default_52')) + .margin({ top: $r('app.float.default_5') }) + .onClick(() => { + ToastUtil.showToast("功能开发中...") + + let pageParam :WebAppPageParam= { + appName: '测试应用', + appId: 'tastApp', + secret: "35DB4R4GHN658S", + linkUrl: "", + operationType:H5OperationType.login, + } + HMRouterMgr.push({pageUrl:'WebAppPages',param: pageParam}) + }) + + Divider() + .backgroundColor($r('app.color.colorGrey2')) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + + Row() { + Image($r('app.media.icon_about')) + .width($r('app.float.default_28')) + .height($r('app.float.default_28')) + + Text("关于") + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.colorGrey8')) + .textAlign(TextAlign.Start) + .layoutWeight(1) + .margin({ left: $r('app.float.default_10') }) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + } + .alignItems(VerticalAlign.Center) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .height($r('app.float.default_52')) + .onClick(() => { + HMRouterMgr.push({ navigationId: 'startNavigation', pageUrl: "AboutPage" }) + }) + + Divider() + .backgroundColor($r('app.color.colorGrey2')) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + } + .width(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.white')) + .margin({ top: $r('app.float.default_20') }) + .border({ + radius: { + topLeft: $r('app.float.default_10'), + topRight: $r('app.float.default_10') + } + }) + .layoutWeight(1) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + } + + /** + * 顶部背景图片 + */ + @Builder + underlyingBackground() { + Column() { + Image($r('app.media.bg_two')) + .width(AppConstants.PERCENTAGE_MAX) + .height('40%') + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/fragment/PendingMessagePage.ets b/entry/src/main/ets/ui/fragment/PendingMessagePage.ets new file mode 100644 index 0000000..7bbefc1 --- /dev/null +++ b/entry/src/main/ets/ui/fragment/PendingMessagePage.ets @@ -0,0 +1,42 @@ +import AppConstants from "../../app/AppConstant" +import { BaseTopBar } from "../custom/BaseTopTar" +import { MessageListFragment } from "./MessageListFragment" + +/** + * 主页组件 + */ +@Preview({ + title: 'ContentTable' +}) +@Component +export struct PendingMessagePage { + + build() { + Column() { + BaseTopBar({ + isBackImag:false, + title: $r('app.string.title_PendingMsg') + }) + Tabs({ barPosition: BarPosition.Start }) { + TabContent() { + MessageListFragment({type:0}) + }.tabBar(new SubTabBarStyle('未读消息')) + + TabContent() { + MessageListFragment({type:1}) + }.tabBar(new SubTabBarStyle('已读消息')) + + } + .vertical(false) + .scrollable(true) + .barMode(BarMode.Fixed) + .width('100%') + .layoutWeight(1) + .backgroundColor(0xF1F3F5) + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + + + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/fragment/WorkbenchFragment.ets b/entry/src/main/ets/ui/fragment/WorkbenchFragment.ets new file mode 100644 index 0000000..4d48fc9 --- /dev/null +++ b/entry/src/main/ets/ui/fragment/WorkbenchFragment.ets @@ -0,0 +1,264 @@ +import { HMRouterMgr } from "@hadss/hmrouter"; +import { AxiosError } from "@ohos/axios"; +import { JSONUtil, ToastUtil } from "@pura/harmony-utils"; +import { BASE_IMAGE_URL } from "../../app/AppCache"; +import AppConstants from "../../app/AppConstant"; +import { ApplicationModel } from "../../model/resultModel/ApplicationResultModel"; +import { H5OperationType, WebAppPageParam } from "../../model/uiModel/WebAppPageParam"; +import { getRecommendApplication } from "../../request/Api"; +import { cardRoundBorderStyle } from "../../style/BorderStyle"; +import { AppUtils } from "../../util/AppUtils"; +import { BaseTopBar } from "../custom/BaseTopTar"; + +/** + * 主页组件 + */ +@Preview({ + title: 'ContentTable' +}) +@Component +export struct WorkbenchFragment { + @State tjyyHeight: Resource = $r('app.float.default_92'); + @State appListData: Array = [] + + + + aboutToAppear(): void { + setTimeout(() => { + this.getRecommendApplicationList(); + // this.getLocationApplicationList(); + },800) + } + + /** + * 获取本地应用列表 you must specify an option at least. + */ + getLocationApplicationList() { + new AppUtils().getAppList() + .then((res) => { + + }) + } + + /** + * 获取推荐应用列表 + */ + getRecommendApplicationList() { + getRecommendApplication() + .then((res) => { + console.log("get 推荐应用列表成功", JSONUtil.beanToJsonStr(res)) + if (res.code == 20041) { + let data = res.data; + if (data) { + let listData = new Array() + let tjyy = data.推荐应用; + if (tjyy) { + tjyy.forEach((item) => { + listData.push(item) + }) + } + let zxyy = data.最新应用; + if (zxyy) { + zxyy.forEach((item) => { + listData.push(item) + }) + } + if (listData.length < 1) { + let bean = new ApplicationModel() + bean.baseType = 91 + bean.name = "应用指南" + bean.locationIcon = $r('app.media.ic_zfjc') + this.appListData.push(bean) + let bean1 = new ApplicationModel() + bean1.baseType = 92 + bean1.name = "常见问题" + bean1.locationIcon = $r('app.media.ic_zazh') + this.appListData.push(bean1) + let bean2 = new ApplicationModel() + bean2.baseType = 93 + bean2.name = "意见反馈" + bean2.locationIcon = $r('app.media.ic_zazh') + this.appListData.push(bean2) + bean = new ApplicationModel() + bean.baseType = 99 + bean.name = "更多应用" + bean.locationIcon = $r('app.media.icon_gd2') + this.appListData.push(bean) + return + } + + if (listData.length >= 8) { + this.appListData = listData.slice(8) + let bean = this.appListData[7] + bean.baseType = 99 + bean.name = "更多应用" + bean.locationIcon = $r('app.media.icon_gd2') + } + this.appListData = listData + if (this.appListData.length > 4) { + this.tjyyHeight = $r('app.float.default_150') + } else { + this.tjyyHeight = $r('app.float.default_98') + } + } + } + }) + .catch((err: AxiosError) => { + console.error("get 推荐应用列表失败", err) + }) + } + + build() { + Column(){ + BaseTopBar({ + isBackImag:false, + title: $r('app.string.title_Workbench') + }) + + Row(){ + Divider() + .width($r('app.float.default_5')) + .height($r('app.float.default_14')) + .backgroundColor($r('app.color.bull')) + .margin({ left: $r('app.float.default_10') }) + + Text("推荐应用") + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.bull')) + .margin({ left: $r('app.float.default_8') }) + + } + .alignItems(VerticalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_40')) + + this.recommendedApplicationUI() + + + Row(){ + Divider() + .width($r('app.float.default_5')) + .height($r('app.float.default_14')) + .backgroundColor($r('app.color.bull')) + .margin({ left: $r('app.float.default_10') }) + + Text("自定义应用") + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.bull')) + .margin({ left: $r('app.float.default_8') }) + + } + .alignItems(VerticalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + .margin({ top: $r('app.float.default_8')}) + .height($r('app.float.default_40')) + + this.locationApp(); + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + } + + /** + * 推荐应用区域 + */ + @Builder + locationApp() { + Column() { + Grid() { + ForEach(this.appListData, (item: ApplicationModel, index) => { + GridItem() { + Column() { + Image(item.baseType == 99 ? item.locationIcon : BASE_IMAGE_URL + item.icon) + .size({ + width: $r('app.float.default_36'), + height: $r('app.float.default_36') + }) + .margin({ top: $r('app.float.default_8') }); + Text(item.name) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey8')) + .margin({ top: $r('app.float.default_8') }); + } + .alignItems(HorizontalAlign.Center); + }; + }); + } + .columnsTemplate('1fr 1fr 1fr 1fr') //一行有4列,等分 + .columnsGap($r('app.float.default_10')) //行间距 + .rowsGap($r('app.float.default_10')); //列间距 + + } + .padding($r('app.float.default_10')) + .margin({ top: $r('app.float.default_10'), right: $r('app.float.default_10'), left: $r('app.float.default_10') }) + .width('95%') + .height(this.tjyyHeight) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + } + + /** + * 推荐应用区域 + */ + @Builder + recommendedApplicationUI() { + Column() { + Grid() { + ForEach(this.appListData, (item: ApplicationModel, index) => { + GridItem() { + Column() { + Image((item.baseType == 99||item.baseType == 91||item.baseType == 92||item.baseType == 93) ? item.locationIcon : BASE_IMAGE_URL + item.icon) + .size({ + width: $r('app.float.default_36'), + height: $r('app.float.default_36') + }) + .margin({ top: $r('app.float.default_8') }); + Text(item.name) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey8')) + .margin({ top: $r('app.float.default_8') }); + } + .alignItems(HorizontalAlign.Center); + } + .onClick(() => { + if (item.baseType == 99) { + HMRouterMgr.push({pageUrl:'ApplicationWorkbenchPage'}) + return + } + if (item.baseType == 91) { + HMRouterMgr.push({pageUrl:'ApplicationGuidePage'}) + return + } + if (item.baseType == 92) { + HMRouterMgr.push({pageUrl:'FrequentlyQuestionsPage'}) + return + } + if (item.baseType == 93) { + HMRouterMgr.push({pageUrl:'OpinionsSuggestionsPages'}) + return + } + let pageParam :WebAppPageParam= { + appName: item.name, + appId: item.clientId, + secret: item.clientSecret, + linkUrl: item.link, + operationType:H5OperationType.login, + } + HMRouterMgr.push({pageUrl:'WebAppPages',param: pageParam}) + }) + }); + } + .columnsTemplate('1fr 1fr 1fr 1fr') //一行有4列,等分 + .columnsGap($r('app.float.default_10')) //行间距 + .rowsGap($r('app.float.default_10')); //列间距 + + } + .padding($r('app.float.default_10')) + .margin({ top: $r('app.float.default_10'), right: $r('app.float.default_10'), left: $r('app.float.default_10') }) + .width('95%') + .height(this.tjyyHeight) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/AboutPage.ets b/entry/src/main/ets/ui/pages/AboutPage.ets new file mode 100644 index 0000000..14ca8a9 --- /dev/null +++ b/entry/src/main/ets/ui/pages/AboutPage.ets @@ -0,0 +1,137 @@ +import { HMRouter } from '@hadss/hmrouter'; +import { bundleManager } from '@kit.AbilityKit'; +import { BaseTopBar } from '../custom/BaseTopTar'; +import { createWaterMark } from '../custom/Watermark'; + +@Preview +@HMRouter({ pageUrl: 'AboutPage' }) +@Component +export struct AboutPage { + // @State about1: string = ' 民警可以使用个人中心查看基本信息,使用。' + // @State about2: string = ' 提供省厅、地市两级用户盘查统计实时展示分析、任务管理、卡点管理、本地临时关注人员车辆管理等功能。' + // @State about3: string = ' 2、实时比对车辆被盗抢库和临时布控库,方便民警快速发现问题车辆。' + @State versionName: string = "1.0" + @State versionCode: string = "1" + + aboutToAppear(): void { + this.getAppVersion() + } + + + /** + * 获取应用版本号 + */ + async getAppVersion() { + let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION; + try { + // 使用await等待Promise的结果 + const data = await bundleManager.getBundleInfoForSelf(bundleFlags); + if (data) { + console.info('FileUtil', 'getBundleInfoForSelf successfully. Data: %s', JSON.stringify(data)); + this.versionName = data.versionName + this.versionCode = data.versionCode + "" + } else { + console.error('FileUtil', 'getBundleInfoForSelf returned an empty result.'); + } + } catch (err) { + console.error('FileUtil', 'getBundleInfoForSelf failed: %s', err.message); + } + } + + build() { + Column() { + BaseTopBar({ + title:$r('app.string.title_About') + }) + + Column() { + + Image($r('app.media.icon_applogin')) + .width($r('app.float.default_68')) + .height($r('app.float.default_68')) + + Text($r('app.string.app_name')) + .fontColor($r('app.color.black')) + .fontWeight(FontWeight.Bold) + .fontSize($r('app.float.text_size_20')) + .margin({ top: $r('app.float.default_18') }) + + + Column() { + Row() { + Text('版本号:') + .fontColor($r('app.color.grad')) + .fontSize($r('app.float.text_size_16')) + Text(this.versionCode) + .fontColor($r('app.color.colorGrey7')) + .fontSize($r('app.float.text_size_16')) + .margin({ left: $r('app.float.default_3') }) + } + .width('100%') + + Divider() + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.page_background')) + .width('100%') + .margin({ top: $r('app.float.default_10') }) + + Row() { + Text('版本名称:') + .fontColor($r('app.color.grad')) + .fontSize($r('app.float.text_size_16')) + Text(this.versionName) + .fontColor($r('app.color.colorGrey7')) + .fontSize($r('app.float.text_size_16')) + .margin({ left: $r('app.float.default_3') }) + } + .width('100%') + .margin({ top: $r('app.float.default_10') }) + + Divider() + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.page_background')) + .width('100%') + .margin({ top: $r('app.float.default_10') }) + + Row() { + Text('检测更新:') + .fontColor($r('app.color.grad')) + .fontSize($r('app.float.text_size_16')) + Text("当前已是最新版本") + .fontColor($r('app.color.colorGrey7')) + .fontSize($r('app.float.text_size_16')) + .margin({ left: $r('app.float.default_3') }) + } + .width('100%') + .margin({ top: $r('app.float.default_10') }) + + // Text('应用介绍') + // .fontColor($r('app.color.grad')) + // .fontSize($r('app.float.text_size_16')) + // .margin({ top: $r('app.float.default_10') }) + + } + .width('90%') + .padding($r('app.float.default_15')) + .margin({ top: $r('app.float.default_40') }) + .backgroundColor($r('app.color.white')) + .border({ + width: $r('app.float.default_1'), + color: $r('app.color.page_background'), + radius: $r('app.float.comm_image_radius') + }) + + } + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .margin({ bottom: $r('app.float.default_80') }) + .width('100%') + .layoutWeight(1) + + } + .width('100%') + .height('100%') + .backgroundColor($r('app.color.page_background')) + .overlay(createWaterMark()) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/ApplicationDetailsPage.ets b/entry/src/main/ets/ui/pages/ApplicationDetailsPage.ets new file mode 100644 index 0000000..07b37b2 --- /dev/null +++ b/entry/src/main/ets/ui/pages/ApplicationDetailsPage.ets @@ -0,0 +1,356 @@ +import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"; +import { ToastUtil } from "@pura/harmony-utils/src/main/ets/action/ToastUtil"; +import { BASE_IMAGE_URL } from "../../app/AppCache"; +import AppConstants from "../../app/AppConstant"; +import { AppDataModel, AppGuideDetailsBean } from "../../model/resultModel/ApplicationResultModel"; +import { StringUtils } from "../../util/StringUtils"; +import { BaseTopBar } from "../custom/BaseTopTar"; +import { createWaterMark } from "../custom/Watermark"; +import { call } from "@kit.TelephonyKit"; +import { StrUtil } from "@pura/harmony-utils/src/main/ets/utils/StrUtil"; +import { LitheRefresh, RefreshController } from "@abner/lithe_refresh"; +import { downLoadFile, operationGuideList } from "../../request/Api"; +import { AxiosError, AxiosResponse } from "@ohos/axios"; +import { EmptyOrErrorItemView } from "../custom/EmptyOrErrorItemView"; +import { ToastUtils } from "../../util/ToasUtils"; +import { plainToInstance } from "class-transformer"; +import { cardRoundBorderStyle } from "../../style/BorderStyle"; +import { FileUtil } from "@pura/harmony-utils"; +import { FileUtils } from "../../util/FileUtils"; +import { common } from "@kit.AbilityKit"; +import { DialogHelper } from "@pura/harmony-dialog"; + +@Component +@HMRouter({ pageUrl: "ApplicationDetailsPage" }) +export struct ApplicationDetailsPage { + context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; + @State param: AppDataModel | undefined = undefined + @State appListData: AppGuideDetailsBean[] = [] + controller: RefreshController = new RefreshController() + scroller: Scroller = new Scroller() + isRefreshStatus: number = 0; + + aboutToAppear(): void { + this.param = HMRouterMgr.getCurrentParam() as AppDataModel; + if (!this.param) { + ToastUtil.showToast("参数错误!") + HMRouterMgr.pop() + return + } + setTimeout(() => { + this.controller.isAutoRefresh = true + }, 800) + } + + /** + * 错误或空处理 + */ + handErrorOrEmPty(type: number, msg: string) { + ToastUtils.toastBottom(msg) + if (this.isRefreshStatus == 1) { + this.controller.finishRefresh() + this.isRefreshStatus = 0 + let bean = new AppGuideDetailsBean() + bean.baseType = type; + bean.remark = msg; + this.appListData = new Array(); + this.appListData.push(bean) + } + } + + //342401199412220026 + getAppDetails() { + operationGuideList(this.param!.id) + .then((res) => { + this.controller.finishRefresh() + if (res.code == 20041) { + let data = res.data; + if (data) { + this.appListData = new Array(); + this.isRefreshStatus = 0 + data.forEach((bean) => { + let item = plainToInstance(AppGuideDetailsBean, bean) + this.appListData.push(item); + }) + } else { + this.handErrorOrEmPty(0, "暂无数据") + } + } else { + this.handErrorOrEmPty(-1, StringUtils.get(res.msg, "")) + } + }) + .catch((err: AxiosError) => { + this.handErrorOrEmPty(-1, err.message) + }) + } + + openOrDownLoad(item: AppGuideDetailsBean) { + if (FileUtil.accessSync(FileUtils.FILE_DIR + "/" + item.getName())) { + FileUtils.openWithThirdPartyApp(this.context,FileUtils.FILE_DIR + "/" + item.getName()); + return + } + //自定义文字内容 + let dialogId = DialogHelper.showLoadingDialog({ + loadColor: Color.White, + content: "正在下载,请稍后...", + fontSize: 15, + backgroundColor: '#ED000000', + autoCancel: true, + onWillDismiss: () => { + DialogHelper.closeDialog(dialogId) + dialogId = '' + } + }) + downLoadFile(BASE_IMAGE_URL+item.filePath, FileUtils.FILE_DIR + "/" + item.getName(), (progressEvent) => { + console.info("下载进度: ", progressEvent && progressEvent.loaded && progressEvent.total ? + Math.ceil(progressEvent.loaded / progressEvent.total * 100) +"%" : 0 +"%"); + }) + .then((res:AxiosResponse) => { + DialogHelper.closeDialog(dialogId) + if (res.status == 200) { + this.openOrDownLoad(item) + } else { + ToastUtils.toastBottom(`下载失败:${res.status}`) + } + }) + .catch((err: AxiosError) => { + DialogHelper.closeDialog(dialogId) + ToastUtils.toastBottom(`下载失败:${err.message}`) + }) + } + + build() { + Column() { + BaseTopBar({ + title: $r('app.string.title_guide_details') + }) + Column() { + + Row() { + Image(BASE_IMAGE_URL + this.param!.icon) + .width($r('app.float.default_46')) + .height($r('app.float.default_46')) + + Column() { + Text(this.param!.name) + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.colorGrey8')) + .maxLines(1) + .ellipsisMode(EllipsisMode.END) + + Text(this.param!.serviceProvider) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey6')) + .margin({ top: $r('app.float.default_5') }) + .maxLines(1) + .ellipsisMode(EllipsisMode.END) + } + .alignItems(HorizontalAlign.Start) + .justifyContent(FlexAlign.Center) + .layoutWeight(1) + .margin({ left: $r('app.float.default_8') }) + .height($r('app.float.default_60')) + + } + .width(AppConstants.PERCENTAGE_MAX) + + Row() { + Text('运维人员:') + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + Text(StringUtils.get(this.param!.operationPerson, "暂无")) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + + Blank() + .layoutWeight(1) + Text('联系电话:') + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + Text(StringUtils.get(this.param!.phoneNumber, "暂无")) + .fontColor($r('app.color.bull')) + .fontSize($r('app.float.text_size_14')) + .decoration({ + type: TextDecorationType.Underline, + color: Color.Blue, + style: TextDecorationStyle.SOLID + }) + .onClick(() => { + if (StrUtil.isNotEmpty(this.param!.phoneNumber)) { + this.callPhone((StringUtils.get(this.param!.phoneNumber, "暂无"))) + } + }) + } + .width(AppConstants.PERCENTAGE_MAX) + .margin({ top: $r('app.float.default_10') }) + + Divider() + .color($r('app.color.colorGrey2')) + .backgroundColor($r('app.color.colorGrey2')) + .margin({ top: $r('app.float.default_10') }) + + Text("应用介绍:") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + .margin({ top: $r('app.float.default_10') }) + .textAlign(TextAlign.Start) + .width(AppConstants.PERCENTAGE_MAX) + + Text(StringUtils.get(this.param!.remark, "暂无")) + .fontColor($r('app.color.colorGrey6')) + .fontSize($r('app.float.text_size_14')) + .margin({ top: $r('app.float.default_10') }) + .textAlign(TextAlign.Start) + .width(AppConstants.PERCENTAGE_MAX) + .margin({ top: $r('app.float.default_10') }) + + } + .padding({ + top: $r('app.float.default_10'), + bottom: $r('app.float.default_10'), + left: $r('app.float.default_10'), + right: $r('app.float.default_10') + }) + .width(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.white')) + + LitheRefresh({ + scroller: this.scroller, + controller: this.controller, + enableLoadMore: false, + itemLayout: () => { + this.listView() + }, + onRefresh: () => { + this.isRefreshStatus = 1; + this.getAppDetails() + } + }) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .overlay(createWaterMark()) + .backgroundColor($r('app.color.page_background')) + } + + @Builder + listView() { + List({ scroller: this.scroller, space: 10 }) { + ForEach(this.appListData, (item: AppGuideDetailsBean) => { + if (item.baseType == 0 || item.baseType == -1) { + ListItem() { + EmptyOrErrorItemView({ type: item.baseType, msg: item.remark }); + } + } else { + ListItem() { + this.itemView(item) + } + .onClick(() => { + this.openOrDownLoad(item) + }) + } + }) + } + .listDirection(Axis.Horizontal) + .scrollBar(BarState.Off) + .edgeEffect(EdgeEffect.None) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .margin({ top: $r('app.float.default_10'), bottom: $r('app.float.default_20') }) + .nestedScroll({ + scrollForward: NestedScrollMode.PARENT_FIRST, + scrollBackward: NestedScrollMode.PARENT_FIRST + }) + } + + @Builder + itemView(item: AppGuideDetailsBean) { + if (item.type == 1) { + Column() { + Image(BASE_IMAGE_URL + item.filePath) + .width($r('app.float.default_110')) + .height($r('app.float.default_180')) + + Text(item.getName()) + .textAlign(TextAlign.Center) + .fontColor($r('app.color.colorBluen7')) + .width($r('app.float.default_110')) + .fontSize($r('app.float.text_size_14')) + .margin({ top: $r('app.float.default_10') }) + + } + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .width($r('app.float.default_160')) + .margin({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .padding($r('app.float.default_10')) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + } else if (item.type == 2) { + Column() { + Video({ + src: BASE_IMAGE_URL + item.filePath, + previewUri: BASE_IMAGE_URL + item.filePath + }) + .width($r('app.float.default_110')) + .height($r('app.float.default_180')) + + Text(item.getName()) + .textAlign(TextAlign.Center) + .fontColor($r('app.color.colorBluen7')) + .fontSize($r('app.float.text_size_14')) + .width($r('app.float.default_110')) + .margin({ top: $r('app.float.default_10') }) + } + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .width($r('app.float.default_160')) + .margin({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .padding($r('app.float.default_10')) + .layoutWeight(1) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + } else { + Column() { + Image(item.getFileIcon(item.filePath)) + .width($r('app.float.default_110')) + .height($r('app.float.default_180')) + + Text(item.getName()) + .textAlign(TextAlign.Center) + .fontColor($r('app.color.colorBluen7')) + .fontSize($r('app.float.text_size_14')) + .width($r('app.float.default_110')) + .margin({ top: $r('app.float.default_10') }) + + } + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .width($r('app.float.default_160')) + .margin({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .padding($r('app.float.default_10')) + .layoutWeight(1) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + } + } + + callPhone(phone: string) { + if (!call.hasVoiceCapability()) { + console.error('设备不支持拨号功能'); + return; + } + + call.makeCall("tel:" + phone, (err: Error) => { + if (err) { + console.error(`跳转失败:${err.message}`); + } + }); + + } +} + diff --git a/entry/src/main/ets/ui/pages/ApplicationGuidePage.ets b/entry/src/main/ets/ui/pages/ApplicationGuidePage.ets new file mode 100644 index 0000000..b13f671 --- /dev/null +++ b/entry/src/main/ets/ui/pages/ApplicationGuidePage.ets @@ -0,0 +1,365 @@ +import { LitheRefresh, RefreshController } from "@abner/lithe_refresh"; +import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"; +import { AxiosError } from "@ohos/axios"; +import { ToastUtil } from "@pura/harmony-utils"; +import { BASE_IMAGE_URL } from "../../app/AppCache"; +import AppConstants from "../../app/AppConstant"; +import { RuanseeAbilityStag } from "../../app/RuanseeAbilityStag"; +import { AppDataModel } from "../../model/resultModel/ApplicationResultModel"; +import { AnHuiAddressModel } from "../../model/uiModel/AnHuiAddressModel"; +import { getAppGuideList } from "../../request/Api"; +import { cardRoundBorderGreyStyle, cardRoundBorderStyle } from "../../style/BorderStyle"; +import { StringUtils } from "../../util/StringUtils"; +import { ToastUtils } from "../../util/ToasUtils"; +import { BaseTopBar } from "../custom/BaseTopTar"; +import { EmptyOrErrorItemView } from "../custom/EmptyOrErrorItemView"; +import { createWaterMark } from "../custom/Watermark"; + +/** + * 应用指南 + */ +@Component +@HMRouter({ pageUrl: 'ApplicationGuidePage' }) +export struct ApplicationGuidePage { + @State inputContent: string | undefined = undefined + @State cityName: string = "省厅" + @State appListData: Array = [] + cityCode: string = "" + controller: RefreshController = new RefreshController() + scroller: Scroller = new Scroller() + total: number = 0; + pageNum: number = 1; + isRefreshStatus: number = 0; + @State isShowPopup: boolean = false + @State cityList: Array> = [] + + aboutToAppear(): void { + this.cityCode = RuanseeAbilityStag.userCache.getDepartmentCode + "00000000"; + this.cityName = RuanseeAbilityStag.userCache.getDepartmentName; + this.cityList = new AnHuiAddressModel().address + setTimeout(() => { + this.controller.isAutoRefresh = true; + }, 800) + } + + getAppListData() { + getAppGuideList(StringUtils.get(this.inputContent, ""), this.cityCode, this.pageNum) + .then((res) => { + console.debug("getAppGuide", JSON.stringify(res)) + if (res.code == 20041) { + let data = res.data; + if (data) { + this.total = data.counts + let items = data.items; + if (items) { + if (this.isRefreshStatus == 1) { + this.appListData = items + this.controller.finishRefresh() + this.isRefreshStatus = 0 + } + if (this.isRefreshStatus == 2) { + this.controller.finishLoadMore() + this.isRefreshStatus = 0 + items.forEach(item => { + this.appListData.push(item) + }) + } + if (this.pageNum * 20 >= this.total) { + this.controller.closeLoadMore = true; + } + } else { + this.handErrorOrEmPty(0, "暂无应用") + } + } else { + this.handErrorOrEmPty(0, "暂无应用") + } + } else { + this.handErrorOrEmPty(-1, StringUtils.get(res.msg, "")) + } + }) + .catch((error: AxiosError) => { + console.error("getAppGuide", JSON.stringify(error)) + this.handErrorOrEmPty(-1, error.message) + }) + } + + /** + * 错误或空处理 + */ + handErrorOrEmPty(type: number, msg: string) { + ToastUtils.toastBottom(msg) + if (this.isRefreshStatus == 1) { + this.controller.finishRefresh() + this.isRefreshStatus = 0 + let bean = new AppDataModel() + bean.baseType = type; + bean.remark = msg; + this.appListData = new Array(); + this.appListData.push(bean) + } + if (this.isRefreshStatus == 2) { + this.controller.finishLoadMore() + this.isRefreshStatus = 0 + } + } + + @Builder + selectCity() { + Column() { + Grid() { + ForEach(this.cityList, (item: Array) => { + GridItem() { + Column() { + Text(item[0]) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + } + .backgroundColor($r('app.color.white')) + .padding({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_5'), + bottom: $r('app.float.default_5') + }) + .height($r('app.float.default_40')) + .width(AppConstants.PERCENTAGE_MAX) + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .border(cardRoundBorderGreyStyle) + }.onClick(() => { + this.cityCode = item[1]+"00000000"; + this.cityName = item[0]; + this.isShowPopup = false; + this.controller.isAutoRefresh = true; + }) + }) + }.width('90%') + .columnsTemplate('1fr 1fr 1fr') + .columnsGap(10) + .rowsGap(10) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_350')) + .padding({ + top: $r('app.float.default_10'), + right: $r('app.float.default_10') + }) + .backgroundColor($r('app.color.page_background')) + .border({ + radius: $r('app.float.default_3'), + }) + } + + build() { + Column() { + BaseTopBar({ + title: $r('app.string.title_application_guide') + }) + + Row() { + TextInput({ text: this.inputContent, placeholder: "请输入应用名称进行搜索" }) + .placeholderColor($r('app.color.colorGrey6')) + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.colorGrey8')) + .margin({ + left: $r('app.float.default_10'), + }) + .padding({ + left: $r('app.float.default_5'), + right: $r('app.float.default_5'), + }) + .onChange((text: string) => { + this.inputContent = text; + }) + .height($r('app.float.default_40')) + .layoutWeight(1) + .textAlign(TextAlign.Start) + .border(cardRoundBorderGreyStyle) + .enterKeyType(EnterKeyType.Search)// 设置为搜索按钮 + .onSubmit((enterKey: EnterKeyType, event: SubmitEvent) => { + // 点击搜索按钮时触发 + this.controller.isAutoRefresh = true; + }); + + Row() { + Image($r('app.media.ic_filter')) + .width($r('app.float.default_14')) + .height($r('app.float.default_14')) + Text(this.cityName) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + } + .width("auto") + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Center) + .padding({ + left: $r('app.float.default_8'), + top: $r('app.float.default_3'), + right: $r('app.float.default_8'), + bottom: $r('app.float.default_3') + }) + .height($r('app.float.default_40')) + .onClick(() => { + if (this.isRefreshStatus != 0) { + return + } + this.isShowPopup = true; + }) + .bindPopup(this.isShowPopup, { + builder: () => this.selectCity(), + placement: Placement.Top, + mask: { color: 0x80000000 }, + maskColor: 0x80000000, + onStateChange: (v) => { + this.isShowPopup = v.isVisible; + }, + onWillDismiss: () => { + this.isShowPopup = false; + } + }) + + .border({ + width: $r('app.float.default_1'), + color: $r('app.color.colorGrey2'), + radius: $r('app.float.default_8') + }) + .margin({ left: $r('app.float.default_8') }) + } + .alignItems(VerticalAlign.Top) + .padding({ + left: $r('app.float.default_10'), + top: $r('app.float.default_5'), + right: $r('app.float.default_10'), + bottom: $r('app.float.default_5') + }) + .height('auto') + .backgroundColor($r('app.color.white')) + + LitheRefresh({ + scroller: this.scroller, + controller: this.controller, + itemLayout: () => { + this.listView() + }, + onRefresh: () => { + this.controller.closeLoadMore = false; + this.pageNum = 1; + this.isRefreshStatus = 1; + this.getAppListData() + }, + onLoadMore: () => { + if (this.pageNum * 20 >= this.total) { + this.controller.finishLoadMore() + this.controller.closeLoadMore = true; + ToastUtil.showToast("没有更多数据!") + return + } + this.pageNum++; + this.isRefreshStatus = 2; + this.getAppListData() + } + }) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .overlay(createWaterMark()) + .backgroundColor($r('app.color.page_background')) + + } + + @Builder + listView() { + List({ scroller: this.scroller, space: 10 }) { + ForEach(this.appListData, (item: AppDataModel) => { + if (item.baseType == 0 || item.baseType == -1) { + ListItem() { + EmptyOrErrorItemView({ type: item.baseType, msg: item.remark }); + } + } else { + ListItem() { + this.itemView(item) + } + .onClick(() => { + HMRouterMgr.push({pageUrl:"ApplicationDetailsPage",param:item}) + }) + } + }) + } + .listDirection(Axis.Vertical) + .scrollBar(BarState.Off) + .edgeEffect(EdgeEffect.None) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .nestedScroll({ + scrollForward: NestedScrollMode.PARENT_FIRST, + scrollBackward: NestedScrollMode.PARENT_FIRST + }) + } + + @Builder + itemView(item: AppDataModel) { + Column() { + Column() { + Row() { + Image(BASE_IMAGE_URL + item.icon) + .width($r('app.float.default_46')) + .height($r('app.float.default_46')) + + Column() { + Text(item.name) + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.colorGrey8')) + .maxLines(1) + .ellipsisMode(EllipsisMode.END) + + Text(item.serviceProvider) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey6')) + .margin({ top: $r('app.float.default_5') }) + .maxLines(1) + .ellipsisMode(EllipsisMode.END) + } + .alignItems(HorizontalAlign.Start) + .justifyContent(FlexAlign.Center) + .layoutWeight(1) + .margin({ left: $r('app.float.default_8') }) + .height($r('app.float.default_60')) + + } + .width(AppConstants.PERCENTAGE_MAX) + + Row() { + Text("查看指南") + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey7')) + .layoutWeight(1) + .ellipsisMode(EllipsisMode.END) + + Image($r('app.media.ic_look')) + .width($r('app.float.default_26')) + .height($r('app.float.default_26')) + } + .width(AppConstants.PERCENTAGE_MAX) + .backgroundColor("#F8F9FC") + .height($r('app.float.default_45')) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .margin({ top: $r('app.float.default_10') }) + .border(cardRoundBorderStyle) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height("auto") + .padding($r('app.float.default_10')) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderGreyStyle) + + } + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .height("auto") + .width(AppConstants.PERCENTAGE_MAX) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/ApplicationWorkbenchPage.ets b/entry/src/main/ets/ui/pages/ApplicationWorkbenchPage.ets new file mode 100644 index 0000000..5f85836 --- /dev/null +++ b/entry/src/main/ets/ui/pages/ApplicationWorkbenchPage.ets @@ -0,0 +1,375 @@ +import { LitheRefresh, RefreshController } from "@abner/lithe_refresh"; +import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"; +import { AxiosError } from "@ohos/axios"; +import { ToastUtil } from "@pura/harmony-utils"; +import { BASE_IMAGE_URL } from "../../app/AppCache"; +import AppConstants from "../../app/AppConstant"; +import { RuanseeAbilityStag } from "../../app/RuanseeAbilityStag"; +import { AppDataModel, ApplicationModel } from "../../model/resultModel/ApplicationResultModel"; +import { BaseResultModel, PagingModel } from "../../model/resultModel/BaseResultModel"; +import { AnHuiAddressModel } from "../../model/uiModel/AnHuiAddressModel"; +import { H5OperationType, WebAppPageParam } from "../../model/uiModel/WebAppPageParam"; +import { applicationPage } from "../../request/Api"; +import { cardRoundBorderGreyStyle, cardRoundBorderStyle } from "../../style/BorderStyle"; +import { StringUtils } from "../../util/StringUtils"; +import { ToastUtils } from "../../util/ToasUtils"; +import { EmptyOrErrorItemView } from "../custom/EmptyOrErrorItemView"; +import { createWaterMark } from "../custom/Watermark"; + +/** + * 应用工作台页面 + */ +@Component +@HMRouter({ pageUrl: 'ApplicationWorkbenchPage' }) +export struct ApplicationWorkbenchPage { + @State selectValue: Array = new Array(); + @State inputAppName: string = ""; + @State leftImage: Resource = $r('app.media.icon_back3') + cityCode: string = "" + @State cityName: string = "省厅" + @State isShowPopup: boolean = false + @State cityList: Array> = [] + controller: RefreshController = new RefreshController() + scroller: Scroller = new Scroller() + total: number = 0; + pageNum: number = 1; + isRefreshStatus: number = 0; + @State gridColumns: string = '1fr 1fr 1fr 1fr' + + aboutToAppear(): void { + this.cityCode = RuanseeAbilityStag.userCache.getDepartmentCode + "00000000"; + this.cityName = RuanseeAbilityStag.userCache.getDepartmentName; + this.cityList = new AnHuiAddressModel().address + setTimeout(() => { + this.controller.autoRefresh(true) + }, 500) + } + + getAppListData() { + applicationPage(this.cityCode, this.pageNum, 50, this.inputAppName) + .then((res) => { + console.debug("获取应用列表成功", JSON.stringify(res)) + if (res.code == 20041) { + let data = res.data; + if (data) { + this.total = data.counts + let list = data.items; + if (list) { + if (this.isRefreshStatus == 1) { + this.gridColumns = '1fr 1fr 1fr 1fr' + this.isRefreshStatus = 0 + this.controller.finishRefresh() + this.selectValue = new Array(); + list.forEach((item) => { + this.selectValue.push(item) + }) + } + if (this.isRefreshStatus == 2) { + this.isRefreshStatus = 0 + this.controller.finishLoadMore() + list.forEach((item) => { + this.selectValue.push(item) + }) + } + } else { + this.handErrorOrEmPty(0, "暂无数据") + } + } else { + this.handErrorOrEmPty(0, "暂无数据") + } + } else { + this.handErrorOrEmPty(-1, StringUtils.get(res.msg, "")) + } + }) + .catch((err: AxiosError) => { + console.debug("获取应用列表成功", JSON.stringify(err)) + this.handErrorOrEmPty(-1, err.message) + }) + } + + /** + * 错误或空处理 + */ + handErrorOrEmPty(type: number, msg: string) { + ToastUtils.toastBottom(msg) + if (this.isRefreshStatus == 1) { + this.gridColumns = '1fr' + this.controller.finishRefresh() + this.isRefreshStatus = 0 + let bean = new AppDataModel() + bean.baseType = type; + bean.remark = msg; + this.selectValue = new Array(); + this.selectValue.push(bean) + } + if (this.isRefreshStatus == 2) { + this.controller.finishLoadMore() + this.isRefreshStatus = 0 + } + } + + @Builder + selectCity() { + Column() { + Grid() { + ForEach(this.cityList, (item: Array) => { + GridItem() { + Column() { + Text(item[0]) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + } + .backgroundColor($r('app.color.white')) + .padding({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_5'), + bottom: $r('app.float.default_5') + }) + .height($r('app.float.default_40')) + .width(AppConstants.PERCENTAGE_MAX) + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .border(cardRoundBorderGreyStyle) + }.onClick(() => { + this.cityCode = item[1] + "00000000"; + this.cityName = item[0]; + this.isShowPopup = false; + this.controller.autoRefresh(true) + }) + }) + }.width('90%') + .columnsTemplate('1fr 1fr 1fr') + .columnsGap(10) + .rowsGap(10) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_350')) + .padding({ + top: $r('app.float.default_10'), + right: $r('app.float.default_10') + }) + .backgroundColor($r('app.color.page_background')) + .border({ + radius: $r('app.float.default_3'), + }) + } + + @Builder + listView() { + Grid(this.scroller) { + ForEach(this.selectValue, (item: AppDataModel, index) => { + if (item.baseType == 0 || item.baseType == -1) { + GridItem() { + EmptyOrErrorItemView({ type: item.baseType, msg: item.remark }) + } + } else { + GridItem() { + Column() { + Image(item.baseType == 99 ? item.locationIcon : BASE_IMAGE_URL + item.icon) + .size({ + width: $r('app.float.default_36'), + height: $r('app.float.default_36') + }) + .margin({ top: $r('app.float.default_8') }); + Text(item.name) + .fontSize($r('app.float.text_size_14')) + .fontColor($r('app.color.colorGrey8')) + .textAlign(TextAlign.Center) + .margin({ top: $r('app.float.default_8') }); + } + .alignItems(HorizontalAlign.Center); + } + .onClick(() => { + if (item.baseType == 99) { + HMRouterMgr.push({pageUrl:'ApplicationWorkbenchPage'}) + return + } + if (item.baseType == 91) { + HMRouterMgr.push({pageUrl:'ApplicationGuidePage'}) + return + } + if (item.baseType == 92) { + HMRouterMgr.push({pageUrl:'FrequentlyQuestionsPage'}) + return + } + if (item.baseType == 93) { + HMRouterMgr.push({pageUrl:'OpinionsSuggestionsPages'}) + return + } + let pageParam :WebAppPageParam= { + appName: item.name, + appId: item.clientId, + secret: item.clientSecret, + linkUrl: item.link, + operationType:H5OperationType.login, + } + HMRouterMgr.push({pageUrl:'WebAppPages',param: pageParam}) + }) + } + }); + } + .columnsTemplate(this.gridColumns) //一行有4列,等分 + .columnsGap($r('app.float.default_10')) //行间距 + .rowsGap($r('app.float.default_10')) //列间距 + .scrollBar(BarState.Off) + .edgeEffect(EdgeEffect.None) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .padding({ left: 20, right: 20 }) + .nestedScroll({ + scrollForward: NestedScrollMode.PARENT_FIRST, + scrollBackward: NestedScrollMode.PARENT_FIRST + }) + + } + + build() { + Column() { + Blank() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_30')) + .backgroundColor($r('app.color.bull')) + this.topBar() + + Column(){ + + LitheRefresh({ + scroller: this.scroller, + controller: this.controller, + itemLayout: () => { + this.listView() + }, + onRefresh: () => { + this.controller.closeLoadMore = false; + this.pageNum = 1; + this.isRefreshStatus = 1; + this.getAppListData() + }, + onLoadMore: () => { + if (this.pageNum * 20 >= this.total) { + this.controller.finishLoadMore() + this.controller.closeLoadMore = true; + ToastUtil.showToast("没有更多数据!") + return + } + this.pageNum++; + this.isRefreshStatus = 2; + this.getAppListData() + } + }) + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .width(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + } + .padding($r('app.float.default_10')) + .layoutWeight(1) + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.page_background')) + .overlay(createWaterMark()) + } + + @Builder + topBar() { + Row() { + Row() { + Image(this.leftImage) + .width($r('app.float.default_24')) + .height($r('app.float.default_24')) + } + .height("100%") + .width('auto') + .alignItems(VerticalAlign.Center) + .padding({ left: $r('app.float.default_10') }) + .onTouch((event) => { + if (event.type === TouchType.Down) { + this.leftImage = $r('app.media.icon_back2'); + } else if (event.type === TouchType.Up) { + this.leftImage = $r('app.media.icon_back3'); + } + }) + .onClick(() => { + HMRouterMgr.pop() + }) + + Row() { + Image($r('app.media.icon_search')) + .width($r('app.float.default_18')) + .height($r('app.float.default_18')) + + TextInput({ text: this.inputAppName, placeholder: '请输入应用名称' }) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + .height($r('app.float.default_38')) + .backgroundColor(Color.Transparent) + .cancelButton({ + style: CancelButtonStyle.INPUT, // 设置清除按钮样式为图标 + icon: { + src: $r('app.media.icon_clean'), // 自定义图标资源路径 + size: $r('app.float.default_18') // 图标尺寸(单位vp,若省略则默认24vp) + } + }) + .layoutWeight(1) + .textAlign(TextAlign.Start) + .onChange((value: string) => { + this.inputAppName = value; + }) + .enterKeyType(EnterKeyType.Search)// 设置为搜索按钮 + .onSubmit((enterKey: EnterKeyType, event: SubmitEvent) => { + // 点击搜索按钮时触发 + this.controller.autoRefresh(true) + }); + } + .alignItems(VerticalAlign.Center) + .layoutWeight(1) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .height($r('app.float.default_38')) + .margin({ left: $r('app.float.default_5') }) + .backgroundColor($r('app.color.white')) + .border({ + width: $r('app.float.default_1'), + color: $r('app.color.white'), + radius: $r('app.float.default_8') + }) + + Row() { + Image($r('app.media.ic_dropup')) + .width($r('app.float.default_24')) + .height($r('app.float.default_24')) + + Text(this.cityName) + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_16')) + } + .alignItems(VerticalAlign.Center) + .height("100%") + .margin({ left: $r('app.float.default_5') }) + .width('auto') + .padding({ right: $r('app.float.default_10') }) + .bindPopup(this.isShowPopup, { + builder: () => this.selectCity(), + placement: Placement.Top, + mask: { color: 0x80000000 }, + maskColor: 0x80000000, + onStateChange: (v) => { + this.isShowPopup = v.isVisible; + }, + onWillDismiss: () => { + this.isShowPopup = false; + } + }) + .onClick(() => { + this.isShowPopup = true + }) + } + .alignItems(VerticalAlign.Center) + .width('100%') + .backgroundColor($r('app.color.bull')) + .height($r('app.float.default_58')) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/FeedBackDetailsPage.ets b/entry/src/main/ets/ui/pages/FeedBackDetailsPage.ets new file mode 100644 index 0000000..153a410 --- /dev/null +++ b/entry/src/main/ets/ui/pages/FeedBackDetailsPage.ets @@ -0,0 +1,233 @@ +import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"; +import { FeedBackBean } from "../../model/requestModel/MessageRequestModel"; +import { BaseTopBar } from "../custom/BaseTopTar"; +import AppConstants from "../../app/AppConstant"; +import { createWaterMark } from "../custom/Watermark"; +import { StringUtils } from "../../util/StringUtils"; +import { cardRoundBorderStyle } from "../../style/BorderStyle"; +import { ToastUtil } from "@pura/harmony-utils/src/main/ets/action/ToastUtil"; +import { plainToInstance } from "class-transformer"; +import { webview } from "@kit.ArkWeb"; +import { StrUtil } from "@pura/harmony-utils/src/main/ets/utils/StrUtil"; + +/** + * 反馈详情 + */ +@HMRouter({ pageUrl: 'FeedBackDetailsPage' }) +@Component +export struct FeedBackDetailsPage { + @State param: FeedBackBean | undefined = undefined; + + webController: webview.WebviewController = new webview.WebviewController(); + aboutToAppear(): void { + let param = HMRouterMgr.getCurrentParam() as FeedBackBean; + if (!param) { + ToastUtil.showToast("参数错误") + HMRouterMgr.pop() + return + } + this.param = plainToInstance(FeedBackBean,param) + // if (StrUtil.isNotEmpty(this.param?.replyContent)){ + // setTimeout(() => { + // + // },800) + // } + + } + + build() { + Column() { + BaseTopBar({ + title: $r('app.string.title_feedback_details'), + }) + + Text(StringUtils.get(this.param?.title, "")) + .constraintSize({ + minHeight: $r('app.float.default_40'), + }) + .width(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.white')) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + .textAlign(TextAlign.Center) + .padding({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_8'), + bottom: $r('app.float.default_8'), + }) + + Scroll(){ + Column() { + Row() { + Text(this.getTypeStr(StringUtils.getNumber(this.param?.type, 0))) + .fontColor($r('app.color.colorYellow7')) + .fontSize($r('app.float.text_size_10')) + .padding({ + left: $r('app.float.default_5'), + right: $r('app.float.default_5'), + top: $r('app.float.default_2'), + bottom: $r('app.float.default_2') + }) + .border({ + width: $r('app.float.default_1'), + color: $r('app.color.colorYellow7'), + radius: $r('app.float.default_8') + }) + Text(StringUtils.get(this.param!.applicationName,"")) + .fontColor($r('app.color.colorBluen7')) + .fontSize($r('app.float.text_size_10')) + .padding({ + left: $r('app.float.default_5'), + right: $r('app.float.default_5'), + top: $r('app.float.default_2'), + bottom: $r('app.float.default_2') + }) + .border({ + width: $r('app.float.default_1'), + color: $r('app.color.colorBluen7'), + radius: $r('app.float.default_8') + }) + .margin({ left: $r('app.float.default_8') }) + .visibility(StringUtils.isNullOrEmpty(this.param!.applicationName) ? Visibility.None : Visibility.Visible) + + Text(this.getReplyStatusStr(this.param!.replyStatus)) + .fontColor(this.param!.replyStatus == 0 ? $r('app.color.colorGrey6') : $r('app.color.colorGreen6')) + .fontSize($r('app.float.text_size_10')) + .padding({ + left: $r('app.float.default_5'), + right: $r('app.float.default_5'), + top: $r('app.float.default_2'), + bottom: $r('app.float.default_2') + }) + .border({ + width: $r('app.float.default_1'), + color: this.param!.replyStatus == 0 ? $r('app.color.colorGrey6') : $r('app.color.colorGreen6'), + radius: $r('app.float.default_8') + }) + .margin({ left: $r('app.float.default_8') }) + } + .width(AppConstants.PERCENTAGE_MAX) + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Start) + .margin({ top: $r('app.float.default_5') }) + + Text(this.param!.createTime) + .fontColor($r('app.color.colorGrey6')) + .fontSize($r('app.float.text_size_12')) + .width(AppConstants.PERCENTAGE_MAX) + .textAlign(TextAlign.End) + .margin({ top: $r('app.float.default_8') }) + + + Column(){ + + Text("意见建议") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + .textAlign(TextAlign.Start) + .height($r('app.float.default_36')) + + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey2')) + + Text(this.param!.content) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + .textAlign(TextAlign.Start) + .margin({ top: $r('app.float.default_10') }) + } + .backgroundColor($r('app.color.white')) + .alignItems(HorizontalAlign.Start) + .border(cardRoundBorderStyle) + .width(AppConstants.PERCENTAGE_MAX) + .height('auto') + .padding($r('app.float.default_10')) + .margin({ top: $r('app.float.default_10') }) + + Column(){ + Text(StringUtils.get(this.param!.replier,"暂无")) + .fontColor($r('app.color.colorBluen6')) + .fontSize($r('app.float.text_size_16')) + .textAlign(TextAlign.Start) + .height($r('app.float.default_36')) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey2')) + + + Web({src:"",controller: this.webController}) + .width(AppConstants.PERCENTAGE_MAX) + .height("auto") + .zoomAccess(true) + + .onAppear(() =>{ + let data = this.param?.getReplyContent(); + // 在组件引用上使用loadData方法 + this.webController.loadData(data, "text/html", "UTF-8") + }) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .margin({ top: $r('app.float.default_8') }) + .backgroundColor($r('app.color.colorGrey2')) + + Text(this.param!.updateTime) + .fontColor($r('app.color.colorGrey6')) + .fontSize($r('app.float.text_size_12')) + .width(AppConstants.PERCENTAGE_MAX) + .textAlign(TextAlign.End) + .margin({ top: $r('app.float.default_8') }) + + } + .visibility(this.param!.replyStatus == 1? Visibility.Visible : Visibility.None) + .backgroundColor($r('app.color.white')) + .alignItems(HorizontalAlign.Start) + .border(cardRoundBorderStyle) + .width(AppConstants.PERCENTAGE_MAX) + .height('auto') + .padding($r('app.float.default_10')) + .margin({ top: $r('app.float.default_10') }) + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .padding({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + }) + } + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.page_background')) + .overlay(createWaterMark()) + + } + + getTypeStr(type: number): string { + switch (type) { + case 1: + return "个人建议"; + case 2: + return "软件问题"; + case 3: + return "硬件问题"; + case 4: + default: + return "其它"; + } + } + + getReplyStatusStr(replyStatus: number): string { + return replyStatus == 0 ? "未回复" : "已回复"; + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/FrequentlyQuestionsPage.ets b/entry/src/main/ets/ui/pages/FrequentlyQuestionsPage.ets new file mode 100644 index 0000000..0baff19 --- /dev/null +++ b/entry/src/main/ets/ui/pages/FrequentlyQuestionsPage.ets @@ -0,0 +1,351 @@ +import { LitheRefresh, RefreshController } from "@abner/lithe_refresh"; +import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"; +import { AxiosError } from "@ohos/axios"; +import { ObjectUtil, ToastUtil } from "@pura/harmony-utils"; +import { BASE_IMAGE_URL } from "../../app/AppCache"; +import AppConstants from "../../app/AppConstant"; +import { QuestionBean, QuestionModel } from "../../model/resultModel/QuestionModel"; +import { BasePageResult } from "../../model/uiModel/PageResultModel"; +import { getQuestion } from "../../request/Api"; +import { StringUtils } from "../../util/StringUtils"; +import { BaseTopBar } from "../custom/BaseTopTar"; +import { EmptyOrErrorItemView } from "../custom/EmptyOrErrorItemView"; +import { createWaterMark } from "../custom/Watermark"; +/** + * 常见问题 + */ +@Component +@HMRouter({ pageUrl: 'FrequentlyQuestionsPage' }) +export struct FrequentlyQuestionsPage { + @State dataList: Array = [] + controller: RefreshController = new RefreshController() + scroller: Scroller = new Scroller() + isRefreshStatus: number = 0; + @State isShowBottomSheet:Array< boolean> = []; + + aboutToAppear(): void { + setTimeout(() => { + this.controller.autoRefresh(true) + }, 500) + } + + getDataList() { + getQuestion() + .then((res) => { + this.controller.finishRefresh() + this.isRefreshStatus = 0; + if (res.code == 20041) { + let data = res.data; + if (data) { + // let beanJG = new QuestionBean() + // beanJG.baseType = 4; + this.dataList = new Array() + this.isShowBottomSheet = new Array(); + data.forEach((item: QuestionModel) => { + let bean = new QuestionBean() + bean.baseType = 1; + bean.problem = item.title + this.dataList.push(bean) + this.isShowBottomSheet.push(false) + let beans = item.data; + if (beans) { + beans.forEach((item: QuestionBean) => { + let bean = ObjectUtil.objToClass(QuestionBean, item) + // let bean = plainToInstance(QuestionBean, item); + this.isShowBottomSheet.push(false) + bean.baseType = 2; + this.dataList.push(bean) + }) + this.dataList[this.dataList.length-1].baseType = 3 + } + }) + if (this.dataList.length < 1) { + this.handErrorOrEmPty(0, "暂无常见问题!") + } + } else { + this.handErrorOrEmPty(0, "暂无常见问题!") + } + } else { + this.handErrorOrEmPty(-1, StringUtils.get(res.msg, res.code + "")) + } + }) + .catch((err: AxiosError) => { + this.handErrorOrEmPty(-1, StringUtils.get(err.message, "")) + }) + } + + /** + * 错误或空处理 + */ + handErrorOrEmPty(type: number, msg: string) { + ToastUtil.showToast(msg) + if (this.isRefreshStatus == 1) { + this.isRefreshStatus = 0 + this.controller.finishRefresh() + this.dataList = new Array(); + let bean = new QuestionBean() + bean.baseType = type; + bean.problem = msg; + this.dataList.push(bean) + } + } + + @Builder + bottomSheet(item: QuestionBean) { + Column() { + Text($r('app.string.title_frequently_questions')) + .fontColor($r('app.color.bull')) + .fontSize($r('app.float.text_size_16')) + .width(AppConstants.PERCENTAGE_MAX) + .fontWeight(FontWeight.Bold) + .height($r('app.float.default_48')) + .textAlign(TextAlign.Center) + .align(Alignment.Center) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey1')) + + Scroll(){ + Column() { + Text(item.problem) + .fontColor($r('app.color.colorBluen7')) + .fontSize($r('app.float.text_size_16')) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_38')) + .textAlign(TextAlign.Start) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .backgroundColor($r('app.color.white')) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey1')) + + Text(StringUtils.get("\t\t"+item.reply.replace("\\n","\n").replace("\\t","\t"),"暂无")) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + .width(AppConstants.PERCENTAGE_MAX) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .height("auto") + .margin({top: $r('app.float.default_10'),bottom: $r('app.float.default_10')}) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey1')) + + Text(item.extend) + .fontColor($r('app.color.colorGrey6')) + .fontSize($r('app.float.text_size_12')) + .width(AppConstants.PERCENTAGE_MAX) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .visibility(StringUtils.isNullOrEmpty(item.guidance)?Visibility.None:Visibility.Visible) + .textAlign(TextAlign.Start) + .margin({top: $r('app.float.default_10'),bottom: $r('app.float.default_10')}) + + Image(BASE_IMAGE_URL+item.guidance) + .width(AppConstants.PERCENTAGE_MAX) + .visibility(StringUtils.isNullOrEmpty(item.guidance)?Visibility.None:Visibility.Visible) + .height($r('app.float.default_240')) + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .padding({bottom: $r('app.float.default_10')}) + + } + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.white')) + .border({ + radius: { + topLeft: $r('app.float.default_10'), + topRight: $r('app.float.default_10') + } + }) + } + + build() { + Column() { + BaseTopBar({ + title: $r('app.string.title_frequently_questions'), + }) + + LitheRefresh({ + scroller: this.scroller, + controller: this.controller, + enableLoadMore: false, + itemLayout: () => { + this.listView() + }, + onRefresh: () => { + this.controller.closeLoadMore = false; + this.isRefreshStatus = 1; + this.getDataList() + } + }) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .overlay(createWaterMark()) + .backgroundColor($r('app.color.page_background')) + } + + @Builder + listView() { + List({ scroller: this.scroller }) { + ForEach(this.dataList, (item: QuestionBean,index:number) => { + + if (item.baseType == 0 || item.baseType == -1) { + ListItem() { + EmptyOrErrorItemView({ type: item.baseType, msg: item.problem }) + } + } else if (item.baseType == 1) { + ListItem() { + this.itemViewTop(item) + } + } else if (item.baseType == 2) { + ListItem() { + this.itemViewCenter(item) + } + .bindSheet(this.isShowBottomSheet[index], this.bottomSheet(item), { + height:'66.6%', + dragBar: true, + // detents:[$r('app.float.default_3')], + preferType: SheetType.BOTTOM, + showClose:false, + shouldDismiss: () => { + this.isShowBottomSheet[index] = false; + } + }) + .onClick(() => { + this.isShowBottomSheet[index] = true; + }) + } else if (item.baseType == 3) { + ListItem() { + this.itemViewBottom(item) + } + .bindSheet(this.isShowBottomSheet[index], this.bottomSheet(item), { + height:'66.6%', + dragBar: true, + showClose:false, + preferType: SheetType.BOTTOM, + shouldDismiss: () => { + this.isShowBottomSheet[index] = false; + } + }) + .onClick(() => { + this.isShowBottomSheet[index] = true; + }) + } + }) + } + .listDirection(Axis.Vertical) + .scrollBar(BarState.Off) + .edgeEffect(EdgeEffect.None) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .nestedScroll({ + scrollForward: NestedScrollMode.PARENT_FIRST, + scrollBackward: NestedScrollMode.PARENT_FIRST + }) + } + + @Builder + itemViewTop(item: QuestionBean) { + Row() { + Text(item.problem) + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_14')) + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .textAlign(TextAlign.Start) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .backgroundColor($r('app.color.bull')) + .border({ + radius: { + topLeft: $r('app.float.default_5'), + topRight: $r('app.float.default_5') + } + }) + .align(Alignment.Center) + } + .padding({ top: $r('app.float.default_10'), left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_46')) + } + + @Builder + itemViewCenter(item: QuestionBean) { + Column() { + Row() { + Text(item.problem) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + .height(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .textAlign(TextAlign.Start) + .align(Alignment.Center) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_20')) + .height($r('app.float.default_20')) + .margin({ left: $r('app.float.default_10') }) + } + .alignItems(VerticalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_46')) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .backgroundColor($r('app.color.white')) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey2')) + } + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_47')) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + } + + @Builder + itemViewBottom(item: QuestionBean) { + Row() { + Row() { + Text(item.problem) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + .height(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .textAlign(TextAlign.Start) + .align(Alignment.Center) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_20')) + .height($r('app.float.default_20')) + .margin({ left: $r('app.float.default_10') }) + } + .alignItems(VerticalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .backgroundColor($r('app.color.white')) + .border({ + radius: { + bottomLeft: $r('app.float.default_5'), + bottomRight: $r('app.float.default_5') + } + }) + } + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_46')) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/Index.ets b/entry/src/main/ets/ui/pages/Index.ets new file mode 100644 index 0000000..5105d98 --- /dev/null +++ b/entry/src/main/ets/ui/pages/Index.ets @@ -0,0 +1,66 @@ +import { AttributeUpdater } from '@kit.ArkUI'; +import { HMDefaultGlobalAnimator, HMNavigation } from '@hadss/hmrouter'; + +@Entry +@Component +struct Index { + modifier: IndexNavModifier = new IndexNavModifier(); + + onPageShow(): void { + + } + + onPageHide(): void { + + } + + getToken() { + // getPgToken() + // .then((res) => { + // if (res) { + // AppCache.getAppCache().setPgToken = res.access_token; + // } + // console.info(JSON.stringify(res)); + // }) + // .catch((error: AxiosError) => { + // console.error(JSON.stringify(error)); + // }) + } + + aboutToAppear() { + // this.getIpAddress(); + // this.getToken() + + } + + build() { + Column() { + HMNavigation({ + navigationId: 'startNavigation', homePageUrl: 'StartPage', + options: { + standardAnimator: HMDefaultGlobalAnimator.STANDARD_ANIMATOR, + dialogAnimator: HMDefaultGlobalAnimator.DIALOG_ANIMATOR, + modifier: this.modifier + } + }) { + } + } + .width('100%') + .height('100%') + .expandSafeArea([SafeAreaType.SYSTEM]) + } + + exitApp() { + // this.context.terminateSelf(); + // let preferences = data_preferences.getPreferences(this.context, H_STORE); + // preferences.then((res) => { + // // res.clearSync(); + // }) + } +} + +class IndexNavModifier extends AttributeUpdater { + initializeModifier(instance: NavigationAttribute): void { + instance.hideNavBar(true); + } +} diff --git a/entry/src/main/ets/ui/pages/MainPage.ets b/entry/src/main/ets/ui/pages/MainPage.ets new file mode 100644 index 0000000..ed2088a --- /dev/null +++ b/entry/src/main/ets/ui/pages/MainPage.ets @@ -0,0 +1,134 @@ +import { HMRouter } from '@hadss/hmrouter'; +import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit'; +import AppConstants from '../../app/AppConstant'; +import { FileUtils } from '../../util/FileUtils'; +import { createWaterMark } from '../custom/Watermark'; +import { HomeFragment } from '../fragment/HomeFragment'; +import { MyFragment } from '../fragment/MyFragment'; +import { PendingMessagePage } from '../fragment/PendingMessagePage'; +import { WorkbenchFragment } from '../fragment/WorkbenchFragment'; + +@HMRouter({ pageUrl: 'MainPage' }) +@Component +export struct MainPage { + context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; + @State currentIndex: number = 0 + private tabsController: TabsController = new TabsController() + // 记录上一次点击时间 + private pretime: number = -1; + + aboutToAppear(): void { + this.applyForPermission() + } + + /** + * 申请权限 + */ + applyForPermission() { + let permissions = new Array(); + permissions.push('ohos.permission.LOCATION') + permissions.push('ohos.permission.APPROXIMATELY_LOCATION') + permissions.push('ohos.permission.CAMERA') + this.checkPermissionGrant(permissions) + } + + /** + * 检测权限 + * @param permissionArray + */ + checkPermissionGrant(permissionArray: Array) { + let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager() + // 获取应用程序的accessTokenID + let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION) + let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo + let tokenId: number = appInfo.accessTokenId + let wsqPermissionArray = new Array() + for (let i = 0; i < permissionArray.length; i++) { + let grantStatus = atManager.checkAccessTokenSync(tokenId, permissionArray[i]) + if (grantStatus == abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) { + wsqPermissionArray.push(permissionArray[i]) + } + } + if (wsqPermissionArray.length > 0) { + //有未申请的权限,发送到Ability,由 Ability 发起权限申请 + // this.requestPermissionsFromUser(wsqPermissionArray) + this.context.eventHub.emit('ui_event', wsqPermissionArray); + } else { + //权限全部申请 + this.initPage() + // this.getCurrentLocation() + } + } + + initPage() { + FileUtils.createFileDir() + + } + + build() { + Column() { + Tabs({ + barPosition: BarPosition.End, + controller: this.tabsController + }) { + TabContent(){ + HomeFragment({ + allMessage:()=>{ + this.tabsController.changeIndex(1) + this.currentIndex =1 + } + }) + } + .tabBar(this.TabBuilder('首页', 0, $r('app.media.icon_main_home'), $r('app.media.icon_main_home_def'))) + + TabContent(){ + PendingMessagePage() + }.tabBar(this.TabBuilder('待办', 1, $r('app.media.icon_main_message'), $r('app.media.icon_main_message_def'))) + + TabContent(){ + WorkbenchFragment() + }.tabBar(this.TabBuilder('工作台', 2, $r('app.media.icon_main_work'), $r('app.media.icon_main_work_def'))) + + TabContent(){ + MyFragment() + }.tabBar(this.TabBuilder('我的', 3, $r('app.media.icon_main_my'), $r('app.media.icon_main_my_def'))) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .scrollable(false) + .barMode(BarMode.Fixed) + .barWidth('100%') + .barHeight('8.7%') + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.page_background')) + .overlay(createWaterMark()) + } + + // 自定义导航页签的样式 + @Builder + TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) { + Column() { + Image(this.currentIndex === targetIndex ? selectedImg : normalImg) + .size({ width: $r('app.float.default_24'), height: $r('app.float.default_24') }) + .margin({top: $r('app.float.default_10')}) + Text(title) + .fontColor(this.currentIndex === targetIndex ? $r('app.color.bull') : '#8a8a8a') + .fontSize($r('app.float.text_size_12')) + .margin({top: $r('app.float.default_5')}) + } + .width('100%') + .height('100%') + .backgroundColor($r('app.color.white')) + .justifyContent(FlexAlign.Start) + .alignItems(HorizontalAlign.Center) + .padding({bottom: $r('app.float.default_28')}) + .onClick(() => { + this.currentIndex = targetIndex + this.tabsController.changeIndex(this.currentIndex) + }) + } + +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/MessageDetailsPage.ets b/entry/src/main/ets/ui/pages/MessageDetailsPage.ets new file mode 100644 index 0000000..03e7545 --- /dev/null +++ b/entry/src/main/ets/ui/pages/MessageDetailsPage.ets @@ -0,0 +1,99 @@ +import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"; +import { ToastUtil } from "@pura/harmony-utils/src/main/ets/action/ToastUtil"; +import { BASE_IMAGE_URL } from "../../app/AppCache"; +import AppConstants from "../../app/AppConstant"; +import { MainMessageBean } from "../../model/resultModel/MessageResultModel"; +import { cardRoundBorderStyle } from "../../style/BorderStyle"; +import { StringUtils } from "../../util/StringUtils"; +import { BaseTopBar } from "../custom/BaseTopTar"; +import { createWaterMark } from "../custom/Watermark"; + +@Component +@HMRouter({ pageUrl: 'MessageDetailsPage' }) +export struct MessageDetailsPage { + @State param: MainMessageBean | undefined = undefined + + aboutToAppear(): void { + this.param = HMRouterMgr.getCurrentParam() as MainMessageBean; + if (!this.param) { + ToastUtil.showToast('参数错误!') + HMRouterMgr.pop() + return + } + } + + build() { + Column() { + BaseTopBar({ + title: $r('app.string.title_msg_details') + }) + + Scroll() { + Column() { + Text(this.param!.msgTitle) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_18')) + .textAlign(TextAlign.Start) + .align(Alignment.Center) + .fontWeight(FontWeight.Bold) + .width(AppConstants.PERCENTAGE_MAX) + .height('auto') + + Row() { + Image(BASE_IMAGE_URL + this.param!.appIcon) + .width($r('app.float.default_24')) + .height($r('app.float.default_24')) + + Text(this.param!.appName) + .fontColor($r('app.color.colorBluen7')) + .fontSize($r('app.float.text_size_16')) + .textAlign(TextAlign.Start) + .fontWeight(FontWeight.Bold) + .width(AppConstants.PERCENTAGE_MAX) + .height('auto') + .margin({ left: $r('app.float.default_5') }) + } + .width(AppConstants.PERCENTAGE_MAX) + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Start) + .margin({ top: $r('app.float.default_10'), bottom: $r('app.float.default_10') }) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey1')) + + Text("\t\t"+StringUtils.get(this.param!.msgContent, '暂无内容')) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + .textAlign(TextAlign.Start) + .align(Alignment.TopStart) + .fontWeight(FontWeight.Normal) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .margin({ top: $r('app.float.default_10'),bottom: $r('app.float.default_10') }) + + Text(this.param!.sendingTime) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + .textAlign(TextAlign.End) + .width(AppConstants.PERCENTAGE_MAX) + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.white')) + .padding($r('app.float.default_10')) + .border(cardRoundBorderStyle) + } + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .padding($r('app.float.default_15')) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.page_background')) + .overlay(createWaterMark()) + + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/MyFeedBackPage.ets b/entry/src/main/ets/ui/pages/MyFeedBackPage.ets new file mode 100644 index 0000000..ead65c5 --- /dev/null +++ b/entry/src/main/ets/ui/pages/MyFeedBackPage.ets @@ -0,0 +1,274 @@ +import { LitheRefresh, RefreshController } from '@abner/lithe_refresh'; +import { HMRouter, HMRouterMgr } from '@hadss/hmrouter'; +import { AxiosError } from '@ohos/axios'; +import { ToastUtil } from '@pura/harmony-utils'; +import { plainToInstance } from 'class-transformer'; +import AppConstants from '../../app/AppConstant'; +import { FeedBackBean } from '../../model/requestModel/MessageRequestModel'; +import { getMyFeedBackList } from '../../request/Api'; +import { cardRoundBorderStyle } from '../../style/BorderStyle'; +import { StringUtils } from '../../util/StringUtils'; +import { ToastUtils } from '../../util/ToasUtils'; +import { BaseTopBar } from '../custom/BaseTopTar'; +import { EmptyOrErrorItemView } from '../custom/EmptyOrErrorItemView'; +import { createWaterMark } from '../custom/Watermark'; + +@Component +@Preview +@HMRouter({ pageUrl: 'MyFeedBackPage' }) +export struct MyFeedBackPage { + @State feedBackList: Array = new Array(); + controller: RefreshController = new RefreshController() + scroller: Scroller = new Scroller() + total: number = 0; + pageNum: number = 1; + isRefreshStatus: number = 0; + + aboutToAppear(): void { + setTimeout(() => { + this.controller.isAutoRefresh = true + }, 800) + } + + getData() { + getMyFeedBackList(this.pageNum) + .then((res) => { + console.debug('get My Feedback', JSON.stringify(res)) + if (res.code == 20041) { + let data = res.data; + if (data) { + this.total = data.counts; + let items = data.items; + if (items) { + if (this.isRefreshStatus == 1) { + this.feedBackList = items + this.controller.finishRefresh() + this.isRefreshStatus = 0 + } + if (this.isRefreshStatus == 2) { + this.controller.finishLoadMore() + this.isRefreshStatus = 0 + items.forEach(item => { + let bean = plainToInstance(FeedBackBean,item) + + this.feedBackList.push(bean) + }) + } + if (this.pageNum * 20>=this.total) { + this.controller.closeLoadMore = true; + } + } else { + this.handErrorOrEmPty(0, "暂无反馈记录") + } + } else { + this.handErrorOrEmPty(0, "暂无反馈记录") + } + } else { + this.handErrorOrEmPty(-1, StringUtils.get(res.msg, "")) + } + }) + .catch((err: AxiosError) => { + console.error('get My Feedback', JSON.stringify(err)) + this.handErrorOrEmPty(-1, err.message) + + }) + } + + /** + * 错误或空处理 + */ + handErrorOrEmPty(type: number, msg: string) { + ToastUtils.toastBottom(msg) + if (this.isRefreshStatus == 1) { + this.controller.finishRefresh() + this.isRefreshStatus = 0 + let bean = new FeedBackBean() + bean.baseType = type; + bean.content = msg; + this.feedBackList = new Array(); + this.feedBackList.push(bean) + } + if (this.isRefreshStatus == 2) { + this.controller.finishLoadMore() + this.isRefreshStatus = 0 + } + } + + build() { + Column() { + BaseTopBar({ + title: $r('app.string.title_my_feedback'), + }) + + LitheRefresh({ + scroller: this.scroller, + controller: this.controller, + itemLayout: () => { + this.listView() + }, + onRefresh: () => { + this.controller.closeLoadMore = false; + this.pageNum = 1; + this.isRefreshStatus = 1; + this.getData() + }, + onLoadMore: () => { + if (this.pageNum * 20 >= this.total) { + this.controller.finishLoadMore() + this.controller.closeLoadMore = true; + ToastUtil.showToast("没有更多数据!") + return + } + this.pageNum++; + this.isRefreshStatus = 2; + this.getData() + } + }) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .overlay(createWaterMark()) + .backgroundColor($r('app.color.page_background')) + } + + @Builder + listView() { + List({ scroller: this.scroller, space: 10 }) { + ForEach(this.feedBackList, (item: FeedBackBean) => { + if (item.baseType == 0 || item.baseType == -1) { + ListItem() { + EmptyOrErrorItemView({ type: item.baseType, msg: item.content }) + } + } else { + ListItem() { + this.itemUI(item) + } + .onClick(()=>{ + HMRouterMgr.push({ navigationId: 'startNavigation', pageUrl: "FeedBackDetailsPage",param:item }) + }) + } + }) + } + .listDirection(Axis.Vertical) + .scrollBar(BarState.Off) + .edgeEffect(EdgeEffect.None) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .nestedScroll({ + scrollForward: NestedScrollMode.PARENT_FIRST, + scrollBackward: NestedScrollMode.PARENT_FIRST + }) + } + + @Builder + itemUI(item: FeedBackBean) { + Column() { + Column() { + Text(item.title) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + .fontWeight(FontWeight.Bold) + .width(AppConstants.PERCENTAGE_MAX) + .textAlign(TextAlign.Start) + .maxLines(1) + .height($r('app.float.default_40')) + .ellipsisMode(EllipsisMode.END) + + Row() { + Text(this.getTypeStr(item.type)) + .fontColor($r('app.color.colorYellow7')) + .fontSize($r('app.float.text_size_10')) + .padding({ + left: $r('app.float.default_5'), + right: $r('app.float.default_5'), + top: $r('app.float.default_2'), + bottom: $r('app.float.default_2') + }) + .border({ + width: $r('app.float.default_1'), + color: $r('app.color.colorYellow7'), + radius: $r('app.float.default_8') + }) + Text(item.applicationName) + .fontColor($r('app.color.colorBluen7')) + .fontSize($r('app.float.text_size_10')) + .padding({ + left: $r('app.float.default_5'), + right: $r('app.float.default_5'), + top: $r('app.float.default_2'), + bottom: $r('app.float.default_2') + }) + .border({ + width: $r('app.float.default_1'), + color: $r('app.color.colorBluen7'), + radius: $r('app.float.default_8') + }) + .margin({ left: $r('app.float.default_8') }) + .visibility(StringUtils.isNullOrEmpty(item.applicationName) ? Visibility.None : Visibility.Visible) + + Text(this.getReplyStatusStr(item.replyStatus)) + .fontColor(item.replyStatus == 0 ? $r('app.color.colorGrey6') : $r('app.color.colorGreen6')) + .fontSize($r('app.float.text_size_10')) + .padding({ + left: $r('app.float.default_5'), + right: $r('app.float.default_5'), + top: $r('app.float.default_2'), + bottom: $r('app.float.default_2') + }) + .border({ + width: $r('app.float.default_1'), + color: item.replyStatus == 0 ? $r('app.color.colorGrey6') : $r('app.color.colorGreen6'), + radius: $r('app.float.default_8') + }) + .margin({ left: $r('app.float.default_8') }) + } + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Start) + .margin({ top: $r('app.float.default_5') }) + + + Text(item.content) + .fontColor($r('app.color.colorGrey6')) + .fontSize($r('app.float.text_size_14')) + .fontWeight(FontWeight.Bold) + .width(AppConstants.PERCENTAGE_MAX) + .textAlign(TextAlign.Start) + .maxLines(1) + .height($r('app.float.default_40')) + .ellipsisMode(EllipsisMode.END) + + } + .padding($r('app.float.default_10')) + .width(AppConstants.PERCENTAGE_MAX) + .height("auto") + .alignItems(HorizontalAlign.Start) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + } + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10'), top: $r('app.float.default_10') }) + .width(AppConstants.PERCENTAGE_MAX) + .height("auto") + .alignItems(HorizontalAlign.Start) + } + + getTypeStr(type: number): string { + switch (type) { + case 1: + return "个人建议"; + case 2: + return "软件问题"; + case 3: + return "硬件问题"; + case 4: + default: + return "其它"; + } + } + + getReplyStatusStr(replyStatus: number): string { + return replyStatus == 0 ? "未回复" : "已回复"; + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/MyUserInfoPage.ets b/entry/src/main/ets/ui/pages/MyUserInfoPage.ets new file mode 100644 index 0000000..453bb49 --- /dev/null +++ b/entry/src/main/ets/ui/pages/MyUserInfoPage.ets @@ -0,0 +1,439 @@ +import { HMRouter } from "@hadss/hmrouter"; +import { AxiosError, AxiosResponse } from "@ohos/axios"; +import { DialogHelper } from "@pura/harmony-dialog"; +import { FileUtil, ImageUtil, JSONUtil } from "@pura/harmony-utils"; +import { ToastUtil } from "@pura/harmony-utils/src/main/ets/action/ToastUtil"; +import AppConstants from "../../app/AppConstant"; +import { RuanseeAbilityStag } from "../../app/RuanseeAbilityStag"; +import { downLoadUserPhoto, updateWorkPhone, uploadUserPhoto } from "../../request/Api"; +import { FileUtils } from "../../util/FileUtils"; +import { StringUtils } from "../../util/StringUtils"; +import { BaseTopBar } from "../custom/BaseTopTar"; +import { createWaterMark } from "../custom/Watermark"; +import { fileIo, fileUri, picker } from "@kit.CoreFileKit"; +import { camera, cameraPicker } from "@kit.CameraKit"; +import { photoAccessHelper } from "@kit.MediaLibraryKit"; +import { DateUtil } from "@pura/harmony-utils/src/main/ets/utils/DateUtil"; +import { StrUtil } from "@pura/harmony-utils/src/main/ets/utils/StrUtil"; +import { common } from "@kit.AbilityKit"; +import { preferences } from "@kit.ArkData"; + +@Component +@HMRouter({ pageUrl: "MyUserInfoPage" }) +export struct MyUserInfoPage { + @State userPhoto: string | Resource = $r('app.media.icon_police_woman') + @State workPhone: string = RuanseeAbilityStag.userCache.getWorkPhone + dialogId: string = '' + + aboutToAppear(): void { + this.getImage() + } + + getImage() { + if (FileUtil.accessSync(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto)) { + this.userPhoto = fileUri.getUriFromPath(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + return + } + downLoadUserPhoto(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + .then((res: AxiosResponse) => { + console.info("result:" + JSON.stringify(res.data)); + if (res.status == 200) { + this.userPhoto = + fileUri.getUriFromPath(FileUtils.IMAGE_DIR + '/' + RuanseeAbilityStag.userCache.getProfilePhoto) + } + }) + .catch((error: AxiosError) => { + console.error("error:" + JSON.stringify(error)); + }) + } + + showUpdatePhone() { + DialogHelper.showTextInputDialog({ + title: "修改工作号码", + fontColor: $r('app.color.colorGrey8'), + fontSize: $r('app.float.text_size_16'), + inputHeight: $r('app.float.default_40'), + maxLength: 11, + defaultFocus: true, + inputBorder: { + width: $r('app.float.default_1'), + color: $r('app.color.colorGrey2'), + radius: $r('app.float.default_5'), + }, + text: this.workPhone, + placeholder: '请输入手机号码', + placeholderColor: $r('app.color.colorGrey6'), + onAction: (action: number, dialogId: string, value: string) => { + DialogHelper.closeDialog(dialogId) + if (action == -1) { + } + if (action == -2) { + this.updatePhone(value); + } + } + }) + } + + updatePhone(value: string) { + if (StringUtils.isNullOrEmpty(value)) { + ToastUtil.showToast("请输入手机号码!") + return + } + if (this.workPhone == value) { + ToastUtil.showToast("请修改手机号码!") + return + } + updateWorkPhone(value) + .then((res) => { + console.debug("updatePhone", JSON.stringify(res)) + ToastUtil.showToast(res.msg) + if (res.code == 200) { + this.workPhone = value + RuanseeAbilityStag.userCache.setWorkPhone = value + let context = getContext(this) as common.UIAbilityContext; + let pref = preferences.getPreferencesSync(context, { name: 'AppStore' }); + pref.put('updateUserInfo',false) + } + }) + .catch((err: AxiosError) => { + console.error("updatePhone", JSON.stringify(err)) + ToastUtil.showToast("修改失败") + }) + } + + async selectImage() { + let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); + let photoPicker = new photoAccessHelper.PhotoViewPicker(); + // 过滤选择媒体文件类型为IMAGE + photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE; + // 设置最大选择数量 + photoSelectOptions.maxSelectNumber = 1; + let chooseFile: picker.PhotoSelectResult = await photoPicker.select(photoSelectOptions); + let newFilePath = FileUtils.IMAGE_DIR + '/' + DateUtil.getTodayTime() + ".jpg"; + let newFileUri = fileUri.getUriFromPath(newFilePath) + let isCopy = await FileUtils.copyToLocal(chooseFile.photoUris[0], newFileUri) + if (isCopy) { + newFileUri = await ImageUtil.compressPhoto(newFileUri, 260); + this.updatePhoto(newFileUri) + } else { + ToastUtil.showToast("复制文件失败!") + } + } + + /** + * 拍照 + */ + async takePhoto() { + let pathDir = FileUtils.IMAGE_DIR; + let fileName = `${new Date().getTime()}.JPEG` + let filePath = `${pathDir}/${fileName}` + let imageFileUri: string | undefined = undefined; + fileIo.createRandomAccessFileSync(filePath, fileIo.OpenMode.CREATE); + + let fileUris = fileUri.getUriFromPath(filePath); + let pickerProfile: cameraPicker.PickerProfile = { + cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK, + saveUri: fileUris, + }; + let result: cameraPicker.PickerResult = + await cameraPicker.pick(getContext(), [cameraPicker.PickerMediaType.PHOTO], + pickerProfile); + console.info(`picker resultCode: ${result.resultCode},resultUri: ${result.resultUri},mediaType: ${result.mediaType}`); + if (result.resultCode == 0) { + if (result.mediaType === cameraPicker.PickerMediaType.PHOTO) { + imageFileUri = result.resultUri + imageFileUri = await ImageUtil.compressPhoto(imageFileUri, 150); + this.updatePhoto(imageFileUri); + } + } else { + ToastUtil.showToast("取消选择") + } + } + + /** + * 更新图片 + * @param imageFileUri + */ + updatePhoto(imageFileUri: string) { + //自定义文字内容 + this.dialogId = DialogHelper.showLoadingDialog({ + loadColor: Color.White, + content: "正在上传,请稍后...", + fontSize: 15, + backgroundColor: '#ED000000', + autoCancel: true, + onWillDismiss: () => { + DialogHelper.closeDialog(this.dialogId) + this.dialogId = '' + } + }) + + //常见问题 + uploadUserPhoto(imageFileUri) + .then((res) => { + DialogHelper.closeDialog(this.dialogId) + console.debug("updatePhoto", JSON.stringify(res)) + if (res.code == 200) { + this.userPhoto = imageFileUri + let data = res.data; + if(data){ + let id :string= data['id'] + if(StrUtil.isNotEmpty(id)){ + FileUtil.renameSync(FileUtil.getFilePath(imageFileUri),FileUtils.IMAGE_DIR+"/"+id); + RuanseeAbilityStag.userCache.setProfilePhoto = id + this.userPhoto = fileUri.getUriFromPath(FileUtils.IMAGE_DIR+"/"+id); + let context = getContext(this) as common.UIAbilityContext; + context.eventHub.emit('updateUserPhoto') + let pref = preferences.getPreferencesSync(context, { name: 'AppStore' }); + pref.put('updateUserInfo',false) + } + } + } + }) + .catch((err: AxiosError) => { + DialogHelper.closeDialog(this.dialogId) + console.error("updatePhoto", JSON.stringify(err)) + }) + } + + showUpdatePhoto() { + //带标题 + DialogHelper.showActionSheetDialog({ + title: "选择头像", + titleFontColor: Color.Black, + cancelFontColor: Color.Red, + cancelFontWeight: FontWeight.Normal, + sheets: ['相机', '相册'], + onAction: (index) => { + switch (index) { + case 0: + this.takePhoto() + break; + case 1: + this.selectImage() + break; + } + } + }) + } + + build() { + Column() { + BaseTopBar({ + title: $r('app.string.title_user_info'), + }) + + Row() { + + Text("头像") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Blank() + .layoutWeight(1) + + Image(this.userPhoto) + .width($r('app.float.default_68')) + .height($r('app.float.default_52')) + .onClick(() => { + this.showUpdatePhoto() + }) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + .margin({ left: $r('app.float.default_10') }) + + } + .padding($r('app.float.default_10')) + .width(AppConstants.PERCENTAGE_MAX) + .height('auto') + .alignItems(VerticalAlign.Center) + .backgroundColor($r('app.color.white')) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey2')) + + Row() { + + Text("姓名") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Blank() + .layoutWeight(1) + + Text(RuanseeAbilityStag.userCache.getUserName) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + .visibility(Visibility.Hidden) + .margin({ left: $r('app.float.default_10') }) + + } + .width(AppConstants.PERCENTAGE_MAX) + .alignItems(VerticalAlign.Center) + .backgroundColor($r('app.color.white')) + .padding($r('app.float.default_10')) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey2')) + + Row() { + + Text("警号") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Blank() + .layoutWeight(1) + + Text(RuanseeAbilityStag.userCache.getUserCode) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + .visibility(Visibility.Hidden) + .margin({ left: $r('app.float.default_10') }) + + } + .width(AppConstants.PERCENTAGE_MAX) + .alignItems(VerticalAlign.Center) + .backgroundColor($r('app.color.white')) + .padding($r('app.float.default_10')) + + Blank() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_10')) + + Row() { + + Text("职位") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Blank() + .layoutWeight(1) + + Text(StringUtils.get(RuanseeAbilityStag.userCache.getPoliceTypeName, "暂无")) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + .visibility(Visibility.Hidden) + .margin({ left: $r('app.float.default_10') }) + + } + .width(AppConstants.PERCENTAGE_MAX) + .alignItems(VerticalAlign.Center) + .backgroundColor($r('app.color.white')) + .padding($r('app.float.default_10')) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey2')) + + Row() { + + Text("单位") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Blank() + .layoutWeight(1) + + Text(RuanseeAbilityStag.userCache.getDeptName) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + .visibility(Visibility.Hidden) + .margin({ left: $r('app.float.default_10') }) + + } + .width(AppConstants.PERCENTAGE_MAX) + .alignItems(VerticalAlign.Center) + .backgroundColor($r('app.color.white')) + .padding($r('app.float.default_10')) + + Blank() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_10')) + + Row() { + + Text("证件号码") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Blank() + .layoutWeight(1) + + Text(RuanseeAbilityStag.userCache.getIdCardNum) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + .visibility(Visibility.Hidden) + .margin({ left: $r('app.float.default_10') }) + + } + .width(AppConstants.PERCENTAGE_MAX) + .alignItems(VerticalAlign.Center) + .backgroundColor($r('app.color.white')) + .padding($r('app.float.default_10')) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .backgroundColor($r('app.color.colorGrey2')) + + Row() { + + Text("工作号码") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Blank() + .layoutWeight(1) + + Text(this.workPhone) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_22')) + .height($r('app.float.default_22')) + .margin({ left: $r('app.float.default_10') }) + + } + .width(AppConstants.PERCENTAGE_MAX) + .alignItems(VerticalAlign.Center) + .backgroundColor($r('app.color.white')) + .padding($r('app.float.default_10')) + .onClick(() => { + this.showUpdatePhone(); + }) + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .overlay(createWaterMark()) + .backgroundColor($r('app.color.page_background')) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/OpinionsSuggestionsPages.ets b/entry/src/main/ets/ui/pages/OpinionsSuggestionsPages.ets new file mode 100644 index 0000000..2c6e853 --- /dev/null +++ b/entry/src/main/ets/ui/pages/OpinionsSuggestionsPages.ets @@ -0,0 +1,380 @@ +import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"; +import { ToastUtil } from "@pura/harmony-utils/src/main/ets/action/ToastUtil"; +import AppConstants from "../../app/AppConstant"; +import { AppDataModel } from "../../model/resultModel/ApplicationResultModel"; +import { BasePageResult } from "../../model/uiModel/PageResultModel"; +import { addFeedBack } from "../../request/Api"; +import { cardRoundBorderGreyStyle, cardRoundBorderStyle } from "../../style/BorderStyle"; +import { StringUtils } from "../../util/StringUtils"; +import { BaseTopBar } from "../custom/BaseTopTar"; +import { createWaterMark } from "../custom/Watermark"; +import { router } from "@kit.ArkUI"; + +/** + * 意见建议页面 + */ +@Component +@Preview +@HMRouter({ pageUrl: 'OpinionsSuggestionsPages' }) +export struct OpinionsSuggestionsPages { + @State selectType: number = 1; + @State inputTitle: string = ""; + @State inputContent: string = ""; + @State appName: string = ""; + appId: string = ""; + textInputController: TextInputController = new TextInputController() + textAreaController: TextInputController = new TextInputController() + + aboutToAppear(): void { + } + + submit() { + if (this.selectType == 2 && StringUtils.isNullOrEmpty(this.appName)) { + ToastUtil.showToast("请选择应用!") + return + } + if (StringUtils.isNullOrEmpty(this.inputTitle)) { + ToastUtil.showToast("请输入标题!") + return + } + if (StringUtils.isNullOrEmpty(this.inputContent)) { + ToastUtil.showToast("请输入内容!") + return + } + addFeedBack(this.appId, this.appName, this.selectType, this.inputTitle, this.inputContent) + .then((res) => { + console.debug("submit feedBack", JSON.stringify(res)) + ToastUtil.showToast(res.msg) + if (res.code == 20011) { + setTimeout(() => { + HMRouterMgr.pop() + }, 800) + } + }) + .catch((err: Error) => { + console.error("submit feedBack", JSON.stringify(err)) + ToastUtil.showToast(err.message) + + }) + } + + build() { + Column() { + BaseTopBar({ + title: $r('app.string.title_Feedback'), + rightText: "我的反馈", + rightClickEvent: () => { + HMRouterMgr.push({ navigationId: 'startNavigation', pageUrl: "MyFeedBackPage" }) + } + }) + Scroll() { + Column() { + //上部分 + this.topModel() + this.bottomModel() + + } + .padding({ + left: $r('app.float.default_15'), + right: $r('app.float.default_15') + }) + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + } + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + + Column() { + Button("提交反馈", { type: ButtonType.Normal }) + .borderRadius(8) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_40')) + .fontColor($r('app.color.white')) + .fontSize($r('app.float.text_size_14')) + .backgroundColor($r('app.color.bull')) + .onClick(() => { + this.submit() + }) + } + .padding({ + left: $r('app.float.default_15'), + right: $r('app.float.default_15') + , bottom: $r('app.float.default_28') + }) + .width(AppConstants.PERCENTAGE_MAX) + .height('auto') + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.page_background')) + .overlay(createWaterMark()) + + // .onVisibleAreaChange([0.5, 1], (isVisible) => { + // if (isVisible) { + // let param = HMRouterMgr.getCurrentParam() as BasePageResult; + // if (param) { + // let data = param.data as AppDataModel; + // if (data) { + // this.appName = data.name + // this.appId = data.id + // } + // router.getParams() + // } + // } + // }) + } + + @Builder + bottomModel() { + //上部分 + Column() { + + Row() { + Text("*") + .fontColor($r('app.color.colorRed9')) + .margin({ top: $r('app.float.default_5') }) + .fontSize($r('app.float.text_size_16')); + + Text("反馈标题") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + .margin({ top: $r('app.float.default_5') }); + + } + .justifyContent(FlexAlign.Start) + .alignItems(VerticalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX); + + TextInput({ text: this.inputTitle, placeholder: '请输入标题', controller: this.textInputController }) + .placeholderColor(Color.Grey) + .placeholderFont({ size: 14, weight: 400 }) + .caretColor(Color.Blue) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_46')) + .margin({ top: $r('app.float.default_10') }) + .fontSize(14) + .fontColor($r('app.color.colorGrey8')) + .backgroundColor($r('app.color.colorGrey1')) + .border(cardRoundBorderStyle) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .onChange((value: string) => { + this.inputTitle = value + }) + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .color($r('app.color.colorGrey3')) + .margin({ top: $r('app.float.default_10') }); + + Row() { + Text("*") + .fontColor($r('app.color.colorRed9')) + .margin({ top: $r('app.float.default_5') }) + .fontSize($r('app.float.text_size_16')); + + Text("反馈内容") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + .margin({ top: $r('app.float.default_5') }); + + } + .justifyContent(FlexAlign.Start) + .alignItems(VerticalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + .margin({ top: $r('app.float.default_10') }); + + TextArea({ + text: this.inputContent, + placeholder: '请输入反馈内容(500字以内)', + controller: this.textAreaController + }) + .placeholderColor(Color.Grey) + .placeholderFont({ size: 14, weight: 400 }) + .caretColor(Color.Blue) + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_180')) + .margin({ top: $r('app.float.default_10') }) + .fontSize(14) + .fontColor($r('app.color.colorGrey8')) + .backgroundColor($r('app.color.colorGrey1')) + .border(cardRoundBorderStyle) + .padding({ left: $r('app.float.default_10'), right: $r('app.float.default_10') }) + .onChange((value: string) => { + this.inputContent = value + }) + } + .padding($r('app.float.default_10')) + .alignItems(HorizontalAlign.Start) + .width(AppConstants.PERCENTAGE_MAX) + .margin({ top: $r('app.float.default_10') }) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + + } + + @Builder + topModel() { + //上部分 + Column() { + Text("反馈类型") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')); + + //类型选项 + Row() { + + Text("个人建议") + .fontColor(this.selectType == 1 ? $r('app.color.white') : $r('app.color.colorGrey7')) + .fontSize($r('app.float.text_size_14')) + .padding({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_8'), + bottom: $r('app.float.default_8') + }) + .backgroundColor(this.selectType == 1 ? $r('app.color.bull') : $r('app.color.white')) + .border(cardRoundBorderGreyStyle) + .onClick(() => { + if (this.selectType == 1) { + return; + } + this.selectType = 1; + }); + + Blank() + .layoutWeight(1); + + Text("软件问题") + .fontColor(this.selectType == 2 ? $r('app.color.white') : $r('app.color.colorGrey7')) + .fontSize($r('app.float.text_size_14')) + .padding({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_8'), + bottom: $r('app.float.default_8') + }) + .backgroundColor(this.selectType == 2 ? $r('app.color.bull') : $r('app.color.white')) + .border(cardRoundBorderGreyStyle) + .onClick(() => { + if (this.selectType == 2) { + return; + } + this.selectType = 2; + }); + + Blank() + .layoutWeight(1); + Text("硬件问题") + .fontColor(this.selectType == 3 ? $r('app.color.white') : $r('app.color.colorGrey7')) + .fontSize($r('app.float.text_size_14')) + .padding({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_8'), + bottom: $r('app.float.default_8') + }) + .backgroundColor(this.selectType == 3 ? $r('app.color.bull') : $r('app.color.white')) + .border(cardRoundBorderGreyStyle) + .onClick(() => { + if (this.selectType == 3) { + return; + } + this.selectType = 3; + }); + + Blank() + .layoutWeight(1); + Text("其他") + .fontColor(this.selectType == 4 ? $r('app.color.white') : $r('app.color.colorGrey7')) + .fontSize($r('app.float.text_size_14')) + .padding({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_8'), + bottom: $r('app.float.default_8') + }) + .backgroundColor(this.selectType == 4 ? $r('app.color.bull') : $r('app.color.white')) + .border(cardRoundBorderGreyStyle) + .onClick(() => { + if (this.selectType == 4) { + return; + } + this.selectType = 4; + }); + + } + .margin({ top: $r('app.float.default_10') }) + .width(AppConstants.PERCENTAGE_MAX); + + Divider() + .width(AppConstants.PERCENTAGE_MAX) + .height($r('app.float.default_1')) + .color($r('app.color.colorGrey3')) + .margin({ top: $r('app.float.default_10') }); + + Row() { + + Text("*") + .fontColor($r('app.color.colorRed9')) + .fontSize($r('app.float.text_size_16')) + .margin({ top: $r('app.float.default_5') }) + .visibility(this.selectType == 2 ? Visibility.Visible : Visibility.Hidden); + + Text("反馈应用") + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + .margin({ top: $r('app.float.default_5') }); + + } + .justifyContent(FlexAlign.Start) + .alignItems(VerticalAlign.Center) + .margin({ top: $r('app.float.default_10') }) + .width(AppConstants.PERCENTAGE_MAX); + + Row() { + Text(StringUtils.get(this.appName, "请选择")) + .fontColor(StringUtils.isNullOrEmpty(this.appName) ? $r('app.color.colorGrey6') : $r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_16')) + .layoutWeight(1) + .maxLines(1) + .ellipsisMode(EllipsisMode.END) + .textAlign(TextAlign.Start); + + Image($r('app.media.arrow_right')) + .width($r('app.float.default_20')) + .height($r('app.float.default_20')); + + } + .padding({ left: $r('app.float.default_5'), right: $r('app.float.default_5') }) + .justifyContent(FlexAlign.Start) + .alignItems(VerticalAlign.Center) + .height($r('app.float.default_46')) + .margin({ top: $r('app.float.default_10') }) + .width(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.colorGrey1')) + .border(cardRoundBorderStyle) + .onClick(() => { + HMRouterMgr.push({ navigationId: 'startNavigation', pageUrl: "SelectAppListPage" }, { + onResult: (result) => { + let param = result.result as BasePageResult + if (param) { + let data = param.data as AppDataModel + if (data) { + this.appName = data.name + this.appId = data.id + } + } + } + }) + }); + } + .padding($r('app.float.default_10')) + .alignItems(HorizontalAlign.Start) + .width(AppConstants.PERCENTAGE_MAX) + .margin({ top: $r('app.float.default_10') }) + .backgroundColor($r('app.color.white')) + .border(cardRoundBorderStyle) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/SelectAppListPage.ets b/entry/src/main/ets/ui/pages/SelectAppListPage.ets new file mode 100644 index 0000000..ce35baf --- /dev/null +++ b/entry/src/main/ets/ui/pages/SelectAppListPage.ets @@ -0,0 +1,242 @@ +import { AxiosError } from "@ohos/axios"; +import { ToastUtil } from "@pura/harmony-utils"; +import AppConstants from "../../app/AppConstant"; +import { cardRoundBorderGreyStyle } from "../../style/BorderStyle"; +import { StringUtils } from "../../util/StringUtils"; +import { ToastUtils } from "../../util/ToasUtils"; +import { BaseTopBar } from "../custom/BaseTopTar"; +import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"; +import { createWaterMark } from "../custom/Watermark"; +import { AppDataModel } from "../../model/resultModel/ApplicationResultModel"; +import { getAppList } from "../../request/Api"; +import { LitheRefresh, RefreshController } from "@abner/lithe_refresh"; +import { EmptyOrErrorItemView } from "../custom/EmptyOrErrorItemView"; +import { SelectAppItem } from "../view/SelectAppItem"; +import { BasePageResult } from "../../model/uiModel/PageResultModel"; +import { plainToInstance } from "class-transformer"; + +/** + * 选择任务 + */ +@Preview +@Component +@HMRouter({ pageUrl: 'SelectAppListPage' }) +export struct SelectAppListPage { + @State inputContent: string | undefined = undefined + @State selectValue: Array = new Array(); + private selectItem: AppDataModel | undefined; + controller: RefreshController = new RefreshController() + scroller: Scroller = new Scroller() + total: number = 0; + pageNum: number = 1; + isRefreshStatus: number = 0; + + aboutToAppear(): void { + setTimeout(() => { + this.controller.isAutoRefresh = true + }, 800) + } + + getAppListData() { + getAppList(StringUtils.get(this.inputContent, ""), this.pageNum) + .then((res) => { + console.debug(JSON.stringify(res)) + if (res.code != 20041) { + this.handErrorOrEmPty(-1, StringUtils.get(res.msg, "")) + return + } + let data = res.data; + if (!data) { + this.handErrorOrEmPty(0, StringUtils.get(res.msg, "暂无应用")) + return + } + this.total = data.counts; + let dataList = data.items; + if (!dataList || dataList.length < 1) { + this.handErrorOrEmPty(0, StringUtils.get(res.msg, "暂无应用")) + return + } + if (this.isRefreshStatus == 1) { + this.controller.finishRefresh() + this.isRefreshStatus = 0 + this.selectValue = new Array(); + dataList.forEach(item => { + this.selectValue.push(plainToInstance(AppDataModel, item)); + }) + } + if (this.isRefreshStatus == 2) { + this.controller.finishLoadMore() + this.isRefreshStatus = 0 + dataList.forEach(item => { + this.selectValue.push(item); + }) + } + if (this.pageNum * 20 >= this.total) { + this.controller.closeLoadMore = true + } + }) + .catch((e: AxiosError) => { + this.handErrorOrEmPty(-1, `查询任务失败:${e.message}`) + }) + } + + /** + * 错误或空处理 + */ + handErrorOrEmPty(type: number, msg: string) { + ToastUtils.toastBottom(msg) + if (this.isRefreshStatus == 1) { + this.controller.finishRefresh() + this.isRefreshStatus = 0 + let bean = new AppDataModel() + bean.baseType = type; + bean.remark = msg; + this.selectValue = new Array(); + this.selectValue.push(bean) + } + if (this.isRefreshStatus == 2) { + this.controller.finishLoadMore() + this.isRefreshStatus = 0 + } + } + + submit() { + if (!this.selectItem) { + ToastUtil.showLong("请先选择应用") + return + } + let param = new BasePageResult() + param.type = 1; + param.data = this.selectItem + HMRouterMgr.pop({ pageUrl: "OpinionsSuggestionsPages", param: param }) + } + + build() { + Column() { + BaseTopBar({ + title: $r('app.string.title_select_app'), + }) + + TextInput({ text: this.inputContent, placeholder: "请输入应用名称进行搜索" }) + .placeholderColor($r('app.color.colorGrey6')) + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.colorGrey8')) + .margin({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_10') + }) + .padding({ + left: $r('app.float.default_5'), + right: $r('app.float.default_5'), + }) + .onChange((text: string) => { + this.inputContent = text; + }) + .height($r('app.float.default_40')) + .width('96%') + .textAlign(TextAlign.Start) + .border(cardRoundBorderGreyStyle) + .enterKeyType(EnterKeyType.Search)// 设置为搜索按钮 + .onSubmit((enterKey: EnterKeyType, event: SubmitEvent) => { + // 点击搜索按钮时触发 + this.controller.isAutoRefresh = true; + }); + + // ListView({ + // data: this.selectValue, + // }) + + LitheRefresh({ + scroller: this.scroller, + controller: this.controller, + itemLayout: () => { + this.listView() + }, + onRefresh: () => { + this.controller.closeLoadMore = false; + this.pageNum = 1; + this.isRefreshStatus = 1; + this.getAppListData() + }, + onLoadMore: () => { + if (this.pageNum * 20 >= this.total) { + this.controller.finishLoadMore() + this.controller.closeLoadMore = true; + ToastUtil.showToast("没有更多数据!") + return + } + this.pageNum++; + this.isRefreshStatus = 2; + this.getAppListData() + } + }) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + + Button("完成", { type: ButtonType.Normal, stateEffect: true }) + .fontSize($r('app.float.text_size_16')) + .fontColor($r('app.color.white')) + .backgroundColor($r('app.color.bull')) + .borderRadius(8) + .margin({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + bottom: $r('app.float.default_28'), + }) + .onClick(() => { + this.submit(); + }) + .width('95%'); + + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .backgroundColor($r('app.color.page_background')) + .overlay(createWaterMark()) + } + + @Builder + listView() { + List({ scroller: this.scroller, space: 10 }) { + ForEach(this.selectValue, (item: AppDataModel) => { + if (item.baseType == 0 || item.baseType == -1) { + ListItem() { + EmptyOrErrorItemView({ type: item.baseType, msg: item.remark }) + } + } else { + ListItem() { + SelectAppItem({ + item: item, + onSelect: (item: AppDataModel) => { + this.selectItem = item; + this.updateCardDataStatus(item) + } + }) + } + } + }) + } + .divider({ + strokeWidth: $r('app.float.default_1'), + color: $r('app.color.colorGrey2'), + startMargin: $r('app.float.default_63') + }) + .listDirection(Axis.Vertical) + .scrollBar(BarState.Off) + .edgeEffect(EdgeEffect.None) + .width(AppConstants.PERCENTAGE_MAX) + .layoutWeight(1) + .nestedScroll({ + scrollForward: NestedScrollMode.PARENT_FIRST, + scrollBackward: NestedScrollMode.PARENT_FIRST + }) + } + + updateCardDataStatus(item: AppDataModel) { + // 遍历所有项,只将当前选中的项设为true,其他设为false + this.selectValue.forEach(selectedItem => { + selectedItem.isSelect = (item.id === selectedItem.id); + }); + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/StartPage.ets b/entry/src/main/ets/ui/pages/StartPage.ets new file mode 100644 index 0000000..7df4c9f --- /dev/null +++ b/entry/src/main/ets/ui/pages/StartPage.ets @@ -0,0 +1,321 @@ +import { HMRouter, HMRouterMgr } from '@hadss/hmrouter'; +import { common } from '@kit.AbilityKit'; + +import { AppCache, AUTH_SYSCODE } from '../../app/AppCache'; +import { UserCache } from '../../app/UserCache'; +import { StringUtils } from '../../util/StringUtils'; +import { UserInfoModel } from '../../model/cacheModel/UserInfoModel'; +import { buffer, util } from '@kit.ArkTS'; +import { connection } from '@kit.NetworkKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { ToastUtils } from '../../util/ToasUtils'; +import { createWaterMark } from '../custom/Watermark'; +import { AuthUserModel, IAuthTaskType } from '../../model/uiModel/IAuthTaskType'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { RuanseeAbilityStag } from '../../app/RuanseeAbilityStag'; +import { DialogAction, ToastUtil } from '@pura/harmony-utils'; +import { AnHuiAddressModel } from '../../model/uiModel/AnHuiAddressModel'; +import { DialogHelper } from '@pura/harmony-dialog'; +import { preferences } from '@kit.ArkData'; + +@HMRouter({ pageUrl: 'StartPage' }) +@Component +export struct StartPage { + @State message: string = '正在初始化...'; + context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; + ipAddress: string | undefined = undefined + + aboutToAppear() { + this.context.eventHub.on('NotPermissions', (data: string) => { + if (data) { + this.showNotPermissionsDialog() + } + }); + this.context.eventHub.on('PermissionsSuccess', (data: string) => { + RuanseeAbilityStag.appCache.setPermissionsStatus = true + this.getIpAddress(); + }); + } + + aboutToDisappear(): void { + this.context.eventHub.off('NotPermissions') + this.context.eventHub.off('PermissionsSuccess') + } + + onPageHide(): void { + + } + + onPageShow(): void { + + } + + showNotPermissionsDialog() { + let dialogID = DialogHelper.showAlertDialog({ + content: "由于您拒绝了应用的权限,应用无法正常运行,请前往设置页面授权!", + onAction: (action) => { + if (action == DialogAction.ONE) { + DialogHelper.closeDialog(dialogID) + HMRouterMgr.pop({ pageUrl: 'StartPage' }) + this.context.terminateSelf() + } else if (action == DialogAction.TWO) { + DialogHelper.closeDialog(dialogID) + // 确认操作处理 + this.jumpToAppDetails() + HMRouterMgr.pop({ pageUrl: 'StartPage' }) + this.context.terminateSelf() + } + } + }) + } + + jumpToAppDetails() { + const context = getContext() as common.UIAbilityContext; + context.startAbility({ + bundleName: 'com.huawei.hmos.settings', + abilityName: 'com.huawei.hmos.settings.MainAbility', + uri: 'application_info_entry', // 固定值表示应用详情页 + parameters: { + pushParams: context.abilityInfo.bundleName // 当前应用包名 + } + }); + } + + //TODO 测试登录信息 + testLogin(){ + let userCache = RuanseeAbilityStag.userCache + userCache.setUserName = "陈乐(测试账号)" + userCache.setUserCode = "999013" + userCache.setDeptCode = '340012000000' + userCache.setDeptName = "测试单位001" + userCache.setIdCardNum = "420113199310297548" + // userCache.setAuthToken = authUserModel.token + // userCache.setProfilePhoto = StringUtils.get(authUserModel.profilePhoto, "") + userCache.setPhoneNum = '18815656560' + // userCache.setEmail = StringUtils.get(authUserModel.email, "") + userCache.setWorkPhone = '19915155150' + // userCache.setPoliceTypeId = StringUtils.get(authUserModel.policeTypeId, "") + // userCache.setPoliceTypeName = StringUtils.get(authUserModel.policeTypeName, "") + userCache.setBirthdate = '19931029' + userCache.setAge = 32 + let departmentCode = userCache.getDeptCode.substring(0, 4) + let departmentName = new AnHuiAddressModel().getAddress(departmentCode) + userCache.setDepartmentCode = departmentCode + userCache.setDepartmentName = departmentName + this.handUserInfo(this.ipAddress) + } + + authLogin() { + let pref = preferences.getPreferencesSync(this.context, { name: 'AppStore' }); + let isUpdate = pref.getSync('updateUserInfo',false) + + + let want: Want = { + bundleName: 'hm.anhui.police.auth', + abilityName: 'OhosAuthAbility', + parameters: { + 'action': 'getAuthUser', + // 'IAuthTaskType': isUpdate?IAuthTaskType.AUTH_TASK_START_AUTH:IAuthTaskType.AUTH_TASK_USER, + 'IAuthTaskType': IAuthTaskType.AUTH_TASK_USER, + 'packageName': 'com.ycgis.macall.personalcenter', + 'sysCode': AUTH_SYSCODE + } + }; + try { + this.context.startAbilityForResult(want, (err: BusinessError, result: common.AbilityResult) => { + if (err.code) { + // 处理业务逻辑错误 + console.error(`startAbility failed, code is ${err.code}, message is ${err.message}`); + return; + } + // 执行正常业务 + console.info(`startAbility succeed resultCode:${result.resultCode} result:${JSON.stringify(result)} want:${JSON.stringify(want)}`); + if (result.resultCode === -1) { + this.message = '未获取到用户信息'; + return; + } + pref.put('updateUserInfo',false) + const iAuthTaskType = result.want?.parameters?.IAuthTaskType + const message = result.want?.parameters?.message + if (iAuthTaskType === IAuthTaskType.AUTH_TASK_USER) { + this.message = `开始处理认证数据`; + let authUser = result.want?.parameters?.authUser; + hilog.info(0x0000, 'carousel', '%{public}s', `authUser:${authUser}`); + if (result.resultCode === 200) { + // 获取到用户信息 + let authUserModel = JSON.parse(StringUtils.get(authUser, "")) as AuthUserModel + if (authUserModel) { + let userCache = RuanseeAbilityStag.userCache + userCache.setUserName = authUserModel.realName + userCache.setUserCode = authUserModel.userNum + userCache.setDeptCode = authUserModel.orgId + userCache.setDeptName = authUserModel.orgName + userCache.setIdCardNum = authUserModel.code + userCache.setAuthToken = authUserModel.token + userCache.setProfilePhoto = StringUtils.get(authUserModel.profilePhoto, "") + userCache.setPhoneNum = StringUtils.get(authUserModel.phoneNum, "") + userCache.setEmail = StringUtils.get(authUserModel.email, "") + userCache.setWorkPhone = StringUtils.get(authUserModel.workPhone, "") + userCache.setPoliceTypeId = StringUtils.get(authUserModel.policeTypeId, "") + userCache.setPoliceTypeName = StringUtils.get(authUserModel.policeTypeName, "") + userCache.setBirthdate = StringUtils.get(authUserModel.birthdate, "") + userCache.setAge = StringUtils.getNumber(authUserModel.age, 0) + let departmentCode = userCache.getDeptCode.substring(0, 4) + userCache.setDepartmentCode = departmentCode + userCache.setDepartmentName = new AnHuiAddressModel().getAddress(departmentCode) + this.handUserInfo(this.ipAddress) + } else { + this.loginError(`获取用户信息失败!${message}}`); + } + } else if (result.resultCode === 100) { + this.message = `用户主动关闭登录页面,未获取到用户信息`; + this.loginError(`用户主动关闭登录页面,未获取到用户信息`); + } else { + this.message = `未获取到用户信息,错误码(${result.resultCode})`; + this.loginError(`未获取到用户信息,错误码(${result.resultCode})`); + } + } else { + this.message = `获取用户信息失败:${result.want?.parameters?.message}`; + this.loginError(`获取用户信息失败:${result.want?.parameters?.message}`); + } + }); + } catch (err) { + // 处理入参错误异常 + let code = (err as BusinessError).code; + let message = (err as BusinessError).message; + console.error(`startAbility failed, code is ${code}, message is ${message}`); + this.loginError(`startAbility failed, code is ${code}, message is ${message}`); + } + } + + loginError(msg: string) { + ToastUtil.showLong(msg) + setTimeout(() => { + HMRouterMgr.pop({ pageUrl: 'StartPage' }) + this.context.terminateSelf() + }, 1500) + } + + handUserInfo(ipAddress: string | undefined) { + let appCache = AppCache.getAppCache(); + let userCache = UserCache.getUserCache(); + appCache.setIpOrPort('20.90.2.2', '80', "/ypc_test_out/") + //设置用户信息,后期改成单点登录获取用户信息 + // userCache.setUserName = "陈乐(测试)" + // userCache.setUserCode = "999013" + // userCache.setDeptName = "测试单位001" + // userCache.setDeptCode = "340012000000" + // userCache.setIdCardNum = "420113199310297548" + + // let departmentCode = userCache.getUserCode.substring(0, 4) + // let departmentName = new AnHuiAddressModel().getAddress(departmentCode) + // userCache.setDepartmentCode = departmentCode + // userCache.setDepartmentName = departmentName + + //本机IP + appCache.setLocalIp = StringUtils.get(ipAddress, "10.115.101.1"); + + let userInfos = userCache.getUserInfo(); + if (StringUtils.isNullOrEmpty(userInfos)) { + let cs: UserInfoModel = { + "userCode": userCache.getUserCode, + "userName": userCache.getUserName, + "deptName": userCache.getDeptName, + "deptCode": userCache.getDeptCode, + "idCardNum": userCache.getIdCardNum, + "ip": appCache.setLocalIp, + "departmentCode": userCache.getDepartmentCode, + "departmentName": userCache.getDepartmentName, + } + let userInfo = JSON.stringify(cs) + let byte = new Uint8Array(buffer.from(userInfo, 'utf-8').buffer); + userCache.setUserInfo = new util.Base64Helper().encodeToStringSync(byte); + } + + setTimeout(() => { + this.message = "正在获取用户信息..." + if (appCache.getPermissionsStatus) { + this.jumpAdPage(); + } + }, 500) + } + + /** + * 获取IP地址 + */ + getIpAddress() { + let defNet = connection.getDefaultNet() + defNet.then((netHandle: connection.NetHandle) => { + connection.getConnectionProperties(netHandle, (error: BusinessError, data: connection.ConnectionProperties) => { + if (error) { + console.error(`Failed to get connection properties. Code:${error.code}, message:${error.message}`); + ToastUtils.toastBottom("获取IP地址失败!") + // this.testLogin() + this.authLogin() + return; + } + console.info("Succeeded to get data: " + JSON.stringify(data)); + try { + let ip = data['linkAddresses'][0]['address']['address'] + console.info('本地ip:', ip) + this.ipAddress = ip + // this.testLogin() + this.authLogin() + } catch (e) { + console.error("e", JSON.stringify(e)); + ToastUtils.toastBottom("获取IP地址失败!") + // this.testLogin() + this.authLogin() + } + }); + }).catch((error: Error) => { + console.error("e", JSON.stringify(error)); + this.loginError(error.message); + }) + } + + build() { + Column() { + Image($r('app.media.icon_applogin')) + .width(100) + .aspectRatio(1) + .margin({ top: 190 }); + + Text($r('app.string.EntryAbility_label')) + .fontSize($r('app.float.text_size_24')) + .fontColor($r('app.color.bull')) + .fontWeight(700) + .letterSpacing(1) + .margin({ + top: $r('app.float.default_20'), + bottom: $r('app.float.default_8') + }) + + Text(this.message) + .fontColor($r('app.color.grad')) + .fontSize($r("app.float.text_size_14")) + .margin({ top: 32 }) + + Text($r('app.string.ownership_dept')) + .fontColor($r('app.color.grad')) + .fontSize($r("app.float.text_size_14")) + .height('100%') + .margin({ bottom: $r('app.float.default_20') }) + + } + .width('100%') + .height('100%') + .expandSafeArea([SafeAreaType.SYSTEM]) + .overlay(createWaterMark()) + } + + /** + * 跳转主页 + */ + jumpAdPage() { + setTimeout(() => { + this.message = "正在跳转..." + HMRouterMgr.replace({ navigationId: 'startNavigation', pageUrl: "MainPage" }) + }, 800); + } +} \ No newline at end of file diff --git a/entry/src/main/ets/ui/pages/WebAppPages.ets b/entry/src/main/ets/ui/pages/WebAppPages.ets new file mode 100644 index 0000000..5406dd7 --- /dev/null +++ b/entry/src/main/ets/ui/pages/WebAppPages.ets @@ -0,0 +1,708 @@ +import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"; +import { common } from "@kit.AbilityKit"; +import AppConstants from "../../app/AppConstant"; +import { createWaterMark } from "../custom/Watermark"; +import { webview } from "@kit.ArkWeb"; +import { fileIo, fileUri, picker } from "@kit.CoreFileKit"; +import { photoAccessHelper } from "@kit.MediaLibraryKit"; +import { WebUserInfoModel } from "../../model/cacheModel/UserInfoModel"; +import { RuanseeAbilityStag } from "../../app/RuanseeAbilityStag"; +import { StringUtils } from "../../util/StringUtils"; +import JiaMi from "../../util/JiaMi"; +import { H5OperationType, WebAppPageParam } from "../../model/uiModel/WebAppPageParam"; +import { SelectFileOptions } from "../../model/uiModel/SelectFileOptions"; +import { window } from "@kit.ArkUI"; +import { DialogHelper } from "@pura/harmony-dialog"; +import { call } from "@kit.TelephonyKit"; +import { StrUtil } from "@pura/harmony-utils/src/main/ets/utils/StrUtil"; +import { FileUtils } from "../../util/FileUtils"; +import { camera, cameraPicker } from "@kit.CameraKit"; +import { ImageUtil, ToastUtil } from "@pura/harmony-utils"; + +@Preview +@HMRouter({ pageUrl: 'WebAppPages' }) +@Component +export struct WebAppPages { + webController: webview.WebviewController = new webview.WebviewController(); + context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; + @State statusBarColor: string | Resource = $r('app.color.bull') + @State statusBarHeight: number = 34 + @State topBarVisible: boolean = true; + @State hmMethodInterface: HMMethodInterface = new HMMethodInterface() + @State leftImage: Resource = $r('app.media.icon_back3') + @State title: string | Resource = '' + @State currentIndex: number = 0 + /** + * 标题栏是否深色模式 + */ + @State isBlackFontColor: boolean = false + fileSelector: SelectFileOptions = new SelectFileOptions(false,true,true,true) + ///////////////// 接收参数 ////////////////// + h5AppParam:WebAppPageParam = new WebAppPageParam() + + @State loadUrl :string|Resource = $rawfile('TestJs.html') + + ///////////////////////////////// + + aboutToAppear(): void { + this.h5AppParam = HMRouterMgr.getCurrentParam() as WebAppPageParam + if (!this.h5AppParam) { + DialogHelper.showToastTip({ + message: "错误的应用参数", + imageRes: $r('app.media.icon_tips_error'), + duration: 1000, + }) + setTimeout(() => { + HMRouterMgr.pop() + }, 1200) + return + } + this.title = this.h5AppParam.appName + this.hmMethodInterface.bindComponent(this) + this.handUrl(); + setTimeout(() => { + this.webController.loadUrl(this.loadUrl) + }, 800) + } + + handUrl() { + if (StringUtils.isNullOrEmpty(this.h5AppParam!.linkUrl)){ + this.loadUrl = $rawfile('TestJs.html') + return + } + if (StringUtils.containsChar(this.h5AppParam.linkUrl,"?")){ + this.loadUrl = `${this.h5AppParam.linkUrl}&userInfo=${this.hmMethodInterface.getUserInfo()}` + }else { + this.loadUrl = `${this.h5AppParam.linkUrl}?userInfo=${this.hmMethodInterface.getUserInfo()}` + } + if(this.h5AppParam!.operationType == H5OperationType.login){ + this.loadUrl = `${this.loadUrl}?operation_type=login` + return + } + if(this.h5AppParam!.operationType == H5OperationType.readMessage){ + if(StringUtils.isNullOrEmpty(this.h5AppParam!.msgId)){ + this.loadUrl = `${this.loadUrl}?operation_type=login` + return + } + this.loadUrl = `${this.loadUrl}?operation_type=readMessage&msg_id=${StringUtils.get(this.h5AppParam!.msgId,"")}` + if (StrUtil.isNotEmpty(this.h5AppParam!.msgType)) { + this.loadUrl = `${this.loadUrl}?msg_type=${StringUtils.get(this.h5AppParam!.msgType,"")}` + } + } + if(this.h5AppParam!.operationType == H5OperationType.search){ + this.loadUrl = `${this.loadUrl}?operation_type=search&search_type=${StringUtils.get(this.h5AppParam!.searchType,"")}` + } + } + + /** + * 文件选择器 + * @param result + * @returns + */ + async selectImage(result: FileSelectorResult): Promise { + let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); + let photoPicker = new photoAccessHelper.PhotoViewPicker(); + // 过滤选择媒体文件类型为IMAGE + photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE; + // 设置最大选择数量 + photoSelectOptions.maxSelectNumber = 1; + let chooseFile: picker.PhotoSelectResult = await photoPicker.select(photoSelectOptions); + // 获取选择的文件列表 + result.handleFileList(chooseFile.photoUris); + } + + async selectFile(result: FileSelectorResult) { + console.log('MyFileUploader onShowFileSelector invoked') + const documentSelectOptions = new picker.DocumentSelectOptions(); + let uri: string | null = null; + documentSelectOptions.maxSelectNumber = 1; + const documentViewPicker = new picker.DocumentViewPicker(); + documentViewPicker.select(documentSelectOptions).then((documentSelectResult) => { + uri = documentSelectResult[0]; + console.info('documentViewPicker.select to file succeed and uri is:' + uri); + if (result) { + result.handleFileList([uri]); + } + }).catch((err: Error) => { + console.error(`Invoke documentViewPicker.select failed, code is ${err.message}, message is ${err.message}`); + }) + } + + /** + * 拍照 + */ + async takePhoto(webResult: FileSelectorResult) { + let pathDir = FileUtils.IMAGE_DIR; + let fileName = `${new Date().getTime()}.JPEG` + let filePath = `${pathDir}/${fileName}` + let imageFileUri: string | undefined = undefined; + fileIo.createRandomAccessFileSync(filePath, fileIo.OpenMode.CREATE); + + let fileUris = fileUri.getUriFromPath(filePath); + let pickerProfile: cameraPicker.PickerProfile = { + cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK, + saveUri: fileUris, + }; + let result: cameraPicker.PickerResult = + await cameraPicker.pick(getContext(), [cameraPicker.PickerMediaType.PHOTO], + pickerProfile); + console.info(`picker resultCode: ${result.resultCode},resultUri: ${result.resultUri},mediaType: ${result.mediaType}`); + if (result.resultCode == 0) { + if (result.mediaType === cameraPicker.PickerMediaType.PHOTO) { + imageFileUri = result.resultUri + imageFileUri = await ImageUtil.compressPhoto(imageFileUri, 150); + webResult.handleFileList([imageFileUri]) + } + } else { + ToastUtil.showToast("取消选择") + } + } + + showUpdatePhoto(selectItems:Array,webResult: FileSelectorResult) { + //带标题 + DialogHelper.showActionSheetDialog({ + title: "选择文件", + titleFontColor: Color.Black, + cancelFontColor: Color.Red, + cancelFontWeight: FontWeight.Normal, + sheets: selectItems, + onAction: (index) => { + let item = selectItems[index] + if(item == '相机拍摄'){ + this.takePhoto(webResult) + } + if(item == '相册选择'){ + this.selectImage(webResult) + } + if(item == '文件选择'){ + this.selectFile(webResult) + } + } + }) + } + + build() { + Column() { + Blank() + .width(AppConstants.PERCENTAGE_MAX) + .height(this.statusBarHeight) + .color(this.statusBarColor) + + this.topBar() + + this.webView() + } + .width(AppConstants.PERCENTAGE_MAX) + .height(AppConstants.PERCENTAGE_MAX) + .padding({bottom: $r('app.float.default_28')}) + .overlay(createWaterMark()) + + } + + @Builder + webView() { + //// 设置为同步渲染模式 + Web({ src: "", controller: this.webController, renderMode: RenderMode.SYNC_RENDER }) + // .layoutMode(WebLayoutMode.FIT_CONTENT)// 设置为Web组件大小自适应页面内容 + .overScrollMode(OverScrollMode.NEVER)// 设置过滚动模式为关闭状态 + .fileAccess(true) + .javaScriptAccess(true) + .layoutWeight(1) + .width(AppConstants.PERCENTAGE_MAX) + .javaScriptProxy({ + object: this.hmMethodInterface, + name: "callByAndroid", + methodList: ["isTitleBlock", "getUserInfo", "setUploadFileOptions", "onBack", "exitToHome", + "setSystemStatusBarStyle", "showNetPermission","reloadPage"], + asyncMethodList: ["asyncTest"], + controller: this.webController, + }) + .defaultFixedFontSize(14) + .defaultFontSize(14) + .minFontSize(14) + .minLogicalFontSize(13) + .mixedMode(MixedMode.All) + .zoomAccess(false) + .databaseAccess(true) + .domStorageAccess(true) + .horizontalScrollBarAccess(false)// .cacheMode(CacheMode.Online) + .copyOptions(CopyOptions.LocalDevice) + .onLoadIntercept((event) => { + if (event.data.getRequestUrl().startsWith('tel:')) { + call.makeCall(event.data.getRequestUrl().substring(4)); + return true; // 阻止默认跳转 + } + return false; + }) + .onAlert((event) => { //网页加载时弹出提示框 + if (event) { + console.log("event.url:" + event.url); + console.log("event.message:" + event.message); + AlertDialog.show({ + title: 'onAlert', + message: event.message, + primaryButton: { + value: '取消', + action: () => { + event.result.handleCancel(); + } + }, + secondaryButton: { + value: '确定', + action: () => { + event.result.handleConfirm(); + } + }, + cancel: () => { + event.result.handleCancel(); + } + }) + } + return false; + }) + .onErrorReceive((event) => { //网页加载遇到错误时触发该回调 + if (event) { + console.log('getErrorInfo:' + event.error.getErrorInfo()); + console.log('getErrorCode:' + event.error.getErrorCode()); + console.log('url:' + event.request.getRequestUrl()); + console.log('isMainFrame:' + event.request.isMainFrame()); + console.log('isRedirect:' + event.request.isRedirect()); + console.log('isRequestGesture:' + event.request.isRequestGesture()); + console.log('getRequestHeader_headerKey:' + event.request.getRequestHeader().toString()); + let result = event.request.getRequestHeader(); + console.log('The request header result size is ' + result.length); + for (let i of result) { + console.log('The request header key is : ' + i.headerKey + ', value is : ' + i.headerValue); + } + } + }) + .onDownloadStart((event) => { //通知主应用开始下载一个文件。 + if (event) { + console.log('url:' + event.url) + console.log('userAgent:' + event.userAgent) + console.log('contentDisposition:' + event.contentDisposition) + console.log('contentLength:' + event.contentLength) + console.log('mimetype:' + event.mimetype) + } + }) + .onHttpErrorReceive((event) => { //网页加载资源遇到的HTTP错误(响应码>=400)时触发该回调。 + if (event) { + console.log('url:' + event.request.getRequestUrl()); + console.log('isMainFrame:' + event.request.isMainFrame()); + console.log('isRedirect:' + event.request.isRedirect()); + console.log('isRequestGesture:' + event.request.isRequestGesture()); + console.log('getResponseData:' + event.response.getResponseData()); + console.log('getResponseEncoding:' + event.response.getResponseEncoding()); + console.log('getResponseMimeType:' + event.response.getResponseMimeType()); + console.log('getResponseCode:' + event.response.getResponseCode()); + console.log('getReasonMessage:' + event.response.getReasonMessage()); + let result = event.request.getRequestHeader(); + console.log('The request header result size is ' + result.length); + for (let i of result) { + console.log('The request header key is : ' + i.headerKey + ' , value is : ' + i.headerValue); + } + let resph = event.response.getResponseHeader(); + console.log('The response header result size is ' + resph.length); + for (let i of resph) { + console.log('The response header key is : ' + i.headerKey + ' , value is : ' + i.headerValue); + } + } + }) + .onPageBegin((event) => { //网页开始加载时触发该回调 + if (event) { + console.log('url:' + event.url); + } + }) + .onPageEnd((event) => { //网页加载完成时触发该回调 + if (event) { + console.log('url:' + event.url); + } + }) + .onProgressChange((event) => { //网页加载进度变化时触发该回调 + if (event) { + console.log('newProgress:' + event.newProgress); + } + }) + .onTitleReceive((event) => { + if (event) { + console.log('title:' + event.title); + } + }) + .onRenderExited((event) => { //应用渲染进程异常退出时触发该回调 + if (event) { + console.log('reason:' + event.renderExitReason); + } + }) + .onShowFileSelector((event) => { + if (this.fileSelector) { + if (this.fileSelector.selfRealization) { + return true + } + if (this.fileSelector.onlyOneItemIsSelected()) { + if(this.fileSelector.isCamera){ + //相机拍照 + this.takePhoto(event.result) + } + if(this.fileSelector.isFileSelection){ + //文件选择 + this.selectFile(event.result) + } + if(this.fileSelector.isDCIM){ + //图库 + this.selectImage(event.result) + } + return true; + }else { + let selectItems = new Array(); + if(this.fileSelector.isCamera) { + selectItems.push('相机拍摄') + } + if(this.fileSelector.isDCIM) { + selectItems.push('相册选择') + } + if(this.fileSelector.isFileSelection) { + selectItems.push('文件选择') + } + this.showUpdatePhoto(selectItems, event.result); + } + return true; + } + /** + * 调用此函数以处理具有“文件”输入类型的HTML表单。如果不调用此函数或返回false, + * Web组件会提供默认的“选择文件”处理界面。如果返回true,应用可以自定义“选择文件”的响应行为。 + */ + event.fileSelector.getMode() + event.fileSelector.getAcceptType() + event.fileSelector.getMimeTypes() + event.fileSelector.isCapture() + if (event.fileSelector) { + + } + return true; + }) + .onPermissionRequest((event) => { //通知收到获取权限请求 + if (event) { + AlertDialog.show({ + title: 'title', + message: 'text', + primaryButton: { + value: 'deny', + action: () => { + event.request.deny(); + } + }, + secondaryButton: { + value: 'onConfirm', + action: () => { + event.request.grant(event.request.getAccessibleResource()); + } + }, + cancel: () => { + event.request.deny(); + } + }) + } + }) + .onGeolocationShow((event) => { //通知用户收到地理位置信息获取请求。 + if (event) { + AlertDialog.show({ + title: 'title', + message: 'text', + confirm: { + value: 'onConfirm', + action: () => { + event.geolocation.invoke(event.origin, true, true); + } + }, + cancel: () => { + event.geolocation.invoke(event.origin, false, true); + } + }) + } + }) + } + + @Builder + topBar() { + Row() { + Row() { + Image(this.leftImage) + .width($r('app.float.default_24')) + .height($r('app.float.default_24')) + } + .height("100%") + .width($r('app.float.default_68')) + .alignItems(VerticalAlign.Center) + .padding({ left: $r('app.float.default_10') }) + .onTouch((event) => { + if (event.type === TouchType.Down) { + this.leftImage = $r('app.media.icon_back2'); + } else if (event.type === TouchType.Up) { + if (this.isBlackFontColor) { + this.leftImage = $r('app.media.icon_back_black'); + } else { + this.leftImage = $r('app.media.icon_back3'); + } + } + }) + .onClick(() => { + if (this.webController.accessBackward()) { + this.webController.backward() + } else { + HMRouterMgr.pop() + } + }) + + Text(this.title) + .fontColor(this.isBlackFontColor ? $r('app.color.colorGrey8') : $r('app.color.white')) + .fontSize($r('app.float.text_size_18')) + .layoutWeight(1) + .height("100%") + .textAlign(TextAlign.Center) + .align(Alignment.Center) + .margin({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10') + }) + + Row() { + Image(this.isBlackFontColor ? $r('app.media.icon_refresh_grad') : $r('app.media.icon_refresh')) + .width($r('app.float.default_24')) + .height($r('app.float.default_24')) + .onClick(() => { + this.webController.refresh() + }) + + Image(this.isBlackFontColor ? $r('app.media.icon_over_back') : $r('app.media.icon_over')) + .width($r('app.float.default_24')) + .height($r('app.float.default_24')) + .margin({ left: $r('app.float.default_5') }) + .onClick(() => { + HMRouterMgr.pop({ navigationId: 'startNavigation', pageUrl: "MainPage" }) + }) + } + .alignItems(VerticalAlign.Center) + .height("100%") + .width($r('app.float.default_68')) + .padding({ right: $r('app.float.default_10') }) + } + .alignItems(VerticalAlign.Center) + .width('100%') + .visibility(this.topBarVisible ? Visibility.Visible : Visibility.None) + .backgroundColor(this.statusBarColor) + .height($r('app.float.default_40')) + } + + hideTopBar(isShow: boolean) { + this.topBarVisible = isShow; + } + + /** + * 设置状态栏颜色 + * @param statusBarColor + */ + setStatusBarColor(statusBarColor: string) { + // 在UIAbility或UI组件中执行(需确保已获取Window对象) + let sysBarProps: window.SystemBarProperties = { + statusBarContentColor: statusBarColor, // 白色文字/图标 + statusBarColor: '#00000000' // 黑色背景 + }; + this.context.windowStage.getMainWindow() + .then((windows) => { + if (windows) { + windows.setWindowSystemBarProperties(sysBarProps) + .then(() => { + console.info('状态栏颜色修改成功'); + }) + .catch((err: Error) => { + console.error(`修改失败,信息: ${err.message}`); + }); + } + }) + .catch((err: Error) => { + console.error(`获取window失败,信息: ${err.message}`); + + }) + } + + @Builder + errorDialog(message: string, ywry: string, ywryPhone: string) { + Column() { + Text(message) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + + Row() { + Text(ywry) + .fontColor($r('app.color.colorGrey8')) + .fontSize($r('app.float.text_size_14')) + Text(ywryPhone) + .fontColor($r('app.color.bull')) + .fontSize($r('app.float.text_size_14')) + .copyOption(CopyOptions.LocalDevice) + .decoration({ + type: TextDecorationType.Underline, + color: Color.Blue, + style: TextDecorationStyle.WAVY + }) + .onClick(() => { + this.callPhone(ywryPhone) + }) + } + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Center) + .height($r('app.float.default_38')) + .width(AppConstants.PERCENTAGE_MAX) + + } + .alignItems(HorizontalAlign.Center) + .width(AppConstants.PERCENTAGE_MAX) + } + + callPhone(phone: string) { + if (!call.hasVoiceCapability()) { + console.error('设备不支持拨号功能'); + return; + } + + call.makeCall("tel:" + phone, (err: Error) => { + if (err) { + console.error(`跳转失败:${err.message}`); + } + }); + + } +} + +class HMMethodInterface { + private componentRef: WebAppPages | null = null; + + bindComponent(ref: WebAppPages) { + this.componentRef = ref; + } + + isTitleBlock(isShow: boolean) { + this.componentRef?.hideTopBar(isShow); + } + + /** + * 获取加密用户信息 + * @returns + */ + getUserInfo(): string { + let userData: WebUserInfoModel = new WebUserInfoModel(); + userData.userCode = RuanseeAbilityStag.userCache.getUserCode + userData.userName = RuanseeAbilityStag.userCache.getUserName + userData.deptName = RuanseeAbilityStag.userCache.getDeptName + userData.deptCode = RuanseeAbilityStag.userCache.getDeptCode + userData.idCardNum = RuanseeAbilityStag.userCache.getIdCardNum + let userInfo = JSON.stringify(userData) + let jmData = StringUtils.get(new JiaMi().desCrypto(userInfo,this.componentRef!.h5AppParam.appId, this.componentRef!.h5AppParam.secret), "") + console.debug("加密后数据:", jmData) + return jmData + } + + /** + * TODO 该方法不能弹出选择框,此方法是在JS调用选择文件方法之前调用的。在使用JS调选择文件时将根据此方法的配置做对应操作 + * 配置上传文件选择项。此方法再调用上传文件的事件之前调用,如果不调用则默认 selfRealization = false , 其他参数默认为 true + * 详情查看 {@link WebViewPresenter#mWebChromeClient} 的 onShowFileChooser(WebView, ValueCallback , FileChooserParams ) 方法 + * + * @param selfRealization 是否由JS自己实现文件选择上传。 + * PS: true:由JS自己实现,Android原生不做操作,不会弹出选择框,.值为false时将原生代码将拦截操作并根据下面参数配置弹出选择框。 + * @param isCamera PS:是否支持相机拍照: true = 支持相机拍照上传,false = 不支持相机拍照上传,值为false时弹出框将没有相机选项 + * @param isDCIM PS:是否支持相册选择: true = 支持相册选择上传,false = 不支持相册选择上传,值为false时弹出框将没有相册选项 + * @param isFileSelection PS:是否支持文件选择: true = 支持文件选择上传,false = 不支持文件选择上传,值为false时弹出框将没有文件选择选项 + * TODO 当且仅当 selfRealization = true && (isCamera | isDCIM | isFileSelection ) 只有一个为 true 时 将没有弹框,直接跳转对应操作 + */ + setUploadFileOptions(selfRealization: boolean, isCamera: boolean, isDCIM: boolean, isFileSelection: boolean) { + if (this.componentRef) { + if (!this.componentRef.fileSelector) { + this.componentRef.fileSelector = new SelectFileOptions(selfRealization, isCamera, isDCIM, isFileSelection); + } else { + this.componentRef.fileSelector.setConfig(selfRealization, isCamera, isDCIM, isFileSelection) + } + } + } + + /** + * 调用返回按钮 + */ + onBack() { + if (this.componentRef) { + if (this.componentRef.webController.accessBackward()) { + this.componentRef.webController.backward() + } else { + HMRouterMgr.pop() + } + } + } + + /** + * 退出到主页 + */ + exitToHome() { + HMRouterMgr.pop() + } + + /** + * 设置状态栏颜色及状态栏图标字体颜色深浅模式 + * + * @param statusBarColor 状态栏颜色 值为字符串 格式为:#ffffff + * @param isBlackFontColor 是否为 true 为黑色字体 | false 为白色字体 + */ + setSystemStatusBarStyle(statusBarColor: string, isBlackFontColor: boolean) { + if (this.componentRef) { + let effectiveColor = "#3255E3"; + if (StringUtils.strictCheckHexColor(statusBarColor)) { + effectiveColor = statusBarColor; + } + this.componentRef.statusBarColor = effectiveColor + this.componentRef.isBlackFontColor = isBlackFontColor + if (isBlackFontColor) { + this.componentRef.leftImage = $r('app.media.icon_back_black') + this.componentRef.setStatusBarColor("#000000") + // setStatusBarColor(this.context, bg, content); + } else { + this.componentRef.leftImage = $r('app.media.icon_back3') + this.componentRef.setStatusBarColor("#ffffff") + // setStatusBarColor(this.context, bg, content); + } + } + } + + /** + * 弹出提示框 + * + * @param title 提示标题 + * @param msg 提示内容 + * @param lxryName 联系人员 + * @param lxryPhone 联系电话 + */ + showNetPermission(title = "重要提醒", msg: string, lxryName: string, lxryPhone: string) { + //自定义文本内容,使用全局 @Builder 和 自定义组件 + DialogHelper.showCustomContentDialog({ + title: title, + contentBuilder: () => { + this.componentRef?.errorDialog(msg, lxryName, lxryPhone) + }, + buttons: [ + { value: '确定', fontColor: Color.Black } + ], + onAction: (action, dialogId, value) => { + if (action === -1) { + DialogHelper.closeDialog(dialogId) + HMRouterMgr.pop() + } + } + }) + } + + /** + * 刷新页面 + */ + reloadPage() { + if (this.componentRef) { + this.componentRef.webController.refresh() + } + } +} diff --git a/entry/src/main/ets/ui/view/SelectAppItem.ets b/entry/src/main/ets/ui/view/SelectAppItem.ets new file mode 100644 index 0000000..fc04a0d --- /dev/null +++ b/entry/src/main/ets/ui/view/SelectAppItem.ets @@ -0,0 +1,56 @@ +import { BASE_IMAGE_URL } from "../../app/AppCache"; +import AppConstants from "../../app/AppConstant"; +import { AppDataModel } from "../../model/resultModel/ApplicationResultModel"; + +@Component +export struct SelectAppItem { + @ObjectLink item: AppDataModel; + onSelect?: (item: AppDataModel) => void + + build() { + Row() { + Radio({ + value: 'Radio1', group: 'radioGroup', + indicatorType: RadioIndicatorType.TICK + }) + .checked(this.item.isSelect) + .height($r('app.float.default_20')) + .width($r('app.float.default_20')) + .onChange((isChecked: boolean) => { + // 只有选中时才触发选择事件,实现单选 + if (isChecked && this.onSelect) { + this.onSelect(this.item) + } + }) + + Image(BASE_IMAGE_URL+this.item.icon) + .width($r('app.float.default_24')) + .height($r('app.float.default_24')) + .margin({left: $r('app.float.default_8'), right: $r('app.float.default_5')}) + + Text(this.item.name) + .layoutWeight(1) + .fontColor(this.item.isSelect ? $r('app.color.colorBluen8') : $r('app.color.colorGrey7')) + .fontSize($r('app.float.text_size_14')) + .onClick(() => { + // 点击文本时触发选择 + if (this.onSelect) { + this.onSelect(this.item) + } + }) + } + .width(AppConstants.PERCENTAGE_MAX) + .padding({ + left: $r('app.float.default_10'), + right: $r('app.float.default_10'), + top: $r('app.float.default_6'), + bottom: $r('app.float.default_6') + }) + // 添加按压效果提升用户体验 + .useEffect(true) + .backgroundColor(this.item.isSelect + ? $r('app.color.colorBluen1') + : Color.Transparent) + + } +} \ No newline at end of file diff --git a/entry/src/main/ets/util/AppUtils.ets b/entry/src/main/ets/util/AppUtils.ets new file mode 100644 index 0000000..1073576 --- /dev/null +++ b/entry/src/main/ets/util/AppUtils.ets @@ -0,0 +1,30 @@ + + +import bundleManager from '@ohos.bundle.bundleManager'; +import { BusinessError } from '@ohos.base'; +import hilog from '@ohos.hilog'; +let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION; + +export class AppUtils { + + + async getAppList() { + try { + bundleManager.getAllBundleInfo(bundleFlags, (err, data) => { + if (err) { + hilog.error(0x0000, 'testTag', 'getAllBundleInfo failed: %{public}s', err.message); + } else { + data.forEach((bundleInfo) => { + let appInfo = bundleInfo.appInfo; + hilog.info(0x0000, 'testTag', 'appInfo: %{public}s', JSON.stringify(appInfo)); + }); + hilog.info(0x0000, 'testTag', 'getAllBundleInfo successfully: %{public}s', JSON.stringify(data)); + } + }); + } catch (err) { + let message = (err as BusinessError).message; + //onForeground + hilog.error(0x0000, 'testTag', 'getAllBundleInfo failed: %{public}s', message); + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/util/ArrayListUtils.ets b/entry/src/main/ets/util/ArrayListUtils.ets new file mode 100644 index 0000000..7c7935b --- /dev/null +++ b/entry/src/main/ets/util/ArrayListUtils.ets @@ -0,0 +1,10 @@ +import { ArrayList } from "@kit.ArkTS"; + +export class ArrayListUtils { + static contain(dataList: ArrayList, data: T): boolean { + return dataList.has(data); + } + + +} + diff --git a/entry/src/main/ets/util/BitMapUtils.ets b/entry/src/main/ets/util/BitMapUtils.ets new file mode 100644 index 0000000..8c23533 --- /dev/null +++ b/entry/src/main/ets/util/BitMapUtils.ets @@ -0,0 +1,53 @@ +import { buffer } from '@kit.ArkTS'; +import { fileIo } from '@kit.CoreFileKit'; +import { fileUri } from "@kit.CoreFileKit"; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { image } from '@kit.ImageKit'; + +export class BitMapUtils{ + + /** + * 保存图片到本地 + * @param data 图片base64 + * @param filesDir 保存目录 + * @param fileName 保存的文件名 + * @returns + */ + static async writeFile(data: string, filesDir :string,fileName:string): Promise { + let fileAbsolutelyPath ="" + try { + let filePath = filesDir+"/" + fileName; + // uri = fileUri.getUriFromPath(filePath); + fileAbsolutelyPath = filePath + let file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE); + console.info("file fd: " + file.fd); + const reg = new RegExp("data:image/\\w+;base64,") + const base64 = data.replace(reg, ""); + console.log("base64flag", base64) + const dataBuffer = buffer.from(base64, 'base64') + let writeLen = fileIo.writeSync(file.fd, dataBuffer.buffer); + hilog.info(0xA0c0d0,'文件长度',writeLen+"") + fileIo.closeSync(file); + } catch (Error) { + hilog.error(0xA0c0d0,'Error',Error.code) + } + return fileAbsolutelyPath; + } + + + static async copyPixelMap(pm: image.PixelMap): Promise { + const imageInfo: image.ImageInfo = await pm.getImageInfo(); + const buffer: ArrayBuffer = new ArrayBuffer(pm.getPixelBytesNumber()); + // TODO 知识点:通过readPixelsToBuffer实现PixelMap的深拷贝,其中readPixelsToBuffer输出为BGRA_8888 + await pm.readPixelsToBuffer(buffer); + // TODO 知识点:readPixelsToBuffer输出为BGRA_8888,此处createPixelMap需转为RGBA_8888 + const opts: image.InitializationOptions = { + editable: true, + pixelFormat: image.PixelMapFormat.RGBA_F16, + size: { height: imageInfo.size.height, width: imageInfo.size.width } + }; + return await image.createPixelMap(buffer, opts); + } + +} +// data为需要转换的base64字符串,返回沙箱路径uri \ No newline at end of file diff --git a/entry/src/main/ets/util/BufferUtil.ets b/entry/src/main/ets/util/BufferUtil.ets new file mode 100644 index 0000000..98c736b --- /dev/null +++ b/entry/src/main/ets/util/BufferUtil.ets @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { util } from '@kit.ArkTS'; + +export function bufferToString(buffer: ArrayBufferLike): string { + let textDecoder = util.TextDecoder.create('utf-8', { + ignoreBOM: true + }); + let result = textDecoder.decodeToString(new Uint8Array(buffer), { + stream: true + }); + return result; +} \ No newline at end of file diff --git a/entry/src/main/ets/util/Constant.ets b/entry/src/main/ets/util/Constant.ets new file mode 100644 index 0000000..9ff5332 --- /dev/null +++ b/entry/src/main/ets/util/Constant.ets @@ -0,0 +1,6 @@ +export class Constant{ + public static REFRESH_PULL_TO_REFRESH : string = "下拉可以刷新"; + public static REFRESH_FREE_TO_REFRESH :string = "释放立即刷新" + public static REFRESH_REFRESHING :string ="正在刷新"; + public static REFRESH_SUCCESS :string="刷新成功" +} \ No newline at end of file diff --git a/entry/src/main/ets/util/DateUtils.ts b/entry/src/main/ets/util/DateUtils.ts new file mode 100644 index 0000000..96c69de --- /dev/null +++ b/entry/src/main/ets/util/DateUtils.ts @@ -0,0 +1,371 @@ +export enum DateFormat { + //'yyyy-mm-dd' + YYYY_MM_DD, + //'yyyy-mm-dd HH:mm:ss' + YYYY_MM_DDkHHdMMdSS, + //'yyyy-mm-dd HH:mm:ss.sss' + YYYY_MM_DDkHHdMMdSSdSSS, + //yyyy/mm/dd + YYYYxMMxDD, + //yyyy/mm/dd HH:mm:ss + YYYYxMMxDDkHHdMMdSS, + //yyyy/mm/dd HH:mm:ss.sss + YYYYxMMxDDkHHdMMdSSdSSS, + //yyyy年mm月dd + YYYYnMMyDDr, + //yyyy年mm月dd日 HH:mm:ss + YYYYnMMyDDrkHHdMMdSS, + //yyyy年mm月dd日 HH:mm:ss.sss + YYYYnMMyDDrkHHdMMdSSdSSS, +} + +export class DateUtils { + static formatDateStr(nowData: Date | undefined | null, format: DateFormat | undefined | null): string { + if (nowData == null || nowData == undefined) { + nowData = new Date(); + } + //年 + let year = nowData.getFullYear() + //月 + let month = ("0" + (nowData.getMonth() + 1)).slice(-2); // 月份是从0开始计数的,所以需要加1 + //日 + let day = ("0" + nowData.getDate()).slice(-2); // 为了保证始终是两位数,不足两位前面补0 + //时 + let hours = nowData.getHours()>9?nowData.getHours():`0${nowData.getHours()}`; + //分 + let minutes = nowData.getMinutes()>9?nowData.getMinutes():`0${nowData.getMinutes()}`; + //秒 + let seconds = nowData.getSeconds()>9?nowData.getSeconds():`0${nowData.getSeconds()}`; + //毫秒 + let milliSeconds = nowData.getMilliseconds(); + if (format == null || format == undefined) { + format = DateFormat.YYYY_MM_DDkHHdMMdSS + } + if (format == DateFormat.YYYY_MM_DD) { + return year + "-" + month + "-" + day + } + if (format == DateFormat.YYYY_MM_DDkHHdMMdSS) { + return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds + } + if (format == DateFormat.YYYY_MM_DDkHHdMMdSSdSSS) { + return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds + "." + milliSeconds + } + if (format == DateFormat.YYYYxMMxDD) { + return year + "/" + month + "/" + day + } + if (format == DateFormat.YYYYxMMxDDkHHdMMdSS) { + return year + "/" + month + "/" + day + " " + hours + ":" + minutes + ":" + seconds + } + if (format == DateFormat.YYYYxMMxDDkHHdMMdSSdSSS) { + return year + "/" + month + "/" + day + " " + hours + ":" + minutes + ":" + seconds + "." + milliSeconds + } + if (format == DateFormat.YYYYnMMyDDr) { + return year + "年" + month + "月" + day + "日" + } + if (format == DateFormat.YYYYnMMyDDrkHHdMMdSS) { + return year + "年" + month + "月" + day + "日 " + hours + ":" + minutes + ":" + seconds + } + if (format == DateFormat.YYYYnMMyDDrkHHdMMdSSdSSS) { + return year + "年" + month + "月" + day + "日 " + hours + ":" + minutes + ":" + seconds + "." + milliSeconds + } + return year + "-" + month + "-" + day + } + + static pastStrDate(strDate: string | null): Date | null { + if (strDate == null) { + return null; + } + let formatting = strDate.trim() + // .replaceAll(' ', '') + // .replace(' ', '') + // .replaceAll('-', "") + // .replace('-', "") + // .replaceAll('.', "") + // .replace('.', "") + // .replaceAll('/', "") + // .replace('/', "") + // .replace('年', "") + // .replace('月', "") + // .replace('日', "") + // .replaceAll(':', "") + // .replace(':', "") + // .replaceAll('—', "") + // .replace('—', "") + // .replaceAll(':', "") + // .replace(':', "") + // .replaceAll('。', "") + // .replace('。', "") + // .trim() + + let f = new Array(); + for (let i = 0; i < formatting.length; i++) { + let s = formatting.charAt(i); + if (!this.isNum(s)) { + f.push(s) + } + } + + for (let i = 0; i < f.length; i++) { + formatting = formatting.replace(f[i], "") + } + + switch (formatting.length) { + case 4: + return new Date(formatting) + case 6: //202306 + let y = formatting.substring(0, 4) + let m = formatting.substring(4, 6) + return new Date(y + "-" + m) + case 8: //20230612 + y = formatting.substring(0, 4) + m = formatting.substring(4, 6) + let d = formatting.substring(6, 8) + return new Date(y + "-" + m + "-" + d) + case 10: //2023061211 + y = formatting.substring(0, 4) + m = formatting.substring(4, 6) + d = formatting.substring(6, 8) + let h = formatting.substring(8, 10) + return new Date(y + "-" + m + "-" + d + " " + h) + case 12: //2023061211 + y = formatting.substring(0, 4) + m = formatting.substring(4, 6) + d = formatting.substring(6, 8) + h = formatting.substring(8, 10) + let f = formatting.substring(10, 12) + return new Date(y + "-" + m + "-" + d + " " + h + ":" + f) + case 14: //20230612101533 + y = formatting.substring(0, 4) + m = formatting.substring(4, 6) + d = formatting.substring(6, 8) + h = formatting.substring(8, 10) + f = formatting.substring(10, 12) + let ms = formatting.substring(12, 14) + return new Date(y + "-" + m + "-" + d + " " + h + ":" + f + ":" + ms) + case 17: //20230612101533333 + y = formatting.substring(0, 4) + m = formatting.substring(4, 6) + d = formatting.substring(6, 8) + h = formatting.substring(8, 10) + f = formatting.substring(10, 12) + ms = formatting.substring(12, 14) + let hms = formatting.substring(14, 17) + return new Date(y + "-" + m + "-" + d + " " + h + ":" + f + ":" + ms + '.' + hms) + default : + return null + } + } + + /** + * 将 "M/D/YY, h:mm A" 时间格式字符 转换成 "yyyy-MM-dd HH:mm:ss" + * @param dateStr 8/12/25, 3:23 PM + * @returns 2025-08-12 15:23:00 + */ + static formatMdyHmA(dateStr: string): string { + if (dateStr == null||dateStr == undefined ||dateStr.toString().trim().length<1) { + return ""; + } + // 解析原始时间字符串 + const [datePart, timePart] = dateStr.split(", "); + const [month, day, year] = datePart.split("/").map(Number); + const [time, period] = timePart.split(" "); + const [hoursStr, minutesStr] = time.split(":"); + let hours = parseInt(hoursStr, 10); + const minutes = parseInt(minutesStr, 10); + + // 处理 AM/PM + if (period === "PM" && hours < 12) hours += 12; + if (period === "AM" && hours === 12) hours = 0; + + // 补零操作 + const pad = (num: number) => num.toString().padStart(2, "0"); + return "yyyy-MM-dd HH:mm:ss" + .replace("yyyy", `${2000 + year}`) // 假设年份简写为后两位(如25表示2025) + .replace("MM", pad(month)) + .replace("dd", pad(day)) + .replace("HH", pad(hours)) + .replace("mm", pad(minutes)) + .replace("ss", "00"); // 秒数未提供,默认补零 + } + + /** + * 数字验证 + * + * @param val 需要验证的字符串 + */ + public static isNum(val: string): boolean { + const reg = new RegExp('^[0-9]*$'); + return val != null && "" != (val) && reg.test(val); + } + + /** + * 获取日期字符 + * @param nowData 日期 + * @returns yyyy-MM-dd + */ + static getNowDats(nowData: Date | null): string { + if (!nowData) { + nowData = new Date(); + } + let year = nowData.getFullYear() + let month = ("0" + (nowData.getMonth() + 1)).slice(-2); // 月份是从0开始计数的,所以需要加1 + let day = ("0" + nowData.getDate()).slice(-2); // 为了保证始终是两位数,不足两位前面补0 + return year + "-" + month + "-" + day + } + + /** + * 当获取指定日期工作周的第一天 + * @param nowData + * @returns yyyy-MM-dd + */ + static getWeekFirstDay(nowData: Date | null): string { + if (!nowData) { + nowData = new Date(); + } + const currentDay = nowData.getDay(); // 0(星期日)到 6(星期六) + let firstDay = new Date() + firstDay.setDate(nowData.getDate() - currentDay + 1) + + return firstDay.getFullYear() + "-" + ("0" + (firstDay.getMonth() + 1)).slice(-2) + "-" + + ("0" + firstDay.getDate()).slice(-2); + } + + /** + * 当获取指定日期工作周的最后一天时间 + * @param nowData + * @returns yyyy-MM-dd + */ + static getWeekLastDay(nowData: Date | null): string { + if (!nowData) { + nowData = new Date(); + } + const currentDay = nowData.getDay(); // 0(星期日)到 6(星期六) + let lastDay = new Date() + lastDay.setDate(nowData.getDate() + (6 - currentDay + 1)) + + return lastDay.getFullYear() + "-" + ("0" + (lastDay.getMonth() + 1)).slice(-2) + "-" + + ("0" + lastDay.getDate()).slice(-2); + + } + + /** + * 获取指定日期所在月份的最后一天 + * @param nowData + * @returns yyyy-MM-dd + */ + static getLastDayOfMonth(nowData: Date | null): string { + if (!nowData) { + nowData = new Date(); + } + let year = nowData.getFullYear(); // 获取当前年份 + let month = nowData.getMonth(); // 获取当前月份(从0开始) + // 创建一个表示当前月份最后一天的Date对象 + let lastDayOfMonth = new Date(year, month + 1, 0); + return lastDayOfMonth.getFullYear() + "-" + ("0" + (lastDayOfMonth.getMonth() + 1)).slice(-2) + "-" + + ("0" + lastDayOfMonth.getDate()).slice(-2); + } + + /** + * 获取当前日期是第几周 + * @param dateTime 当前传入的日期值 + * @returns 返回第几周数字值 + */ + static getWeek(dateTime: Date): number { + const temptTime = new Date(dateTime); + const weekday = temptTime.getDay() || 7; // 周几 (0-6,0代表星期天) + + // 调整日期到上周一 + temptTime.setDate(temptTime.getDate() - weekday + 1); + const firstDay = new Date(temptTime.getFullYear(), 0, 1); + + // 获取第一周的第一天 + const dayOfWeek = firstDay.getDay(); + const spendDay = dayOfWeek === 0 ? 7 : 7 - dayOfWeek + 1; + + // 计算周数 + const startOfYear = new Date(temptTime.getFullYear(), 0, 1 + spendDay); + const days = Math.ceil((temptTime.getTime() - startOfYear.getTime()) / 86400000); + return Math.ceil(days / 7); + } + + /** + * 将时间转换为 `几秒前`、`几分钟前`、`几小时前`、`几天前` + * @param param 当前时间,new Date() 格式或者字符串时间格式 + * @param format 需要转换的时间格式字符串 + * @returns 返回拼接后的时间字符串 + */ + static formatPast(param: string | Date, format: string = 'YYYY-mm-dd'): string { + const time = new Date().getTime(); + let t = typeof param === 'string' || param instanceof Date ? new Date(param).getTime() : param; + const diff = time - t; + + if (diff < 10000) { + return '刚刚'; + } // 10秒内 + if (diff < 60000) { + return `${Math.floor(diff / 1000)}秒前`; + } // 少于1分钟 + if (diff < 3600000) { + return `${Math.floor(diff / 60000)}分钟前`; + } // 少于1小时 + if (diff < 86400000) { + return `${Math.floor(diff / 3600000)}小时前`; + } // 少于24小时 + if (diff < 259200000) { + return `${Math.floor(diff / 86400000)}天前`; + } // 少于3天 + + return DateUtils.formatDate(new Date(param), format); // 超过3天 + } + + /** + * 时间日期转换 + * @param date 当前时间,new Date() 格式 + * @param format 需要转换的时间格式字符串 + * @returns 返回拼接后的时间字符串 + */ + static formatDate(date: Date, format: string): string { + const week: { [key: string]: string } = { + '0': '日', + '1': '一', + '2': '二', + '3': '三', + '4': '四', + '5': '五', + '6': '六', + }; + const quarter: { [key: string]: string } = { + '1': '一', + '2': '二', + '3': '三', + '4': '四' + }; + + const we = date.getDay(); // 星期 + const z = DateUtils.getWeek(date); // 周 + const qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 季度 + + const opt: { [key: string]: string } = { + 'Y+': date.getFullYear().toString(), + 'm+': (date.getMonth() + 1).toString(), + 'd+': date.getDate().toString(), + 'H+': date.getHours().toString(), + 'M+': date.getMinutes().toString(), + 'S+': date.getSeconds().toString(), + 'q+': quarter[qut], // 季度 + }; + + // 处理格式中的特殊标记 + format = format.replace(/(W+)/, (match) => match.length > 1 ? `周${week[we]}` : week[we]); + format = format.replace(/(Q+)/, (match) => match.length === 4 ? `第${quarter[qut]}季度` : quarter[qut]); + format = format.replace(/(Z+)/, (match) => match.length === 3 ? `第${z}周` : `${z}`); + + // 替换日期格式中的部分 + Object.keys(opt).forEach((key) => { + const reg = new RegExp(`(${key})`); + format = format.replace(reg, (match) => match.length === 1 ? opt[key] : opt[key].padStart(match.length, '0')); + }); + + return format; + } +} \ No newline at end of file diff --git a/entry/src/main/ets/util/FileMd5Utils.ets b/entry/src/main/ets/util/FileMd5Utils.ets new file mode 100644 index 0000000..b1f9b92 --- /dev/null +++ b/entry/src/main/ets/util/FileMd5Utils.ets @@ -0,0 +1,110 @@ +import { common } from "@kit.AbilityKit"; +import { OpenFiles } from "./OpenFiles"; +import { filePreview } from "@kit.PreviewKit"; +import { fileUri } from "@kit.CoreFileKit"; + +const MineType: Record = { + 'txt': 'text/plain', + 'cpp': 'text/x-c++src', + 'c': 'text/x-csrc', + 'h': 'text/x-chdr', + 'java': 'text/x-java', + 'xhtml': 'application/xhtml+xml', + 'xml': 'text/xml', + 'html': 'text/html', + 'htm': 'text/html', + 'jpg': 'image/jpeg', + 'png': 'image/png', + 'gif': 'image/gif', + 'webp': 'image/webp', + 'bmp': 'image/bmp', + 'svg': 'image/svg+xml', + 'm4a': 'audio/mp4a-latm', + 'aac': 'audio/aac', + 'mp3': 'audio/mpeg', + 'ogg': 'audio/ogg', + 'wav': 'audio/x-wav', + 'mp4': 'video/mp4', + 'mkv': 'video/x-matroska', + 'ts': 'video/mp2ts', + 'pdf': 'application/pdf', + 'doc': 'application/msword', + 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'xls': 'application/vnd.ms-excel', + 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'ppt': 'application/vnd.ms-powerpoint', + 'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'csv': 'text/comma-separated-values', +} + +export class FileMd5Utils { + static openFile(context: common.UIAbilityContext, fileName: string, filePath: string) { + if (FileMd5Utils.checkEndsWithInStringArray(fileName, ['.png', '.gif', '.jpg', '.jpeg', '.bmp'])) { + context.startAbility(OpenFiles.getImageFileIntent(FileMd5Utils.getUriFromPath(filePath))) + } else if (FileMd5Utils.checkEndsWithInStringArray(fileName, ['.htm', '.html', '.php', '.jsp'])) { + context.startAbility(OpenFiles.getHtmlFileIntent(FileMd5Utils.getUriFromPath(filePath))) + } else if (FileMd5Utils.checkEndsWithInStringArray(fileName, ['.jar', '.zip', '.rar', '.gz', '.img'])) { + context.startAbility(OpenFiles.getApkFileIntent(FileMd5Utils.getUriFromPath(filePath))) + } else if (FileMd5Utils.checkEndsWithInStringArray(fileName, ['.mp3', '.wav', '.ogg', '.midi'])) { + context.startAbility(OpenFiles.getAudioFileIntent(FileMd5Utils.getUriFromPath(filePath))) + } else if (FileMd5Utils.checkEndsWithInStringArray(fileName, ['.mp4', '.rmvb', '.avi', '.flv'])) { + context.startAbility(OpenFiles.getVideoFileIntent(FileMd5Utils.getUriFromPath(filePath))) + } else if (FileMd5Utils.checkEndsWithInStringArray(fileName, ['.txt','.java','.c','.cpp','.py','.xml','.json','.log'])) { + context.startAbility(OpenFiles.getTextFileIntent(FileMd5Utils.getUriFromPath(filePath))) + } else if (FileMd5Utils.checkEndsWithInStringArray(fileName, ['.pdf'])) { + context.startAbility(OpenFiles.getPdfFileIntent(FileMd5Utils.getUriFromPath(filePath))) + } else if (FileMd5Utils.checkEndsWithInStringArray(fileName, ['.doc', '.docx'])) { + context.startAbility(OpenFiles.getWordFileWant(FileMd5Utils.getUriFromPath(filePath))) + } else if (FileMd5Utils.checkEndsWithInStringArray(fileName, ['.xls', '.xlsx'])) { + context.startAbility(OpenFiles.getExcelFileIntent(FileMd5Utils.getUriFromPath(filePath))) + } else if (FileMd5Utils.checkEndsWithInStringArray(fileName, ['.ppt', '.pptx'])) { + context.startAbility(OpenFiles.getPPTFileIntent(FileMd5Utils.getUriFromPath(filePath))) + } else { + return false; + } + return true; + } + + /** + * 检查文件后缀 + * + * @param checkItsEnd + * @param fileEndings + * @return + */ + static checkEndsWithInStringArray(checkItsEnd: string, fileEndings: string[]): boolean { + for (let i = 0; i < fileEndings.length; i++) { + if (checkItsEnd.endsWith(fileEndings[i])) { + return true; + } + } + return false; + } + + /** + * 获取文件的资源路径 + * @param filePath 文件路径 + * @returns file://开头的系统资源路径 + */ + static getUriFromPath(filePath: string) { + if (filePath.startsWith('file:')) { + return filePath; + } + return fileUri.getUriFromPath(filePath); + } + + static openPreview(context: Context, fileName: string, filePath: string) { + let fileInfo: filePreview.PreviewInfo = { + title: fileName, + uri: fileUri.getUriFromPath(filePath), + mimeType: FileMd5Utils.getMimeType(fileName) + }; + + return filePreview.openPreview(context, fileInfo); + } + + static getMimeType(fileName: string) { + const fileType: string = fileName.substring(fileName.lastIndexOf('.') + 1) + return MineType[fileType] || '' + } +} \ No newline at end of file diff --git a/entry/src/main/ets/util/FileUtils.ets b/entry/src/main/ets/util/FileUtils.ets new file mode 100644 index 0000000..d056c44 --- /dev/null +++ b/entry/src/main/ets/util/FileUtils.ets @@ -0,0 +1,96 @@ +import { FileUtil } from "@pura/harmony-utils"; +import fs from '@ohos.file.fs'; +import { common } from "@kit.AbilityKit"; +import { uniformTypeDescriptor } from '@kit.ArkData'; +import { FileMd5Utils } from "./FileMd5Utils"; + +export class FileUtils { + public static ROOT_DIR: string + public static ID_CARD_DIR: string + public static FILE_DIR: string + public static IMAGE_DIR: string + public static LOG_DIR: string + + constructor() { + } + + /** + * 初始化应用路径 + * @param uiContext + */ + public static init(context: Context) { + if (context) { + FileUtils.ROOT_DIR = context.filesDir; + FileUtils.ID_CARD_DIR = context.filesDir + "/IdCardPhoto"; + FileUtils.FILE_DIR = context.filesDir + "/File"; + FileUtils.IMAGE_DIR = context.filesDir + "/Image"; + FileUtils.LOG_DIR = context.filesDir + "/Log"; + } + } + + public static createFileDir() { + if (!FileUtil.accessSync(FileUtils.ID_CARD_DIR)) { + FileUtil.mkdirSync(FileUtils.ID_CARD_DIR) + } + if (!FileUtil.accessSync(FileUtils.FILE_DIR)) { + FileUtil.mkdirSync(FileUtils.FILE_DIR) + } + if (!FileUtil.accessSync(FileUtils.IMAGE_DIR)) { + FileUtil.mkdirSync(FileUtils.IMAGE_DIR) + } + if (!FileUtil.accessSync(FileUtils.LOG_DIR)) { + FileUtil.mkdirSync(FileUtils.LOG_DIR) + } + } + + + public static async copyToLocal(src: string, dest: string): Promise { + // 创建目标路径(示例使用应用缓存目录) + try { + // 打开输入输出流 + let srcFile = await fs.open(src, fs.OpenMode.READ_ONLY); + let destFile = await fs.open(dest, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); + + // 执行复制操作 + await fs.copyFile(srcFile.fd, destFile.fd); + + fs.closeSync(srcFile.fd) + fs.closeSync(destFile.fd) + return true + // 关闭文件描述符 + } catch (err) { + console.error(`文件复制失败: ${err.code}, ${err.message}`); + return false + } + } + + private static MATCH_ARRAY: string[][] = [ + ["docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"], + [".", "application/msword"], + ["xls", "application/vnd.ms-excel"], + ["xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"], + ["ppt", "application/vnd.ms-powerpoint"], + ["pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"], + ["zip", "application/zip"], + ["txt", "text/plain"], + ["jpg", "image/jpeg"], + ["jpeg", "image/jpeg"], + ["png", "image/png"], + ["gif", "image/gif"], + ["mp3", "audio/mpeg"], + ["mp4", "video/mp4"], + ["m4u", "video/vnd.mpegurl"], + ["m4v", "video/x-m4v"], + ["avi", "video/x-msvideo"], + ["pdf", "application/pdf"], + ] + + static async openWithThirdPartyApp(context: common.UIAbilityContext, filePath: string) { + // let fileExt = FileUtil.getFileExtention(filePath) + // let fileUri = FileUtil.getFileUri(filePath).toString(); + + FileMd5Utils.openFile(context, FileUtil.getFileName(filePath), filePath) + return + + } +} \ No newline at end of file diff --git a/entry/src/main/ets/util/IdCardNumUtils.ets b/entry/src/main/ets/util/IdCardNumUtils.ets new file mode 100644 index 0000000..5fada6e --- /dev/null +++ b/entry/src/main/ets/util/IdCardNumUtils.ets @@ -0,0 +1,143 @@ +import { StringUtils } from "./StringUtils"; + +export class IdCardNumUtils { + /** + * 验证身份证号 + * @param idCardNum 身份证号 + * @returns true or false + */ + public static validateIdCardNum(idCardNum: string): boolean { + if (idCardNum == null) { + return false; + } + let idCardNumS = idCardNum.trim(); + if (idCardNumS.length != 18) { + return false; + } + if (!IdCardNumUtils.checkCode(idCardNumS)) { + return false + } + const date = idCardNumS.substring(6, 14) + if (!IdCardNumUtils.checkDate(date)) { + return false + } + if (IdCardNumUtils.checkProv(idCardNumS.substring(0, 2))) { + return true + } + + return false; + } + + /** + * 数字验证 + * + * @param val 需要验证的字符串 + */ + public static isNum(val: string): boolean { + const reg = new RegExp('^[0-9]*$'); + return val != null && "" != (val) && reg.test(val); + } + + // 省份 + public static checkProv(val: string) { + const pattern = /^[1-9][0-9]/ + const provs: Record = { + 11: '北京', + 12: '天津', + 13: '河北', + 14: '山西', + 15: '内蒙古', + 21: '辽宁', + 22: '吉林', + 23: '黑龙江 ', + 31: '上海', + 32: '江苏', + 33: '浙江', + 34: '安徽', + 35: '福建', + 36: '江西', + 37: '山东', + 41: '河南', + 42: '湖北 ', + 43: '湖南', + 44: '广东', + 45: '广西', + 46: '海南', + 50: '重庆', + 51: '四川', + 52: '贵州', + 53: '云南', + 54: '西藏 ', + 61: '陕西', + 62: '甘肃', + 63: '青海', + 64: '宁夏', + 65: '新疆', + 71: '台湾', + 81: '香港', + 82: '澳门' + } + if (pattern.test(val)) { + if (provs[val]) { + return true + } + } + return false + } + + // 出生日期 + private static checkDate(val: string) { + const pattern = + /^(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)$/ + if (pattern.test(val)) { + const year = val.substring(0, 4) + const month = val.substring(4, 6) + const date = val.substring(6, 8) + const date2 = new Date(year + '-' + month + '-' + date) + if (date2 && date2.getMonth() === parseInt(month) - 1) { + return true + } + } + return false + } + + // 校验码校验 + private static checkCode(val: string) { + const p = + /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/ + const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] + const parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2] + const code = val.substring(17) + if (p.test(val)) { + let sum = 0 + for (let i = 0; i < 17; i++) { + sum += Number(val.charAt(i)) * factor[i] + } + if (parity[sum % 11].toString() === code.toUpperCase()) { + return true + } + } + return false + } + + + + public static isCarNumberNO(carNumber: string): boolean { + if (StringUtils.isNullOrEmpty(carNumber)) { + return false; + } + //两车同用 + const carTreg = + /^([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[a-zA-Z](([ADF]((?![IO])[a-zA-Z0-9](?![IO]))[0-9]{4})|([0-9]{5}[ADF]))|[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1})$/ + return carTreg.test(carNumber); + } + + //简称 + public static isJc(cph: string): boolean { + if (StringUtils.isNullOrEmpty(cph)) { + return false; + } + const ss = /^[A-Z]$/; + return ss.test(cph); + } +} \ No newline at end of file diff --git a/entry/src/main/ets/util/IdGeneratedUtils.ets b/entry/src/main/ets/util/IdGeneratedUtils.ets new file mode 100644 index 0000000..95a93f1 --- /dev/null +++ b/entry/src/main/ets/util/IdGeneratedUtils.ets @@ -0,0 +1,36 @@ +import { util } from "@kit.ArkTS"; +import { StrUtil } from "@pura/harmony-utils/src/main/ets/utils/StrUtil"; + +export class IdGeneratedUtils { + private static idGeneratedUtils = new IdGeneratedUtils(""); + private static idCardNum: string = ""; + + private constructor(idCardNum: string) { + IdGeneratedUtils.idCardNum = idCardNum + } + + public static getInstance(idCardNum: string): IdGeneratedUtils { + if (IdGeneratedUtils.idGeneratedUtils == null || IdGeneratedUtils.idCardNum !== idCardNum) { + IdGeneratedUtils.idGeneratedUtils = new IdGeneratedUtils(idCardNum) + } + return IdGeneratedUtils.idGeneratedUtils; + } + + public generatedRandomID(): string { + let uuid = util.generateRandomUUID(false).replaceAll("-", "").replaceAll("-", ""); + if (StrUtil.isNotEmpty(IdGeneratedUtils.idCardNum)) { + let start = IdGeneratedUtils.idCardNum.substring(0, IdGeneratedUtils.idCardNum.length - 1); + let end = IdGeneratedUtils.idCardNum.substring(IdGeneratedUtils.idCardNum.length - 1); + let startStr = parseInt(start).toString(16).toUpperCase() + return startStr + end + uuid + (this.getRandomInt(1,1000) + 1000); + }else { + return Date.now()+uuid+ (this.getRandomInt(1,1000) + 1000); + } + } + + // 生成指定范围的随机整数 + getRandomInt(min: number, max: number): number { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + +} \ No newline at end of file diff --git a/entry/src/main/ets/util/JiaMi.ets b/entry/src/main/ets/util/JiaMi.ets new file mode 100644 index 0000000..c81163c --- /dev/null +++ b/entry/src/main/ets/util/JiaMi.ets @@ -0,0 +1,108 @@ +import { CryptoJS } from '@ohos/crypto-js' +import { buffer, util } from '@kit.ArkTS'; + +/** + * DES 加密工具类(ArkTS 版本) + */ +class JiaMi { + /** + * 使用 key 对 data 进行 DES 加密,并返回 Base64 编码字符串 + * @param data 待加密的字符串(UTF-8) + * @param id 用户ID + * @param secret 密钥 + * @returns Base64 编码的加密字符串,失败返回 null + */ + desCrypto(data: string, id: string, secret: string): string | null { + const key = `${id}:${secret}`; + return this.desCryptoWithKey(data, key); + } + + /** + * 使用指定 key 对 data 进行 DES 加密 + * @param data 待加密的字符串 + * @param key 密钥字符串 + * @returns Base64 编码的加密字符串,失败返回 null + */ + desCryptoWithKey(data: string, key: string) { + const keyHex = CryptoJS.enc.Utf8.parse(key); + const encrypted = CryptoJS.DES.encrypt(data, keyHex, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }); + return encrypted.toString(); // 默认就是 Base64 + + + + let new_key = CryptoJS.enc.Utf8.parse(key); + // let iv:CryptoJS.lib.WordArray = CryptoJS.lib.WordArray.create(uintArray) + let encryptd = CryptoJS.DES.encrypt(data, new_key, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7, + // iv:iv + }) + + let words = encryptd.ciphertext; + let sigBytes = words.sigBytes; + let uint8Array = new Uint8Array(sigBytes); + + for (let i = 0; i < sigBytes; i++) { + uint8Array[i] = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + } + + return new util.Base64Helper().encodeToStringSync(uint8Array) + // let jiMw = new util.Base64Helper().decodeSync(jiemiDa) + return encryptd.toString(); + } + + /** + * DES 解密(Base64 输入,返回字符串) + * @param encryptData Base64 编码的密文 03962723612 + * @param key 密钥 + * @returns 明文字符串 + * @throws 错误信息 + */ + decrypt(encryptData: string, key: string): string { + let new_key = CryptoJS.enc.Utf8.parse(key); + let uintArray = new Uint8Array([1,2,3,4,5,6,7,8]) + let iv:CryptoJS.lib.WordArray = CryptoJS.lib.WordArray.create(uintArray) + let bytes = CryptoJS.DES.decrypt(encryptData, new_key, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7, + // iv:iv + }) + let result = bytes.toString(CryptoJS.enc.Utf8); + return result.toString(); + } + + /** + * 使用 id 和 secret 解密 + * @param encryptData Base64 密文 + * @param id 用户ID + * @param secret 密钥 + * @returns 明文字符串 + * @throws 错误信息 + */ + decryptWithId(encryptData: string, id: string, secret: string): string { + const key = `${id}:${secret}`; + return this.decrypt(encryptData, key); + } + + /** + * 辅助函数:将密钥补全或截断为 8 字节(DES 要求) + * @param key 原始密钥字符串 + * @returns 8 字节长度的字符串 + */ + private static padKeyTo8Bytes(key: string): string { + let keyStr = key; + if (keyStr.length < 8) { + // 不足8字节,补空格(或可改为补0或其他) + keyStr = keyStr.padEnd(8, ' '); + } else if (keyStr.length > 8) { + // 超过8字节,截断 + keyStr = keyStr.substring(0, 8); + } + return keyStr; + } +} + +export default JiaMi; \ No newline at end of file diff --git a/entry/src/main/ets/util/OpenFiles.ets b/entry/src/main/ets/util/OpenFiles.ets new file mode 100644 index 0000000..78e6896 --- /dev/null +++ b/entry/src/main/ets/util/OpenFiles.ets @@ -0,0 +1,93 @@ +import { Want, wantConstant } from "@kit.AbilityKit"; + +export class OpenFiles { + static getWordFileWant(filePath: string) { + let wantInfo: Want = { + uri: filePath, + type: 'application/msword', + flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + } + return wantInfo + } + + static getPdfFileIntent(filePath: string) { + let wantInfo: Want = { + uri: filePath, + type: 'application/pdf', + flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + } + return wantInfo + } + + static getHtmlFileIntent(filePath: string) { + let wantInfo: Want = { + uri: filePath, + type: 'text/html', + flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + } + return wantInfo + } + + static getApkFileIntent(filePath: string) { + let wantInfo: Want = { + uri: filePath, + type: 'application/x-rar-compressed', + flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + } + return wantInfo + } + + static getAudioFileIntent(filePath: string) { + let wantInfo: Want = { + uri: filePath, + type: 'audio/mpeg', + flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + } + return wantInfo + } + + static getVideoFileIntent(filePath: string) { + let wantInfo: Want = { + uri: filePath, + type: 'video/mp4', + flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + } + return wantInfo + } + + static getTextFileIntent(filePath: string) { + let wantInfo: Want = { + uri: filePath, + type: 'text/plain', + flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + } + return wantInfo + } + + static getExcelFileIntent(filePath: string) { + let wantInfo: Want = { + uri: filePath, + type: 'application/vnd.ms-excel', + flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + } + return wantInfo + } + + static getPPTFileIntent(filePath: string) { + let wantInfo: Want = { + uri: filePath, + type: 'application/vnd.ms-powerpoint', + flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + } + return wantInfo + } + + static getImageFileIntent(filePath: string) { + let wantInfo: Want = { + uri: filePath, + type: 'image/jpeg', + flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + } + return wantInfo + } +} \ No newline at end of file diff --git a/entry/src/main/ets/util/PixelMapUtils.ets b/entry/src/main/ets/util/PixelMapUtils.ets new file mode 100644 index 0000000..0aa35fe --- /dev/null +++ b/entry/src/main/ets/util/PixelMapUtils.ets @@ -0,0 +1,26 @@ +import image from '@ohos.multimedia.image'; +import buffer from '@ohos.buffer'; + +export class PixelMapUtils { + static async pixelMapToBase64(pixelMap: image.PixelMap): Promise { + // 1. 创建图像打包器 + const imagePacker = image.createImagePacker(); + + // 2. 设置打包选项 (PNG格式) + const packOpts: image.PackingOption = { + format: "image/png", + quality: 100 // 最高质量 + }; + + // 3. 打包到内存缓冲区 + const arrayBuffer = await imagePacker.packing(pixelMap, packOpts); + + // 4. 转换为Base64 + const base64Data = buffer.from(arrayBuffer).toString('base64'); + + // 5. 添加Data URL前缀 + return base64Data; + } + + +} \ No newline at end of file diff --git a/entry/src/main/ets/util/ReadLocationAppUtils.ets b/entry/src/main/ets/util/ReadLocationAppUtils.ets new file mode 100644 index 0000000..2ae8d00 --- /dev/null +++ b/entry/src/main/ets/util/ReadLocationAppUtils.ets @@ -0,0 +1,21 @@ +import { bundleManager } from "@kit.AbilityKit"; + +export class ReadLocationAppUtils { + + // 获取所有已安装的应用包信息 + // async getAllApplications() { + // try { + // const bundleInfos = await bundleManager.getAllBundleInfo(bundleManager.BundleFlag.GET_BUNDLE_DEFAULT); + // console.log('Installed applications:', bundleInfos); + // + // // 遍历应用信息 + // bundleInfos.forEach(bundleInfo => { + // console.log('Bundle Name:', bundleInfo.name); + // console.log('Bundle Label:', bundleInfo.label); + // console.log('Version Code:', bundleInfo.versionCode); + // }); + // } catch (error) { + // console.error('Failed to get bundle info:', error); + // } + // } +} \ No newline at end of file diff --git a/entry/src/main/ets/util/StatusIconUtils.ets b/entry/src/main/ets/util/StatusIconUtils.ets new file mode 100644 index 0000000..a7de033 --- /dev/null +++ b/entry/src/main/ets/util/StatusIconUtils.ets @@ -0,0 +1 @@ +import { StringUtils } from "./StringUtils" diff --git a/entry/src/main/ets/util/StringUtils.ets b/entry/src/main/ets/util/StringUtils.ets new file mode 100644 index 0000000..d3867d8 --- /dev/null +++ b/entry/src/main/ets/util/StringUtils.ets @@ -0,0 +1,192 @@ +import { resourceManager } from "@kit.LocalizationKit"; +import { IdCardNumUtils } from "./IdCardNumUtils"; + +export class StringUtils { + /** + * 获取字符串, 如果为空则返回默认值, 如果非空则返回该值并拼接endStr到末尾 + * @param value 要获取的字符串 + * @param defValue 默认值 + * @param endStr 要拼接的字符串 + * @returns value+endStr || defValue + */ + static get(value: string | Object | undefined | null, defValue: string, endStr?: string): string { + if (StringUtils.isNullOrEmpty(value)) { + return defValue; + } + if (endStr) { + return String(value) + endStr; + } + return String(value); + } + + /** + * 判断值是否为空 + * @param value + * @returns + */ + static isNullOrEmpty(value: string | Object | undefined | null): boolean { + return value == null || value == undefined || value.toString().trim().length < 1; + } + + /** + * 获取数字, 如果为空或者不是数字类型的字符则返回默认值, 如果是number或者数字字符串者返回该值的number值 + * @param value 要获取的字符串 + * @param defValue 默认值 + * @returns value|| defValue + */ + static getNumber(value: string | number | null | undefined, defValue: number = 0): number { + // 处理空值和未定义情况 + if (value === null || value === undefined) { + return defValue; + } + // 处理数字类型直接返回 + if (typeof value === 'number') { + return value; + } + // 处理字符串类型 + if (typeof value === 'string') { + // 去除首尾空格 + const trimmedValue = value.trim(); + + // 正则验证数字格式(包含整数、小数、科学计数法) + const isNumeric = /^[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?$/.test(trimmedValue); + + // 有效数字则进行转换 + if (isNumeric) { + const numberValue = Number(trimmedValue); + return Number.isNaN(numberValue) ? defValue : numberValue; + } + } + // 非数字类型返回默认值 + return defValue; + } + + /** + * + * @param str 待查找源字符串 + * @param char 待匹配的目标 + * @returns true 表示包含 false 表示不包含 + */ + static containsChar(str: string, char: string): boolean { + //当 str 内含有 char 则返回 char所在位置索引 即 返回值大与 -1 + return str.indexOf(char) > -1; + } + + /** + * 去除JSON字符串 转义字符 + * @param value 需要转译的字符 + * @return 转译后的JSON格式数据 + */ + public static toJsonParaphrase(value: string): string { + if (value == null || value.length < 1) { + return ""; + } + let isJx = true; + while (isJx) { + //去除 \\ + if (StringUtils.containsChar(value, "\\\\")) { + value = value.replace("\\\\", "").replaceAll("\\\\", ""); + } + isJx = StringUtils.containsChar(value, "\\\\"); + } + isJx = true; + while (isJx) { + //转 \" 替换为 " + if (StringUtils.containsChar(value, "\\\"")) { + value = value.replace("\\\"", "\"").replaceAll("\\\"", "\""); + } + isJx = StringUtils.containsChar(value, "\\\""); + } + isJx = true; + while (isJx) { + //转 "{ 替换为 { + if (StringUtils.containsChar(value, "\"{")) { + value = value.replace("\"{", "{").replaceAll("\"{", "{"); + } + isJx = StringUtils.containsChar(value, "\"{"); + } + isJx = true; + while (isJx) { + //转 }" 替换为 } + if (StringUtils.containsChar(value, "}\"")) { + value = value.replace("}\"", "}").replaceAll("}\"", "}"); + } + isJx = StringUtils.containsChar(value, "}\""); + } + isJx = true; + while (isJx) { + //转 "[ 替换为 [ + if (StringUtils.containsChar(value, "\"[")) { + value = value.replace("\"[", "[").replaceAll("\"[", "["); + } + isJx = StringUtils.containsChar(value, "\"["); + } + isJx = true; + while (isJx) { + //转 ]" 替换为 ] + if (StringUtils.containsChar(value, "]\"")) { + value = value.replace("]\"", "]").replaceAll("]\"", "]"); + } + isJx = StringUtils.containsChar(value, "]\""); + } + return value; + } + + /** + * 生成指定范围内的随机数 + * @param min 最小数(包含) + * @param max 最大数(不包含) + * @return 随机数 + */ + public static randomNumber(min: number, max: number): number { + return Math.floor(Math.random() * (max - min) + min); + } + + /** + * 获取资源字符串 + * @param context + * @param resource + * @returns + */ + public static getResourceString(context: Context, resource: Resource): string { + let resourceString: string = ''; + try { + resourceString = context.resourceManager.getStringSync(resource.id); + } catch (error) { + console.error('getResourceString err:' + JSON.stringify(error)); + } + return resourceString; + } + + /** + * 检查16进制颜色 + * @param colorStr + * @returns + */ + public static isValidHexColor(colorStr: string): boolean { + // 正则表达式匹配标准格式 + const hexRegex = /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/ + return hexRegex.test(colorStr) + } + + /** + * 严格检查16进制颜色 + * @param colorStr + * @returns + */ + public static strictCheckHexColor(colorStr: string): boolean { + if (!StringUtils.isValidHexColor(colorStr)) return false + + try { + // 移除#符号并补齐透明度通道 + const cleanStr = colorStr.replace('#', '') + const fullHex = cleanStr.length === 6 ? `FF${cleanStr}` : cleanStr + + // 尝试转换为数值验证有效性 + const colorValue = parseInt(fullHex, 16) + return !isNaN(colorValue) && colorValue >= 0 + } catch { + return false + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/util/ToasUtils.ets b/entry/src/main/ets/util/ToasUtils.ets new file mode 100644 index 0000000..c59c3d6 --- /dev/null +++ b/entry/src/main/ets/util/ToasUtils.ets @@ -0,0 +1,19 @@ +import { promptAction } from "@kit.ArkUI"; + +export class ToastUtils{ + + public static toastCenter(msg:string|Resource){ + promptAction.showToast({ + message: msg, + duration: 1200, + alignment:Alignment.Center + }) + } + public static toastBottom(msg:string|Resource){ + promptAction.showToast({ + message: msg, + duration: 1200, + bottom: 100 + }) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/util/VibratorUtils.ets b/entry/src/main/ets/util/VibratorUtils.ets new file mode 100644 index 0000000..d35a358 --- /dev/null +++ b/entry/src/main/ets/util/VibratorUtils.ets @@ -0,0 +1,26 @@ + +import vibrator from "@ohos.vibrator" +export class VibratorUtils{ + + static startVibrator(){ + vibrator.startVibration({type:"time",duration:1000},{usage:'alarm'}) + .then(()=>{ + console.warn("开始震动成功!") + }) + .catch((error:Error)=>{ + console.error("开始震动失败:"+JSON.stringify(error)) + }) + } + + static stopVibrator(){ + vibrator.stopVibration() + .then(()=>{ + console.warn("停止震动成功!") + }) + .catch((error:Error)=>{ + console.error("停止震动失败:"+JSON.stringify(error)) + }) + } + + +} \ No newline at end of file diff --git a/entry/src/main/module.json5 b/entry/src/main/module.json5 new file mode 100644 index 0000000..4f384e6 --- /dev/null +++ b/entry/src/main/module.json5 @@ -0,0 +1,157 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "srcEntry": './ets/app/RuanseeAbilityStag.ets', + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "$string:app_name", + "usedScene": { + "abilities": [ + ".EntryAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.ACCELEROMETER", + "reason": "$string:app_name", + "usedScene": { + "abilities": [ + ".EntryAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.INTERNET", + "usedScene": { + "when": "always" + } + }, + { + "name": "ohos.permission.GET_NETWORK_INFO" + }, + // 震动权限 + { + "name": 'ohos.permission.VIBRATE', + "reason": "$string:app_name", + "usedScene": { + "abilities": [ + ".EntryAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.CAMERA", + "reason": "$string:app_name", + "usedScene": { + "abilities": [ + "EntryAbility" + ] + } + }, + { + "name": "ohos.permission.READ_MEDIA", + "reason": "$string:app_name", + "usedScene": { + "abilities": [ + "EntryAbility" + ] + } + }, + { + "name": "ohos.permission.WRITE_MEDIA", + "reason": "$string:app_name", + "usedScene": { + "abilities": [ + "EntryAbility" + ] + } + }, + { + "name": "ohos.permission.LOCATION", + "reason": "$string:app_name", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.APPROXIMATELY_LOCATION", + "reason": "$string:app_name", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.LOCATION_IN_BACKGROUND", + "reason": "$string:app_name", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "inuse" + } + } + ], + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon_applogin", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:icon_applogin", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home", + "ohos.want.action.viewData" + ], + "uris": [ + { + "scheme": "file", + "type": "application/\*" + } + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/entry/src/main/resources/base/element/color.json b/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000..00b2e4c --- /dev/null +++ b/entry/src/main/resources/base/element/color.json @@ -0,0 +1,301 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + }, + { + "name": "total_background", + "value": "#FF1954EE" + }, + { + "name": "hc_an_bk", + "value": "#FF2170eb" + }, + { + "name": "hc_an_bj", + "value": "#12ffffff" + }, + { + "name": "page_background", + "value": "#F3F7FA" + }, + { + "name": "divider_background", + "value": "#FFB8B8B8" + }, + { + "name": "time_background", + "value": "#a0C7CDD0" + }, + { + "name": "read", + "value": "#FFEE1939" + }, + { + "name": "white", + "value": "#FFFFFF" + }, + { + "name": "green", + "value": "#FF19EE35" + }, + { + "name": "grad", + "value": "#FF646464" + }, + { + "name": "black", + "value": "#FF1D1D1D" + }, + { + "name": "bull", + "value": "#1264DE" + }, + { + "name": "colorRed9", + "value": "#e63119" + }, + { + "name": "colorBluen12", + "value": "#5BC5D5E2" + }, + { + "name": "detailsBackdrop", + "value": "#fff4f8fa" + }, + { + "name": "peopletype1", + "value": "#c8f49f" + }, + { + "name": "peopletype2", + "value": "#a3d273" + }, + { + "name": "peopletype3", + "value": "#06e45f" + }, + { + "name": "peopletype4", + "value": "#fae2ba" + }, + { + "name": "peopletype5", + "value": "#e9bf95" + }, + { + "name": "peopletype6", + "value": "#e4872a" + }, + { + "name": "peopletype7", + "value": "#FFE99595" + }, + { + "name": "peopletype8", + "value": "#FFE42A2A" + }, + { + "name": "state_styles_pressed", + "value": "#868B95" + }, + { + "name": "state_styles_normal", + "value": "#B5B7BF" + }, + { + "name": "delete_key_background", + "value": "#A8ABB7" + }, + { + "name": "delete_key_shadow", + "value": "#76787C" + }, + { + "name": "search_background_normal", + "value": "#0A59F7" + }, + { + "name": "font_background_white", + "value": "#FFFFFF" + }, + { + "name": "keyboard_background_color", + "value": "#DADFE6" + }, + { + "name": "search_background_color", + "value": "#F2F2F2" + }, + { + "name": "search_font_color", + "value": "#000000" + }, + { + "name": "font_color", + "value": "#222222" + }, + { + "name": "main_tj_a", + "value": "#FFD5EBF5" + }, + { + "name": "main_tj_b", + "value": "#E9FDE5" + }, + { + "name": "main_tj_c", + "value": "#FDF9E5" + }, + { + "name": "main_tj_d", + "value": "#FF93C1F1" + }, + { + "name": "colorBluen8", + "value": "#0A87CC" + }, + { + "name": "colorBluen7", + "value": "#0785c9" + }, + { + "name": "colorBluen6", + "value": "#1f94d3" + }, + { + "name": "colorBluen5", + "value": "#67bdec" + }, + { + "name": "colorBluen4", + "value": "#67bbe9" + }, + { + "name": "colorBluen3", + "value": "#80cdf7" + }, + { + "name": "colorBluen2", + "value": "#a7defc" + }, + { + "name": "colorBluen1", + "value": "#e1f3fd" + }, + { + "name": "colorBluen", + "value": "#E6F5FF" + }, + { + "name": "colorGreen1", + "value": "#e8f5e9" + }, + { + "name": "colorGreen2", + "value": "#c8e6c9" + }, + { + "name": "colorGreen3", + "value": "#a5d6a7" + }, + { + "name": "colorGreen4", + "value": "#81c784" + }, + { + "name": "colorGreen5", + "value": "#66bb6a" + }, + { + "name": "colorGreen6", + "value": "#43a047" + }, + { + "name": "colorGreen7", + "value": "#388e3c" + }, + { + "name": "colorGreen", + "value": "#2DED36" + }, + + { + "name": "colorYellow", + "value": "#F19149" + }, + { + "name": "colorYellow1", + "value": "#fff3e0" + }, + + { + "name": "colorYellow2", + "value": "#ffe0b2" + }, + { + "name": "colorYellow3", + "value": "#ffcc80" + }, + + { + "name": "colorYellow4", + "value": "#ffb74d" + }, + { + "name": "colorYellow5", + "value": "#ffa726" + }, + + { + "name": "colorYellow6", + "value": "#fb8c00" + }, + { + "name": "colorYellow7", + "value": "#f57c00" + }, + { + "name": "colorYellow8", + "value": "#ff8304" + }, + + { + "name": "colorGrey1", + "value": "#f5f5f5" + }, + { + "name": "colorGreyte", + "value": "#e5e5e5" + }, + { + "name": "colorGrey2", + "value": "#eeeeee" + }, + { + "name": "colorGrey3", + "value": "#e8e8e8" + }, + { + "name": "colorGrey4", + "value": "#b2b2b2" + }, + { + "name": "colorGrey5", + "value": "#888888" + }, + { + "name": "colorGrey6", + "value": "#626262" + }, + { + "name": "colorGrey7", + "value": "#323232" + }, + { + "name": "colorGrey8", + "value": "#fe131313" + } + ] +} \ No newline at end of file diff --git a/entry/src/main/resources/base/element/float.json b/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000..77b1abd --- /dev/null +++ b/entry/src/main/resources/base/element/float.json @@ -0,0 +1,360 @@ +{ + "float": [ + { + "name": "down_image_size", + "value": "36vp" + }, + { + "name": "down_image_margin", + "value": "10vp" + }, + { + "name": "search_height", + "value": "40vp" + }, + { + "name": "search_margin", + "value": "16vp" + }, + { + "name": "search_border_radius", + "value": "20vp" + }, + { + "name": "default_1", + "value": "1vp" + }, + { + "name": "default_2", + "value": "2vp" + }, + { + "name": "default_3", + "value": "3vp" + }, + { + "name": "default_5", + "value": "5vp" + }, + { + "name": "default_6", + "value": "6vp" + }, + { + "name": "default_8", + "value": "8vp" + }, + { + "name": "default_10", + "value": "10vp" + }, + { + "name": "default_12", + "value": "12vp" + }, + { + "name": "default_14", + "value": "14vp" + }, + { + "name": "default_15", + "value": "15vp" + }, + { + "name": "default_16", + "value": "16vp" + }, + { + "name": "default_18", + "value": "18vp" + }, + { + "name": "default_20", + "value": "20vp" + }, + { + "name": "default_22", + "value": "22vp" + }, + { + "name": "default_23", + "value": "23vp" + }, + { + "name": "default_24", + "value": "24vp" + }, + { + "name": "default_25", + "value": "25vp" + }, + { + "name": "default_26", + "value": "26vp" + }, + { + "name": "default_28", + "value": "28vp" + }, + { + "name": "default_30", + "value": "30vp" + }, + { + "name": "default_32", + "value": "32vp" + }, + { + "name": "default_35", + "value": "35vp" + }, + { + "name": "default_36", + "value": "36vp" + }, + { + "name": "default_38", + "value": "38vp" + }, + { + "name": "default_40", + "value": "40vp" + }, + { + "name": "default_43", + "value": "43vp" + }, + { + "name": "default_45", + "value": "45vp" + }, + { + "name": "default_46", + "value": "46vp" + }, + { + "name": "default_47", + "value": "47vp" + }, + { + "name": "default_48", + "value": "48vp" + }, + { + "name": "default_52", + "value": "52vp" + }, + { + "name": "default_50", + "value": "50vp" + }, + { + "name": "default_58", + "value": "58vp" + }, + { + "name": "default_60", + "value": "60vp" + }, + { + "name": "default_63", + "value": "63vp" + }, + { + "name": "default_68", + "value": "68vp" + }, + { + "name": "default_66", + "value": "66vp" + }, + { + "name": "default_72", + "value": "72vp" + }, + { + "name": "default_80", + "value": "80vp" + }, + { + "name": "default_84", + "value": "84vp" + }, + { + "name": "default_88", + "value": "88vp" + }, + { + "name": "default_90", + "value": "90vp" + }, + { + "name": "default_92", + "value": "92vp" + }, + { + "name": "default_94", + "value": "94vp" + }, + { + "name": "default_98", + "value": "98vp" + }, + { + "name": "default_100", + "value": "100vp" + }, + { + "name": "default_105", + "value": "105vp" + }, + { + "name": "default_110", + "value": "110vp" + }, + { + "name": "default_115", + "value": "115vp" + }, + { + "name": "default_120", + "value": "120vp" + }, + { + "name": "default_125", + "value": "125vp" + }, + { + "name": "default_130", + "value": "130vp" + }, + { + "name": "default_150", + "value": "150vp" + }, + { + "name": "default_160", + "value": "160vp" + }, + { + "name": "default_170", + "value": "170vp" + }, + { + "name": "default_180", + "value": "180vp" + }, + { + "name": "default_185", + "value": "185vp" + }, + { + "name": "default_190", + "value": "190vp" + }, + { + "name": "default_200", + "value": "200vp" + }, + { + "name": "default_240", + "value": "240vp" + }, + { + "name": "default_300", + "value": "300vp" + }, + { + "name": "default_350", + "value": "350vp" + }, + { + "name": "default_400", + "value": "400vp" + }, + { + "name": "delete_image_size", + "value": "30vp" + }, + { + "name": "shift_image_size", + "value": "30vp" + }, + { + "name": "keyboard_height", + "value": "255vp" + }, + { + "name": "keyboard_height_2", + "value": "290vp" + }, + { + "name": "comm_image_radius", + "value": "4vp" + }, + { + "name": "text_size_5", + "value": "5fp" + }, + { + "name": "text_size_6", + "value": "6fp" + }, + { + "name": "text_size_8", + "value": "8fp" + }, + { + "name": "text_size_10", + "value": "10fp" + }, + { + "name": "text_size_12", + "value": "12fp" + }, + { + "name": "text_size_14", + "value": "14fp" + }, + { + "name": "text_size_15", + "value": "15fp" + }, + { + "name": "text_size_16", + "value": "16fp" + }, + { + "name": "text_size_18", + "value": "18fp" + }, + { + "name": "text_size_20", + "value": "20fp" + }, + { + "name": "text_size_22", + "value": "22fp" + }, + { + "name": "text_size_24", + "value": "24fp" + }, + { + "name": "text_size_28", + "value": "28fp" + }, + { + "name": "text_size_32", + "value": "32fp" + }, + { + "name": "text_size_38", + "value": "38fp" + }, + { + "name": "text_size_42", + "value": "42fp" + } + ] +} \ No newline at end of file diff --git a/entry/src/main/resources/base/element/string.json b/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000..7d9228a --- /dev/null +++ b/entry/src/main/resources/base/element/string.json @@ -0,0 +1,72 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "个人中心" + }, + { + "name": "ownership_dept", + "value": "安徽省公安厅" + }, + { + "name": "title_PendingMsg", + "value": "待办消息" + }, + { + "name": "title_Workbench", + "value": "工作台" + }, + { + "name": "title_About", + "value": "关于" + }, + { + "name": "title_Feedback", + "value": "意见反馈" + }, + { + "name": "loading_hint", + "value": "正在加载,请稍后..." + }, + { + "name": "title_select_app", + "value": "选择应用" + }, + { + "name": "title_my_feedback", + "value": "我的反馈" + }, + { + "name": "title_feedback_details", + "value": "反馈详情" + }, + { + "name": "title_application_guide", + "value": "应用指南" + }, + { + "name": "title_guide_details", + "value": "指南详情" + }, + { + "name": "title_user_info", + "value": "个人中心" + }, + { + "name": "title_frequently_questions", + "value": "常见问题" + }, + { + "name": "title_msg_details", + "value": "消息详情" + } + ] +} \ No newline at end of file diff --git a/entry/src/main/resources/base/media/arrow_right.png b/entry/src/main/resources/base/media/arrow_right.png new file mode 100644 index 0000000..6d1657e Binary files /dev/null and b/entry/src/main/resources/base/media/arrow_right.png differ diff --git a/entry/src/main/resources/base/media/background.png b/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000..923f2b3 Binary files /dev/null and b/entry/src/main/resources/base/media/background.png differ diff --git a/entry/src/main/resources/base/media/bg_two.png b/entry/src/main/resources/base/media/bg_two.png new file mode 100644 index 0000000..b762dc2 Binary files /dev/null and b/entry/src/main/resources/base/media/bg_two.png differ diff --git a/entry/src/main/resources/base/media/fileselect_img_doc.png b/entry/src/main/resources/base/media/fileselect_img_doc.png new file mode 100644 index 0000000..4e6da43 Binary files /dev/null and b/entry/src/main/resources/base/media/fileselect_img_doc.png differ diff --git a/entry/src/main/resources/base/media/fileselect_img_music.png b/entry/src/main/resources/base/media/fileselect_img_music.png new file mode 100644 index 0000000..1266cce Binary files /dev/null and b/entry/src/main/resources/base/media/fileselect_img_music.png differ diff --git a/entry/src/main/resources/base/media/fileselect_img_pfd.png b/entry/src/main/resources/base/media/fileselect_img_pfd.png new file mode 100644 index 0000000..e9293cf Binary files /dev/null and b/entry/src/main/resources/base/media/fileselect_img_pfd.png differ diff --git a/entry/src/main/resources/base/media/fileselect_img_ppt.PNG b/entry/src/main/resources/base/media/fileselect_img_ppt.PNG new file mode 100644 index 0000000..93365fc Binary files /dev/null and b/entry/src/main/resources/base/media/fileselect_img_ppt.PNG differ diff --git a/entry/src/main/resources/base/media/fileselect_img_txt.png b/entry/src/main/resources/base/media/fileselect_img_txt.png new file mode 100644 index 0000000..357ea7c Binary files /dev/null and b/entry/src/main/resources/base/media/fileselect_img_txt.png differ diff --git a/entry/src/main/resources/base/media/fileselect_img_unknown.png b/entry/src/main/resources/base/media/fileselect_img_unknown.png new file mode 100644 index 0000000..d4ef3ff Binary files /dev/null and b/entry/src/main/resources/base/media/fileselect_img_unknown.png differ diff --git a/entry/src/main/resources/base/media/fileselect_img_xls.png b/entry/src/main/resources/base/media/fileselect_img_xls.png new file mode 100644 index 0000000..8d99e7f Binary files /dev/null and b/entry/src/main/resources/base/media/fileselect_img_xls.png differ diff --git a/entry/src/main/resources/base/media/fileselect_img_zip.png b/entry/src/main/resources/base/media/fileselect_img_zip.png new file mode 100644 index 0000000..7b599f4 Binary files /dev/null and b/entry/src/main/resources/base/media/fileselect_img_zip.png differ diff --git a/entry/src/main/resources/base/media/foreground.png b/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000..97014d3 Binary files /dev/null and b/entry/src/main/resources/base/media/foreground.png differ diff --git a/entry/src/main/resources/base/media/ic_back_b.png b/entry/src/main/resources/base/media/ic_back_b.png new file mode 100644 index 0000000..9c3c2ed Binary files /dev/null and b/entry/src/main/resources/base/media/ic_back_b.png differ diff --git a/entry/src/main/resources/base/media/ic_dropup.png b/entry/src/main/resources/base/media/ic_dropup.png new file mode 100644 index 0000000..d1c7f46 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_dropup.png differ diff --git a/entry/src/main/resources/base/media/ic_filter.png b/entry/src/main/resources/base/media/ic_filter.png new file mode 100644 index 0000000..f55c299 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_filter.png differ diff --git a/entry/src/main/resources/base/media/ic_load_imag_eerror.png b/entry/src/main/resources/base/media/ic_load_imag_eerror.png new file mode 100644 index 0000000..447a7ce Binary files /dev/null and b/entry/src/main/resources/base/media/ic_load_imag_eerror.png differ diff --git a/entry/src/main/resources/base/media/ic_look.png b/entry/src/main/resources/base/media/ic_look.png new file mode 100644 index 0000000..e438ec2 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_look.png differ diff --git a/entry/src/main/resources/base/media/ic_unread_doit.png b/entry/src/main/resources/base/media/ic_unread_doit.png new file mode 100644 index 0000000..bbf47c3 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_unread_doit.png differ diff --git a/entry/src/main/resources/base/media/ic_zazdr.png b/entry/src/main/resources/base/media/ic_zazdr.png new file mode 100644 index 0000000..89c8bf5 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_zazdr.png differ diff --git a/entry/src/main/resources/base/media/ic_zazh.png b/entry/src/main/resources/base/media/ic_zazh.png new file mode 100644 index 0000000..361366e Binary files /dev/null and b/entry/src/main/resources/base/media/ic_zazh.png differ diff --git a/entry/src/main/resources/base/media/ic_zfjc.png b/entry/src/main/resources/base/media/ic_zfjc.png new file mode 100644 index 0000000..6f76c1e Binary files /dev/null and b/entry/src/main/resources/base/media/ic_zfjc.png differ diff --git a/entry/src/main/resources/base/media/icon_about.png b/entry/src/main/resources/base/media/icon_about.png new file mode 100644 index 0000000..f1fb20f Binary files /dev/null and b/entry/src/main/resources/base/media/icon_about.png differ diff --git a/entry/src/main/resources/base/media/icon_applogin.png b/entry/src/main/resources/base/media/icon_applogin.png new file mode 100644 index 0000000..2f33529 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_applogin.png differ diff --git a/entry/src/main/resources/base/media/icon_authen.png b/entry/src/main/resources/base/media/icon_authen.png new file mode 100644 index 0000000..f5477e3 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_authen.png differ diff --git a/entry/src/main/resources/base/media/icon_back2.png b/entry/src/main/resources/base/media/icon_back2.png new file mode 100644 index 0000000..d8ca19a Binary files /dev/null and b/entry/src/main/resources/base/media/icon_back2.png differ diff --git a/entry/src/main/resources/base/media/icon_back3.png b/entry/src/main/resources/base/media/icon_back3.png new file mode 100644 index 0000000..39478c5 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_back3.png differ diff --git a/entry/src/main/resources/base/media/icon_back_black.png b/entry/src/main/resources/base/media/icon_back_black.png new file mode 100644 index 0000000..0b5ead8 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_back_black.png differ diff --git a/entry/src/main/resources/base/media/icon_clean.png b/entry/src/main/resources/base/media/icon_clean.png new file mode 100644 index 0000000..05a95ee Binary files /dev/null and b/entry/src/main/resources/base/media/icon_clean.png differ diff --git a/entry/src/main/resources/base/media/icon_edit_info.png b/entry/src/main/resources/base/media/icon_edit_info.png new file mode 100644 index 0000000..580ec6f Binary files /dev/null and b/entry/src/main/resources/base/media/icon_edit_info.png differ diff --git a/entry/src/main/resources/base/media/icon_empty.png b/entry/src/main/resources/base/media/icon_empty.png new file mode 100644 index 0000000..6bf9897 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_empty.png differ diff --git a/entry/src/main/resources/base/media/icon_error2.png b/entry/src/main/resources/base/media/icon_error2.png new file mode 100644 index 0000000..6f3c01b Binary files /dev/null and b/entry/src/main/resources/base/media/icon_error2.png differ diff --git a/entry/src/main/resources/base/media/icon_feedback.png b/entry/src/main/resources/base/media/icon_feedback.png new file mode 100644 index 0000000..a254ea7 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_feedback.png differ diff --git a/entry/src/main/resources/base/media/icon_gd2.png b/entry/src/main/resources/base/media/icon_gd2.png new file mode 100644 index 0000000..326f8fa Binary files /dev/null and b/entry/src/main/resources/base/media/icon_gd2.png differ diff --git a/entry/src/main/resources/base/media/icon_main_feedback.png b/entry/src/main/resources/base/media/icon_main_feedback.png new file mode 100644 index 0000000..68b23ce Binary files /dev/null and b/entry/src/main/resources/base/media/icon_main_feedback.png differ diff --git a/entry/src/main/resources/base/media/icon_main_feedback_def.png b/entry/src/main/resources/base/media/icon_main_feedback_def.png new file mode 100644 index 0000000..220b01a Binary files /dev/null and b/entry/src/main/resources/base/media/icon_main_feedback_def.png differ diff --git a/entry/src/main/resources/base/media/icon_main_home.png b/entry/src/main/resources/base/media/icon_main_home.png new file mode 100644 index 0000000..98816e8 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_main_home.png differ diff --git a/entry/src/main/resources/base/media/icon_main_home_def.png b/entry/src/main/resources/base/media/icon_main_home_def.png new file mode 100644 index 0000000..9ed29ed Binary files /dev/null and b/entry/src/main/resources/base/media/icon_main_home_def.png differ diff --git a/entry/src/main/resources/base/media/icon_main_message.png b/entry/src/main/resources/base/media/icon_main_message.png new file mode 100644 index 0000000..a0dda53 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_main_message.png differ diff --git a/entry/src/main/resources/base/media/icon_main_message_def.png b/entry/src/main/resources/base/media/icon_main_message_def.png new file mode 100644 index 0000000..b207d7a Binary files /dev/null and b/entry/src/main/resources/base/media/icon_main_message_def.png differ diff --git a/entry/src/main/resources/base/media/icon_main_my.png b/entry/src/main/resources/base/media/icon_main_my.png new file mode 100644 index 0000000..b429efe Binary files /dev/null and b/entry/src/main/resources/base/media/icon_main_my.png differ diff --git a/entry/src/main/resources/base/media/icon_main_my_def.png b/entry/src/main/resources/base/media/icon_main_my_def.png new file mode 100644 index 0000000..b020d78 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_main_my_def.png differ diff --git a/entry/src/main/resources/base/media/icon_main_work.png b/entry/src/main/resources/base/media/icon_main_work.png new file mode 100644 index 0000000..e74268b Binary files /dev/null and b/entry/src/main/resources/base/media/icon_main_work.png differ diff --git a/entry/src/main/resources/base/media/icon_main_work_def.png b/entry/src/main/resources/base/media/icon_main_work_def.png new file mode 100644 index 0000000..5110194 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_main_work_def.png differ diff --git a/entry/src/main/resources/base/media/icon_my_userbg.png b/entry/src/main/resources/base/media/icon_my_userbg.png new file mode 100644 index 0000000..e37e979 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_my_userbg.png differ diff --git a/entry/src/main/resources/base/media/icon_not_record.png b/entry/src/main/resources/base/media/icon_not_record.png new file mode 100644 index 0000000..243f7cf Binary files /dev/null and b/entry/src/main/resources/base/media/icon_not_record.png differ diff --git a/entry/src/main/resources/base/media/icon_operation_guide.png b/entry/src/main/resources/base/media/icon_operation_guide.png new file mode 100644 index 0000000..52b177b Binary files /dev/null and b/entry/src/main/resources/base/media/icon_operation_guide.png differ diff --git a/entry/src/main/resources/base/media/icon_over.png b/entry/src/main/resources/base/media/icon_over.png new file mode 100644 index 0000000..d1f9747 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_over.png differ diff --git a/entry/src/main/resources/base/media/icon_over_back.png b/entry/src/main/resources/base/media/icon_over_back.png new file mode 100644 index 0000000..98649fa Binary files /dev/null and b/entry/src/main/resources/base/media/icon_over_back.png differ diff --git a/entry/src/main/resources/base/media/icon_police_man.png b/entry/src/main/resources/base/media/icon_police_man.png new file mode 100644 index 0000000..d515e42 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_police_man.png differ diff --git a/entry/src/main/resources/base/media/icon_police_woman.png b/entry/src/main/resources/base/media/icon_police_woman.png new file mode 100644 index 0000000..30c4cff Binary files /dev/null and b/entry/src/main/resources/base/media/icon_police_woman.png differ diff --git a/entry/src/main/resources/base/media/icon_problen.png b/entry/src/main/resources/base/media/icon_problen.png new file mode 100644 index 0000000..54dc98a Binary files /dev/null and b/entry/src/main/resources/base/media/icon_problen.png differ diff --git a/entry/src/main/resources/base/media/icon_record.png b/entry/src/main/resources/base/media/icon_record.png new file mode 100644 index 0000000..ff8f18a Binary files /dev/null and b/entry/src/main/resources/base/media/icon_record.png differ diff --git a/entry/src/main/resources/base/media/icon_refresh.png b/entry/src/main/resources/base/media/icon_refresh.png new file mode 100644 index 0000000..9e7643f Binary files /dev/null and b/entry/src/main/resources/base/media/icon_refresh.png differ diff --git a/entry/src/main/resources/base/media/icon_refresh_grad.png b/entry/src/main/resources/base/media/icon_refresh_grad.png new file mode 100644 index 0000000..ec19ea6 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_refresh_grad.png differ diff --git a/entry/src/main/resources/base/media/icon_search.png b/entry/src/main/resources/base/media/icon_search.png new file mode 100644 index 0000000..c9fb117 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_search.png differ diff --git a/entry/src/main/resources/base/media/icon_tips_error.png b/entry/src/main/resources/base/media/icon_tips_error.png new file mode 100644 index 0000000..e510160 Binary files /dev/null and b/entry/src/main/resources/base/media/icon_tips_error.png differ diff --git a/entry/src/main/resources/base/media/layered_image.json b/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000..fb49920 --- /dev/null +++ b/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/entry/src/main/resources/base/media/startIcon.png b/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000..205ad8b Binary files /dev/null and b/entry/src/main/resources/base/media/startIcon.png differ diff --git a/entry/src/main/resources/base/profile/backup_config.json b/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000..78f40ae --- /dev/null +++ b/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000..a2500ee --- /dev/null +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "ui/pages/Index" + ] +} diff --git a/entry/src/main/resources/dark/element/color.json b/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000..79b11c2 --- /dev/null +++ b/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/entry/src/main/resources/rawfile/TestJs.html b/entry/src/main/resources/rawfile/TestJs.html new file mode 100644 index 0000000..2367c2f --- /dev/null +++ b/entry/src/main/resources/rawfile/TestJs.html @@ -0,0 +1,90 @@ + + + + + 这里是一个H5页面 + + + + + +

+ +

+ +

+ +

+ +

+ +

+ + + + \ No newline at end of file diff --git a/entry/src/main/resources/rawfile/anHuiCityName.json b/entry/src/main/resources/rawfile/anHuiCityName.json new file mode 100644 index 0000000..938033c --- /dev/null +++ b/entry/src/main/resources/rawfile/anHuiCityName.json @@ -0,0 +1,70 @@ +[ + { + "name": "省厅", + "code": "3400" + }, + { + "name": "合肥", + "code": "3401" + }, + { + "name": "芜湖", + "code": "3402" + }, + { + "name": "蚌埠", + "code": "3403" + }, + { + "name": "淮南", + "code": "3404" + }, + { + "name": "马鞍山", + "code": "3405" + }, + { + "name": "淮北", + "code": "3406" + }, + { + "name": "铜陵", + "code": "3407" + }, + { + "name": "安庆", + "code": "3408" + }, + { + "name": "黄山", + "code": "3410" + }, + { + "name": "滁州", + "code": "3411" + }, + { + "name": "阜阳", + "code": "3412" + }, + { + "name": "宿州", + "code": "3413" + }, + { + "name": "六安", + "code": "3415" + }, + { + "name": "亳州", + "code": "3416" + }, + { + "name": "池州", + "code": "3417" + }, + { + "name": "宣城", + "code": "3418" + } +] \ No newline at end of file diff --git a/entry/src/mock/mock-config.json5 b/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/entry/src/mock/mock-config.json5 @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/Ability.test.ets b/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000..85c78f6 --- /dev/null +++ b/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,35 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/List.test.ets b/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000..794c7dc --- /dev/null +++ b/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/entry/src/ohosTest/module.json5 b/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000..509a3a2 --- /dev/null +++ b/entry/src/ohosTest/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/entry/src/test/List.test.ets b/entry/src/test/List.test.ets new file mode 100644 index 0000000..bb5b5c3 --- /dev/null +++ b/entry/src/test/List.test.ets @@ -0,0 +1,5 @@ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/entry/src/test/LocalUnit.test.ets b/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000..165fc16 --- /dev/null +++ b/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,33 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/hvigor/hvigor-config.json5 b/hvigor/hvigor-config.json5 new file mode 100644 index 0000000..c5b5183 --- /dev/null +++ b/hvigor/hvigor-config.json5 @@ -0,0 +1,23 @@ +{ + "modelVersion": "5.0.5", + "dependencies": { + "@hadss/hmrouter-plugin": "^1.2.0-rc.0" + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/hvigorfile.ts b/hvigorfile.ts new file mode 100644 index 0000000..2c59813 --- /dev/null +++ b/hvigorfile.ts @@ -0,0 +1,7 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; +import { appPlugin } from "@hadss/hmrouter-plugin"; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [appPlugin({ ignoreModuleNames: [ /** 不需要扫描的模块 **/ ] })] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/oh-package-lock.json5 b/oh-package-lock.json5 new file mode 100644 index 0000000..a1ded28 --- /dev/null +++ b/oh-package-lock.json5 @@ -0,0 +1,125 @@ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@abner/lithe_refresh@^1.0.3": "@abner/lithe_refresh@1.0.3", + "@abner/refresh@^1.4.6": "@abner/refresh@1.4.6", + "@hadss/hmrouter-transitions@^1.2.0-rc.0": "@hadss/hmrouter-transitions@1.2.0", + "@hadss/hmrouter@1.2.0": "@hadss/hmrouter@1.2.0", + "@hadss/hmrouter@^1.2.0-rc.0": "@hadss/hmrouter@1.2.0", + "@ohos/axios@^2.2.5": "@ohos/axios@2.2.6", + "@ohos/crypto-js@^2.0.5": "@ohos/crypto-js@2.0.5", + "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0", + "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21", + "@pura/harmony-dialog@^1.1.6": "@pura/harmony-dialog@1.1.8", + "@pura/harmony-utils@^1.3.7": "@pura/harmony-utils@1.3.8", + "@pura/spinkit@^1.0.5": "@pura/spinkit@1.0.5", + "class-transformer@0.5.1": "class-transformer@0.5.1", + "libhmrouterlibrary.so@oh_modules/.ohpm/@hadss+hmrouter@1.2.0/oh_modules/@hadss/hmrouter/src/main/cpp/types/libhmrouterlibrary": "libhmrouterlibrary.so@oh_modules/.ohpm/@hadss+hmrouter@1.2.0/oh_modules/@hadss/hmrouter/src/main/cpp/types/libhmrouterlibrary" + }, + "packages": { + "@abner/lithe_refresh@1.0.3": { + "name": "@abner/lithe_refresh", + "version": "1.0.3", + "integrity": "sha512-yvhvqz9MCGhcYfiVXo2cuV0f9fOxDopc8JK+OREjy1y/mFomAHTAUT+PtQtuWW5ptHWE3h9T6rlrTclDH5gulg==", + "resolved": "https://repo.harmonyos.com/ohpm/@abner/lithe_refresh/-/lithe_refresh-1.0.3.har", + "registryType": "ohpm" + }, + "@abner/refresh@1.4.6": { + "name": "@abner/refresh", + "version": "1.4.6", + "integrity": "sha512-VkU3sXfJ3oQBrMulMni7THR9yDycmes24Dydvo69NmzgjiRGveki2VR/ZUNybaSfL88k/ycjWAC86+7AKT34NA==", + "resolved": "https://repo.harmonyos.com/ohpm/@abner/refresh/-/refresh-1.4.6.har", + "registryType": "ohpm" + }, + "@hadss/hmrouter-transitions@1.2.0": { + "name": "@hadss/hmrouter-transitions", + "version": "1.2.0", + "integrity": "sha512-rcRpX6+qFBW86nunRwG59lcb8UwSPBRwpVO1wlvVuQ4muSM8rNzpo5XvhbHi/rc+Rf53XdBU+oUlGat2vVsskw==", + "resolved": "https://repo.harmonyos.com/ohpm/@hadss/hmrouter-transitions/-/hmrouter-transitions-1.2.0.har", + "registryType": "ohpm", + "dependencies": { + "@hadss/hmrouter": "1.2.0" + } + }, + "@hadss/hmrouter@1.2.0": { + "name": "@hadss/hmrouter", + "version": "1.2.0", + "integrity": "sha512-BC/e1ZdPbu7zmE4Lui7pr1d8EQk1RfA88qP6HJEHJLCrhY7kX2SeX6KIZlUMD5NTAit6YymmqUK0BYnBalsgJg==", + "resolved": "https://repo.harmonyos.com/ohpm/@hadss/hmrouter/-/hmrouter-1.2.0.har", + "registryType": "ohpm", + "dependencies": { + "libhmrouterlibrary.so": "file:./src/main/cpp/types/libhmrouterlibrary" + } + }, + "@ohos/axios@2.2.6": { + "name": "@ohos/axios", + "version": "2.2.6", + "integrity": "sha512-A1JqGe6XaeqWyjQETitFW4EkubQS7Fv7h0YG5a/ry3/a/vOgVGzwC4y5KAhvMzVv1tYjfY0ntMtV2kJGlmOHcQ==", + "resolved": "https://repo.harmonyos.com/ohpm/@ohos/axios/-/axios-2.2.6.har", + "registryType": "ohpm" + }, + "@ohos/crypto-js@2.0.5": { + "name": "@ohos/crypto-js", + "version": "2.0.5", + "integrity": "sha512-QPW+vxSambzep39qnnvGLk2lItqPqt+HBTo7FsTdL9edv3z35h4D80ClnEPNPfXQzIp8DgVDMIgbAWa1hWq8ug==", + "resolved": "https://repo.harmonyos.com/ohpm/@ohos/crypto-js/-/crypto-js-2.0.5.har", + "registryType": "ohpm" + }, + "@ohos/hamock@1.0.0": { + "name": "@ohos/hamock", + "version": "1.0.0", + "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==", + "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hamock/-/hamock-1.0.0.har", + "registryType": "ohpm" + }, + "@ohos/hypium@1.0.21": { + "name": "@ohos/hypium", + "version": "1.0.21", + "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==", + "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.21.har", + "registryType": "ohpm" + }, + "@pura/harmony-dialog@1.1.8": { + "name": "@pura/harmony-dialog", + "version": "1.1.8", + "integrity": "sha512-IG2BJti8LBvJvkAD7yLwk6F2D66BGYPt6mae2yqAB9hMU5HnOTslWJbrReN9qPQl+ssIjSahMC7aJexEFYm5Dw==", + "resolved": "https://repo.harmonyos.com/ohpm/@pura/harmony-dialog/-/harmony-dialog-1.1.8.har", + "registryType": "ohpm", + "dependencies": { + "@pura/spinkit": "^1.0.5" + } + }, + "@pura/harmony-utils@1.3.8": { + "name": "@pura/harmony-utils", + "version": "1.3.8", + "integrity": "sha512-y9+6Ft8crDs0dIdgaxhdRig24FQSwreBajY0KEUvCLafQnbQ2H3rcRitTxvyRiaesUNw4jG+PVJHAOyuvJTf9Q==", + "resolved": "https://repo.harmonyos.com/ohpm/@pura/harmony-utils/-/harmony-utils-1.3.8.har", + "registryType": "ohpm" + }, + "@pura/spinkit@1.0.5": { + "name": "@pura/spinkit", + "version": "1.0.5", + "integrity": "sha512-EKG+yzbCj/owI5zUYukIZV+YMRbeS/Ymd281Dj5asCKQHTWoEUVGmow3HCo7rl2Bdh8yliIT/StxPokUf8a6bQ==", + "resolved": "https://repo.harmonyos.com/ohpm/@pura/spinkit/-/spinkit-1.0.5.har", + "registryType": "ohpm" + }, + "class-transformer@0.5.1": { + "name": "class-transformer", + "version": "0.5.1", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "resolved": "https://repo.harmonyos.com/ohpm/class-transformer/-/class-transformer-0.5.1.tgz", + "shasum": "24147d5dffd2a6cea930a3250a677addf96ab336", + "registryType": "ohpm" + }, + "libhmrouterlibrary.so@oh_modules/.ohpm/@hadss+hmrouter@1.2.0/oh_modules/@hadss/hmrouter/src/main/cpp/types/libhmrouterlibrary": { + "name": "libhmrouterlibrary.so", + "version": "1.0.0", + "resolved": "oh_modules/.ohpm/@hadss+hmrouter@1.2.0/oh_modules/@hadss/hmrouter/src/main/cpp/types/libhmrouterlibrary", + "registryType": "local" + } + } +} \ No newline at end of file diff --git a/oh-package.json5 b/oh-package.json5 new file mode 100644 index 0000000..69e4db3 --- /dev/null +++ b/oh-package.json5 @@ -0,0 +1,20 @@ +{ + "modelVersion": "5.0.5", + "description": "Please describe the basic information.", + "dependencies": { + "@ohos/axios": "^2.2.5", + "@pura/harmony-utils": "^1.3.7", + "@pura/harmony-dialog": "^1.1.6", + "@abner/lithe_refresh": "^1.0.3", + "@abner/refresh": "^1.4.6", + "@hadss/hmrouter": "^1.2.0-rc.0", + "@hadss/hmrouter-transitions": "^1.2.0-rc.0", + "@ohos/crypto-js": "^2.0.5", + "class-transformer": "0.5.1" + }, + "devDependencies": { + "@ohos/hypium": "1.0.21", + "@ohos/hamock": "1.0.0" + }, + "dynamicDependencies": {} +} \ No newline at end of file diff --git a/统一认证.hap b/统一认证.hap new file mode 100644 index 0000000..696f031 Binary files /dev/null and b/统一认证.hap differ