Files
SyncCalendar/entry/src/main/ets/pages/widget/Widget4x2.ets
T
2026-09-14 21:28:51 +08:00

213 lines
6.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// entry/src/main/ets/pages/widget/Widget4x2.ets
// 2x4 服务卡片:2x2 的横向扩展。左侧 = 日期/星期/农历 + 今日日程条数(与 2x2 一致);
// 右侧 = **当前时间之后最近的两条**日程(不含全天/跨天,不显示"进行中"等字样,不显示日历本名);
// 整卡点击进入 App,右上角 + 直接新建日程
let storage2x4 = new LocalStorage();
/** 与 eventsJson 同结构的卡片单条日程(本卡片只用到标题/时间/日历色/进行中标记) */
class CardItem2x4 {
title: string = '';
time: string = '';
endTime: string = '';
calName: string = '';
color: string = '#007DFF';
isNow: boolean = false;
}
@Entry(storage2x4)
@Component
struct Widget4x2Card {
@LocalStorageProp('dateMd') dateMd: string = '';
@LocalStorageProp('dateText') dateText: string = '';
@LocalStorageProp('weekday') weekday: string = '';
@LocalStorageProp('lunarText') lunarText: string = '';
@LocalStorageProp('todayCount') todayCount: number = 0;
@LocalStorageProp('ongoingJson') ongoingJson: string = '[]';
/** 右侧最多渲染 2 条(数据侧已裁剪,这里再兜底截断) */
private parseOngoing(): CardItem2x4[] {
try {
const all: CardItem2x4[] = JSON.parse(this.ongoingJson) as CardItem2x4[];
return all.slice(0, 2);
} catch (err) {
return [];
}
}
/** 右上角添加按钮:拉起 App 直接进入新建日程页(兄弟节点布局,点击不会冒泡到左侧日期区) */
@Builder
addButton() {
Button() {
Text('+')
.fontSize(20)
.fontWeight(FontWeight.Medium)
.fontColor('#FFFFFF')
}
.width(30)
.height(30)
.borderRadius(15)
.padding(0)
.backgroundColor('#007DFF')
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: { widgetAction: 'add' }
});
})
}
/** 卡片"打开 App":点击左侧日期区、今日条数区、右侧日程区触发;添加按钮是 header 行兄弟节点,不冒泡 */
private openApp(): void {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: {}
});
}
/** 右侧单条:左色竖条 + 起止时间 + 标题。
* 不显示"进行中 / 即将开始"字样,也不显示日历本名 */
@Builder
ongoingRow(item: CardItem2x4) {
Row({ space: 8 }) {
Column()
.width(3)
.height(40)
.borderRadius(2)
.backgroundColor(item.color)
Column({ space: 2 }) {
Text(item.time)
.fontSize(10)
.fontWeight(FontWeight.Medium)
.fontColor('#333333')
.maxLines(1)
if (item.endTime !== '' && item.endTime !== '全天') {
Text(item.endTime)
.fontSize(9)
.fontColor('#999999')
.maxLines(1)
}
}
.width(36)
.alignItems(HorizontalAlign.Start)
Text(item.title)
.fontSize(13)
.fontColor('#1A1A1A')
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.layoutWeight(1)
}
.alignItems(VerticalAlign.Center)
.width('100%')
.padding({ left: 8, right: 8, top: 5, bottom: 5 })
.borderRadius(8)
.backgroundColor('#F5F7FA')
}
/** 右侧空态:今日无日程 / 日程已全部结束 */
@Builder
emptyHint() {
Column() {
Text(this.todayCount === 0 ? '今日暂无日程' : '今日日程已结束')
.fontSize(12)
.fontColor('#8A8A8A')
.maxLines(2)
.textAlign(TextAlign.Center)
}
.width('100%')
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
.onClick(() => this.openApp())
}
build() {
Row({ space: 10 }) {
// ===== 左半:与 2x2 一致(日期 / 星期 + 农历 / 今日条数大数字) =====
Column({ space: 6 }) {
Row({ space: 6 }) {
Column({ space: 2 }) {
Text(this.dateMd === '' ? this.dateText : this.dateMd)
.fontSize(15)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Text(`${this.weekday === '' ? '' : this.weekday + ' '}${this.lunarText}`)
.fontSize(10)
.fontColor('#8A8A8A')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
.onClick(() => this.openApp())
this.addButton()
}
.width('100%')
Divider()
.strokeWidth(0.5)
.color('#E5E5E5')
Row({ space: 6 }) {
Text(`${this.todayCount}`)
.fontSize(38)
.fontWeight(FontWeight.Bold)
.fontColor('#007DFF')
Column({ space: 2 }) {
Row({ space: 4 }) {
Text('今日日程')
.fontSize(11)
.fontColor('#1A1A1A')
.maxLines(1)
}
Text(this.todayCount === 0 ? '点击添加' : '点击查看')
.fontSize(9)
.fontColor('#8A8A8A')
.maxLines(1)
}
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.layoutWeight(1)
.alignItems(VerticalAlign.Center)
.onClick(() => this.openApp())
}
.layoutWeight(1)
.height('100%')
Divider()
.vertical(true)
.height('92%')
.strokeWidth(0.5)
.color('#E5E5E5')
// ===== 右半:当前时间之后最近的两条日程(不滚动)=====
Column() {
if (this.parseOngoing().length === 0) {
this.emptyHint()
} else {
Column({ space: 6 }) {
ForEach(this.parseOngoing(), (item: CardItem2x4, idx: number) => {
this.ongoingRow(item)
}, (item: CardItem2x4, idx: number) => `${idx}_${item.title}_${item.time}`)
}
.width('100%')
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
.onClick(() => this.openApp())
}
}
.layoutWeight(1)
.height('100%')
}
.width('100%')
.height('100%')
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(16)
}
}