患者相关文件
This commit is contained in:
@@ -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]
|
||||
@@ -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]
|
||||
Reference in New Issue
Block a user