患者相关文件
This commit is contained in:
parent
971cd1c332
commit
4df444ed0e
@ -83,4 +83,6 @@ export { PhotoGrids } from './src/main/ets/components/PhotoGrids'
|
||||
|
||||
export { ViewImageInfo } from './src/main/ets/models/ViewImageInfo'
|
||||
|
||||
export { ChangePhotoGrids } from './src/main/ets/components/ChangePhotoGrids'
|
||||
export { ChangePhotoGrids } from './src/main/ets/components/ChangePhotoGrids'
|
||||
|
||||
export { InputPopWindow } from './src/main/ets/Views/InputPopWindow'
|
||||
53
commons/basic/src/main/ets/Views/InputPopWindow.ets
Normal file
53
commons/basic/src/main/ets/Views/InputPopWindow.ets
Normal file
@ -0,0 +1,53 @@
|
||||
@CustomDialog
|
||||
export struct InputPopWindow {
|
||||
controller: CustomDialogController; // 控制器(必须)
|
||||
@Prop title: string; // 提示语(从父组件传入)
|
||||
@Link inputValue: string; // 输入框值(双向绑定)
|
||||
|
||||
// 按钮回调函数(通过构造函数传入)
|
||||
private cancel?: () => void;
|
||||
private confirm?: (value: string) => void;
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
// 提示语标题
|
||||
Text(this.title)
|
||||
.fontSize(18)
|
||||
.margin({ top: 20, bottom: 15 });
|
||||
|
||||
// 输入框
|
||||
TextInput({ placeholder: '请输入内容', text: this.inputValue })
|
||||
.width('90%')
|
||||
.height(50)
|
||||
.onChange((value: string) => {
|
||||
this.inputValue = value; // 双向绑定更新值
|
||||
})
|
||||
.border({ width: 1, color: '#CCCCCC' })
|
||||
.borderRadius(4)
|
||||
|
||||
// 按钮行(取消 + 确定)
|
||||
Flex({ justifyContent: FlexAlign.SpaceAround }) {
|
||||
Button('取消')
|
||||
.backgroundColor('#FFFFFF')
|
||||
.fontColor('#666666')
|
||||
.onClick(() => {
|
||||
this.cancel?.(); // 触发取消回调
|
||||
this.controller.close(); // 关闭弹窗
|
||||
})
|
||||
|
||||
Button('确定')
|
||||
.backgroundColor('#317AFF')
|
||||
.fontColor('#FFFFFF')
|
||||
.onClick(() => {
|
||||
this.confirm?.(this.inputValue); // 传递输入值给父组件
|
||||
this.controller.close();
|
||||
})
|
||||
}
|
||||
.margin({ top: 20, bottom: 10 })
|
||||
.width('100%')
|
||||
}
|
||||
.width('100%')
|
||||
.padding(10)
|
||||
.borderRadius(16) // 圆角弹窗
|
||||
}
|
||||
}
|
||||
@ -40,6 +40,7 @@ export class BasicConstant {
|
||||
static readonly patientCard = BasicConstant.urlExpertAPI+'patientCard'
|
||||
static readonly toAddNickname = BasicConstant.urlExpert+'toAddNickname'
|
||||
static readonly patientDetail = BasicConstant.urlExpert+'patientDetail'
|
||||
static readonly GroupList = BasicConstant.urlExpertApp+'GroupList'
|
||||
static readonly getStartpage=BasicConstant.urlExpertApp + "startpage";
|
||||
static readonly meetingListV2=BasicConstant.urlExpertAPI + "meetingListV2";
|
||||
static readonly meetingV2Video=BasicConstant.urlExpertAPI + "meetingV2Video";
|
||||
|
||||
@ -14,4 +14,6 @@ export { BuildOrEditGroupPage } from './src/main/ets/components/BuildOrEditGroup
|
||||
|
||||
export { PatientsListComp } from './src/main/ets/components/PatientsListComp'
|
||||
|
||||
export { PatientDetailsComp } from './src/main/ets/components/PatientDetailsComp'
|
||||
export { PatientDetailsComp } from './src/main/ets/components/PatientDetailsComp'
|
||||
|
||||
export { GroupManagementComp } from './src/main/ets/components/GroupManagementComp'
|
||||
231
features/patient/src/main/ets/components/GroupManagementComp.ets
Normal file
231
features/patient/src/main/ets/components/GroupManagementComp.ets
Normal file
@ -0,0 +1,231 @@
|
||||
import { BasicConstant, hdHttp, HdResponse, authStore, HdNav , HdLoadingDialog, ChangeUtil,DefaultHintProWindows,InputPopWindow } from '@itcast/basic/Index'
|
||||
import { promptAction, router } from '@kit.ArkUI'
|
||||
import { groupModel } from '../models/PatientsGroupModel'
|
||||
import HashMap from '@ohos.util.HashMap';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
|
||||
@Component
|
||||
export struct GroupManagementComp {
|
||||
@State params:Record<string, string> = router.getParams() as Record<string, string>
|
||||
private hintWindowDialog!: CustomDialogController
|
||||
@State dialogInputValue: string = ''; // 绑定输入框的值
|
||||
// InputPopWindow: CustomDialogController; // 控制器实例
|
||||
@State groupList: Array<Record<string,string>> = []
|
||||
@State selectedGroups: Array<Record<string,string>> = []
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
customStyle: true,
|
||||
alignment: DialogAlignment.Center
|
||||
})
|
||||
|
||||
private hintPopWindowDialog() {
|
||||
this.hintWindowDialog = new CustomDialogController({
|
||||
builder:DefaultHintProWindows({
|
||||
controller:this.hintWindowDialog,
|
||||
message:'最多只能选三项',
|
||||
confirmTitleColor: '#333333',
|
||||
selectedButton: (index:number)=>{
|
||||
this.hintWindowDialog.close();
|
||||
}
|
||||
}),
|
||||
alignment: DialogAlignment.Center,
|
||||
cornerRadius:24,
|
||||
backgroundColor: ('rgba(0,0,0,0.5)'),
|
||||
})
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
this.hintPopWindowDialog()
|
||||
this.addShowTagAction()
|
||||
this.fetchGroups()
|
||||
}
|
||||
|
||||
addShowTagAction() {
|
||||
if (!ChangeUtil.stringIsUndefinedAndNull(this.params.groupNames)) {
|
||||
this.selectedGroups = convertToRecordArray(String(this.params.groupNames),String(this.params.groupUuids))
|
||||
}
|
||||
}
|
||||
|
||||
fetchGroups() {
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(BasicConstant.GroupList, {
|
||||
"expert_uuid": authStore.getUser().uuid
|
||||
} as Record<string,string>).then(async (res: HdResponse<string>) => {
|
||||
this.dialog.close();
|
||||
let json:Record<string,string | Array<Record<string,string>>> = JSON.parse(res+'') as Record<string,string | Array<Record<string,string>>>
|
||||
if(json.code == '1') {
|
||||
console.info('上一层传过来的group:',this.params.groupNames)
|
||||
// groupUuids
|
||||
this.groupList = json.data 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}`);
|
||||
})
|
||||
}
|
||||
|
||||
onSelectGroup(item: Record<string,string>) {
|
||||
const idx = this.selectedGroups.findIndex(g => g.uuid === item.uuid)
|
||||
if (idx > -1) {
|
||||
this.selectedGroups.splice(idx, 1)
|
||||
this.selectedGroups = [...this.selectedGroups]
|
||||
} else {
|
||||
if (this.selectedGroups.length >= 3) {
|
||||
this.hintWindowDialog.open()
|
||||
return
|
||||
}
|
||||
this.selectedGroups.push(item)
|
||||
this.selectedGroups = [...this.selectedGroups]
|
||||
}
|
||||
}
|
||||
|
||||
getSelected(item:Record<string,string>):boolean {
|
||||
let selected = this.selectedGroups.some(g => g.uuid === item.uuid)
|
||||
return selected
|
||||
}
|
||||
|
||||
isChangeColor(showItem:Record<string,string>):boolean {
|
||||
return this.selectedGroups.some(item=>`${item.uuid}` === `${showItem.uuid}`)
|
||||
}
|
||||
|
||||
onAddGroup() {
|
||||
|
||||
}
|
||||
|
||||
confirmAddGroup() {
|
||||
// if (!this.newGroupName.trim()) {
|
||||
// promptAction.showToast({ message: '请输入分组名', duration: 1000 })
|
||||
// return
|
||||
// }
|
||||
// if (this.newGroupName.length > 10) {
|
||||
// promptAction.showToast({ message: '最多10个字符', duration: 1000 })
|
||||
// return
|
||||
// }
|
||||
// this.addLoading = true
|
||||
// const params = {
|
||||
// expert_uuid: authStore.getUser().uuid,
|
||||
// name: this.newGroupName.trim(),
|
||||
// patient_uuid: ''
|
||||
// }
|
||||
// hdHttp.post<string>(BasicConstant.addGroup, params).then(async (res: HdResponse<string>) => {
|
||||
// this.addLoading = false
|
||||
// let json = JSON.parse(res + '') as { code: number, message: string }
|
||||
// if (json.code === 1) {
|
||||
// this.showAddDialog = false
|
||||
// this.addDialog.close()
|
||||
// this.fetchGroups()
|
||||
// promptAction.showToast({ message: '添加成功', duration: 1000 })
|
||||
// } else {
|
||||
// promptAction.showToast({ message: json.message, duration: 1000 })
|
||||
// }
|
||||
// }).catch(() => {
|
||||
// this.addLoading = false
|
||||
// })
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
HdNav({ title: '分组管理', showRightIcon: false, hasBorder: true, rightText: '保存', showRightText: true })
|
||||
// 已选分组
|
||||
Row() {
|
||||
Flex({ justifyContent: FlexAlign.Start, wrap: FlexWrap.Wrap }) {
|
||||
ForEach(this.selectedGroups, (item: Record<string, string>) => {
|
||||
Text(item.name)
|
||||
.border({ width: 1, color: $r('app.color.main_color') })
|
||||
.fontColor($r('app.color.main_color'))
|
||||
.fontSize(16)
|
||||
.borderRadius(10)
|
||||
.padding({
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 5,
|
||||
bottom: 5
|
||||
})
|
||||
.margin({ right: 10 })
|
||||
.borderRadius(20)
|
||||
})
|
||||
}
|
||||
}
|
||||
.alignItems(VerticalAlign.Top)
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.width('100%').height(100)
|
||||
.backgroundColor(Color.White)
|
||||
.padding({left:10,top:10,right:10})
|
||||
Column() {
|
||||
Row() {
|
||||
Text('所有分组').fontColor($r('app.color.main_color')).fontSize(15)
|
||||
Text('(选择或取消分组)').fontColor('#999999').fontSize(15)
|
||||
}
|
||||
.margin({ left: 10, top: 10 })
|
||||
.justifyContent(FlexAlign.Start)
|
||||
|
||||
Row() {
|
||||
Flex({ justifyContent: FlexAlign.Start, wrap: FlexWrap.Wrap }) {
|
||||
ForEach(this.groupList, (item: Record<string, string>) => {
|
||||
Text(item.name)
|
||||
.border({ width: 1, color: this.getSelected(item)||this.isChangeColor(item) ? '#981308' : '#999999' })
|
||||
.fontColor(this.getSelected(item)||this.isChangeColor(item) ? '#981308' : '#999999')
|
||||
.fontSize(16)
|
||||
.padding({
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 5,
|
||||
bottom: 5
|
||||
})
|
||||
.margin({ left: 10, top: 10})
|
||||
.borderRadius(10)
|
||||
.textAlign(TextAlign.Center)
|
||||
.backgroundColor(Color.White)
|
||||
.onClick(() => this.onSelectGroup(item))
|
||||
})
|
||||
}
|
||||
}
|
||||
.justifyContent(FlexAlign.Start)
|
||||
}
|
||||
.width('100%')
|
||||
.height('40%')
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.backgroundColor(Color.White)
|
||||
.margin({top:10})
|
||||
.layoutWeight(1)
|
||||
|
||||
Text('添加分组')
|
||||
.width('100%')
|
||||
.height(50)
|
||||
.fontSize(20)
|
||||
.fontColor(Color.White)
|
||||
.textAlign(TextAlign.Center)
|
||||
.backgroundColor('#3CC7C0')
|
||||
.margin({bottom:10})
|
||||
.onClick(()=>this.onAddGroup())
|
||||
}
|
||||
.height('100%')
|
||||
.backgroundColor('#f4f4f4')
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
}
|
||||
}
|
||||
|
||||
export function convertToRecordArray(
|
||||
namesStr: string,
|
||||
uuidsStr: string
|
||||
): Record<string, string>[] {
|
||||
const names: string[] = namesStr.split(",").map(item => item.trim());
|
||||
const uuids: string[] = uuidsStr.split(",").map(item => item.trim());
|
||||
|
||||
const maxLength: number = Math.max(names.length, uuids.length);
|
||||
const result: Record<string, string>[] = [];
|
||||
|
||||
for (let i = 0; i < maxLength; i++) {
|
||||
const name: string = i < names.length ? names[i] : "";
|
||||
const uuid: string = i < uuids.length ? uuids[i] : "";
|
||||
const newObject:Record<string,string> = {"name":name,"uuid":uuid} as Record<string,string>
|
||||
result.push(newObject);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -181,7 +181,7 @@ export struct PatientApplyPage {
|
||||
.onClick(()=>{
|
||||
router.pushUrl({
|
||||
url: 'pages/WebView/WebPage', // 目标url
|
||||
params: {url:BasicConstant.wxUrl+'expert/expertcodeimg?expert_uuid='+authStore.getUser().uuid,title:'我的二维码'}
|
||||
params: {url:BasicConstant.wxUrl+'expert/expertcodeimg?expert_uuid='+authStore.getUser().uuid,title:'随访二维码'}
|
||||
})
|
||||
})
|
||||
}.width('100%').height(56).backgroundColor(Color.White).alignItems(VerticalAlign.Top)
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import { authStore, HdNav, PositionSelectedSheet } from '@itcast/basic';
|
||||
import { promptAction, router } from '@kit.ArkUI'
|
||||
import { HdLoadingDialog,DefaultHintProWindows } from '@itcast/basic'
|
||||
import { authStore, ChangeUtil, HdNav } from '@itcast/basic';
|
||||
import { LevelMode, 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 { patientListModel } from '../models/PatientsGroupModel'
|
||||
import measure from '@ohos.measure';
|
||||
import { TextSectionAttribute,LastSpanAttribute } from '../utils/Models'
|
||||
import { applyListModel } from '../models/ApplyModel'
|
||||
import { TextExpandView } from '../views/TextExpandView'
|
||||
import call from '@ohos.telephony.call'
|
||||
|
||||
@Component
|
||||
export struct PatientDetailsComp {
|
||||
@ -16,10 +18,13 @@ export struct PatientDetailsComp {
|
||||
@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; // 是否显示操作按钮
|
||||
@State patientData2:applyListModel = {}
|
||||
@State patientGroupData:Record<string,string> = {}
|
||||
@State patientAge:string = ''
|
||||
@State nationName:string = ''
|
||||
@State addresString:string = ''
|
||||
@State medicalHistoryContent:TextSectionAttribute = new TextSectionAttribute()
|
||||
@State lastSpanAttribute:LastSpanAttribute = new LastSpanAttribute(0, 7, ['展开全部', '收起'], 15, $r('app.color.main_color'))
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
@ -50,6 +55,7 @@ export struct PatientDetailsComp {
|
||||
router.back()
|
||||
} else {
|
||||
if(json.code == '200') {
|
||||
this.patientGroupData = json
|
||||
this.getPatientDetailsData(String(json.group["name"]))
|
||||
} else {
|
||||
console.error('患者详情请求失败:'+json.message)
|
||||
@ -71,16 +77,8 @@ export struct PatientDetailsComp {
|
||||
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":""}]
|
||||
}
|
||||
this.getPatientData(groupType)
|
||||
} else {
|
||||
console.error('获取患者信息失败:'+json.message)
|
||||
promptAction.showToast({ message: String(json.message), duration: 1000 })
|
||||
@ -91,7 +89,7 @@ export struct PatientDetailsComp {
|
||||
})
|
||||
}
|
||||
|
||||
getPatientData() {
|
||||
getPatientData(groupType:string) {
|
||||
this.dialog.open()
|
||||
hdHttp.post<string>(BasicConstant.patientDetail, {
|
||||
"patientUuid":String(this.params.patient_uuid)
|
||||
@ -100,9 +98,46 @@ export struct PatientDetailsComp {
|
||||
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.patientData2 = json.data as applyListModel
|
||||
this.patientData2.note = String(this.patientGroupData.group["note"])
|
||||
this.patientData2.nickname = String(this.patientData.nickname)
|
||||
this.patientData2.groupType = String(this.patientGroupData.group["name"])
|
||||
this.patientData2.groupUuid = String(this.patientGroupData.group["uuid"])
|
||||
this.patientData2.patientUuid = String(this.patientData2.uuid)
|
||||
if (String(json.age) == '0') {
|
||||
this.patientAge = '0'
|
||||
} else if (String(json.age) == '-1') {
|
||||
this.patientAge = '未知'
|
||||
} else {
|
||||
this.patientAge = String(json.age)
|
||||
}
|
||||
if (ChangeUtil.stringIsUndefinedAndNull(String(this.patientData2.nationName))) {
|
||||
this.nationName = '未知'
|
||||
} else {
|
||||
this.nationName = String(this.patientData2.nationName)
|
||||
}
|
||||
let countyName = ChangeUtil.stringIsUndefinedAndNull(String(this.patientData2.countyName))?'':String(this.patientData2.countyName)
|
||||
let provName = ChangeUtil.stringIsUndefinedAndNull(String(this.patientData2.provName))?'':String(this.patientData2.provName)
|
||||
let cityName = ChangeUtil.stringIsUndefinedAndNull(String(this.patientData2.cityName))?'':String(this.patientData2.cityName)
|
||||
if (String(countyName) == String(cityName)) {
|
||||
this.addresString = String(provName)+String(cityName)
|
||||
} else {
|
||||
this.addresString = String(provName)+String(provName)+String(countyName)
|
||||
}
|
||||
if (this.addresString.length <= 0) {
|
||||
this.addresString = '未知'
|
||||
}
|
||||
let content = ChangeUtil.stringIsUndefinedAndNull(String(json.medicalHistoryContent))?'':String(json.medicalHistoryContent)
|
||||
this.medicalHistoryContent = new TextSectionAttribute(content, 2, '#666666', 15, 16, 350)
|
||||
this.patientCase = json.patientCase as Array<Record<string,string>>
|
||||
let nickname = this.patientData.nickname
|
||||
let note = this.patientData.note
|
||||
let mobile = this.patientData2.mobile
|
||||
if (ChangeUtil.stringIsUndefinedAndNull(String(nickname))) {
|
||||
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 })
|
||||
@ -130,50 +165,186 @@ export struct PatientDetailsComp {
|
||||
}
|
||||
})
|
||||
Scroll(this.scroller){
|
||||
this.historyView()
|
||||
this.footerView()
|
||||
}.width('100%').height('calc(100% - 56vp)').backgroundColor('#f4f4f4')
|
||||
Column(){
|
||||
this.patientsView()
|
||||
this.otherMsgView()
|
||||
this.historyView()
|
||||
if (this.patientCase.length > 0) {
|
||||
this.patientCaseView()
|
||||
}
|
||||
this.footerView()
|
||||
}
|
||||
.width('100%')
|
||||
.justifyContent(FlexAlign.Start)
|
||||
}
|
||||
.width('100%')
|
||||
.height('calc(100% - 56vp)')
|
||||
.backgroundColor('#f4f4f4')
|
||||
.scrollBar(BarState.Off)
|
||||
.align(Alignment.TopStart)
|
||||
}
|
||||
.width('100%').height('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
@Builder
|
||||
patientsView(){
|
||||
Row(){
|
||||
Image(BasicConstant.urlImage+this.patientData2.photo)
|
||||
.alt($r('app.media.userPhoto_default'))
|
||||
.width(60)
|
||||
.height(60)
|
||||
.borderRadius(6)
|
||||
.margin({left:15,top:15})
|
||||
Column(){
|
||||
Row({space:5}){
|
||||
Text(ChangeUtil.stringIsUndefinedAndNull(this.patientData.nickname)?this.patientData2.realName:this.patientData.nickname)
|
||||
.fontSize(18)
|
||||
.fontColor('#333333')
|
||||
Image(String(this.patientData2.sex) == '0'?$r('app.media.patient_details_man'):$r('app.media.patient_details_wuman'))
|
||||
.width(18)
|
||||
.height(18)
|
||||
}
|
||||
.margin({top:15})
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.alignItems(VerticalAlign.Top)
|
||||
if (!ChangeUtil.stringIsUndefinedAndNull(this.patientData.nickname)) {
|
||||
Text('昵称:'+String(this.patientData2.realName))
|
||||
.fontSize(14)
|
||||
.fontColor('#666666')
|
||||
.margin({top:8})
|
||||
}
|
||||
Text('年龄:'+this.patientAge+' | '+'民族:'+this.nationName)
|
||||
.fontSize(14)
|
||||
.fontColor('#666666')
|
||||
.margin({top:8})
|
||||
Text('城区:'+this.addresString)
|
||||
.fontSize(14)
|
||||
.fontColor('#666666')
|
||||
.margin({top:8,bottom:30})
|
||||
}
|
||||
.margin({left:15})
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
}
|
||||
.width('100%')
|
||||
.backgroundColor(Color.White)
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.alignItems(VerticalAlign.Top)
|
||||
.margin({bottom:15})
|
||||
}
|
||||
|
||||
@Builder
|
||||
otherMsgView(){
|
||||
List(){
|
||||
ForEach(this.groupArray,(item:Record<string,string>)=>{
|
||||
ListItem(){
|
||||
Row() {
|
||||
Text(item.title)
|
||||
.fontSize(15)
|
||||
.fontColor('#333333')
|
||||
.margin({left:15})
|
||||
.layoutWeight(1)
|
||||
Text(ChangeUtil.stringIsUndefinedAndNull(item.content)?item.prompt:item.content)
|
||||
.fontSize(15)
|
||||
.fontColor(!ChangeUtil.stringIsUndefinedAndNull(item.content)&&item.title == '电话号码'?$r('app.color.main_color'):'#666666')
|
||||
.textAlign(TextAlign.End)
|
||||
.margin({right:5})
|
||||
.maxLines(1)
|
||||
.textOverflow({overflow:TextOverflow.Ellipsis})
|
||||
.width('calc(100% - 100vp)')
|
||||
Image($r('app.media.course_invoice_to_details'))
|
||||
.width(6)
|
||||
.height(10)
|
||||
.margin({right:10})
|
||||
.visibility(item.title == '电话号码'?Visibility.Hidden:Visibility.Visible)
|
||||
}
|
||||
.width('100%')
|
||||
.height(49)
|
||||
.backgroundColor(Color.White)
|
||||
.onClick(()=>{
|
||||
if (item.title == '电话号码') {
|
||||
if (call.hasVoiceCapability() && !ChangeUtil.stringIsUndefinedAndNull(item.content)) {
|
||||
call.makeCall(item.content, (err) => {
|
||||
if (err) console.error("拨号失败:" + JSON.stringify(err));
|
||||
});
|
||||
}
|
||||
} else {
|
||||
router.pushUrl({
|
||||
url:'pages/PatientsPage/PatientMsgSetPage',
|
||||
params:{"model":this.patientData2}
|
||||
})
|
||||
}
|
||||
})
|
||||
}.width('100%').height(50)
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.margin({bottom:15})
|
||||
}
|
||||
|
||||
@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.medicalHistoryContent.title) {
|
||||
TextExpandView({
|
||||
textSectionAttribute: this.medicalHistoryContent,
|
||||
lastSpanAttribute: this.lastSpanAttribute
|
||||
})
|
||||
// 操作按钮(独立可点击区域)
|
||||
if (this.showExpandBtn) {
|
||||
Text(this.isExpanded ? "...收起" : "..展开全部")
|
||||
.fontSize(15)
|
||||
.fontColor($r('app.color.main_color')) // 红色标识可点击
|
||||
.onClick(() => {
|
||||
this.isExpanded = !this.isExpanded; // 切换状态
|
||||
})
|
||||
} else {
|
||||
Text('暂无')
|
||||
.fontSize(14)
|
||||
.fontColor('#666666')
|
||||
.width('100%')
|
||||
.textAlign(TextAlign.Start)
|
||||
}
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.backgroundColor(Color.White)
|
||||
.width('100%')
|
||||
.padding(15)
|
||||
.margin({bottom:15})
|
||||
}
|
||||
|
||||
@Builder
|
||||
patientCaseView(){
|
||||
Column(){
|
||||
Text('检查报告')
|
||||
.fontSize(15)
|
||||
.fontColor('#333333')
|
||||
.margin({bottom:10})
|
||||
|
||||
Grid(){
|
||||
ForEach(this.patientCase,(item:Record<string,string>)=>{
|
||||
GridItem(){
|
||||
Column(){
|
||||
Text(String(item.createDate).substring(0,10))
|
||||
.fontSize(15)
|
||||
.fontColor('#999999')
|
||||
Text(String(item.diseaseName))
|
||||
.fontSize(15)
|
||||
.fontColor('#333333')
|
||||
.margin({top:10})
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width(130)
|
||||
.height(70)
|
||||
.backgroundColor('#f4f4f4')
|
||||
.borderRadius(3)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.backgroundColor(Color.White)
|
||||
.width('100%')
|
||||
.padding(15)
|
||||
.margin({bottom:15})
|
||||
}
|
||||
|
||||
@Builder
|
||||
@ -186,6 +357,7 @@ export struct PatientDetailsComp {
|
||||
.width(20).height(20)
|
||||
Text(item.title)
|
||||
.fontSize(15)
|
||||
.fontColor('#333333')
|
||||
}
|
||||
.height(49)
|
||||
.width('100%')
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { authStore, HdNav } from '@itcast/basic';
|
||||
import { authStore, ChangeUtil, HdNav } from '@itcast/basic';
|
||||
import { applyListModel } from '../models/ApplyModel'
|
||||
import HashMap from '@ohos.util.HashMap';
|
||||
import { HdLoadingDialog } from '@itcast/basic'
|
||||
@ -20,14 +20,14 @@ interface paramsCallData {
|
||||
|
||||
@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;
|
||||
@State params:paramsCallData = router.getParams() as paramsCallData
|
||||
@State noteName: string | undefined = ChangeUtil.stringIsUndefinedAndNull(this.params.model.nickname)?'':String(this.params.model.nickname)
|
||||
@State contentFrist:string | undefined = ''
|
||||
@State groupName: string = ChangeUtil.stringIsUndefinedAndNull(this.params.model.groupType)?'通过分组给患者分类':String(this.params.model.groupType)
|
||||
@State maxDescribe:string = '0'
|
||||
@State descibe:string = ChangeUtil.stringIsUndefinedAndNull(this.params.model.note)?'':String(this.params.model.note)
|
||||
@State isNote:boolean = false
|
||||
@State isDescibe:boolean = false
|
||||
|
||||
dialog: CustomDialogController = new CustomDialogController({
|
||||
builder: HdLoadingDialog({ message: '加载中...' }),
|
||||
@ -108,16 +108,18 @@ export struct PatientSetMsgPage {
|
||||
}
|
||||
})
|
||||
|
||||
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(()=>{
|
||||
if (!ChangeUtil.stringIsUndefinedAndNull(this.contentFrist)) {
|
||||
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})
|
||||
@ -137,7 +139,10 @@ export struct PatientSetMsgPage {
|
||||
.borderRadius(4)
|
||||
.margin({left:15,top:10})
|
||||
.onClick(()=>{
|
||||
|
||||
router.pushUrl({
|
||||
url:'pages/PatientsPage/GroupManagementPage',
|
||||
params:{groupNames:this.params.model.groupType,groupUuids:this.params.model.groupUuid}
|
||||
})
|
||||
})
|
||||
|
||||
Text('描述')
|
||||
@ -145,7 +150,7 @@ export struct PatientSetMsgPage {
|
||||
.fontSize(15).fontColor('#333333')
|
||||
|
||||
Column() {
|
||||
TextArea({ placeholder: '补充患者关键信息,方便随访患者' })
|
||||
TextArea({ placeholder: '补充患者关键信息,方便随访患者',text:this.descibe })
|
||||
.fontSize(15).placeholderColor('#999999')
|
||||
.fontColor('#333333')
|
||||
.backgroundColor('#f4f4f4')
|
||||
|
||||
@ -25,6 +25,15 @@ export class applyListModel {
|
||||
expertUuid?:string;
|
||||
status?:number;
|
||||
content?:string;
|
||||
nationName?:string;
|
||||
provName?:string;
|
||||
cityName?:string;
|
||||
countyName?:string;
|
||||
nation?:string;
|
||||
note?:string
|
||||
nickname?:string
|
||||
groupType?:string
|
||||
groupUuid?:string
|
||||
}
|
||||
|
||||
export interface historyObjectModel {
|
||||
|
||||
218
features/patient/src/main/ets/utils/Models.ets
Normal file
218
features/patient/src/main/ets/utils/Models.ets
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// [Start RichTextModel]
|
||||
export class RichTextModel {
|
||||
// All the text
|
||||
text: string = '';
|
||||
// Array of information
|
||||
textArray: RichTextContentModel[] = [];
|
||||
// fontSize
|
||||
fontSize: number = 16;
|
||||
}
|
||||
|
||||
export class RichTextContentModel {
|
||||
// The index value of a single piece of information throughout the text
|
||||
index: number = 0;
|
||||
// The length of a single text (the agreed length in the case of an image)
|
||||
length: number = 0;
|
||||
// The type of text
|
||||
type: string = '';
|
||||
// images
|
||||
images: string[] = [];
|
||||
// content
|
||||
content: string = '';
|
||||
// Hyperlinks
|
||||
link: string = '';
|
||||
// fontColor
|
||||
fontColor: string = '#000';
|
||||
// fontSize
|
||||
fontSize: number = 16;
|
||||
// Image width
|
||||
imgWidth: number = 16;
|
||||
// Image height
|
||||
imgHeight: number = 16;
|
||||
// If the number of lines exceeds the limit, the entire message will be intercepted, and the content to be displayed will be intercepted
|
||||
shortContent: string = '';
|
||||
}
|
||||
// [End RichTextModel]
|
||||
|
||||
// [Start TextExpand_TabData]
|
||||
export class TabData {
|
||||
id: number;
|
||||
name: string | Resource;
|
||||
// ItemList: ItemData[] = [
|
||||
// new ItemData(),
|
||||
// new ItemData(),
|
||||
// new ItemData()
|
||||
// ];
|
||||
|
||||
constructor(id: number, name: string | Resource) {
|
||||
this.id = id;
|
||||
this.name = name
|
||||
}
|
||||
}
|
||||
|
||||
export class ItemData {
|
||||
// profileImg: Resource = $r('app.media.head_0');
|
||||
// profileImg1: Resource = $r('app.media.head_1');
|
||||
// rawTitle: Resource | string = $r('app.string.text_expand_long_title')
|
||||
// imgUrlList: Resource[] | string[] = [
|
||||
// $r('app.media.text_expand_img2'),
|
||||
// $r('app.media.text_expand_img3'),
|
||||
// $r('app.media.text_expand_img4')
|
||||
// ];
|
||||
// imgUrl: Resource | string = $r('app.media.text_expand_img2')
|
||||
// iconUrlList: Resource[] | string[] = [
|
||||
// $r('app.media.ic_pl_light'),
|
||||
// $r('app.media.ic_sc_light'),
|
||||
// $r('app.media.ic_dz_light'),
|
||||
// $r('app.media.ic_fx_light')
|
||||
// ]
|
||||
}
|
||||
// [End TextExpand_TabData]
|
||||
|
||||
// [Start RichTextExpandModel]
|
||||
/**
|
||||
* Rich text expands the view model
|
||||
* @param {RichTextContentModel[]} textContentArray - Textual content
|
||||
* @param {boolean} needProcess - Whether to display the Expand and collapse button
|
||||
* @param {exceedOneLine} boolean - When adding the word 'collapse', more than one line needs to be wrapped
|
||||
*/
|
||||
export class RichTextExpandModel {
|
||||
textContentArray: RichTextContentModel[] = [];
|
||||
needProcess: boolean = true;
|
||||
exceedOneLine: boolean = false;
|
||||
}
|
||||
|
||||
// [End RichTextExpandModel]
|
||||
|
||||
// [Start RichTextSectionAttribute]
|
||||
/**
|
||||
* Rich Text Attribute
|
||||
*
|
||||
* @param {ResourceStr} title - Textual content
|
||||
* @param {number} {maxLines} - maxLines
|
||||
* @param {ResourceStr} {fontColor} - fontColor
|
||||
* @param { Resource | number | string} {fontSize} - fontSize
|
||||
* @param { number } {imgWidth} - Image width
|
||||
* @param { number } {lineHeight} - Image height
|
||||
* @param {number} lineHeight - lineHeight
|
||||
* @param {Resource | number | string} contraintWidth - Sets the maximum width of the text on the line
|
||||
*/
|
||||
|
||||
export class RichTextSectionAttribute {
|
||||
title: ResourceStr = '';
|
||||
maxLines: number;
|
||||
fontColor: ResourceStr;
|
||||
fontSize: number;
|
||||
imgWidth: number;
|
||||
imgHeight: number;
|
||||
lineHeight: number;
|
||||
constraintWidth: number;
|
||||
|
||||
constructor(title: ResourceStr = '', maxLines: number = 3, fontColor: ResourceStr = '#000',
|
||||
fontSize: number = 16, imgWidth: number = 0, imgHeight: number = 0, lineHeight: number = 16,
|
||||
constraintWidth: number = 350) {
|
||||
this.title = title;
|
||||
this.maxLines = maxLines;
|
||||
this.fontColor = fontColor;
|
||||
this.fontSize = fontSize;
|
||||
this.imgWidth = imgWidth;
|
||||
this.imgHeight = imgHeight;
|
||||
this.lineHeight = lineHeight;
|
||||
this.constraintWidth = constraintWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// [End RichTextSectionAttribute]
|
||||
|
||||
// [Start LastSpanAttribute]
|
||||
/**
|
||||
* Text that controls text folding
|
||||
*
|
||||
* @param {number} lastSpanType - Type (0 for text)
|
||||
* @param {number} charactersNumber - The number of characters in the collapsed text or image
|
||||
* @param {ResourceStr[]} -Text or image content
|
||||
* @param {size} Text or image size
|
||||
* @param {color} color
|
||||
*/
|
||||
export class LastSpanAttribute {
|
||||
lastSpanType: number;
|
||||
charactersNumber: number;
|
||||
content: string[];
|
||||
size: ResourceStr | number;
|
||||
color: ResourceStr | Color;
|
||||
|
||||
constructor(lastSpanType: number, charactersNumber: number = 1,
|
||||
content: string[], size: ResourceStr | number, color: ResourceStr | Color = Color.Orange) {
|
||||
this.lastSpanType = lastSpanType;
|
||||
this.charactersNumber = charactersNumber;
|
||||
this.content = content;
|
||||
this.size = size;
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
// [End LastSpanAttribute]
|
||||
|
||||
// [Start TextExpandModel]
|
||||
/**
|
||||
* Plain text expands the view model
|
||||
* @param {ResourceStr} title - Textual content
|
||||
* @param {boolean} needProcess - Whether to display the Expand and collapse button
|
||||
* @param {exceedOneLine} boolean - When adding the word 'collapse', more than one line needs to be wrapped
|
||||
*/
|
||||
export class TextExpandModel {
|
||||
title: ResourceStr = '';
|
||||
needProcess: boolean = true;
|
||||
exceedOneLine: boolean = false;
|
||||
}
|
||||
|
||||
// [End TextExpandModel]
|
||||
|
||||
// [Start TextSectionAttribute]
|
||||
/**
|
||||
* Plain Text Attribute
|
||||
*
|
||||
* @param {ResourceStr} title - Textual content
|
||||
* @param {number} {maxLines} - maxLines
|
||||
* @param {ResourceStr} {fontColor} - fontColor
|
||||
* @param { Resource | number | string} {fontSize} - fontSize
|
||||
* @param {number} lineHeight - lineHeight
|
||||
* @param {Resource | number | string} contraintWidth - Sets the maximum width of the text on the line
|
||||
*/
|
||||
|
||||
export class TextSectionAttribute {
|
||||
title: ResourceStr = '';
|
||||
maxLines: number;
|
||||
fontColor: ResourceStr;
|
||||
fontSize: Resource | number | string;
|
||||
lineHeight: number;
|
||||
constraintWidth: Resource | number | string;
|
||||
|
||||
constructor(title: ResourceStr = '', maxLines: number = 2, fontColor: ResourceStr = '#666666',
|
||||
fontSize: Resource | number | string = '15vp', lineHeight: number = 16,
|
||||
constraintWidth: Resource | number | string = 350) {
|
||||
this.title = title;
|
||||
this.maxLines = maxLines;
|
||||
this.fontColor = fontColor;
|
||||
this.fontSize = fontSize;
|
||||
this.lineHeight = lineHeight;
|
||||
this.constraintWidth = constraintWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// [End TextSectionAttribute]
|
||||
241
features/patient/src/main/ets/utils/TextUtils.ets
Normal file
241
features/patient/src/main/ets/utils/TextUtils.ets
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// [Start TextUtils]
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { RichTextContentModel, RichTextModel, RichTextSectionAttribute, TextSectionAttribute } from './Models';
|
||||
import { text } from '@kit.ArkGraphics2D';
|
||||
|
||||
const suffix: string = '...';
|
||||
|
||||
export class TextUtils {
|
||||
/**
|
||||
* Gets the collapsed short paragraph string
|
||||
*
|
||||
* @param uiContext UI Context
|
||||
* @param textSectionAttribute Plain Text Attribute
|
||||
* @param lastSpan Expand the collapse button text
|
||||
* @returns Short paragraph strings
|
||||
*/
|
||||
// [Start TextUtils_getShortText]
|
||||
public static getShortText(uiContext: UIContext, textSectionAttribute: TextSectionAttribute, lastSpan: string): string {
|
||||
let text = TextUtils.getStringFromResource(uiContext, textSectionAttribute.title);
|
||||
const minLinesTextSize: SizeOptions | undefined = uiContext?.getMeasureUtils().measureTextSize({
|
||||
textContent: text,
|
||||
fontSize: textSectionAttribute.fontSize,
|
||||
maxLines: textSectionAttribute.maxLines,
|
||||
wordBreak: WordBreak.BREAK_ALL,
|
||||
constraintWidth: textSectionAttribute.constraintWidth
|
||||
});
|
||||
const minHeight: Length | undefined = minLinesTextSize?.height;
|
||||
if (minHeight === undefined) {
|
||||
return '';
|
||||
}
|
||||
// Use the dichotomy to find strings that are exactly two lines in length
|
||||
let textStr: string[] = Array.from(text); //Split the string to avoid special characters and inconsistent sizes
|
||||
let leftCursor: number = 0;
|
||||
let rightCursor: number = textStr.length;
|
||||
let cursor: number = Math.floor(rightCursor / 2);
|
||||
let tempTitle: string = '';
|
||||
while (true) {
|
||||
tempTitle = text.substring(0, cursor) + suffix + lastSpan;
|
||||
const currentLinesTextSize: SizeOptions | undefined = uiContext?.getMeasureUtils().measureTextSize({
|
||||
textContent: tempTitle,
|
||||
fontSize: textSectionAttribute.fontSize,
|
||||
wordBreak: WordBreak.BREAK_ALL,
|
||||
constraintWidth: textSectionAttribute.constraintWidth
|
||||
});
|
||||
const currentLineHeight: Length | undefined = currentLinesTextSize?.height;
|
||||
if (currentLineHeight === undefined) {
|
||||
return '';
|
||||
}
|
||||
if (currentLineHeight > minHeight) {
|
||||
// The current character has exceeded two lines, continue to look to the left
|
||||
rightCursor = cursor;
|
||||
cursor = leftCursor + Math.floor((cursor - leftCursor) / 2);
|
||||
} else {
|
||||
// The current character is less than two lines, it may be OK, but you still need to look to the right
|
||||
leftCursor = cursor;
|
||||
cursor += Math.floor((rightCursor - cursor) / 2);
|
||||
}
|
||||
if (Math.abs(rightCursor - leftCursor) <= 1) {
|
||||
// The two pointers basically coincide, which means that they have been found
|
||||
break;
|
||||
}
|
||||
}
|
||||
return text.substring(0, cursor) + suffix;
|
||||
}
|
||||
|
||||
// [End TextUtils_getShortText]
|
||||
|
||||
// [Start TextUtils_getStringFromResource]
|
||||
public static getStringFromResource(uiContext: UIContext, source: Resource | string): string {
|
||||
try {
|
||||
if (typeof source === 'string') {
|
||||
return source;
|
||||
}
|
||||
if (uiContext?.getHostContext()) {
|
||||
return uiContext?.getHostContext()!.resourceManager.getStringSync(source);
|
||||
}
|
||||
return '';
|
||||
} catch (error) {
|
||||
let code = (error as BusinessError).code;
|
||||
let message = (error as BusinessError).message;
|
||||
console.log('getStringFromResource' + code + message);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// [End TextUtils_getStringFromResource]
|
||||
|
||||
/**
|
||||
* Set up paragraph layout
|
||||
* @param uiContext UI Context
|
||||
* @param contentArray Typography content
|
||||
* @param fontSize
|
||||
* @param textWidth
|
||||
*/
|
||||
public static getParagraph(uiContext: UIContext, contentArray: RichTextContentModel[], fontSize: number,
|
||||
textMaxWidth: number): text.Paragraph {
|
||||
// Set up paragraph layout
|
||||
// [Start TextUtils_paragraphBuilder]
|
||||
let myTextStyle: text.TextStyle = {
|
||||
fontSize: uiContext?.fp2px(fontSize)
|
||||
};
|
||||
|
||||
let myParagraphStyle: text.ParagraphStyle = {
|
||||
textStyle: myTextStyle,
|
||||
align: text.TextAlign.START,
|
||||
maxLines: 300, // Just specify a large enough number of rows
|
||||
breakStrategy: text.BreakStrategy.GREEDY,
|
||||
wordBreak: text.WordBreak.BREAK_WORD
|
||||
};
|
||||
|
||||
let fontCollection = new text.FontCollection();
|
||||
let paragraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);
|
||||
// [End TextUtils_paragraphBuilder]
|
||||
contentArray.forEach((item, index) => {
|
||||
if (item.type === 'topic') {
|
||||
// The text specifies the style
|
||||
paragraphGraphBuilder.pushStyle({
|
||||
fontSize: fontSize,
|
||||
});
|
||||
paragraphGraphBuilder.addText(item.content);
|
||||
} else if (item.type === 'images') {
|
||||
item.images.forEach(() => {
|
||||
// Add a placeholder to specify the style
|
||||
// [Start TextUtils_addPlaceholder]
|
||||
paragraphGraphBuilder.addPlaceholder({
|
||||
width: item.imgWidth,
|
||||
height: item.imgHeight,
|
||||
align: text.PlaceholderAlignment.BOTTOM_OF_ROW_BOX,
|
||||
baseline: text.TextBaseline.IDEOGRAPHIC,
|
||||
baselineOffset: 0
|
||||
});
|
||||
// [End TextUtils_addPlaceholder]
|
||||
});
|
||||
|
||||
} else if (item.type === 'link') {
|
||||
// [Start TextUtils_addText]
|
||||
paragraphGraphBuilder.pushStyle({
|
||||
fontSize: fontSize,
|
||||
});
|
||||
paragraphGraphBuilder.addText(item.content);
|
||||
// [End TextUtils_addText]
|
||||
} else {
|
||||
paragraphGraphBuilder.pushStyle({
|
||||
fontSize: fontSize,
|
||||
});
|
||||
paragraphGraphBuilder.addText(item.content);
|
||||
}
|
||||
})
|
||||
// [Start TextUtils_getParagraph_build]
|
||||
let paragraph = paragraphGraphBuilder.build();
|
||||
paragraph.layoutSync(textMaxWidth);
|
||||
// [End TextUtils_getParagraph_build]
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
// [End TextUtils_getParagraph]
|
||||
|
||||
// [Start TextUtils_getShortRichText]
|
||||
/**
|
||||
* Get the collapsed dash word data
|
||||
*
|
||||
* @param uiContext UI Context
|
||||
* @param dataModel Content Model
|
||||
* @param textSectionAttribute Rich Text Attribute
|
||||
* @param lastSpan Expand the collapse button text
|
||||
* @returns Short paragraph strings
|
||||
*/
|
||||
|
||||
public static getShortRichText(uiContext: UIContext, dataModel: RichTextModel, textSectionAttribute: RichTextSectionAttribute,
|
||||
lastSpan: string): RichTextContentModel[] {
|
||||
let paragraph =
|
||||
TextUtils.getParagraph(uiContext, dataModel.textArray, dataModel.fontSize, textSectionAttribute.constraintWidth);
|
||||
const minLinesTextSize: SizeOptions | undefined = uiContext?.getMeasureUtils().measureTextSize({
|
||||
textContent: suffix + lastSpan,
|
||||
fontSize: dataModel.fontSize,
|
||||
});
|
||||
const widthMore = uiContext?.px2vp(Number(minLinesTextSize?.width));
|
||||
// Calculates the coordinates of the last text before three points
|
||||
let x: number = 0;
|
||||
let y: number = 0;
|
||||
// [Start TextUtils_getShortRichText_y]
|
||||
for (let i = 0; i < textSectionAttribute.maxLines; i++) {
|
||||
y += i === textSectionAttribute.maxLines - 1 ? paragraph.getLineHeight(i) / 2 : paragraph.getLineHeight(i);
|
||||
}
|
||||
// [End TextUtils_getShortRichText_y]
|
||||
|
||||
// [Start TextUtils_getShortRichText_x]
|
||||
if (paragraph.getLineWidth(textSectionAttribute.maxLines - 1) + Number(widthMore) >
|
||||
textSectionAttribute.constraintWidth) {
|
||||
x = textSectionAttribute.constraintWidth - Number(widthMore);
|
||||
} else {
|
||||
x = paragraph.getLineWidth(textSectionAttribute.maxLines - 1)
|
||||
}
|
||||
// [End TextUtils_getShortRichText_x]
|
||||
|
||||
// [Start TextUtils_getShortRichText_Index]
|
||||
// The conversion coordinates correspond to the index
|
||||
let positionWithAffinity = paragraph.getGlyphPositionAtCoordinate(x, y);
|
||||
let index = 0;
|
||||
if (positionWithAffinity.affinity === text.Affinity.UPSTREAM) {
|
||||
index = positionWithAffinity.position;
|
||||
} else {
|
||||
index = positionWithAffinity.position + 1;
|
||||
}
|
||||
// [Start TextUtils_getShortRichText_Index]
|
||||
// The position of the last character
|
||||
let lastIndex = index - 1;
|
||||
let shortContentArray: RichTextContentModel[] = [];
|
||||
for (let i = 0; i < dataModel.textArray.length; i++) {
|
||||
let model = dataModel.textArray[i];
|
||||
// Determine which text message is in the truncated position, process it, and sort out the display content
|
||||
if (0 <= lastIndex - model.index && lastIndex - model.index <= model.length) {
|
||||
model.shortContent = model.content.substring(0, lastIndex - model.index) + suffix;
|
||||
let b = lastIndex - model.index;
|
||||
let a = model.content.substring(0, lastIndex - model.index);
|
||||
shortContentArray.push(model);
|
||||
return shortContentArray;
|
||||
} else {
|
||||
shortContentArray.push(model);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// [End TextUtils]
|
||||
141
features/patient/src/main/ets/views/TextExpandView.ets
Normal file
141
features/patient/src/main/ets/views/TextExpandView.ets
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// [Start TextExpandView]
|
||||
import { LastSpanAttribute, TextExpandModel, TextSectionAttribute } from '../utils/Models';
|
||||
import { TextUtils } from '../utils/TextUtils';
|
||||
|
||||
@Component
|
||||
export struct TextExpandView {
|
||||
//[StartExclude TextExpandView]
|
||||
// Text chapter attribute class
|
||||
@Prop @Watch('textSectionAttributeChange') textSectionAttribute: TextSectionAttribute;
|
||||
// Controls the text or image properties of text folding
|
||||
@Prop lastSpanAttribute: LastSpanAttribute;
|
||||
// Whether to expand or not
|
||||
@State expanded: boolean = false;
|
||||
// Text expansion properties
|
||||
@State textModifier: TextExpandModel = new TextExpandModel();
|
||||
uiContext = this.getUIContext()
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.getIsExpanded();
|
||||
}
|
||||
|
||||
//[EndExclude TextExpandView]
|
||||
|
||||
// [Start TextExpandView_textSectionAttributeChange]
|
||||
textSectionAttributeChange() {
|
||||
this.textModifier.title = this.textSectionAttribute.title;
|
||||
// this.lastSpanAttribute.content = this.lastSpanAttribute.content
|
||||
// 重置展开状态
|
||||
this.expanded = false;
|
||||
this.textModifier.exceedOneLine = false;
|
||||
this.getIsExpanded();
|
||||
}
|
||||
|
||||
// [End TextExpandView_textSectionAttributeChange]
|
||||
|
||||
// [Start TextExpandView_getIsExpanded]
|
||||
getIsExpanded() {
|
||||
let titleSize: SizeOptions = this.uiContext.getMeasureUtils().measureTextSize({
|
||||
textContent: this.textSectionAttribute.title, //The text content is calculated
|
||||
lineHeight: this.textSectionAttribute.lineHeight,
|
||||
constraintWidth: this.textSectionAttribute.constraintWidth, //The text layout width is calculated
|
||||
fontSize: this.textSectionAttribute.fontSize //The text font size is calculated
|
||||
});
|
||||
let height = this.getUIContext().px2vp(Number(titleSize.height));
|
||||
if (height <= this.textSectionAttribute.lineHeight * 2) {
|
||||
this.textModifier.needProcess = false;
|
||||
this.textModifier.title = this.textSectionAttribute.title;
|
||||
return;
|
||||
} else {
|
||||
this.textModifier.title = this.textSectionAttribute.title
|
||||
this.textModifier.needProcess = true;
|
||||
}
|
||||
// 初始状态显示截断的文本
|
||||
this.collapseText();
|
||||
}
|
||||
|
||||
// [End TextExpandView_getIsExpanded]
|
||||
|
||||
build() {
|
||||
Column({ space: 3 }) {
|
||||
//[StartExclude TextExpandView]
|
||||
Text() {
|
||||
Span(this.textModifier.title)
|
||||
if (this.textModifier.needProcess && !this.textModifier.exceedOneLine) {
|
||||
Span(this.lastSpanAttribute.content[0])
|
||||
.fontColor(this.lastSpanAttribute.color)
|
||||
} else if (this.textModifier.needProcess) {
|
||||
Span(this.lastSpanAttribute.content[1])
|
||||
.fontColor(this.lastSpanAttribute.color)
|
||||
}
|
||||
}
|
||||
.fontSize(this.lastSpanAttribute.size)
|
||||
.width(this.textSectionAttribute.constraintWidth)
|
||||
.lineHeight(this.textSectionAttribute.lineHeight)
|
||||
|
||||
//[EndExclude TextExpandView]
|
||||
}
|
||||
.onClick(() => {
|
||||
if (!this.textModifier.needProcess) {
|
||||
return;
|
||||
}
|
||||
this.process();
|
||||
})
|
||||
}
|
||||
|
||||
// [Start TextExpandView_process]
|
||||
process(): void {
|
||||
if (this.expanded) {
|
||||
this.expanded = false;
|
||||
this.collapseText();
|
||||
this.textModifier.exceedOneLine = false;
|
||||
} else {
|
||||
this.expanded = true;
|
||||
this.expandText();
|
||||
this.textModifier.exceedOneLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
// [End TextExpandView_process]
|
||||
|
||||
// [Start TextExpandView_expandText]
|
||||
// Expand text
|
||||
expandText(): void {
|
||||
if (this.textModifier.needProcess) {
|
||||
this.textModifier.title = this.textSectionAttribute.title;
|
||||
}
|
||||
}
|
||||
|
||||
// [End TextExpandView_expandText]
|
||||
|
||||
// [Start TextExpandView_collapseText]
|
||||
// Collapse text
|
||||
collapseText(): void {
|
||||
if (!this.textModifier.needProcess) {
|
||||
return;
|
||||
}
|
||||
this.textModifier.title =
|
||||
TextUtils.getShortText(
|
||||
this.uiContext,
|
||||
this.textSectionAttribute,
|
||||
this.expanded ? `${this.lastSpanAttribute.content[1]}` : `${this.lastSpanAttribute.content[0]}`);
|
||||
// [End TextExpandView_collapseText]
|
||||
}
|
||||
}
|
||||
|
||||
// [End TextExpandView]
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 968 B |
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@ -0,0 +1,14 @@
|
||||
import { GroupManagementComp } from 'patient'
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct GroupManagementPage {
|
||||
|
||||
build() {
|
||||
RelativeContainer() {
|
||||
GroupManagementComp()
|
||||
}
|
||||
.height('100%')
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
@ -40,6 +40,7 @@
|
||||
"pages/Netease/PreviewPhotoPage",
|
||||
"pages/Netease/InterrogationDetailCompPage",
|
||||
"pages/Netease/PatientSimplyPage",
|
||||
"pages/Netease/MyOpinionPage"
|
||||
"pages/Netease/MyOpinionPage",
|
||||
"pages/PatientsPage/GroupManagementPage"
|
||||
]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user