患者相关

This commit is contained in:
xiaoxiao 2025-07-25 13:38:42 +08:00
parent 6744eb1a78
commit abbd0540ab
39 changed files with 1527 additions and 281 deletions

View File

@ -14,3 +14,5 @@ export { ForwardMessageDialog } from './src/main/ets/view/ForwardMessageDialog'
export { TextMessageDetailDialog } from './src/main/ets/view/TextMessageDetailDialog'
export { MessageItemClick } from './src/main/ets/view/MessageItemClick'
export { TeachDialog } from './src/main/ets/view/TeachDialog'

View File

@ -92,3 +92,5 @@ export { ChatExtModel,ChatParam } from './src/main/ets/models/ChatExtModel'
export { PatientListModel,PatientsData } from './src/main/ets/models/PatientListModel'
export { applyListCallBacl, applyListModel, applyHistoryCallBacl , historyObjectModel, historyModel } from './src/main/ets/models/ApplyModel'
export { TripleOptionDialog } from './src/main//ets/Views/TripleOptionDialog'

View File

@ -53,7 +53,7 @@ export struct DefaultHintProWindows {
Text(this.confirmTitle)
.fontSize(15)
.fontColor(this.confirmTitleColor)
}.width('45%').height(30).backgroundColor(this.cancleColor)
}.width('45%').height(30).backgroundColor(this.confirmColor)
.onClick(() => {
this.selectedButton(1)
})

View File

@ -1,5 +1,5 @@
import { router } from "@kit.ArkUI";
import { promptAction, router } from "@kit.ArkUI";
import http from '@ohos.net.http'
import fileio from '@ohos.fileio'
import prompt from '@ohos.promptAction'
@ -8,11 +8,15 @@ import { BusinessError } from '@kit.BasicServicesKit';
import { BasicConstant } from "../constants/BasicConstant";
import { ViewImageInfo } from "../models/ViewImageInfo";
import { PermissionsUtils } from "../utils/PermissionsUtils";
import { fileIo, fileUri } from "@kit.CoreFileKit";
import { photoAccessHelper } from "@kit.MediaLibraryKit";
import fs from '@ohos.file.fs'
@Component
export struct PreviewPhotos {
private imageBuffer?: ArrayBuffer
@State
imgList: ViewImageInfo[]=[] // 传入图片数组
@State params:paramPhoto= router.getParams() as paramPhoto
@ -46,54 +50,85 @@ export struct PreviewPhotos {
}
}
// 下载图片方法伪代码需根据实际API实现
async downloadImage(url: string) {
// // 下载图片方法伪代码需根据实际API实现
// async downloadImage(url: string) {
// try {
// // 1. 检查权限
// const hasPermission = await this.checkStoragePermission();
// if (!hasPermission) {
// // 申请权限
// const granted = await this.requestStoragePermission();
// if (!granted) {
// prompt.showToast({ message: $r('app.string.netease_permission_denied_tips') });
// return;
// }
// }
//
// // 显示下载中提示
// prompt.showToast({ message: $r('app.string.netease_saving_image_tips') });
//
// // 2. 下载图片
// const httpRequest = http.createHttp()
// const response = await httpRequest.request(url, {
// method: http.RequestMethod.GET,
// expectDataType: http.HttpDataType.ARRAY_BUFFER,
// connectTimeout: 30000, // 30秒连接超时
// readTimeout: 30000, // 30秒读取超时
// })
// httpRequest.destroy()
//
// if (response.responseCode !== 200) {
// prompt.showToast({ message: $r('app.string.netease_download_failed_tips') })
// return
// }
//
// // 3. 写入到公共图片目录
// const fileName = 'img_' + Date.now() + '.jpg'
// const filePath = '/storage/media/100/local/photos/' + fileName
//
// try {
// const fd = await fileio.open(filePath, 0o2 | 0o100) // 写入+创建
// await fileio.write(fd, new Uint8Array(response.result as ArrayBuffer))
// await fileio.close(fd)
// prompt.showToast({ message: $r('app.string.netease_save_success_tips') })
// } catch (fileError) {
// console.error('文件写入失败:', fileError);
// prompt.showToast({ message: $r('app.string.netease_save_failed_tips') })
// }
// } catch (e) {
// console.error('下载图片失败:', e);
// prompt.showToast({ message: $r('app.string.netease_save_error_tips') })
// }
// }
async downloadImage(url: string,result: SaveButtonOnClickResult) {
if (result !== SaveButtonOnClickResult.SUCCESS) {
promptAction.showToast({ message: '权限获取失败', duration: 2000 })
return
}
const context = getContext(this) as common.UIAbilityContext
try {
// 1. 检查权限
const hasPermission = await this.checkStoragePermission();
if (!hasPermission) {
// 申请权限
const granted = await this.requestStoragePermission();
if (!granted) {
prompt.showToast({ message: $r('app.string.netease_permission_denied_tips') });
return;
}
}
// 显示下载中提示
prompt.showToast({ message: $r('app.string.netease_saving_image_tips') });
// 2. 下载图片
const httpRequest = http.createHttp()
const response = await httpRequest.request(url, {
method: http.RequestMethod.GET,
expectDataType: http.HttpDataType.ARRAY_BUFFER,
connectTimeout: 30000, // 30秒连接超时
readTimeout: 30000, // 30秒读取超时
expectDataType: http.HttpDataType.ARRAY_BUFFER
})
httpRequest.destroy()
this.imageBuffer = response.result as ArrayBuffer
const phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context)
const uri = await phAccessHelper.createAsset(
photoAccessHelper.PhotoType.IMAGE,
'jpg' // 文件扩展名
)
if (response.responseCode !== 200) {
prompt.showToast({ message: $r('app.string.netease_download_failed_tips') })
return
}
const file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
await fs.write(file.fd, this.imageBuffer)
await fs.close(file.fd)
// 3. 写入到公共图片目录
const fileName = 'img_' + Date.now() + '.jpg'
const filePath = '/storage/media/100/local/photos/' + fileName
try {
const fd = await fileio.open(filePath, 0o2 | 0o100) // 写入+创建
await fileio.write(fd, new Uint8Array(response.result as ArrayBuffer))
await fileio.close(fd)
prompt.showToast({ message: $r('app.string.netease_save_success_tips') })
} catch (fileError) {
console.error('文件写入失败:', fileError);
prompt.showToast({ message: $r('app.string.netease_save_failed_tips') })
}
} catch (e) {
console.error('下载图片失败:', e);
prompt.showToast({ message: $r('app.string.netease_save_error_tips') })
promptAction.showToast({ message: '图片已保存到相册', duration: 2000 })
} catch (error) {
const err = error as BusinessError
console.error(`保存失败: Code=${err.code}, Message=${err.message}`)
promptAction.showToast({ message: `保存失败: ${err.code}` })
}
}
@ -165,25 +200,29 @@ export struct PreviewPhotos {
.onClick(() => {
router.back()
})
Row()
{
Image($r('app.media.ic_topbar_save')).width(30).height(30)
.onClick(()=>{
this.downloadImage( this.imgList[this.previewIndex].url?(BasicConstant.urlHtml + this.imgList[this.previewIndex].url): this.imgList[this.previewIndex].url)
Row() {
SaveButton({icon:SaveIconStyle.FULL_FILLED,buttonType:ButtonType.Capsule})
.iconSize(25)
.iconColor($r('app.color.main_color'))
.backgroundColor('rgba(255,255,255,0.01)')
.width(50)
.height(30)
.onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
const url = this.imgList[this.previewIndex].url
? (BasicConstant.urlHtml + this.imgList[this.previewIndex].url)
: this.imgList[this.previewIndex].url;
this.downloadImage(url,result)
})
Blank()
Text(`${this.previewIndex + 1}/${this.imgList.length}`)
.fontSize(18)
.fontColor($r('app.color.top_title'))
}
.visibility(this.downLoad?Visibility.Visible:Visibility.Hidden)
.height(30)
.width('100%')
.padding({ left:20,right:20 })
.padding({ left:10,right:20 })
.margin({bottom:40})
.alignRules({bottom: { anchor: "__container__", align: VerticalAlign.Bottom }} )
}

View File

@ -0,0 +1,65 @@
@CustomDialog
export struct TripleOptionDialog {
controller: CustomDialogController; // 必须包含的控制器属性
@Prop title: string = ''
@Prop subTitle:string = ''
@Prop oneButtonTitle:string = ''
@Prop twoButtonTitle:string = ''
private buttonSelected: (actionType:string) => void = () => {};
// 按钮点击事件处理
private handleAction(actionType: string) {
this.buttonSelected(actionType)
this.controller.close(); // 关闭弹窗
}
build() {
Column() {
Text(this.title)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ top: 20 })
if (this.subTitle.length) {
Text(this.subTitle)
.fontSize(15)
.padding({top:5})
}
Column() {
Blank()
.width('100%')
.height(1)
.backgroundColor('#f4f4f4')
Text(this.oneButtonTitle)
.height(40)
.fontSize(14)
.fontColor('#333333')
.onClick(() => this.handleAction(this.oneButtonTitle))
Blank()
.width('100%')
.height(1)
.backgroundColor('#f4f4f4')
Text(this.twoButtonTitle)
.height(40)
.fontSize(14)
.fontColor('#333333')
.onClick(() => this.handleAction(this.twoButtonTitle))
Blank()
.width('100%')
.height(1)
.backgroundColor('#f4f4f4')
Text('取消')
.height(40)
.fontSize(14)
.fontColor('#999999')
.onClick(() => this.controller.close())
}
.width('100%')
.margin({ top:20,bottom: 20 })
}
.backgroundColor(Color.Transparent)
.borderRadius(16)
.width('100%')
}
}

