首页、患者分组、审核、列表等

This commit is contained in:
xiaoxiao 2025-07-10 09:27:17 +08:00
parent 5954f51701
commit 4641e9ecee
136 changed files with 7577 additions and 171 deletions

6
RefreshLib/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/node_modules
/oh_modules
/.preview
/build
/.cxx
/.test

View File

@ -0,0 +1,17 @@
/**
* Use these variables when you tailor your ArkTS code. They must be of the const type.
*/
export const HAR_VERSION = '1.0.0';
export const BUILD_MODE_NAME = 'debug';
export const DEBUG = true;
export const TARGET_NAME = 'default';
/**
* BuildProfile Class is used only for compatibility purposes.
*/
export default class BuildProfile {
static readonly HAR_VERSION = HAR_VERSION;
static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
static readonly DEBUG = DEBUG;
static readonly TARGET_NAME = TARGET_NAME;
}

5
RefreshLib/CHANGELOG.md Normal file
View File

@ -0,0 +1,5 @@
# 版本更新记录
## [v1.0.0] 2024-09-24
# 首次上传

15
RefreshLib/Index.ets Normal file
View File

@ -0,0 +1,15 @@
export { PullToRefreshLayout } from './src/main/ets/PullToRefreshLayout'
export { RefreshLayout } from './src/main/ets/RefreshLayout'
export { RefreshLayoutConfig } from './src/main/ets/RefreshLayoutConfig'
export { PullDown } from './src/main/ets/PullDown'
export { PullStatus } from './src/main/ets/PullStatus'
export { RefreshLayoutHelper } from './src/main/ets/RefreshLayoutHelper'
export { RefreshController } from './src/main/ets/RefreshController'
export { PullToRefreshConfig } from './src/main/ets/PullToRefreshConfig'

22
RefreshLib/README.md Normal file
View File

@ -0,0 +1,22 @@
PullToRefresh
简介
PullToRefresh 实现垂直列表下拉刷新,上拉加载,横向列表左拉刷新,右拉加载
特点
1.无入侵性,不需要传数据源
2.不限制组件,支持任意布局(List,Grid,Web,Scroll,Text,Row,Column等布局)
3.支持header和footer定制(支持Lottie动画)
4.支持垂直列表和横向列表的刷新和加载
5.支持下拉(或者上拉)打开其他页面
提供了RefreshLayout和PullToRefreshLayout
1.RefreshLayout支持各种定制化
2.PullToRefreshLayout是在RefreshLayout基础上定制的实现常用刷新和加载功能
3.如果没有个性化需求可以直接使用PullToRefreshLayout
详细使用Domehttps://gitee.com/myspace01/refresh-lib

View File

@ -0,0 +1,31 @@
{
"apiType": "stageMode",
"buildOption": {
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": false,
"files": [
"./obfuscation-rules.txt"
]
},
"consumerFiles": [
"./consumer-rules.txt"
]
}
},
},
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest"
}
]
}

View File

6
RefreshLib/hvigorfile.ts Normal file
View File

@ -0,0 +1,6 @@
import { harTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
}

View File

@ -0,0 +1,23 @@
# Define project specific obfuscation rules here.
# You can include the obfuscation configuration files in the current module's build-profile.json5.
#
# For more details, see
# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
# Obfuscation options:
# -disable-obfuscation: disable all obfuscations
# -enable-property-obfuscation: obfuscate the property names
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
# -compact: remove unnecessary blank spaces and all line feeds
# -remove-log: remove all console.* statements
# -print-namecache: print the name cache that contains the mapping from the old names to new names
# -apply-namecache: reuse the given cache file
# Keep options:
# -keep-property-name: specifies property names that you want to keep
# -keep-global-name: specifies names that you want to keep in the global scope
-enable-property-obfuscation
-enable-toplevel-obfuscation
-enable-filename-obfuscation
-enable-export-obfuscation

View File

@ -0,0 +1,9 @@
{
"name": "refreshlib",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "Index.ets",
"author": "os_space",
"license": "Apache-2.0",
"dependencies": {}
}

View File

@ -0,0 +1,20 @@
import { PullStatus } from './PullStatus'
export interface PullDown {
/*是否是下拉*/
isPullDown: boolean
/*是否是上拉*/
isPullUp: boolean
/*是否触摸*/
isTouch: boolean
/*下拉距离*/
distance: number
/*上拉距离*/
distanceLoad: number
/*headerView高度*/
headerViewSize: number
/*footerView高度*/
footerViewSize: number
/*状态*/
status: PullStatus
}

View File

@ -0,0 +1,34 @@
export enum PullStatus {
/*0默认状态(无下拉距离)*/
DEF,
/***********************************下拉状态*******************************************/
/*1下拉状态*/
PullDown,
/*2下拉至可以刷新的状态(准备刷新)*/
PreRefresh,
/*3刷新中*/
Refresh,
/*4下拉超过刷新高度时准备打开其他页面*/
PreOpenPage,
/*5下拉超过刷新高度时松手打开其他页面*/
OpenPage,
/*6刷新成功*/
RefreshSuccess,
/*7刷新失败*/
RefreshError,
/***********************************上拉状态*******************************************/
/*8上拉状态*/
PullUp,
/*9上拉至可以加载的状态(准备加载)*/
PreLoad,
/*10加载中*/
Load,
/*11上拉超过加载高度时准备打开其他页面*/
PreLoadOpenPage,
/*12上拉超过加载高度时松手打开其他页面*/
LoadOpenPage,
/*13加载成功*/
LoadSuccess,
/*14加载失败*/
LoadError
}

View File

@ -0,0 +1,95 @@
export class PullToRefreshConfig {
/*刷新loading宽度*/
public refreshLoadingWidth: Length = 25
/*刷新loading高度*/
public refreshLoadingHeight: Length = 25
/*刷新loading颜色*/
public refreshLoadingColor: ResourceColor = "#333333"
/*下拉刷新箭头*/
public arrowImage: Resource = $r("app.media.icon_refresh_arrow")
/*下拉刷新箭头颜色*/
public arrowImageColor: ResourceColor = "#333333"
/*下拉刷新箭头宽度*/
public arrowImageWidth: Length = 20
/*下拉刷新箭头高度*/
public arrowImageHeight: Length = 20
/*上拉刷新箭头*/
public arrowLoadImage: Resource = $r("app.media.icon_refresh_arrow")
/*上拉刷新箭头颜色*/
public arrowLoadImageColor: ResourceColor = "#333333"
/*上拉刷新箭头宽度*/
public arrowLoadImageWidth: Length = 20
/*上拉刷新箭头高度*/
public arrowLoadImageHeight: Length = 20
/*暂无更多提示*/
public noMoreTips: string | Resource = $r("app.string.zr_load_no_more")
/*暂无更多提示大小*/
public noMoreTipsSize: number | string | Resource = 13
/*暂无更多提示颜色*/
public noMoreTipsColor: ResourceColor = "#666666"
/*暂无更多提示——横向列表*/
public noMoreTipsHorizontal: string | Resource = $r("app.string.h_zr_load_no_more")
/*是否显示刷新时间*/
public showRefreshTime: boolean = false
/*刷新时间tips大小*/
public refreshTimeTipsSize: number | string | Resource = 11
/*刷新时间tips颜色*/
public refreshTimeTipsColor: ResourceColor = "#999999"
/*下拉刷新提示*/
public pullDownTips: string | Resource = $r("app.string.zr_pull_down_to_refresh")
/*下拉刷新提示——横向列表*/
public pullDownTipsHorizontal: string | Resource = $r("app.string.h_zr_pull_down_to_refresh")
/*下拉刷新提示大小*/
public pullDownTipsSize: number | string | Resource = 13
/*下拉刷新提示颜色*/
public pullDownTipsColor: ResourceColor = "#666666"
/*释放立即刷新tips*/
public releaseRefreshTips: string | Resource = $r("app.string.zr_release_to_refresh")
/*释放立即刷新tips——横向列表*/
public releaseRefreshTipsHorizontal: string | Resource = $r("app.string.h_zr_release_to_refresh")
/*正在刷新tips*/
public refreshTips: string | Resource = $r("app.string.zr_refreshing")
/*正在刷新tips——横向列表*/
public refreshTipsHorizontal: string | Resource = $r("app.string.h_zr_refreshing")
/*刷新成功tips*/
public refreshSuccessTips: string | Resource = $r("app.string.zr_refresh_success")
/*刷新成功tips——横向列表*/
public refreshSuccessTipsHorizontal: string | Resource = $r("app.string.h_zr_refresh_success")
/*刷新失败tips*/
public refreshErrorTips: string | Resource = $r("app.string.zr_refresh_error")
/*刷新失败tips——横向列表*/
public refreshErrorTipsHorizontal: string | Resource = $r("app.string.h_zr_refresh_error")
/*下拉打开其他页面tips*/
public pullOpenPageTips: string | Resource = $r("app.string.zr_release_to_open_age")
/*下拉打开其他页面tips——横向列表*/
public pullOpenPageTipsHorizontal: string | Resource = $r("app.string.h_zr_release_to_open_age")
/*上拉加载提示*/
public pullUpTips: string | Resource = $r("app.string.zr_pull_up_to_load")
/*上拉加载提示——横向列表*/
public pullUpTipsHorizontal: string | Resource = $r("app.string.h_zr_pull_up_to_load")
/*上拉加载提示大小*/
public pullUpTipsSize: number | string | Resource = 13
/*上拉加载提示颜色*/
public pullUpTipsColor: ResourceColor = "#333333"
/*释放立即加载tips*/
public releaseLoadTips: string | Resource = $r("app.string.zr_release_to_load")
/*释放立即加载tips——横向列表*/
public releaseLoadTipsHorizontal: string | Resource = $r("app.string.h_zr_release_to_load")
/*正在加载tips*/
public loadTips: string | Resource = $r("app.string.zr_loading")
/*正在加载tips——横向列表*/
public loadTipsHorizontal: string | Resource = $r("app.string.h_zr_loading")
/*加载成功tips*/
public loadSuccessTips: string | Resource = $r("app.string.zr_load_success")
/*加载成功tips——横向列表*/
public loadSuccessTipsHorizontal: string | Resource = $r("app.string.h_zr_load_success")
/*加载失败tips*/
public loadErrorTips: string | Resource = $r("app.string.zr_load_error")
/*加载失败tips——横向列表*/
public loadErrorTipsHorizontal: string | Resource = $r("app.string.h_zr_load_error")
/*下拉打开其他页面tips*/
public loadOpenPageTips: string | Resource = $r("app.string.zr_release_to_open_age")
}

View File

