1.2.0部分代码
@ -113,4 +113,16 @@ export { compressedImage,saveImageToGallery,CompressedImageInfo } from './src/ma
|
||||
|
||||
export { ScreeningView } from './src/main/ets/Views/ScreeningView'
|
||||
|
||||
export { TagListModel, TagList} from './src/main/ets/models/TagListModel'
|
||||
export { TagListModel, TagList} from './src/main/ets/models/TagListModel'
|
||||
|
||||
export { AppUtil } from './src/main/ets/utils/AppUtil'
|
||||
|
||||
export { OnWXResp,WXApi,WXEventHandler } from './src/main/ets/models/WXApiWrap'
|
||||
|
||||
// export { DBManager,FileDownloadManager } from './src/main/ets/utils/FileManager'
|
||||
|
||||
export { FileManager } from './src/main/ets/utils/FileManager'
|
||||
|
||||
export { FileInfo,DownloadCallback,PreviewConfig } from './src/main/ets/models/FileModel'
|
||||
|
||||
export { FileDownloadManager } from './src/main/ets/utils/FileDownloadManager'
|
||||
@ -1,3 +1,5 @@
|
||||
import { ChangeUtil } from "../../../../Index";
|
||||
import { promptAction } from "@kit.ArkUI";
|
||||
|
||||
@CustomDialog
|
||||
export struct DefaultHintProWindows {
|
||||
@ -12,16 +14,23 @@ export struct DefaultHintProWindows {
|
||||
@Prop cancleColor:ResourceStr = '#FFFFFF';
|
||||
@Prop confirmColor:ResourceStr = '#FFFFFF';
|
||||
controller: CustomDialogController;
|
||||
@State inputContent:string = ''
|
||||
|
||||
// 添加回调函数属性
|
||||
private selectedButton: (index: number) => void = () => {};
|
||||
|
||||
private selectedButtonAndContent: (index: number,content:string) => void = () => {};
|
||||
|
||||
// 修改构造函数
|
||||
constructor(controller: CustomDialogController, selectedButton: (index:number) => void) {
|
||||
super();
|
||||
this.controller = controller;
|
||||
this.selectedButton = selectedButton;
|
||||
}
|
||||
constructor(controller:CustomDialogController,selectedButtonAndContent: (index: number,content:string) => void) {
|
||||
super();
|
||||
this.controller = controller
|
||||
this.selectedButtonAndContent = selectedButtonAndContent
|
||||
}
|
||||
|
||||
build() {
|
||||
Row(){
|
||||
@ -32,10 +41,21 @@ export struct DefaultHintProWindows {
|
||||
.textAlign(TextAlign.Center)
|
||||
.margin({ top: 20 })
|
||||
|
||||
Text(this.message)
|
||||
.fontSize(this.messageFont)
|
||||
.textAlign(TextAlign.Center)
|
||||
.margin({ top: 10 })
|
||||
if (!ChangeUtil.stringIsUndefinedAndNull(this.message)) {
|
||||
Text(this.message)
|
||||
.fontSize(this.messageFont)
|
||||
.textAlign(TextAlign.Center)
|
||||
.margin({ top: 10 })
|
||||
.padding({left:10,right:10})
|
||||
} else {
|
||||
TextInput({placeholder:'请输入您的登录密码'})
|
||||
.margin(10)
|
||||
.backgroundColor('#f4f4f4')
|
||||
.borderRadius(5)
|
||||
.onChange((value:string)=>{
|
||||
this.inputContent = value
|
||||
})
|
||||
}
|
||||
|
||||
Row({ space: 20 }) {
|
||||
Button({ buttonStyle: ButtonStyleMode.TEXTUAL }) {
|
||||
@ -45,7 +65,11 @@ export struct DefaultHintProWindows {
|
||||
}
|
||||
.width('45%').height(30).backgroundColor(this.cancleColor)
|
||||
.onClick(() => {
|
||||
this.selectedButton(0)
|
||||
if (ChangeUtil.stringIsUndefinedAndNull(this.message)) {
|
||||
this.selectedButtonAndContent(0,'')
|
||||
} else {
|
||||
this.selectedButton(0)
|
||||
}
|
||||
})
|
||||
.visibility(this.cancleTitle?Visibility.Visible:Visibility.None)
|
||||
|
||||
@ -55,7 +79,15 @@ export struct DefaultHintProWindows {
|
||||
.fontColor(this.confirmTitleColor)
|
||||
}.width('45%').height(30).backgroundColor(this.confirmColor)
|
||||
.onClick(() => {
|
||||
this.selectedButton(1)
|
||||
if (ChangeUtil.stringIsUndefinedAndNull(this.message)) {
|
||||
if (ChangeUtil.stringIsUndefinedAndNull(this.inputContent)) {
|
||||
promptAction.showToast({ message: '请输入您的登录密码', duration: 1000 })
|
||||
return
|
||||
}
|
||||
this.selectedButtonAndContent(1,this.inputContent)
|
||||
} else {
|
||||
this.selectedButton(1)
|
||||
}
|
||||
})
|
||||
}.margin({ top: 20, bottom: 20 })
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ export class BasicConstant {
|
||||
static readonly wxUrl = "https://dev-wx.igandan.com/";
|
||||
static readonly polvId = "11";//保利威视学员id
|
||||
static readonly urlApp="https://dev-app.igandan.com/app/"
|
||||
static readonly expertPay = "https://dev-app.igandan.com/app/expertPay/"
|
||||
//正式环境
|
||||
// static readonly urlExpertAPI = "https://app.igandan.com/app/expertAPI/";
|
||||
// static readonly urlExpertApp = "http://app.igandan.com/app/expertApp/"
|
||||
@ -23,7 +24,9 @@ export class BasicConstant {
|
||||
// static readonly wxUrl = "https://wx.igandan.com/";// 微信服务器地址
|
||||
// static readonly polvId = "21";//保利威视学员id
|
||||
// static readonly urlApp="http://app.igandan.com/app/"
|
||||
// static readonly expertPay = "https://app.igandan.com/app/expertPay/"
|
||||
|
||||
static readonly getSystemTime = BasicConstant.urlApp + 'manager/' + 'getSystemTime'
|
||||
static readonly getSystemTimeStamp = BasicConstant.urlApp+'manager/getSystemTimeStamp'
|
||||
static readonly addBonusPoints = BasicConstant.urlExpertApp+'addBonusPoints'
|
||||
static readonly indexV2 = BasicConstant.urlExpertAPI+'indexV2';//首页轮播
|
||||
@ -72,12 +75,33 @@ export class BasicConstant {
|
||||
static readonly deleteComment = BasicConstant.urlExpertApp+'deleteComment';//删除评论
|
||||
static readonly meetingHistoryList = BasicConstant.urlExpertAPI + "meetingHistoryList";
|
||||
static readonly videoRoll = BasicConstant.urlExpertAPI + "videoRoll";
|
||||
static readonly newsRollNew = BasicConstant.urlExpert + 'newsRollNew'
|
||||
static readonly newsTagList = BasicConstant.urlExpert + 'newsTagList'
|
||||
static readonly newsListNew = BasicConstant.urlExpert + 'newsListNew'
|
||||
static readonly defaultNewsListNew = BasicConstant.urlExpert + 'defaultNewsListNew'
|
||||
static readonly expertVideoTypeList = BasicConstant.urlExpertAPI + "expertVideoTypeList";
|
||||
static readonly patientVideoNew = BasicConstant.urlExpertApp + 'patientVideoNew';
|
||||
static readonly videoByKeyWordsNew = BasicConstant.urlExpertApp + "videoByKeyWordsNew";
|
||||
static readonly patientVideoByKeyWordsNew = BasicConstant.urlExpertApp + 'patientVideoByKeyWordsNew'
|
||||
static readonly feedBack = BasicConstant.urlExpert+'feedBack'
|
||||
static readonly ganDanFileByKeyWords = BasicConstant.urlExpertAPI+'ganDanFileByKeyWords'//肝胆课件
|
||||
static readonly getKePuCollection = BasicConstant.urlExpert+'getKePuCollection'
|
||||
static readonly discollection = BasicConstant.urlExpert + 'discollection'
|
||||
static readonly collection = BasicConstant.urlExpert + 'collection'
|
||||
static readonly disagree = BasicConstant.urlExpert + 'disagree'
|
||||
static readonly agree = BasicConstant.urlExpert + 'agree'
|
||||
static readonly ganDanFileDetials = BasicConstant.urlExpertAPI + 'ganDanFileDetials'
|
||||
static readonly newsDetial = BasicConstant.urlExpert + 'newsDetial'
|
||||
static readonly createGanDanFileOrder = BasicConstant.expertPay + 'createGanDanFileOrder'
|
||||
static readonly getBalance = BasicConstant.expertPay + 'getBalance'
|
||||
static readonly payGanDanFileOrder = BasicConstant.expertPay + 'payGanDanFileOrder'
|
||||
static readonly getOrderStatus = BasicConstant.expertPay + 'getOrderStatus'
|
||||
static readonly useWelfareNum = BasicConstant.urlExpertAPI + 'useWelfareNum'
|
||||
static readonly allXinyiList = BasicConstant.expertPay + 'allXinyiList'
|
||||
static readonly xinyiPrice = BasicConstant.expertPay + 'xinyiPrice'
|
||||
static readonly createXinYiOrder = BasicConstant.expertPay + 'createXinYiOrder'
|
||||
static readonly payXinYiOrder = BasicConstant.expertPay + 'payXinYiOrder'
|
||||
static readonly getFlowerList = BasicConstant.expertPay + 'getFlowerList'
|
||||
static readonly tagList = BasicConstant.urlExpertApp + "tagList";
|
||||
static readonly meetingListBySearch = BasicConstant.urlExpertAPI + "meetingListBySearch";
|
||||
static readonly videoBySearchNew = BasicConstant.urlExpertApp+'videoBySearchNew';//搜索肝胆视频列表
|
||||
@ -135,6 +159,8 @@ export class BasicConstant {
|
||||
static readonly notification_back_refreshData = 250529;//返回上页通知刷新数据
|
||||
//首页tabContent切换事件通知
|
||||
static readonly notification_home_tab_change = 25060413;
|
||||
//课件支付成功返回上一页下载科技
|
||||
static readonly notification_kejian_pay_success = 202509041128;
|
||||
|
||||
|
||||
static readonly YX_accid='YX_accid'//云信
|
||||
|
||||
2
commons/basic/src/main/ets/constants/Constants.ets
Normal file
@ -0,0 +1,2 @@
|
||||
export const APP_ID = "wxbf3658f5e674667c"
|
||||
export const APP_SECRET = "c4505a04a9910c65efea8e11ffc93f92"
|
||||
51
commons/basic/src/main/ets/models/FileModel.ets
Normal file
@ -0,0 +1,51 @@
|
||||
// 文件信息接口
|
||||
export interface FileInfo {
|
||||
fileId: string;
|
||||
fileName: string;
|
||||
fileType: string;
|
||||
fileSize: number;
|
||||
fileUrl: string;
|
||||
filePath?: string;
|
||||
downloadStatus: 'pending' | 'downloading' | 'downloaded' | 'failed' | 'cancelled';
|
||||
downloadProgress: number;
|
||||
createTime: number;
|
||||
updateTime: number;
|
||||
}
|
||||
|
||||
// 下载进度回调
|
||||
export interface DownloadCallback {
|
||||
onProgress?: (progress: number) => void;
|
||||
onSuccess?: (filePath: string) => void;
|
||||
onFailed?: (error: string) => void;
|
||||
onCancelled?: () => void;
|
||||
}
|
||||
|
||||
// 文件预览配置
|
||||
export interface PreviewConfig {
|
||||
enableCache?: boolean;
|
||||
maxCacheSize?: number;
|
||||
supportedTypes?: string[];
|
||||
}
|
||||
|
||||
// 定义下载状态枚举
|
||||
export enum DownloadStatus {
|
||||
PENDING = 'pending', // 等待中
|
||||
DOWNLOADING = 'downloading', // 下载中
|
||||
PAUSED = 'paused', // 已暂停
|
||||
COMPLETED = 'completed', // 已完成
|
||||
FAILED = 'failed', // 失败
|
||||
}
|
||||
|
||||
// 定义文件项接口
|
||||
export interface DownloadFileItem {
|
||||
id: string; // 文件唯一标识
|
||||
name: string; // 文件名
|
||||
url: string; // 下载地址
|
||||
localPath: string; // 本地存储路径
|
||||
size: number; // 文件大小(字节)
|
||||
downloadedSize: number; // 已下载大小(字节)
|
||||
status: DownloadStatus; // 下载状态
|
||||
createTime: number; // 创建时间
|
||||
finishTime?: number; // 完成时间
|
||||
error?: string; // 错误信息(失败时)
|
||||
}
|
||||
44
commons/basic/src/main/ets/models/WXApiWrap.ets
Normal file
@ -0,0 +1,44 @@
|
||||
import * as wxopensdk from '@tencent/wechat_open_sdk';
|
||||
import { APP_ID } from '../constants/Constants';
|
||||
|
||||
export type OnWXReq = (req: wxopensdk.BaseReq) => void
|
||||
export type OnWXResp = (resp: wxopensdk.BaseResp) => void
|
||||
|
||||
const kTag = "WXApiEventHandlerImpl"
|
||||
|
||||
class WXApiEventHandlerImpl implements wxopensdk.WXApiEventHandler {
|
||||
private onReqCallbacks: Map<OnWXReq, OnWXReq> = new Map
|
||||
private onRespCallbacks: Map<OnWXResp, OnWXResp> = new Map
|
||||
|
||||
registerOnWXReqCallback(on: OnWXReq) {
|
||||
this.onReqCallbacks.set(on, on)
|
||||
}
|
||||
unregisterOnWXReqCallback(on: OnWXReq) {
|
||||
this.onReqCallbacks.delete(on)
|
||||
}
|
||||
|
||||
registerOnWXRespCallback(on: OnWXResp) {
|
||||
this.onRespCallbacks.set(on, on)
|
||||
}
|
||||
unregisterOnWXRespCallback(on: OnWXResp) {
|
||||
this.onRespCallbacks.delete(on)
|
||||
}
|
||||
|
||||
onReq(req: wxopensdk.BaseReq): void {
|
||||
wxopensdk.Log.i(kTag, "onReq:%s", JSON.stringify(req))
|
||||
this.onReqCallbacks.forEach((on) => {
|
||||
on(req)
|
||||
})
|
||||
}
|
||||
|
||||
onResp(resp: wxopensdk.BaseResp): void {
|
||||
wxopensdk.Log.i(kTag, "onResp:%s", JSON.stringify(resp))
|
||||
this.onRespCallbacks.forEach((on) => {
|
||||
on(resp)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const WXApi = wxopensdk.WXAPIFactory.createWXAPI(APP_ID)
|
||||
export const WXEventHandler = new WXApiEventHandlerImpl
|
||||
|
||||
@ -111,7 +111,7 @@ export class AESEncryptionDecryption {
|
||||
globalResult = AESEncryptionDecryption.uint8ArrayToString(result.data);
|
||||
console.info('解密后的明文:' + globalResult);
|
||||
} catch (err) {
|
||||
console.info(err.message);
|
||||
console.info('解密失败:',err.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ import { BusinessError } from '@ohos.base'
|
||||
import { KeyboardAvoidMode, window } from '@kit.ArkUI'
|
||||
import { resourceManager } from '@kit.LocalizationKit'
|
||||
import { common } from '@kit.AbilityKit'
|
||||
import display from '@ohos.display'
|
||||
|
||||
export class AppUtil {
|
||||
|
||||
@ -236,6 +237,22 @@ export class AppUtil {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* display width
|
||||
* @returns width in px
|
||||
*/
|
||||
static getDisplayWindowWidth(): Pixels {
|
||||
return px(display.getDefaultDisplaySync().width)
|
||||
}
|
||||
|
||||
/**
|
||||
* display height
|
||||
* @returns height in px
|
||||
*/
|
||||
static getDisplayWindowHeight(): Pixels {
|
||||
return px(display.getDefaultDisplaySync().height)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置沉浸式状态栏
|
||||
* @param isLayoutFullScreen 窗口的布局是否为沉浸式布局(该沉浸式布局状态栏、导航栏仍然显示)。true表示沉浸式布局;false表示非沉浸式布局。
|
||||
@ -342,6 +359,29 @@ export class AppUtil {
|
||||
AppUtil.getContext().terminateSelf();
|
||||
AppUtil.getContext().getApplicationContext().killAllProcesses();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function px(value: number) {
|
||||
return new Pixels(value)
|
||||
}
|
||||
|
||||
export class Pixels {
|
||||
value: number;
|
||||
|
||||
constructor(value: number) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
get px() {
|
||||
return this.value
|
||||
}
|
||||
|
||||
get vp() {
|
||||
return px2vp(this.value)
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `${this.value}px`
|
||||
}
|
||||
}
|
||||
@ -315,6 +315,18 @@ export class ChangeUtil {
|
||||
return height
|
||||
}
|
||||
|
||||
static formatPrice(priceStr: string): string {
|
||||
let priceInFen = parseFloat(priceStr);
|
||||
let priceInYuan = priceInFen / 100;
|
||||
return `${priceInYuan.toFixed(2)}`;
|
||||
}
|
||||
|
||||
static formatPrice2(priceStr: string,discount: string): string {
|
||||
let priceInFen = parseFloat(priceStr);
|
||||
let priceInYuan = priceInFen / 100 * parseFloat(discount);
|
||||
return `${priceInYuan.toFixed(2)}`;
|
||||
}
|
||||
|
||||
static Logout(phone:string)
|
||||
{
|
||||
authStore.delUser();
|
||||
|
||||
366
commons/basic/src/main/ets/utils/FileDownloadManager.ets
Normal file
@ -0,0 +1,366 @@
|
||||
import fileIO from '@ohos.fileio';
|
||||
import request from '@ohos.request';
|
||||
import common from '@ohos.app.ability.common';
|
||||
import hilog from '@ohos.hilog';
|
||||
|
||||
/**
|
||||
* 文件下载状态枚举
|
||||
*/
|
||||
export enum DownloadStatus {
|
||||
DOWNLOADING = 'downloading',
|
||||
COMPLETED = 'completed',
|
||||
FAILED = 'failed'
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件信息接口
|
||||
*/
|
||||
export interface FileInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
url: string;
|
||||
format: string;
|
||||
size: number;
|
||||
status: DownloadStatus;
|
||||
localPath: string;
|
||||
downloadTime: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件下载管理类
|
||||
*/
|
||||
export class FileDownloadManager {
|
||||
private static instance: FileDownloadManager;
|
||||
private downloadQueue: Map<string, FileInfo> = new Map();
|
||||
private downloadTasks: Map<string, request.DownloadTask> = new Map();
|
||||
private context: common.UIAbilityContext;
|
||||
private downloadDir: string = '';
|
||||
|
||||
private constructor(context: common.UIAbilityContext) {
|
||||
this.context = context;
|
||||
this.initDownloadDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单例实例
|
||||
*/
|
||||
public static getInstance(context: common.UIAbilityContext): FileDownloadManager {
|
||||
if (!FileDownloadManager.instance) {
|
||||
FileDownloadManager.instance = new FileDownloadManager(context);
|
||||
}
|
||||
return FileDownloadManager.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化下载目录
|
||||
*/
|
||||
private async initDownloadDirectory(): Promise<void> {
|
||||
try {
|
||||
const filesDir = this.context.filesDir;
|
||||
this.downloadDir = `${filesDir}/downloads`;
|
||||
|
||||
// 检查并创建下载目录
|
||||
try {
|
||||
await fileIO.access(this.downloadDir);
|
||||
} catch {
|
||||
await fileIO.mkdir(this.downloadDir);
|
||||
}
|
||||
} catch (error) {
|
||||
hilog.error(0x0000, 'FileDownloadManager', '初始化下载目录失败: %{public}s', String(error));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始下载文件
|
||||
*/
|
||||
public async downloadFile(url: string,fileId:string, fileName: string, fileType:string): Promise<string> {
|
||||
try {
|
||||
// 从URL中提取文件格式
|
||||
const format = this.extractFileFormat(url);
|
||||
|
||||
// 生成文件名
|
||||
const finalFileName = `${fileName}/${fileId}.${fileType}`;
|
||||
|
||||
// 创建文件信息
|
||||
const fileInfo: FileInfo = {
|
||||
id: fileId,
|
||||
name: finalFileName,
|
||||
url: url,
|
||||
format: format,
|
||||
size: 0,
|
||||
status: DownloadStatus.DOWNLOADING,
|
||||
localPath: `${this.downloadDir}/${finalFileName}`,
|
||||
downloadTime: Date.now()
|
||||
};
|
||||
|
||||
// 添加到下载队列
|
||||
this.downloadQueue.set(fileId, fileInfo);
|
||||
|
||||
// 开始下载
|
||||
await this.startDownload(fileInfo);
|
||||
|
||||
return fileId;
|
||||
} catch (error) {
|
||||
hilog.error(0x0000, 'FileDownloadManager', '下载文件失败: %{public}s', String(error));
|
||||
throw new Error(String(error));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始下载任务
|
||||
*/
|
||||
private async startDownload(fileInfo: FileInfo): Promise<void> {
|
||||
try {
|
||||
const config: request.DownloadConfig = {
|
||||
url: fileInfo.url,
|
||||
title: fileInfo.name,
|
||||
description: '文件下载中...',
|
||||
filePath: fileInfo.localPath,
|
||||
header: {
|
||||
'User-Agent': 'HarmonyOS File Downloader'
|
||||
}
|
||||
};
|
||||
|
||||
const downloadTask = await request.downloadFile(this.context, config);
|
||||
this.downloadTasks.set(fileInfo.id, downloadTask);
|
||||
|
||||
// 监听下载进度
|
||||
downloadTask.on('progress', (receivedSize: number, totalSize: number) => {
|
||||
fileInfo.size = totalSize;
|
||||
this.updateFileInfo(fileInfo);
|
||||
});
|
||||
|
||||
// 监听下载完成
|
||||
downloadTask.on('complete', () => {
|
||||
fileInfo.status = DownloadStatus.COMPLETED;
|
||||
this.updateFileInfo(fileInfo);
|
||||
this.downloadTasks.delete(fileInfo.id);
|
||||
});
|
||||
|
||||
// 监听下载失败
|
||||
downloadTask.on('fail', (err: number) => {
|
||||
fileInfo.status = DownloadStatus.FAILED;
|
||||
this.updateFileInfo(fileInfo);
|
||||
this.downloadTasks.delete(fileInfo.id);
|
||||
hilog.error(0x0000, 'FileDownloadManager', '下载失败: %{public}d', err);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
fileInfo.status = DownloadStatus.FAILED;
|
||||
this.updateFileInfo(fileInfo);
|
||||
throw new Error(String(error));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新文件信息
|
||||
*/
|
||||
private updateFileInfo(fileInfo: FileInfo): void {
|
||||
this.downloadQueue.set(fileInfo.id, fileInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从URL提取文件格式
|
||||
*/
|
||||
private extractFileFormat(url: string): string {
|
||||
const supportedFormats = ['docx', 'txt', 'ppt', 'pdf', 'doc', 'pptx', 'xls', 'xlsx'];
|
||||
const urlParts = url.split('.');
|
||||
const format = urlParts[urlParts.length - 1].toLowerCase();
|
||||
|
||||
return supportedFormats.includes(format) ? format : 'bin';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载状态
|
||||
*/
|
||||
public getDownloadStatus(fileId: string): DownloadStatus | null {
|
||||
const fileInfo = this.downloadQueue.get(fileId);
|
||||
return fileInfo ? fileInfo.status : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件信息
|
||||
*/
|
||||
public getFileInfo(fileId: string): FileInfo | null {
|
||||
return this.downloadQueue.get(fileId) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有文件信息
|
||||
*/
|
||||
public getAllFiles(): FileInfo[] {
|
||||
return Array.from(this.downloadQueue.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定状态的文件
|
||||
*/
|
||||
public getFilesByStatus(status: DownloadStatus): FileInfo[] {
|
||||
return Array.from(this.downloadQueue.values()).filter(file => file.status === status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看单个文件
|
||||
*/
|
||||
public async viewFile(fileId: string): Promise<boolean> {
|
||||
try {
|
||||
const fileInfo = this.downloadQueue.get(fileId);
|
||||
if (!fileInfo || fileInfo.status !== DownloadStatus.COMPLETED) {
|
||||
throw new Error('文件不存在或下载未完成');
|
||||
}
|
||||
|
||||
// 检查文件是否存在
|
||||
try {
|
||||
await fileIO.access(fileInfo.localPath);
|
||||
} catch {
|
||||
throw new Error('文件不存在');
|
||||
}
|
||||
|
||||
// 获取文件信息
|
||||
const stat = await fileIO.stat(fileInfo.localPath);
|
||||
hilog.info(0x0000, 'FileDownloadManager', '文件信息: %{public}s', JSON.stringify(stat));
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
hilog.error(0x0000, 'FileDownloadManager', '查看文件失败: %{public}s', String(error));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看所有文件
|
||||
*/
|
||||
public async viewAllFiles(): Promise<FileInfo[]> {
|
||||
try {
|
||||
const allFiles = this.getAllFiles();
|
||||
const completedFiles: FileInfo[] = [];
|
||||
|
||||
for (const file of allFiles) {
|
||||
if (file.status === DownloadStatus.COMPLETED) {
|
||||
try {
|
||||
await fileIO.access(file.localPath);
|
||||
completedFiles.push(file);
|
||||
} catch {
|
||||
// 文件不存在,跳过
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return completedFiles;
|
||||
} catch (error) {
|
||||
hilog.error(0x0000, 'FileDownloadManager', '查看所有文件失败: %{public}s', String(error));
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单个文件
|
||||
*/
|
||||
public async deleteFile(fileId: string): Promise<boolean> {
|
||||
try {
|
||||
const fileInfo = this.downloadQueue.get(fileId);
|
||||
if (!fileInfo) {
|
||||
throw new Error('文件不存在');
|
||||
}
|
||||
|
||||
// 取消下载任务
|
||||
const downloadTask = this.downloadTasks.get(fileId);
|
||||
if (downloadTask) {
|
||||
downloadTask.off('progress');
|
||||
downloadTask.off('complete');
|
||||
downloadTask.off('fail');
|
||||
this.downloadTasks.delete(fileId);
|
||||
}
|
||||
|
||||
// 删除本地文件
|
||||
if (fileInfo.status === DownloadStatus.COMPLETED) {
|
||||
try {
|
||||
await fileIO.unlink(fileInfo.localPath);
|
||||
} catch {
|
||||
// 文件可能不存在,忽略错误
|
||||
}
|
||||
}
|
||||
|
||||
// 从队列中移除
|
||||
this.downloadQueue.delete(fileId);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
hilog.error(0x0000, 'FileDownloadManager', '删除文件失败: %{public}s', String(error));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除所有文件
|
||||
*/
|
||||
public async deleteAllFiles(): Promise<boolean> {
|
||||
try {
|
||||
const allFiles = Array.from(this.downloadQueue.keys());
|
||||
|
||||
for (const fileId of allFiles) {
|
||||
await this.deleteFile(fileId);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
hilog.error(0x0000, 'FileDownloadManager', '删除所有文件失败: %{public}s', String(error));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停下载
|
||||
*/
|
||||
public pauseDownload(fileId: string): boolean {
|
||||
const downloadTask = this.downloadTasks.get(fileId);
|
||||
if (downloadTask) {
|
||||
downloadTask.off('progress');
|
||||
downloadTask.off('complete');
|
||||
downloadTask.off('fail');
|
||||
this.downloadTasks.delete(fileId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复下载
|
||||
*/
|
||||
public async resumeDownload(fileId: string): Promise<boolean> {
|
||||
try {
|
||||
const fileInfo = this.downloadQueue.get(fileId);
|
||||
if (!fileInfo || fileInfo.status !== DownloadStatus.DOWNLOADING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await this.startDownload(fileInfo);
|
||||
return true;
|
||||
} catch (error) {
|
||||
hilog.error(0x0000, 'FileDownloadManager', '恢复下载失败: %{public}s', String(error));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理下载目录
|
||||
*/
|
||||
// public async cleanDownloadDirectory(): Promise<boolean> {
|
||||
// try {
|
||||
// // 使用fileIO.listDir替代readdir
|
||||
// const files = await fileIO.listDir(this.downloadDir);
|
||||
// for (const file of files) {
|
||||
// const filePath = `${this.downloadDir}/${file}`;
|
||||
// try {
|
||||
// await fileIO.unlink(filePath);
|
||||
// } catch {
|
||||
// // 忽略删除失败的文件
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// } catch (error) {
|
||||
// hilog.error(0x0000, 'FileDownloadManager', '清理下载目录失败: %{public}s', String(error));
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
799
commons/basic/src/main/ets/utils/FileManager.ets
Normal file
@ -0,0 +1,799 @@
|
||||
import { http } from '@kit.NetworkKit';
|
||||
import { promptAction, router } from '@kit.ArkUI';
|
||||
import { common } from '@kit.AbilityKit';
|
||||
import { fileIo, fileUri } from '@kit.CoreFileKit';
|
||||
import { FileInfo,DownloadCallback } from '../models/FileModel'
|
||||
import preferences from '@ohos.data.preferences';
|
||||
import { Want } from '@kit.AbilityKit';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { filePreview } from '@kit.PreviewKit';
|
||||
import request from '@ohos.request';
|
||||
|
||||
// 下载任务接口
|
||||
export interface DownloadTask {
|
||||
httpRequest: http.HttpRequest;
|
||||
filePath: string;
|
||||
}
|
||||
|
||||
// 文件统计信息接口
|
||||
export interface FileStat {
|
||||
size: number;
|
||||
ctime: number;
|
||||
mtime: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件管理类 - 提供下载、查询、预览等功能
|
||||
*/
|
||||
export class FileManager {
|
||||
private context: common.Context;
|
||||
private downloadTasks: Map<string, DownloadTask> = new Map();
|
||||
private downloadCallbacks: Map<string, DownloadCallback> = new Map();
|
||||
private fileCache: Map<string, FileInfo> = new Map();
|
||||
private downloadDir: string;
|
||||
private isDownloading: boolean = false;
|
||||
private preferencesHelper: preferences.Preferences | null = null;
|
||||
private readonly STORE_NAME = 'file_manager_store';
|
||||
private readonly FILE_INFO_KEY = 'file_info_cache';
|
||||
|
||||
constructor(context: common.Context) {
|
||||
this.context = context;
|
||||
this.downloadDir = `${this.context.filesDir}/downloads`;
|
||||
this.initDownloadDirectory();
|
||||
this.initPreferences();
|
||||
this.loadFileInfoFromStorage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化偏好设置存储
|
||||
*/
|
||||
private async initPreferences(): Promise<void> {
|
||||
try {
|
||||
this.preferencesHelper = await preferences.getPreferences(this.context, this.STORE_NAME);
|
||||
} catch (error) {
|
||||
console.error('初始化偏好设置失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从存储加载文件信息
|
||||
*/
|
||||
private async loadFileInfoFromStorage(): Promise<void> {
|
||||
try {
|
||||
if (this.preferencesHelper) {
|
||||
const fileInfoJson = await this.preferencesHelper.get(this.FILE_INFO_KEY, '[]');
|
||||
const fileInfoArray: FileInfo[] = JSON.parse(fileInfoJson as string);
|
||||
|
||||
// 恢复缓存
|
||||
for (const fileInfo of fileInfoArray) {
|
||||
this.fileCache.set(fileInfo.fileId, fileInfo);
|
||||
}
|
||||
|
||||
console.info(`从存储加载了 ${fileInfoArray.length} 个文件信息`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载文件信息失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件信息到存储
|
||||
*/
|
||||
private async saveFileInfoToStorage(): Promise<void> {
|
||||
try {
|
||||
if (this.preferencesHelper) {
|
||||
const fileInfoArray = Array.from(this.fileCache.values());
|
||||
const fileInfoJson = JSON.stringify(fileInfoArray);
|
||||
await this.preferencesHelper.put(this.FILE_INFO_KEY, fileInfoJson);
|
||||
await this.preferencesHelper.flush();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存文件信息失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化下载目录
|
||||
*/
|
||||
private async initDownloadDirectory(): Promise<void> {
|
||||
try {
|
||||
if (!fileIo.accessSync(this.downloadDir)) {
|
||||
fileIo.mkdirSync(this.downloadDir);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('创建下载目录失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
* @param fileInfo 文件信息
|
||||
* @param callback 下载回调
|
||||
* @returns Promise<boolean>
|
||||
*/
|
||||
async downloadFile(fileInfo: FileInfo, callback?: DownloadCallback): Promise<boolean> {
|
||||
try {
|
||||
// 检查是否正在下载
|
||||
if (this.downloadTasks.has(fileInfo.fileId)) {
|
||||
promptAction.showToast({ message: '文件正在下载中,请勿重复操作', duration: 2000 });
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查文件是否已下载
|
||||
if (await this.isFileDownloaded(fileInfo.fileId)) {
|
||||
promptAction.showToast({ message: '文件已下载', duration: 2000 });
|
||||
return true;
|
||||
}
|
||||
|
||||
// 设置下载状态
|
||||
this.isDownloading = true;
|
||||
fileInfo.downloadStatus = 'downloading';
|
||||
fileInfo.downloadProgress = 0;
|
||||
|
||||
// 保存回调
|
||||
if (callback) {
|
||||
this.downloadCallbacks.set(fileInfo.fileId, callback);
|
||||
}
|
||||
|
||||
// 创建下载任务
|
||||
const downloadTask = await this.createDownloadTask(fileInfo);
|
||||
this.downloadTasks.set(fileInfo.fileId, downloadTask);
|
||||
|
||||
// 开始下载
|
||||
const success = await this.startDownload(downloadTask, fileInfo);
|
||||
|
||||
if (success) {
|
||||
fileInfo.downloadStatus = 'downloaded';
|
||||
fileInfo.downloadProgress = 100;
|
||||
this.onDownloadSuccess(fileInfo);
|
||||
} else {
|
||||
fileInfo.downloadStatus = 'failed';
|
||||
this.onDownloadFailed(fileInfo, '下载失败');
|
||||
}
|
||||
|
||||
return success;
|
||||
} catch (error) {
|
||||
console.error('下载文件失败:', error);
|
||||
fileInfo.downloadStatus = 'failed';
|
||||
this.onDownloadFailed(fileInfo, '下载失败');
|
||||
return false;
|
||||
} finally {
|
||||
this.isDownloading = false;
|
||||
this.downloadTasks.delete(fileInfo.fileId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建下载任务
|
||||
*/
|
||||
private async createDownloadTask(fileInfo: FileInfo): Promise<DownloadTask> {
|
||||
try {
|
||||
// 创建文件名目录
|
||||
const fileNameDir = `${fileInfo.fileName}`;
|
||||
const fileNameDirPath = `${this.downloadDir}/${fileNameDir}`;
|
||||
|
||||
// 确保目录存在
|
||||
if (!fileIo.accessSync(fileNameDirPath)) {
|
||||
fileIo.mkdirSync(fileNameDirPath);
|
||||
}
|
||||
|
||||
// 设置文件保存路径 - 格式:文件名/文件ID.文件格式
|
||||
const fileName = `${fileInfo.fileId}.${fileInfo.fileType}`;
|
||||
const filePath = `${fileNameDirPath}/${fileName}`;
|
||||
fileInfo.filePath = filePath;
|
||||
|
||||
// 创建HTTP请求
|
||||
const httpRequest = http.createHttp();
|
||||
|
||||
const task: DownloadTask = {
|
||||
httpRequest: httpRequest,
|
||||
filePath: filePath
|
||||
};
|
||||
|
||||
return task;
|
||||
} catch (error) {
|
||||
console.error('创建下载任务失败:', error);
|
||||
throw new Error('创建下载任务失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
*/
|
||||
private async startDownload(downloadTask: DownloadTask, fileInfo: FileInfo): Promise<boolean> {
|
||||
//
|
||||
// let contexta = getContext(this) as common.UIAbilityContext;
|
||||
// request.downloadFile(contexta.getApplicationContext(), {
|
||||
// url: fileInfo.fileUrl,
|
||||
// filePath: downloadTask.filePath,
|
||||
// enableMetered:true
|
||||
// }).then((downloadTask: request.DownloadTask) => {
|
||||
// let progresCallback = (receivedSize: number, totalSize: number) => {
|
||||
// console.info("downloadddd1 receivedSize:" + receivedSize + " totalSize:" + totalSize);
|
||||
// };
|
||||
// let pauseCallback = () => {
|
||||
// console.info('Downloadddd task pause.');
|
||||
// };
|
||||
// //开启进度回调
|
||||
// downloadTask.on('progress', progresCallback);
|
||||
// //开启暂停回调
|
||||
// downloadTask.on('pause', pauseCallback);
|
||||
// //开启下载完成回调
|
||||
// downloadTask.on('complete', async () => {
|
||||
// const taskInfo = await downloadTask.getTaskInfo();
|
||||
// console.info('downloaddddTask1 complete:'+`status: ${taskInfo.status}`);
|
||||
// // downloadTask.getTaskInfo();
|
||||
//
|
||||
// })
|
||||
// return true
|
||||
// }).catch((err: BusinessError) => {
|
||||
// console.error(`Invoke downloadTask failed, code is ${err.code}, message is ${err.message}`);
|
||||
// return false;
|
||||
// })
|
||||
try {
|
||||
const httpRequest = downloadTask.httpRequest;
|
||||
const filePath = downloadTask.filePath;
|
||||
|
||||
// 配置下载选项 - 参考iOS代码的请求头设置
|
||||
const options: http.HttpRequestOptions = {
|
||||
method: http.RequestMethod.GET,
|
||||
header: {
|
||||
'User-Agent': 'Mozilla/5.0 (Linux; Android 10; HarmonyOS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9',
|
||||
},
|
||||
expectDataType: http.HttpDataType.ARRAY_BUFFER,
|
||||
usingCache: false,
|
||||
connectTimeout: 60000,
|
||||
readTimeout: 300000
|
||||
};
|
||||
|
||||
console.info(`开始下载文件: ${fileInfo.fileUrl}`);
|
||||
console.info(`目标路径: ${filePath}`);
|
||||
|
||||
// 发起下载请求
|
||||
const response = await httpRequest.request(fileInfo.fileUrl, options);
|
||||
|
||||
console.info(`响应状态码: ${response.responseCode}`);
|
||||
console.info(`响应头: ${JSON.stringify(response.header)}`);
|
||||
|
||||
if (response.responseCode === 200) {
|
||||
try {
|
||||
// 验证响应数据
|
||||
if (!response.result) {
|
||||
console.error('下载响应数据为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查数据类型和大小
|
||||
if (!(response.result instanceof ArrayBuffer)) {
|
||||
console.error('响应数据不是ArrayBuffer类型:', typeof response.result);
|
||||
return false;
|
||||
}
|
||||
|
||||
const dataSize = response.result.byteLength;
|
||||
console.info(`下载数据大小: ${dataSize} 字节`);
|
||||
|
||||
if (dataSize <= 10) {
|
||||
console.error('文件有误:',response.result)
|
||||
return false
|
||||
}
|
||||
|
||||
// 确保目标目录存在
|
||||
const dirPath = filePath.substring(0, filePath.lastIndexOf('/'));
|
||||
if (!fileIo.accessSync(dirPath)) {
|
||||
fileIo.mkdirSync(dirPath);
|
||||
}
|
||||
|
||||
// 将下载的数据写入文件
|
||||
const file = fileIo.openSync(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
|
||||
|
||||
try {
|
||||
// 写入文件数据
|
||||
const bytesWritten = fileIo.writeSync(file.fd, response.result);
|
||||
console.info(`写入文件成功,写入字节数: ${bytesWritten}`);
|
||||
|
||||
// 验证写入的字节数
|
||||
if (bytesWritten !== dataSize) {
|
||||
console.error(`写入字节数不匹配: 期望 ${dataSize}, 实际 ${bytesWritten}`);
|
||||
fileIo.closeSync(file);
|
||||
fileIo.unlinkSync(filePath); // 删除损坏的文件
|
||||
return false;
|
||||
}
|
||||
|
||||
// 同步文件到磁盘
|
||||
fileIo.fsyncSync(file.fd);
|
||||
|
||||
// 关闭文件
|
||||
fileIo.closeSync(file);
|
||||
|
||||
// 验证文件是否创建成功
|
||||
if (!fileIo.accessSync(filePath)) {
|
||||
console.error('文件创建失败');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取文件统计信息
|
||||
const stat = fileIo.statSync(filePath);
|
||||
console.info(`文件创建成功: ${filePath}, 大小: ${stat.size} 字节`);
|
||||
|
||||
// 验证文件大小
|
||||
if (stat.size !== dataSize) {
|
||||
console.error(`文件大小不匹配: 期望 ${dataSize}, 实际 ${stat.size}`);
|
||||
fileIo.unlinkSync(filePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新文件信息
|
||||
fileInfo.fileSize = stat.size;
|
||||
await this.saveFileInfo(fileInfo);
|
||||
|
||||
return true;
|
||||
} catch (writeError) {
|
||||
console.error('写入文件失败:', writeError);
|
||||
fileIo.closeSync(file);
|
||||
// 清理可能创建的文件
|
||||
try {
|
||||
if (fileIo.accessSync(filePath)) {
|
||||
fileIo.unlinkSync(filePath);
|
||||
}
|
||||
} catch (cleanupError) {
|
||||
console.error('清理文件失败:', cleanupError);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} catch (writeError) {
|
||||
console.error('文件写入过程失败:', writeError);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
console.error(`下载失败,状态码: ${response.responseCode}`);
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('下载执行失败:', error);
|
||||
return false;
|
||||
} finally {
|
||||
// 销毁HTTP请求
|
||||
downloadTask.httpRequest.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消下载
|
||||
*/
|
||||
async cancelDownload(fileId: string): Promise<boolean> {
|
||||
try {
|
||||
const task = this.downloadTasks.get(fileId);
|
||||
if (task) {
|
||||
// 销毁HTTP请求
|
||||
task.httpRequest.destroy();
|
||||
this.downloadTasks.delete(fileId);
|
||||
|
||||
// 更新状态
|
||||
const fileInfo = this.fileCache.get(fileId);
|
||||
if (fileInfo) {
|
||||
fileInfo.downloadStatus = 'cancelled';
|
||||
fileInfo.downloadProgress = 0;
|
||||
this.onDownloadCancelled(fileInfo);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('取消下载失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询已下载文件
|
||||
*/
|
||||
async getDownloadedFiles(): Promise<FileInfo[]> {
|
||||
try {
|
||||
const files: FileInfo[] = [];
|
||||
|
||||
// 从缓存获取
|
||||
for (const fileInfo of this.fileCache.values()) {
|
||||
if (fileInfo.downloadStatus === 'downloaded') {
|
||||
files.push(fileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// 从本地目录扫描
|
||||
const localFiles = await this.scanLocalFiles();
|
||||
files.push(...localFiles);
|
||||
|
||||
// 按时间排序
|
||||
return files.sort((a, b) => b.updateTime - a.updateTime);
|
||||
} catch (error) {
|
||||
console.error('查询下载文件失败:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描本地文件
|
||||
*/
|
||||
private async scanLocalFiles(): Promise<FileInfo[]> {
|
||||
try {
|
||||
const files: FileInfo[] = [];
|
||||
|
||||
if (!fileIo.accessSync(this.downloadDir)) {
|
||||
return files;
|
||||
}
|
||||
|
||||
const entryList = fileIo.listFileSync(this.downloadDir);
|
||||
|
||||
for (let i = 0; i < entryList.length; i++) {
|
||||
const entryName = entryList[i];
|
||||
const entryPath = `${this.downloadDir}/${entryName}`;
|
||||
|
||||
// 优先按目录处理(当前下载结构是 按文件名建目录,目录下放置 文件ID.扩展名)
|
||||
let childNames: string[] | null = null;
|
||||
try {
|
||||
childNames = fileIo.listFileSync(entryPath);
|
||||
} catch (_e) {
|
||||
childNames = null;
|
||||
}
|
||||
|
||||
if (childNames && childNames.length > 0) {
|
||||
// 目录:遍历子文件
|
||||
for (let j = 0; j < childNames.length; j++) {
|
||||
const childName = childNames[j];
|
||||
const childPath = `${entryPath}/${childName}`;
|
||||
try {
|
||||
const childStat = fileIo.statSync(childPath);
|
||||
const fileInfo = this.parseFileName(childName, childPath, childStat);
|
||||
if (fileInfo) {
|
||||
files.push(fileInfo);
|
||||
}
|
||||
} catch (childErr) {
|
||||
console.error('读取子文件失败:', childErr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 非目录项(兼容旧结构,直接作为文件解析)
|
||||
try {
|
||||
const stat = fileIo.statSync(entryPath);
|
||||
const fileInfo = this.parseFileName(entryName, entryPath, stat);
|
||||
if (fileInfo) {
|
||||
files.push(fileInfo);
|
||||
}
|
||||
} catch (fileErr) {
|
||||
console.error('读取文件失败:', fileErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
} catch (error) {
|
||||
console.error('扫描本地文件失败:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析文件名
|
||||
*/
|
||||
private parseFileName(fileName: string, filePath: string, stat: fileIo.Stat): FileInfo | null {
|
||||
try {
|
||||
// 新的文件名格式: 文件名/文件ID.扩展名
|
||||
const pathParts = filePath.split('/');
|
||||
if (pathParts.length < 2) return null;
|
||||
|
||||
const fileNameDir = pathParts[pathParts.length - 2]; // 文件名目录
|
||||
const fileNameWithExt = pathParts[pathParts.length - 1]; // 文件ID.扩展名
|
||||
|
||||
const fileIdParts = fileNameWithExt.split('.');
|
||||
if (fileIdParts.length < 2) return null;
|
||||
|
||||
const fileId = fileIdParts[0];
|
||||
const extension = fileIdParts[1];
|
||||
|
||||
return {
|
||||
fileId,
|
||||
fileName: fileNameDir, // 使用目录名作为文件名
|
||||
fileType: extension,
|
||||
fileSize: stat.size,
|
||||
fileUrl: '',
|
||||
filePath: filePath,
|
||||
downloadStatus: 'downloaded',
|
||||
downloadProgress: 100,
|
||||
createTime: stat.ctime,
|
||||
updateTime: stat.mtime
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('解析文件名失败:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否已下载
|
||||
*/
|
||||
private async isFileDownloaded(fileId: string): Promise<boolean> {
|
||||
try {
|
||||
// 检查缓存
|
||||
const cachedFile = this.fileCache.get(fileId);
|
||||
if (cachedFile && cachedFile.downloadStatus === 'downloaded') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查本地文件
|
||||
const localFiles = await this.scanLocalFiles();
|
||||
for (let i = 0; i < localFiles.length; i++) {
|
||||
if (localFiles[i].fileId === fileId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('检查文件下载状态失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览文件 - 使用系统原生方法
|
||||
*/
|
||||
async previewFile(identifier: string) {
|
||||
try {
|
||||
// 1) 优先按 uuid 在缓存中查找
|
||||
let target: FileInfo | null = null;
|
||||
const cachedById = this.fileCache.get(identifier);
|
||||
if (cachedById) {
|
||||
target = cachedById;
|
||||
}
|
||||
|
||||
// 2) 若未命中,再按文件名在缓存中查找(取最近更新)
|
||||
if (!target) {
|
||||
let latest: FileInfo | null = null;
|
||||
for (const info of this.fileCache.values()) {
|
||||
if (info.fileName === identifier) {
|
||||
if (!latest || info.updateTime > latest.updateTime) {
|
||||
latest = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
target = latest;
|
||||
}
|
||||
|
||||
// 3) 若缓存仍未命中,扫描本地目录
|
||||
if (!target) {
|
||||
const localFiles = await this.scanLocalFiles();
|
||||
let latest: FileInfo | null = null;
|
||||
for (const info of localFiles) {
|
||||
if (info.fileId === identifier || info.fileName === identifier) {
|
||||
if (!latest || info.updateTime > latest.updateTime) {
|
||||
latest = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
target = latest;
|
||||
}
|
||||
|
||||
if (!target || !target.filePath) {
|
||||
promptAction.showToast({ message: '未找到对应文件', duration: 2000 });
|
||||
return;
|
||||
}
|
||||
|
||||
const filePath = target.filePath;
|
||||
const fileType = target.fileType || '';
|
||||
|
||||
// 文件是否存在
|
||||
if (!fileIo.accessSync(filePath)) {
|
||||
promptAction.showToast({ message: '文件不存在', duration: 2000 });
|
||||
return;
|
||||
}
|
||||
|
||||
let uri = fileUri.getUriFromPath(filePath);
|
||||
filePreview.canPreview(this.context, uri).then((result) => { // 传入支持的文件类型且项目存在时会返回true
|
||||
console.info(`Succeeded in obtaining the result of whether it can be previewed. result = ${result}`);
|
||||
}).catch((err: BusinessError) => {
|
||||
console.error(`Failed to obtain the result of whether it can be previewed, err.code = ${err.code}, err.message = ${err.message}`);
|
||||
});
|
||||
|
||||
let fileInfo: filePreview.PreviewInfo = {
|
||||
title: target.fileName,
|
||||
uri: uri,
|
||||
mimeType: this.getMimeType(fileType)
|
||||
};
|
||||
let files: Array<filePreview.PreviewInfo> = new Array();
|
||||
files.push(fileInfo);
|
||||
filePreview.openPreview(this.context, files, 0).then(() => {
|
||||
console.info('Succeeded in opening preview');
|
||||
}).catch((err: BusinessError) => {
|
||||
console.error(`Failed to open preview, err.code = ${err.code}, err.message = ${err.message}`);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('打开文件异常:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取MIME类型
|
||||
*/
|
||||
private getMimeType(fileType: string): string {
|
||||
const mimeTypes: Record<string, string> = {
|
||||
'pdf': 'application/pdf',
|
||||
'doc': 'application/msword',
|
||||
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'ppt': 'application/vnd.ms-powerpoint',
|
||||
'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'xls': 'application/vnd.ms-excel',
|
||||
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'txt': 'text/plain',
|
||||
'jpg': 'image/jpeg',
|
||||
'jpeg': 'image/jpeg',
|
||||
'png': 'image/png',
|
||||
'gif': 'image/gif',
|
||||
'bmp': 'image/bmp',
|
||||
'mp4': 'video/mp4',
|
||||
'avi': 'video/x-msvideo',
|
||||
'mov': 'video/quicktime',
|
||||
'wmv': 'video/x-ms-wmv'
|
||||
};
|
||||
return mimeTypes[fileType.toLowerCase()] || '*/*';
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*/
|
||||
async deleteFile(identifier: string): Promise<boolean> {
|
||||
try {
|
||||
// 1) 优先按 fileId 在缓存中查找
|
||||
let target: FileInfo | null = null;
|
||||
const cachedById = this.fileCache.get(identifier);
|
||||
if (cachedById) {
|
||||
target = cachedById;
|
||||
}
|
||||
|
||||
// 2) 若未命中,再按文件名在缓存中查找(取最近更新)
|
||||
if (!target) {
|
||||
let latest: FileInfo | null = null;
|
||||
for (const info of this.fileCache.values()) {
|
||||
if (info.fileName === identifier) {
|
||||
if (!latest || info.updateTime > latest.updateTime) {
|
||||
latest = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
target = latest;
|
||||
}
|
||||
|
||||
// 3) 若缓存仍未命中,扫描本地目录
|
||||
if (!target) {
|
||||
const localFiles = await this.scanLocalFiles();
|
||||
let latest: FileInfo | null = null;
|
||||
for (const info of localFiles) {
|
||||
if (info.fileId === identifier || info.fileName === identifier) {
|
||||
if (!latest || info.updateTime > latest.updateTime) {
|
||||
latest = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
target = latest;
|
||||
}
|
||||
|
||||
if (!target || !target.filePath) {
|
||||
console.error('未找到要删除的文件:', identifier);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 删除本地文件
|
||||
if (fileIo.accessSync(target.filePath)) {
|
||||
fileIo.unlinkSync(target.filePath);
|
||||
console.info(`成功删除文件: ${target.filePath}`);
|
||||
|
||||
// 删除文件后,检查并删除空的文件夹
|
||||
await this.cleanupEmptyDirectory(target.filePath);
|
||||
}
|
||||
|
||||
// 从缓存中移除
|
||||
this.fileCache.delete(target.fileId);
|
||||
|
||||
// 更新持久化存储
|
||||
await this.saveFileInfoToStorage();
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('删除文件失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理空文件夹
|
||||
*/
|
||||
private async cleanupEmptyDirectory(filePath: string): Promise<void> {
|
||||
try {
|
||||
// 获取文件所在目录
|
||||
const dirPath = filePath.substring(0, filePath.lastIndexOf('/'));
|
||||
|
||||
// 检查目录是否存在
|
||||
if (!fileIo.accessSync(dirPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查目录是否为空
|
||||
const files = fileIo.listFileSync(dirPath);
|
||||
if (files.length === 0) {
|
||||
// 目录为空,删除目录
|
||||
fileIo.rmdirSync(dirPath);
|
||||
console.info(`成功删除空文件夹: ${dirPath}`);
|
||||
|
||||
// 递归检查父目录是否也为空(但不要删除下载根目录)
|
||||
const parentDir = dirPath.substring(0, dirPath.lastIndexOf('/'));
|
||||
if (parentDir !== this.downloadDir && fileIo.accessSync(parentDir)) {
|
||||
const parentFiles = fileIo.listFileSync(parentDir);
|
||||
if (parentFiles.length === 0) {
|
||||
fileIo.rmdirSync(parentDir);
|
||||
console.info(`成功删除空父文件夹: ${parentDir}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('清理空文件夹失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载状态
|
||||
*/
|
||||
isDownloadingFile(): boolean {
|
||||
return this.isDownloading;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件信息
|
||||
*/
|
||||
private async saveFileInfo(fileInfo: FileInfo): Promise<void> {
|
||||
try {
|
||||
this.fileCache.set(fileInfo.fileId, fileInfo);
|
||||
// 保存到持久化存储
|
||||
await this.saveFileInfoToStorage();
|
||||
} catch (error) {
|
||||
console.error('保存文件信息失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载成功回调
|
||||
*/
|
||||
private onDownloadSuccess(fileInfo: FileInfo): void {
|
||||
const callback = this.downloadCallbacks.get(fileInfo.fileId);
|
||||
if (callback && callback.onSuccess) {
|
||||
callback.onSuccess(fileInfo.filePath || '');
|
||||
}
|
||||
this.downloadCallbacks.delete(fileInfo.fileId);
|
||||
|
||||
promptAction.showToast({ message: '下载完成', duration: 2000 });
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载失败回调
|
||||
*/
|
||||
private onDownloadFailed(fileInfo: FileInfo, error: string): void {
|
||||
const callback = this.downloadCallbacks.get(fileInfo.fileId);
|
||||
if (callback && callback.onFailed) {
|
||||
callback.onFailed(error);
|
||||
}
|
||||
this.downloadCallbacks.delete(fileInfo.fileId);
|
||||
|
||||
promptAction.showToast({ message: error, duration: 2000 });
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载取消回调
|
||||
*/
|
||||
private onDownloadCancelled(fileInfo: FileInfo): void {
|
||||
const callback = this.downloadCallbacks.get(fileInfo.fileId);
|
||||
if (callback && callback.onCancelled) {
|
||||
callback.onCancelled();
|
||||
}
|
||||
this.downloadCallbacks.delete(fileInfo.fileId);
|
||||
|
||||
promptAction.showToast({ message: '下载已取消', duration: 2000 });
|
||||
}
|
||||
}
|
||||
346
commons/basic/src/main/ets/utils/FileManagerCopy.ets
Normal file
@ -0,0 +1,346 @@
|
||||
// 导入必要的鸿蒙模块
|
||||
import http from '@ohos.net.http';
|
||||
import fs from '@ohos.file.fs';
|
||||
import relationalStore from '@ohos.data.relationalStore';
|
||||
import common from '@ohos.app.ability.common';
|
||||
import security from '@ohos.security.cryptoFramework';
|
||||
import util from '@ohos.util';
|
||||
import { BusinessError } from '@ohos.base';
|
||||
import promptAction from '@ohos.promptAction';
|
||||
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
|
||||
import { authStore } from './auth';
|
||||
import { AESEncryptionDecryption } from './AESEncryptionDecryption';
|
||||
import { BasicConstant } from '../constants/BasicConstant';
|
||||
import { rcp } from '@kit.RemoteCommunicationKit';
|
||||
import fileIo from '@ohos.file.fs';
|
||||
|
||||
// 1. 定义数据模型和数据库结构
|
||||
// 文件信息实体
|
||||
class WPSFile {
|
||||
fileId: string = ''; // 对应fileID
|
||||
fileTitle: string = ''; // 对应fileTitle
|
||||
fileType: string = ''; // 对应fileType
|
||||
filePath: string = ''; // 本地存储路径
|
||||
downloadType: string = ''; // 下载状态: 'downloading', 'downloadFalse', 'downloaded'
|
||||
md5?: string = ''; // 文件MD5值
|
||||
}
|
||||
|
||||
// 数据库管理器
|
||||
export class DBManager {
|
||||
private rdbStore: relationalStore.RdbStore | null = null;
|
||||
private readonly TABLE_NAME: string = 'WPSFILELIST';
|
||||
private readonly STORE_CONFIG: relationalStore.StoreConfig = {
|
||||
name: 'WPSFileDB.db',
|
||||
securityLevel: relationalStore.SecurityLevel.S1,
|
||||
};
|
||||
private context: common.Context;
|
||||
|
||||
constructor(context: common.Context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
// 初始化数据库
|
||||
async initializeDB(): Promise<void> {
|
||||
try {
|
||||
this.rdbStore = await relationalStore.getRdbStore(this.context, this.STORE_CONFIG);
|
||||
// 创建表
|
||||
const sql = `
|
||||
CREATE TABLE IF NOT EXISTS ${this.TABLE_NAME} (
|
||||
fileId TEXT PRIMARY KEY,
|
||||
fileTitle TEXT NOT NULL,
|
||||
fileType TEXT NOT NULL,
|
||||
filePath TEXT,
|
||||
downloadType TEXT NOT NULL,
|
||||
md5 TEXT
|
||||
)`;
|
||||
await this.rdbStore.executeSql(sql);
|
||||
console.log('数据库初始化成功');
|
||||
} catch (err) {
|
||||
console.error(`数据库初始化失败: ${err.code}, ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 插入文件记录
|
||||
async insertFile(file: WPSFile): Promise<boolean> {
|
||||
if (!this.rdbStore) {
|
||||
await this.initializeDB();
|
||||
}
|
||||
|
||||
try {
|
||||
const valueBucket: relationalStore.ValuesBucket = {
|
||||
'fileId': file.fileId,
|
||||
'fileTitle': file.fileTitle,
|
||||
'fileType': file.fileType,
|
||||
'filePath': file.filePath,
|
||||
'downloadType': file.downloadType,
|
||||
'md5': file.md5 || ''
|
||||
};
|
||||
|
||||
await this.rdbStore?.insert(this.TABLE_NAME, valueBucket);
|
||||
console.log('文件记录插入成功');
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(`插入文件记录失败: ${err.code}, ${err.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新下载状态
|
||||
async updateDownloadStatus(fileId: string, status: string): Promise<boolean> {
|
||||
if (!this.rdbStore) {
|
||||
await this.initializeDB();
|
||||
}
|
||||
|
||||
try {
|
||||
const valueBucket: relationalStore.ValuesBucket = {
|
||||
'downloadType': status
|
||||
};
|
||||
|
||||
let predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates(this.TABLE_NAME);
|
||||
predicates.equalTo('fileId', fileId);
|
||||
|
||||
await this.rdbStore?.update(valueBucket, predicates);
|
||||
console.log('下载状态更新成功');
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(`更新下载状态失败: ${err.code}, ${err.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 删除文件记录
|
||||
async deleteFile(fileId: string): Promise<boolean> {
|
||||
if (!this.rdbStore) {
|
||||
await this.initializeDB();
|
||||
}
|
||||
|
||||
try {
|
||||
let predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates(this.TABLE_NAME);
|
||||
predicates.equalTo('fileId', fileId);
|
||||
|
||||
await this.rdbStore?.delete(predicates);
|
||||
console.log('文件记录删除成功');
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(`删除文件记录失败: ${err.code}, ${err.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 根据ID查询文件
|
||||
async getFileById(fileId: string): Promise<WPSFile | null> {
|
||||
if (!this.rdbStore) {
|
||||
await this.initializeDB();
|
||||
}
|
||||
|
||||
try {
|
||||
let predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates(this.TABLE_NAME);
|
||||
predicates.equalTo('fileId', fileId);
|
||||
|
||||
let resultSet = await this.rdbStore?.query(predicates, ['fileId', 'fileTitle', 'fileType', 'filePath', 'downloadType', 'md5']);
|
||||
if (resultSet && resultSet.rowCount > 0) {
|
||||
await resultSet.goToFirstRow();
|
||||
let file = new WPSFile();
|
||||
file.fileId = resultSet.getString(resultSet.getColumnIndex('fileId')) || '';
|
||||
file.fileTitle = resultSet.getString(resultSet.getColumnIndex('fileTitle')) || '';
|
||||
file.fileType = resultSet.getString(resultSet.getColumnIndex('fileType')) || '';
|
||||
file.filePath = resultSet.getString(resultSet.getColumnIndex('filePath')) || '';
|
||||
file.downloadType = resultSet.getString(resultSet.getColumnIndex('downloadType')) || '';
|
||||
file.md5 = resultSet.getString(resultSet.getColumnIndex('md5')) || '';
|
||||
resultSet.close();
|
||||
return file;
|
||||
}
|
||||
return null;
|
||||
} catch (err) {
|
||||
console.error(`查询文件失败: ${err.code}, ${err.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 计算文件 MD5 (使用路径创建流)
|
||||
async function calculateFileMD5(filePath: string): Promise<string> {
|
||||
let stream: fs.Stream = fs.createStreamSync(filePath, 'r');
|
||||
let md5AlgName: string = "MD5";
|
||||
let hash: cryptoFramework.Md = cryptoFramework.createMd(md5AlgName);
|
||||
|
||||
let dataBuff: ArrayBuffer = new ArrayBuffer(4096);
|
||||
let readCount: number = stream.readSync(dataBuff);
|
||||
while (readCount > 0) {
|
||||
let messageData: Uint8Array = new Uint8Array(dataBuff.slice(0, readCount));
|
||||
let updateMessageBlob: cryptoFramework.DataBlob = { data: messageData };
|
||||
hash.updateSync(updateMessageBlob);
|
||||
readCount = stream.readSync(dataBuff);
|
||||
}
|
||||
stream.closeSync();
|
||||
|
||||
let md5Result: cryptoFramework.DataBlob = hash.digestSync();
|
||||
let md5Hex: string = Array.from(md5Result.data).map(byte => byte.toString(16).padStart(2, '0')).join('');
|
||||
return md5Hex;
|
||||
}
|
||||
|
||||
// 2. 文件下载管理器
|
||||
export class FileManagerCopy {
|
||||
private httpRequest: http.HttpRequest = http.createHttp();
|
||||
private context: common.Context;
|
||||
private dbManager: DBManager;
|
||||
|
||||
constructor(context: common.Context) {
|
||||
this.context = context;
|
||||
this.dbManager = new DBManager(context);
|
||||
}
|
||||
|
||||
private generateRandomString(): string {
|
||||
// 生成1到10之间的随机整数作为字符串长度[6,8](@ref)
|
||||
const minLength: number = 1;
|
||||
const maxLength: number = 10;
|
||||
const targetLength: number = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;
|
||||
// 初始化一个空数组用于存储字符
|
||||
let charArray: string[] = [];
|
||||
// 循环生成指定数量的随机大写字母[6](@ref)
|
||||
for (let i = 0; i < targetLength; i++) {
|
||||
// 生成65('A')到90('Z')之间的随机数[6](@ref)
|
||||
const randomCharCode: number = Math.floor(Math.random() * 26) + 65;
|
||||
// 将Unicode编码转换为字符并添加到数组
|
||||
charArray.push(String.fromCharCode(randomCharCode));
|
||||
}
|
||||
return charArray.join('');
|
||||
}
|
||||
|
||||
async downloadFile(wpsUuid: string, wpsTitle: string, wpsType: string, fileMd5: string, order_id:string , orderStatus: number, timestamp: string) {
|
||||
// 检查是否正在下载
|
||||
let existingFile = await this.dbManager.getFileById(wpsUuid);
|
||||
if (existingFile && existingFile.downloadType === 'downloading') {
|
||||
promptAction.showToast({ message: '正在下载,请勿重复点击', duration: 2000 });
|
||||
// return false;
|
||||
}
|
||||
|
||||
let daijiami:string = ''
|
||||
if (orderStatus == 1) {//免费
|
||||
daijiami = `${wpsUuid}|${order_id}|${authStore.getUser().uuid}|${timestamp}`
|
||||
}
|
||||
// else if (orderStatus == 8) {//复制iOS代码逻辑,有这样的内容
|
||||
// daijiami = `${wpsUuid}|${orderStatus}|${authStore.getUser().uuid}|${timestamp}`
|
||||
// }
|
||||
else {
|
||||
daijiami = `${wpsUuid}|${order_id}|${authStore.getUser().uuid}|${timestamp}`
|
||||
}
|
||||
// f6f25104fa0345b38074710c9356948b|USEWELFARENUM|1CBMDQbuOX3xbxAcxE5|2025-09-01 11:02:42
|
||||
//ios-//f6f25104fa0345b38074710c9356948b|USEWELFARENUM|GA5LeMOXChsKxMrqFnL|2025-08-29 17:25:54
|
||||
const scanData = await AESEncryptionDecryption.aesEncrypt(daijiami,BasicConstant.ExpertAesKey)
|
||||
//hGaao+F44L7qAHJW3s6SuuJHMpP5jrLrFbPRA6AuJY5jF7eBABjSJDjIJL7uvAusvVMJT9371Bvey44xs48MtAaBPRdKMufmGMUkiOiS/916uiWz8iNWCZMYLa4iKXw3
|
||||
const encodedString = encodeURIComponent(scanData)
|
||||
// hGaao%2BF44L7qAHJW3s6SuuJHMpP5jrLrFbPRA6AuJY5jF7eBABjSJDjIJL7uvAusvVMJT9371Bvey44xs48MtAaBPRdKMufmGMUkiOiS%2F916uiWz8iNWCZMYLa4iKXw3
|
||||
//ios-//hGaao+F44L7qAHJW3s6SuuJHMpP5jrLrFbPRA6AuJY7QHyYsqbbyOz0oyH4orYtJgPbG1eN9syk0G2vJ1oxq9/0V/ZZMHwb7Qu6H1TEVKLsZOInUm1rOJBhY1/hac4Dv
|
||||
let pinString = 'X'+encodedString
|
||||
//XhGaao%2BF44L7qAHJW3s6SuuJHMpP5jrLrFbPRA6AuJY5jF7eBABjSJDjIJL7uvAusvVMJT9371Bvey44xs48MtAaBPRdKMufmGMUkiOiS%2F90X6zMHwPph2jDuPjTMzXqP
|
||||
//ios-//XhGaao+F44L7qAHJW3s6SuuJHMpP5jrLrFbPRA6AuJY7QHyYsqbbyOz0oyH4orYtJgPbG1eN9syk0G2vJ1oxq9/0V/ZZMHwb7Qu6H1TEVKLsZOInUm1rOJBhY1/hac4Dv
|
||||
const targetLength: number = Math.floor(Math.random() * (10 - 1 + 1)) + 1;
|
||||
let downloadUrl = `${BasicConstant.urlExpertApp}downloadGanDanFile?&gdf=${pinString}&a=${targetLength}`
|
||||
//https://dev-app.igandan.com/app/expertApp/downloadGanDanFile?&gdf=XhGaao%2BF44L7qAHJW3s6SuuJHMpP5jrLrFbPRA6AuJY5jF7eBABjSJDjIJL7uvAusvVMJT9371Bvey44xs48MtAaBPRdKMufmGMUkiOiS%2F90X6zMHwPph2jDuPjTMzXqP&a=10
|
||||
//ios-//https://dev-app.igandan.com/app/expertApp/downloadGanDanFile?&gdf=XhGaao+F44L7qAHJW3s6SuuJHMpP5jrLrFbPRA6AuJY7QHyYsqbbyOz0oyH4orYtJgPbG1eN9syk0G2vJ1oxq9/0V/ZZMHwb7Qu6H1TEVKLsZOInUm1rOJBhY1/hac4Dv&a=1
|
||||
|
||||
// 创建下载记录
|
||||
let wpsFile = new WPSFile();
|
||||
wpsFile.fileId = wpsUuid;
|
||||
wpsFile.fileTitle = wpsTitle;
|
||||
wpsFile.fileType = wpsType;
|
||||
wpsFile.downloadType = 'downloading';
|
||||
wpsFile.md5 = fileMd5;
|
||||
|
||||
//下载文件保存的文件夹路径,仅为示例,请按需求进行替换。
|
||||
const DOWNLOAD_TO_PATH = `/data/storage/el2/base/haps/entry/files`;
|
||||
// 创建了一个安全配置对象,其中remoteValidation设置为'skip',表示将跳过远程验证。
|
||||
const securityConfig: rcp.SecurityConfiguration = {
|
||||
remoteValidation: 'skip'
|
||||
}
|
||||
|
||||
// 创建了一个下载配置对象,其中kind设置为'folder',表示下载的目标是文件夹,path设置为之前定义的DOWNLOAD_TO_PATH。
|
||||
let downloadToFile: rcp.DownloadToFile = {
|
||||
kind: 'folder',
|
||||
path: DOWNLOAD_TO_PATH
|
||||
}
|
||||
|
||||
// 创建一个HTTP会话,其中请求配置包括传输超时设置和安全配置(配置可自定义)
|
||||
const session = rcp.createSession({
|
||||
requestConfiguration: {
|
||||
transfer: { timeout: { connectMs: 6000, transferMs: 6000, inactivityMs: 6000 } },
|
||||
security: securityConfig
|
||||
}
|
||||
})
|
||||
|
||||
// 检查目标路径是否存在
|
||||
if (fileIo.accessSync(DOWNLOAD_TO_PATH)) {
|
||||
fileIo.rmdirSync(DOWNLOAD_TO_PATH);
|
||||
}
|
||||
// 发起请求,执行下载操作
|
||||
session.downloadToFile(downloadUrl, downloadToFile)
|
||||
.then((response: rcp.Response) => {
|
||||
console.info(`Successfully received the response, statusCode: ${JSON.stringify(response.statusCode)}`);
|
||||
|
||||
}).catch((err: BusinessError) => {
|
||||
console.error(`Failed, the error message is ${JSON.stringify(err)}`)
|
||||
|
||||
})
|
||||
|
||||
// // 文件保存路径
|
||||
// let filesDir = this.context.filesDir;
|
||||
// wpsFile.filePath = `${filesDir}/${wpsUuid}.${wpsType}`;
|
||||
//
|
||||
// // 插入数据库记录
|
||||
// let insertSuccess = await this.dbManager.insertFile(wpsFile);
|
||||
// if (!insertSuccess) {
|
||||
// promptAction.showToast({ message: '下载初始化失败', duration: 2000 });
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// promptAction.showToast({ message: '开始下载,请勿重复点击', duration: 2000 });
|
||||
//
|
||||
// try {
|
||||
// // 配置下载选项
|
||||
// let options: http.HttpRequestOptions = {
|
||||
// method: http.RequestMethod.GET,
|
||||
// header: {
|
||||
// 'Content-Type': 'application/octet-stream'
|
||||
// },
|
||||
// expectDataType: http.HttpDataType.ARRAY_BUFFER,
|
||||
// usingCache: false,
|
||||
// };
|
||||
//
|
||||
// // 执行下载请求
|
||||
// let response = await this.httpRequest.request(downloadUrl, options);
|
||||
// if (response.responseCode === 200) {
|
||||
// // 保存文件到本地
|
||||
// let file = fs.openSync(wpsFile.filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
|
||||
// fs.writeSync(file.fd, response.result as ArrayBuffer);
|
||||
// fs.closeSync(file);
|
||||
//
|
||||
// // 验证MD5
|
||||
// let localMd5 = await calculateFileMD5(wpsFile.filePath)
|
||||
// if (localMd5 === fileMd5) {
|
||||
// // 更新数据库状态为下载成功
|
||||
// await this.dbManager.updateDownloadStatus(wpsUuid, 'downloaded');
|
||||
// promptAction.showToast({ message: '下载完成', duration: 2000 });
|
||||
// return true;
|
||||
// } else {
|
||||
// // MD5不匹配,删除文件
|
||||
// fs.unlinkSync(wpsFile.filePath);
|
||||
// await this.dbManager.deleteFile(wpsUuid);
|
||||
// promptAction.showToast({ message: '下载失败,文件校验错误', duration: 2000 });
|
||||
// return false;
|
||||
// }
|
||||
// } else {
|
||||
// // 下载失败
|
||||
// await this.dbManager.deleteFile(wpsUuid);
|
||||
// promptAction.showToast({ message: '下载失败,请重试', duration: 2000 });
|
||||
// return false;
|
||||
// }
|
||||
// } catch (err) {
|
||||
// // 异常处理
|
||||
// await this.dbManager.deleteFile(wpsUuid);
|
||||
// console.error(`下载失败: ${err.code}, ${err.message}`);
|
||||
// promptAction.showToast({ message: '下载失败,请重试', duration: 2000 });
|
||||
// return false;
|
||||
// }
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,7 @@ import { deviceInfo } from '@kit.BasicServicesKit';
|
||||
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
|
||||
import { rcp } from '@kit.RemoteCommunicationKit';
|
||||
import { BasicConstant } from '../../../../Index';
|
||||
import { connection } from '@kit.NetworkKit';
|
||||
|
||||
interface HdRequestOptions {
|
||||
baseURL?: string
|
||||
@ -26,8 +27,14 @@ export interface HdResponse<T> {
|
||||
}
|
||||
export interface TimestampBean {
|
||||
timestamp:string
|
||||
}
|
||||
|
||||
|
||||
export enum NetworkStatus {
|
||||
type_default = 0,//无网络
|
||||
type_wifi = 1,//wifi
|
||||
type_traffic = 2,//蜂窝网络类型(2G/3G/4G/5G)
|
||||
type_unknown = 3,//未知网络
|
||||
type_error = -1,//失败
|
||||
}
|
||||
|
||||
class HdHttp {
|
||||
@ -431,6 +438,30 @@ class HdHttp {
|
||||
return result === 0 ? (a < b ? -1 : 1) : result;
|
||||
});
|
||||
}
|
||||
|
||||
getNetworkType():number {
|
||||
try {
|
||||
let netHandle = connection.getDefaultNetSync()
|
||||
if (!netHandle || netHandle.netId === 0) {
|
||||
console.info('当前网络状态:无网络')
|
||||
return NetworkStatus.type_default;
|
||||
}
|
||||
let netCap = connection.getNetCapabilitiesSync(netHandle);
|
||||
if (netCap.bearerTypes.includes(connection.NetBearType.BEARER_WIFI)) {
|
||||
console.info('当前网络状态:wifi')
|
||||
return NetworkStatus.type_wifi;
|
||||
} else if (netCap.bearerTypes.includes(connection.NetBearType.BEARER_CELLULAR)) {
|
||||
console.info('当前网络状态:2G/3G/4G/5G')
|
||||
return NetworkStatus.type_traffic;
|
||||
} else {
|
||||
console.info('当前网络状态:未知网络')
|
||||
return NetworkStatus.type_unknown;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Get net type failed, error: " + JSON.stringify(error));
|
||||
return NetworkStatus.type_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface DataBlob {
|
||||
|
||||
BIN
commons/basic/src/main/resources/base/media/fenxiang.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
commons/basic/src/main/resources/base/media/huise_kongquan.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
commons/basic/src/main/resources/base/media/wei_dian_zan.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
commons/basic/src/main/resources/base/media/wei_shou_cang.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
commons/basic/src/main/resources/base/media/yi_dian_zan.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
commons/basic/src/main/resources/base/media/yi_shou_cang.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
179
features/Home/src/main/ets/components/HomeGanDanFileComp.ets
Normal file
@ -0,0 +1,179 @@
|
||||
import { gandanfileModel, guideModel } from "../model/HomeModel";
|
||||
|
||||
@Component
|
||||
export struct HomeGanDanFileComp {
|
||||
@Prop gandanFileList:gandanfileModel[]
|
||||
@Prop guideList:guideModel[]
|
||||
@State currentIndex: number = 0
|
||||
private tabsController: TabsController = new TabsController()
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
this.headerView()
|
||||
this.tabContent()
|
||||
}
|
||||
.width('100%')
|
||||
.backgroundColor('#F5F5F5')
|
||||
}
|
||||
|
||||
@Builder
|
||||
headerView() {
|
||||
Stack() {
|
||||
Row() {
|
||||
Image($r('app.media.home_guideAndShare_icon'))
|
||||
.width('70%')
|
||||
.height(50)
|
||||
.objectFit(ImageFit.Cover)
|
||||
}
|
||||
.width('100%')
|
||||
.height(50)
|
||||
.justifyContent(FlexAlign.End)
|
||||
|
||||
Row() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text('实用指南')
|
||||
.fontSize(this.currentIndex === 0 ? 17 :14)
|
||||
.fontColor(this.currentIndex === 0 ? '#000000' : '#666666')
|
||||
.fontWeight(this.currentIndex === 0 ? FontWeight.Bold : FontWeight.Normal)
|
||||
Blank()
|
||||
.width(32)
|
||||
.height(2)
|
||||
.margin({top:5})
|
||||
.backgroundColor($r('app.color.main_color'))
|
||||
.visibility(this.currentIndex == 0? Visibility.Visible: Visibility.Hidden)
|
||||
}
|
||||
.width(80)
|
||||
.height(50)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.onClick(() => {
|
||||
this.currentIndex = 0
|
||||
this.tabsController.changeIndex(0)
|
||||
})
|
||||
|
||||
Column() {
|
||||
Text('课件分享')
|
||||
.fontSize(this.currentIndex === 1 ? 17 : 14)
|
||||
.fontColor(this.currentIndex === 1 ? '#000000' : '#666666')
|
||||
.fontWeight(this.currentIndex === 1 ? FontWeight.Bold : FontWeight.Normal)
|
||||
Blank()
|
||||
.width(32)
|
||||
.height(2)
|
||||
.margin({top:5})
|
||||
.backgroundColor($r('app.color.main_color'))
|
||||
.visibility(this.currentIndex == 1? Visibility.Visible: Visibility.Hidden)
|
||||
}
|
||||
.width(80)
|
||||
.height(50)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.onClick(() => {
|
||||
this.currentIndex = 1
|
||||
this.tabsController.changeIndex(1)
|
||||
})
|
||||
}
|
||||
.width('80%')
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.margin({ left: 15 })
|
||||
|
||||
Row() {
|
||||
Text('更多')
|
||||
.fontSize(15)
|
||||
.fontColor('#999999')
|
||||
Image($r('app.media.arrow_right'))
|
||||
.width(10)
|
||||
.height(15)
|
||||
.margin({ left: 5 })
|
||||
}
|
||||
.width(100)
|
||||
.height('100%')
|
||||
.padding({right:10})
|
||||
}
|
||||
.width('100%')
|
||||
.height(60)
|
||||
.alignItems(VerticalAlign.Center)
|
||||
}
|
||||
.width('100%')
|
||||
.height(50)
|
||||
.backgroundColor(Color.White)
|
||||
}
|
||||
|
||||
@Builder
|
||||
tabContent() {
|
||||
Tabs({ index: this.currentIndex, controller: this.tabsController }) {
|
||||
TabContent() {
|
||||
this.BuildGuideList()
|
||||
}
|
||||
TabContent() {
|
||||
this.BuildShareList()
|
||||
}
|
||||
}
|
||||
.onChange((index: number) => {
|
||||
this.currentIndex = index
|
||||
})
|
||||
.width('100%')
|
||||
.barWidth(0)
|
||||
.animationDuration(0)
|
||||
.backgroundColor(Color.White)
|
||||
}
|
||||
|
||||
@Builder
|
||||
BuildGuideList() {
|
||||
Column() {
|
||||
this.BuildListItem(
|
||||
'一学就会的keynote教程番外篇】keynote 线下实训你们要的带练来了',
|
||||
'查看'
|
||||
)
|
||||
|
||||
this.BuildListItem(
|
||||
'胆源性肝脏疾病一专题研讨会成功举行',
|
||||
'查看'
|
||||
)
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
|
||||
// 构建课件分享列表
|
||||
@Builder
|
||||
BuildShareList() {
|
||||
Column() {
|
||||
this.BuildListItem(
|
||||
'肝病学新领域:肝硬化合并慢性肾脏病 | 深度综述大的并慢性肾脏病 | 深度综述并慢并慢性...',
|
||||
'↓'
|
||||
)
|
||||
|
||||
this.BuildListItem(
|
||||
'【一学就会的keynote教程番外篇】keynote 线下实训你们要的带练来了',
|
||||
'↓'
|
||||
)
|
||||
|
||||
this.BuildListItem(
|
||||
'段钟平教授:终末期肝病营养治疗的价值及研究进展',
|
||||
'↓'
|
||||
)
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
|
||||
// 构建列表项
|
||||
@Builder
|
||||
BuildListItem(title: string, action: string) {
|
||||
Row() {
|
||||
Text(title)
|
||||
.fontSize(14)
|
||||
.fontColor('#000000')
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
.maxLines(2)
|
||||
.layoutWeight(1)
|
||||
|
||||
Text(action)
|
||||
.fontSize(14)
|
||||
.fontColor('#FF0000')
|
||||
.margin({ left: 10 })
|
||||
}
|
||||
.width('95%')
|
||||
.padding(10)
|
||||
.backgroundColor('#f4f4f4')
|
||||
.borderRadius(8)
|
||||
.margin({ left: 10, bottom: 10, right:10 })
|
||||
}
|
||||
}
|
||||
@ -26,6 +26,7 @@ export struct HomeIconComp {
|
||||
@State consultation: string = '公益咨询';
|
||||
@State consultationRed: boolean = false;
|
||||
@State iconListtmp:iconsModel[]=[];
|
||||
|
||||
listener: (info: uiObserver.RouterPageInfo) => void = (info: uiObserver.RouterPageInfo) => {
|
||||
let routerInfo: uiObserver.RouterPageInfo | undefined = this.queryRouterPageInfo();
|
||||
if (info.pageId == routerInfo?.pageId) {
|
||||
@ -36,6 +37,7 @@ export struct HomeIconComp {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aboutToAppear(): void {
|
||||
let uiObserver: UIObserver = this.getUIContext().getUIObserver();
|
||||
uiObserver.on('routerPageUpdate', this.listener);
|
||||
@ -79,52 +81,39 @@ export struct HomeIconComp {
|
||||
{
|
||||
consultcount++
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
unreadCount=unreadCount-consultcount
|
||||
if(unreadCount>0)
|
||||
{
|
||||
if(unreadCount>0) {
|
||||
this.patientRed=true
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this.patientRed=false
|
||||
hdHttp.post<string>(BasicConstant.applyList,{
|
||||
expertUuid: authStore.getUser().uuid,
|
||||
} as updateExtraData).then(async (res: HdResponse<string>) => {
|
||||
let json:applyListCallBacl = JSON.parse(res+'') as applyListCallBacl;
|
||||
if(json.code == 1) {
|
||||
if(json.data!=null&&json.data.length>0)
|
||||
{
|
||||
if(json.data!=null&&json.data.length>0) {
|
||||
this.patientRed=true
|
||||
}
|
||||
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
|
||||
})
|
||||
}
|
||||
if(consultcount>0)
|
||||
{
|
||||
if(consultcount>0) {
|
||||
this.consultationRed=true
|
||||
}
|
||||
|
||||
this.initList()
|
||||
const hashMap: HashMap<string, string> = new HashMap();
|
||||
hdHttp.httpReq<string>(BasicConstant.indexV2,hashMap).then(async (res: HdResponse<string>) => {
|
||||
let json:HomeModel = JSON.parse(res+'') as HomeModel;
|
||||
if(json.data!=null&&json.data.consult_list!=null&&json.data.consult_list.list!=null)
|
||||
{
|
||||
if(json.data!=null&&json.data.consult_list!=null&&json.data.consult_list.list!=null) {
|
||||
consultcount=consultcount>0?consultcount:json.data.consult_list.list.length
|
||||
if(consultcount>0)
|
||||
{
|
||||
if(consultcount>0) {
|
||||
this.consultationRed=true
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this.consultationRed=false
|
||||
}
|
||||
this.initList()
|
||||
@ -132,17 +121,18 @@ export struct HomeIconComp {
|
||||
}).catch((err: BusinessError) => {
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
initList()
|
||||
{
|
||||
initList() {
|
||||
const targetNews:iconsModel | undefined = this.iconList.find((model: iconsModel) => model.name === '肝胆新闻');
|
||||
const targekejian:iconsModel | undefined = this.iconList.find((model: iconsModel) => model.name === '肝胆课件');
|
||||
this.iconListtmp=[...[{ 'img': this.patientIcon, 'name': this.patientName,'isRed':this.patientRed } as iconsModel,
|
||||
{ 'img': this.videoIcon, 'name': this.videoName} as iconsModel,
|
||||
{'img':this.zixunIcon,'name':this.consultation,'isRed':this.consultationRed} as iconsModel]]
|
||||
{'img':this.zixunIcon,'name':this.consultation,'isRed':this.consultationRed} as iconsModel],
|
||||
{'img':targekejian == undefined?$r('app.media.home_kejian_icon'):targekejian?.img,'name':'肝胆课件','isRed':false} as iconsModel,
|
||||
{'img':targetNews == undefined?$r('app.media.home_news_icon'):targetNews?.img,'name':'肝胆新闻','isRed':false} as iconsModel]
|
||||
}
|
||||
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Grid() {
|
||||
@ -173,8 +163,15 @@ export struct HomeIconComp {
|
||||
url:'pages/VideoPage/VideoGandanPage',
|
||||
params:{"page":"首页"}
|
||||
})
|
||||
} else if (item.name == '肝胆新闻') {
|
||||
router.pushUrl({
|
||||
url:'pages/News/GandanNewsPages'
|
||||
})
|
||||
} else if (item.name == '肝胆课件') {
|
||||
router.pushUrl({
|
||||
url:'pages/Courseware/CoursewarePage'
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
}.width('100%').backgroundColor(Color.White)
|
||||
|
||||
@ -10,6 +10,7 @@ import { BasicConstant,hdHttp, HdResponse ,logger,HdHomeNav, ChangeUtil} from '@
|
||||
import { HomeModel,dataModel, newsModel,iconsModel } from '../model/HomeModel';
|
||||
import { DefaultHintProWindows,SignPopWindow,HdLoadingDialog } from '@itcast/basic'
|
||||
import { promptAction, router } from '@kit.ArkUI';
|
||||
import { HomeGanDanFileComp } from '../components/HomeGanDanFileComp'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
@ -158,6 +159,9 @@ export struct HomePage {
|
||||
if (this.homeData.video_list && this.homeData.video_list.length > 0) {
|
||||
HomeReplayVideoComp({ videoList: this.homeData.video_list })
|
||||
}
|
||||
if (this.homeData.gandanfile_list && this.homeData.gandanfile_list.length > 0) {
|
||||
HomeGanDanFileComp({ gandanFileList:this.homeData.gandanfile_list,guideList:this.homeData.guide_ist })
|
||||
}
|
||||
}
|
||||
}
|
||||
.edgeEffect(EdgeEffect.Spring)
|
||||
|
||||
@ -75,6 +75,18 @@ export struct VideoGandan {
|
||||
})
|
||||
})
|
||||
|
||||
Image($r('app.media.send_follow_icon'))
|
||||
.width(48)
|
||||
.height(48)
|
||||
.position({ x: '100%', y: '100%' })
|
||||
.translate({ x: -48, y: -176 })
|
||||
.visibility(ChangeUtil.stringIsUndefinedAndNull(this.rightBottom)?Visibility.None:Visibility.Visible)
|
||||
.onClick(()=>{
|
||||
router.pushUrl({
|
||||
url: 'pages/Pay/SendFollowPage'
|
||||
})
|
||||
})
|
||||
|
||||
Image(BasicConstant.urlImage+this.rightBottom)
|
||||
.width(76)
|
||||
.height(40)
|
||||
|
||||
@ -12,7 +12,7 @@ import { http } from '@kit.NetworkKit';
|
||||
@Entry
|
||||
@Component
|
||||
export struct VideoPage {
|
||||
|
||||
@State params:Record<string, string> = router.getParams() as Record<string, string>
|
||||
@State notselectImg: ResourceStr = $r('app.media.triangle_normal');
|
||||
@State selectImg: ResourceStr = $r('app.media.triangle_green_theme');
|
||||
@State monthWords:Array<string> =[]
|
||||
@ -42,7 +42,7 @@ export struct VideoPage {
|
||||
{
|
||||
Column()
|
||||
{
|
||||
HdNav({ title: '肝胆会议', showRightIcon: false, showLeftIcon: false,showRightText:true,rightText:'扫一扫',rightTextColor:$r('app.color.main_color'),rightItemAction:()=>{
|
||||
HdNav({ title: '肝胆会议',showLeftIcon:this.params?true:false, showRightIcon: false,showRightText:true,rightText:'扫一扫',rightTextColor:$r('app.color.main_color'),rightItemAction:()=>{
|
||||
if (ScanUtil.canIUseScan()) {
|
||||
ScanUtil.startScanForResult().then((scanResult) => {
|
||||
decryptString(scanResult.originalValue)
|
||||
|
||||
|
After Width: | Height: | Size: 32 KiB |
BIN
features/Home/src/main/resources/base/media/home_kejian_icon.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
features/Home/src/main/resources/base/media/home_news_icon.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
BIN
features/Home/src/main/resources/base/media/send_follow_icon.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
@ -4,9 +4,13 @@ import { TwoSection } from '../view/TwoSection'
|
||||
import { ThreeSection } from '../view/ThreeSection'
|
||||
import { FourSection } from '../view/FourSection'
|
||||
import { OtherList } from '../view/OtherList'
|
||||
import { HdNav,hdHttp,HdResponse,BasicConstant,ExpertData,authStore,RequestDefaultModel } from '@itcast/basic'
|
||||
import { HdNav,hdHttp,HdResponse,BasicConstant,ExpertData,authStore,RequestDefaultModel,
|
||||
ChangeUtil,
|
||||
logger,
|
||||
HdLoadingDialog} from '@itcast/basic'
|
||||
import { BusinessError, emitter } from '@kit.BasicServicesKit';
|
||||
import HashMap from '@ohos.util.HashMap'
|
||||
import { router } from '@kit.ArkUI'
|
||||
|
||||
interface heroFirst {
|
||||
id: string;
|
||||
@ -18,13 +22,23 @@ export struct MyHomePage {
|
||||
@State title: string = '我的';
|
||||
@StorageProp('topHeight')
|
||||
topHeight: number = 0
|
||||
@State rightBottom:string = ''
|
||||
@State rightBottomPath:string = ''
|
||||
@State rightBottomTitle:string = ''
|
||||
|
||||
@State myInfoBackGround:string = '';
|
||||
@State heroArray:Array<object> = [];
|
||||
@State expertData:object | string = new Object;
|
||||
scroller = new Scroller()
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.getAppActivity()
|
||||
this.uploadBackImgAction();
|
||||
emitter.on({ eventId: BasicConstant.notification_home_tab_change }, (eventData: emitter.EventData) => {
|
||||
if (eventData.data?.changeIndex === 2) {
|
||||
@ -61,6 +75,25 @@ export struct MyHomePage {
|
||||
})
|
||||
}
|
||||
|
||||
getAppActivity() {
|
||||
const hashMap: HashMap<string, string> = new HashMap()
|
||||
this.dialog.open()
|
||||
hashMap.clear()
|
||||
hashMap.set('id','6')
|
||||
hdHttp.httpReq<string>(BasicConstant.getAppActivity,hashMap).then(async (res: HdResponse<string>) => {
|
||||
logger.info('Response addBonusPoints'+res)
|
||||
this.dialog.close()
|
||||
let json:Record<string,string | Record<string,string>> = JSON.parse(res+'') as Record<string,string | Record<string,string>>
|
||||
if (json.code == '200') {
|
||||
this.rightBottom = json.data['img']
|
||||
this.rightBottomPath = json.data['url_path']
|
||||
this.rightBottomTitle = json.data['name']
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close()
|
||||
})
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
HdNav({ title: '我的', showLeftIcon:false , showRightIcon: false, hasBorder: true })
|
||||
@ -73,6 +106,8 @@ export struct MyHomePage {
|
||||
Column() {
|
||||
HeaderView({heroArray:this.heroArray,expertData:this.expertData})
|
||||
OneSection()
|
||||
TwoSection()
|
||||
ThreeSection()
|
||||
FourSection()
|
||||
OtherList()
|
||||
}
|
||||
@ -83,6 +118,20 @@ export struct MyHomePage {
|
||||
.layoutWeight(1)
|
||||
.scrollBar(BarState.Off)
|
||||
.align(Alignment.TopStart)
|
||||
|
||||
|
||||
Image(BasicConstant.urlImage+this.rightBottom)
|
||||
.width(76)
|
||||
.height(40)
|
||||
.position({ x: '100%', y: '100%' })
|
||||
.translate({ x: -76, y: -76 })
|
||||
.visibility(ChangeUtil.stringIsUndefinedAndNull(this.rightBottom)?Visibility.None:Visibility.Visible)
|
||||
.onClick(()=>{
|
||||
router.pushUrl({
|
||||
url: 'pages/WebView/WebPage',
|
||||
params: {'title':this.rightBottomTitle,'url':this.rightBottomPath}
|
||||
})
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { it } from "@ohos/hypium";
|
||||
import { MyPageSectionClass } from "../model/MyPageSectionClass";
|
||||
import { MyPageSectionItem } from '../view/MyPageSectionItem'
|
||||
import { router } from "@kit.ArkUI";
|
||||
|
||||
@Preview
|
||||
@Component
|
||||
@ -9,12 +10,12 @@ export struct ThreeSection {
|
||||
@State currentIndex: number = 0;
|
||||
|
||||
@State threeSectionList:Array<MyPageSectionClass> = [
|
||||
new MyPageSectionClass('oneItem',$r('app.media.app_icon'),'我的账户','/pages/MyHomePage',false),
|
||||
new MyPageSectionClass('twoItem',$r('app.media.app_icon'),'我的积分','/pages/MyHomePage',false),
|
||||
new MyPageSectionClass('threeItem',$r('app.media.app_icon'),'我的福利','/pages/MyHomePage',false),
|
||||
new MyPageSectionClass('fourItem',$r('app.media.app_icon'),'我的鲜花','/pages/MyHomePage',false),
|
||||
new MyPageSectionClass('fiveItem',$r('app.media.app_icon'),'课件明细','/pages/MyHomePage',false),
|
||||
new MyPageSectionClass('fiveItem',$r('app.media.app_icon'),'课程明细','/pages/MyHomePage',false)
|
||||
// new MyPageSectionClass('oneItem',$r('app.media.app_icon'),'我的账户','/pages/MyHomePage',false),
|
||||
// new MyPageSectionClass('twoItem',$r('app.media.app_icon'),'我的积分','/pages/MyHomePage',false),
|
||||
// new MyPageSectionClass('threeItem',$r('app.media.app_icon'),'我的福利','/pages/MyHomePage',false),
|
||||
new MyPageSectionClass('oneItem',$r('app.media.my_page_myFlower'),'我的鲜花','pages/Flower/FlowerDetailsPage',false),
|
||||
new MyPageSectionClass('twoItem',$r("app.media.my_page_coursewareDetails"),'课件明细','/pages/MyHomePage',false),
|
||||
// new MyPageSectionClass('fiveItem',$r('app.media.app_icon'),'课程明细','/pages/MyHomePage',false)
|
||||
];
|
||||
|
||||
private getPagedItems(): Array<Array<MyPageSectionClass>> {
|
||||
@ -43,6 +44,11 @@ export struct ThreeSection {
|
||||
ForEach(pageItems, (item: MyPageSectionClass) => {
|
||||
GridItem() {
|
||||
MyPageSectionItem({ sectionItem: item })
|
||||
.onClick(()=>{
|
||||
router.pushUrl({
|
||||
url:item.path
|
||||
})
|
||||
})
|
||||
}
|
||||
}, (item: MyPageSectionClass) => item.id)
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { it } from "@ohos/hypium";
|
||||
import { MyPageSectionClass } from "../model/MyPageSectionClass";
|
||||
import { MyPageSectionItem } from '../view/MyPageSectionItem'
|
||||
import { router } from "@kit.ArkUI";
|
||||
|
||||
@Preview
|
||||
@Component
|
||||
@ -9,10 +10,10 @@ export struct TwoSection {
|
||||
@State currentIndex: number = 0;
|
||||
|
||||
@State twoSectionList:Array<MyPageSectionClass> = [
|
||||
new MyPageSectionClass('oneItem',$r('app.media.app_icon'),'我的视频','/pages/MyHomePage',false),
|
||||
new MyPageSectionClass('twoItem',$r('app.media.app_icon'),'我的课程','/pages/MyHomePage',false),
|
||||
new MyPageSectionClass('threeItem',$r('app.media.app_icon'),'我的下载','/pages/MyHomePage',false),
|
||||
new MyPageSectionClass('fourItem',$r('app.media.app_icon'),'我的收藏','/pages/MyHomePage',false)
|
||||
// new MyPageSectionClass('oneItem',$r('app.media.app_icon'),'我的视频','pages/MyHomePage',false),
|
||||
// new MyPageSectionClass('twoItem',$r('app.media.app_icon'),'我的课程','pages/MyHomePage',false),
|
||||
new MyPageSectionClass('oneItem',$r('app.media.my_page_download'),'我的下载','pages/Download/AllDownloadPage',false),
|
||||
// new MyPageSectionClass('fourItem',$r('app.media.app_icon'),'我的收藏','pages/MyHomePage',false)
|
||||
];
|
||||
|
||||
private getPagedItems(): Array<Array<MyPageSectionClass>> {
|
||||
@ -41,6 +42,11 @@ export struct TwoSection {
|
||||
ForEach(pageItems, (item: MyPageSectionClass) => {
|
||||
GridItem() {
|
||||
MyPageSectionItem({ sectionItem: item })
|
||||
.onClick(()=>{
|
||||
router.pushUrl({
|
||||
url:item.path
|
||||
})
|
||||
})
|
||||
}
|
||||
}, (item: MyPageSectionClass) => item.id)
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
@ -2,4 +2,18 @@ export { SchoolhouseComp } from './src/main/ets/components/SchoolhouseComp';
|
||||
|
||||
export { KeepStudyComp } from './src/main/ets/components/KeepStudyComp';
|
||||
|
||||
export { CoursewareComp } from './src/main/ets/components/CoursewareComp';
|
||||
export { CoursewareComp } from './src/main/ets/components/CoursewareComp';
|
||||
|
||||
export { PayComp } from './src/main/ets/components/PayComp'
|
||||
|
||||
export { NewsComp } from './src/main/ets/components/NewsComp'
|
||||
|
||||
export { newsUtil } from './src/main/ets/utils/NewsUtil'
|
||||
|
||||
export { newsRollNewRequest,newsRequestOfData } from './src/main/ets/models/NewsModel'
|
||||
|
||||
export { NewsListComp } from './src/main/ets/components/NewsListComp'
|
||||
|
||||
export { SendFollowComp } from './src/main/ets/components/SendFollowComp'
|
||||
|
||||
export { FlowerDetailsComp } from './src/main/ets/components/FlowerDetailsComp'
|
||||
@ -242,6 +242,9 @@ export struct CoursewareComp {
|
||||
ForEach(this.data, (item: KeJianModel) => {
|
||||
ListItem() {
|
||||
KeJianItemComp({item:item})
|
||||
.onClick(()=>{
|
||||
router.pushUrl({url:"pages/WebView/KeJianDetailsWebPage",params:{"model":item}})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
232
features/study/src/main/ets/components/FlowerDetailsComp.ets
Normal file
@ -0,0 +1,232 @@
|
||||
import { BasicConstant, ChangeUtil, EmptyViewComp, hdHttp, HdLoadingDialog, HdNav, HdResponse } from '@itcast/basic';
|
||||
import { PullToRefreshLayout, RefreshController } from 'refreshlib';
|
||||
import { HashMap } from '@kit.ArkTS';
|
||||
import { promptAction } from '@kit.ArkUI';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
|
||||
@Component
|
||||
export struct FlowerDetailsComp {
|
||||
public controller:RefreshController = new RefreshController();
|
||||
scroller = new Scroller();
|
||||
@State pageNumber:number = 1;
|
||||
@State totalPageNumer:number = 1;
|
||||
@State flowerList:flowerListData[] = []
|
||||
@State isEmptyViewVisible: boolean = false; // 控制显隐的状态变量
|
||||
@State allFlower:string = '0'
|
||||
@State allTotalNum:string = '0.00'
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.getFlowetListData()
|
||||
}
|
||||
|
||||
getFlowetListData() {
|
||||
const hashMap: HashMap<string, string> = new HashMap();
|
||||
hashMap.set('page',this.pageNumber.toString());
|
||||
this.dialog.open()
|
||||
hdHttp.httpReq<string>(BasicConstant.getFlowerList,hashMap).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
let json:flowerRequest = JSON.parse(res+'') as flowerRequest;
|
||||
if(json.code == 200) {
|
||||
if(this.pageNumber==1) {
|
||||
this.flowerList=[]
|
||||
if(json.data!=null) {
|
||||
this.flowerList = json.data.flower_data.list;
|
||||
}
|
||||
} else if(this.pageNumber>1) {
|
||||
this.flowerList.push(...json.data.flower_data.list)
|
||||
}
|
||||
this.totalPageNumer = json.data.flower_data.pages
|
||||
if (ChangeUtil.stringIsUndefinedAndNull(json.data.total_num.toString())) {
|
||||
this.allFlower = '0'
|
||||
} else {
|
||||
this.allFlower = json.data.total_num.toString()
|
||||
}
|
||||
this.allTotalNum = ChangeUtil.formatPrice(json.data.total_amount.toString())
|
||||
} else {
|
||||
promptAction.showToast({ message: json.message, duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
this.controller.refreshError();
|
||||
console.info(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
HdNav({title:'我的鲜花',showRightIcon:false,showRightText:false})
|
||||
|
||||
if (this.isEmptyViewVisible){
|
||||
EmptyViewComp({promptText:'您暂未收到鲜花',isVisibility:this.isEmptyViewVisible}).layoutWeight(1)
|
||||
} else {
|
||||
PullToRefreshLayout({
|
||||
scroller:this.scroller,
|
||||
viewKey:"ListPage",
|
||||
controller:this.controller,
|
||||
contentView:()=>{
|
||||
this.contentView()
|
||||
},
|
||||
|
||||
onRefresh:()=>{
|
||||
this.pageNumber = 1;
|
||||
this.getFlowetListData();
|
||||
setTimeout(() => {
|
||||
this.controller.refreshSuccess()
|
||||
}, 1000)
|
||||
},
|
||||
onCanPullRefresh:()=>{
|
||||
if (!this.scroller.currentOffset()) {
|
||||
/*处理无数据,为空的情况*/
|
||||
return true
|
||||
}
|
||||
//如果列表到顶,返回true,表示可以下拉,返回false,表示无法下拉
|
||||
return this.scroller.currentOffset().yOffset <= 0
|
||||
},
|
||||
onLoad:()=>{
|
||||
this.pageNumber++;
|
||||
this.getFlowetListData();
|
||||
setTimeout(() => {
|
||||
this.controller.loadSuccess()
|
||||
}, 1000)
|
||||
|
||||
},
|
||||
onCanPullLoad: () => {
|
||||
if (this.pageNumber >= this.totalPageNumer) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}).width('100%').layoutWeight(1).clip(true)
|
||||
}
|
||||
}
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
.backgroundColor('#f1f1f1')
|
||||
}
|
||||
|
||||
@Builder
|
||||
contentView() {
|
||||
List({scroller:this.scroller}) {
|
||||
ListItemGroup({header:this.headerView()}) {
|
||||
ForEach(this.flowerList,(item:flowerListData)=>{
|
||||
ListItem() {
|
||||
Row() {
|
||||
Text(item.patient_name)
|
||||
.fontColor(Color.Gray)
|
||||
.width(130)
|
||||
Blank()
|
||||
.layoutWeight(1)
|
||||
Text(item.create_date.substring(0,10))
|
||||
.fontColor(Color.Gray)
|
||||
.width(180)
|
||||
Blank()
|
||||
.layoutWeight(1)
|
||||
Text(item.num.toString())
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontColor(Color.Gray)
|
||||
.width(40)
|
||||
}
|
||||
.padding(10)
|
||||
.width('100%')
|
||||
.height(50)
|
||||
.backgroundColor(Color.White)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
@Builder
|
||||
headerView() {
|
||||
Column() {
|
||||
Row() {
|
||||
Row() {
|
||||
Image($r('app.media.flower_expertFlower_icon'))
|
||||
.size({ width: 20, height: 20 })
|
||||
Text(this.allFlower)
|
||||
.fontColor($r('app.color.main_color'))
|
||||
.margin({ left: 10 })
|
||||
}
|
||||
|
||||
Row() {
|
||||
Image($r('app.media.flower_accountJinbi_icon'))
|
||||
.size({ width: 20, height: 20 })
|
||||
Text(this.allTotalNum)
|
||||
.fontColor($r('app.color.main_color'))
|
||||
.margin({ left: 10 })
|
||||
}
|
||||
.margin({ left: 50 })
|
||||
}
|
||||
.padding(10)
|
||||
.width('100%')
|
||||
.height(45)
|
||||
.backgroundColor(Color.White)
|
||||
|
||||
Row(){
|
||||
Text('姓名')
|
||||
.fontColor(Color.White)
|
||||
Blank()
|
||||
.layoutWeight(1)
|
||||
Text('时间')
|
||||
.fontColor(Color.White)
|
||||
Blank()
|
||||
.layoutWeight(1)
|
||||
Text('数量')
|
||||
.fontColor(Color.White)
|
||||
}
|
||||
.padding(10)
|
||||
.width('100%')
|
||||
.height(45)
|
||||
.backgroundColor($r('app.color.main_color'))
|
||||
}
|
||||
.width('100%')
|
||||
.height(90)
|
||||
}
|
||||
}
|
||||
|
||||
export interface flowerRequest {
|
||||
'code':number
|
||||
'message':string
|
||||
'data':flowerData
|
||||
}
|
||||
|
||||
export interface flowerData {
|
||||
'flower_data':flower_data,
|
||||
'total_num':number
|
||||
'total_amount':number
|
||||
}
|
||||
|
||||
export interface flower_data {
|
||||
'isFirstPage':number
|
||||
'isLastPage':number
|
||||
'pageNum':number
|
||||
'pages':number
|
||||
'pageSize':number
|
||||
'total':number
|
||||
'list':flowerListData[]
|
||||
}
|
||||
|
||||
export interface flowerListData {
|
||||
'patiet_photo':string
|
||||
'expert_photo':string
|
||||
'expert_name':string
|
||||
'patient_name':string
|
||||
'patient_uuid':string
|
||||
'expert_uuid':string
|
||||
'num':number
|
||||
'create_date':string
|
||||
'trade_no':string
|
||||
'order_status':string
|
||||
'amount':number
|
||||
'message':string
|
||||
'id':string
|
||||
}
|
||||
@ -79,6 +79,6 @@ export struct KeepStudyComp {
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.backgroundColor('#F1F3F5')
|
||||
.backgroundColor('#f1f1f1')
|
||||
}
|
||||
}
|
||||
|
||||
19
features/study/src/main/ets/components/MainPage.ets
Normal file
@ -0,0 +1,19 @@
|
||||
@Component
|
||||
export struct MainPage {
|
||||
@State message: string = 'Hello World';
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(this.message)
|
||||
.fontSize($r('app.float.page_text_font_size'))
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.onClick(() => {
|
||||
this.message = 'Welcome';
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
85
features/study/src/main/ets/components/NewsComp.ets
Normal file
@ -0,0 +1,85 @@
|
||||
import { AppUtil, HdNav } from "@itcast/basic"
|
||||
import { NewsSwiperView } from "../views/NewsSwiperView"
|
||||
import { router } from "@kit.ArkUI"
|
||||
|
||||
@Component
|
||||
export struct NewsComp {
|
||||
build() {
|
||||
Column() {
|
||||
HdNav({title:'肝胆新闻',showRightIcon:false,showRightText:false})
|
||||
NewsSwiperView().height(AppUtil.getDisplayWindowWidth().vp / 16 * 9)
|
||||
|
||||
Row(){
|
||||
Image($r('app.media.news_new_icon'))
|
||||
.width(50)
|
||||
.height(50)
|
||||
.margin({left:10})
|
||||
.objectFit(ImageFit.Fill)
|
||||
Column(){
|
||||
Text('肝胆新闻')
|
||||
.fontSize(16)
|
||||
Text('新鲜资讯,一触即达')
|
||||
.fontSize(14)
|
||||
.margin({top:5})
|
||||
.fontColor($r('app.color.common_gray_02'))
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.margin({left:10,right:10})
|
||||
.layoutWeight(1)
|
||||
|
||||
Image($r('app.media.arrow_right'))
|
||||
.width(12)
|
||||
.height(15)
|
||||
.margin({right:10})
|
||||
}
|
||||
.width('95%')
|
||||
.height(90)
|
||||
.borderRadius(3)
|
||||
.backgroundColor(Color.White)
|
||||
.margin({left:10,top:10,right:10})
|
||||
.onClick(()=>{
|
||||
router.pushUrl({
|
||||
url:'pages/News/GandanNewsListPage',
|
||||
})
|
||||
})
|
||||
|
||||
Row(){
|
||||
Image($r('app.media.news_meeting_icon'))
|
||||
.width(50)
|
||||
.height(50)
|
||||
.margin({left:10})
|
||||
.objectFit(ImageFit.Fill)
|
||||
Column(){
|
||||
Text('肝胆会议')
|
||||
.fontSize(16)
|
||||
Text('了解会议信息的最佳入口')
|
||||
.fontSize(14)
|
||||
.margin({top:5})
|
||||
.fontColor($r('app.color.common_gray_02'))
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.margin({left:10,right:10})
|
||||
.layoutWeight(1)
|
||||
.onClick(()=>{
|
||||
router.pushUrl({
|
||||
url:'pages/Meeting/MeetingPage',
|
||||
params:{"isLeft":"需要"}
|
||||
})
|
||||
})
|
||||
|
||||
Image($r('app.media.arrow_right'))
|
||||
.width(12)
|
||||
.height(15)
|
||||
.margin({right:10})
|
||||
}
|
||||
.width('95%')
|
||||
.height(90)
|
||||
.borderRadius(3)
|
||||
.backgroundColor(Color.White)
|
||||
.margin({left:10,top:10,right:10})
|
||||
}
|
||||
.backgroundColor('#f1f1f1')
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
188
features/study/src/main/ets/components/NewsListComp.ets
Normal file
@ -0,0 +1,188 @@
|
||||
import { AppUtil, BasicConstant,
|
||||
EmptyViewComp,
|
||||
hdHttp, HdLoadingDialog, HdNav, HdResponse, logger } from "@itcast/basic"
|
||||
import { NewsSwiperView } from "../views/NewsSwiperView"
|
||||
import { promptAction, router } from "@kit.ArkUI"
|
||||
import { HashMap } from "@kit.ArkTS";
|
||||
import {
|
||||
newsListRequest,
|
||||
newsRequestOfData, newsRollNewRequest, newsTagRequest, newsTagsRequestData } from "../models/NewsModel";
|
||||
import { BusinessError } from "@kit.BasicServicesKit";
|
||||
import { PullToRefreshLayout, RefreshController } from "refreshlib";
|
||||
import { NewsItemView } from "../views/NewsItemView";
|
||||
|
||||
@Component
|
||||
export struct NewsListComp {
|
||||
@State tagsList:newsTagsRequestData[] = []
|
||||
@State newsList:newsRequestOfData[] = []
|
||||
@State isEmptyViewVisible: boolean = false; // 控制显隐的状态变量
|
||||
public controller:RefreshController = new RefreshController();
|
||||
scroller = new Scroller();
|
||||
@State pageNumber:number = 1;
|
||||
@State totalPageNumer:number = 1;
|
||||
@State selectedTagId:string = '';
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.getHeaderTags()
|
||||
this.getNewsListData(true)
|
||||
}
|
||||
|
||||
getHeaderTags() {
|
||||
const entity = {} as Record<string,string>
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(BasicConstant.newsTagList, entity).then(async (res: HdResponse<string>) => {
|
||||
logger.info('Response newsTagList'+res);
|
||||
let json:newsTagRequest = JSON.parse(res+'') as newsTagRequest;
|
||||
this.dialog.close();
|
||||
this.tagsList = json.data
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
})
|
||||
}
|
||||
|
||||
getNewsListData(isDefault:boolean) {
|
||||
const hashMap: HashMap<string, string> = new HashMap();
|
||||
this.dialog.open()
|
||||
hashMap.clear();
|
||||
hashMap.set('page',this.pageNumber.toString())
|
||||
if (!isDefault)
|
||||
hashMap.set('newstagid', this.selectedTagId)//点击标签的ID
|
||||
hdHttp.httpReq<string>(isDefault?BasicConstant.defaultNewsListNew:BasicConstant.newsListNew,hashMap).then(async (res: HdResponse<string>) => {
|
||||
logger.info('Response newsListNew/defaultNewsListNew'+res);
|
||||
this.dialog.close();
|
||||
let json:newsListRequest = JSON.parse(res+'') as newsListRequest;
|
||||
if(json.code == '1') {
|
||||
if(this.pageNumber==1) {
|
||||
this.newsList = []
|
||||
if(json.data!=null) {
|
||||
this.newsList = json.data;
|
||||
}
|
||||
} else if(this.pageNumber>1) {
|
||||
this.newsList.push(...json.data)
|
||||
}
|
||||
this.totalPageNumer =json.totalPage;
|
||||
if (this.newsList.length > 0) {
|
||||
this.isEmptyViewVisible = false;
|
||||
} else {
|
||||
this.isEmptyViewVisible = true;
|
||||
}
|
||||
} else {
|
||||
promptAction.showToast({ message: json.message, duration: 1000 })
|
||||
}
|
||||
this.isEmptyViewVisible = !this.newsList || this.newsList.length === 0
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
})
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
HdNav({ title: '肝胆新闻',showRightIcon: true,rightIcon:$r('app.media.selected_hospital_ws') ,showRightText:false,
|
||||
rightItemAction:()=>{
|
||||
router.pushUrl({
|
||||
url:'pages/SearchPage/VideoSearchPage',
|
||||
params:{'pageName':'视频'}
|
||||
})
|
||||
}})
|
||||
|
||||
//标签
|
||||
if (this.tagsList && this.tagsList.length > 0) {
|
||||
Scroll() {
|
||||
Row() {
|
||||
ForEach(this.tagsList, (tag:newsTagsRequestData) => {
|
||||
Text(tag.NAME)
|
||||
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
|
||||
.margin({ left: 6, right: 6, top: 10, bottom: 10 })
|
||||
.fontSize(16)
|
||||
.fontColor(this.selectedTagId == tag.ID?$r('app.color.main_color'):Color.Black)
|
||||
.borderRadius(16)
|
||||
.onClick(() => {
|
||||
if (this.selectedTagId !== tag.ID) {
|
||||
this.selectedTagId = tag.ID
|
||||
this.pageNumber = 1
|
||||
this.getNewsListData(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
.scrollable(ScrollDirection.Horizontal)
|
||||
.width('100%')
|
||||
.height(48)
|
||||
.scrollBar(BarState.Off)
|
||||
.backgroundColor('#ffffff')
|
||||
}
|
||||
|
||||
//轮播
|
||||
NewsSwiperView().height(AppUtil.getDisplayWindowWidth().vp / 16 * 9)
|
||||
|
||||
//列表
|
||||
if (this.isEmptyViewVisible){
|
||||
EmptyViewComp({promptText:'暂无肝胆资讯',isVisibility:this.isEmptyViewVisible}).layoutWeight(1)
|
||||
} else {
|
||||
PullToRefreshLayout({
|
||||
scroller:this.scroller,
|
||||
viewKey:"ListPage",
|
||||
controller:this.controller,
|
||||
contentView:()=>{
|
||||
this.contentView()
|
||||
},
|
||||
|
||||
onRefresh:()=>{
|
||||
this.pageNumber = 1;
|
||||
this.getNewsListData(this.selectedTagId==='');//标签点击的第一个为true,后面是false
|
||||
setTimeout(() => {
|
||||
this.controller.refreshSuccess()
|
||||
}, 1000)
|
||||
},
|
||||
onCanPullRefresh:()=>{
|
||||
if (!this.scroller.currentOffset()) {
|
||||
/*处理无数据,为空的情况*/
|
||||
return true
|
||||
}
|
||||
//如果列表到顶,返回true,表示可以下拉,返回false,表示无法下拉
|
||||
return this.scroller.currentOffset().yOffset <= 0
|
||||
},
|
||||
onLoad:()=>{
|
||||
this.pageNumber++;
|
||||
this.getNewsListData(this.selectedTagId==='');//标签点击的第一个为true,后面是false
|
||||
setTimeout(() => {
|
||||
this.controller.loadSuccess()
|
||||
}, 1000)
|
||||
|
||||
},
|
||||
onCanPullLoad: () => {
|
||||
if (this.pageNumber >= this.totalPageNumer) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}).width('100%').layoutWeight(1).clip(true)
|
||||
}
|
||||
}
|
||||
.backgroundColor('#f1f1f1')
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
@Builder
|
||||
contentView(){
|
||||
List({ scroller: this.scroller }) {
|
||||
ForEach(this.newsList, (item: newsRequestOfData, index) => {
|
||||
ListItem() {
|
||||
NewsItemView({item:item})
|
||||
}
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.edgeEffect(EdgeEffect.None)
|
||||
}
|
||||
}
|
||||
323
features/study/src/main/ets/components/PayComp.ets
Normal file
@ -0,0 +1,323 @@
|
||||
import { BasicConstant, ChangeUtil,
|
||||
DefaultHintProWindows,
|
||||
hdHttp, HdLoadingDialog, HdNav, HdResponse,
|
||||
OnWXResp,
|
||||
WXApi,
|
||||
WXEventHandler} from "@itcast/basic";
|
||||
import { promptAction, router } from "@kit.ArkUI";
|
||||
import { BusinessError, emitter } from "@kit.BasicServicesKit";
|
||||
import { HashMap } from "@kit.ArkTS";
|
||||
import * as wxopensdk from '@tencent/wechat_open_sdk';
|
||||
import { common } from "@kit.AbilityKit";
|
||||
|
||||
@Component
|
||||
export struct PayComp {
|
||||
@State params:Record<string,string | Record<string,string> | FileOrderData> = router.getParams() as Record<string,string | Record<string,string> | FileOrderData>
|
||||
@State payType:number = 0//0没有选择支付;1;选择余额支付;2:选择微信支付
|
||||
@State balanceEnough: boolean = false
|
||||
@State balanceMoney: string = ''
|
||||
@State name:string = ''
|
||||
@State hintMessage:string = ''
|
||||
@State pwd:string = ''
|
||||
|
||||
@State kejianData:FileOrderData = {} as FileOrderData
|
||||
@State songhuaData:Record<string,string | Record<string,string>> = {}
|
||||
|
||||
private wxApi = WXApi
|
||||
private wxEventHandler = WXEventHandler
|
||||
|
||||
private onWXResp: OnWXResp = (resp) => {
|
||||
console.info('wxResp:'+JSON.stringify(resp ?? {}, null, 2))
|
||||
if (resp.errCode == 0) {
|
||||
this.notificationRequest()
|
||||
} else if (resp.errCode == -2) {
|
||||
this.hintMessage = '支付取消'
|
||||
this.alertView.open()
|
||||
}
|
||||
}
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
alertView:CustomDialogController = new CustomDialogController({
|
||||
builder:DefaultHintProWindows({
|
||||
title:'提示',
|
||||
message:this.hintMessage,
|
||||
cancleTitle: '',
|
||||
confirmTitleColor: '#666666',
|
||||
selectedButton: (index:number)=>{
|
||||
this.alertView.close();
|
||||
if (this.hintMessage == '支付成功' || '您已经成功送给肝胆相照送出心意') {
|
||||
let innerEvent: emitter.InnerEvent = {
|
||||
eventId: BasicConstant.notification_kejian_pay_success
|
||||
};
|
||||
let eventData: emitter.EventData = {
|
||||
data:{"status":'success'}
|
||||
};
|
||||
emitter.emit(innerEvent, eventData);
|
||||
router.back()
|
||||
}
|
||||
}
|
||||
}),
|
||||
alignment: DialogAlignment.Center,
|
||||
cornerRadius:24,
|
||||
backgroundColor: ('rgba(0,0,0,0.5)'),
|
||||
})
|
||||
|
||||
inputAlertView:CustomDialogController = new CustomDialogController({
|
||||
builder:DefaultHintProWindows({
|
||||
title:'提示',
|
||||
message:'',
|
||||
cancleTitleColor: '#333333',
|
||||
confirmTitleColor: $r('app.color.main_color'),
|
||||
selectedButtonAndContent:(index:number,content:string)=>{
|
||||
if (index == 0) {
|
||||
this.inputAlertView.close()
|
||||
} else {
|
||||
if (!ChangeUtil.stringIsUndefinedAndNull(content)) {
|
||||
this.pwd = content
|
||||
this.inputAlertView.close()
|
||||
this.payOrderRequest()
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
alignment: DialogAlignment.Center,
|
||||
cornerRadius:24,
|
||||
backgroundColor: ('rgba(0,0,0,0.5)'),
|
||||
})
|
||||
|
||||
aboutToDisappear(): void {
|
||||
this.wxEventHandler.unregisterOnWXRespCallback(this.onWXResp)
|
||||
}
|
||||
|
||||
aboutToAppear(): void {
|
||||
if (this.params.page == '送花') {
|
||||
this.name = '肝胆相照'
|
||||
this.songhuaData = this.params.data as Record<string,string | Record<string,string>>
|
||||
} else if (this.params.page == '课件详情') {
|
||||
this.kejianData = this.params.data as FileOrderData
|
||||
this.name = this.kejianData.provider_name
|
||||
}
|
||||
this.getAccountData()
|
||||
this.wxEventHandler.registerOnWXRespCallback(this.onWXResp)
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
HdNav({title:'在线支付',showRightIcon:false,showRightText:false})
|
||||
|
||||
Column() {
|
||||
Row() {
|
||||
Row() {
|
||||
Text(this.params.page == '课件详情'?`下载${this.name}医生的`:`给${this.name}`)
|
||||
.fontSize(16)
|
||||
|
||||
Text(this.params.page == '课件详情'?'课件':'送心意')
|
||||
.borderRadius(8)
|
||||
.fontColor(Color.White)
|
||||
.margin({ left: 20 })
|
||||
.size({ width: 50, height: 30 })
|
||||
.textAlign(TextAlign.Center)
|
||||
.backgroundColor($r('app.color.main_color'))
|
||||
}
|
||||
.layoutWeight(1)
|
||||
|
||||
Text(this.params.page == '课件详情'?ChangeUtil.formatPrice(this.kejianData.amount).toString():ChangeUtil.formatPrice(String(this.songhuaData.amount)).toString()+' 元')
|
||||
.fontColor(Color.Red)
|
||||
.width('40%')
|
||||
.textAlign(TextAlign.End)
|
||||
}
|
||||
.padding(10)
|
||||
.width('100%')
|
||||
.backgroundColor(Color.White)
|
||||
|
||||
Text('请通过以下方式支付')
|
||||
.width('100%')
|
||||
.padding(10)
|
||||
|
||||
Row() {
|
||||
Row() {
|
||||
Image($r('app.media.pay_account_icon'))
|
||||
.size({ width: 35, height: 35 })
|
||||
Text('余额支付')
|
||||
.fontSize(16)
|
||||
.margin({ left: 10 })
|
||||
Text(` ¥ ${ChangeUtil.formatPrice(this.balanceMoney)}`)
|
||||
.fontSize(16)
|
||||
}
|
||||
.layoutWeight(1)
|
||||
|
||||
Row() {
|
||||
if (!this.balanceEnough) {
|
||||
Text('余额不足')
|
||||
.fontSize(16)
|
||||
.fontColor(Color.Red)
|
||||
.margin({ right: 20 })
|
||||
}
|
||||
Image(this.payType == 1 ? $r('app.media.patiemts_list_selected') : $r('app.media.huise_kongquan'))
|
||||
.width(15)
|
||||
.height(15)
|
||||
.enabled(this.balanceEnough)// 余额不足时禁用
|
||||
}
|
||||
.width('40%')
|
||||
.justifyContent(FlexAlign.End)
|
||||
.onClick(() => {
|
||||
if (this.balanceEnough) {
|
||||
this.payType = 1
|
||||
}
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.padding(10)
|
||||
.backgroundColor(Color.White)
|
||||
|
||||
Text('选择付款方式')
|
||||
.width('100%')
|
||||
.padding(10)
|
||||
Row() {
|
||||
Image($r('app.media.pay_wx_icon'))
|
||||
.size({ width: 35, height: 35 })
|
||||
Text('微信支付')
|
||||
.fontSize(16)
|
||||
.margin({ left: 10 })
|
||||
.layoutWeight(1)
|
||||
Image(this.payType == 2 ? $r('app.media.patiemts_list_selected') : $r('app.media.huise_kongquan'))
|
||||
.width(15)
|
||||
.height(15)
|
||||
}
|
||||
.width('100%')
|
||||
.padding(10)
|
||||
.backgroundColor(Color.White)
|
||||
.onClick(() => {
|
||||
this.payType = 2
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.layoutWeight(1)
|
||||
|
||||
Button('立即支付')
|
||||
.width('90%')
|
||||
.height(40)
|
||||
.fontColor(Color.White)
|
||||
.backgroundColor($r('app.color.main_color'))
|
||||
.margin({left:20,bottom:50,right:20})
|
||||
.onClick(() => {
|
||||
if (this.payType == 0) {
|
||||
this.hintMessage = '请选择支付方式'
|
||||
this.alertView.open()
|
||||
return
|
||||
} else if (this.payType == 1) {
|
||||
this.inputAlertView.open()
|
||||
return
|
||||
}
|
||||
this.payOrderRequest()
|
||||
})
|
||||
}
|
||||
.backgroundColor('#f4f4f4')
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
getAccountData() {
|
||||
const hashMap: HashMap<string, string> = new HashMap()
|
||||
this.dialog.open()
|
||||
hashMap.clear()
|
||||
hdHttp.httpReq<string>(BasicConstant.getBalance,hashMap).then(async (res: HdResponse<string>) => {
|
||||
console.info('Response getBalance'+res)
|
||||
this.dialog.close()
|
||||
let json:Record<string,string> = JSON.parse(res+'') as Record<string,string>;
|
||||
if(json.code == '200') {
|
||||
this.balanceMoney = json.data
|
||||
let amount = this.params.page == '课件详情'?ChangeUtil.formatPrice(this.kejianData.amount):ChangeUtil.formatPrice(String(this.songhuaData.amount))
|
||||
if (ChangeUtil.formatPrice(this.balanceMoney)> amount) {
|
||||
this.balanceEnough = true
|
||||
}
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close()
|
||||
console.error(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
|
||||
payOrderRequest() {
|
||||
const hashMap: HashMap<string, string> = new HashMap()
|
||||
this.dialog.open()
|
||||
let trade_no = this.params.page == '课件详情'?this.kejianData.trade_no:String(this.songhuaData.trade_no)
|
||||
hashMap.clear()
|
||||
hashMap.set('channel', this.payType == 1?'balance':'wx')
|
||||
hashMap.set('trade_no',trade_no)
|
||||
hashMap.set('pwd',this.pwd)
|
||||
hdHttp.httpReq<string>(this.params.page == '课件详情'?BasicConstant.payGanDanFileOrder:BasicConstant.payXinYiOrder,hashMap).then(async (res: HdResponse<string>) => {
|
||||
console.info('Response payGanDanFileOrder'+res)
|
||||
this.dialog.close()
|
||||
let json:Record<string,string | Record<string,string>> = JSON.parse(res+'') as Record<string,string | Record<string,string>>;
|
||||
if(json.code == '200') {
|
||||
if (json.data != undefined) {
|
||||
let req = new wxopensdk.PayReq
|
||||
req.partnerId = json.data['partnerid']
|
||||
req.appId = json.data['appid']
|
||||
req.packageValue = json.data['package_str']
|
||||
req.prepayId = json.data['prepayid']
|
||||
req.nonceStr = json.data['noncestr']
|
||||
req.timeStamp = json.data['timestamp']
|
||||
req.sign = json.data['sign']
|
||||
req.extData = 'extData'
|
||||
|
||||
let finished = await this.wxApi.sendReq(getContext(this) as common.UIAbilityContext, req)
|
||||
console.info("send request finished: ", finished)
|
||||
} else {
|
||||
if (this.payType == 1) {
|
||||
this.hintMessage = this.params.page == '课件详情'?'支付成功':'您已经成功送给肝胆相照送出心意'
|
||||
this.alertView.open()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close()
|
||||
console.error(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
|
||||
notificationRequest() {
|
||||
const hashMap: HashMap<string, string> = new HashMap()
|
||||
let trade_no = this.params.page == '课件详情'?this.kejianData.trade_no:String(this.songhuaData.trade_no)
|
||||
this.dialog.open()
|
||||
hashMap.clear()
|
||||
hashMap.set('trade_no',trade_no)
|
||||
hdHttp.httpReq<string>(BasicConstant.getOrderStatus,hashMap).then(async (res: HdResponse<string>) => {
|
||||
console.info('Response getOrderStatus'+res)
|
||||
this.dialog.close()
|
||||
let json:Record<string,string | Record<string,string>> = JSON.parse(res+'') as Record<string,string | Record<string,string>>;
|
||||
if(json.code == '200') {
|
||||
if (this.payType == 2) {
|
||||
let tradeState = json.data['tradeState'] as string
|
||||
if (tradeState == 'SUCCESS') {
|
||||
this.hintMessage = this.params.page == '课件详情'?'支付成功':'您已经成功送给肝胆相照送出心意'
|
||||
this.alertView.open()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close()
|
||||
console.error(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
interface FileOrderData {
|
||||
trade_no:string
|
||||
order_id:string
|
||||
amount:string
|
||||
account:string
|
||||
provider_name:string
|
||||
}
|
||||
@ -258,7 +258,6 @@ export struct SchoolhouseComp {
|
||||
ForEach(this.data, (item: PatientTBean, index) => {
|
||||
ListItem() {
|
||||
ItemCompTeach({item:item})
|
||||
.onClick(()=>{this.pushDetailsView(item)})
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -266,25 +265,4 @@ export struct SchoolhouseComp {
|
||||
.height('100%')
|
||||
.edgeEffect(EdgeEffect.None)
|
||||
}
|
||||
|
||||
private pushDetailsView(item: PatientTBean) {
|
||||
const entity = {
|
||||
"news_article_uuid":item.uuid,
|
||||
"user_uuid": authStore.getUser().uuid,
|
||||
"type":'2'
|
||||
} as Record<string,string>
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(BasicConstant.read, entity).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
console.info('Response delConditionRecord'+res);
|
||||
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
|
||||
if(json.code == '1') {
|
||||
router.pushUrl({url:"pages/WebView/EducationDetailsWebPage",params:{"model":item}})
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
console.error(`Response fails: ${err}`);
|
||||
promptAction.showToast({ message: String('患教文库数据请求失败!'), duration: 1000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
343
features/study/src/main/ets/components/SendFollowComp.ets
Normal file
@ -0,0 +1,343 @@
|
||||
import { BasicConstant, ChangeUtil,
|
||||
DefaultHintProWindows,
|
||||
hdHttp, HdLoadingDialog, HdNav, HdResponse } from "@itcast/basic";
|
||||
import { PullToRefreshLayout, RefreshController } from "refreshlib";
|
||||
import { HashMap } from "@kit.ArkTS";
|
||||
import { xinyiListData, xinyiRequest } from "../models/XinYiModel";
|
||||
import { promptAction, router } from "@kit.ArkUI";
|
||||
import { BusinessError, emitter } from "@kit.BasicServicesKit";
|
||||
|
||||
@Component
|
||||
export struct SendFollowComp {
|
||||
public controller:RefreshController = new RefreshController();
|
||||
scroller = new Scroller();
|
||||
@State pageNumber:number = 1;
|
||||
@State totalPageNumer:number = 1;
|
||||
@State xinyiList:xinyiListData[] = []
|
||||
@State xinyiPrice:string = ''
|
||||
@State sendPrice:string = ''
|
||||
@State selectedAmount:number = 5
|
||||
@State message:string = '祝肝胆相照平台越来越好!'
|
||||
moneyOptions:number[] = [1,2,5,10,50]
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
alertView:CustomDialogController = new CustomDialogController({
|
||||
builder:DefaultHintProWindows({
|
||||
title:'提示',
|
||||
message:'您确定是否送出',
|
||||
cancleTitle:'否',
|
||||
confirmTitle:'是',
|
||||
cancleTitleColor: '#666666',
|
||||
confirmTitleColor: $r('app.color.main_color'),
|
||||
selectedButton: (index:number)=>{
|
||||
this.alertView.close();
|
||||
if (index == 1) {
|
||||
this.createXinYiOrder()
|
||||
}
|
||||
}
|
||||
}),
|
||||
alignment: DialogAlignment.Center,
|
||||
cornerRadius:24,
|
||||
backgroundColor: ('rgba(0,0,0,0.5)'),
|
||||
})
|
||||
|
||||
private refreshDataCallback = (eventData?: emitter.EventData): void => {
|
||||
if (Object(eventData?.data)['status'] == 'success') {
|
||||
this.pageNumber = 1;
|
||||
this.getXinYiListData()
|
||||
}
|
||||
};
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.getXinyiPriceData()
|
||||
this.getXinYiListData()
|
||||
let innerEvent: emitter.InnerEvent = {
|
||||
eventId: BasicConstant.notification_kejian_pay_success
|
||||
}
|
||||
emitter.on(innerEvent, this.refreshDataCallback)
|
||||
}
|
||||
|
||||
aboutToDisappear(): void {
|
||||
emitter.off(BasicConstant.notification_kejian_pay_success, this.refreshDataCallback)
|
||||
}
|
||||
|
||||
getXinYiListData() {
|
||||
const hashMap: HashMap<string, string> = new HashMap();
|
||||
hashMap.set('page',this.pageNumber.toString());
|
||||
this.dialog.open()
|
||||
hdHttp.httpReq<string>(BasicConstant.allXinyiList,hashMap).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
let json:xinyiRequest = JSON.parse(res+'') as xinyiRequest;
|
||||
if(json.code == '200') {
|
||||
if(this.pageNumber==1) {
|
||||
this.xinyiList=[]
|
||||
if(json.data!=null) {
|
||||
this.xinyiList = json.data.list;
|
||||
}
|
||||
} else if(this.pageNumber>1) {
|
||||
this.xinyiList.push(...json.data.list)
|
||||
}
|
||||
this.totalPageNumer = json.data.total;
|
||||
} else {
|
||||
promptAction.showToast({ message: json.message, duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
this.controller.refreshError();
|
||||
console.info(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
|
||||
getXinyiPriceData() {
|
||||
const hashMap: HashMap<string, string> = new HashMap();
|
||||
this.dialog.open()
|
||||
hdHttp.httpReq<string>(BasicConstant.xinyiPrice,hashMap).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
let json:Record<string , string> = JSON.parse(res+'') as Record<string , string>;
|
||||
if(json.code == '200') {
|
||||
this.xinyiPrice = String(json.data)
|
||||
this.sendPrice = ChangeUtil.formatPrice2(this.xinyiPrice,'5')
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
this.controller.refreshError();
|
||||
console.info(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
|
||||
createXinYiOrder() {
|
||||
const hashMap: HashMap<string, string> = new HashMap();
|
||||
this.dialog.open()
|
||||
hashMap.set('message',ChangeUtil.stringIsUndefinedAndNull(this.message)?'祝肝胆相照平台越来越好!':this.message)
|
||||
hashMap.set('amount',this.selectedAmount.toString())
|
||||
hdHttp.httpReq<string>(BasicConstant.createXinYiOrder,hashMap).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
let json:Record<string , string | Record<string,string>> = JSON.parse(res+'') as Record<string , string | Record<string,string>>
|
||||
if(json.code == '200') {
|
||||
router.pushUrl({
|
||||
url:"pages/Pay/PayPage",
|
||||
params:{"data":json.data,"page":"送花"}
|
||||
})
|
||||
} else {
|
||||
promptAction.showToast({message:'服务器异常',duration:1000})
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
this.controller.refreshError();
|
||||
console.info(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
HdNav({title:'表达暖暖心意',showRightIcon:false,showRightText:false})
|
||||
|
||||
PullToRefreshLayout({
|
||||
scroller:this.scroller,
|
||||
viewKey:"ListPage",
|
||||
controller:this.controller,
|
||||
contentView:()=>{
|
||||
this.contentView()
|
||||
},
|
||||
|
||||
onRefresh:()=>{
|
||||
this.pageNumber = 1;
|
||||
setTimeout(() => {
|
||||
this.controller.refreshSuccess()
|
||||
}, 1000)
|
||||
},
|
||||
onCanPullRefresh:()=>{
|
||||
if (!this.scroller.currentOffset()) {
|
||||
/*处理无数据,为空的情况*/
|
||||
return true
|
||||
}
|
||||
//如果列表到顶,返回true,表示可以下拉,返回false,表示无法下拉
|
||||
return this.scroller.currentOffset().yOffset <= 0
|
||||
},
|
||||
onLoad:()=>{
|
||||
this.pageNumber++;
|
||||
this.getXinYiListData();
|
||||
setTimeout(() => {
|
||||
this.controller.loadSuccess()
|
||||
}, 1000)
|
||||
},
|
||||
onCanPullLoad: () => {
|
||||
if (this.pageNumber >= this.totalPageNumer) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}).width('100%').layoutWeight(1).clip(true)
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
@Builder
|
||||
contentView() {
|
||||
Column() {
|
||||
List({scroller:this.scroller}) {
|
||||
ListItemGroup({header:this.headerView()}) {
|
||||
ForEach(this.xinyiList, (item: xinyiListData, index: number) => {
|
||||
ListItem() {
|
||||
Column() {
|
||||
Row() {
|
||||
Image(BasicConstant.urlImage + item.user_photo)
|
||||
.alt($r('app.media.userPhoto_default'))
|
||||
.width(50)
|
||||
.height(50)
|
||||
.borderRadius(5)
|
||||
|
||||
Column() {
|
||||
Text(ChangeUtil.stringIsUndefinedAndNull(item.user_name) ? '账号已注销' : item.user_name)
|
||||
.fontColor($r('app.color.main_color'))
|
||||
.fontSize(16)
|
||||
Text(item.message)
|
||||
.fontSize(14)
|
||||
.fontColor(Color.Grey)
|
||||
}
|
||||
.width('60%')
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.margin({left:10})
|
||||
|
||||
Text(item.create_date.length > 10 ? item.create_date.substring(0,10) : item.create_date)
|
||||
.fontSize(12)
|
||||
.textAlign(TextAlign.End)
|
||||
.margin({top:10})
|
||||
}
|
||||
.width('100%')
|
||||
|
||||
Blank()
|
||||
.height(1)
|
||||
.width('100%')
|
||||
.margin({top:10})
|
||||
.backgroundColor('rgb(227,227,227)')
|
||||
}
|
||||
.width('100%')
|
||||
.padding(10)
|
||||
}
|
||||
}, (item: xinyiListData) => item.create_date + item.user_name)
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.layoutWeight(1)
|
||||
}
|
||||
}
|
||||
|
||||
@Builder
|
||||
headerView() {
|
||||
Column() {
|
||||
Blank()
|
||||
.backgroundColor('rgb(227,228,229)')
|
||||
.width('100%')
|
||||
.height(10)
|
||||
Image($r('app.media.patientLogo'))
|
||||
.size({width:40,height:40})
|
||||
.margin({top:10})
|
||||
Text('肝胆相照')
|
||||
.fontSize(16)
|
||||
.margin({top:10})
|
||||
.fontColor($r('app.color.main_color'))
|
||||
Text('您的心意将用于肝胆相照平台的持续发展,有了您的支持,肝胆相照会越来越好,同时将给大家带来更多、更好的服务。')
|
||||
.fontSize(11)
|
||||
.fontColor('rgb(102,102,102)')
|
||||
.margin({ left: 8, right: 8, top: 10 })
|
||||
|
||||
Blank()
|
||||
.backgroundColor('rgb(227,227,227)')
|
||||
.width('100%')
|
||||
.height(1)
|
||||
.margin({top:10})
|
||||
|
||||
Image($r("app.media.send_header_follow_icon"))
|
||||
.size({width:75,height:75})
|
||||
.margin({top:25})
|
||||
|
||||
Text(`¥ ${this.sendPrice}元`)
|
||||
.fontSize(14)
|
||||
.textAlign(TextAlign.Center)
|
||||
.fontColor(Color.Red)
|
||||
.margin({ top: 20 })
|
||||
|
||||
// 金额选项
|
||||
Row() {
|
||||
ForEach(this.moneyOptions, (money:number) => {
|
||||
Text(`${money}`)
|
||||
.backgroundColor(this.selectedAmount === money ? $r('app.color.main_color') : Color.White)
|
||||
.fontColor(this.selectedAmount === money ? Color.White : $r('app.color.main_color'))
|
||||
.fontSize(16)
|
||||
.border({ width: 1, color: $r('app.color.main_color') })
|
||||
.width(30)
|
||||
.height(30)
|
||||
.borderRadius(15)
|
||||
.textAlign(TextAlign.Center)
|
||||
.margin({ left: 10, right: 10, top: 12 })
|
||||
.onClick(() => {
|
||||
this.selectedAmount = money
|
||||
this.sendPrice = ChangeUtil.formatPrice2(this.xinyiPrice,String(money))
|
||||
})
|
||||
})
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width('100%')
|
||||
}
|
||||
.width('100%')
|
||||
|
||||
// 留言输入
|
||||
TextInput({ text: this.message, placeholder: '请输入您的祝福' })
|
||||
.onChange((val:string) => this.message = val)
|
||||
.margin({ left: 10, right: 10, top: 15 })
|
||||
.height(55)
|
||||
.borderRadius(8)
|
||||
.fontSize(12)
|
||||
.maxLength(100)
|
||||
.backgroundColor('rgb(227,227,227)')
|
||||
.onChange((value:string)=>{
|
||||
this.message = value
|
||||
})
|
||||
|
||||
// 送出按钮
|
||||
Text('送出')
|
||||
.fontSize(16)
|
||||
.backgroundColor($r('app.color.main_color'))
|
||||
.fontColor(Color.White)
|
||||
.margin({ top: 10 })
|
||||
.height(40)
|
||||
.textAlign(TextAlign.Center)
|
||||
.width('100%')
|
||||
.onClick(() => {
|
||||
this.alertView.open()
|
||||
})
|
||||
|
||||
Blank()
|
||||
.width('100%')
|
||||
.height(10)
|
||||
.backgroundColor('rgb(227,228,229)')
|
||||
|
||||
// 心意墙标题
|
||||
Row() {
|
||||
Image($r('app.media.send_follow_list_icon'))
|
||||
.size({width:25,height:25})
|
||||
Text('肝胆相照的心意墙')
|
||||
.fontSize(18)
|
||||
.fontColor($r('app.color.main_color'))
|
||||
.margin({ left: 10 })
|
||||
}
|
||||
.width('100%')
|
||||
.padding(10)
|
||||
|
||||
Blank()
|
||||
.backgroundColor('rgb(227,228,229)')
|
||||
.width('100%')
|
||||
.height(1)
|
||||
}
|
||||
}
|
||||
49
features/study/src/main/ets/models/NewsModel.ets
Normal file
@ -0,0 +1,49 @@
|
||||
export interface newsRollNewRequest {
|
||||
"code":string
|
||||
"data":newsRequestOfData[]
|
||||
"message":string
|
||||
}
|
||||
|
||||
export interface newsRequestOfData {
|
||||
"path":string
|
||||
"title":string
|
||||
"imgs":string
|
||||
"imgpath":string
|
||||
"author":string
|
||||
"headImg":string
|
||||
"name":string
|
||||
"uuid":string
|
||||
"projectName":string
|
||||
"content":string
|
||||
"projectType":string
|
||||
"createDateStr":string
|
||||
"createDate":string
|
||||
"create_date":string
|
||||
"contentText":string
|
||||
"endDate":string
|
||||
"summary":string
|
||||
"readnum":string
|
||||
"agreenum":string
|
||||
"public_name":string
|
||||
"HEAD_IMG":string
|
||||
"TITLE":string
|
||||
"editType":string
|
||||
}
|
||||
|
||||
export interface newsTagRequest {
|
||||
'code':string
|
||||
'data':newsTagsRequestData[]
|
||||
}
|
||||
|
||||
export interface newsTagsRequestData {
|
||||
"NAME":string
|
||||
"ID":string
|
||||
}
|
||||
|
||||
export interface newsListRequest {
|
||||
'code':string
|
||||
'data':newsRequestOfData[]
|
||||
'message':string
|
||||
'totalPage':number
|
||||
}
|
||||
|
||||
17
features/study/src/main/ets/models/XinYiModel.ets
Normal file
@ -0,0 +1,17 @@
|
||||
export interface xinyiRequest {
|
||||
'code':string
|
||||
'message':string
|
||||
'data':xinyiRequestOfData
|
||||
}
|
||||
|
||||
export interface xinyiRequestOfData {
|
||||
'total':number
|
||||
'list':xinyiListData[]
|
||||
}
|
||||
|
||||
export interface xinyiListData {
|
||||
'user_photo':string
|
||||
'user_name':string
|
||||
'message':string
|
||||
'create_date':string
|
||||
}
|
||||
33
features/study/src/main/ets/utils/NewsUtil.ets
Normal file
@ -0,0 +1,33 @@
|
||||
import { BasicConstant,authStore } from '@itcast/basic'
|
||||
import HashMap from '@ohos.util.HashMap';
|
||||
import { hdHttp, HdResponse} from '@itcast/basic/Index'
|
||||
import { BusinessError } from '@kit.BasicServicesKit'
|
||||
import { newsRequestOfData } from '../models/NewsModel';
|
||||
import { router } from '@kit.ArkUI';
|
||||
|
||||
class NewsUtil {
|
||||
hashMap: HashMap<string, string> = new HashMap();
|
||||
readNews(uuid:string,model:newsRequestOfData) {
|
||||
hdHttp.post<string>(BasicConstant.read, {
|
||||
user_uuid: authStore.getUser().uuid,
|
||||
news_article_uuid:uuid,
|
||||
type: '1',
|
||||
} as readExtraData).then(async (res: HdResponse<string>) => {
|
||||
console.info('Response delConditionRecord'+res);
|
||||
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
|
||||
if(json.code == '1') {
|
||||
router.pushUrl({url:"pages/WebView/NewsDetailsWebPage",params:{"model":model}})
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
console.error(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
interface readExtraData{
|
||||
user_uuid:string,
|
||||
news_article_uuid:string,
|
||||
type:string,
|
||||
}
|
||||
|
||||
export const newsUtil = new NewsUtil()
|
||||
@ -1,5 +1,7 @@
|
||||
import { BasicConstant, TimestampUtil } from '@itcast/basic';
|
||||
import { authStore, BasicConstant, hdHttp, HdLoadingDialog, HdResponse, TimestampUtil } from '@itcast/basic';
|
||||
import { PatientTBean } from '@itcast/basic/src/main/ets/models/TeachModel';
|
||||
import { promptAction, router } from '@kit.ArkUI';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
|
||||
|
||||
@Preview
|
||||
@ -7,9 +9,12 @@ import { PatientTBean } from '@itcast/basic/src/main/ets/models/TeachModel';
|
||||
export struct ItemCompTeach {
|
||||
@Prop item:PatientTBean;
|
||||
|
||||
aboutToAppear(): void {
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
}
|
||||
build() {
|
||||
Column() {
|
||||
Row() {
|
||||
@ -58,11 +63,32 @@ export struct ItemCompTeach {
|
||||
.width('100%')
|
||||
.padding(10)
|
||||
.onClick(() => {
|
||||
|
||||
this.pushDetailsView(this.item)
|
||||
})
|
||||
Text().backgroundColor($r('app.color.efefef')).width('100%').height(1)
|
||||
}
|
||||
.backgroundColor(Color.White)
|
||||
}
|
||||
|
||||
private pushDetailsView(item: PatientTBean) {
|
||||
const entity = {
|
||||
"news_article_uuid":item.uuid,
|
||||
"user_uuid": authStore.getUser().uuid,
|
||||
"type":'2'
|
||||
} as Record<string,string>
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(BasicConstant.read, entity).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
console.info('Response delConditionRecord'+res);
|
||||
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
|
||||
if(json.code == '1') {
|
||||
router.pushUrl({url:"pages/WebView/EducationDetailsWebPage",params:{"model":item,"isAgree":json.isAgree}})
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
console.error(`Response fails: ${err}`);
|
||||
promptAction.showToast({ message: String('患教文库数据请求失败!'), duration: 1000 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ export struct KeJianItemComp {
|
||||
.margin({ left: 2 })
|
||||
.fontSize(13)
|
||||
.fontColor(Color.Red)
|
||||
Text(this.formatPrice(this.item.price))
|
||||
Text(ChangeUtil.formatPrice(this.item.price))
|
||||
.fontColor(Color.Red)
|
||||
.fontSize(16)
|
||||
}
|
||||
@ -79,14 +79,14 @@ export struct KeJianItemComp {
|
||||
.margin({ left: 2 })
|
||||
.fontSize(13)
|
||||
.fontColor(Color.Red)
|
||||
Text(this.formatPrice2(this.item.price, this.item.discount))
|
||||
Text(ChangeUtil.formatPrice2(this.item.price, this.item.discount))
|
||||
.fontColor(Color.Red)
|
||||
.fontSize(16)
|
||||
Text('原价')
|
||||
.margin({ left: 10 })
|
||||
.fontSize(12)
|
||||
.fontColor('#999999')
|
||||
Text('¥'+this.formatPrice(this.item.price))
|
||||
Text('¥'+ChangeUtil.formatPrice(this.item.price))
|
||||
.fontSize(12)
|
||||
.fontColor('#999999')
|
||||
.decoration({ type: TextDecorationType.LineThrough })
|
||||
@ -113,18 +113,6 @@ export struct KeJianItemComp {
|
||||
.backgroundColor(Color.White)
|
||||
}
|
||||
|
||||
private formatPrice(priceStr: string): string {
|
||||
let priceInFen = parseFloat(priceStr);
|
||||
let priceInYuan = priceInFen / 100;
|
||||
return `${priceInYuan.toFixed(2)}`;
|
||||
}
|
||||
|
||||
private formatPrice2(priceStr: string,discount: string): string {
|
||||
let priceInFen = parseFloat(priceStr);
|
||||
let priceInYuan = priceInFen / 100 * parseFloat(discount);
|
||||
return `${priceInYuan.toFixed(2)}`;
|
||||
}
|
||||
|
||||
private contentShow(name:string,hospital:string):string {
|
||||
let newname:string = ''
|
||||
let newhospital:string = ''
|
||||
|
||||
67
features/study/src/main/ets/views/NewsItemView.ets
Normal file
@ -0,0 +1,67 @@
|
||||
import { authStore, BasicConstant,
|
||||
ChangeUtil,
|
||||
hdHttp, HdLoadingDialog, HdResponse, TimestampUtil } from '@itcast/basic';
|
||||
import { newsRequestOfData } from '../models/NewsModel';
|
||||
import { newsUtil } from '../utils/NewsUtil';
|
||||
|
||||
@Preview
|
||||
@Component
|
||||
export struct NewsItemView {
|
||||
@Prop item:newsRequestOfData;
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Row() {
|
||||
Image(ChangeUtil.stringIsUndefinedAndNull(this.item.headImg)?BasicConstant.urlHtml+this.item.imgs:BasicConstant.urlHtml+this.item.headImg).width(114).height(76).alt($r('app.media.home_scroll_default1'))
|
||||
.alt($r('app.media.home_top_scroll_default'))
|
||||
Column() {
|
||||
Text(ChangeUtil.stringIsUndefinedAndNull(this.item.title)?this.item.projectName:this.item.title).fontColor($r('app.color.common_gray_01')).fontSize(16) .textOverflow({ overflow: TextOverflow.Ellipsis }).height(40)
|
||||
.ellipsisMode(EllipsisMode.END).maxLines(2) .textAlign(TextAlign.Start).align(Alignment.TopStart)
|
||||
.width('100%')
|
||||
Row() {
|
||||
Row() {
|
||||
Text('今日')
|
||||
.borderRadius(30)
|
||||
.fontColor(Color.White)
|
||||
.backgroundColor('#f24d57')
|
||||
.fontSize(11)
|
||||
.padding({ left: 5, right: 5,top:2,bottom:2 })
|
||||
.visibility(TimestampUtil.isToday(this.item.createDate) ? Visibility.Visible : Visibility.None)
|
||||
Text(this.item.createDate.length > 10 ? this.item.createDate.substring(5, 10) : this.item.createDate)
|
||||
.fontColor($r('app.color.common_gray_03'))
|
||||
.fontSize(12)
|
||||
.visibility(!TimestampUtil.isToday(this.item.createDate) ? Visibility.Visible : Visibility.None)
|
||||
}.width(80).align(Alignment.Start)
|
||||
|
||||
Row() {
|
||||
Image($r('app.media.read_commient')).width(10).height(10)
|
||||
Text(Number(this.item.readnum) > 100000 ? Number(this.item.readnum) * 1.000 / 10000.00 + '万' : this.item.readnum + '')
|
||||
.fontColor($r('app.color.common_gray_03')).padding({left:3})
|
||||
.fontSize(12)
|
||||
}.width(80).align(Alignment.Start)
|
||||
|
||||
Row() {
|
||||
Image($r('app.media.argee_commient')).width(10).height(10)
|
||||
Text(Number(this.item.agreenum) > 100000 ? Number(this.item.agreenum) * 1.000 / 10000.00 + '万' : this.item.agreenum + '')
|
||||
.fontColor($r('app.color.common_gray_03')).padding({left:3})
|
||||
.fontSize(12)
|
||||
}.width(80).align(Alignment.Start)
|
||||
}
|
||||
.margin({top:10})
|
||||
.width('100%')
|
||||
}.padding({left:10})
|
||||
.layoutWeight(1)
|
||||
|
||||
}.alignSelf(ItemAlign.Start)
|
||||
|
||||
.width('100%')
|
||||
.padding(10)
|
||||
.onClick(() => {
|
||||
newsUtil.readNews(this.item.uuid,this.item)
|
||||
})
|
||||
Text().backgroundColor($r('app.color.efefef')).width('100%').height(1)
|
||||
}
|
||||
.backgroundColor(Color.White)
|
||||
}
|
||||
}
|
||||
|
||||
79
features/study/src/main/ets/views/NewsSwiperView.ets
Normal file
@ -0,0 +1,79 @@
|
||||
import { AppUtil, BasicConstant,hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { HdLoadingDialog } from '@itcast/basic'
|
||||
import HashMap from '@ohos.util.HashMap';
|
||||
import { newsRequestOfData, newsRollNewRequest } from '../models/NewsModel';
|
||||
import { newsUtil } from '../utils/NewsUtil';
|
||||
|
||||
@Component
|
||||
export struct NewsSwiperView {
|
||||
@State list: newsRequestOfData[] = []
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.initData()
|
||||
}
|
||||
|
||||
initData() {
|
||||
const hashMap: HashMap<string, string> = new HashMap();
|
||||
this.dialog.open()
|
||||
hashMap.clear();
|
||||
hdHttp.httpReq<string>(BasicConstant.newsRollNew,hashMap).then(async (res: HdResponse<string>) => {
|
||||
logger.info('Response newsRollNew'+res);
|
||||
let json:newsRollNewRequest = JSON.parse(res+'') as newsRollNewRequest;
|
||||
this.dialog.close();
|
||||
this.list = json.data
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
})
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() { // 使用堆叠布局实现按钮覆盖
|
||||
Swiper() {
|
||||
ForEach(this.list, (item: newsRequestOfData) => {
|
||||
Stack({alignContent:Alignment.Bottom}) {
|
||||
Image(BasicConstant.urlHtml + item.headImg)
|
||||
.objectFit(ImageFit.Fill)// 图片填充模式
|
||||
.width('100%')
|
||||
.height(AppUtil.getDisplayWindowWidth().vp / 16 * 9)
|
||||
Text(item.title)
|
||||
.maxLines(1)
|
||||
.height(30)
|
||||
.fontColor('#F6F6F6')
|
||||
.textAlign(TextAlign.Start)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
.backgroundColor('#88000000')
|
||||
.width('100%')
|
||||
.padding({right:100,left:5})
|
||||
.margin({ bottom: 0 })
|
||||
}.onClick(()=>{
|
||||
newsUtil.readNews(item.uuid,item)
|
||||
})
|
||||
}, (item: newsRequestOfData) => JSON.stringify(item))
|
||||
}
|
||||
.indicator(
|
||||
Indicator.dot()
|
||||
.right(0)
|
||||
.itemWidth(4)
|
||||
.itemHeight(4)
|
||||
.selectedItemWidth(4)
|
||||
.selectedItemHeight(4)
|
||||
.color($r('app.color.common_gray_02'))
|
||||
.selectedColor('#3cc9c0')
|
||||
)
|
||||
.loop(true)
|
||||
.autoPlay(true)
|
||||
.interval(3000)
|
||||
.onChange((index: number) => {
|
||||
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
BIN
features/study/src/main/resources/base/media/news_new_icon.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
BIN
features/study/src/main/resources/base/media/patientLogo.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
BIN
features/study/src/main/resources/base/media/pay_wx_icon.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 12 KiB |
@ -4,7 +4,7 @@ import { window } from '@kit.ArkUI';
|
||||
import notificationManager from '@ohos.notificationManager';
|
||||
import { PLVMediaPlayerStartUp } from '../startup/PLVMediaPlayerStartUp';
|
||||
import contextConstant from '@ohos.app.ability.contextConstant';
|
||||
import { patientDbManager } from '@itcast/basic';
|
||||
import { patientDbManager, WXApi, WXEventHandler } from '@itcast/basic';
|
||||
import { HMRouterMgr } from '@hadss/hmrouter'
|
||||
import { BusinessError } from '@kit.BasicServicesKit'
|
||||
|
||||
@ -16,6 +16,8 @@ export default class EntryAbility extends UIAbility {
|
||||
this.checkNotificationStatus(); // 首次检查
|
||||
// 初始化患者数据库
|
||||
this.initPatientDatabase();
|
||||
//微信
|
||||
this.handleWeChatCallIfNeed(want)
|
||||
|
||||
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
|
||||
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
|
||||
@ -89,4 +91,12 @@ export default class EntryAbility extends UIAbility {
|
||||
// 错误处理,例如保持当前状态或设置为默认值
|
||||
}
|
||||
}
|
||||
|
||||
onNewWant(want: Want, _launchParam: AbilityConstant.LaunchParam): void {
|
||||
this.handleWeChatCallIfNeed(want)
|
||||
}
|
||||
|
||||
private handleWeChatCallIfNeed(want: Want) {
|
||||
WXApi.handleWant(want, WXEventHandler)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
import { HdNav } from '@itcast/basic'
|
||||
import { router } from '@kit.ArkUI'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct AllDownloadPage {
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
HdNav({title:'我的下载',showRightIcon:false,showRightText:false})
|
||||
|
||||
Column() {
|
||||
Row(){
|
||||
Text('课件文档')
|
||||
.fontSize(16)
|
||||
.layoutWeight(1)
|
||||
Image($r('app.media.arrow_right'))
|
||||
.width(7)
|
||||
.height(10)
|
||||
.margin({right:10})
|
||||
}
|
||||
.width('100%')
|
||||
.height('calc(100% - 1vp)')
|
||||
}
|
||||
.width('100%')
|
||||
.height(50)
|
||||
.padding(10)
|
||||
.backgroundColor(Color.White)
|
||||
.onClick(()=>{
|
||||
router.pushUrl({url:'pages/Download/KeJianDownloadPage'})
|
||||
})
|
||||
}
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
.backgroundColor('#f1f1f1')
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,149 @@
|
||||
import { DefaultHintProWindows, HdNav } from '@itcast/basic'
|
||||
import { FileManager } from '@itcast/basic'
|
||||
import { FileInfo } from '@itcast/basic'
|
||||
import { common } from '@kit.AbilityKit'
|
||||
import { promptAction } from '@kit.ArkUI'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct KeJianDownloadPage {
|
||||
@State fileList: FileInfo[] = []
|
||||
private fileManager: FileManager | null = null
|
||||
@State selected:number = 0
|
||||
|
||||
alertView:CustomDialogController = new CustomDialogController({
|
||||
builder:DefaultHintProWindows({
|
||||
title:'提示',
|
||||
message:'确定删除该课件?',
|
||||
cancleTitleColor: '#666666',
|
||||
confirmTitleColor: $r('app.color.main_color'),
|
||||
selectedButton: (index:number)=>{
|
||||
this.alertView.close();
|
||||
if (index == 1) {
|
||||
this.deleteFile(this.fileList[this.selected].fileId)
|
||||
}
|
||||
}
|
||||
}),
|
||||
alignment: DialogAlignment.Center,
|
||||
cornerRadius:24,
|
||||
backgroundColor: ('rgba(0,0,0,0.5)'),
|
||||
})
|
||||
|
||||
aboutToAppear() {
|
||||
this.initFileManager()
|
||||
this.loadDownloadedFiles()
|
||||
}
|
||||
|
||||
private initFileManager() {
|
||||
try {
|
||||
const context = getContext(this) as common.UIAbilityContext
|
||||
this.fileManager = new FileManager(context)
|
||||
} catch (error) {
|
||||
console.error('初始化文件管理器失败:', error)
|
||||
promptAction.showToast({ message: '初始化失败', duration: 2000 })
|
||||
}
|
||||
}
|
||||
|
||||
private async loadDownloadedFiles() {
|
||||
try {
|
||||
if (this.fileManager) {
|
||||
this.fileList = await this.fileManager.getDownloadedFiles()
|
||||
console.info(`加载了 ${this.fileList.length} 个已下载文件`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载文件列表失败:', error)
|
||||
promptAction.showToast({ message: '加载失败', duration: 2000 })
|
||||
}
|
||||
}
|
||||
|
||||
private async previewFile(fileId: string) {
|
||||
try {
|
||||
if (this.fileManager) {
|
||||
await this.fileManager.previewFile(fileId)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('预览文件失败:', error)
|
||||
promptAction.showToast({ message: '预览失败', duration: 2000 })
|
||||
}
|
||||
}
|
||||
|
||||
private async deleteFile(fileId: string) {
|
||||
try {
|
||||
if (this.fileManager) {
|
||||
const success = await this.fileManager.deleteFile(fileId)
|
||||
if (success) {
|
||||
this.fileList = this.fileList.filter(file => file.fileId !== fileId)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('删除文件失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
HdNav({title:'课件文档',showRightIcon:false,showRightText:false})
|
||||
|
||||
if (this.fileList.length === 0) {
|
||||
Column() {
|
||||
Text('暂无下载课件')
|
||||
.fontSize(16)
|
||||
.fontColor('#999999')
|
||||
.margin({ top: 10 })
|
||||
}
|
||||
.width('100%')
|
||||
.height(200)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
} else {
|
||||
List() {
|
||||
ForEach(this.fileList, (file: FileInfo, index: number) => {
|
||||
ListItem() {
|
||||
Row() {
|
||||
Text(file.fileName)
|
||||
.fontSize(16)
|
||||
.fontColor('#333333')
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.maxLines(1)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
.layoutWeight(1)
|
||||
}
|
||||
.height(50)
|
||||
.width('100%')
|
||||
.padding(10)
|
||||
.backgroundColor(Color.White)
|
||||
.onClick(() => {
|
||||
this.previewFile(file.fileId)
|
||||
})
|
||||
}
|
||||
.swipeAction({
|
||||
end: {
|
||||
builder: () => { this.itemEnd(index) },
|
||||
}
|
||||
})
|
||||
}, (file: FileInfo) => file.fileId)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.backgroundColor('#f1f1f1')
|
||||
}
|
||||
}
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
.backgroundColor('#F5F5F5')
|
||||
}
|
||||
|
||||
@Builder
|
||||
itemEnd(index: number) {
|
||||
Text('删除')
|
||||
.fontSize(14)
|
||||
.fontColor(Color.White)
|
||||
.backgroundColor(Color.Red)
|
||||
.textAlign(TextAlign.Center)
|
||||
.size({width:60,height:50})
|
||||
.borderRadius(4)
|
||||
.onClick(() => {
|
||||
this.selected = index
|
||||
this.alertView.open()
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
import { FlowerDetailsComp } from 'study'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct FlowerDetailsPage {
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
FlowerDetailsComp()
|
||||
}
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@ import { NimRepository } from '../../entryability/NimRepository'
|
||||
import { AppConfig } from '../../constants/AppConfig'
|
||||
import { PerfactInputSheet } from '@itcast/basic/src/main/ets/Views/PerfactInputSheet'
|
||||
import { LengthMetrics, router } from '@kit.ArkUI'
|
||||
import { TimestampUtil } from '@itcast/basic'
|
||||
import { TimestampUtil, WXApi } from '@itcast/basic'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
@ -65,6 +65,7 @@ struct LoginPage {
|
||||
this.dialog.open()
|
||||
}
|
||||
|
||||
console.info('是否安装微信:',WXApi.isWXAppInstalled())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
14
products/expert/src/main/ets/pages/Meeting/MeetingPage.ets
Normal file
@ -0,0 +1,14 @@
|
||||
import { VideoPage } from 'home'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct MeetingPage {
|
||||
|
||||
build() {
|
||||
Column(){
|
||||
VideoPage()
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,7 @@ struct SettingPage {
|
||||
getVersion() {
|
||||
bundleManager.getBundleInfoForSelf(
|
||||
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION |
|
||||
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_METADATA
|
||||
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_METADATA | bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO
|
||||
)
|
||||
.then((res) => {
|
||||
this.version = 'V' + res.versionName
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
import { NewsListComp } from 'study'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct GandanNewsListPage {
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
NewsListComp()
|
||||
}
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
14
products/expert/src/main/ets/pages/News/GandanNewsPages.ets
Normal file
@ -0,0 +1,14 @@
|
||||
import { NewsComp } from 'study'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct GandanNewsPages {
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
NewsComp()
|
||||
}
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
14
products/expert/src/main/ets/pages/Pay/PayPage.ets
Normal file
@ -0,0 +1,14 @@
|
||||
import { PayComp } from 'study';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct PayPage {
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
PayComp()
|
||||
}
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
14
products/expert/src/main/ets/pages/Pay/SendFollowPage.ets
Normal file
@ -0,0 +1,14 @@
|
||||
import { SendFollowComp } from 'study'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct SendFollowPage {
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
SendFollowComp()
|
||||
}
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,7 @@
|
||||
import webview from '@ohos.web.webview';
|
||||
import { BasicConstant, HdNav, preferenceStore } from '@itcast/basic';
|
||||
import { authStore, BasicConstant, hdHttp, HdLoadingDialog, HdNav, HdResponse, preferenceStore } from '@itcast/basic';
|
||||
import router from '@ohos.router';
|
||||
import { image } from '@kit.ImageKit';
|
||||
import { photoAccessHelper } from '@kit.MediaLibraryKit';
|
||||
import { promptAction } from '@kit.ArkUI';
|
||||
import { fileIo, fileUri } from '@kit.CoreFileKit';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { PatientTBean } from '@itcast/basic/src/main/ets/models/TeachModel';
|
||||
|
||||
@ -13,6 +10,10 @@ import { PatientTBean } from '@itcast/basic/src/main/ets/models/TeachModel';
|
||||
struct EducationDetailsWebPage {
|
||||
private controller: webview.WebviewController = new webview.WebviewController();
|
||||
@State params:RouteParams = router.getParams() as RouteParams;
|
||||
@State isDianZan:boolean = String(this.params.isAgree)=='1'?true:false
|
||||
@State isShouCang:boolean = false
|
||||
@State agreenum:string = this.params.model.agreenum.toString()
|
||||
@State readnum:string = this.params.model.readnum.toString()
|
||||
|
||||
// 修改为移动端User-Agent,解决链接中有视频的问题
|
||||
private customUserAgent: string = 'Mozilla/5.0 (Linux; Android 10; HarmonyOS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 gdxz-expert';
|
||||
@ -22,6 +23,16 @@ struct EducationDetailsWebPage {
|
||||
@State url: string = BasicConstant.urlHtml+this.params.model.path;
|
||||
@State title: string = '患教详情';
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.getKepuDetailsData()
|
||||
}
|
||||
|
||||
onBackPress(): boolean | void {
|
||||
if (this.controller.accessStep(-1)) {
|
||||
this.controller.backward();
|
||||
@ -64,24 +75,173 @@ struct EducationDetailsWebPage {
|
||||
|
||||
})
|
||||
.width('100%')
|
||||
.layoutWeight(1)
|
||||
.height('calc(100% - 80vp)')
|
||||
.height('calc(100% - 156vp)')
|
||||
.clip(true)
|
||||
|
||||
Row(){
|
||||
Row(){
|
||||
Image('')
|
||||
Image($r('app.media.eye_main_color'))
|
||||
.size({width:20,height:20})
|
||||
.objectFit(ImageFit.Contain)
|
||||
Text(this.readnum)
|
||||
.margin({left:10})
|
||||
.fontSize(15)
|
||||
.fontColor(Color.Gray)
|
||||
}
|
||||
.margin({left:15,top:12})
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width(80)
|
||||
.margin({top:12})
|
||||
.layoutWeight(1)
|
||||
Row(){
|
||||
Image(this.isDianZan?$r('app.media.yi_dian_zan'):$r('app.media.wei_dian_zan'))
|
||||
.objectFit(ImageFit.Contain)
|
||||
.size({width:20,height:20})
|
||||
Text(this.agreenum)
|
||||
.margin({left:10})
|
||||
.fontSize(15)
|
||||
.fontColor(Color.Gray)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width(80)
|
||||
.margin({top:12})
|
||||
.layoutWeight(1)
|
||||
.onClick(()=>{
|
||||
this.setAgreeData(this.isDianZan?"0":"1")
|
||||
})
|
||||
Row(){
|
||||
Image(this.isShouCang?$r('app.media.yi_shou_cang'):$r('app.media.wei_shou_cang'))
|
||||
.objectFit(ImageFit.Contain)
|
||||
.size({width:20,height:20})
|
||||
Text('收藏')
|
||||
.margin({left:10})
|
||||
.fontSize(15)
|
||||
.fontColor(Color.Gray)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width(80)
|
||||
.margin({top:12})
|
||||
.layoutWeight(1)
|
||||
.onClick(()=>{
|
||||
this.setCollectionData(this.isShouCang?"0":"1")
|
||||
})
|
||||
Row(){
|
||||
Image($r('app.media.fenxiang'))
|
||||
.objectFit(ImageFit.Contain)
|
||||
.size({width:20,height:20})
|
||||
Text('分享')
|
||||
.margin({left:10})
|
||||
.fontSize(15)
|
||||
.fontColor(Color.Gray)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width(80)
|
||||
.margin({top:12})
|
||||
.layoutWeight(1)
|
||||
.onClick(()=>{
|
||||
promptAction.showToast({ message:'敬请期待', duration: 1000 })
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.alignItems(VerticalAlign.Top)
|
||||
.backgroundColor(Color.White)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
getKepuDetailsData() {
|
||||
const entity = {
|
||||
"uuid":this.params.model.uuid,
|
||||
"user_uuid": authStore.getUser().uuid
|
||||
} as Record<string,string>
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(BasicConstant.getKePuCollection, entity).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
console.info('Response delConditionRecord'+res);
|
||||
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
|
||||
if(json.code == '1') {
|
||||
let isCollection = json.isCollection
|
||||
if (isCollection == '1') {
|
||||
this.isShouCang = true
|
||||
} else {
|
||||
this.isShouCang = false
|
||||
}
|
||||
this.readnum = String(json.readnum)
|
||||
this.agreenum = String(json.agreenum)
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
console.error(`Response fails: ${err}`);
|
||||
promptAction.showToast({ message: String('患教文库数据请求失败!'), duration: 1000 })
|
||||
})
|
||||
}
|
||||
|
||||
setCollectionData(type:string) {//0取消收藏;1收藏
|
||||
const entity = {
|
||||
"other_uuid":this.params.model.uuid,
|
||||
"user_uuid": authStore.getUser().uuid,
|
||||
"title":this.params.model.topic,
|
||||
"path":this.params.model.path,
|
||||
"imgpath":this.params.model.imgPath,
|
||||
"readnum":this.readnum,
|
||||
"type":"2"
|
||||
} as Record<string,string>
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(type=='0'?BasicConstant.discollection:BasicConstant.collection, entity).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
console.info('Response delConditionRecord'+res);
|
||||
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
|
||||
if(json.code == '1') {
|
||||
if (type == '0') {
|
||||
this.isShouCang = false
|
||||
promptAction.showToast({ message: '取消收藏成功', duration: 1000 })
|
||||
} else {
|
||||
this.isShouCang = true
|
||||
promptAction.showToast({ message: '收藏成功', duration: 1000 })
|
||||
}
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
console.error(`Response fails: ${err}`);
|
||||
promptAction.showToast({ message: String('患教文库数据请求失败!'), duration: 1000 })
|
||||
})
|
||||
}
|
||||
|
||||
setAgreeData(type:string) {//0取消点赞;1点赞
|
||||
const entity = {
|
||||
"news_article_uuid":this.params.model.uuid,
|
||||
"user_uuid": authStore.getUser().uuid,
|
||||
"type":"2"
|
||||
} as Record<string,string>
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(type=='0'?BasicConstant.disagree:BasicConstant.agree, entity).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
console.info('Response delConditionRecord'+res);
|
||||
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
|
||||
if(json.code == '1') {
|
||||
if (type == '0') {
|
||||
this.agreenum = String(Number(this.agreenum)-1)
|
||||
this.isDianZan = false
|
||||
promptAction.showToast({ message: '取消点赞成功', duration: 1000 })
|
||||
} else {
|
||||
this.agreenum = String(Number(this.agreenum)+1)
|
||||
this.isDianZan = true
|
||||
promptAction.showToast({ message: '点赞成功', duration: 1000 })
|
||||
}
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
console.error(`Response fails: ${err}`);
|
||||
promptAction.showToast({ message: String('患教文库数据请求失败!'), duration: 1000 })
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface RouteParams {
|
||||
model:PatientTBean
|
||||
isAgree:string
|
||||
}
|
||||
@ -0,0 +1,553 @@
|
||||
import webview from '@ohos.web.webview';
|
||||
import {
|
||||
authStore, BasicConstant,
|
||||
ChangeUtil,
|
||||
DefaultHintProWindows,
|
||||
FileManager,
|
||||
FileInfo,
|
||||
hdHttp, HdLoadingDialog, HdNav, HdResponse, preferenceStore,
|
||||
WXApi,
|
||||
AESEncryptionDecryption} from '@itcast/basic';
|
||||
import router from '@ohos.router';
|
||||
import { promptAction } from '@kit.ArkUI';
|
||||
import { BusinessError, emitter } from '@kit.BasicServicesKit';
|
||||
import { KeJianModel } from 'study/src/main/ets/models/KeJianModel';
|
||||
import { HashMap } from '@kit.ArkTS';
|
||||
import * as wxopensdk from '@tencent/wechat_open_sdk';
|
||||
import { common, Want } from '@kit.AbilityKit';
|
||||
import { http } from '@kit.NetworkKit';
|
||||
import { fileIo } from '@kit.CoreFileKit';
|
||||
import request from '@ohos.request';
|
||||
|
||||
export enum OrderStatus {
|
||||
status_default = 0,/**不能点击 */
|
||||
status_pay = 1,/**付费下载 */
|
||||
status_free = 2,/**免费下载 */
|
||||
status_download = 3,/**重新下载 */
|
||||
status_check = 4,/**查看课件 */
|
||||
}
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct KeJianDetailsWebPage {
|
||||
private controller: webview.WebviewController = new webview.WebviewController();
|
||||
@State params:RouteParams = router.getParams() as RouteParams;
|
||||
|
||||
// 修改为移动端User-Agent,解决链接中有视频的问题
|
||||
private customUserAgent: string = 'Mozilla/5.0 (Linux; Android 10; HarmonyOS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 gdxz-expert';
|
||||
private hcp_token:string = preferenceStore.getItemString(BasicConstant.EXPERT_HCP_TOKEN)
|
||||
|
||||
private wxApi = WXApi
|
||||
@State btnStatus: number = OrderStatus.status_default
|
||||
@State contentWidth: number = 0;
|
||||
@State contentHeight: number = 0;
|
||||
@State url: string = BasicConstant.urlHtml+this.params.model.preview_path;
|
||||
@State title: string = '课件详情';
|
||||
@State downloadImage: ResourceStr = ''
|
||||
@State isShowDownloadImage: boolean = false
|
||||
@State downloadState: string = ''
|
||||
@State collectionIcon: ResourceStr = $r('app.media.wei_shou_cang')
|
||||
@State kejianDetailsData : RequestData = {} as RequestData
|
||||
@State hintMessage:string = ''
|
||||
@State downType:string = ''
|
||||
@State down_order_id:string = ''
|
||||
@State isUseFreeRecord:boolean = false
|
||||
@State isUserWelfareNum:boolean = false
|
||||
@State system_time:string = ''
|
||||
|
||||
private context: common.Context = getContext(this) as common.Context;
|
||||
private fileManager: FileManager = new FileManager(this.context);
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
alertView:CustomDialogController = new CustomDialogController({
|
||||
builder:DefaultHintProWindows({
|
||||
title:'提示',
|
||||
message:this.hintMessage,
|
||||
cancleTitleColor: '#666666',
|
||||
confirmTitleColor: $r('app.color.main_color'),
|
||||
selectedButton: (index:number)=>{
|
||||
this.alertView.close();
|
||||
if (index == 1) {//确定按钮
|
||||
if (this.btnStatus == OrderStatus.status_free) {
|
||||
if (this.hintMessage.includes('确定要下载')) {
|
||||
this.chackNetStatusAction()
|
||||
}
|
||||
} else if (this.btnStatus == OrderStatus.status_pay) {
|
||||
if (this.hintMessage.includes('免费下载机会')) {
|
||||
if (this.kejianDetailsData.welfareNum !== '0') {
|
||||
this.isUserWelfareNum = true
|
||||
this.useWelfareData()
|
||||
} else {
|
||||
if (this.kejianDetailsData.freeRecord !== '0') {
|
||||
this.isUseFreeRecord = true
|
||||
this.chackNetStatusAction()
|
||||
} else {
|
||||
this.chackNetStatusAction()
|
||||
}
|
||||
}
|
||||
} else if (this.hintMessage.includes('确定要下载')) {
|
||||
this.creatOrderData()
|
||||
} else if (this.hintMessage.includes('正使用手机网络')) {
|
||||
this.downloadFileAction()
|
||||
}
|
||||
}
|
||||
} else {//取消按钮
|
||||
if (this.btnStatus == OrderStatus.status_pay) {
|
||||
if (this.hintMessage.includes('免费下载机会')) {
|
||||
this.creatOrderData()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
alignment: DialogAlignment.Center,
|
||||
cornerRadius:24,
|
||||
backgroundColor: ('rgba(0,0,0,0.5)'),
|
||||
})
|
||||
|
||||
private refreshDataCallback = (eventData?: emitter.EventData): void => {
|
||||
if (Object(eventData?.data)['status'] == 'success') {
|
||||
this.chackNetStatusAction()
|
||||
}
|
||||
};
|
||||
|
||||
onPageShow(): void {
|
||||
this.getKeJianDetailsData()
|
||||
}
|
||||
|
||||
aboutToDisappear(): void {
|
||||
emitter.off(BasicConstant.notification_kejian_pay_success, this.refreshDataCallback)
|
||||
}
|
||||
|
||||
aboutToAppear(): void {
|
||||
let innerEvent: emitter.InnerEvent = {
|
||||
eventId: BasicConstant.notification_kejian_pay_success
|
||||
}
|
||||
emitter.on(innerEvent, this.refreshDataCallback)
|
||||
if (this.params.model.preview_path.includes('http')) {
|
||||
this.url = this.params.model.preview_path
|
||||
}
|
||||
}
|
||||
|
||||
onBackPress(): boolean | void {
|
||||
if (this.controller.accessStep(-1)) {
|
||||
this.controller.backward();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
if (WXApi.isWXAppInstalled()) {
|
||||
HdNav({
|
||||
title: this.title,
|
||||
showRightIcon: true,
|
||||
rightIcon: $r('app.media.fenxiang'),
|
||||
twoRightIcon: this.collectionIcon,
|
||||
hasBorder: true,
|
||||
isLeftAction: true,
|
||||
showTwoRightItem: true,
|
||||
leftItemAction: () => {
|
||||
if (this.controller.accessBackward()) {
|
||||
this.controller.backward();
|
||||
} else {
|
||||
if (this.fileManager.isDownloadingFile()) {
|
||||
promptAction.showToast({message:'当前有课件正在下载,请稍等...'})
|
||||
} else {
|
||||
router.back();
|
||||
}
|
||||
}
|
||||
},
|
||||
rightItemAction: () => {
|
||||
let shareUrl = new wxopensdk.WXWebpageObject
|
||||
shareUrl.type = 5
|
||||
shareUrl.webpageUrl = `${this.url}&fromtype=doctor`
|
||||
let mediaMessage = new wxopensdk.WXMediaMessage()
|
||||
mediaMessage.title = this.params.model.title
|
||||
mediaMessage.description = '肝胆相照-国内专业优质肝胆课件共享平台'
|
||||
mediaMessage.mediaObject = shareUrl
|
||||
let req = new wxopensdk.SendMessageToWXReq()
|
||||
req.scene = 0
|
||||
req.message = mediaMessage
|
||||
let finished = this.wxApi.sendReq(getContext(this) as common.UIAbilityContext, req)
|
||||
console.log("send request finished: ", finished)
|
||||
},
|
||||
twoRightItemAction: () => {
|
||||
this.setCollectionData(this.kejianDetailsData.iscollection == '0' ? '1' : '0')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
HdNav({
|
||||
title: this.title,
|
||||
showRightIcon: true,
|
||||
rightIcon: this.collectionIcon,
|
||||
hasBorder: true,
|
||||
isLeftAction: true,
|
||||
leftItemAction: () => {
|
||||
if (this.controller.accessBackward()) {
|
||||
this.controller.backward();
|
||||
} else {
|
||||
if (this.fileManager.isDownloadingFile()) {
|
||||
promptAction.showToast({message:'当前有课件正在下载,请稍等...'})
|
||||
} else {
|
||||
router.back();
|
||||
}
|
||||
}
|
||||
},
|
||||
rightItemAction: () => {
|
||||
this.setCollectionData(this.kejianDetailsData.iscollection == '0' ? '1' : '0')
|
||||
}
|
||||
})
|
||||
}
|
||||
Stack() {
|
||||
Web({
|
||||
src: this.url,
|
||||
controller: this.controller
|
||||
})
|
||||
.id('webView')
|
||||
.mixedMode(MixedMode.All)
|
||||
.overScrollMode(OverScrollMode.ALWAYS)
|
||||
.domStorageAccess(true)
|
||||
.onControllerAttached(() => {
|
||||
let userAgent = this.controller.getUserAgent() + this.customUserAgent;
|
||||
this.controller.setCustomUserAgent(userAgent);
|
||||
})
|
||||
.onPageBegin(() => {
|
||||
this.dialog.open()
|
||||
this.controller.runJavaScript(`document.cookie = 'hcp_from=expert_app; domain=.igandan.com; path=/';`)
|
||||
this.controller.runJavaScript(`document.cookie = 'hcp_token=${this.hcp_token}; domain=.igandan.com; path=/';`)
|
||||
})
|
||||
.onPageEnd(() => {
|
||||
this.dialog.close()
|
||||
// 注入JS获取body高度
|
||||
this.controller.runJavaScript(
|
||||
'document.documentElement.scrollWidth', (error, result) => {
|
||||
if (!error) this.contentWidth = Number(result);
|
||||
}
|
||||
);
|
||||
this.controller.runJavaScript('document.body.scrollHeight', (error, result) => {
|
||||
if (!error) this.contentHeight = Number(result);
|
||||
})
|
||||
})
|
||||
.width('100%')
|
||||
.layoutWeight(1)
|
||||
|
||||
Row(){
|
||||
Image(this.downloadImage)
|
||||
.size({width:16,height:16})
|
||||
.visibility(this.isShowDownloadImage?Visibility.Visible:Visibility.None)
|
||||
Text(this.downloadState)
|
||||
.fontSize(18)
|
||||
.fontColor(Color.White)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.backgroundColor(Color.Gray)
|
||||
.width('100%')
|
||||
.height(44)
|
||||
.onClick(()=>{
|
||||
if (this.btnStatus == OrderStatus.status_check) {
|
||||
// 查看已下载文件
|
||||
this.fileManager.previewFile(this.params.model.uuid)
|
||||
} else if (this.btnStatus == OrderStatus.status_download) {
|
||||
// 重新下载
|
||||
this.downloadFileAction()
|
||||
} else if (this.btnStatus == OrderStatus.status_pay) {
|
||||
if (this.kejianDetailsData.welfareNum == '0') {
|
||||
if (this.kejianDetailsData.freeRecord == '0') {
|
||||
this.hintMessage = '您确定要下载该课件吗'
|
||||
this.alertView.open()
|
||||
} else {
|
||||
this.hintMessage = `您还有${this.getFreeDownLoadCount()}次免费下载机会,希望本次下载免费吗?`
|
||||
this.alertView.open()
|
||||
}
|
||||
} else {
|
||||
this.hintMessage = `您还有${this.getFreeDownLoadCount()}次免费下载机会,希望本次下载免费吗?`
|
||||
this.alertView.open()
|
||||
}
|
||||
} else if (this.btnStatus == OrderStatus.status_free) {
|
||||
this.hintMessage = '您确定要下载该课件吗'
|
||||
this.alertView.open()
|
||||
}
|
||||
})
|
||||
}
|
||||
.alignContent(Alignment.Top)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
getKeJianDetailsData() {
|
||||
const hashMap: HashMap<string, string> = new HashMap()
|
||||
this.dialog.open()
|
||||
hashMap.clear()
|
||||
hashMap.set('file_uuid', this.params.model.uuid)
|
||||
hdHttp.httpReq<string>(BasicConstant.ganDanFileDetials,hashMap).then(async (res: HdResponse<string>) => {
|
||||
console.info('Response ganDanFileDetials'+res)
|
||||
this.dialog.close()
|
||||
let json:Record<string,string | RequestData> = JSON.parse(res+'') as Record<string,string | RequestData>;
|
||||
if(json.code == '200') {
|
||||
this.kejianDetailsData = json.data as RequestData
|
||||
if (this.kejianDetailsData.iscollection == '0') {
|
||||
this.collectionIcon = $r('app.media.wei_shou_cang')
|
||||
} else {
|
||||
this.collectionIcon = $r('app.media.yi_shou_cang')
|
||||
}
|
||||
if (this.kejianDetailsData.order == null || this.kejianDetailsData.order == undefined) {//没有订单
|
||||
if (parseFloat(this.kejianDetailsData.price) < 0) {
|
||||
this.btnStatus = 0
|
||||
this.downloadImage = ''
|
||||
this.isShowDownloadImage = false
|
||||
this.downloadState = '本课件不支持下载'
|
||||
} else {
|
||||
this.btnStatus = 2
|
||||
this.downloadImage = $r('app.media.kejian_download_white')
|
||||
this.isShowDownloadImage = true
|
||||
this.downloadState = ' 本课件免费下载'
|
||||
}
|
||||
if (parseFloat(this.kejianDetailsData.price) > 0) {
|
||||
this.btnStatus = 1
|
||||
this.downloadImage = $r('app.media.kejian_download_white')
|
||||
this.isShowDownloadImage = true
|
||||
this.downloadState = `本课件下载${ChangeUtil.formatPrice(this.kejianDetailsData.price)}元`
|
||||
}
|
||||
} else {//有订单
|
||||
try {
|
||||
const downloadedFiles = await this.fileManager.getDownloadedFiles();
|
||||
const downloadedFile = downloadedFiles.find(file => file.fileId === this.params.model.uuid);
|
||||
if (downloadedFile && downloadedFile.filePath && fileIo.accessSync(downloadedFile.filePath)) {
|
||||
// 本地已存在,显示查看文件
|
||||
this.btnStatus = OrderStatus.status_check
|
||||
this.downloadImage = ''
|
||||
this.isShowDownloadImage = false
|
||||
this.downloadState = '查看课件'
|
||||
} else {
|
||||
// 本地不存在,显示重新下载
|
||||
this.down_order_id = `${this.kejianDetailsData.order['order_id']}&R`
|
||||
this.btnStatus = OrderStatus.status_download
|
||||
this.downloadImage = ''
|
||||
this.isShowDownloadImage = false
|
||||
this.downloadState = '重新下载本课件'
|
||||
}
|
||||
} catch (e) {
|
||||
// 异常情况下,默认提供重新下载
|
||||
this.btnStatus = OrderStatus.status_download
|
||||
this.downloadImage = ''
|
||||
this.isShowDownloadImage = false
|
||||
this.downloadState = ' 重新下载'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close()
|
||||
console.error(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
|
||||
chackNetStatusAction() {
|
||||
if (hdHttp.getNetworkType() == 2) {
|
||||
this.hintMessage = '您当前正使用手机网络,是否继续下载?'
|
||||
this.alertView.open()
|
||||
} else if (hdHttp.getNetworkType() == 1 || hdHttp.getNetworkType() == 3) {
|
||||
this.downloadFileAction()
|
||||
} else if (hdHttp.getNetworkType() == 0 || hdHttp.getNetworkType() == -1) {
|
||||
this.hintMessage = '未连接网络,请设置'
|
||||
this.alertView.open()
|
||||
}
|
||||
}
|
||||
|
||||
downloadFileAction() {
|
||||
let httpRequest = http.createHttp();
|
||||
let timeStampurl = BasicConstant.getSystemTime;
|
||||
let promise = httpRequest.request(timeStampurl, {
|
||||
method: http.RequestMethod.GET,
|
||||
connectTimeout: 60000,
|
||||
readTimeout: 60000,
|
||||
header: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
promise.then(async (data) => {
|
||||
if (data.responseCode === http.ResponseCode.OK) {
|
||||
let json:TimestampBean = JSON.parse(data.result.toString()) as TimestampBean
|
||||
let daijiami:string = ''
|
||||
if (this.btnStatus == OrderStatus.status_free) {
|
||||
daijiami = `${this.params.model.uuid}|FREE|${authStore.getUser().uuid}|${json.system_time}`
|
||||
} else if (this.btnStatus == OrderStatus.status_download) {
|
||||
daijiami = `${this.params.model.uuid}|${this.down_order_id}|${authStore.getUser().uuid}|${json.system_time}`
|
||||
}
|
||||
if (this.isUseFreeRecord) {
|
||||
daijiami = `${this.params.model.uuid}|FREERECORD|${authStore.getUser().uuid}|${json.system_time}`
|
||||
}
|
||||
if (this.kejianDetailsData.welfareNum != '0') {
|
||||
if (this.isUserWelfareNum) {
|
||||
daijiami = `${this.params.model.uuid}|USEWELFARENUM|${authStore.getUser().uuid}|${json.system_time}`
|
||||
}
|
||||
}
|
||||
const scanData = await AESEncryptionDecryption.aesEncrypt(daijiami,BasicConstant.ExpertAesKey)
|
||||
let x: number = 10;
|
||||
let valueINTT: number = Math.floor(Math.random() * x) + 1;
|
||||
let pinString = `${getChars(valueINTT)}${scanData}`
|
||||
let downloadUrl = `${BasicConstant.urlExpertApp}downloadGanDanFile?&gdf=${pinString}&a=${valueINTT}`
|
||||
console.info('开始下载文件,URL:', downloadUrl);
|
||||
const fileInfo: FileInfo = {
|
||||
fileId: this.params.model.uuid,
|
||||
fileName: this.params.model.title,
|
||||
fileType: this.params.model.type,
|
||||
fileSize: 0,
|
||||
fileUrl: downloadUrl,
|
||||
downloadStatus: 'pending',
|
||||
downloadProgress: 0,
|
||||
createTime: Date.now(),
|
||||
updateTime: Date.now()
|
||||
};
|
||||
promptAction.showToast({ message: '开始下载,请勿重复点击', duration: 1000 })
|
||||
this.fileManager.downloadFile(fileInfo, {
|
||||
onSuccess: (filePath: string) => {
|
||||
this.btnStatus = OrderStatus.status_check
|
||||
this.downloadImage = ''
|
||||
this.downloadState = '查看课件'
|
||||
},
|
||||
onFailed: (error: string) => {
|
||||
console.info('fileDownload,error:',error)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
).catch((err: BusinessError) => {
|
||||
return Promise.reject(err);
|
||||
}).finally(() => {
|
||||
httpRequest.destroy()
|
||||
})
|
||||
}
|
||||
|
||||
setCollectionData(type:string) {//0取消收藏;1收藏
|
||||
const entity = {
|
||||
"other_uuid":this.params.model.uuid,
|
||||
"user_uuid": authStore.getUser().uuid,
|
||||
"title":this.params.model.title,
|
||||
"path":this.params.model.preview_path,
|
||||
"type":"6"
|
||||
} as Record<string,string>
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(type=='0'?BasicConstant.discollection:BasicConstant.collection, entity).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
console.info('Response delConditionRecord'+res);
|
||||
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
|
||||
if(json.code == '1') {
|
||||
if (type == '0') {
|
||||
this.collectionIcon = $r('app.media.wei_shou_cang')
|
||||
promptAction.showToast({ message: '取消收藏成功', duration: 1000 })
|
||||
} else {
|
||||
this.collectionIcon = $r('app.media.yi_shou_cang')
|
||||
promptAction.showToast({ message: '收藏成功', duration: 1000 })
|
||||
}
|
||||
this.getKeJianDetailsData()
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
console.error(`Response fails: ${err}`);
|
||||
promptAction.showToast({ message: String('患教文库数据请求失败!'), duration: 1000 })
|
||||
})
|
||||
}
|
||||
|
||||
creatOrderData() {
|
||||
const hashMap: HashMap<string, string> = new HashMap()
|
||||
this.dialog.open()
|
||||
hashMap.clear()
|
||||
hashMap.set('file_uuid', this.params.model.uuid)
|
||||
hdHttp.httpReq<string>(BasicConstant.createGanDanFileOrder,hashMap).then(async (res: HdResponse<string>) => {
|
||||
console.info('Response ganDanFileDetials'+res)
|
||||
this.dialog.close()
|
||||
let json:Record<string,string | FileOrderData> = JSON.parse(res+'') as Record<string,string | FileOrderData>;
|
||||
if(json.code == '200') {
|
||||
router.pushUrl({
|
||||
url:"pages/Pay/PayPage",
|
||||
params:{"data":json.data,"page":"课件详情"}
|
||||
})
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close()
|
||||
console.error(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
|
||||
useWelfareData() {
|
||||
const hashMap: HashMap<string, string> = new HashMap()
|
||||
this.dialog.open()
|
||||
hashMap.clear()
|
||||
hashMap.set('type', '2')
|
||||
hashMap.set('other_uuid',this.params.model.uuid)
|
||||
hdHttp.httpReq<string>(BasicConstant.useWelfareNum,hashMap).then(async (res: HdResponse<string>) => {
|
||||
console.info('Response useWelfareNum'+res)
|
||||
this.dialog.close()
|
||||
let json:Record<string,string > = JSON.parse(res+'') as Record<string,string>;
|
||||
if(json.code == '1') {
|
||||
this.downloadFileAction()
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close()
|
||||
console.error(`Response fails: ${err}`);
|
||||
})
|
||||
}
|
||||
|
||||
private getFreeDownLoadCount():string {
|
||||
let count = Number(this.kejianDetailsData.welfareNum)+Number(this.kejianDetailsData.freeRecord)
|
||||
return count.toString()
|
||||
}
|
||||
}
|
||||
|
||||
interface RouteParams {
|
||||
model:KeJianModel
|
||||
}
|
||||
|
||||
interface RequestData {
|
||||
iscollection:string
|
||||
welfareNum:string
|
||||
freeRecord:string
|
||||
fileSize:string
|
||||
fileMD5:string
|
||||
price:string
|
||||
order:object
|
||||
}
|
||||
|
||||
interface FileOrderData {
|
||||
trade_no:string
|
||||
order_id:string
|
||||
amount:string
|
||||
account:string
|
||||
provider_name:string
|
||||
file_uuid:string
|
||||
order_status:string
|
||||
}
|
||||
|
||||
export interface TimestampBean {
|
||||
system_time:string
|
||||
}
|
||||
|
||||
export function getChars(number_od_chars:number):string {
|
||||
// 创建字符数组并填充随机大写字母
|
||||
let data: string[] = [];
|
||||
for (let i: number = 0; i < number_od_chars; i++) {
|
||||
// 生成A-Z的随机字母
|
||||
let randomChar: string = String.fromCharCode(65 + Math.floor(Math.random() * 26));
|
||||
data.push(randomChar);
|
||||
}
|
||||
|
||||
// 将字符数组转换为字符串
|
||||
let stringValue: string = data.join('');
|
||||
return stringValue
|
||||
}
|
||||
@ -0,0 +1,247 @@
|
||||
import webview from '@ohos.web.webview';
|
||||
import { authStore, BasicConstant, hdHttp, HdLoadingDialog, HdNav, HdResponse } from '@itcast/basic';
|
||||
import router from '@ohos.router';
|
||||
import { promptAction } from '@kit.ArkUI';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { newsRequestOfData } from 'study';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct NewsDetailsWebPage {
|
||||
private controller: webview.WebviewController = new webview.WebviewController();
|
||||
@State params:RouteParams = router.getParams() as RouteParams;
|
||||
@State isDianZan:boolean = String(this.params.isAgree)=='1'?true:false
|
||||
@State isShouCang:boolean = false
|
||||
@State agreenum:string = this.params.model.agreenum.toString()
|
||||
@State readnum:string = this.params.model.readnum.toString()
|
||||
|
||||
// 修改为移动端User-Agent,解决链接中有视频的问题
|
||||
private customUserAgent: string = 'Mozilla/5.0 (Linux; Android 10; HarmonyOS) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 gdxz-expert';
|
||||
|
||||
@State contentWidth: number = 0;
|
||||
@State contentHeight: number = 0;
|
||||
@State url: string = BasicConstant.urlHtml+this.params.model.path;
|
||||
@Prop title: string = '新闻详情';
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.getNewsDetailsData()
|
||||
}
|
||||
|
||||
onBackPress(): boolean | void {
|
||||
if (this.controller.accessStep(-1)) {
|
||||
this.controller.backward();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
HdNav({ title: this.title, showRightIcon: false, hasBorder: true ,isLeftAction:true,leftItemAction:()=>{
|
||||
if (this.controller.accessBackward()) {
|
||||
this.controller.backward();
|
||||
} else {
|
||||
router.back();
|
||||
}
|
||||
}})
|
||||
Web({
|
||||
src: this.url,
|
||||
controller: this.controller
|
||||
})
|
||||
.id('webView')
|
||||
.mixedMode(MixedMode.All)
|
||||
.overScrollMode(OverScrollMode.ALWAYS)
|
||||
.domStorageAccess(true)
|
||||
.onControllerAttached(() => {
|
||||
let userAgent = this.controller.getUserAgent() + this.customUserAgent;
|
||||
this.controller.setCustomUserAgent(userAgent);
|
||||
})
|
||||
.onPageEnd(() => {
|
||||
// 注入JS获取body高度
|
||||
this.controller.runJavaScript(
|
||||
'document.documentElement.scrollWidth', (error, result) => {
|
||||
if (!error) this.contentWidth = Number(result);
|
||||
}
|
||||
);
|
||||
this.controller.runJavaScript('document.body.scrollHeight',(error,result)=>{
|
||||
if (!error) this.contentHeight = Number(result);
|
||||
})
|
||||
|
||||
})
|
||||
.width('100%')
|
||||
.height('calc(100% - 156vp)')
|
||||
.clip(true)
|
||||
|
||||
Row(){
|
||||
Row(){
|
||||
Image($r('app.media.eye_main_color'))
|
||||
.size({width:20,height:20})
|
||||
.objectFit(ImageFit.Contain)
|
||||
Text(this.readnum)
|
||||
.margin({left:10})
|
||||
.fontSize(15)
|
||||
.fontColor(Color.Gray)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width(80)
|
||||
.margin({top:12})
|
||||
.layoutWeight(1)
|
||||
Row(){
|
||||
Image(this.isDianZan?$r('app.media.yi_dian_zan'):$r('app.media.wei_dian_zan'))
|
||||
.objectFit(ImageFit.Contain)
|
||||
.size({width:20,height:20})
|
||||
Text(this.agreenum)
|
||||
.margin({left:10})
|
||||
.fontSize(15)
|
||||
.fontColor(Color.Gray)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width(80)
|
||||
.margin({top:12})
|
||||
.layoutWeight(1)
|
||||
.onClick(()=>{
|
||||
this.setAgreeData(this.isDianZan?"0":"1")
|
||||
})
|
||||
Row(){
|
||||
Image(this.isShouCang?$r('app.media.yi_shou_cang'):$r('app.media.wei_shou_cang'))
|
||||
.objectFit(ImageFit.Contain)
|
||||
.size({width:20,height:20})
|
||||
Text('收藏')
|
||||
.margin({left:10})
|
||||
.fontSize(15)
|
||||
.fontColor(Color.Gray)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width(80)
|
||||
.margin({top:12})
|
||||
.layoutWeight(1)
|
||||
.onClick(()=>{
|
||||
this.setCollectionData(this.isShouCang?"0":"1")
|
||||
})
|
||||
Row(){
|
||||
Image($r('app.media.fenxiang'))
|
||||
.objectFit(ImageFit.Contain)
|
||||
.size({width:20,height:20})
|
||||
Text('分享')
|
||||
.margin({left:10})
|
||||
.fontSize(15)
|
||||
.fontColor(Color.Gray)
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width(80)
|
||||
.margin({top:12})
|
||||
.layoutWeight(1)
|
||||
.onClick(()=>{
|
||||
promptAction.showToast({ message:'敬请期待', duration: 1000 })
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.alignItems(VerticalAlign.Top)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
getNewsDetailsData() {
|
||||
const entity = {
|
||||
"uuid":this.params.model.uuid,
|
||||
"user_uuid": authStore.getUser().uuid
|
||||
} as Record<string,string>
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(BasicConstant.newsDetial, entity).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
console.info('Response delConditionRecord'+res);
|
||||
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
|
||||
if(json.code == '1') {
|
||||
let isCollection = json.isCollection
|
||||
if (isCollection == '1') {
|
||||
this.isShouCang = true
|
||||
} else {
|
||||
this.isShouCang = false
|
||||
}
|
||||
this.readnum = String(json.readnum)
|
||||
this.agreenum = String(json.agreenum)
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
console.error(`Response fails: ${err}`);
|
||||
promptAction.showToast({ message: String('患教文库数据请求失败!'), duration: 1000 })
|
||||
})
|
||||
}
|
||||
|
||||
setCollectionData(type:string) {//0取消收藏;1收藏
|
||||
const entity = {
|
||||
"other_uuid":this.params.model.uuid,
|
||||
"user_uuid": authStore.getUser().uuid,
|
||||
"title":this.params.model.title,
|
||||
"path":this.params.model.path,
|
||||
"imgpath":this.params.model.imgpath,
|
||||
"readnum":this.readnum,
|
||||
"type":"1"
|
||||
} as Record<string,string>
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(type=='0'?BasicConstant.discollection:BasicConstant.collection, entity).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
console.info('Response delConditionRecord'+res);
|
||||
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
|
||||
if(json.code == '1') {
|
||||
if (type == '0') {
|
||||
this.isShouCang = false
|
||||
promptAction.showToast({ message: '取消收藏成功', duration: 1000 })
|
||||
} else {
|
||||
this.isShouCang = true
|
||||
promptAction.showToast({ message: '收藏成功', duration: 1000 })
|
||||
}
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
console.error(`Response fails: ${err}`);
|
||||
promptAction.showToast({ message: String('患教文库数据请求失败!'), duration: 1000 })
|
||||
})
|
||||
}
|
||||
|
||||
setAgreeData(type:string) {//0取消点赞;1点赞
|
||||
const entity = {
|
||||
"news_article_uuid":this.params.model.uuid,
|
||||
"user_uuid": authStore.getUser().uuid,
|
||||
"type":"1"
|
||||
} as Record<string,string>
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(type=='0'?BasicConstant.disagree:BasicConstant.agree, entity).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
console.info('Response delConditionRecord'+res);
|
||||
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
|
||||
if(json.code == '1') {
|
||||
if (type == '0') {
|
||||
this.agreenum = String(Number(this.agreenum)-1)
|
||||
this.isDianZan = false
|
||||
promptAction.showToast({ message: '取消点赞成功', duration: 1000 })
|
||||
} else {
|
||||
this.agreenum = String(Number(this.agreenum)+1)
|
||||
this.isDianZan = true
|
||||
promptAction.showToast({ message: '点赞成功', duration: 1000 })
|
||||
}
|
||||
} else {
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
this.dialog.close();
|
||||
console.error(`Response fails: ${err}`);
|
||||
promptAction.showToast({ message: String('患教文库数据请求失败!'), duration: 1000 })
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface RouteParams {
|
||||
model:newsRequestOfData
|
||||
isAgree:string
|
||||
}
|
||||
@ -72,7 +72,16 @@
|
||||
"name": "ohos.permission.WRITE_MEDIA",
|
||||
"reason": "$string:media_reason",
|
||||
"usedScene": {}
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.READ_WRITE_USER_FILE",
|
||||
"reason": "$string:write_file",
|
||||
"usedScene": {}
|
||||
}
|
||||
],
|
||||
"querySchemes": [
|
||||
"weixin",
|
||||
"wxopensdk"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -49,6 +49,17 @@
|
||||
"pages/VideoPage/CustomScanResultPage",
|
||||
"pages/VideoPage/EducationVideoPage",
|
||||
"pages/Courseware/CoursewarePage",
|
||||
"pages/WebView/EducationDetailsWebPage"
|
||||
"pages/WebView/EducationDetailsWebPage",
|
||||
"pages/WebView/KeJianDetailsWebPage",
|
||||
"pages/Pay/PayPage",
|
||||
"pages/News/GandanNewsPages",
|
||||
"pages/WebView/NewsDetailsWebPage",
|
||||
"pages/Meeting/MeetingPage",
|
||||
"pages/News/GandanNewsListPage",
|
||||
"pages/Pay/SendFollowPage",
|
||||
"pages/Download/AllDownloadPage",
|
||||
"pages/Download/KeJianDownloadPage",
|
||||
"pages/Flower/FlowerDetailsPage",
|
||||
"pages/Courseware/CourseDetailsPage"
|
||||
]
|
||||
}
|
||||