View File

@ -38,6 +38,12 @@ export class BasicConstant {
static readonly updateNicknameNote = BasicConstant.urlExpertAPI+'updateNicknameNote'
static readonly applyListOperate = BasicConstant.urlExpert+'applyListOperate'
static readonly patientListNoInThisGroup = BasicConstant.urlExpertAPI+'patientListNoInThisGroup'
static readonly patientList = BasicConstant.urlExpert+'patientList'
static readonly listGroupSendMsg = BasicConstant.urlExpertAPI+'listGroupSendMsg'
static readonly delGroupSendMsg = BasicConstant.urlExpertAPI+'delGroupSendMsg'
static readonly addGroupSendMsg4YunXin = BasicConstant.urlExpertAPI+'addGroupSendMsg4YunXin'
static readonly addConditionRecord = BasicConstant.urlExpert+'addConditionRecord'
static readonly upConditionRecord = BasicConstant.urlExpert+'upConditionRecord'
static readonly patientCard = BasicConstant.urlExpertAPI+'patientCard'
static readonly toAddNickname = BasicConstant.urlExpert+'toAddNickname'
static readonly cancelRes = BasicConstant.urlExpert+'cancelRes'

View File

@ -9,6 +9,7 @@ import util from '@ohos.util';
import { i18n } from '@kit.LocalizationKit';
import { connection } from '@kit.NetworkKit';
import http from '@ohos.net.http'
import {BasicConstant} from '../constants/BasicConstant'
export class ChangeUtil {
/**
* 将HashMap转成JsonString
@ -98,67 +99,6 @@ export class ChangeUtil {
return bf
}
/**
* 将图片转换为base64字符串
* @param imageUri 图片URI
* @returns Promise<string> base64字符串
*/
static async imageToBase64(imageUri: string): Promise<string> {
// 1. 验证URI有效性
if (!imageUri || !imageUri.startsWith('file://')) {
throw new Error('无效的图片URI必须以file://开头');
}
let imageSource: image.ImageSource | undefined;
let pixelMap: image.PixelMap | undefined;
let imagePacker: image.ImagePacker | undefined;
try {
const file = fs.openSync(imageUri, fs.OpenMode.READ_ONLY);
const imageSource = image.createImageSource(file.fd);
if (!imageSource) {
throw new Error('创建ImageSource失败请检查图片路径');
}
logger.info('正在获取图片信息...');
const imageInfo = await imageSource.getImageInfo();
logger.info(`图片尺寸: ${imageInfo.size.width}x${imageInfo.size.height}`);
pixelMap = await imageSource.createPixelMap({
desiredSize: {
width: imageInfo.size.width,
height: imageInfo.size.height
}
});
if (!pixelMap) {
throw new Error('创建PixelMap失败');
}
// 5. 压缩图片
imagePacker = image.createImagePacker();
const packOpts: image.PackingOption = {
format: "image/jpeg",
quality: 80 // 适当提高质量保证清晰度
};
logger.info('正在压缩图片...');
const arrayBuffer = await imagePacker.packing(pixelMap, packOpts);
const unit8Array = new Uint8Array(arrayBuffer);
let binary = '';
unit8Array.forEach(byte => {
binary += String.fromCharCode(byte);
});
const base64String = Base64Util.encodeToStrSync(binary);
logger.info(`图片转换成功,大小: ${Math.round(base64String.length / 1024)}KB`);
return base64String;
} catch (error) {
logger.error('图片处理失败: ' + JSON.stringify(error));
throw new Error(`图片处理失败: ${error.message}`);
} finally {
// 7. 确保释放资源
try {
pixelMap?.release();
imageSource?.release();
imagePacker?.release();
} catch (e) {
logger.error('资源释放异常: ' + JSON.stringify(e));
}
}
}
static isLetter(char: string): boolean {
if (char.length !== 1) return false;
@ -244,4 +184,107 @@ export class ChangeUtil {
arr[arr.length - 1] = first; // 首位移至末尾
return arr;
}
/**
* 将URI或URL数组转换为Base64字符串数组
* @param items - 包含文件URI或网络URL的数组
* @returns Promise<string[]> - Base64字符串数组
*/
static async convertUrisOrUrlsToBase64(items: string[]): Promise<string[]> {
const results: string[] = [];
for (const item of items) {
try {
let arrayBuffer: ArrayBuffer;
let mimeType = 'image/jpeg'; // 默认MIME类型
// 处理本地文件URI
if (item.startsWith('file://')) {// || !item.includes('://')
arrayBuffer = await ChangeUtil.readLocalFile(item);
}
// 处理网络URL
else if (item.startsWith('http://') || item.startsWith('https://') || ChangeUtil.isImageFileByRegex(item)) {
arrayBuffer = await ChangeUtil.downloadNetworkResource(item);
}
// 处理其他类型资源
else {
throw new Error(`Unsupported URI scheme: ${item}`);
}
// 关键优化:添加图片压缩步骤[6,8](@ref)
const compressedBuffer = await ChangeUtil.compression(
arrayBuffer,
mimeType,
0.5 // 压缩质量为50%
);
// 转换为Base64
results.push(ChangeUtil.convertToBase64(compressedBuffer));
} catch (err) {
console.error(`转换失败: ${JSON.stringify(err)}`);
results.push(''); // 失败时返回空字符串
}
}
return results;
}
/**
* 读取本地文件到ArrayBuffer
* @param uri - 文件URI
* @returns Promise<ArrayBuffer>
*/
static async readLocalFile(uri: string): Promise<ArrayBuffer> {
try {
// 打开文件
const file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
// 获取文件大小
const stat = fs.statSync(file.fd);
const size = stat.size;
// 创建缓冲区并读取数据
const buffer = new ArrayBuffer(size);
fs.readSync(file.fd, buffer);
// 关闭文件
fs.closeSync(file);
return buffer;
} catch (err) {
throw new Error(`文件读取失败: ${JSON.stringify(err)}`);
}
}
/**
* 下载网络资源到ArrayBuffer
* @param url - 资源URL
* @returns Promise<ArrayBuffer>
*/
static async downloadNetworkResource(url: string): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
const httpRequest = http.createHttp();
httpRequest.request(
BasicConstant.urlImage+url,
{
method: http.RequestMethod.GET
},
(err, data) => {
httpRequest.destroy();
if (err) {
reject(new Error(`网络请求失败: ${JSON.stringify(err)}`));
return;
}
if (data.responseCode === 200) {
resolve(data.result as ArrayBuffer);
} else {
reject(new Error(`HTTP错误: ${data.responseCode}`));
}
}
)
})
}
static convertToBase64(buffer: ArrayBuffer): string {
const helper = new util.Base64Helper();
const uint8Array = new Uint8Array(buffer);
return helper.encodeToStringSync(uint8Array);
}
static isImageFileByRegex(path: string): boolean {
const pattern = /\.(jpg|jpeg|png|gif|bmp|webp)$/i;
return pattern.test(path);
}
}