@ -0,0 +1,806 @@
import { PullDown } from './PullDown';
import { PullStatus } from './PullStatus';
import { RefreshController } from './RefreshController';
import { RefreshLayout } from './RefreshLayout';
import { RefreshLayoutConfig } from './RefreshLayoutConfig';
import { _ContentView } from './RefreshLayoutHelper';
import web from '@ohos.web.webview';
import preferences from '@ohos.data.preferences';
import { PullToRefreshConfig } from './PullToRefreshConfig';
@ComponentV2
export struct PullToRefreshLayout {
/*下拉箭头旋转角度*/
@Local arrowRotate: number = 0;
/*上拉箭头旋转角度*/
@Local arrowRotateLoad: number = 180;
@Local status: PullStatus = PullStatus.DEF
/********************************************************************************************************/
@Param public pullConfig: PullToRefreshConfig = new PullToRefreshConfig()
/*记录组件刷新时间*/
@Param public viewKey: string = ""
@Param public scroller: Scroller | undefined = undefined
@Param public webviewController: web.WebviewController | undefined = undefined
@Param public controller: RefreshController = new RefreshController()
/*是否可以下拉*/
@Param public onCanPullRefresh: () => boolean = () => true
/*是否可以下拉*/
@Param public onCanPullLoad: () => boolean = () => false
/*刷新通知*/
@Param public onRefresh: () => void = () => {
}
/*刷新通知*/
@Param public onLoad: () => void = () => {
}
/*打开页面通知*/
@Param public onOpenPage: () => void = () => {
}
/*打开页面通知*/
@Param public onLoadOpenPage: () => void = () => {
}
/*下拉状态监听*/
@Param public onPullListener: (pullDown: PullDown) => void = () => {
}
//内容视图
@BuilderParam contentView: () => void = _ContentView
//loading视图
@BuilderParam headerLoadIngView?: () => void
//loading视图
@BuilderParam footerLoadIngView?: () => void
/*下拉刷新配置*/
@Param public config: RefreshLayoutConfig = new RefreshLayoutConfig()
//正在加载视图
@BuilderParam viewLoading?: () => void
//空视图
@BuilderParam viewEmpty?: () => void
//加载错误视图
@BuilderParam viewError?: () => void
//无网络视图
@BuilderParam viewNoNetwork?: () => void
/********************************************************************************************************/
aboutToAppear(): void {
this.resetArrowRotate()
this.resetArrowRotateLoad()
}
/*************垂直列表和水平列表feader视图箭头角度**************/
private isPullRotate(): boolean {
if (this.isVerticalLayout()) {
return this.arrowRotate == 0
} else {
return this.arrowRotate == -90
}
}
private isPreRefreshRotate(): boolean {
if (this.isVerticalLayout()) {
return this.arrowRotate == 180
} else {
return this.arrowRotate == 90
}
}
private setPreRefreshRotate() {
if (this.isVerticalLayout()) {
this.arrowRotate = 180
} else {
this.arrowRotate = 90
}
}
private resetArrowRotate() {
if (this.isVerticalLayout()) {
this.arrowRotate = 0
} else {
this.arrowRotate = -90
}
}
/*************垂直列表和水平列表footer视图箭头角度**************/
private isPullLoadRotate(): boolean {
if (this.isVerticalLayout()) {
return this.arrowRotateLoad == 180
} else {
return this.arrowRotateLoad == 90
}
}
private isPreLoadRotate(): boolean {
if (this.isVerticalLayout()) {
return this.arrowRotateLoad == 0
} else {
return this.arrowRotateLoad == -90
}
}
private setPreLoadRotate() {
if (this.isVerticalLayout()) {
this.arrowRotateLoad = 180
} else {
this.arrowRotateLoad = 90
}
}
private resetArrowRotateLoad() {
if (this.isVerticalLayout()) {
this.arrowRotateLoad = 0
} else {
this.arrowRotateLoad = -90
}
}
build() {
RefreshLayout({
scroller: this.scroller,
webviewController: this.webviewController,
controller: this.controller,
config: this.config,
headerView: () => {
if (this.isVerticalLayout()) {
this.defHeaderView()
} else {
this.defHeaderViewHorizontal()
}
},
onCanPullRefresh: () => {
return this.onCanPullRefresh()
},
onCanPullLoad: () => {
return this.onCanPullLoad()
},
onRefresh: () => {
this.onRefresh()
},
onLoad: () => {
this.onLoad()
},
onOpenPage: () => {
this.onOpenPage()
},
onLoadOpenPage: () => {
this.onLoadOpenPage()
},
contentView: () => {
this.contentView()
},
loadView: () => {
if (this.isVerticalLayout()) {
this.defFooterView()
} else {
this.defFooterViewHorizontal()
}
},
noMoreView: () => {
if (this.isVerticalLayout()) {
this.defFooterNoMoreView()
} else {
this.defFooterNoMoreViewHorizontal()
}
},
onPullListener: (pullDown: PullDown) => {
this.status = pullDown.status
this.updateRefreshTime(this.status)
this.onPullListener?.(pullDown)
if (this.config.pullHeaderHeightRefresh <= pullDown.headerViewSize) {
this.config.pullHeaderHeightRefresh = pullDown.headerViewSize * 1.5
}
if (this.config.pullHeaderHeightOpenPage <= this.config.pullHeaderHeightRefresh) {
this.config.pullHeaderHeightOpenPage = pullDown.headerViewSize * 2.6
}
if (this.config.pullFooterHeightLoad <= pullDown.footerViewSize) {
this.config.pullFooterHeightLoad = pullDown.footerViewSize * 1.1
}
if (this.config.pullFooterHeightOpenPage <= this.config.pullFooterHeightLoad) {
this.config.pullFooterHeightOpenPage = pullDown.footerViewSize * 2.6
}
if (this.status == PullStatus.PullDown) {
if (this.isPullRotate()) {
return
}
/*进入下拉状态*/
animateTo({ duration: 10, curve: Curve.Linear }, () => {
this.resetArrowRotate()
})
} else if (this.status == PullStatus.PreRefresh) {
if (this.isPreRefreshRotate()) {
return
}
/*进入释放刷新状态*/
animateTo({ duration: 150, curve: Curve.Linear }, () => {
this.setPreRefreshRotate()
})
} else if (this.status == PullStatus.PullUp) {
if (this.isPullLoadRotate()) {
return
}
/*进入上拉状态*/
animateTo({ duration: 10, curve: Curve.Linear }, () => {
this.setPreLoadRotate()
})
} else if (this.status == PullStatus.PreLoad) {
if (this.isPreLoadRotate()) {
return
}
/*进入释放加载状态*/
animateTo({ duration: 150, curve: Curve.Linear }, () => {
this.resetArrowRotateLoad()
})
}
},
/*正在加载视图*/
viewLoading: this.viewLoading,
/*空数据视图*/
viewEmpty: this.viewEmpty,
/*加载失败视图*/
viewError: this.viewError,
/*无网络视图*/
viewNoNetwork: this.viewNoNetwork
}).clip(true)
}
private isVerticalLayout(): boolean {
return (this.config.isVertical || this.config.horizontalMode == 1 || this.config.horizontalMode == 2)
}
@Local private zrLastUpdate: string = getContext().resourceManager.getStringByNameSync(("zr_last_update"))
@Builder
defHeaderViewHorizontal() {
RelativeContainer() {
Stack() {
Image(this.pullConfig.arrowImage)
.width(this.pullConfig.arrowImageWidth)
.height(this.pullConfig.arrowImageHeight)
.visibility(this.getPullArrowVisibility())
.fillColor(this.pullConfig.arrowImageColor)
.margin({ top: 5 })
.rotate({
x: 0,
y: 0,
z: 1,
angle: this.arrowRotate
})
if (this.headerLoadIngView) {
Stack() {
this.headerLoadIngView()
}
.visibility(this.getRefreshVisibility())
} else {
LoadingProgress()
.color(this.pullConfig.refreshLoadingColor)
.width(this.pullConfig.refreshLoadingWidth)
.height(this.pullConfig.refreshLoadingHeight)
.visibility(this.getRefreshVisibility())
}
}.alignRules({
top: { anchor: "title", align: VerticalAlign.Bottom },
middle: { anchor: "__container__", align: HorizontalAlign.Center }
}).id("arrow")
Row() {
Text(this.getTips())
.fontSize(this.pullConfig.pullDownTipsSize)
.fontColor(this.pullConfig.pullDownTipsColor)
.textAlign(TextAlign.Center)
Text(this.zrLastUpdate)
.fontSize(this.pullConfig.refreshTimeTipsSize)
.fontColor(this.pullConfig.refreshTimeTipsColor)
.margin({ left: 2 })
.visibility(this.pullConfig.showRefreshTime ? this.getTimeTipsVisibility() : Visibility.None)
.textAlign(TextAlign.Center)
}.id("title").alignRules({
middle: { anchor: "__container__", align: HorizontalAlign.Center },
center: { anchor: "__container__", align: VerticalAlign.Center }
}).alignItems(VerticalAlign.Center)
}.width(50).height("100%")
}
@Builder
defHeaderView() {
RelativeContainer() {
Stack() {
Image(this.pullConfig.arrowImage)
.width(this.pullConfig.arrowImageWidth)
.height(this.pullConfig.arrowImageHeight)
.visibility(this.getPullArrowVisibility())
.fillColor(this.pullConfig.arrowImageColor)
.margin({ right: 10 })
.rotate({
x: 0,
y: 0,
z: 1,
angle: this.arrowRotate
})
if (this.headerLoadIngView) {
Stack() {
this.headerLoadIngView()
}
.visibility(this.getRefreshVisibility())
} else {
LoadingProgress()
.color(this.pullConfig.refreshLoadingColor)
.width(this.pullConfig.refreshLoadingWidth)
.height(this.pullConfig.refreshLoadingHeight)
.visibility(this.getRefreshVisibility())
}
}.alignRules({
right: { anchor: "title", align: HorizontalAlign.Start },
center: { anchor: "__container__", align: VerticalAlign.Center }
}).id("arrow")
Column() {
Text(this.getTips()).fontSize(this.pullConfig.pullDownTipsSize)
.fontColor(this.pullConfig.pullDownTipsColor)
Text(this.zrLastUpdate).fontSize(this.pullConfig.refreshTimeTipsSize)
.fontColor(this.pullConfig.refreshTimeTipsColor).margin({ top: 2 })
.visibility(this.pullConfig.showRefreshTime ? this.getTimeTipsVisibility() : Visibility.None)
}.id("title").alignRules({
middle: { anchor: "__container__", align: HorizontalAlign.Center },
center: { anchor: "__container__", align: VerticalAlign.Center }
}).constraintSize({ minWidth: 80 }).alignItems(HorizontalAlign.Center)
}.height(50).width("100%")
}
@Builder
defFooterViewHorizontal() {
RelativeContainer() {
Stack() {
Image(this.pullConfig.arrowLoadImage)
.width(this.pullConfig.arrowLoadImageWidth)
.height(this.pullConfig.arrowLoadImageHeight)
.visibility(this.getPullUpArrowVisibility())
.fillColor(this.pullConfig.arrowLoadImageColor)
.margin({ top: 5 })
.rotate({
x: 0,
y: 0,
z: 1,
angle: this.arrowRotateLoad
})
if (this.footerLoadIngView) {
Stack() {
this.footerLoadIngView()
}
.visibility(this.getLoadVisibility())
} else {
LoadingProgress()
.color(this.pullConfig.refreshLoadingColor)
.width(this.pullConfig.refreshLoadingWidth)
.height(this.pullConfig.refreshLoadingHeight).visibility(this.getLoadVisibility())
}
}.alignRules({
top: { anchor: "title", align: VerticalAlign.Bottom },
middle: { anchor: "__container__", align: HorizontalAlign.Center }
}).id("arrow")
Row() {
Text(this.getLoadTips())
.fontSize(this.pullConfig.pullUpTipsSize)
.fontColor(this.pullConfig.pullUpTipsColor)
.textAlign(TextAlign.Center)
}.id("title").alignRules({
middle: { anchor: "__container__", align: HorizontalAlign.Center },
center: { anchor: "__container__", align: VerticalAlign.Center }
}).alignItems(VerticalAlign.Center)
}.width(50).height("100%")
}
@Builder
defFooterNoMoreViewHorizontal() {
Text(this.pullConfig.noMoreTipsHorizontal)
.textAlign(TextAlign.Center)
.height("100%")
.width(50)
.fontSize(this.pullConfig.noMoreTipsSize)
.fontColor(this.pullConfig.noMoreTipsColor)
}
@Builder
defFooterView() {
RelativeContainer() {
Stack() {
Image(this.pullConfig.arrowLoadImage)
.width(this.pullConfig.arrowLoadImageWidth)
.height(this.pullConfig.arrowLoadImageHeight)
.visibility(this.getPullUpArrowVisibility())
.fillColor(this.pullConfig.arrowLoadImageColor)
.margin({ right: 10 })
.rotate({
x: 0,
y: 0,
z: 1,
angle: this.arrowRotateLoad
})
if (this.footerLoadIngView) {
Stack() {
this.footerLoadIngView()
}
.visibility(this.getLoadVisibility())
} else {
LoadingProgress()
.color(this.pullConfig.refreshLoadingColor)
.width(this.pullConfig.refreshLoadingWidth)
.height(this.pullConfig.refreshLoadingHeight)
.visibility(this.getLoadVisibility())
}
}.alignRules({
right: { anchor: "title", align: HorizontalAlign.Start },
center: { anchor: "__container__", align: VerticalAlign.Center }
}).id("arrow")
Column() {
Text(this.getLoadTips()).fontSize(this.pullConfig.pullUpTipsSize).fontColor(this.pullConfig.pullUpTipsColor)
}.id("title").alignRules({
middle: { anchor: "__container__", align: HorizontalAlign.Center },
center: { anchor: "__container__", align: VerticalAlign.Center }
}).constraintSize({ minWidth: 80 }).alignItems(HorizontalAlign.Center)
}.height(50).width("100%")
}
@Builder
defFooterNoMoreView() {
Text(this.pullConfig.noMoreTips)
.textAlign(TextAlign.Center)
.height(50)
.width("100%")
.fontSize(this.pullConfig.noMoreTipsSize)
.fontColor(this.pullConfig.noMoreTipsColor)
}
private getTips(): Resource | string {
// todo
if (!this.config.isVertical && this.config.horizontalMode != 1 && this.config.horizontalMode != 2) {
switch (this.status) {
case PullStatus.DEF:
case PullStatus.PullDown:
return this.pullConfig.pullDownTipsHorizontal
case PullStatus.PreRefresh:
return this.pullConfig.releaseRefreshTipsHorizontal
case PullStatus.Refresh:
return this.pullConfig.refreshTipsHorizontal
case PullStatus.PreOpenPage:
case PullStatus.OpenPage:
return this.pullConfig.pullOpenPageTipsHorizontal
case PullStatus.RefreshSuccess:
if (this.controller.getConfig().refreshShowSuccess) {
return this.pullConfig.refreshSuccessTipsHorizontal
} else {
/*如果不显示刷新成功的视图*/
return this.pullConfig.refreshTipsHorizontal
}
case PullStatus.RefreshError:
if (this.controller.getConfig().refreshShowError) {
return this.pullConfig.refreshErrorTipsHorizontal
} else {
/*如果不显示刷新失败的视图*/
return this.pullConfig.refreshTipsHorizontal
}
default:
return this.pullConfig.pullDownTipsHorizontal
}
}
switch (this.status) {
case PullStatus.DEF:
case PullStatus.PullDown:
return this.pullConfig.pullDownTips
case PullStatus.PreRefresh:
return this.pullConfig.releaseRefreshTips
case PullStatus.Refresh:
return this.pullConfig.refreshTips
case PullStatus.PreOpenPage:
case PullStatus.OpenPage:
return this.pullConfig.pullOpenPageTips
case PullStatus.RefreshSuccess:
if (this.controller.getConfig().refreshShowSuccess) {
return this.pullConfig.refreshSuccessTips
} else {
/*如果不显示刷新成功的视图*/
return this.pullConfig.refreshTips
}
case PullStatus.RefreshError:
if (this.controller.getConfig().refreshShowError) {
return this.pullConfig.refreshErrorTips
} else {
/*如果不显示刷新失败的视图*/
return this.pullConfig.refreshTips
}
default:
return this.pullConfig.pullDownTips
}
}
private getLoadTips(): Resource | string {
if (!this.config.isVertical && this.config.horizontalMode != 1 && this.config.horizontalMode != 2) {
switch (this.status) {
case PullStatus.DEF:
case PullStatus.PullUp:
return this.pullConfig.pullUpTipsHorizontal
case PullStatus.PreLoad:
return this.pullConfig.releaseLoadTipsHorizontal
case PullStatus.Load:
return this.pullConfig.loadTipsHorizontal
case PullStatus.PreLoadOpenPage:
case PullStatus.LoadOpenPage:
return this.pullConfig.pullOpenPageTipsHorizontal
case PullStatus.LoadSuccess:
if (this.controller.getConfig().loadShowSuccess) {
return this.pullConfig.loadSuccessTipsHorizontal
} else {
/*如果不显示刷新成功的视图*/
return this.pullConfig.loadTipsHorizontal
}
case PullStatus.LoadError:
if (this.controller.getConfig().loadShowError) {
return this.pullConfig.loadErrorTipsHorizontal
} else {
/*如果不显示刷新失败的视图*/
return this.pullConfig.loadTipsHorizontal
}
default:
return this.pullConfig.pullUpTipsHorizontal
}
}
switch (this.status) {
case PullStatus.DEF:
case PullStatus.PullUp:
return this.pullConfig.pullUpTips
case PullStatus.PreLoad:
return this.pullConfig.releaseLoadTips
case PullStatus.Load:
return this.pullConfig.loadTips
case PullStatus.PreLoadOpenPage:
case PullStatus.LoadOpenPage:
return this.pullConfig.loadOpenPageTips
case PullStatus.LoadSuccess:
if (this.controller.getConfig().loadShowSuccess) {
return this.pullConfig.loadSuccessTips
} else {
/*如果不显示刷新成功的视图*/
return this.pullConfig.loadTips
}
case PullStatus.LoadError:
if (this.controller.getConfig().loadShowError) {
return this.pullConfig.loadErrorTips
} else {
/*如果不显示刷新失败的视图*/
return this.pullConfig.loadTips
}
default:
return this.pullConfig.pullUpTips
}
}
/*下拉箭头显示逻辑*/
private getPullArrowVisibility(): Visibility {
switch (this.status) {
case PullStatus.DEF:
case PullStatus.PullDown:
case PullStatus.PreRefresh:
return Visibility.Visible
}
return Visibility.Hidden
}
private getRefreshVisibility(): Visibility {
switch (this.status) {
case PullStatus.Refresh:
return Visibility.Visible
case PullStatus.RefreshSuccess:
if (this.controller.getConfig().refreshShowSuccess) {
return Visibility.Hidden
} else {
/*如果不显示刷新成功的视图*/
return Visibility.Visible
}
case PullStatus.RefreshError:
if (this.controller.getConfig().refreshShowError) {
return Visibility.Hidden
} else {
/*如果不显示刷新失败的视图*/
return Visibility.Visible
}
}
return Visibility.Hidden
}
private getPullUpArrowVisibility(): Visibility {
switch (this.status) {
case PullStatus.DEF:
case PullStatus.PullUp:
case PullStatus.PreLoad:
return Visibility.Visible
}
return Visibility.Hidden
}
private getLoadVisibility(): Visibility {
switch (this.status) {
case PullStatus.Load:
return Visibility.Visible
case PullStatus.LoadSuccess:
if (this.controller.getConfig().loadShowSuccess) {
return Visibility.Hidden
} else {
/*如果不显示刷新成功的视图*/
return Visibility.Visible
}
case PullStatus.LoadError:
if (this.controller.getConfig().loadShowError) {
return Visibility.Hidden
} else {
/*如果不显示刷新失败的视图*/
return Visibility.Visible
}
}
return Visibility.Hidden
}
private getTimeTipsVisibility(): Visibility {
switch (this.status) {
case PullStatus.Refresh:
case PullStatus.PreOpenPage:
case PullStatus.OpenPage:
case PullStatus.RefreshSuccess:
case PullStatus.RefreshError:
return Visibility.None
}
if (this.getLastRefreshTime() <= 0) {
return Visibility.None
}
return Visibility.Visible
}
private sp: preferences.Preferences | undefined = undefined
private lastRefreshTime: number | undefined = undefined
private getLastRefreshTime(): number {
if (!this.sp) {
this.sp = preferences.getPreferencesSync(getContext(), {
name: "PullToRefreshLayoutTime"
})
}
if (this.lastRefreshTime) {
return this.lastRefreshTime
}
let preTime: number = this.sp.getSync("lastRefreshTimeKey" + this.viewKey, 0) as number
this.lastRefreshTime = preTime
return preTime;
}
private saveRefreshTime() {
if (!this.sp) {
this.sp = preferences.getPreferencesSync(getContext(), {
name: "PullToRefreshLayoutTime"
})
}
this.lastRefreshTime = new Date().getTime()
this.sp.put("lastRefreshTimeKey" + this.viewKey, this.lastRefreshTime)
this.sp.flush()
}
private lineBreak(): string {
if (this.isVerticalLayout()) {
return ""
} else {
return "\n"
}
}
private getLastFormatRefreshTime(): string {
const time = this.getLastRefreshTime();
if (time <= 0) {
return ""
}
const currentTime = new Date().getTime()
const timeIntervalSecond = Math.floor(((currentTime - time) / 1000))
let timeFormat: string = ""
if (!this.zr_last_update) {
if (this.isVerticalLayout()) {
this.zr_last_update = getContext().resourceManager.getStringByNameSync(("zr_last_update"))
} else {
this.zr_last_update = "\n" + getContext().resourceManager.getStringByNameSync(("h_zr_last_update"))
}
}
timeFormat = timeFormat + this.zr_last_update
if (timeIntervalSecond < 60) {
timeFormat = timeFormat + this.lineBreak() + timeIntervalSecond;
if (!this.zr_seconds_ago) {
if (this.isVerticalLayout()) {
this.zr_seconds_ago = getContext().resourceManager.getStringByNameSync(("zr_seconds_ago"))
} else {
this.zr_seconds_ago = "\n" + getContext().resourceManager.getStringByNameSync(("h_zr_seconds_ago"))
}
}
timeFormat = timeFormat + this.zr_seconds_ago
} else if (timeIntervalSecond < 3600) {
/*小于一小时*/
timeFormat = timeFormat + this.lineBreak() + Math.floor((timeIntervalSecond / 60));
if (!this.zr_minutes_ago) {
if (this.isVerticalLayout()) {
this.zr_minutes_ago = getContext().resourceManager.getStringByNameSync(("zr_minutes_ago"))
} else {
this.zr_minutes_ago = "\n" + getContext().resourceManager.getStringByNameSync(("h_zr_minutes_ago"))
}
}
timeFormat = timeFormat + this.zr_minutes_ago
} else if (timeIntervalSecond < 86400) {
/*小于一天*/
timeFormat = timeFormat + this.lineBreak() + Math.floor((timeIntervalSecond / 3600));
if (!this.zr_hours_ago) {
if (this.isVerticalLayout()) {
this.zr_hours_ago = getContext().resourceManager.getStringByNameSync(("zr_hours_ago"))
} else {
this.zr_hours_ago = "\n" + getContext().resourceManager.getStringByNameSync(("h_zr_hours_ago"))
}
}
timeFormat = timeFormat + this.zr_hours_ago
} else {
/*大于一天*/
timeFormat = timeFormat + this.lineBreak() + Math.floor((timeIntervalSecond / 86400));
if (!this.zr_days_ago) {
if (this.isVerticalLayout()) {
this.zr_days_ago = getContext().resourceManager.getStringByNameSync(("zr_days_ago"))
} else {
this.zr_days_ago = "\n" + getContext().resourceManager.getStringByNameSync(("h_zr_days_ago"))
}
}
timeFormat = timeFormat + this.zr_days_ago
}
return timeFormat
}
private zr_last_update: string | undefined = undefined
private zr_seconds_ago: string | undefined = undefined
private zr_minutes_ago: string | undefined = undefined
private zr_hours_ago: string | undefined = undefined
private zr_days_ago: string | undefined = undefined
private isUpdateTime = false;
private updateRefreshTime(status: PullStatus) {
if (status == PullStatus.RefreshSuccess) {
this.saveRefreshTime()
}
if (status == PullStatus.PullDown || status == PullStatus.PreRefresh) {
if (this.isUpdateTime) {
return;
}
this.isUpdateTime = true
setTimeout(() => {
this.zrLastUpdate = this.getLastFormatRefreshTime()
this.startUpdateTime();
})
} else {
this.stopUpdateTime();
}
}
private startUpdateTime() {
if (!this.isUpdateTime) {
return
}
setTimeout(() => {
this.zrLastUpdate = this.getLastFormatRefreshTime()
// console.log(this.zrLastUpdate + "=======startUpdateTime=====" + (1000 - new Date().getTime() % 1000));
this.startUpdateTime();
}, 1000 - new Date().getTime() % 1000)
}
private stopUpdateTime() {
this.isUpdateTime = false
}
}

View File

@ -0,0 +1,80 @@
import { PullStatus } from './PullStatus'
import { RefreshLayoutConfig } from './RefreshLayoutConfig'
export enum ViewState{
success=0,
loading,
empty,
error,
noNetwork
}
export class RefreshController {
/*刷新成功*/
refreshSuccess: (ignoreViewTips?:boolean) => void = (ignoreViewTips?:boolean) => {
}
/*刷新失败*/
refreshError: () => void = () => {
}
/*刷新完成true:成功false失败*/
refreshComplete: (isSuccess: boolean,ignoreViewTips?:boolean) => void = (isSuccess: boolean,ignoreViewTips?:boolean) => {
}
/*取消刷新*/
refreshCancel: () => void = () => {
}
/*加载成功*/
loadSuccess: (hasMore?: boolean) => void = (hasMore?: boolean) => {
}
/*加载失败*/
loadError: () => void = () => {
}
/*加载完成true:成功false失败*/
loadComplete: (isSuccess: boolean, hasMore?: boolean) => void = (isSuccess: boolean, hasMore?: boolean) => {
}
/*取消加载*/
loadCancel: () => void = () => {
}
/*显示加载中*/
viewLoading: () => void = () => {
this.viewState=ViewState.loading
}
/*显示空布局*/
viewEmpty: () => void = () => {
this.viewState=ViewState.empty
}
/*显示加载失败布局*/
viewError: () => void = () => {
this.viewState=ViewState.error
}
/*显示无网络布局*/
viewNoNetwork: () => void = () => {
this.viewState=ViewState.noNetwork
}
/**/
/*获取当前状态*/
getStatus: () => PullStatus = () => PullStatus.DEF
/*设置是否还有更多数据*/
hasMore: (hasMore: boolean) => void = (hasMore: boolean) => {
}
/*手动触发下拉刷新*/
refresh: () => void = () => {
}
/*手动触发上拉*/
load: () => void = () => {
}
/*下拉刷新开关是否打开*/
refreshIsEnable: () => boolean = () => true
/*下拉刷新开关是否打开*/
loadIsEnable: () => boolean = () => false
/*设置配置*/
/*由于v2装饰器@Param限制原因setConfig方法在v2版本上不提供*/
/*@Param装饰的变量在子组件中无法进行修改。但当装饰的变量类型为对象时在子组件中修改对象中属性是允许的。*/
// setConfig: (config: RefreshLayoutConfig) => void = () => {}
/*获取配置*/
getConfig: () => RefreshLayoutConfig = () => new RefreshLayoutConfig()
/*webview专用*/
onWebviewScroll: (xOffset: number, yOffset: number) => void = (xOffset: number, yOffset: number) => {
}
private viewState:ViewState=ViewState.success
public getViewState():ViewState{
return this.viewState
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
export class RefreshLayoutConfig {
/*是否是垂直列表*/
public isVertical: boolean = true
/*横向模式0正常横向布局1header和footer逆时针旋转90度2header和footer顺时针旋转90度*/
public horizontalMode: number = 0
/*是否打开刷新*/
public pullRefreshEnable: boolean = true
/*是否打开加载更多*/
public pullLoadEnable: boolean = true
/*******************************刷新配置*******************************************/
/*true:释放刷新false下拉到一定距离刷新*/
public releaseRefresh: boolean = true
/*下拉最大距离*/
public pullMaxDistance: number = 500
/*下拉阻力*/
public pullRefreshResistance: number = 0.5
/*下拉距离超过多少时达到刷新条件*/
public pullHeaderHeightRefresh: number = 0
/*下拉打开其他页面开关*/
public pullRefreshOpenPageEnable: boolean = false
/*下拉距离超过多少时达到打开其他页面条件*/
public pullHeaderHeightOpenPage: number = 0
/*释放刷新时回弹至headerView高度的时间*/
public durationToHeader: number = 250
/*头布局刷新结束时回弹的时间*/
public durationCloseHeader: number = 200
/*需要打开其他页面时,头布局的回弹时间*/
public durationCloseForOpenPage: number = 180
/*刷新时是否显示头view*/
public refreshKeepHeader: boolean = true
/*是否显示刷新成功状态的view*/
public refreshShowSuccess: boolean = true;
/*是否显示刷新失败状态的view*/
public refreshShowError: boolean = true;
/*刷新结果view显示持续时间*/
public refreshResultDurationTime: number = 600
/*******************************加载更多配置*******************************************/
/*true:释放加载false下拉到一定距离加载*/
public releaseLoad: boolean = true
/*上拉最大距离*/
public pullLoadMaxDistance: number = 500
/*上拉阻力*/
public pullLoadResistance: number = 0.5
/*上拉距离超过多少时达到刷新条件*/
public pullFooterHeightLoad: number = 0
/*上拉打开其他页面开关*/
public pullLoadOpenPageEnable: boolean = false
/*上拉距离超过多少时达到打开其他页面条件*/
public pullFooterHeightOpenPage: number = 0
/*释放刷新时回弹至footerView高度的时间*/
public durationToFooter: number = 250
/*footer布局刷新结束时回弹的时间*/
public durationCloseFooter: number = 200
/*需要打开其他页面时,头布局的回弹时间*/
public durationCloseLoadForOpenPage: number = 180
/*刷新时是否显示footerView*/
public loadKeepFooter: boolean = true
/*是否显示刷新成功状态的view*/
public loadShowSuccess: boolean = true;
/*是否显示刷新失败状态的view*/
public loadShowError: boolean = true;
/*刷新结果view显示持续时间*/
public loadResultDurationTime: number = 600
}

View File

@ -0,0 +1,67 @@
import { AnimatorOptions } from '@kit.ArkUI';
@Builder
export function _headerView() {
Text("headerView:()=>{your @Builder View}")
}
@Builder
export function _ContentView() {
Text("contentView:()=>{your @Builder View}")
}
@Builder
export function _loadMoreView() {
Text("loadView:()=>{your @Builder View}")
}
@Builder
export function _noMoreView() {
Text("noMoreView:()=>{your @Builder View}")
}
export class RefreshLayoutHelper {
private log(str: string, tag: string = "RefreshLayout") {
console.debug(tag + "==" + str)
}
/*记录列表滑动到底部的偏移量*/
public scrollerOffset: number = 0;
/*下拉刷新*/
public preOffset: number = 0;
public totalOffset: number = 0;
/*上拉加载*/
// public preOffsetLoad: number = 0;
public totalOffsetLoad: number = 0;
public headerSize: number = 0;
public footerSize: number = 0;
public isPressDown: boolean = false
public options: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Down | PanDirection.Up })
/*不是释放刷新*/
public notReleaseRefresh: boolean = false
/*不是释放加载*/
public notReleaseLoad: boolean = false
public animOptions: AnimatorOptions = {
duration: 250,
easing: "fast-out-linear-in",
delay: 0,
fill: "forwards",
direction: "normal",
iterations: 1,
begin: 0,
end: 1
}
public animLoadOptions: AnimatorOptions = {
duration: 250,
easing: "fast-out-linear-in",
delay: 0,
fill: "forwards",
direction: "normal",
iterations: 1,
begin: 0,
end: 1
}
/*webview滑动偏移量*/
public webViewXOffset: number = 0
public webViewYOffset: number = 0
}

View File

@ -0,0 +1,11 @@
{
"module": {
"name": "refreshlib",
"type": "har",
"deviceTypes": [
"default",
"tablet",
"2in1"
]
}
}

View File