View File

@ -23,8 +23,6 @@ export struct HomePage {
@State signData:Record<string,string> = {};
scroller:Scroller = new Scroller()
private hintWindowDialog!: CustomDialogController;
private signWindowDialog!:CustomDialogController;
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
@ -32,10 +30,8 @@ export struct HomePage {
alignment: DialogAlignment.Center
})
private hintPopWindowDialog() {
this.hintWindowDialog = new CustomDialogController({
hintWindowDialog: CustomDialogController = new CustomDialogController({
builder:DefaultHintProWindows({
controller:this.hintWindowDialog,
message:this.hintMessage,
cancleTitle:'',
confirmTitle:'关闭',
@ -49,15 +45,12 @@ export struct HomePage {
autoCancel:false,
backgroundColor: ('rgba(0,0,0,0.5)'),
})
}
private signPopWindowDialog(){
this.signWindowDialog = new CustomDialogController({
signWindowDialog:CustomDialogController = new CustomDialogController({
builder:SignPopWindow({
controller:this.signWindowDialog,
signDay:'今天是我们相识的第'+this.signData.gdxzday+'天',
signWeek:this.signData.totalDay,
signMouth:this.signData.continuous_day,
signDay:'今天是我们相识的第'+String(this.signData.gdxzday)+'天',
signWeek:String(this.signData.totalDay),
signMouth:String(this.signData.continuous_day),
signNews:this.signData.news['title'],
signHtml:this.signData.news['path'],
}),
@ -67,7 +60,6 @@ export struct HomePage {
backgroundColor: Color.Transparent,
backgroundBlurStyle: BlurStyle.NONE,
})
}
gotoTop() {
this.scroller.scrollToIndex(0);
@ -76,8 +68,6 @@ export struct HomePage {
aboutToAppear(): void {
this.initData()
this.hintPopWindowDialog();
this.signPopWindowDialog();
}
initData() {
@ -100,25 +90,25 @@ export struct HomePage {
}
getSignData() {
const hashMap: HashMap<string, string> = new HashMap();
const hashMap: HashMap<string, string> = new HashMap()
this.dialog.open()
hashMap.clear();
hashMap.set('score_type','1');
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>;
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();
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();
this.homeData.sign_in = '1'
this.hintMessage = '今日已签到,每日只能签到一次。\n请明日继续哦~'
this.hintWindowDialog.open()
}
}).catch((err: BusinessError) => {
this.dialog.close();
this.dialog.close()
})
}
@ -170,9 +160,7 @@ export struct HomePage {
searchItemAction:()=>{
router.pushUrl({
url:'pages/SearchPage/VideoSearchPage',
params: {
params:{'pageName':'视频'}
}
})
}
})

View File

@ -26,7 +26,7 @@ export struct OneSection {
@State oneSectionList: Array<MyPageSectionClass> = [
new MyPageSectionClass('oneItem', $r('app.media.my_page_patientAudit'), '患者审核', 'pages/PatientsPage/PatientPages',false),
new MyPageSectionClass('twoItem', $r('app.media.my_page_patientList'), '患者分组', 'pages/PatientsPage/PatientsGroupPage',false),
new MyPageSectionClass('threeItem', $r('app.media.my_page_message'), '群发消息', '/pages/MyHomePage',false),
new MyPageSectionClass('threeItem', $r('app.media.my_page_message'), '群发消息', 'pages/PatientsPage/GroupSendMessagePage',false),
new MyPageSectionClass('fourItem', $r('app.media.my_page_QrCode'), '随访二维码', 'pages/WebView/WebPage',false),
new MyPageSectionClass('fiveItem', $r('app.media.my_page_visitPlan'), '出诊计划', 'pages/Netease/OutpatientPage',false)
];

View File

@ -15,3 +15,5 @@ export { PatientsListComp } from './src/main/ets/components/PatientsListComp'
export { PatientDetailsComp } from './src/main/ets/components/PatientDetailsComp'
export { GroupManagementComp } from './src/main/ets/components/GroupManagementComp'
export { MassSendingComp } from './src/main/ets/components/MassSendingComp'

View File

@ -7,6 +7,8 @@
"license": "Apache-2.0",
"dependencies": {
"@itcast/basic": "file:../../commons/basic",
"refreshlib": "file:../../RefreshLib"
"refreshlib": "file:../../RefreshLib",
'@nimkit/chatkit': 'file:../../chatkit',
"@nimkit/chatkit_ui": 'file:../../chatkit_ui'
}
}

View File

@ -0,0 +1,263 @@
import { HMRouter, HMRouterMgr } from "@hadss/hmrouter";
import {
authStore,
BasicConstant,
ChangePhotoGrids, ChangeUtil,
hdHttp,
HdLoadingDialog,
HdNav,
HdResponse,
logger,
PhotoActionSheet, TimestampUtil, ViewImageInfo } from "@itcast/basic";
import { promptAction } from "@kit.ArkUI";
import { BusinessError } from "@kit.BasicServicesKit";
import { values } from "@nimsdk/vendor";
import { uri } from "@kit.ArkTS";
import { rcp } from "@kit.RemoteCommunicationKit";
@HMRouter({pageUrl:'AddAndEditRecordComp'})
@Component
export struct AddAndEditRecordComp {
@State photos: string[] = []
@State base64Array:string[] = []
@State maxSelectNumber: number = 8
private params: ESObject = HMRouterMgr.getCurrentParam()
private photoSheetDialog!: CustomDialogController;
@State nowDate:Date = new Date
@State creat_time:string = TimestampUtil.format(this.nowDate,'YYYY-MM-DD')
@State recordUuid:string = ''
@State inputContent:string = ''
@State
@Watch('onAddImg')
addImg: boolean=false
@State
@Watch('onRemoveImg')
removeImg: boolean=false
@State removeIndex: number = 0
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
customStyle: true,
alignment: DialogAlignment.Center
})
onAddImg() {
this.photoSheetDialog.open()
}
onRemoveImg() {
this.photos.splice(this.removeIndex, 1)
this.maxSelectNumber = 8 - this.photos.length;
}
aboutToAppear(): void {
this.initPhotoDialog()
if (this.params) {
if (this.params["model"]) {
const model:recordList = this.params["model"]
this.photos.push(...this.changeToImgs(model.photo))
this.inputContent = model.des
this.recordUuid = model.uuid
this.creat_time = model.create_date
this.maxSelectNumber = 8 - this.photos.length
ChangeUtil.convertUrisOrUrlsToBase64(model.photo).then(base64Array => {
console.info('转换结果:', base64Array+'转换个数:'+base64Array.length)
this.base64Array = base64Array
}).catch((err:BusinessError) => {
console.error('批量转换失败:', err)
})
}
}
}
submitData() {
if (ChangeUtil.stringIsUndefinedAndNull(this.creat_time)) {
promptAction.showToast({ message:'请选择日期', duration: 1000 })
return
}
if (ChangeUtil.stringIsUndefinedAndNull(this.inputContent)) {
promptAction.showToast({ message:'请描述患者病情', duration: 1000 })
return
}
this.dialog.open()
const requestUrl = this.recordUuid?BasicConstant.upConditionRecord:BasicConstant.addConditionRecord
const entity: rcp.MultipartForm = this.recordUuid? new rcp.MultipartForm({
"uuid":this.recordUuid,
"des":this.inputContent,
"create_date":this.creat_time
}) : new rcp.MultipartForm({
"expert_uuid":authStore.getUser().uuid,
"patient_uuid":this.params["patient_uuid"],
"des":this.inputContent,
"create_date":this.creat_time,
// "img1":this.base64Array[0]
})
this.base64Array.forEach((base64Str: string, index: number) => {
if (index < 8) {
entity.fields[`img${index + 1}`] = base64Str;
}
})
const session = rcp.createSession();
session.post(requestUrl, entity)
.then((response) => {
this.dialog.close();
logger.info('Response '+requestUrl+':'+response);
let json:Record<string,string | Record<string,string> | Array<Record<string,string>>> = JSON.parse(response+'') as Record<string,string | Record<string,string> | Array<Record<string,string>>>;
if(json.code == '1') {
HMRouterMgr.pop({param:{"isRefresh":"1"}})
promptAction.showToast({ message:'提交病情记录成功', duration: 1000 })
} 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() {
Column() {
HdNav({title:'病情记录',isLeftAction:true,showRightIcon:false,showRightText:true,rightText:'提交',rightItemAction:()=>{
this.submitData()
},leftItemAction:()=>{
HMRouterMgr.pop()
}})
this.contentView()
}
.width('100%')
}
@Builder
contentView() {
Row(){
Text('日期')
.fontColor($r('app.color.main_color'))
.margin({left:10})
.layoutWeight(1)
Text(this.creat_time)
.margin({right:10})
.onClick(()=>{
this.selectedData()
})
}
.width('100%')
.height(50)
.margin({top:5})
Blank()
.width('100%')
.height(0.5)
.margin({left:10})
.backgroundColor('#999999')
TextArea({
placeholder:'请描述患者病情',
text:this.inputContent
})
.backgroundColor(Color.White)
.margin({top:10})
.width('100%')
.height(150)
.onChange((values:string)=>{
this.inputContent = values
})
ChangePhotoGrids({
imgList:this.changeToImg(this.photos),
maxSelectNumber:8,
addImg:this.addImg,
removeImg:this.removeImg,
removeIndex:this.removeIndex
})
.height(200)
.padding({top:10})
.backgroundColor('#f4f4f4')
}
changeToImg( imgListurl:string[]) {
let imgListtmps:ViewImageInfo[]=[]
imgListurl.forEach((url: string) => {
let item = {uri:url} as ViewImageInfo
imgListtmps.push(item)
})
return imgListtmps
}
changeToImgs( imgListurl:string[])
{
let imgListtmps:string[]=[]
imgListurl.forEach((url: string) => {
let item = BasicConstant.urlHtml + url
imgListtmps.push(item)
})
return imgListtmps
}
private initPhotoDialog() {
this.photoSheetDialog = new CustomDialogController({
builder: PhotoActionSheet({
controller: this.photoSheetDialog,
maxSelectNumber:this.maxSelectNumber,
onPhotoSelected: async (uris: string[] | string) => {
let selectedUris: string[] = [];
if (Array.isArray(uris)) {
selectedUris = uris;
} else if (typeof uris === 'string') {
selectedUris = [uris];
}
this.photos.push(...selectedUris);
this.maxSelectNumber = 8 - this.photos.length
// ChangeUtil.convertUriToBase64(selectedUris[0]).then((base64)=>{
// this.base64Array = [base64]
// })
ChangeUtil.convertUrisOrUrlsToBase64(selectedUris).then(base64Array => {
console.info('转换结果:', base64Array+'转换个数:'+base64Array.length)
this.base64Array = base64Array
}).catch((err:BusinessError) => {
console.error('批量转换失败:', err)
})
}
}),
alignment: DialogAlignment.Bottom,
customStyle: true,
autoCancel: false,
backgroundColor: ('rgba(0,0,0,0.5)'),
height: '100%'
});
}
selectedData(){
CalendarPickerDialog.show({
selected: new Date(),
backgroundColor: Color.White,
backgroundBlurStyle: BlurStyle.NONE,
shadow: ShadowStyle.OUTER_FLOATING_SM,
onAccept: (value) => {
const today = new Date();
today.setHours(0, 0, 0, 0);
const selected = new Date(value);
selected.setHours(0, 0, 0, 0);
if (selected < today) {
promptAction.showToast({ message: '只能选择今天及以后的日期', duration: 1500 })
return
}
this.creat_time = TimestampUtil.format(value,'YYYY-MM-DD')
}
})
}
}
interface recordList {
create_date: string
des: string
patient_uuid: string
expert_uuid: string
uuid:string
photo:Array<string>
lineHeight:Length
}

View File

@ -1,22 +0,0 @@
import { HMRouter } from "@hadss/hmrouter";
@HMRouter({pageUrl:'AddRecordIllnessComp'})
@Component
export struct AddRecordIllnessComp {
@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

@ -82,7 +82,7 @@ export struct BuildOrEditGroupPage {
if(json.code == '1') {
promptAction.showToast({ message: '删除分组成功', duration: 1000 })
// router.back();
HMRouterMgr.pop()
HMRouterMgr.pop({param:{"nameString":true}})
} else {
console.error('删除患者分组列表失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
@ -114,8 +114,7 @@ export struct BuildOrEditGroupPage {
let json:Record<string,string> = JSON.parse(res+'') as Record<string,string>;
if(json.code == '1') {
promptAction.showToast({ message:'分组成功', duration: 1000 })
// router.back();
HMRouterMgr.pop()
HMRouterMgr.pop({param:{"nameString":true}})
} else if (json.code == '2') {
promptAction.showToast({ message:'该分组已存在', duration: 1000 })
} else {
@ -139,7 +138,7 @@ export struct BuildOrEditGroupPage {
showRightText: true,
isLeftAction:true,
leftItemAction:()=>{
HMRouterMgr.pop()
HMRouterMgr.pop({param:{"nameString":false}})
},
rightItemAction: () => {
if (this.params.title == '新建分组') {
@ -248,7 +247,7 @@ export struct BuildOrEditGroupPage {
.onClick(()=>{
this.hintWindowDialog.open();
})
.visibility(this.params.title == '新建分组'?Visibility.Hidden:Visibility.Visible)
.visibility(this.params.title == '新建分组'?Visibility.None:Visibility.Visible)
}.width('100%')
.height(120)
.justifyContent(FlexAlign.End)

View File

@ -48,7 +48,7 @@ export struct PatientApplyPage {
let json:applyHistoryCallBacl = JSON.parse(res+'') as applyHistoryCallBacl;
if(json.code == 200) {
this.historyArray = json.data.list;
this.totalPageNumer = Number(json.data.total);
this.totalPageNumer = Number(json.data.pages);
} else {
console.error('患者申请记录列表失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })

View File

@ -1,4 +1,4 @@
import { authStore, ChangeUtil, HdNav } from '@itcast/basic';
import { authStore, ChangeUtil, ChatParam, HdNav, preferenceStore } from '@itcast/basic';
import { promptAction } from '@kit.ArkUI'
import { HdLoadingDialog } from '@itcast/basic'
import { BasicConstant,hdHttp, HdResponse ,logger} from '@itcast/basic/Index'
@ -9,6 +9,7 @@ import { applyListModel } from '../models/ApplyModel'
import { TextExpandView } from '../views/TextExpandView'
import call from '@ohos.telephony.call'
import { HMLifecycleContext, HMRouter, HMRouterMgr, IHMLifecycle } from "@hadss/hmrouter"
import { ChatKitClient } from '@nimkit/chatkit';
@HMRouter({ pageUrl: 'PatientDetailsComp' })
@Component
@ -152,7 +153,6 @@ export struct PatientDetailsComp {
}
build() {
Row() {
Column() {
HdNav({
title: '患者详情',
@ -182,14 +182,12 @@ export struct PatientDetailsComp {
.justifyContent(FlexAlign.Start)
}
.width('100%')
.height('calc(100% - 56vp)')
.height('calc(100% - 106vp)')
.backgroundColor('#f4f4f4')
.scrollBar(BarState.Off)
.align(Alignment.TopStart)
}
.width('100%').height('100%')
}
.height('100%')
.width('100%')
}
@Builder
@ -324,9 +322,9 @@ export struct PatientDetailsComp {
.fontColor('#333333')
.margin({bottom:10})
Grid(){
Scroll() {
Row({ space: 10 }) {
ForEach(this.patientCase,(item:Record<string,string>)=>{
GridItem(){
Column(){
Text(String(item.createDate).substring(0,10))
.fontSize(15)
@ -341,14 +339,15 @@ export struct PatientDetailsComp {
.height(70)
.backgroundColor('#f4f4f4')
.borderRadius(3)
}
.padding({right:10})
.onClick(()=>{
HMRouterMgr.push({pageUrl:'InspectionReportComp',param:item})
})
})
}
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
}
.alignItems(HorizontalAlign.Start)
.backgroundColor(Color.White)
.width('100%')
@ -384,6 +383,13 @@ export struct PatientDetailsComp {
} else if (index == 2) {
HMRouterMgr.push({pageUrl:"RecordTheIllnessComp",
param:{"patient_uuid":this.params.patient_uuid}})
} else {
preferenceStore.setItemString('gdxz_consult_uuid',this.params.patient_uuid)
preferenceStore.setItemString('gdxz_sessionType',BasicConstant.general)
HMRouterMgr.push({ pageUrl: 'ChatP2PPage' , param: {
conversationId: ChatKitClient.nim.conversationIdUtil.p2pConversationId(this.params.patient_uuid
.toLowerCase())
} as ChatParam})
}
})
})

View File

@ -43,10 +43,10 @@ export struct PatientsGroup {
list_sort:this.list_sort
} as groupRequest).then(async (res: HdResponse<string>) => {
this.dialog.close();
this.groupListArray = []
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)

View File

@ -1,10 +1,10 @@
import { HdNav, EmptyViewComp,HdLoadingDialog } from '@itcast/basic';
import { HdNav, EmptyViewComp,HdLoadingDialog, authStore } from '@itcast/basic';
import { promptAction } 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'
import { HMRouter, HMRouterMgr } from "@hadss/hmrouter"
import { HMPopInfo, HMRouter, HMRouterMgr } from "@hadss/hmrouter"
@HMRouter({ pageUrl: 'PatientsListComp' })
@Component
@ -18,7 +18,12 @@ export struct PatientsListComp {
@State isEmptyViewVisible: boolean = false; // 控制显隐的状态变量
aboutToAppear(): void {
this.getPatientsListData();
const groupPatientsList = this.params?.selectedPatients as patientListModel[] | undefined
if (groupPatientsList?.length) {
this.getPatientsListData()
} else {
this.getAllPatientsListData()
}
}
dialog: CustomDialogController = new CustomDialogController({
@ -28,22 +33,22 @@ export struct PatientsListComp {
})
getPatientsListData() {
const hashMap: HashMap<string, string> = new HashMap();
hashMap.set('group_uuid',String(this.params.group_uuid));
const hashMap: HashMap<string, string> = new HashMap()
hashMap.set('group_uuid',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[]>;
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;
const patientsList = this.params?.selectedPatients as patientListModel[] | undefined
if (patientsList?.length) {
const uuidSet = new Set(patientsList.map(item => item.uuid));
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);
this.patientsList.push(model)
this.patientsArray.push(model)
}
}
} else {
@ -61,6 +66,27 @@ export struct PatientsListComp {
})
}
getAllPatientsListData() {
this.dialog.open()
hdHttp.post<string>(BasicConstant.patientList, {
"expertUuid": authStore.getUser().uuid
} as Record<string,string>).then(async (res: HdResponse<string>) => {
this.dialog.close()
logger.info('Response patientList'+res)
let json:Record<string,string | patientListModel[]> = JSON.parse(res+'') as Record<string,string | patientListModel[]>
if(json.code == '1') {
this.patientsList = json.data as patientListModel[];
this.patientsArray = 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}`);
})
}
searchPatientAction(){
if (this.inputString.length > 0) {
this.patientsList = []
@ -82,7 +108,21 @@ export struct PatientsListComp {
leftItemAction:()=>{
HMRouterMgr.pop()
},rightItemAction:()=>{
if (this.params.pageName) {
if (this.patientsList.length > 200) {
promptAction.showToast({message:'最多发送200个患者请重新选择',duration:1000})
return
}
HMRouterMgr.push({pageUrl:'SendGroupMessageComp',param:{'selectedPatients':this.patientsList}},{
onResult:(popInfo:HMPopInfo)=>{
if (popInfo && popInfo.result && popInfo.result["isPop"] !== undefined) {
HMRouterMgr.pop({param:{'isRefresh':true}})
}
}
})
} else {
HMRouterMgr.pop({param:{'selectedPatients':this.patientsList}})
}
// router.back({
// url:'pages/PatientsPage/BuildOrEditGroupPage',
// params:{'selectedPatients':this.patientsList}
@ -158,7 +198,7 @@ export struct PatientsListComp {
.width(50)
.height(50)
.margin({ left: 15 })
Text(item.nickname ? item.nickname : item.realname)
Text(item.nickname ? item.nickname : item.realname?item.realname:item.realName)
.fontSize(16)
.fontColor('#333333')
.margin({ left: 15 })

View File

@ -1,4 +1,4 @@
import { HMRouter, HMRouterMgr } from "@hadss/hmrouter";
import { HMPopInfo, HMRouter, HMRouterMgr } from "@hadss/hmrouter";
import { authStore, hdHttp, BasicConstant, HdNav, HdResponse, logger, HdLoadingDialog,
EmptyViewComp } from "@itcast/basic";
import { PullToRefreshLayout, RefreshController } from "refreshlib";
@ -60,7 +60,15 @@ export struct RecordTheIllnessComp {
build() {
Column() {
HdNav({isLeftAction:true,title:'病情记录',showRightText:false,rightIcon:$r('app.media.record_add_list'),rightItemAction:()=>{
HMRouterMgr.push({pageUrl:'AddRecordIllnessComp'})
HMRouterMgr.push({pageUrl:'AddAndEditRecordComp',param:{"patient_uuid":this.params.patient_uuid}},{
onResult:(popInfo:HMPopInfo)=>{
if (popInfo && popInfo.result && popInfo.result["isRefresh"] !== undefined) {
this.pageNumber = 1
this.recordList = []
this.getRecordListData()
}
}
})
},leftItemAction:()=>{
HMRouterMgr.pop()
}})
@ -104,11 +112,12 @@ export struct RecordTheIllnessComp {
@Builder
contentView(){
List({scroller:this.scroller}){
ForEach(this.recordList,(item:recordList)=>{
ForEach(this.recordList,(item:recordList,index:number)=>{
ListItem(){
Stack(){
Text()
.width(2)
.height(item.lineHeight ?? 0)
.backgroundColor($r('app.color.main_color'))
.margin({left:13})
Image($r('app.media.record_list_time_dian'))
@ -130,8 +139,7 @@ export struct RecordTheIllnessComp {
Column() {
Text(item.des)
.fontSize(16)
.width('100%')
.margin({left:35,right:15})
Grid() {
ForEach(item.photo, (photo: string) => {
GridItem() {
@ -143,23 +151,37 @@ export struct RecordTheIllnessComp {
.margin({ right: 10, bottom: 10 })
})
}
.width('100%')
.margin({top:20})
.margin({left:35,top:20,right:50})
Blank()
Text()
.width('100%')
.height(1)
.backgroundColor('#f4f4f4')
.margin({top: 10})
.height(0.5)
.backgroundColor('#999999')
.margin({left:15,top:10})
}
.margin({left:35,top:60,right:15})
.margin({top:60})
.alignItems(HorizontalAlign.Start)
.justifyContent(FlexAlign.Start)
}
.width('100%')
.alignContent(Alignment.TopStart)
.onAreaChange((oldVal, newVal) => {
this.recordList[index].lineHeight = newVal.height
this.recordList = [...this.recordList]
})
}
.width('100%')
.onClick(()=>{
HMRouterMgr.push({pageUrl:'AddAndEditRecordComp',param:{"model":item}},{
onResult:(popInfo:HMPopInfo)=>{
if (popInfo && popInfo.result && popInfo.result["isRefresh"] !== undefined) {
this.pageNumber = 1
this.recordList = []
this.getRecordListData()
}
}
})
})
})
}
.width('100%')
@ -180,4 +202,5 @@ interface recordList {
expert_uuid: string
uuid:string
photo:Array<string>
lineHeight:Length
}

View File

@ -0,0 +1,238 @@
import { authStore, HdNav, PositionSelectedSheet } from '@itcast/basic';
import { promptAction } 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'
import { HMRouterMgr, HMRouterPathInfo, HMRouterPathCallback, HMRouter, HMPopInfo } from "@hadss/hmrouter"
@HMRouter({pageUrl:'SelectedPatientGroupComp'})
@Component
export struct SelectedPatientGroupComp {
private params: ESObject = HMRouterMgr.getCurrentParam()
@State group_sort:string = '0'
@State list_sort:string = '0'
scroller:Scroller = new Scroller()
@State groupListArray: groupModel[] = []
@State patientsList: patientListModel[] = []
@State naviRightText:string = '确定(0)'
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
customStyle: true,
alignment: DialogAlignment.Center
})
aboutToAppear(): void {
this.getGroupData()
}
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();
this.groupListArray = []
logger.info('Response groupList'+res);
let json:groupRequestCall = JSON.parse(res+'') as groupRequestCall;
if(json.code == 1) {
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}`);
})
}
build() {
Column() {
HdNav({
title: '患者分组',
showRightIcon: false,
hasBorder: true,
rightText: this.naviRightText,
showRightText: true,
isLeftAction: true,
rightTextColor:Color.White,
rightBackColor:$r('app.color.main_color'),
leftItemAction:() => {
HMRouterMgr.pop()
},
rightItemAction: () => {
this.getSelectedPatients()
if (this.patientsList.length <= 0) {
promptAction.showToast({message:'请选择患者',duration:1000})
return
}
if (this.patientsList.length > 200) {
promptAction.showToast({message:'最多发送200个患者请重新选择',duration:1000})
return
}
HMRouterMgr.push({pageUrl:'SendGroupMessageComp',param:{'selectedPatients':this.patientsList}},{
onResult:(popInfo:HMPopInfo)=>{
if (popInfo && popInfo.result && popInfo.result["isPop"] !== undefined) {
HMRouterMgr.pop({param:{'isRefresh':true}})
}
}
})
}
})
this.contentView()
}
}
@Builder
contentView() {
Scroll(this.scroller) {
Column() {
List() {
ForEach(this.groupListArray, (sectionModel: groupModel, index: number) => {
ListItemGroup({ header: this.itemHeaderView(sectionModel, index) }) {
ForEach(sectionModel.isShow ? sectionModel.patientList : [], (rowModel: patientListModel,rowIndex:number) => {
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')
.layoutWeight(1)
Row() {
Image(rowModel.isSelected?$r('app.media.patiemts_list_selected'):$r('app.media.patients_list_noSelect'))
.width(22)
.height(22)
}
.width(60)
.height(60)
.justifyContent(FlexAlign.End)
.margin({ right: 15 })
}.width('100%').height(80)
Row()
.width('95%').height(0.5)
.backgroundColor('#999999')
}.width('100%').height(80).alignContent(Alignment.BottomEnd)
.onClick(() => {
this.groupListArray[index].patientList[rowIndex].isSelected = !this.groupListArray[index].patientList[rowIndex].isSelected
const allSelected = this.groupListArray[index].patientList.every(patient => patient.isSelected)
this.groupListArray[index].isSelected = allSelected
this.groupListArray = [...this.groupListArray]
this.updateNaviRightText()
})
}.width('100%')
})
}
})
}
.width('100%')
.scrollBar(BarState.Off)
.sticky(StickyStyle.Header)
Text('清空选择')
.fontColor($r('app.color.main_color'))
.borderWidth(1)
.borderRadius(5)
.fontSize(16)
.textAlign(TextAlign.Center)
.backgroundColor(Color.White)
.borderColor($r('app.color.main_color'))
.width('90%')
.height(45)
.margin({ top: 50,left:10,right:10 })
.onClick(()=>{
for (const group of this.groupListArray) {
group.isSelected = false
if (group.patientList) {
for (const patient of group.patientList) {
patient.isSelected = false
}
}
}
this.groupListArray = [...this.groupListArray]
this.updateNaviRightText()
})
}
}
.height('calc(100% - 55vp - 56vp)')
.align(Alignment.TopStart)
.backgroundColor('#f4f4f4')
}
@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)
Row() {
Image(model.isSelected?$r('app.media.patiemts_list_selected'):$r('app.media.patients_list_noSelect'))
.width(22)
.height(22)
}
.width(60)
.height(60)
.justifyContent(FlexAlign.End)
.margin({ right: 15 })
.onClick(()=>{
const newSelected = !this.groupListArray[index].isSelected
this.groupListArray[index].isSelected = newSelected
if (this.groupListArray[index].patientList) {
for (const patient of this.groupListArray[index].patientList) {
patient.isSelected = newSelected
}
}
this.groupListArray = [...this.groupListArray]
this.updateNaviRightText()
})
}
.width('100%')
.height(60)
.onClick(() => {
this.groupListArray[index].isShow = !this.groupListArray[index].isShow;
this.groupListArray = [...this.groupListArray];
})
Blank()
.width('100%').height(1).backgroundColor('#666666')
}.width('100%').height(61).backgroundColor(Color.White)
}
updateNaviRightText() {
let total = 0
for (const group of this.groupListArray) {
if (group.patientList) {
total += group.patientList.filter(patient => patient.isSelected).length
}
}
this.naviRightText = `确定(${total})`
}
getSelectedPatients() {
let result: patientListModel[] = []
for (const group of this.groupListArray) {
if (group.patientList) {
result = result.concat(group.patientList.filter(patient => patient.isSelected))
}
}
this.patientsList = result
}
}
export class sortModel {
name?:string;
isSeleted:boolean = false;
}

View File

@ -0,0 +1,471 @@
import { HMPopInfo, HMRouter, HMRouterMgr, IHMAnimator } from "@hadss/hmrouter"
import { BasicConstant,
ChangeUtil,
DefaultHintProWindows,
hdHttp, HdLoadingDialog, HdNav, HdResponse, logger, TripleOptionDialog } from "@itcast/basic"
import { patientListModel } from "../models/PatientsGroupModel"
import { display, promptAction } from "@kit.ArkUI"
import { HashMap } from "@kit.ArkTS"
import { BusinessError } from "@kit.BasicServicesKit"
import { camera, cameraPicker } from "@kit.CameraKit"
import { picker } from "@kit.CoreFileKit"
import { TeachDialog } from "@nimkit/chatkit_ui"
import { PerfactInputSheet } from "@itcast/basic/src/main/ets/Views/PerfactInputSheet"
import { NewWaDialog } from "@nimkit/chatkit_ui/src/main/ets/view/NewWaDialog"
@HMRouter({pageUrl:'SendGroupMessageComp'})
@Component
export struct SendGroupMessageComp {
private params: ESObject = HMRouterMgr.getCurrentParam()
@State patientsList:patientListModel[] = []
@State patientsName:string = ''
@State patient_user_uuid:string = ''
@State functionsVisible: boolean = false
@State inputValue: string = ''
@State msg_content: string = ''
@State screenWidth: number = vp2px(display.getDefaultDisplaySync().width)
@State isPossessList:boolean = false
dialogController: CustomDialogController = new CustomDialogController({
builder: TripleOptionDialog({ title: '温馨提示',subTitle:'',oneButtonTitle:'单独选择',twoButtonTitle:'分组选择',buttonSelected:(actionType:string)=>{
if (actionType == '单独选择') {
HMRouterMgr.push({pageUrl:'PatientsListComp',
param:{group_uuid:"",selectedPatients:[],pageName:"群发消息"}
},{
onResult:(popInfo:HMPopInfo)=>{
if (popInfo && popInfo.result && popInfo.result["isRefresh"] !== undefined) {
}
}
})
} else {
HMRouterMgr.push({pageUrl:'SelectedPatientGroupComp'
},{
onResult:(popInfo:HMPopInfo)=>{
if (popInfo && popInfo.result && popInfo.result["isRefresh"] !== undefined) {
}
}
})
}
}}),
alignment: DialogAlignment.Center,
offset: { dx: 0, dy: 0 },
autoCancel: true
})
dialog: CustomDialogController = new CustomDialogController({
builder: HdLoadingDialog({ message: '加载中...' }),
customStyle: true,
alignment: DialogAlignment.Center
})
outpatient:CustomDialogController = new CustomDialogController({
builder:PerfactInputSheet({
inputTitle:'提示',
inputPlaceholder:this.isPossessList?'您是否发送您的出/停诊公告?':'暂未设置停/出诊公告是否前往设置?',
style:'2',
okColor:$r('app.color.top_title'),
inputCallBack:(input: string,title:string)=>{
if (this.isPossessList) {
this.submintMessage("5")
} else {
HMRouterMgr.push({})
}
this.outpatient.close();
}
}),
alignment: DialogAlignment.Center,
customStyle: true,
autoCancel: false,
backgroundColor: ('rgba(0,0,0,0.5)'),
height: '100%'
})
teachDialog: CustomDialogController = new CustomDialogController({
builder: TeachDialog({
imgCallBack:()=>{
HMRouterMgr.push({pageUrl:'TuwenCompPage'},{
onResult: (popInfo: PopInfo) => {
const result = JSON.parse(String(popInfo.result)) as Record<string,string>
this.msg_content = result["gdxz_id"]
this.submintMessage("3")
}
})
},
videoCallBack:()=>{
HMRouterMgr.push({pageUrl:'VideoTeach'},{
onResult: (popInfo: PopInfo) => {
const result = JSON.parse(String(popInfo.result)) as Record<string,string>
this.msg_content = result["gdxz_id"]
this.submintMessage("4")
}
})
}
}),
cornerRadius: 4,
width: '70%',
})
waDialog: CustomDialogController = new CustomDialogController({
builder: NewWaDialog({
firstCallBack:()=> {
this.msg_content = "纽娃复合营养素固体饮料主要成分是:蜂花粉、乳清蛋白粉、灰树花粉、低聚木糖、蚕蛹氨基酸、麦芽粉、薏苡仁粉、烟酸、磷脂,以及其他调味品、辅助原料。科学配比制成,含有丰富的蛋白质、氨基酸、维生素、微量元素及其他营养元素,点击链接了解详情。"
this.submintMessage("6")
}
}),
cornerRadius: 4,
width: '70%',
})
aboutToAppear(): void {
const patients = this.params?.selectedPatients as patientListModel[] | undefined
const realname = this.params?.realname as string[] | string
const patient_uuid = this.params?.patient_uuid as string[] | string
if (patients?.length) {
for (const model of this.params?.selectedPatients as patientListModel[]) {
if (model.isSelected) {
this.patientsList.push(model)
this.patientsName = this.converNameToString(this.patientsList)
this.patient_user_uuid = this.converUuidToString(this.patientsList)
console.info('数组转字符串文字为:',this.patientsName)
}
}
}
if (realname) {
this.patientsName = realname as string
this.patient_user_uuid = patient_uuid as string
}
this.getStopOutPatientList()
}
submintMessage(type:string) {
const hashMap: HashMap<string, string> = new HashMap();
hashMap.set('msg_type',type)
hashMap.set('msg_content',this.msg_content)
hashMap.set('patient_user_uuid',this.patient_user_uuid)
this.dialog.open()
hdHttp.httpReq<string>(BasicConstant.addGroupSendMsg4YunXin,hashMap).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response addGroupSendMsg4YunXin'+res);
let json:Record<string,string> = JSON.parse(res+'') as Record<string,string>;
if(json.code == '200') {
promptAction.showToast({ message: '消息已发出', duration: 1000 })
// HMRouterMgr.pop({param:{"isPop":true},pageUrl:'MassSendingComp',navigationId:'GroupSendMessagePageNavigation'})//无用
HMRouterMgr.pop({param:{"isPop":true}})
} else {
console.error('群发消息失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.info(`Response fails: ${err}`);
})
}
getStopOutPatientList() {
const hashMap: HashMap<string, string> = new HashMap();
this.dialog.open()
hdHttp.httpReq<string>(BasicConstant.stopOutPatientList,hashMap).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response stopOutPatientList'+res);
let json:Record<string,string> = JSON.parse(res+'') as Record<string,string>;
if(json.code == '200') {
if (Array.isArray(json.data)) {
const data:Array<Record<string,string>> = json.data
if (data.length>0) {
this.isPossessList = true
} else {
this.getListOutPatient()
}
} else {
this.getListOutPatient()
}
} else {
console.error('停/出诊公告列表失败:'+json.message)
promptAction.showToast({ message: json.message, duration: 1000 })
}
}).catch((err: BusinessError) => {
this.dialog.close();
console.info(`Response fails: ${err}`);
})
}
getListOutPatient() {
const hashMap: HashMap<string, string> = new HashMap();
hashMap.set('page',"1")
this.dialog.open()
hdHttp.httpReq<string>(BasicConstant.listOutPatient,hashMap).then(async (res: HdResponse<string>) => {
this.dialog.close();
logger.info('Response listOutPatient'+res);
let json:Record<string,string> = JSON.parse(res+'') as Record<string,string>;
if(json.code == '200') {
if (Array.isArray(json.data)) {
const data:Array<Record<string,string>> = json.data
if (data.length>0) {
this.isPossessList = 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({isLeftAction:true,title:'群发消息',rightIcon:$r('app.media.group_message_navi_righr'),showRightIcon:true,showRightText:false,rightItemAction:()=>{
this.dialogController.open()
},leftItemAction:()=>{
HMRouterMgr.pop()
}})
this.contentView()
Blank().layoutWeight(1)
this.buildInputArea()
}
.width('100%')
.height('100%')
.backgroundColor('#f4f4f4')
.onClick(()=>{
this.functionsVisible = false
this.getUIContext().getFocusController().clearFocus()
})
}
@Builder
contentView() {
Column() {
Row() {
Image($r('app.media.addPatientApply_reminder_icon'))
.width(18).height(21)
Blank()
.width(1)
.backgroundColor('rgba(239,239,239,1)')
.margin({left:10, top: 10, bottom: 10 })
Text('若群发消息选择患者过多建议少于200个部分患者可能将延迟收到消息')
.fontSize(13).fontColor('#666666')
.margin({left:10,right:20})
}
.padding({left:10,top:10,bottom:10,right:20})
.width('100%')
.backgroundColor(Color.White)
Column() {
Blank()
.width('100%')
.height(3)
.backgroundColor($r('app.color.main_color'))
Text('消息将发送给'+this.patientsList.length+'位患者')
.fontSize(16)
.margin({top:10})
Text(this.patientsName)
.width('100%')
.fontSize(14)
.fontColor('#666666')
.padding({top:10,bottom:10})
}
// .width('90%')
.borderRadius(5)
.backgroundColor(Color.White)
.margin({top:10,left:10,right:10})
.alignItems(HorizontalAlign.Start)
.justifyContent(FlexAlign.Start)
}
.layoutWeight(1)
.margin({bottom:80})
}
@Builder
buildInputArea() {
Column() {
Row() {
TextArea({ placeholder: '输入内容...', text: this.inputValue })
.width('85%')
.flexGrow(1)
.padding({ left: 10, right: 10 })
.borderRadius(15)
.backgroundColor('#FFFFFF')
.constraintSize({ maxHeight: 150 })
.border({ width: 1, color: '#DDDDDD' })
.onChange((value:string)=>{
this.inputValue = value
this.msg_content = value
})
if (this.inputValue.length) {
Text('发送')
.textAlign(TextAlign.Center)
.fontSize(12)
.borderWidth(1)
.borderRadius(5)
.margin({ left: 8 })
.borderColor('#999999')
.backgroundColor('#f4f4f4')
.width(41)
.height(35)
.onClick(()=>this.submintMessage('1'))
} else {
Image($r('app.media.group_message_more_icon'))
.width(35)
.height(35)
.objectFit(ImageFit.Fill)
.margin({ left: 8 })
.onClick(() => {
this.hideKeyboard()
})
}
}
.padding(8)
.width('100%')
.alignItems(VerticalAlign.Bottom)
if (this.functionsVisible) {
this.buildFunctionButtons()
}
}
.width('100%')
.backgroundColor('rgba(0.98,0.98,0.98,1)')
.border({ width: 1, color: '#EEEEEE'})
.shadow({ radius: 4, color: '#1A000000', offsetX: 0, offsetY: -2 })
.margin({ bottom: 20 })
}
@Builder
buildFunctionButtons() {
Flex({ wrap: FlexWrap.Wrap }) {
this.buildFunctionButton('图片', $r('app.media.im_icon_images'), () => { this.onFunctionClick('图片'); })
this.buildFunctionButton('拍摄', $r('app.media.im_icon_camera'), () => { this.onFunctionClick('拍摄'); })
this.buildFunctionButton('快捷回复', $r('app.media.quck_message'), () => { this.onFunctionClick('快捷回复'); })
this.buildFunctionButton('患教', $r('app.media.patient_teach_call'), () => { this.onFunctionClick('患教'); })
this.buildFunctionButton('出/停诊公告', $r('app.media.outpatient_true'), () => { this.onFunctionClick('出/停诊公告'); })
this.buildFunctionButton('商城', $r('app.media.ytx_chattingfooter_shopping'), () => { this.onFunctionClick('商城'); })
}
.width('100%')
.padding({ top: 10, bottom: 10 })
.backgroundColor('rgba(0.96,0.96,0.96,1)')
}
@Builder
buildFunctionButton(text: string, iconString: Resource, onClick: () => void) {
Column() {
Image(iconString)
.width(50)
.height(50)
.objectFit(ImageFit.Fill)
Text(text)
.width('200%')
.fontSize(13)
.fontColor('#666666')
.textAlign(TextAlign.Center)
.margin({ top: 5 })
}
.width('25%')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Start)
.margin({ bottom: 20 })
.onClick(onClick)
}
onFunctionClick(functionName: string) {
if (functionName == '快捷回复') {
HMRouterMgr.push({pageUrl:'QuickMessagePage'},{
onResult: (popInfo: PopInfo) => {
const result = popInfo.result as string;
if (result == undefined) return
this.inputValue = result
}
})
} else if (functionName == '患教') {
this.teachDialog.open()
} else if (functionName == '图片') {
this.selectPhoto()
} else if (functionName == '拍摄') {
this.openSystemCamera()
} else if (functionName == '商城') {
this.waDialog.open()
} else {
this.outpatient.open()
}
}
private async openSystemCamera() {
try {
const pickerProfile: cameraPicker.PickerProfile = {
cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK,
videoDuration: 15
};
const result = await cameraPicker.pick(
getContext(),
[cameraPicker.PickerMediaType.PHOTO],
pickerProfile
);
if (result.resultCode === 0) {
ChangeUtil.convertUriToBase64(result.resultUri).then(base64 =>{
this.msg_content = base64
this.submintMessage("2")
})
}
} catch (error) {
console.error('Camera error:', error.code);
}
}
private selectPhoto() {
let photoSelectOptions = new picker.PhotoSelectOptions();
photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
photoSelectOptions.maxSelectNumber = 1;
let photoViewPicker = new picker.PhotoViewPicker();
photoViewPicker.select(photoSelectOptions)
.then((photoSelectResult) => {
console.info('PhotoViewPicker.select successfully, photoSelectResult uri: ' +
JSON.stringify(photoSelectResult))
if (photoSelectResult.photoUris && photoSelectResult.photoUris.length > 0) {
ChangeUtil.convertUriToBase64(photoSelectResult.photoUris[0]).then(base64 =>{
this.msg_content = base64
this.submintMessage("2")
})
}
})
.catch((err: BusinessError) => {
console.error('PhotoViewPicker.select failed with err: ' + err);
});
}
showKeyboard() {
this.functionsVisible = false
}
hideKeyboard() {
this.getUIContext().getFocusController().clearFocus()
this.functionsVisible = !this.functionsVisible
}
converNameToString(patients:patientListModel[]):string {
if (!patients?.length) return '[]';
const nameList = patients
.map(patient => {
return patient.nickname || patient.realname || patient.realName || ''
})
.filter(name => name.trim() !== '')
return nameList.join(',')
}
converUuidToString(patients:patientListModel[]):string {
if (!patients?.length) return '[]';
const nameList = patients
.map(patient => {
return patient.uuid || ''
})
.filter(name => name.trim() !== '')
return nameList.join(',')
}
}

View File

@ -53,4 +53,5 @@ export class historyModel {
content?:string;
nickname?:string;
patient_name?:string;
patient_uuid?:string
}

View File

@ -18,7 +18,8 @@ export class groupModel {
name:string = ''
type:number = 0
uuid:string = ''
isShow:boolean = false;
isShow:boolean = false
isSelected:boolean = false
constructor(data: groupModel) {
this.patientList = data.patientList

View File

@ -1,5 +1,6 @@
import { applyListModel,historyModel } from '../models/ApplyModel'
import { BasicConstant } from '@itcast/basic/Index'
import { HMRouterMgr } from '@hadss/hmrouter';
@Component
export struct ApplyViews {
@ -57,6 +58,11 @@ export struct ApplyViews {
.width('100%').height(1)
.backgroundColor('#f4f4f4')
}.width('100%').margin({left:10,right:10}).alignItems(HorizontalAlign.Start)
.onClick(()=>{
if (!this.isApply && this.historyItem.status == '2') {
HMRouterMgr.push({pageUrl:'PatientDetailsComp',param:{"patient_uuid":this.historyItem.patient_uuid}})
}
})
}.width('100%').backgroundColor(Color.White)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -21,6 +21,7 @@ interface callBackData {
struct FeedbackPage {
@State feedbackText: string = ''
controller:TextAreaController = new TextAreaController();
@State params:Record<string,string> = router.getParams() as Record<string,string>;
uploadChangePasswordAction() {
hdHttp.post<string>(BasicConstant.urlExpert + 'feedBack', {
@ -42,7 +43,7 @@ struct FeedbackPage {
build() {
Column() {
HdNav({ title: '意见反馈', showRightIcon: false, hasBorder: true })
HdNav({ title: this.params.title, showRightIcon: false, hasBorder: true })
// 输入框区域
TextArea({
placeholder:'欢迎对我们的软件提供建议,帮助我们更快更好地改进"肝胆相照"APP(200字以内)',

View File

@ -0,0 +1,41 @@
import { MassSendingComp } from 'patient'
import { HMDefaultGlobalAnimator, HMNavigation } from '@hadss/hmrouter';
import { AttributeUpdater } from '@kit.ArkUI';
class NavModifier extends AttributeUpdater<NavigationAttribute> {
initializeModifier(instance: NavigationAttribute): void {
instance.mode(NavigationMode.Stack);
instance.navBarWidth('100%');
instance.hideTitleBar(true);
instance.hideToolBar(true);
}
}
@Entry
@Component
struct GroupSendMessagePage {
@Provide refreshFlag:boolean = false;
modifier: NavModifier = new NavModifier();
onPageShow(): void {
this.refreshFlag = !this.refreshFlag;
}
build() {
Column() {
HMNavigation({
navigationId:"GroupSendMessagePageNavigation",
homePageUrl:'MassSendingComp',
options:{
standardAnimator:HMDefaultGlobalAnimator.STANDARD_ANIMATOR,
dialogAnimator:HMDefaultGlobalAnimator.DIALOG_ANIMATOR,
modifier:this.modifier
}
}) {
MassSendingComp()
}
}
.height('100%')
.width('100%')
}
}

View File

@ -1,11 +1,39 @@
import { PatientApplyPage } from 'patient'
import { HMDefaultGlobalAnimator, HMNavigation } from '@hadss/hmrouter';
import { AttributeUpdater } from '@kit.ArkUI';
class NavModifier extends AttributeUpdater<NavigationAttribute> {
initializeModifier(instance: NavigationAttribute): void {
instance.mode(NavigationMode.Stack);
instance.navBarWidth('100%');
instance.hideTitleBar(true);
instance.hideToolBar(true);
}
}
@Entry
@Component
struct PatientPages {
@Provide refreshFlag:boolean = false;
modifier: NavModifier = new NavModifier();
onPageShow(): void {
this.refreshFlag = !this.refreshFlag;
}
build() {
RelativeContainer() {
PatientApplyPage();
Column() {
HMNavigation({
navigationId:"PatientPagesNavigation",
homePageUrl:'PatientApplyPage',
options:{
standardAnimator:HMDefaultGlobalAnimator.STANDARD_ANIMATOR,
dialogAnimator:HMDefaultGlobalAnimator.DIALOG_ANIMATOR,
modifier:this.modifier
}
}) {
PatientApplyPage()
}
}
.height('100%')
.width('100%')

View File

@ -44,6 +44,7 @@
"pages/PatientsPage/GroupManagementPage",
"pages/WebView/WebPageSnapshot",
"pages/VideoPage/PLVMediaPlayerOnlyVideoPage",
"pages/Netease/OutpatientPage"
"pages/Netease/OutpatientPage",
"pages/PatientsPage/GroupSendMessagePage"
]
}