@ -0,0 +1,72 @@
{
"string": [
{
"name": "zr_pull_down_to_refresh",
"value": "下拉刷新"
},
{
"name": "zr_release_to_refresh",
"value": "释放立即刷新"
},
{
"name": "zr_release_to_open_age",
"value": "释放打开其他页面"
},
{
"name": "zr_refreshing",
"value": "正在刷新..."
},
{
"name": "zr_refresh_success",
"value": "刷新完成"
},
{
"name": "zr_refresh_error",
"value": "刷新失败"
},
{
"name": "zr_last_update",
"value": "上次更新:"
},
{
"name": "zr_seconds_ago",
"value": " 秒之前"
},
{
"name": "zr_minutes_ago",
"value": " 分钟之前"
},
{
"name": "zr_hours_ago",
"value": " 小时之前"
},
{
"name": "zr_days_ago",
"value": " 天之前"
},
{
"name": "zr_pull_up_to_load",
"value": "上拉加载"
},
{
"name": "zr_release_to_load",
"value": "释放立即加载"
},
{
"name": "zr_loading",
"value": "正在加载..."
},
{
"name": "zr_load_success",
"value": "加载完成"
},
{
"name": "zr_load_error",
"value": "加载失败"
},
{
"name": "zr_load_no_more",
"value": "暂无更多"
}
]
}

View File

@ -0,0 +1,72 @@
{
"string": [
{
"name": "h_zr_pull_down_to_refresh",
"value": "右\n拉\n刷\n新"
},
{
"name": "h_zr_release_to_refresh",
"value": "释\n放\n立\n即\n刷\n新"
},
{
"name": "h_zr_release_to_open_age",
"value": "释\n放\n打\n开\n其\n他\n页\n面"
},
{
"name": "h_zr_refreshing",
"value": "正\n在\n刷\n新\n..."
},
{
"name": "h_zr_refresh_success",
"value": "刷\n新\n完\n成"
},
{
"name": "h_zr_refresh_error",
"value": "刷\n新\n失\n败"
},
{
"name": "h_zr_last_update",
"value": "上\n次\n更\n新"
},
{
"name": "h_zr_seconds_ago",
"value": "秒\n之\n前"
},
{
"name": "h_zr_minutes_ago",
"value": "分\n钟\n之\n前"
},
{
"name": "h_zr_hours_ago",
"value": "小\n时\n之\n前"
},
{
"name": "h_zr_days_ago",
"value": "天\n之\n前"
},
{
"name": "h_zr_pull_up_to_load",
"value": "左\n拉\n加\n载"
},
{
"name": "h_zr_release_to_load",
"value": "释\n放\n立\n即\n加\n载"
},
{
"name": "h_zr_loading",
"value": "正\n在\n加\n载\n..."
},
{
"name": "h_zr_load_success",
"value": "加\n载\n完\n成"
},
{
"name": "h_zr_load_error",
"value": "加\n载\n失\n败"
},
{
"name": "h_zr_load_no_more",
"value": "暂\n无\n更\n多"
}
]
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="0"
width="64" height="64" >
<path d="M641.774 783.11L382.209 783.11c-26.078 0-47.1785-21.1016-47.1785-47.1785l23.5877-330.373c0-26.078 21.1016-47.1785 47.1795-47.1785L618.183 358.38c26.077 0 47.2205 21.1006 47.2205 47.1785l23.5877 330.373c0 26.077-21.1415 47.1784-47.2184 47.1785Zm-35.3631-471.951L417.61299999 311.159c-19.5678 0-35.4043-15.8357-35.40429999-35.4043L382.208 252.166c0-19.52679999 15.8357-35.40540001 35.4043-35.4054l188.798 0c19.52679999 0 35.3634 15.8796 35.3634 35.4054l0 23.5894c-0.00106066 19.5677-15.8377 35.4034-35.3644 35.4033Zm-11.8155-141.57700001L429.386 169.582c-13.0165 0-23.5882-10.5708-23.5882-23.5882l0-23.6322c0-13.0165 10.5718-23.58820001 23.5882-23.5882l165.208 0c13.0185 0 23.58820001 10.5718 23.5882 23.5882l0 23.63219999c0.00101823 13.0185-10.5697 23.5882-23.5872 23.58820001ZM571.00600001 51.596L453.018 51.596c-13.0594 0-23.6312-10.5728-23.6312-23.5903 0-13.05739999 10.5718-23.62919999 23.6312-23.6292l117.988 0c13.0165 0 23.58820001 10.5718 23.5882 23.6292 0.0010253 13.0165-10.5708 23.5903-23.58819999 23.5903Zm284.687 626.294L537.508 1008.759c-6.92267 7.21328-15.5041 10.8614-25.4967 10.8614-10.03150001 0-18.572-3.64811-25.5366-10.8614L168.29 677.89c-10.0744-10.4868-12.7299-25.0393-7.04851-38.4303 5.68037-13.349 18.0337-21.515 32.5851-21.51499999l636.372-1e-8c14.5504 0 26.8628 8.16701 32.5442 21.515 5.72027 13.39 3.02493001 27.9434-7.04957 38.4303Z"
fill="#333333"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,8 @@
{
"string": [
{
"name": "page_show",
"value": "page from package"
}
]
}

View File

@ -0,0 +1,8 @@
{
"string": [
{
"name": "page_show",
"value": "page from package"
}
]
}

View File

@ -0,0 +1,35 @@
import { hilog } from '@kit.PerformanceAnalysisKit';
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function abilityTest() {
describe('ActsAbilityTest', () => {
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
beforeAll(() => {
// Presets an action, which is performed only once before all test cases of the test suite start.
// This API supports only one parameter: preset action function.
})
beforeEach(() => {
// Presets an action, which is performed before each unit test case starts.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: preset action function.
})
afterEach(() => {
// Presets a clear action, which is performed after each unit test case ends.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: clear action function.
})
afterAll(() => {
// Presets a clear action, which is performed after all test cases of the test suite end.
// This API supports only one parameter: clear action function.
})
it('assertContain', 0, () => {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
let a = 'abc';
let b = 'b';
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
expect(a).assertContain(b);
expect(a).assertEqual(a);
})
})
}

View File

@ -0,0 +1,5 @@
import abilityTest from './Ability.test';
export default function testsuite() {
abilityTest();
}

View File

@ -0,0 +1,13 @@
{
"module": {
"name": "refreshlib",
"type": "feature",
"deviceTypes": [
"default",
"tablet",
"2in1"
],
"deliveryWithInstall": true,
"installationFree": false
}
}

View File

@ -0,0 +1,5 @@
import localUnitTest from './LocalUnit.test';
export default function testsuite() {
localUnitTest();
}

View File

@ -0,0 +1,33 @@
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function localUnitTest() {
describe('localUnitTest', () => {
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
beforeAll(() => {
// Presets an action, which is performed only once before all test cases of the test suite start.
// This API supports only one parameter: preset action function.
});
beforeEach(() => {
// Presets an action, which is performed before each unit test case starts.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: preset action function.
});
afterEach(() => {
// Presets a clear action, which is performed after each unit test case ends.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: clear action function.
});
afterAll(() => {
// Presets a clear action, which is performed after all test cases of the test suite end.
// This API supports only one parameter: clear action function.
});
it('assertContain', 0, () => {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
let a = 'abc';
let b = 'b';
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
expect(a).assertContain(b);
expect(a).assertEqual(a);
});
});
}

View File

@ -77,6 +77,14 @@
"name": "scene_single_video",
"srcPath": "./scene_single_video"
},
{
"name": "patient",
"srcPath": "./features/patient",
},
{
"name": "refreshlib",
"srcPath": "./RefreshLib"
},
{
"name": "corekit",
"srcPath": "./corekit"

View File

@ -26,7 +26,7 @@ export { DataWebModel,DataWebModels } from './src/main/ets/models/DataWebModel'
export { PromptActionClass } from './src/main/ets/components/PromptActionClass'
export { RequestDefaultModel,ExpertData } from './src/main/ets/models/RequestDefaultModel'
export { RequestDefaultModel,ExpertData} from './src/main/ets/models/RequestDefaultModel'
export { HdList, HdListController } from './src/main/ets/components/HdList'
@ -56,8 +56,23 @@ export { huanzheDb } from './src/main/ets/utils/HuanzhelasDbHelper'
export { HdSearchNav } from './src/main/ets/components/HdSearchNav'
export { HdHomeNav } from './src/main/ets/components/HdHomeNav'
export { DefaultHintProWindows } from './src/main/ets/Views/DefaultHintProWindows'
export { TimestampUtil } from './src/main/ets/utils/TimestampUtil'
export { SignPopWindow } from './src/main/ets/Views/SignPopWindow'
// 患者数据库管理相关导出
export {
patientDbManager,
PatientDatabaseManager,
PatientEntity,
PatientDao,
PatientData
} from './src/main/ets/utils/PatientsEntity'
export { PermissionsUtils } from './src/main/ets/utils/PermissionsUtils'
export { calculateExactAge } from './src/main/ets/utils/DateUtils'

View File

@ -0,0 +1,75 @@
import { router } from '@kit.ArkUI'
import { BasicConstant } from '../../../../Index';
@CustomDialog
export struct SignPopWindow {
controller: CustomDialogController;
@Prop signDay:string = '今天是我们相识的第1天';
@Prop signWeek:string = '1';
@Prop signMouth:string = '1';
@Prop signNews:string = '卫健委:鼓励医务人员做兼职!可以做哪些兼职,有哪些法律分险?';
@Prop signHtml:string = '';
build() {
Column(){
Image($r('app.media.sign_popwindow_close'))
.margin({right:10}).width(20).height(70)
.onClick(()=>{
this.controller.close()
})
Stack(){
Column(){
Text('签到成功')
.textAlign(TextAlign.Center)
.fontSize(21).fontColor(Color.White).backgroundColor('rgb(255, 210,3)').height(50).width('100%')
.borderRadius({topLeft:8,topRight:8})
Text(this.signDay)
.textAlign(TextAlign.Center)
.fontSize(16).fontColor(Color.Black).height(18).width('100%').margin({top:15})
Row(){
Text('本周共签到')
.fontSize(14).fontColor('#333333')
Text(this.signWeek)
.fontSize(20).fontColor(Color.Red)
Text('次')
.fontSize(14).fontColor('#333333')
}.width('100%').justifyContent(FlexAlign.Center).height(20).margin({top:15,bottom:3}).alignItems(VerticalAlign.Bottom)
Row(){
Text('已连续签到')
.fontSize(14).fontColor('#333333')
Text(this.signMouth)
.fontSize(20).fontColor(Color.Red)
Text('天')
.fontSize(14).fontColor('#333333')
}.width('100%').justifyContent(FlexAlign.Center).height(20).alignItems(VerticalAlign.Bottom)
Text('连续签到获得更多积分')
.textAlign(TextAlign.Center)
.fontSize(14).fontColor(Color.Red).margin({top:15,bottom:10})
}.width('90%').backgroundColor(Color.White).borderRadius(8).margin({top:30})
Row(){
Image($r('app.media.sign_back_leftright_icon')).width(18).height(18)
Blank()
.width('50%').height(18)
Image($r('app.media.sign_back_leftright_icon')).width(18).height(18)
}.margin({top:20})
Column(){
Image($r('app.media.sign_back_news_icon'))
.width(36).height(36)
Text(this.signNews)
.width('100%')
.fontSize(16).fontColor(Color.Black)
.backgroundColor(Color.White).borderRadius(8).padding({left:10,top:10,right:10,bottom:10}).margin({top:5})
}.width('90%').margin({top:215,bottom:15})
.onClick(()=>{
this.controller.close();
router.pushUrl({
url: 'pages/WebView/WebPage',
params: {'title':this.signNews,'url':BasicConstant.urlHtml+this.signHtml}
})
})
}.width('100%').backgroundColor('rgb(255, 161, 24)').borderRadius(8).alignContent(Alignment.Top)
}.width('100%').alignItems(HorizontalAlign.End)
}
}

View File

@ -0,0 +1,59 @@
import { ChangeUtil } from "../../../../Index";
@Component
export struct HdHomeNav {
@StorageProp('topHeight')
topHeight: number = 0
@Prop
bgColor: ResourceStr = $r('app.color.top_bg')
@Prop
hasBorder: boolean = false
@Prop
leftIcon: ResourceStr = $r('app.media.home_no_qiandao_icon')
@Prop
isFocus:boolean = false;
@Prop
placeholder:string = ''
@State textInputContent:string = ''
@Prop alpha: number = 0; // 接收透明度值
@Prop backColor: string = ''
private leftItemAction: () => void = () => {};
// 添加左侧点击函数
private searchItemAction:()=> void = () => {};
build() {
Row() {
Row() {
Image(this.leftIcon)
.size({ width: 24, height: 24 })
.fillColor($r('app.color.black'))
}.size({ width: 40, height: 50 })
.onClick(()=>this.leftItemAction())
Row(){
Image($r('app.media.selected_hospital_ws'))
.width(20).height(20)
.margin({left:10})
Text(this.placeholder)
.defaultFocus(this.isFocus)
.fontSize(15)
.fontColor(Color.Gray)
.backgroundColor(Color.White)
.height('100%').width('calc(100% - 40vp)')
.padding({ left: 0 })
.margin({left:5})
}
.backgroundColor(Color.White)
.borderWidth(0.5).borderRadius(5).borderColor($r('app.color.common_main_color')).justifyContent(FlexAlign.Start)
.width('calc(100% - 40vp)').height(40)
.onClick(()=>{
this.searchItemAction();
})
}
.padding({ left: 16, right: 16, top: this.topHeight })
.height(56 + this.topHeight)
.width('100%')
.backgroundColor(ChangeUtil.hexToRgba(this.backColor,this.alpha))
}
}

View File

@ -29,13 +29,20 @@ export struct HdNav {
showRightText: boolean = false
@Prop
rightText: string = ''
@Prop
rightBackColor:ResourceColor = this.bgColor
@Prop
rightTextColor:ResourceColor = this.textColor
@BuilderParam
titleBuilder: () => void = defaultBuilder
@BuilderParam
menuBuilder: () => void = defaultBuilder
@Prop
isLeftAction: boolean = false
// 添加右侧点击函数
private rightItemAction:()=> void = () => {};
// 添加左侧点击函数
private leftItemAction:()=> void = () => {};
build() {
Row() {
@ -44,7 +51,7 @@ export struct HdNav {
{
Image(this.leftIcon)
.size({ width: 24, height: 24 })
.onClick(() => router.back())
.onClick(() => this.isLeftAction? this.leftItemAction():router.back())
.fillColor($r('app.color.black'))
}
.size({ width: 50, height: 50 })
@ -84,11 +91,16 @@ export struct HdNav {
} else if (this.showRightText) {
Text(this.rightText)
.fontSize(16)
.fontColor(this.textColor)
.maxFontSize(16)
.minFontSize(6)
.maxLines(1)
.fontColor(this.rightTextColor)
.onClick(()=>this.rightItemAction())
.width(50)
.textAlign(TextAlign.Center)
.borderRadius(5)
.backgroundColor(this.rightBackColor)
.height(35)
// .margin({right:10})
} else {
Blank()

View File

@ -50,7 +50,6 @@ export struct HdSearchNav {
.fontSize(15)
.backgroundColor(this.bgColor)
.height('100%').width('calc(100% - 40vp)')
.padding({ left: 0 })
.margin({left:5})
.onChange((value:string)=>{
this.textInputContent = value;

View File

@ -24,6 +24,22 @@ export class BasicConstant {
// static readonly polvId = "21";//保利威视学员id
static readonly addBonusPoints = BasicConstant.urlExpertApp+'addBonusPoints'
static readonly indexV2 = BasicConstant.urlExpertAPI+'indexV2';//首页轮播
static readonly applyList = BasicConstant.urlExpert+'applyList'
static readonly groupList = BasicConstant.urlExpertApp+'groupList'
static readonly isMaiLanExpert = BasicConstant.urlExpertAPI+'isMaiLanExpert'
static readonly patientListByGroup = BasicConstant.urlExpertApp+'patientListByGroup'
static readonly deleteGroup = BasicConstant.urlExpertApp+'deleteGroup'
static readonly addGroup = BasicConstant.urlExpertApp+'addGroup'
static readonly updateGroup = BasicConstant.urlExpertApp+'updateGroup'
static readonly relationRecordLately = BasicConstant.urlExpertAPI+'relationRecordLately'
static readonly updateNicknameNote = BasicConstant.urlExpertAPI+'updateNicknameNote'
static readonly applyListOperate = BasicConstant.urlExpert+'applyListOperate'
static readonly patientListNoInThisGroup = BasicConstant.urlExpertAPI+'patientListNoInThisGroup'
static readonly patientCard = BasicConstant.urlExpertAPI+'patientCard'
static readonly toAddNickname = BasicConstant.urlExpert+'toAddNickname'
static readonly patientDetail = BasicConstant.urlExpert+'patientDetail'
static readonly getStartpage=BasicConstant.urlExpertApp + "startpage";
static readonly meetingListV2=BasicConstant.urlExpertAPI + "meetingListV2";
static readonly meetingV2Video=BasicConstant.urlExpertAPI + "meetingV2Video";
@ -53,7 +69,6 @@ export class BasicConstant {
static readonly listOutPatient = BasicConstant.urlExpertApp+'listOutPatient'//出诊
static readonly urlOutpatientnew = BasicConstant.wxUrl+"wxPatient/index.htm#/outPatient?link=share&expertUuid=";//出诊
static readonly getNewWa="https://wx.igandan.com/shop_notify/";//肝胆商城妞娃购买链接
static readonly patientDetail= BasicConstant.urlExpert + "patientDetail";// 患者详情
static readonly newConsultList = BasicConstant.urlExpertAPI + "newConsultList";// 新的公益咨询列表
static readonly consultListHis = BasicConstant.urlExpertAPI +"consultListHis";// 公益咨询历史列表
static readonly consultDetail = BasicConstant.urlExpertAPI + "consultDetail";// 公益咨询详情

View File

@ -1,4 +1,3 @@
export interface RequestDefaultModel{
code:string;
data:DefaulyData[];

View File

@ -0,0 +1,862 @@
import { Entity, Id, Columns, ColumnType } from '@ohos/dataorm';
import { authStore } from './auth';
import { hdHttp, HdResponse } from '../utils/request';
import { BasicConstant } from '../constants/BasicConstant';
import { BusinessError } from '@kit.BasicServicesKit';
import relationalStore from '@ohos.data.relationalStore';
import common from '@ohos.app.ability.common';
// 患者数据接口
export interface PatientData {
uuid: string;
nickname: string;
mobile: string;
realName: string;
nation: string | null;
sex: number;
type: number;
photo: string;
expertUuid: string; // 关联的专家UUID
}
// 服务器响应接口
interface updateExtraData {
expertUuid: string
}
// 患者实体类
@Entity('patients')
export class PatientEntity {
@Id()
@Columns({ columnName: 'id', types: ColumnType.num })
id: number = 0;
@Columns({ columnName: 'uuid', types: ColumnType.str })
uuid: string = '';
@Columns({ columnName: 'nickname', types: ColumnType.str })
nickname: string = '';
@Columns({ columnName: 'mobile', types: ColumnType.str })
mobile: string = '';
@Columns({ columnName: 'realName', types: ColumnType.str })
realName: string = '';
@Columns({ columnName: 'nation', types: ColumnType.str })
nation: string = '';
@Columns({ columnName: 'sex', types: ColumnType.num })
sex: number = 0;
@Columns({ columnName: 'type', types: ColumnType.num })
type: number = 0;
@Columns({ columnName: 'photo', types: ColumnType.str })
photo: string = '';
@Columns({ columnName: 'expertUuid', types: ColumnType.str })
expertUuid: string = '';
@Columns({ columnName: 'createTime', types: ColumnType.str })
createTime: string = '';
@Columns({ columnName: 'updateTime', types: ColumnType.str })
updateTime: string = '';
constructor(
uuid: string = '',
nickname: string = '',
mobile: string = '',
realName: string = '',
nation: string = '',
sex: number = 0,
type: number = 0,
photo: string = '',
expertUuid: string = ''
) {
this.uuid = uuid;
this.nickname = nickname;
this.mobile = mobile;
this.realName = realName;
this.nation = nation;
this.sex = sex;
this.type = type;
this.photo = photo;
this.expertUuid = expertUuid;
this.createTime = new Date().toISOString();
this.updateTime = new Date().toISOString();
}
}
// 患者DAO类 - 使用原生 relationalStore
export class PatientDao {
private rdbStore: relationalStore.RdbStore | null = null;
private context: common.Context;
private isInitialized: boolean = false;
constructor(context: common.Context) {
this.context = context;
}
// 初始化数据库
async initDatabase(): Promise<void> {
try {
console.info('开始初始化患者数据库...');
const storeConfig: relationalStore.StoreConfig = {
name: 'patient_database',
securityLevel: relationalStore.SecurityLevel.S1
};
this.rdbStore = await relationalStore.getRdbStore(this.context, storeConfig);
console.info('数据库连接创建成功');
// 创建表
await this.createTable();
this.isInitialized = true;
console.info('患者数据库初始化完成');
} catch (error) {
console.error('初始化患者数据库失败:', error);
this.isInitialized = false;
if (error instanceof Error) {
throw error;
} else {
throw new Error('初始化患者数据库失败');
}
}
}
// 创建患者表
private async createTable(): Promise<void> {
if (!this.rdbStore) {
throw new Error('数据库未初始化');
}
try {
const createTableSql = `
CREATE TABLE IF NOT EXISTS patients (
id INTEGER PRIMARY KEY AUTOINCREMENT,
uuid TEXT NOT NULL,
nickname TEXT,
mobile TEXT,
realName TEXT,
nation TEXT,
sex INTEGER DEFAULT 0,
type INTEGER DEFAULT 0,
photo TEXT,
expertUuid TEXT NOT NULL,
createTime TEXT,
updateTime TEXT
)
`;
await this.rdbStore.executeSql(createTableSql);
console.info('患者表创建成功');
// 验证表是否存在
await this.verifyTableExists();
} catch (error) {
console.error('创建患者表失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('创建患者表失败');
}
}
}
// 验证表是否存在
private async verifyTableExists(): Promise<void> {
if (!this.rdbStore) {
throw new Error('数据库未初始化');
}
try {
const checkTableSql = "SELECT name FROM sqlite_master WHERE type='table' AND name='patients'";
const resultSet = await this.rdbStore.querySql(checkTableSql, []);
if (resultSet.rowCount === 0) {
throw new Error('患者表创建失败');
}
resultSet.close();
console.info('患者表验证成功');
} catch (error) {
console.error('验证患者表失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('验证患者表失败');
}
}
}
// 检查数据库状态
private checkDatabaseState(): void {
if (!this.rdbStore) {
throw new Error('数据库未初始化');
}
if (!this.isInitialized) {
throw new Error('数据库初始化未完成');
}
}
// 根据专家UUID查询所有患者
async getPatientsByExpertUuid(expertUuid: string): Promise<PatientEntity[]> {
try {
this.checkDatabaseState();
console.info(`开始查询专家 ${expertUuid} 的患者数据`);
if (!this.rdbStore) {
throw new Error('数据库连接为空');
}
const sql = 'SELECT * FROM patients WHERE expertUuid = ? ORDER BY createTime DESC';
const resultSet = await this.rdbStore.querySql(sql, [expertUuid]);
const patients: PatientEntity[] = [];
if (resultSet.rowCount > 0) {
resultSet.goToFirstRow();
do {
try {
const patient = this.parseResultSet(resultSet);
patients.push(patient);
} catch (parseError) {
console.error('解析患者数据失败:', parseError);
}
} while (resultSet.goToNextRow());
}
resultSet.close();
console.info(`成功查询到 ${patients.length} 个患者`);
return patients;
} catch (error) {
console.error('查询患者数据失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('查询患者数据失败');
}
}
}
// 根据患者UUID查询单个患者
async getPatientByUuid(uuid: string): Promise<PatientEntity | null> {
try {
this.checkDatabaseState();
if (!this.rdbStore) {
throw new Error('数据库连接为空');
}
const sql = 'SELECT * FROM patients WHERE uuid = ?';
const resultSet = await this.rdbStore.querySql(sql, [uuid]);
if (resultSet.rowCount > 0) {
resultSet.goToFirstRow();
const patient = this.parseResultSet(resultSet);
resultSet.close();
return patient;
}
resultSet.close();
return null;
} catch (error) {
console.error('根据UUID查询患者失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('根据UUID查询患者失败');
}
}
}
// 根据手机号查询患者
async getPatientByMobile(mobile: string, expertUuid: string): Promise<PatientEntity | null> {
try {
this.checkDatabaseState();
if (!this.rdbStore) {
throw new Error('数据库连接为空');
}
const sql = 'SELECT * FROM patients WHERE mobile = ? AND expertUuid = ?';
const resultSet = await this.rdbStore.querySql(sql, [mobile, expertUuid]);
if (resultSet.rowCount > 0) {
resultSet.goToFirstRow();
const patient = this.parseResultSet(resultSet);
resultSet.close();
return patient;
}
resultSet.close();
return null;
} catch (error) {
console.error('根据手机号查询患者失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('根据手机号查询患者失败');
}
}
}
// 删除指定专家的所有患者数据
async deletePatientsByExpertUuid(expertUuid: string): Promise<void> {
try {
this.checkDatabaseState();
console.info(`开始删除专家 ${expertUuid} 的所有患者数据`);
if (!this.rdbStore) {
throw new Error('数据库连接为空');
}
const sql = 'DELETE FROM patients WHERE expertUuid = ?';
await this.rdbStore.executeSql(sql, [expertUuid]);
console.info('删除专家患者数据成功');
} catch (error) {
console.error('删除专家患者数据失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('删除专家患者数据失败');
}
}
}
// 删除单个患者
async deletePatientByUuid(uuid: string): Promise<void> {
try {
this.checkDatabaseState();
if (!this.rdbStore) {
throw new Error('数据库连接为空');
}
const sql = 'DELETE FROM patients WHERE uuid = ?';
await this.rdbStore.executeSql(sql, [uuid]);
} catch (error) {
console.error('删除患者失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('删除患者失败');
}
}
}
// 更新患者信息
async updatePatient(patient: PatientEntity): Promise<void> {
try {
this.checkDatabaseState();
if (!this.rdbStore) {
throw new Error('数据库连接为空');
}
patient.updateTime = new Date().toISOString();
const sql = `
UPDATE patients
SET nickname = ?, mobile = ?, realName = ?, nation = ?,
sex = ?, type = ?, photo = ?, updateTime = ?
WHERE uuid = ?
`;
await this.rdbStore.executeSql(sql, [
patient.nickname,
patient.mobile,
patient.realName,
patient.nation,
patient.sex,
patient.type,
patient.photo,
patient.updateTime,
patient.uuid
]);
} catch (error) {
console.error('更新患者信息失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('更新患者信息失败');
}
}
}
// 插入单个患者
async insertPatient(patient: PatientEntity): Promise<void> {
try {
this.checkDatabaseState();
if (!this.rdbStore) {
throw new Error('数据库连接为空');
}
const sql = `
INSERT INTO patients (uuid, nickname, mobile, realName, nation, sex, type, photo, expertUuid, createTime, updateTime)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`;
await this.rdbStore.executeSql(sql, [
patient.uuid,
patient.nickname,
patient.mobile,
patient.realName,
patient.nation,
patient.sex,
patient.type,
patient.photo,
patient.expertUuid,
patient.createTime,
patient.updateTime
]);
} catch (error) {
console.error('插入患者数据失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('插入患者数据失败');
}
}
}
// 批量插入患者数据
async insertPatients(patients: PatientEntity[]): Promise<void> {
try {
this.checkDatabaseState();
console.info(`开始批量插入 ${patients.length} 个患者数据`);
if (!this.rdbStore) {
throw new Error('数据库连接为空');
}
await this.rdbStore.beginTransaction();
try {
for (const patient of patients) {
await this.insertPatient(patient);
}
await this.rdbStore.commit();
console.info('批量插入患者数据成功');
} catch (error) {
await this.rdbStore.rollBack();
console.error('批量插入患者数据失败,已回滚:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('批量插入患者数据失败');
}
}
} catch (error) {
console.error('批量插入患者数据失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('批量插入患者数据失败');
}
}
}
// 解析查询结果
private parseResultSet(resultSet: relationalStore.ResultSet): PatientEntity {
try {
const uuidIndex = resultSet.getColumnIndex('uuid');
const nicknameIndex = resultSet.getColumnIndex('nickname');
const mobileIndex = resultSet.getColumnIndex('mobile');
const realNameIndex = resultSet.getColumnIndex('realName');
const nationIndex = resultSet.getColumnIndex('nation');
const sexIndex = resultSet.getColumnIndex('sex');
const typeIndex = resultSet.getColumnIndex('type');
const photoIndex = resultSet.getColumnIndex('photo');
const expertUuidIndex = resultSet.getColumnIndex('expertUuid');
return new PatientEntity(
uuidIndex >= 0 ? (resultSet.getString(uuidIndex) ?? '') : '',
nicknameIndex >= 0 ? (resultSet.getString(nicknameIndex) ?? '') : '',
mobileIndex >= 0 ? (resultSet.getString(mobileIndex) ?? '') : '',
realNameIndex >= 0 ? (resultSet.getString(realNameIndex) ?? '') : '',
nationIndex >= 0 ? (resultSet.getString(nationIndex) ?? '') : '',
sexIndex >= 0 ? (resultSet.getDouble(sexIndex) ?? 0) : 0,
typeIndex >= 0 ? (resultSet.getDouble(typeIndex) ?? 0) : 0,
photoIndex >= 0 ? (resultSet.getString(photoIndex) ?? '') : '',
expertUuidIndex >= 0 ? (resultSet.getString(expertUuidIndex) ?? '') : ''
);
} catch (error) {
console.error('解析查询结果失败:', error);
if (error instanceof Error) {
throw error;
} else {
throw new Error('解析查询结果失败');
}
}
}
// 关闭数据库连接
async closeDatabase(): Promise<void> {
try {
if (this.rdbStore) {
await this.rdbStore.close();
this.rdbStore = null;
this.isInitialized = false;
console.info('数据库连接已关闭');
}
} catch (error) {
console.error('关闭数据库连接失败:', error);
}
}
// 检查数据库是否已初始化
isDatabaseInitialized(): boolean {
return this.isInitialized && this.rdbStore !== null;
}
// 开始事务
async beginTransaction(): Promise<void> {
this.checkDatabaseState();
if (this.rdbStore) {
await this.rdbStore.beginTransaction();
}
}
// 提交事务
async commitTransaction(): Promise<void> {
this.checkDatabaseState();
if (this.rdbStore) {
await this.rdbStore.commit();
}
}
// 回滚事务
async rollbackTransaction(): Promise<void> {
this.checkDatabaseState();
if (this.rdbStore) {
await this.rdbStore.rollBack();
}
}
}
// 数据库管理类
export class PatientDatabaseManager {
private static instance: PatientDatabaseManager;
private patientDao: PatientDao | null = null;
private context: common.Context | null = null;
private isInitialized: boolean = false;
private constructor() {}
public static getInstance(): PatientDatabaseManager {
if (!PatientDatabaseManager.instance) {
PatientDatabaseManager.instance = new PatientDatabaseManager();
}
return PatientDatabaseManager.instance;
}
// 初始化数据库
async initDatabase(context: common.Context): Promise<void> {
try {
console.info('开始初始化患者数据库管理器...');
this.context = context;
this.patientDao = new PatientDao(context);
await this.patientDao.initDatabase();
this.isInitialized = true;
console.info('患者数据库管理器初始化成功');
} catch (error) {
console.error('初始化患者数据库管理器失败:', error);
this.isInitialized = false;
if (error instanceof Error) {
throw error;
} else {
throw new Error('初始化患者数据库管理器失败');
}
}
}
// 获取PatientDao实例
getPatientDao(): PatientDao {
if (!this.patientDao || !this.isInitialized) {
throw new Error('数据库未初始化。请先调用 initDatabase() 方法。');
}
return this.patientDao;
}
// 检查数据库状态
isDatabaseReady(): boolean {
return this.isInitialized && this.patientDao !== null && this.patientDao.isDatabaseInitialized();
}
// 从服务器获取患者列表并存储到数据库
async patientsToFMDB(): Promise<void> {
try {
if (!this.isDatabaseReady()) {
console.error('数据库未准备好,无法获取患者数据');
return;
}
const expertUuid = authStore.getUser().uuid;
if (!expertUuid) {
console.error('专家UUID未找到');
return;
}
console.info('开始从服务器获取患者数据...');
hdHttp.post<string>(BasicConstant.urlExpert + 'patientList', {
expertUuid: authStore.getUser().uuid
} as updateExtraData).then(async (res: HdResponse<string>) => {
try {
let json: Record<string, string> = JSON.parse(res + '') as Record<string, string>;
console.log('服务器返回的患者数据:', json);
if (json.code == '1' && json.data && Array.isArray(json.data)) {
console.info(`服务器返回 ${json.data.length} 个患者数据`);
for (const item of json.data as PatientData[]) {
const patientEntity = new PatientEntity(
item.uuid || '',
item.nickname || '',
item.mobile || '',
item.realName || '',
item.nation || '',
item.sex || 0,
item.type || 0,
item.photo || '',
expertUuid
);
// 检查本地是否已存在
const localPatient = await this.getPatientDao().getPatientByUuid(item.uuid || '');
if (localPatient) {
// 已存在,更新
await this.getPatientDao().updatePatient(patientEntity);
} else {
// 不存在,插入
await this.getPatientDao().insertPatient(patientEntity);
}
}
} else {
console.error('服务器返回数据格式错误:', json);
}
} catch (parseError) {
console.error('解析服务器响应失败:', parseError);
}
}).catch((err: BusinessError) => {
console.error('请求患者数据失败:', err);
});
} catch (error) {
console.error('获取患者数据过程中发生错误:', error);
}
}
// 获取所有患者数据
async getAllPatients(): Promise<PatientEntity[]> {
try {
if (!this.isDatabaseReady()) {
console.error('数据库未准备好,无法获取患者数据');
return [];
}
const expertUuid = authStore.getUser().uuid;
if (!expertUuid) {
console.error('专家UUID未找到');
return [];
}
console.info('开始获取所有患者数据...');
const patients = await this.getPatientDao().getPatientsByExpertUuid(expertUuid);
console.info(`成功获取 ${patients.length} 个患者数据`);
return patients;
} catch (error) {
console.error('获取所有患者数据失败:', error);
return [];
}
}
// 根据UUID获取单个患者
async getPatientByUuid(uuid: string): Promise<PatientEntity | null> {
try {
if (!this.isDatabaseReady()) {
console.error('数据库未准备好,无法获取患者数据');
return null;
}
return await this.getPatientDao().getPatientByUuid(uuid);
} catch (error) {
console.error('根据UUID获取患者失败:', error);
return null;
}
}
// 根据手机号获取患者
async getPatientByMobile(mobile: string): Promise<PatientEntity | null> {
try {
if (!this.isDatabaseReady()) {
console.error('数据库未准备好,无法获取患者数据');
return null;
}
const expertUuid = authStore.getUser().uuid;
if (!expertUuid) {
console.error('专家UUID未找到');
return null;
}
return await this.getPatientDao().getPatientByMobile(mobile, expertUuid);
} catch (error) {
console.error('根据手机号获取患者失败:', error);
return null;
}
}
// 更新患者信息
async updatePatient(patient: PatientEntity): Promise<boolean> {
try {
if (!this.isDatabaseReady()) {
console.error('数据库未准备好,无法更新患者数据');
return false;
}
await this.getPatientDao().updatePatient(patient);
return true;
} catch (error) {
console.error('更新患者信息失败:', error);
return false;
}
}
// 删除患者
async deletePatient(uuid: string): Promise<boolean> {
try {
if (!this.isDatabaseReady()) {
console.error('数据库未准备好,无法删除患者数据');
return false;
}
await this.getPatientDao().deletePatientByUuid(uuid);
return true;
} catch (error) {
console.error('删除患者失败:', error);
return false;
}
}
// 删除当前专家的所有患者数据
async deleteAllPatients(): Promise<boolean> {
try {
if (!this.isDatabaseReady()) {
console.error('数据库未准备好,无法删除患者数据');
return false;
}
const expertUuid = authStore.getUser().uuid;
if (!expertUuid) {
console.error('专家UUID未找到');
return false;
}
await this.getPatientDao().deletePatientsByExpertUuid(expertUuid);
return true;
} catch (error) {
console.error('删除所有患者失败:', error);
return false;
}
}
// 搜索患者(根据姓名或昵称)
async searchPatients(keyword: string): Promise<PatientEntity[]> {
try {
if (!this.isDatabaseReady()) {
console.error('数据库未准备好,无法搜索患者数据');
return [];
}
const expertUuid = authStore.getUser().uuid;
if (!expertUuid) {
console.error('专家UUID未找到');
return [];
}
const allPatients = await this.getPatientDao().getPatientsByExpertUuid(expertUuid);
return allPatients.filter(patient =>
patient.realName.toLowerCase().includes(keyword.toLowerCase()) ||
patient.nickname.toLowerCase().includes(keyword.toLowerCase())
);
} catch (error) {
console.error('搜索患者失败:', error);
return [];
}
}
// 添加患者信息(支持单个或多个)
async addPatients(patients: PatientData | PatientData[]): Promise<boolean> {
try {
if (!this.isDatabaseReady()) {
console.error('数据库未准备好,无法添加患者数据');
return false;
}
const expertUuid = authStore.getUser().uuid;
if (!expertUuid) {
console.error('专家UUID未找到');
return false;
}
// 将单个患者转换为数组
const patientsArray = Array.isArray(patients) ? patients : [patients];
if (patientsArray.length === 0) {
console.warn('没有患者数据需要添加');
return true;
}
console.info(`开始处理 ${patientsArray.length} 个患者数据...`);
// 批量处理患者数据
const patientDao = this.getPatientDao();
await patientDao.beginTransaction();
try {
for (const patientData of patientsArray) {
// 转换为PatientEntity对象
const patientEntity = new PatientEntity(
patientData.uuid || '',
patientData.nickname || '',
patientData.mobile || '',
patientData.realName || '',
patientData.nation || '',
patientData.sex || 0,
patientData.type || 0,
patientData.photo || '',
expertUuid
);
// 检查患者是否已存在根据UUID
const existingPatient = await patientDao.getPatientByUuid(patientData.uuid || '');
if (existingPatient) {
// 患者已存在,更新信息
console.info(`患者 ${patientData.uuid} 已存在,执行更新操作`);
await patientDao.updatePatient(patientEntity);
} else {
// 患者不存在,插入新记录
console.info(`患者 ${patientData.uuid} 不存在,执行插入操作`);
await patientDao.insertPatient(patientEntity);
}
}
await patientDao.commitTransaction();
console.info(`成功处理 ${patientsArray.length} 个患者数据`);
return true;
} catch (error) {
await patientDao.rollbackTransaction();
console.error('处理患者数据失败,已回滚:', error);
return false;
}
} catch (error) {
console.error('添加患者数据失败:', error);
return false;
}
}
// 添加单个患者信息(便捷方法)
async addPatient(patient: PatientData): Promise<boolean> {
return await this.addPatients(patient);
}
}
// 导出单例实例
export const patientDbManager = PatientDatabaseManager.getInstance();

View File

@ -0,0 +1,50 @@
import { systemDateTime } from '@kit.BasicServicesKit';
export class TimestampUtil {
static format(timestamp: number | string, formatStr: string): string {
const date = new Date(timestamp);
const padZero = (num: number, len: number = 2) => num.toString().padStart(len, '0');
const map: Record<string, string> = {
'YYYY': date.getFullYear().toString(),
'MM': padZero(date.getMonth() + 1),
'DD': padZero(date.getDate()),
'HH': padZero(date.getHours()),
'mm': padZero(date.getMinutes()),
'ss': padZero(date.getSeconds()),
};
let result = formatStr;
Object.keys(map).forEach((key) => {
result = result.replace(new RegExp(key, 'g'), map[key]);
});
return result;
}
static isToday(dateStr: string): boolean {
try {
// 1. 解析目标日期字符串 → Date对象
const targetDate = new Date(dateStr);
// 2. 获取当前系统日期(年、月、日)
const now = new Date(systemDateTime.getTime());
const currentYear = now.getFullYear();
const currentMonth = now.getMonth();
const currentDay = now.getDate();
// 3. 提取目标日期的年、月、日
const targetYear = targetDate.getFullYear();
const targetMonth = targetDate.getMonth();
const targetDay = targetDate.getDate();
// 4. 比较日期是否相同
return (
targetYear === currentYear &&
targetMonth === currentMonth &&
targetDay === currentDay
);
} catch (e) {
console.error("日期解析失败", e);
return false;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 984 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,108 @@
import { FlipperOptions,FlipperView,FlipperOptionsBuilder } from '@hshare/hshare-flipper'
import { promptAction } from '@kit.ArkUI';
import { router } from '@kit.ArkUI'
import { meetingModel } from '../model/HomeModel'
import { TimestampUtil } from '@itcast/basic'
@Component
export struct FlipperComp {
@Prop bankAdBeans: meetingModel[];
@State processedData: meetingModel[] = [];
options: FlipperOptions = FlipperOptionsBuilder.getInstance()
.setHeight(56)//View高度
.setInterval(3000)//上下滚动间隔,单位为毫秒
.setAnimateParam(500)//动画持续时间,单位为毫秒
.setOnItemClicked((item: meetingModel, index: number) => {
router.pushUrl({
url: 'pages/WebView/WebPage', // 目标url
params: {url:item.liveurl,title:item.title}
})
})
.setOnItemScrolled((item: meetingModel, index: number) => {
//滚动事件
})
.build()
aboutToAppear() {
if (this.bankAdBeans.length === 1) {
this.processedData = [...this.bankAdBeans, ...this.bankAdBeans, ...this.bankAdBeans];
} else {
this.processedData = this.bankAdBeans;
}
}
build() {
Column() {
Row() {
FlipperView({
options: this.options,
sourceBeans: this.processedData,
itemContentView: (data: meetingModel, index: number) => {
this.itemContentView(data, index)
}
})
}
}
.width('100%').height('100%').backgroundColor('#F4F4F4')
}
@Builder
itemContentView(item: meetingModel, index: number) {
Stack({alignContent:Alignment.Center}){
Image($r('app.media.meeting_back_icon'))
.width('100%').height(46).margin({top:10})
Row(){
Column() {
Row({space:2}){
Image($r('app.media.meeting_live_icon')).width(30).height(13)
if (item.state === '1') {
if (TimestampUtil.isToday(item.begin_date_timestamp)) {
Image($r('app.media.meeting_begin_play_icon')).width(16).height(16)
} else {
Image($r('app.media.meeting_noPlay_icon')).width(16).height(16)
}
} else if (item.state === '0' || item.state === '3') {
if (TimestampUtil.isToday(item.begin_date_timestamp)) {
Image($r('app.media.meeting_begin_play_icon')).width(16).height(16)
} else {
Image($r('app.media.meeting_noPlay_icon')).width(16).height(16)
}
} else {
Image($r('app.media.meeting_begin_play_icon')).width(16).height(16)
}
}
Stack({alignContent:Alignment.Center}){
Image($r('app.media.meeting_timeBack_icon')).width(74).height(15).margin({top:-3})
if (item.state === '1') {
if (TimestampUtil.isToday(item.begin_date_timestamp)) {
Text('开播'+TimestampUtil.format(item.begin_date_timestamp,'HH:mm'))
.fontSize(12).fontColor(Color.White)
} else {
Text(TimestampUtil.format(item.begin_date_timestamp,'MM月dd日'))
.fontSize(12).fontColor(Color.White)
}
} else if (item.state === '0' || item.state === '3') {
if (TimestampUtil.isToday(item.begin_date_timestamp)) {
Text('开播'+TimestampUtil.format(item.begin_date_timestamp,'HH:mm'))
.fontSize(12).fontColor(Color.White)
} else {
Text(TimestampUtil.format(item.begin_date_timestamp,'MM月dd日'))
.fontSize(12).fontColor(Color.White)
}
} else {
Text('正在直播')
.fontSize(12).fontColor(Color.White)
}
}
}.margin({left:10}).alignItems(HorizontalAlign.Start)
Blank()
.width(1).height(28).margin({left:9}).backgroundColor('#C5C5C5')
Text(item.title)
.fontSize(14)
.fontColor('#333333')
.margin({left:9})
}.margin({top:10}).width('100%').height(46)
}
}
}

View File

@ -0,0 +1,65 @@
import { iconsModel } from '../model/HomeModel'
import { patientDbManager, PatientEntity } from '@itcast/basic';
import { promptAction } from '@kit.ArkUI';
// interface iconsModel {
// img:string;
// name:string;
// isRed:boolean;
// }
@Component
export struct HomeIconComp {
@Prop iconList: iconsModel[];
@State patientIcon: string = '';
@State patientName: string = '我的患者';
@State videoIcon: string = '';
@State videoName: string = '肝胆视频';
aboutToAppear(): void {
for (const icons of this.iconList) {
if (icons.name === '我的患者') {
this.patientIcon = icons.img;
} else if (icons.name === '肝胆视频') {
this.videoIcon = icons.img;
}
}
for (let index = 0; index < this.iconList!.length; index++) {
const iconModel = this.iconList![index] as iconsModel ;
if (index == 0) {
iconModel.isRed = true;
}
}
}
build() {
Row() {
Grid() {
ForEach(this.iconList, (item: iconsModel) => {//[{ 'img': this.patientIcon, 'name': this.patientName },{ 'img': this.videoIcon, 'name': this.videoName}]
GridItem(){
Stack() {
Column() {
Image(item.img)
.width(24).height(24)
.objectFit(ImageFit.Auto)
Text(item.name)
.fontSize(14)
.fontColor('#333333')
.margin({ top: 10 })
}.width('100%')
if (item.isRed) {
Text().backgroundColor(Color.Red).width(10).height(10).borderRadius(5)
}
}.width('25%').alignContent(Alignment.TopEnd)
}.margin({top:20,bottom:20})
.onClick(async ()=>{
const patients = await patientDbManager.getAllPatients();
console.info(`添加了 ${patients.length} 个患者`);
promptAction.showToast({message:`添加了 ${patients.length} 个患者`})
})
})
}.width('100%').backgroundColor(Color.White)
}
}
}

View File

@ -0,0 +1,56 @@
import { videoModel } from '../model/HomeModel'
import { router } from '@kit.ArkUI';
import { BasicConstant } from '@itcast/basic'
import { videoTools } from '../polyv/VideoUtil'
import { getDisplayWindowWidth } from 'media-player-common'
@Component
export struct HomeReplayVideoComp {
@Prop videoList: videoModel[];
@State newVideosList: videoModel[] = this.videoList.slice(0, 4);
build() {
Column() {
Row(){
Text('精彩回放')
.fontSize(17)
.fontWeight(FontWeight.Bold)
.margin({left:15})
Blank()
.layoutWeight(1)
Row(){
Text('更多 ')
.fontSize(15)
.fontColor('#999999')
Image($r('app.media.course_invoice_to_details'))
.width(15).height(15)
}.margin({right:15})
.onClick(()=>{
router.pushUrl({
url:'pages/VideoPage/VideoGandanPage',
})
})
}.height(50)
Grid(){
ForEach(this.newVideosList,(item:videoModel,index:number)=>{
GridItem(){
Column() {
Image(item.imgpath).alt($r('app.media.default_video')).width('100%').height(102)
.objectFit(ImageFit.Fill)
Text(item.name).maxLines(2).fontSize(15).fontColor('app.color.666666').textAlign(TextAlign.Start)
.textOverflow({ overflow: TextOverflow.Ellipsis }).width('100%').height(56).padding({left:10,top:10,right:10,bottom:10})
}.backgroundColor(Color.White)
.borderRadius(5)
.height('auto')
.clip(true)
.width('calc((100% - 45vp)/2)')
.margin({left:15,bottom:15})
.onClick(()=>{
videoTools.getVideoDetail(item.uuid)
})
}
})
}.width('100%')
}.width('100%')
}
}

View File

@ -0,0 +1,57 @@
import { newsModel,expertDetailModel } from '../model/HomeModel'
import { router } from '@kit.ArkUI'
@Preview
@Component
export struct HomeSwiperComp {
@Prop newslist: newsModel[];
@Prop expertData:expertDetailModel;
build() {
Column() {
Swiper() {
ForEach(this.newslist, (item: newsModel,index:number) => {
Stack({alignContent:Alignment.Center}) {
Image(item.headImg)
.objectFit(ImageFit.Fill)// 图片填充模式
.width('100%').height('100%')
if (index == 0) {
Column({space:5}){
Text(this.expertData.realName+'专家工作室')
.fontSize(19)
.fontColor(Color.White)
.margin({left:20,top:60})
Text(this.expertData.hospitalName)
.fontSize(16)
.fontColor(Color.White)
.margin({left:20})
}.width('100%').alignItems(HorizontalAlign.Start)
}
}.onClick(()=>{
if (index == 0) {
router.pushUrl({url:'pages/MinePage/EditUserDataPage'})
} else {
router.pushUrl({
url: 'pages/WebView/WebPage', // 目标url
params: {url:item.path,title:item.title}
})
}
})
}, (item: newsModel) => JSON.stringify(item))
}
.indicator(
Indicator.dot()
.itemWidth(8)
.itemHeight(8)
.selectedItemWidth(8)
.selectedItemHeight(8)
.color(Color.Gray)
.selectedColor($r('app.color.main_color'))
)
.loop(true)
.autoPlay(true)
.interval(5000)
}
.width('100%')
}
}

View File

@ -0,0 +1,92 @@
import { esiteModel } from '../model/HomeModel'
import { router } from '@kit.ArkUI'
@Component
export struct SpeciallyEStandingComp {
@Prop esiteArray: esiteModel[];
@State newEsiteArr: esiteModel[][] = [];
@State selectedIndex:number = 0;
aboutToAppear(): void {
this.newEsiteArr = convertTo2DArray(this.esiteArray)
}
changeGroup() {
animateTo({
duration: 500,
curve: Curve.EaseIn,
}, () => {
if (this.selectedIndex === this.newEsiteArr.length - 1) {
this.selectedIndex = 0;
} else {
this.selectedIndex++;
}
})
}
build() {
Column() {
Row(){
Text('专题E站')
.fontSize(17)
.fontWeight(FontWeight.Bold)
.margin({left:15})
Blank()
.layoutWeight(1)
if (this.newEsiteArr.length>=2) {
Row(){
Image($r('app.media.new_home_choose_icon'))
.width(15).height(15)
Text(' 换一换')
.fontSize(15)
.fontColor('#999999')
}.margin({right:15})
.onClick(()=>{
this.changeGroup();
})
}
}.height(50)
Column(){
ForEach(getSubArray(this.newEsiteArr,this.selectedIndex),(item:esiteModel,index:number)=>{
Image(item.img_path)
.objectFit(ImageFit.Cover)
.margin({left:10,top:10,right:10})
.height(45).width('95%')
.onClick(()=>{
router.pushUrl({
url: 'pages/WebView/WebPage', // 目标url
params: {url:item.url,title:item.name}
})
})
})
}.backgroundColor(Color.White).borderRadius(4).height(175).width('93%')
.margin({left:15,right:15})
}.width('100%').alignItems(HorizontalAlign.Start)
}
}
function convertTo2DArray<T extends esiteModel>(sourceArray: T[], groupSize: number = 3): T[][] {
const resultArray: T[][] = [];
for (let i = 0; i < sourceArray.length; i += groupSize) {
const group = sourceArray.slice(i, i + groupSize);
if (group.length < groupSize) {
const emptyObj: esiteModel = {} as esiteModel;
const emptyItems = Array(groupSize - group.length).fill(emptyObj) as T[];
resultArray.push([...group, ...emptyItems]);
} else {
resultArray.push(group);
}
}
return resultArray;
}
// 获取指定下标的子数组(带边界检查)
function getSubArray<T>(data: T[][], index: number): T[] {
if (index < 0 || index >= data.length) {
// 越界返回空数组(或抛异常)
return [];
}
return data[index];
}

View File

@ -0,0 +1,126 @@
export interface HomeModel {
code:string;
data:dataModel;
message:string;
}
export interface dataModel{
consult_list?:consultModel;
news_list?:newsModel[];
gandanfile_list?:gandanfileModel[];
isOnlineToday?:string;
has_unread?:string;
guide_ist?:guideModel[];
expertDetail?:expertDetailModel;
excellencourse_list?:excellencourseModel[];
video_list?:videoModel[];
meeting_list?:meetingModel[];
icons_list?:iconsModel[];
welfare_notice?:welfareModel;
esite_list?:esiteModel[];
sign_in?:string
}
export interface consultModel {
yetDayTotalNum:string;
count:string;
list:[];
yetDayTotalnumEPNum:string
}
export interface newsModel {
uuid:string;
title:string;
headImg:string;
color:string;
type:string;
path:string;
}
export interface gandanfileModel {
type:string;
article_uuid:string;
title:string;
tags:string;
path:string
}
export interface guideModel {
create_date:string;
guide_type_uuid:string;
guide_type:string;
guide_uuid:string;
article_uuid:string;
title:string;
tags:string;
path:string
}
export interface expertDetailModel {
photo:string;
officeName:string;
positionName:string;
hospitalName:string;
qrcode:string;
realName:string;
}
export interface excellencourseModel {
video_num:string;
discount_type:string;
account:string;
discount_price:string;
title:string;
search_second_list:string;
study_num:string;
sroll_img:string;
index_img:string;
upload_num:string;
back_bon:string;
fuli_bon:string;
special_type_name:string;
tags:string;
id:string;
}
export interface videoModel {
readnum:string;
uuid:string;
imgpath:string;
polyv_uuid:string;
public_name:string;
imgUrl:string;
note:string;
name:string;
path:string;
content:string;
}
export interface meetingModel {
title:string;
begin_date_timestamp:string;
end_date_timestamp:string;
liveurl:string;
begin_date:string;
end_date:string;
state:string;
path:string;
}
export interface iconsModel {
fixed:string;
img:string;
name:string;
isRed:boolean;
}
export interface welfareModel {
one_last_notice:boolean;
receive_notice:boolean;
}
export interface esiteModel {
url:string;
img_path:string;
name:string;
}

View File

@ -1,19 +1,185 @@
import { FlipperComp } from '../components/FlipperComp'
import { HomeIconComp } from '../components/HomeIconComp'
import { HomeSwiperComp } from '../components/HomeSwiperComp'
import { SpeciallyEStandingComp } from '../components/SpeciallyEStandingComp'
import { HomeReplayVideoComp } from '../components/HomeReplayVideoComp'
import { getDisplayWindowWidth } from 'media-player-common'
import { BusinessError } from '@kit.BasicServicesKit';
import HashMap from '@ohos.util.HashMap';
import { BasicConstant,hdHttp, HdResponse ,logger,HdHomeNav} from '@itcast/basic/Index'
import { HomeModel,dataModel, newsModel,iconsModel } from '../model/HomeModel';
import { DefaultHintProWindows,SignPopWindow,HdLoadingDialog } from '@itcast/basic'
import { promptAction, router } from '@kit.ArkUI';
@Entry
@Component
export struct HomePage {
@State message: string = 'Hello World';
@State homeData:dataModel = {} as dataModel;
@State navAlpha: number = 0;
@State navBackColor: string = 'FFFFFF'
@Consume@Watch('gotoTop')
toTop:boolean;
@State hintMessage:string = '';
@State signData:Record<string,string> = {};
scroller:Scroller = new Scroller()
private hintWindowDialog!: CustomDialogController;
private signWindowDialog!:CustomDialogController;
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
customStyle: true,
alignment: DialogAlignment.Center
})
private hintPopWindowDialog() {
this.hintWindowDialog = new CustomDialogController({
builder:DefaultHintProWindows({
controller:this.hintWindowDialog,
message:this.hintMessage,
cancleTitle:'',
confirmTitle:'关闭',
confirmTitleColor: '#000000',
selectedButton: (index:number)=>{
this.hintWindowDialog.close();
}
}),
alignment: DialogAlignment.Center,
cornerRadius:24,
autoCancel:false,
backgroundColor: ('rgba(0,0,0,0.5)'),
})
}
private signPopWindowDialog(){
this.signWindowDialog = new CustomDialogController({
builder:SignPopWindow({
controller:this.signWindowDialog,
signDay:'今天是我们相识的第'+this.signData.gdxzday+'天',
signWeek:this.signData.totalDay,
signMouth:this.signData.continuous_day,
signNews:this.signData.news['title'],
signHtml:this.signData.news['path'],
}),
alignment: DialogAlignment.Center,
cornerRadius:8,
autoCancel:false,
backgroundColor: Color.Transparent,
backgroundBlurStyle: BlurStyle.NONE,
})
}
gotoTop() {
this.scroller.scrollToIndex(0);
this.initData()
}
aboutToAppear(): void {
this.initData()
this.hintPopWindowDialog();
this.signPopWindowDialog();
}
initData() {
const hashMap: HashMap<string, string> = new HashMap();
this.dialog.open()
hashMap.clear();
hdHttp.httpReq<string>(BasicConstant.indexV2,hashMap).then(async (res: HdResponse<string>) => {
logger.info('Response indexV2'+res);
let json:HomeModel = JSON.parse(res+'') as HomeModel;
this.dialog.close();
this.homeData = json.data;
for (const item of this.homeData.news_list as newsModel[]) {
if (item.type == '1') {
this.navBackColor = item.color;
}
}
}).catch((err: BusinessError) => {
this.dialog.close();
})
}
getSignData() {
const hashMap: HashMap<string, string> = new HashMap();
this.dialog.open()
hashMap.clear();
hashMap.set('score_type','1');
hdHttp.httpReq<string>(BasicConstant.addBonusPoints,hashMap).then(async (res: HdResponse<string>) => {
logger.info('Response addBonusPoints'+res);
this.dialog.close();
let json:Record<string,string> = JSON.parse(res+'') as Record<string,string>;
if (json.code == '1') {
this.homeData.sign_in = '1';
this.signData = json;
this.signWindowDialog.open();
} else if (json.code == '201') {
this.homeData.sign_in = '1';
this.hintMessage = '今日已签到,每日只能签到一次。\n请明日继续哦~';
this.hintWindowDialog.open();
}
}).catch((err: BusinessError) => {
this.dialog.close();
})
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.message = 'Welcome';
})
Stack(){
Scroll(this.scroller) {
Column() {
if (this.homeData.news_list && this.homeData.news_list.length > 0) {
HomeSwiperComp({ newslist: this.homeData.news_list, expertData: this.homeData.expertDetail })
.height(getDisplayWindowWidth().vp / 16 * 9)
}
if (this.homeData.icons_list && this.homeData.icons_list.length > 0) {
HomeIconComp({iconList:this.homeData.icons_list})
}
if (this.homeData.meeting_list && this.homeData.meeting_list.length > 0) {
FlipperComp({ bankAdBeans: this.homeData.meeting_list })
.height(56)
.backgroundColor(Color.Yellow)
}
if (this.homeData.esite_list && this.homeData.esite_list.length > 0) {
SpeciallyEStandingComp({ esiteArray: this.homeData.esite_list })
}
if (this.homeData.video_list && this.homeData.video_list.length > 0) {
HomeReplayVideoComp({ videoList: this.homeData.video_list })
}
}
}
.width('100%')
.edgeEffect(EdgeEffect.Spring)
.scrollBar(BarState.Off)
.onWillScroll(() => {
const yOffset = this.scroller.currentOffset().yOffset;
const threshold = 56;
if (yOffset <= 0) {
this.navAlpha = 0;
} else if (yOffset >= threshold) {
this.navAlpha = 1;
} else {
this.navAlpha = yOffset / threshold;
}
})
HdHomeNav({
leftIcon:this.homeData.sign_in == '0'?$r('app.media.home_no_qiandao_icon'):$r('app.media.home_qiandao_icon'),
placeholder:'搜索视频、会议',
alpha:this.navAlpha,
backColor:this.navBackColor,
leftItemAction:()=>{
this.getSignData();
},
searchItemAction:()=>{
router.pushUrl({
url:'pages/SearchPage/VideoSearchPage',
params: {
params:{'pageName':'视频'}
}
})
}
})
}
.alignContent(Alignment.Top)
.backgroundColor('#f4f4f4')
.width('100%')
.height('100%')
}
}

View File

@ -5,4 +5,4 @@
"value": "50fp"
}
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -4,11 +4,13 @@ export class MyPageSectionClass {
imageSrc:ResourceStr = '';
title:string = '';
path:string = '';
status:boolean = false;
constructor(id:string,imageSrc:ResourceStr,title:string,path:string) {
constructor(id:string,imageSrc:ResourceStr,title:string,path:string,status:boolean) {
this.id = id;
this.imageSrc = imageSrc;
this.title = title;
this.path = path;
this.status = status;
}
}

View File

@ -1,11 +1,17 @@
import { HeaderView } from '../view/HeaderView'
import { HdNav, getTimeText, hdHttp, HdUser } from '@itcast/basic'
import { OneSection } from '../view/OneSection'
import { TwoSection } from '../view/TwoSection'
import { ThreeSection } from '../view/ThreeSection'
import { FourSection } from '../view/FourSection'
import { OtherList } from '../view/OtherList'
import { emitter } from '@kit.BasicServicesKit'
import { HdNav,hdHttp,HdResponse,BasicConstant,ExpertData,authStore,RequestDefaultModel } from '@itcast/basic'
import { BusinessError, emitter } from '@kit.BasicServicesKit';
import HashMap from '@ohos.util.HashMap'
interface heroFirst {
id: string;
nick_name: string;
}
@Component
export struct MyHomePage {
@ -13,21 +19,64 @@ export struct MyHomePage {
@StorageProp('topHeight')
topHeight: number = 0
@State myInfoBackGround:string = '';
@State heroArray:Array<object> = [];
@State expertData:object | string = new Object;
scroller = new Scroller()
aboutToAppear(): void {
this.uploadBackImgAction();
emitter.on({ eventId: BasicConstant.notification_home_tab_change }, (eventData: emitter.EventData) => {
if (eventData.data?.changeIndex === 2) {
this.uploadBackImgAction();
}
});
}
uploadBackImgAction() {
const hashMap: HashMap<string, string> = new HashMap();
hdHttp.httpReq<string>(BasicConstant.myData,hashMap).then(async (res: HdResponse<string>) => {
console.info(`我的背景图: ${res}`);
let json:Record<string,object | string> = JSON.parse(res+'') as Record<string,object | string>;
if(json.code == '200') {
this.heroArray = json.data["honor_list"];
this.myInfoBackGround = json.data['myInfoBackGround'];
this.expertData = json.data;
// 获取ranking值带安全类型转换
const ranking: string = json.data["ranking"]?.toString() ?? "";
if (Number(ranking) > 0) {
// 创建排名对象
const rankDic: heroFirst = {
"id": "ranking",
"nick_name": `随访达人 I 排名${ranking}`
};
// 插入数组首位
this.heroArray.unshift(rankDic);
}
} else {
console.error('我的背景图:'+json.message)
}
}).catch((err: BusinessError) => {
console.info(`Response login fail: ${err}`);
})
}
build() {
Column() {
HdNav({ title: '我的', showLeftIcon:false , showRightIcon: false, hasBorder: true })
Scroll(this.scroller) {
Column() {
HeaderView()
// OneSection()
// TwoSection()
// ThreeSection()
FourSection()
OtherList()
}
Stack() {
Image(this.myInfoBackGround)
.backgroundImageSize(ImageSize.Cover)
.width('100%')
Column() {
HeaderView({heroArray:this.heroArray,expertData:this.expertData})
OneSection()
FourSection()
OtherList()
}
}.alignContent(Alignment.Top)
}
.width('100%')
.height('100%')

View File

@ -21,10 +21,10 @@ export struct FourSection {
// new MyPageSectionClass('threeItem',this.pushIconPath,this.pushStatus,''),
// new MyPageSectionClass('fourItem',$r('app.media.my_page_version'),'发现新版本','')
new MyPageSectionClass('oneItem',$r('app.media.my_page_choosePhone'),'更换手机号','pages/MinePage/ChangePhonePage'),
new MyPageSectionClass('twoItem',this.pushIconPath,this.pushStatus,''),
new MyPageSectionClass('threeItem',$r('app.media.my_page_guanyu_icon'),'关于肝胆相照','pages/WebView/WebPage'),
new MyPageSectionClass('fourItem',$r('app.media.my_page_zhibo_icon'),'肝胆相照直播群','pages/WebView/WebPage')
new MyPageSectionClass('oneItem',$r('app.media.my_page_choosePhone'),'更换手机号','pages/MinePage/ChangePhonePage',false),
new MyPageSectionClass('twoItem',this.pushIconPath,this.pushStatus,'',false),
new MyPageSectionClass('threeItem',$r('app.media.my_page_guanyu_icon'),'关于肝胆相照','pages/WebView/WebPage',false),
new MyPageSectionClass('fourItem',$r('app.media.my_page_zhibo_icon'),'肝胆相照直播群','pages/WebView/WebPage',false)
];
aboutToAppear() {
@ -60,7 +60,7 @@ export struct FourSection {
// 更新数组中的标题
this.fourSectionList = this.fourSectionList.map((item, index) => {
if (index === 1) {
return new MyPageSectionClass(item.id, this.pushIconPath, this.pushStatus, item.path);
return new MyPageSectionClass(item.id, this.pushIconPath, this.pushStatus, item.path,false);
}
return item;
});

View File

@ -33,8 +33,8 @@ export struct HeaderView {
@State heroIndex: number = 0 // 当前页索引
@State photoPath:string = BasicConstant.urlImage+authStore.getUser().photo;
@State name:string = authStore.getUser().realName;
@State myPageData:object = new Object;
@State heroArray:Array<object> = [];
@Prop heroArray:Array<object> = [];
@Prop expertData:object | string= new Object;
@State clickHeroId:string = '';
@Consume@Watch('gotoTop')
toTop:boolean;
@ -48,11 +48,9 @@ export struct HeaderView {
aboutToAppear(): void {
this.uploadUserDataAction();
this.uploadBackImgAction();
emitter.on({ eventId: BasicConstant.notification_home_tab_change }, (eventData: emitter.EventData) => {
if (eventData.data?.changeIndex === 2) {
this.uploadUserDataAction();
this.uploadBackImgAction();
}
});
}
@ -81,103 +79,82 @@ export struct HeaderView {
})
}
uploadBackImgAction() {
const hashMap: HashMap<string, string> = new HashMap();
hdHttp.httpReq<string>(BasicConstant.myData,hashMap).then(async (res: HdResponse<string>) => {
console.info(`我的背景图: ${res}`);
let json:RequestDefaultModel = JSON.parse(res+'') as RequestDefaultModel;
if(json.code == '200') {
this.heroArray = json.data["honor_list"];
this.myPageData = json.data;
// 获取ranking值带安全类型转换
const ranking: string = this.myPageData["ranking"]?.toString() ?? "";
if (Number(ranking) > 0) {
// 创建排名对象
const rankDic: heroFirst = {
"id": "ranking",
"nick_name": `随访达人 I 排名${ranking}`
};
// 插入数组首位
this.heroArray.unshift(rankDic);
}
} else {
console.error('我的背景图:'+json.message)
}
}).catch((err: BusinessError) => {
console.info(`Response login fail: ${err}`);
})
}
handleAvatarClick() {
router.pushUrl({url:'pages/MinePage/EditUserDataPage'})
}
build() {
// Row() {
Column({space:5}) {
Row({space:10}) {
Image(this.photoPath)
.alt($r('app.media.userPhoto_default'))
.margin({left:15})
.width(60)
.height(60)
.borderRadius(5)
.objectFit(ImageFit.Cover)
.onClick(()=>this.handleAvatarClick())
Column({space:5}) {
Text(this.name)
.fontSize(18)
.fontColor('#FFFFFF')
.onClick(()=>this.handleAvatarClick())
List({space:5,initialIndex:this.heroIndex,scroller:this.scrollerForList}) {
ForEach(this.heroArray, (item: heroFirst) => {
ListItem() {
Row() {
Image(item.id === 'ranking'?$r('app.media.my_home_hero_ranking'):$r('app.media.my_page_header_hertIcon'))
.width(13)
.height(13)
.margin({left:7})
Text(item.nick_name)
.fontColor(Color.White)
.fontSize(11)
.margin({left:4,right:10})
}
.height(18)
.margin({right:5})
.borderRadius(9)
.borderWidth(1)
.borderColor(Color.White)
.onClick(()=>{
if (item.id !== 'ranking') {
this.clickHeroId = item.id;
this.dialogController.open();
}
})
}
})
}
.listDirection(Axis.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
.height(18)
}
.alignItems(HorizontalAlign.Start)
Column({space:15}) {
Row({space:10}) {
Image(this.photoPath)
.alt($r('app.media.userPhoto_default'))
.margin({left:15})
.width(60)
.height(60)
.width('70%')
.margin({top:22})
.borderRadius(5)
.objectFit(ImageFit.Cover)
.onClick(()=>this.handleAvatarClick())
Column({space:5}) {
Text(this.name)
.fontSize(18)
.fontColor('#FFFFFF')
.onClick(()=>this.handleAvatarClick())
List({space:5,initialIndex:this.heroIndex,scroller:this.scrollerForList}) {
ForEach(this.heroArray, (item: heroFirst) => {
ListItem() {
Row() {
Image(item.id === 'ranking'?$r('app.media.my_home_hero_ranking'):$r('app.media.my_page_header_hertIcon'))
.width(13)
.height(13)
.margin({left:7})
Text(item.nick_name)
.fontColor(Color.White)
.fontSize(11)
.margin({left:4,right:10})
}
.height(18)
.margin({right:5})
.borderRadius(9)
.borderWidth(1)
.borderColor(Color.White)
.onClick(()=>{
if (item.id !== 'ranking') {
this.clickHeroId = item.id;
this.dialogController.open();
}
})
}
})
}
.listDirection(Axis.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
.height(18)
}.alignItems(HorizontalAlign.Start).width('calc(100% - 100vp)')
}.width('100%').margin({top:20})
Column(){
Row({space:70}){
ForEach([{'title':'随访患者数','content':this.expertData['expert_apply_num'] || '0'},
{'title':'公益咨询数','content':this.expertData['consult_total_num'] || '0'}],
// {'title':'患者送花数','content':this.expertData['ping_flowewr_num'] || '0'}],
(item:object)=>{
Column(){
Text(item['content']?.toString() || '0')
.fontSize(20)
.fontColor('#000000')
.height(28)
Text(item['title'])
.fontSize(12)
.fontColor('#333333')
.height(17)
}.height('100%').justifyContent(FlexAlign.Center)
})
}
.width('100%')
.height(97)
}
.width('100%')
.height(97)
.backgroundImage(this.myPageData["myInfoBackGround"]).backgroundImageSize(ImageSize.Cover)
}.width('95%').height(65).borderRadius(5).backgroundColor(Color.White)
}
// }
gotoTop()
{
.width('100%')
}
gotoTop() {
this.photoPath = BasicConstant.urlImage+authStore.getUser().photo;
}
}

View File

@ -5,15 +5,19 @@ export struct MyPageSectionItem {
@Prop sectionItem: MyPageSectionClass;
build() {
Column(){
Image(this.sectionItem.imageSrc)
.width(35).height(35)
.borderRadius(17.5)
.objectFit(ImageFit.Auto)
Text(this.sectionItem.title)
.fontSize(12)
.fontColor(Color.Black)
.margin({top:6})
}
Stack() {
Column() {
Image(this.sectionItem.imageSrc)
.width(24).height(24)
.objectFit(ImageFit.Auto)
Text(this.sectionItem.title)
.fontSize(14)
.fontColor('#333333')
.margin({ top: 10 })
}.width('100%')
if (this.sectionItem.status) {
Text().backgroundColor(Color.Red).width(10).height(10).borderRadius(5)
}
}.width('100%').height('100%').alignContent(Alignment.TopEnd)
}
}

View File

@ -1,19 +1,34 @@
import { it } from "@ohos/hypium";
import { MyPageSectionClass } from "../model/MyPageSectionClass";
import { MyPageSectionItem } from '../view/MyPageSectionItem'
import { router } from "@kit.ArkUI";
import { BasicConstant,hdHttp, HdResponse ,logger,authStore} from '@itcast/basic/Index'
import { BusinessError } from '@kit.BasicServicesKit';
import { it } from "@ohos/hypium";
interface extraData {
expertUuid: string
}
interface requestCallBack {
code:string;
msg:string;
message:string;
data:Array<object>
}
@Preview
@Component
export struct OneSection {
@State sectionTitle: string = "随访服务";
@State currentIndex: number = 0;
@Consume@Watch('gotoTop')
toTop:boolean;
@State oneSectionList: Array<MyPageSectionClass> = [
new MyPageSectionClass('oneItem', $r('app.media.app_icon'), '患者审核', '/pages/MyHomePage'),
new MyPageSectionClass('twoItem', $r('app.media.app_icon'), '患者分组', '/pages/MyHomePage'),
new MyPageSectionClass('threeItem', $r('app.media.app_icon'), '群发消息', '/pages/MyHomePage'),
new MyPageSectionClass('fourItem', $r('app.media.app_icon'), '随访二维码', '/pages/MyHomePage'),
new MyPageSectionClass('fiveItem', $r('app.media.app_icon'), '出诊计划', '/pages/MyHomePage')
new MyPageSectionClass('oneItem', $r('app.media.my_page_patientAudit'), '患者审核', '/pages/MyHomePage',false),
new MyPageSectionClass('twoItem', $r('app.media.my_page_patientList'), '患者分组', '/pages/MyHomePage',false),
new MyPageSectionClass('threeItem', $r('app.media.my_page_message'), '群发消息', '/pages/MyHomePage',false),
new MyPageSectionClass('fourItem', $r('app.media.my_page_QrCode'), '随访二维码', '/pages/MyHomePage',false),
new MyPageSectionClass('fiveItem', $r('app.media.my_page_visitPlan'), '出诊计划', '/pages/MyHomePage',false)
];
private getPagedItems(): Array<Array<MyPageSectionClass>> {
@ -25,6 +40,35 @@ export struct OneSection {
return pages;
}
aboutToAppear(): void {
this.getApplyListData();
}
gotoTop() {
this.getApplyListData();
}
getApplyListData(){
hdHttp.post<string>(BasicConstant.applyList, {
expertUuid: authStore.getUser().uuid,
} as extraData).then(async (res: HdResponse<string>) => {
logger.info('Response applyList'+res);
let json:requestCallBack = JSON.parse(res+'') as requestCallBack;
if(json.code == '1') {
if (json.data.length > 0) {
this.oneSectionList = this.oneSectionList.map((item, index) => {
if (index === 0) {
return new MyPageSectionClass(item.id,item.imageSrc,item.title,item.path,true);
}
return item;
});
}
}
}).catch((err: BusinessError) => {
console.info(`Response fails: ${err}`);
})
}
build() {
Column() {
// 标题
@ -42,6 +86,17 @@ export struct OneSection {
ForEach(pageItems, (item: MyPageSectionClass) => {
GridItem() {
MyPageSectionItem({ sectionItem: item })
.onClick(()=>{
if (item.title === '患者审核') {
router.pushUrl({
url:'pages/PatientsPage/PatientPages'
})
} else if (item.title === '患者分组') {
router.pushUrl({
url:'pages/PatientsPage/PatientsGroupPage'
})
}
})
}
}, (item: MyPageSectionClass) => item.id)
}
@ -51,13 +106,13 @@ export struct OneSection {
.height('100%')
.width('100%')
})
}
}.width('100%')
.index(this.currentIndex)
.onChange((index: number) => {
this.currentIndex = index;
})
.height(78)
.indicator(false)
.indicator(false).loop(false)
Row() {
ForEach(new Array(Math.ceil(this.oneSectionList.length / 4)).fill(0), (item: number, idx: number) => {

View File

@ -9,12 +9,12 @@ export struct ThreeSection {
@State currentIndex: number = 0;
@State threeSectionList:Array<MyPageSectionClass> = [
new MyPageSectionClass('oneItem',$r('app.media.app_icon'),'我的账户','/pages/MyHomePage'),
new MyPageSectionClass('twoItem',$r('app.media.app_icon'),'我的积分','/pages/MyHomePage'),
new MyPageSectionClass('threeItem',$r('app.media.app_icon'),'我的福利','/pages/MyHomePage'),
new MyPageSectionClass('fourItem',$r('app.media.app_icon'),'我的鲜花','/pages/MyHomePage'),
new MyPageSectionClass('fiveItem',$r('app.media.app_icon'),'课件明细','/pages/MyHomePage'),
new MyPageSectionClass('fiveItem',$r('app.media.app_icon'),'课程明细','/pages/MyHomePage')
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)
];
private getPagedItems(): Array<Array<MyPageSectionClass>> {

View File

@ -9,10 +9,10 @@ export struct TwoSection {
@State currentIndex: number = 0;
@State twoSectionList:Array<MyPageSectionClass> = [
new MyPageSectionClass('oneItem',$r('app.media.app_icon'),'我的视频','/pages/MyHomePage'),
new MyPageSectionClass('twoItem',$r('app.media.app_icon'),'我的课程','/pages/MyHomePage'),
new MyPageSectionClass('threeItem',$r('app.media.app_icon'),'我的下载','/pages/MyHomePage'),
new MyPageSectionClass('fourItem',$r('app.media.app_icon'),'我的收藏','/pages/MyHomePage')
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)
];
private getPagedItems(): Array<Array<MyPageSectionClass>> {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

6
features/patient/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/node_modules
/oh_modules
/.preview
/build
/.cxx
/.test

View File

@ -0,0 +1,17 @@
/**
* Use these variables when you tailor your ArkTS code. They must be of the const type.
*/
export const HAR_VERSION = '1.0.0';
export const BUILD_MODE_NAME = 'debug';
export const DEBUG = true;
export const TARGET_NAME = 'default';
/**
* BuildProfile Class is used only for compatibility purposes.
*/
export default class BuildProfile {
static readonly HAR_VERSION = HAR_VERSION;
static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
static readonly DEBUG = DEBUG;
static readonly TARGET_NAME = TARGET_NAME;
}

View File

@ -0,0 +1,17 @@
export { MainPage } from './src/main/ets/components/MainPage';
export { PatientApplyPage } from './src/main/ets/components/PatientApplyPage'
export { PatientSetMsgPage } from './src/main/ets/components/PatientSetMsgPage'
export { applyListCallBacl, applyListModel, applyHistoryCallBacl , historyObjectModel, historyModel } from './src/main/ets/models/ApplyModel'
export { PatientsGroup } from './src/main/ets/components/PatientsGroup'
export { groupRequest,groupRequestCall,groupModel,patientListModel } from './src/main/ets/models/PatientsGroupModel'
export { BuildOrEditGroupPage } from './src/main/ets/components/BuildOrEditGroupPage'
export { PatientsListComp } from './src/main/ets/components/PatientsListComp'
export { PatientDetailsComp } from './src/main/ets/components/PatientDetailsComp'

View File

@ -0,0 +1,31 @@
{
"apiType": "stageMode",
"buildOption": {
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": false,
"files": [
"./obfuscation-rules.txt"
]
},
"consumerFiles": [
"./consumer-rules.txt"
]
}
},
},
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest"
}
]
}

View File

View File

@ -0,0 +1,6 @@
import { harTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
}

View File

@ -0,0 +1,23 @@
# Define project specific obfuscation rules here.
# You can include the obfuscation configuration files in the current module's build-profile.json5.
#
# For more details, see
# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
# Obfuscation options:
# -disable-obfuscation: disable all obfuscations
# -enable-property-obfuscation: obfuscate the property names
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
# -compact: remove unnecessary blank spaces and all line feeds
# -remove-log: remove all console.* statements
# -print-namecache: print the name cache that contains the mapping from the old names to new names
# -apply-namecache: reuse the given cache file
# Keep options:
# -keep-property-name: specifies property names that you want to keep
# -keep-global-name: specifies names that you want to keep in the global scope
-enable-property-obfuscation
-enable-toplevel-obfuscation
-enable-filename-obfuscation
-enable-export-obfuscation

View File

@ -0,0 +1,25 @@
{
"meta": {
"stableOrder": true
},
"lockfileVersion": 3,
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
"specifiers": {
"@itcast/basic@../../commons/basic": "@itcast/basic@../../commons/basic",
"refreshlib@../../RefreshLib": "refreshlib@../../RefreshLib"
},
"packages": {
"@itcast/basic@../../commons/basic": {
"name": "@itcast/basic",
"version": "1.0.0",
"resolved": "../../commons/basic",
"registryType": "local"
},
"refreshlib@../../RefreshLib": {
"name": "refreshlib",
"version": "1.0.0",
"resolved": "../../RefreshLib",
"registryType": "local"
}
}
}

View File

@ -0,0 +1,12 @@
{
"name": "patient",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "Index.ets",
"author": "",
"license": "Apache-2.0",
"dependencies": {
"@itcast/basic": "file:../../commons/basic",
"refreshlib": "file:../../RefreshLib"
}
}

View File

@ -0,0 +1,304 @@
import { authStore, HdNav, PositionSelectedSheet } from '@itcast/basic';
import { promptAction, router } from '@kit.ArkUI'
import { HdLoadingDialog,DefaultHintProWindows } from '@itcast/basic'
import { BasicConstant,hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
import { BusinessError } from '@kit.BasicServicesKit';
import { patientListModel } from '../models/PatientsGroupModel'
@Component
export struct BuildOrEditGroupPage {
@State params:Record<string, string> = router.getParams() as Record<string, string>
scrollerCon:Scroller = new Scroller()
@State groupPatientList:patientListModel[] = []
@State groupName:string = ''
private hintWindowDialog!: CustomDialogController
@Consume@Watch('onRefreshAction') refreshFlag: boolean;
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
customStyle: true,
alignment: DialogAlignment.Center
})
private hintPopWindowDialog() {
this.hintWindowDialog = new CustomDialogController({
builder:DefaultHintProWindows({
controller:this.hintWindowDialog,
message:'确定删除该分组',
cancleTitleColor: '#333333',
confirmTitleColor: '#333333',
selectedButton: (index:number)=>{
if (index === 1) {
this.deleGroupAction()
}
this.hintWindowDialog.close();
}
}),
alignment: DialogAlignment.Center,
cornerRadius:24,
backgroundColor: ('rgba(0,0,0,0.5)'),
})
}
onRefreshAction(flag: boolean) {
const returnParams = this.getUIContext().getRouter().getParams() as Record<string, string | patientListModel[]>;
const patients = returnParams?.selectedPatients as patientListModel[] | undefined;
if (patients?.length) {
for (const model of returnParams.selectedPatients as patientListModel[]) {
if (model.isSelected) {
this.groupPatientList.push(model)
}
}
}
}
aboutToAppear(): void {
if (this.params.title != '新建分组') {
this.getGroupPatientsData()
}
this.hintPopWindowDialog()
}
getGroupPatientsData() {
this.dialog.open()
hdHttp.post<string>(BasicConstant.patientListByGroup, {
"expert_uuid": authStore.getUser().uuid,
"group_uuid":this.params.group_uuid
} as Record<string,string>).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response patientListByGroup'+res);
let json:Record<string,string | patientListModel[]> = JSON.parse(res+'') as Record<string,string | patientListModel[]>;
if(json.code == '1') {
this.groupPatientList = json.data as patientListModel[];
} else {
console.error('获取患者分组列表失败:'+json.message)
promptAction.showToast({ message: String(json.message), duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.error(`Response fails: ${err}`);
})
}
deleGroupAction() {
this.dialog.open()
hdHttp.post<string>(BasicConstant.deleteGroup, {
"expert_uuid": authStore.getUser().uuid,
"group_uuid":this.params.group_uuid
} as Record<string,string>).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response patientListByGroup'+res);
let json:Record<string,string> = JSON.parse(res+'') as Record<string,string>;
if(json.code == '1') {
promptAction.showToast({ message: '删除分组成功', duration: 1000 })
router.back();
} else {
console.error('删除患者分组列表失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.error(`Response fails: ${err}`);
})
}
setCreatOrEditGroup(index:number) {
if (this.groupName.length <= 0) {
promptAction.showToast({ message: '请输入分组名称', duration: 1000 })
return
}
const uuidString:string = this.groupPatientList.map(item => item.uuid).join(",");
this.dialog.open()
hdHttp.post<string>(index == 0 ? BasicConstant.addGroup:BasicConstant.updateGroup, index == 0 ? {
"expert_uuid": authStore.getUser().uuid,
"name":this.groupName,
"patient_uuid":uuidString
} as Record<string,string> : {
"uuid": this.params.group_uuid,
"name":this.groupName,
"patient_uuid":uuidString
} as Record<string,string>).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response patientListByGroup'+res);
let json:Record<string,string> = JSON.parse(res+'') as Record<string,string>;
if(json.code == '1') {
promptAction.showToast({ message:'分组成功', duration: 1000 })
router.back();
} else if (json.code == '2') {
promptAction.showToast({ message:'该分组已存在', duration: 1000 })
} else {
console.error('删除患者分组列表失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.error(`Response fails: ${err}`);
})
// const postContent = new rcp.MultipartForm({
// "uuid": this.params.group_uuid,
// "name":this.groupName,
// "patient_uuid":uuidString
// })
// const session = rcp.createSession();
// session.post(BasicConstant.updateGroup, postContent)
// .then((response) => {
// this.dialog.close();
// logger.info('Response patientListByGroup'+response);
// let json:Record<string,string> = JSON.parse(response+'') as Record<string,string>;
// if(json.code == '1') {
// promptAction.showToast({ message:'分组成功', duration: 1000 })
// router.back();
// } else if (json.code == '2') {
// promptAction.showToast({ message:'该分组已存在', duration: 1000 })
// } else {
// console.error('删除患者分组列表失败:'+json.message)
// promptAction.showToast({ message: json.message, duration: 1000 })
// }
// })
// .catch((err: BusinessError) => {
// this.dialog.close();
// console.error(`Response err: Code is ${JSON.stringify(err.code)}, message is ${JSON.stringify(err)}`);
// })
}
build() {
Row() {
Column() {
HdNav({
title: this.params.title,
showRightIcon: false,
hasBorder: true,
rightText: '保存',
showRightText: true,
rightItemAction: () => {
if (this.params.title == '新建分组') {
this.setCreatOrEditGroup(0);
} else {
this.setCreatOrEditGroup(1);
}
}
})
Scroll(this.scrollerCon){
Column() {
Text('分组名称')
.fontSize(15)
.fontColor('#333333')
.margin({ left: 15 })
.height(50)
.textAlign(TextAlign.Start)
TextInput({placeholder:'设置分组名称',text:this.params.group_name})
.padding({left:15})
.width('100%')
.height(50)
.backgroundColor(Color.White)
.onChange((input:string)=>{
this.groupName = input;
})
Text('分组成员')
.fontSize(15)
.fontColor('#333333')
.margin({ left: 15 })
.height(50)
.textAlign(TextAlign.Start)
Row(){
Image($r('app.media.add_patients_to_roup'))
.width(50).height(50)
.margin({left:15})
Text('添加组患者')
.fontSize(16)
.fontColor('#333333')
.margin({left:15})
}
.width('100%')
.height(80)
.backgroundColor(Color.White)
.onClick(()=>{
router.pushUrl({
url:'pages/PatientsPage/PatientsListPage',
params:{group_uuid:this.params.group_uuid,selectedPatients:this.groupPatientList}
})
})
List(){
ListItemGroup({footer:this.footerView()}) {
ForEach(this.groupPatientList,(item:patientListModel,index:number)=>{
ListItem(){
this.patientsListItem(item,index)
}
})
}
}
}.width('100%').alignItems(HorizontalAlign.Start).justifyContent(FlexAlign.Start)
}
.width('100%').height('calc(100% - 56vp - 55vp)')
.scrollBar(BarState.Off)
.backgroundColor('#f4f4f4')
.align(Alignment.TopStart)
}
.width('100%').height('100%')
}
.height('100%')
}
@Builder
footerView (){
Column() {
Text('删除分组')
.fontSize(16)
.fontColor(Color.White)
.backgroundColor($r('app.color.main_color'))
.borderRadius(5)
.height(50)
.textAlign(TextAlign.Center)
.width('90%')
.onClick(()=>{
this.hintWindowDialog.open();
})
.visibility(this.params.title == '新建分组'?Visibility.Hidden:Visibility.Visible)
}.width('100%')
.height(120)
.justifyContent(FlexAlign.End)
}
@Builder
patientsListItem(item:patientListModel,index:number) {
Column() {
Row() {
Image(BasicConstant.urlImage + item.photo)
.alt($r('app.media.userPhoto_default'))
.borderRadius(6)
.width(50)
.height(50)
.margin({ left: 15 })
Text(item.nickname ? item.nickname : item.realname)
.fontSize(16)
.fontColor('#333333')
.margin({ left: 15 })
Blank()
Image($r('app.media.dele_patient_inThe_group'))
.width(22).height(22)
.objectFit(ImageFit.Fill)
.margin({ right: 15 })
.onClick(()=>{
this.groupPatientList.splice(index,1);
this.groupPatientList = [...this.groupPatientList];
})
}
.width('100%')
.height(80)
.backgroundColor(Color.White)
Blank()
.width('80%')
.height(1)
.backgroundColor(Color.Gray)
.margin({left:60})
}
}
}

View 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%')
}
}

View File

@ -0,0 +1,222 @@
import { ApplyViews } from '../views/ApplyViews'
import { authStore, HdNav } from '@itcast/basic';
import { applyListCallBacl,applyListModel,applyHistoryCallBacl,historyModel } from '../models/ApplyModel'
import HashMap from '@ohos.util.HashMap';
import { HdLoadingDialog } from '@itcast/basic'
import { BasicConstant,hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction, router } from '@kit.ArkUI'
import { patientDbManager, PatientData } from '@itcast/basic';
import { PullToRefreshLayout, RefreshController } from 'refreshlib'
interface extraData {
expertUuid: string,
page: number,
uuid: string,
status: string
}
@Component
export struct PatientApplyPage {
public controller:RefreshController = new RefreshController();
scroller = new Scroller();
@State applyArray:applyListModel[] = [];
@State historyArray:historyModel[] = [];
@State pageNumber:number = 1;
@State totalPageNumer:number = 1;
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
customStyle: true,
alignment: DialogAlignment.Center
})
aboutToAppear(): void {
this.getApplyList();
this.getHistoryApplyList();
}
getHistoryApplyList() {
const hashMap: HashMap<string, string> = new HashMap();
hashMap.set('page',this.pageNumber.toString());
this.dialog.open()
hdHttp.httpReq<string>(BasicConstant.relationRecordLately,hashMap).then(async (res: HdResponse<string>) => {
this.dialog.close();
this.controller.refreshSuccess();
this.controller.loadSuccess();
logger.info('Response relationRecordLately'+res);
let json:applyHistoryCallBacl = JSON.parse(res+'') as applyHistoryCallBacl;
if(json.code == 200) {
this.historyArray = json.data.list;
this.totalPageNumer = Number(json.data.total);
} else {
console.error('患者申请记录列表失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
this.controller.refreshError();
console.info(`Response fails: ${err}`);
})
}
getApplyList() {
this.dialog.open()
hdHttp.post<string>(BasicConstant.applyList, {
expertUuid: authStore.getUser().uuid,
} as extraData).then(async (res: HdResponse<string>) => {
this.dialog.close();
this.controller.refreshSuccess();
this.controller.loadSuccess();
logger.info('Response applyList'+res);
let json:applyListCallBacl = JSON.parse(res+'') as applyListCallBacl;
if(json.code == 1) {
this.applyArray = json.data;
} else {
console.error('新的患者列表失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
this.controller.refreshError();
console.info(`Response fails: ${err}`);
})
}
getApplyListOperate(status: string,model:applyListModel) {
this.dialog.open()
hdHttp.post<string>(BasicConstant.applyListOperate, {
uuid: model.uuid,
status: status
} as extraData).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response applyListOperate'+res);
let json:applyListCallBacl = JSON.parse(res+'') as applyListCallBacl;
if(json.code == 1) {
if (status == '2') {
this.getApplyList();
// 添加单个患者
const singlePatient: PatientData = {
uuid:model.patientUuid as string,
nickname: '',
mobile: model.mobile as string,
realName: model.realName as string,
nation: '',
sex: model.sex as number,
type: 1,
photo: model.photo as string,
expertUuid: authStore.getUser().uuid
};
const success1 = await patientDbManager.addPatient(singlePatient);
if (success1) {
console.info('添加成功');
const patients = await patientDbManager.getAllPatients();
promptAction.showToast({message:`现在一共是 ${patients.length} 个患者`})
} else {
console.info('添加失败');
}
promptAction.showToast({ message: '消息已处理', duration: 1000 })
router.pushUrl({
url:'pages/PatientsPage/PatientMsgSetPage',
params:{ 'model':model }
})
} else if (status == '3') {
this.pageNumber = 1;
this.getApplyList();
this.getHistoryApplyList();
}
} else {
console.error('患者列表申请处理失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.info(`Response fails: ${err}`);
})
}
build() {
Column(){
HdNav({ title: '新的患者', showRightIcon: false, hasBorder: true })
PullToRefreshLayout({
scroller:this.scroller,
viewKey:"ListPage",
controller:this.controller,
contentView:()=>{
this.contentView()
},
onRefresh:()=>{
this.pageNumber = 1;
this.getApplyList();
this.getHistoryApplyList();
},
onCanPullRefresh:()=>{
if (!this.scroller.currentOffset()) {
/*处理无数据,为空的情况*/
return true
}
//如果列表到顶返回true表示可以下拉返回false表示无法下拉
return this.scroller.currentOffset().yOffset <= 0
},
onLoad:()=>{
this.pageNumber++;
this.getApplyList();
this.getHistoryApplyList();
},
onCanPullLoad: () => {
if (this.pageNumber >= this.totalPageNumer) {
return false;
} else {
return true;
}
}
}).width('100%').height('calc(100% - 156vp)').clip(true)
Row(){
Text('加患者')
.fontSize(16)
.fontColor(Color.White)
.backgroundColor('rgb(63,199,193)')
.width('100%').height(50).textAlign(TextAlign.Center)
.onClick(()=>{
router.pushUrl({
url: 'pages/WebView/WebPage', // 目标url
params: {url:BasicConstant.wxUrl+'expert/expertcodeimg?expert_uuid='+authStore.getUser().uuid,title:'我的二维码'}
})
})
}.width('100%').height(56).backgroundColor(Color.White).alignItems(VerticalAlign.Top)
}.width('100%').height('100%')
}
@Builder
contentView(){
Column(){
Row({space:5}){
Image($r('app.media.addPatientApply_reminder_icon'))
.width(18).height(21)
Text('提醒: 为了避免不必要的纠纷,请您务必选择线下就诊过的患者')
.fontSize(16).fontColor('#666666')
}.width('100%').padding({left:10,top:10,right:20,bottom:10}).backgroundColor(Color.White)
if (this.applyArray.length > 0) {
Column(){
Text('随访申请')
.fontSize(15).fontColor('#333333').margin({left:10}).height(42)
ForEach(this.applyArray,(item:applyListModel)=>{
ApplyViews({applyItme:item,isApply:true,applyItemAction:((status: string,model:applyListModel)=>{
this.getApplyListOperate(status,model)
})})
})
}.width('100%').alignItems(HorizontalAlign.Start)
}
if (this.historyArray.length > 0) {
Column(){
Text('申请记录(近一月)')
.fontSize(15).fontColor('#333333').margin({left:10}).height(42)
ForEach(this.historyArray,(item:historyModel)=>{
ApplyViews({historyItem:item,isApply:false})
})
}.width('100%').alignItems(HorizontalAlign.Start)
}
}.width('100%').height('100%').backgroundColor('#f4f4f4')
}
}

View File

@ -0,0 +1,198 @@
import { authStore, HdNav, PositionSelectedSheet } from '@itcast/basic';
import { promptAction, router } from '@kit.ArkUI'
import { HdLoadingDialog,DefaultHintProWindows } from '@itcast/basic'
import { BasicConstant,hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
import { BusinessError } from '@kit.BasicServicesKit';
import HashMap from '@ohos.util.HashMap';
import { patientListModel } from '../models/PatientsGroupModel'
import measure from '@ohos.measure';
@Component
export struct PatientDetailsComp {
scroller:Scroller = new Scroller()
@Consume@Watch('onRefreshAction') refreshFlag: boolean
@State params:Record<string, string> = router.getParams() as Record<string, string>
@State groupArray:Array<Record<string,string>> = []
@State footerArray:Array<Record<string,string | ResourceStr>> = []
@State patientCase:Array<Record<string,string>> = []
@State patientData:Record<string,string> = {}
@State patientData2:Record<string,string> = {}
@State medicalHistoryContent:string = ''
@State isExpanded: boolean = false; // 展开状态
@State showExpandBtn: boolean = false; // 是否显示操作按钮
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
customStyle: true,
alignment: DialogAlignment.Center
})
onRefreshAction() {
this.getPatientCardData()
}
aboutToAppear(): void {
this.getPatientCardData()
this.footerArray = [{"img":$r('app.media.sendMessage_blackBtn'),"title":"发消息"},{"img":$r('app.media.fuifangPlan_blackBtn'),"title":"制定随访计划"},{"img":$r('app.media.listBing_blackBtn'),"title":"记录病情"}]
}
getPatientCardData(){
const hashMap: HashMap<string, string> = new HashMap();
hashMap.set('patient_uuid',String(this.params.patient_uuid));
this.dialog.open()
hdHttp.httpReq<string>(BasicConstant.patientCard,hashMap).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response patientCard'+res);
let json:Record<string,string> = JSON.parse(res+'') as Record<string,string>
const isFriend = String(json.isFriend)
if (isFriend == '0') {
promptAction.showToast({ message: '随访关系已解除', duration: 1000 })
router.back()
} else {
if(json.code == '200') {
this.getPatientDetailsData(String(json.group["name"]))
} else {
console.error('患者详情请求失败:'+json.message)
}
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.info(`Response fails: ${err}`);
})
}
getPatientDetailsData(groupType:string){
this.dialog.open()
hdHttp.post<string>(BasicConstant.toAddNickname, {
"expertUuid": authStore.getUser().uuid,
"patientUuid":String(this.params.patient_uuid)
} as Record<string,string>).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response toAddNickname'+res);
let json:Record<string,string | Record<string,string>> = JSON.parse(res+'') as Record<string,string | Record<string,string>>;
if(json.code == '1') {
this.getPatientData()
this.patientData = json.patientEx as Record<string,string>
let nickname = this.patientData.nickname
let note = this.patientData.note
let mobile = this.patientData.mobile
if (nickname.length>0) {
this.groupArray = [{"title":"备注","content":String(nickname),"prompt":"给患者添加备注名"},{"title":"分组","content":String(groupType),"prompt":"通过分组给患者分类"},{"title":"描述","content":String(note),"prompt":"补充患者关键信息,方便随访患者"},{"title":"电话号码","content":String(mobile),"prompt":""}]
} else {
this.groupArray = [{"title":"分组","content":String(groupType),"prompt":"通过分组给患者分类"},{"title":"描述","content":String(note),"prompt":"补充患者关键信息,方便随访患者"},{"title":"电话号码","content":String(mobile),"prompt":""}]
}
} else {
console.error('获取患者信息失败:'+json.message)
promptAction.showToast({ message: String(json.message), duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.error(`Response fails: ${err}`);
})
}
getPatientData() {
this.dialog.open()
hdHttp.post<string>(BasicConstant.patientDetail, {
"patientUuid":String(this.params.patient_uuid)
} as Record<string,string>).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response patientDetail'+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') {
this.patientData2 = json.data as Record<string,string>
this.medicalHistoryContent = String(json.medicalHistoryContent)
this.patientCase = json.patientCase as Array<Record<string,string>>
} else {
console.error('获取患者信息失败:'+json.message)
promptAction.showToast({ message: String(json.message), duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.error(`Response fails: ${err}`);
})
}
build() {
Row() {
Column() {
HdNav({
title: '患者详情',
showRightIcon: true,
hasBorder: true,
rightIcon:$r("app.media.patient_details_navigation_right"),
showRightText: false,
rightItemAction: () => {
router.pushUrl({
url: 'pages/PatientsPage/BuildOrEditGroupPage',
params:{"title":"新建分组"}
})
}
})
Scroll(this.scroller){
this.historyView()
this.footerView()
}.width('100%').height('calc(100% - 56vp)').backgroundColor('#f4f4f4')
.scrollBar(BarState.Off)
}
.width('100%').height('100%')
}
.height('100%')
}
@Builder
historyView(){
Column({space:10}){
Text('患者病史')
.fontSize(15)
.fontColor('#333333')
Text(this.medicalHistoryContent)
.fontSize(16)
.lineHeight(22)
.maxLines(this.isExpanded ? 0 : 2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.onAreaChange((_, area) => {
let fullHeight = measure.measureTextSize({
textContent: this.medicalHistoryContent,
fontSize: 15,
maxLines:2
}).height;
this.showExpandBtn = Number(area.height) < Number(fullHeight);
})
// 操作按钮(独立可点击区域)
if (this.showExpandBtn) {
Text(this.isExpanded ? "...收起" : "..展开全部")
.fontSize(15)
.fontColor($r('app.color.main_color')) // 红色标识可点击
.onClick(() => {
this.isExpanded = !this.isExpanded; // 切换状态
})
}
}
.alignItems(HorizontalAlign.Start)
.backgroundColor(Color.White)
.width('100%')
.padding(15)
}
@Builder
footerView(){
List(){
ForEach(this.footerArray,(item:Record<string,string>,index:number)=>{
ListItem(){
Row(){
Image(item.img)
.width(20).height(20)
Text(item.title)
.fontSize(15)
}
.height(49)
.width('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor(Color.White)
}.width('100%').height(50)
})
}
}
}

View File

@ -0,0 +1,197 @@
import { authStore, HdNav } from '@itcast/basic';
import { applyListModel } from '../models/ApplyModel'
import HashMap from '@ohos.util.HashMap';
import { HdLoadingDialog } from '@itcast/basic'
import { BasicConstant,hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
import { BusinessError } from '@kit.BasicServicesKit';
import { Font, promptAction, router } from '@kit.ArkUI'
import { patientDbManager, PatientData } from '@itcast/basic';
interface callBackData {
code: string,
data: object,
msg: string,
message: string
}
interface paramsCallData {
model:applyListModel;
}
@Component
export struct PatientSetMsgPage {
@State params:paramsCallData = router.getParams() as paramsCallData;
@State noteName: string | undefined = '';
@State contentFrist:string | undefined = '';
@State groupName: string = '通过分组给患者分类';
@State maxDescribe:string = '0';
@State descibe:string = '';
@State isNote:boolean = false;
@State isDescibe:boolean = false;
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
customStyle: true,
alignment: DialogAlignment.Center
})
aboutToAppear(): void {
this.contentFrist = getFirstSegment(this.params.model.content)
}
patientMsgSubmit(){
const hashMap: HashMap<string, string> = new HashMap();
hashMap.set('patient_uuid',this.params.model.patientUuid);
hashMap.set('nickname',this.noteName);
hashMap.set('note',this.descibe);
this.dialog.open()
hdHttp.httpReq<string>(BasicConstant.updateNicknameNote,hashMap).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response relationRecordLately'+res);
let json:callBackData = JSON.parse(res+'') as callBackData;
if(json.code == '200') {
// 添加单个患者
const singlePatient: PatientData = {
uuid:this.params.model.patientUuid as string,
nickname: this.noteName as string,
mobile: this.params.model.mobile as string,
realName: this.params.model.realName as string,
nation: '',
sex: this.params.model.sex as number,
type: 1,
photo: this.params.model.photo as string,
expertUuid: authStore.getUser().uuid
};
const success1 = await patientDbManager.addPatient(singlePatient);
if (success1) {
console.info('添加成功');
const patients = await patientDbManager.getAllPatients();
promptAction.showToast({message:`现在一共是 ${patients.length} 个患者`})
} else {
console.info('添加失败');
}
promptAction.showToast({ message: '设置成功', duration: 1000 })
router.back()
} else {
console.error('患者申请记录列表失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.info(`Response fails: ${err}`);
})
}
build() {
Column() {
HdNav({ title: '设置备注和分组', showRightIcon: false, hasBorder: true })
Text('备注')
.margin({left:15,top:15})
.fontSize(15).fontColor('#333333')
TextInput({placeholder:'给患者添加备注名',text:this.noteName})
.fontSize(15).fontColor('#333333').placeholderColor('#999999')
.padding({left:10,right:10})
.width('calc(100% - 30vp)')
.height(50)
.backgroundColor('#f4f4f4')
.borderRadius(4)
.maxLength(20)
.margin({left:15,top:10})
.onChange((value:string)=>{
this.noteName = value;
if (value.length > 0) {
this.isNote = true;
}else {
this.isNote = false;
}
})
Row() {
Text('申请消息为:'+this.contentFrist)
.fontSize(15).fontColor('#666666')
Text('填入')
.fontSize(15).fontColor('#3CC7C0')
}.justifyContent(FlexAlign.Start).margin({left:15,top:5})
// .visibility(this.contentFrist?Visibility.Visible:Visibility.Hidden)
.onClick(()=>{
this.noteName = this.contentFrist?.substring(2);
})
Text('分组')
.margin({left:15,top:15})
.fontSize(15).fontColor('#333333')
Row(){
Text(this.groupName)
.fontSize(15).fontColor(this.groupName.includes('通过分组给患者分类')?'#999999':'#333333')
.margin({left:10})
.layoutWeight(1)
Image($r('sys.media.ohos_ic_public_arrow_right'))
.width(15).height(15).margin({right:10})
}
.height(50)
.width('calc(100% - 30vp)')
.backgroundColor('#f4f4f4')
.borderRadius(4)
.margin({left:15,top:10})
.onClick(()=>{
})
Text('描述')
.margin({left:15,top:15})
.fontSize(15).fontColor('#333333')
Column() {
TextArea({ placeholder: '补充患者关键信息,方便随访患者' })
.fontSize(15).placeholderColor('#999999')
.fontColor('#333333')
.backgroundColor('#f4f4f4')
.borderRadius(4)
.maxLength(100)
.padding({
left: 10,
top: 10,
right: 10,
bottom: 10
})
.width('100%').height(100)
.onChange((value: string) => {
this.maxDescribe = value.length.toString();
this.descibe = value;
if (value.length > 0) {
this.isDescibe = true;
} else {
this.isDescibe = false;
}
})
Text('已输入'+this.maxDescribe+'/100')
.fontSize(13).fontColor('#cccccc').textAlign(TextAlign.End).width('90%')
.margin({top:-20})
}
.margin({ left: 15,top: 10,}).width('calc(100% - 30vp)').height(120).borderRadius(4)
.layoutWeight(1)
Text('完成')
.width('100%').height(45)
.fontSize(18).fontColor(Color.White).textAlign(TextAlign.Center)
.backgroundColor(this.isNote||this.isDescibe?'#3CC7C0':'#cccccc')
.margin({bottom:10})
.onClick(()=>{
if (this.isNote || this.isDescibe) {
this.patientMsgSubmit();
}
})
}.justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Start)
.height('100%')
}
}
function getFirstSegment(content?: string): string | undefined {
if (!content) return undefined;
const segments: string[] = content.split(/[\uFF0C,]/);
return segments.find(seg => seg.trim() !== '');
}

View File

@ -0,0 +1,315 @@
import { authStore, HdNav, PositionSelectedSheet } from '@itcast/basic';
import { promptAction, router } from '@kit.ArkUI'
import { HdLoadingDialog } from '@itcast/basic'
import { BasicConstant,hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
import { BusinessError } from '@kit.BasicServicesKit';
import HashMap from '@ohos.util.HashMap';
import { groupRequest,groupRequestCall,groupModel,patientListModel } from '../models/PatientsGroupModel'
@Component
export struct PatientsGroup {
@State groupSort: string = '分组排序'
@State innerSort: string = '组内排序'
@State groupSortList:sortModel[] = [];
@State innerSortList:sortModel[] = [];
@State groupSortSelected: boolean = false//是否展开
@State innerSortSelected: boolean = false//是否展开
@State isGroupSelected: boolean = false//是否选中
@State IsInnerSelected: boolean = false//是否选中
@State isMaiLanHidden:boolean = false;//麦兰项目是否显示
@State group_sort:string = '0'
@State list_sort:string = '0'
@State groupListArray: groupModel[] = [];
@Consume@Watch('onRefreshAction') refreshFlag: boolean;
onRefreshAction(flag: boolean) {
this.getGroupData();
}
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
customStyle: true,
alignment: DialogAlignment.Center
})
aboutToAppear(): void {
this.getIsMaiLanData();
this.groupSortList = [{"name":"按首字母","isSeleted":false} as sortModel,{"name":"分组人数","isSeleted":false} as sortModel]
this.innerSortList = [{"name":"按首字母","isSeleted":false} as sortModel,{"name":"随访时间","isSeleted":false} as sortModel]
}
getGroupData(){
this.dialog.open()
hdHttp.post<string>(BasicConstant.groupList, {
expert_uuid: authStore.getUser().uuid,
group_sort:this.group_sort,
list_sort:this.list_sort
} as groupRequest).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response groupList'+res);
let json:groupRequestCall = JSON.parse(res+'') as groupRequestCall;
if(json.code == 1) {
this.groupListArray = []
this.groupListArray = json.data
} else {
console.error('患者分组列表失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.error(`Response fails: ${err}`);
})
}
getIsMaiLanData() {
const hashMap: HashMap<string, string> = new HashMap();
this.dialog.open()
hdHttp.httpReq<string>(BasicConstant.isMaiLanExpert,hashMap).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response isMaiLanExpert'+res);
let json:Record<string,string> = JSON.parse(res+'') as Record<string,string>;
if(json.code == '200') {
let isMaiLanExpert:string = json.isMaiLanExpert;
if (isMaiLanExpert == '1') {
this.isMaiLanHidden = true;
}
} else {
console.error('麦兰:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.info(`Response fails: ${err}`);
})
}
build() {
Column() {
HdNav({
title: '患者分组',
showRightIcon: false,
hasBorder: true,
rightText: '新建',
showRightText: true,
rightItemAction: () => {
router.pushUrl({
url: 'pages/PatientsPage/BuildOrEditGroupPage',
params:{"title":"新建分组"}
})
}
})
Stack() {
Row() {
Row() {
Text(this.groupSort)
.fontSize(16).fontColor(this.isGroupSelected ? $r('app.color.main_color') : '#333333')
Image(this.isGroupSelected ?$r('app.media.triangle_green_theme'):$r('app.media.triangle_normal')).width(10).height(10)
}
.width('50%')
.height(48)
.backgroundColor(Color.White)
.justifyContent(FlexAlign.Center)
.onClick(() => {
this.groupSortSelected = !this.groupSortSelected
this.innerSortSelected = false
})
Blank()
.width(1).height(20).margin({ top: 15 })
Row() {
Text(this.innerSort)
.fontSize(16).fontColor(this.IsInnerSelected ? $r('app.color.main_color') : '#333333')
Image(this.IsInnerSelected ?$r('app.media.triangle_green_theme'):$r('app.media.triangle_normal')).width(10).height(10)
}
.width('50%')
.height(48)
.backgroundColor(Color.White)
.justifyContent(FlexAlign.Center)
.onClick(() => {
this.innerSortSelected = !this.innerSortSelected
this.groupSortSelected = false
})
}.width('100%').height(55).backgroundColor('#f4f4f4')
List() {
ForEach(this.groupListArray, (sectionModel: groupModel,index:number) => {
ListItemGroup({ header: this.itemHeaderView(sectionModel,index) }) {
ForEach(sectionModel.isShow ? sectionModel.patientList : [], (rowModel: patientListModel) => {
ListItem() {
Stack() {
Row({ space: 15 }) {
Image(BasicConstant.urlImage + rowModel.photo)
.alt($r('app.media.userPhoto_default'))
.width(54)
.height(54)
.borderRadius(6)
.margin({ left: 15 })
Text(rowModel.nickname ? rowModel.nickname : rowModel.realName)
.fontSize(16).fontColor('#666666')
if (Number(rowModel.type) === 0) {
Image($r('app.media.group_vip'))
.objectFit(ImageFit.Cover)
.width(10).height(10)
}
}.width('100%').height(80)
Text('随访于' + rowModel.join_date?.substring(0, 10))
.fontSize(14)
.fontColor('#999999')
.textAlign(TextAlign.End)
.margin({ right: 15 })
.height(30)
Row()
.width('95%').height(0.5)
.backgroundColor('#999999')
}.width('100%').height(80).alignContent(Alignment.BottomEnd)
.onClick(()=>{
router.pushUrl({
url:'pages/PatientsPage/PatientDetailsPage',
params:{"patient_uuid":rowModel.uuid}
})
})
}.width('100%')
})
}
})
}
.width('100%')
.height('calc(100% - 55vp - 56vp)')
.backgroundColor('#f4f4f4')
.scrollBar(BarState.Off)
.sticky(StickyStyle.Header)
.margin({top:55})
List() {
ForEach(this.groupSortList, (item: sortModel) => {
ListItem() {
Column() {
Row() {
Text(item.name)
.fontSize(16)
.fontColor(item.isSeleted ? $r('app.color.main_color') : 'rgba(144,144,144)')
.margin({ left: 20 })
Blank()
if (item.isSeleted) {
Image($r('app.media.chose_card'))
.width(20).height(20).margin({ right: 25 })
}
}.width('100%').height(50).backgroundColor(Color.White)
Blank()
.width('100%').height(1).backgroundColor($r('app.color.main_color')).margin({left:20})
}.onClick(()=>{
this.isGroupSelected = true;
this.innerSortSelected = false
this.groupSortSelected = false
this.groupSort = String(item.name);
this.group_sort = item.name == '按首字母' ? '0' : '1'
this.groupSortList.forEach((element: sortModel) => {
element.isSeleted = false
})
const indexof = this.groupSortList.indexOf(item)
if (indexof !== -1) {
this.groupSortList[indexof].isSeleted = true
}
this.groupSortList = [...this.groupSortList]
this.getGroupData()
})
}
})
}.width('100%').height('calc(100% - 55vp)').backgroundColor('rgba(0,0,0,0.5)').margin({top:55})
.visibility(this.groupSortSelected?Visibility.Visible:Visibility.Hidden)
List() {
ForEach(this.innerSortList, (item: sortModel) => {
ListItem() {
Column() {
Row() {
Text(item.name)
.fontSize(16)
.fontColor(item.isSeleted ? $r('app.color.main_color') : 'rgba(144,144,144)')
.margin({ left: 20 })
Blank()
if (item.isSeleted) {
Image($r('app.media.chose_card'))
.width(20).height(20).margin({ right: 25 })
}
}.width('100%').height(50).backgroundColor(Color.White)
Blank()
.width('95%').height(1).backgroundColor($r('app.color.main_color'))
}
.onClick(()=>{
this.IsInnerSelected = true
this.innerSortSelected = false
this.groupSortSelected = false
this.innerSort = String(item.name);
this.list_sort = item.name == '按首字母' ? '0' : '1'
this.innerSortList.forEach((element: sortModel) => {
element.isSeleted = false
});
const indexof = this.innerSortList.indexOf(item)
if (indexof !== -1) {
this.innerSortList[indexof].isSeleted = true
}
this.innerSortList = [...this.innerSortList]
this.getGroupData()
})
}
})
}.width('100%').height('calc(100% - 55vp)').backgroundColor('rgba(0,0,0,0.5)').margin({top:55})
.visibility(this.innerSortSelected?Visibility.Visible:Visibility.Hidden)
Image($r('app.media.lifetime_right_icon'))
.width(76).height(40)
.position({ x: '80%', y: '80%' }) // 定位到右下角
.visibility(this.isMaiLanHidden?Visibility.Visible:Visibility.Hidden)
}.width('100%').height('calc(100% - 56vp)').backgroundColor('#f4f4f4').alignContent(Alignment.TopStart)
}
}
@Builder
itemHeaderView(model:groupModel,index:number) {
Column() {
Row() {
Image(model.isShow ? $r('app.media.group_turnDown') : $r('app.media.group_turnRight'))
.width(model.isShow ? 10 : 5).height(model.isShow ? 5 : 10).margin({ left: 15 })
Text(model.name + ' | ' + model.patientNum)
.fontSize(16)
.fontColor('#333333')
.margin({ left: 15 })
.layoutWeight(1)
Text('编辑')
.width(60)
.height(60)
.fontSize(15)
.fontColor('#981308')
.margin({ right: 15 })
.textAlign(TextAlign.End)
.visibility(model.name != '待分组患者'?Visibility.Visible:Visibility.Hidden)
.onClick(()=>{
router.pushUrl({
url: 'pages/PatientsPage/BuildOrEditGroupPage',
params:{"title":"编辑分组","group_uuid":model.uuid,"group_name":model.name}
})
})
}
.width('100%')
.height(60)
.onClick(() => {
let newModel = new groupModel(model);
newModel.isShow = !model.isShow;
this.groupListArray[index] = newModel;
this.groupListArray = [...this.groupListArray];
})
Blank()
.width('100%').height(1).backgroundColor('#666666')
}.width('100%').height(61).backgroundColor(Color.White)
}
}
export class sortModel {
name?:string;
isSeleted:boolean = false;
}

View File

@ -0,0 +1,179 @@
import { authStore, ChangeUtil, HdNav, PositionSelectedSheet, EmptyViewComp,HdLoadingDialog } from '@itcast/basic';
import { promptAction, router } from '@kit.ArkUI'
import { BasicConstant,hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
import { BusinessError } from '@kit.BasicServicesKit';
import HashMap from '@ohos.util.HashMap';
import { patientListModel } from '../models/PatientsGroupModel'
@Component
export struct PatientsListComp {
@State params:Record<string, string | patientListModel[]> = router.getParams() as Record<string, string | patientListModel[]>
@State patientsArray:patientListModel[] = []
@State patientsList:patientListModel[] = []
@State inputString:string = ''
@State naviRightTitle:string = '确定(0)'
@State isEmptyViewVisible: boolean = false; // 控制显隐的状态变量
aboutToAppear(): void {
this.getPatientsListData();
}
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
customStyle: true,
alignment: DialogAlignment.Center
})
getPatientsListData() {
const hashMap: HashMap<string, string> = new HashMap();
hashMap.set('group_uuid',String(this.params.group_uuid));
this.dialog.open()
hdHttp.httpReq<string>(BasicConstant.patientListNoInThisGroup,hashMap).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response patientListNoInThisGroup'+res);
let json:Record<string,string | patientListModel[]> = JSON.parse(res+'') as Record<string,string | patientListModel[]>;
if(json.code == '1') {
const patientsList = this.params?.selectedPatients as patientListModel[] | undefined;
if (patientsList?.length) {
const uuidSet = new Set(patientsList.map(item => item.uuid));
const dataArray = json.data as patientListModel[];
for (const model of dataArray) {
if (!uuidSet.has(model.uuid)) {
this.patientsList.push(model);
this.patientsArray.push(model);
}
}
} else {
this.patientsList = json.data as patientListModel[];
this.patientsArray = json.data as patientListModel[];
}
this.isEmptyViewVisible = this.patientsList.length>0?false:true
} else {
console.error('分组患者列表失败:'+json.message)
promptAction.showToast({ message: String(json.message), duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.info(`Response fails: ${err}`);
})
}
searchPatientAction(){
if (this.inputString.length > 0) {
this.patientsList = []
for (const model of this.patientsArray) {
if (model.realname?.includes(this.inputString) || model.mobile?.includes(this.inputString) || model.nickname?.includes(this.inputString)) {
this.patientsList.push(model)
}
}
} else {
this.patientsList = this.patientsArray
}
this.isEmptyViewVisible = this.patientsList.length>0?false:true
}
build() {
Column() {
HdNav({showLeftIcon:true,title:'选择患者',rightText:this.naviRightTitle,showRightText:true,rightTextColor:Color.White,rightBackColor:$r('app.color.main_color'),showRightIcon:false,rightItemAction:()=>{
router.back({
url:'pages/PatientsPage/BuildOrEditGroupPage',
params:{'selectedPatients':this.patientsList}
})
}})
Row(){
Row(){
TextInput({placeholder:'搜索患者的备注名、昵称或手机号'})
.fontSize(15)
.backgroundColor(Color.White)
.layoutWeight(1)
.onChange((value:string)=>{
this.inputString = value
})
.onSubmit(()=>{
this.searchPatientAction()
})
Blank()
.width(0.5)
.height(20)
.backgroundColor($r('app.color.main_color'))
Image($r('app.media.selected_hospital_ws'))
.width(30)
.height(30)
.margin({left:10,right:10})
.onClick(()=>{
this.searchPatientAction()
})
}
.width('95%')
.height(50)
.borderRadius(5)
.borderWidth(1)
.margin({left:10})
.borderColor($r('app.color.main_color'))
}
.backgroundColor(Color.White)
.width('100%')
.height(70)
if (this.isEmptyViewVisible) {
EmptyViewComp({promptText:'无搜索结果',isVisibility:this.isEmptyViewVisible})
.width('100%')
.height('calc(100% - 56vp - 70vp)')
} else {
List(){
ForEach(this.patientsList,(model:patientListModel)=>{
ListItem() {
this.patientListItem(model)
}
})
}
.width('100%')
.height('calc(100% - 56vp - 70vp)')
.backgroundColor('#f4f4f4')
.scrollBar(BarState.Off)
}
}
.width('100%')
.height('calc(100% - 56vp)')
.backgroundColor('#f4f4f4')
.justifyContent(FlexAlign.Start)
}
@Builder
patientListItem(item:patientListModel) {
Column() {
Row() {
Image(BasicConstant.urlImage + item.photo)
.alt($r('app.media.userPhoto_default'))
.borderRadius(6)
.width(50)
.height(50)
.margin({ left: 15 })
Text(item.nickname ? item.nickname : item.realname)
.fontSize(16)
.fontColor('#333333')
.margin({ left: 15 })
Blank()
Image(item.isSelected?$r('app.media.patiemts_list_selected'):$r('app.media.patients_list_noSelect'))
.width(22).height(22)
.objectFit(ImageFit.Fill)
.margin({ right: 15 })
}
.width('100%')
.height(80)
.backgroundColor(Color.White)
.onClick(()=>{
item.isSelected = !item.isSelected;
this.patientsList = [...this.patientsList];
const selectedNum = this.patientsList.filter(item => item.isSelected == true).length;
this.naviRightTitle = '确定('+selectedNum+')'
})
Blank()
.width('80%')
.height(1)
.backgroundColor(Color.Gray)
.margin({left:60})
}
}
}

View File

@ -0,0 +1,47 @@
export interface applyListCallBacl {
code:number,
msg:string,
data:applyListModel[],
message:string,
}
export interface applyHistoryCallBacl {
code:number,
msg:string,
data:historyObjectModel,
message:string,
}
export class applyListModel {
mobile?:string;
photo?:string;
birthDate?:string;
sex?:number;
realName?:string;
checkDate?:string;
uuid?:string;
createDate?:string;
patientUuid?:string;
expertUuid?:string;
status?:number;
content?:string;
}
export interface historyObjectModel {
list:historyModel[];
isFirstPage?:string;
isLastPage?:string;
pageNum?:string;
pages?:string;
pageSize?:string;
total?:string;
}
export class historyModel {
status?:string;//审核状态1.待审核2.审核通过3.拒绝4.已过期 5.患者取消 6专家解除
patient_photo?:string;
create_date?:string;
content?:string;
nickname?:string;
patient_name?:string;
}

View File

@ -0,0 +1,62 @@
export interface groupRequest {
expert_uuid:string,
group_sort:string,
list_sort:string,
}
export interface groupRequestCall {
code:number,
msg:string,
data:groupModel[],
message:string,
}
export class groupModel {
patientList:patientListModel[] = []
patientNum:number = 0
expert_uuid:string = ''
name:string = ''
type:number = 0
uuid:string = ''
isShow:boolean = false;
constructor(data: groupModel) {
this.patientList = data.patientList
this.patientNum = data.patientNum
this.expert_uuid = data.expert_uuid
this.name = data.name
this.type = data.type
this.uuid = data.uuid
this.isShow = data.isShow
}
}
export class patientListModel {
nickname?:string;
is_start?:string;
join_date?:string;
note?:string;
type?:string;
photo?:string;
birthDate?:string;
uuid?:string;
isEnable?:string;
height?:string;
ctdidId?:string;
mobile?:string;
nation?:string;
bloodType?:string;
fixedTelephone?:string;
mailingAddress?:string;
postalCode?:string;
detailed_address?:string;
weight?:string;
diagnosis?:string;
sex?:string;
provId?:string;
countyId?:string;
cityId?:string;
realName?:string;
realname?:string;
isSelected:boolean = false;
}

View File

@ -0,0 +1,72 @@
import { applyListModel,historyModel } from '../models/ApplyModel'
import { BasicConstant } from '@itcast/basic/Index'
@Component
export struct ApplyViews {
@Prop applyItme:applyListModel;
@Prop historyItem:historyModel;
@Prop isApply:boolean = true;//随访申请的样式还是申请记录的样式
private applyItemAction: (status: string,model:applyListModel) => void = () => {};
build() {
Row() {
Column(){
Row({space:10}){
Image(this.isApply?this.applyItme.photo:BasicConstant.urlImage+this.historyItem.patient_photo)
.alt($r('app.media.userPhoto_default'))
.width(50).height(50).borderRadius(5)
Column(){
Text(this.isApply?this.applyItme.createDate:this.historyItem.create_date)
.fontSize(14).fontColor('#333333').width('100%').textAlign(TextAlign.End)
if (!this.isApply) {
Text('昵称:'+this.historyItem.patient_name)
.fontSize(16).fontColor($r('app.color.main_color')).width('100%')
}
Text(this.isApply?this.applyItme.content:this.historyItem.content)
.fontSize(16).fontColor('#333333').width('100%').margin({top:this.isApply?10:0})
.maxLines(this.isApply?3:1).textOverflow({ overflow: TextOverflow.Ellipsis })
}.width('calc(100% - 60vp)')
}.width('calc(100% - 20vp)').margin({top:10,bottom:5}).alignItems(VerticalAlign.Top)
if (this.isApply) {
Row({ space: 40 }) {
Text('拒绝')
.fontColor($r('app.color.main_color'))
.borderColor($r('app.color.main_color'))
.customTextStyle()
.onClick(()=>this.applyItemAction('3',this.applyItme))
Text('同意')
.fontColor(Color.White)
.backgroundColor($r('app.color.main_color'))
.customTextStyle()
.onClick(()=>this.applyItemAction('2',this.applyItme))
}.padding({ top: 5, bottom: 10 }).justifyContent(FlexAlign.Center).width('calc(100% - 20vp)')
} else {
Row(){
if (this.historyItem.status == '2') {
Image($r('app.media.Patients_Apply_History_Status')).width(14).height(14)
Text('已同意').height(28).fontColor('#999999').fontSize(15)
} else if (this.historyItem.status == '3') {
Text('已拒绝').height(28).fontColor('#999999').fontSize(15)
} else if (this.historyItem.status == '4' || this.historyItem.status == '5') {
Text('已过期').height(28).fontColor('#999999').fontSize(15)
}
}.padding({ top: 5, bottom: 5 }).justifyContent(FlexAlign.End).width('calc(100% - 20vp)')
}
Blank()
.width('100%').height(1)
.backgroundColor('#f4f4f4')
}.width('100%').margin({left:10,right:10}).alignItems(HorizontalAlign.Start)
}.width('100%').backgroundColor(Color.White)
}
}
@Extend(Text)
function customTextStyle() {
.textAlign(TextAlign.Center)
.fontSize(15)
.borderRadius(4)
.borderWidth(0.5)
.width(77)
.height(30)
}

View File

@ -0,0 +1,11 @@
{
"module": {
"name": "patient",
"type": "har",
"deviceTypes": [
"default",
"tablet",
"2in1"
]
}
}

View File

@ -0,0 +1,8 @@
{
"float": [
{
"name": "page_text_font_size",
"value": "50fp"
}
]
}

View File

@ -0,0 +1,8 @@
{
"string": [
{
"name": "page_show",
"value": "page from package"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Some files were not shown because too many files have changed in this diff Show More