1.修改了2x2的卡片样式。

2.为卡片增加了添加按钮,可以通过卡片直接添加日程。

Signed-off-by: Yang Yongquan <i@yangyq.net>
This commit is contained in:
2026-09-14 09:07:47 +08:00
parent d1252ed2b7
commit 3c9b4dcfdd
7 changed files with 263 additions and 133 deletions
+18
View File
@@ -58,6 +58,8 @@ struct Index {
private permissionAsked: boolean = false;
@State detailShow: boolean = false; // 只读日程详情半屏弹层
@State detailEvent: DisplayEvent | null = null;
// 服务卡片"添加"按钮深链:EntryAbility 写入,本页读取后拉起新建日程页
@Watch('onWidgetActionChange') @StorageLink('widgetAction') widgetAction: string = '';
aboutToAppear(): void {
const ctx = this.getUIContext().getHostContext();
@@ -97,11 +99,27 @@ struct Index {
/** 从设置页/账号页返回时刷新(同步间隔、系统日历开关立即生效),并处理编辑账号后的待同步 */
onPageShow(): void {
// 卡片"添加"按钮深链:首次冷启动经 onCreate→AppStorage 落到这里消费
this.consumeWidgetAction();
// 无条件刷新:之前"列表为空就跳过"的条件会导致账号列表卡死在空状态,
// 同步时误报"没有可同步的账号"
this.reloadAll().then((): Promise<void> => this.handlePendingSync());
}
/** 卡片深链监听(App 已在后台运行时,onNewWant 改写 AppStorage 触发) */
private onWidgetActionChange(): void {
this.consumeWidgetAction();
}
/** 消费卡片"添加"深链:拉起新建日程页并立即清除标记,避免重复触发 */
private consumeWidgetAction(): void {
const action: string = AppStorage.get<string>('widgetAction') ?? '';
if (action === 'add') {
AppStorage.setOrCreate<string>('widgetAction', '');
this.addEvent();
}
}
private async handlePendingSync(): Promise<void> {
const pendingId: string | undefined = AppStorage.get<string>('pendingSyncAccountId');
if (pendingId !== undefined && pendingId !== '') {
+69 -81
View File
@@ -1,44 +1,69 @@
// entry/src/main/ets/pages/widget/Widget2x2.ets
// 2x2 服务卡片:日期 + 农历 + 下一条日程
// 2x2 服务卡片:突出今天的日期(年月日 / 星期 / 农历+ 今日日程条数;点击卡片打开 App,右上角 + 直接添加日程
let storage2x2 = new LocalStorage();
class CardItem2x2 {
title: string = '';
time: string = '';
endTime: string = '';
date: string = '';
showDate: boolean = false;
calName: string = '';
color: string = '#007DFF';
}
@Entry(storage2x2)
@Component
struct Widget2x2Card {
@LocalStorageProp('eventsJson') eventsJson: string = '[]';
@LocalStorageProp('dateText') dateText: string = '';
@LocalStorageProp('lunarText') lunarText: string = '';
@LocalStorageProp('dateMd') dateMd: string = '';
@LocalStorageProp('weekday') weekday: string = '';
@LocalStorageProp('todayCount') todayCount: number = 0;
private parseItems(): CardItem2x2[] {
try {
return JSON.parse(this.eventsJson) as CardItem2x2[];
} catch (err) {
return [];
/** 右上角添加按钮:拉起 App 直接进入新建日程页(阻止冒泡,避免同时打开 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: {}
});
}
build() {
Column({ space: 4 }) {
Column({ space: 6 }) {
// 顶部:大日期 + 添加按钮
Row({ space: 6 }) {
Text(this.dateText)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
.maxLines(1)
Blank()
Text(this.lunarText)
.fontSize(11)
.fontColor('#8A8A8A')
Column({ space: 2 }) {
Text(this.dateMd === '' ? this.dateText : this.dateMd)
.fontSize(15)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
.maxLines(1)
Text(`${this.weekday === '' ? '' : this.weekday + ' '}${this.lunarText}`)
.fontSize(11)
.fontColor('#8A8A8A')
.maxLines(1)
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
.onClick(() => this.openApp())
this.addButton()
}
.width('100%')
@@ -46,68 +71,31 @@ struct Widget2x2Card {
.strokeWidth(0.5)
.color('#E5E5E5')
if (this.parseItems().length === 0) {
Column({ space: 4 }) {
Text('暂无日程')
.fontSize(13)
// 今日日程条数(占据剩余空间,垂直居中)
Row({ space: 8 }) {
Text(`${this.todayCount}`)
.fontSize(40)
.fontWeight(FontWeight.Bold)
.fontColor('#007DFF')
Column({ space: 2 }) {
Text('今日日程')
.fontSize(12)
.fontColor('#1A1A1A')
Text(this.todayCount === 0 ? '点击添加' : '点击查看')
.fontSize(10)
.fontColor('#8A8A8A')
}
.width('100%')
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
} else {
Column({ space: 4 }) {
Row({ space: 6 }) {
Circle().width(6).height(6).fill(this.parseItems()[0].color)
Text(this.parseItems()[0].title)
.fontSize(13)
.fontWeight(FontWeight.Medium)
.fontColor('#1A1A1A')
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.layoutWeight(1)
if (this.parseItems()[0].calName !== '') {
Text(this.parseItems()[0].calName)
.fontSize(9)
.fontColor(this.parseItems()[0].color)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.constraintSize({ maxWidth: '30%' })
}
}
.width('100%')
.alignItems(VerticalAlign.Center)
Blank()
Row({ space: 6 }) {
Text(this.parseItems()[0].date)
.fontSize(10)
.fontColor('#8A8A8A')
Text(this.parseItems()[0].time === '全天'
? '全天'
: `${this.parseItems()[0].time} - ${this.parseItems()[0].endTime}`)
.fontSize(11)
.fontWeight(FontWeight.Medium)
.fontColor('#007DFF')
}
.width('100%')
.justifyContent(FlexAlign.End)
}
.width('100%')
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.layoutWeight(1)
.alignItems(VerticalAlign.Center)
.onClick(() => this.openApp())
}
.width('100%')
.height('100%')
.padding(12)
.padding(14)
.backgroundColor('#FFFFFF')
.borderRadius(16)
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: {}
});
})
}
}
+48 -16
View File
@@ -28,6 +28,29 @@ struct Widget4x2Card {
}
}
/** 右上角添加按钮:拉起 App 直接进入新建日程页(阻止冒泡,避免同时打开 App 首页) */
@Builder
addButton() {
Button() {
Text('')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#FFFFFF')
}
.width(26)
.height(26)
.borderRadius(13)
.padding(0)
.backgroundColor('#007DFF')
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: { widgetAction: 'add' }
});
})
}
/** 全天事件行:圆角矩形 + 左侧日历色竖条 + 标题 + “全天”标记(无时间轴) */
@Builder
buildAllDayRow(item: CardItem2x4) {
@@ -114,18 +137,32 @@ struct Widget4x2Card {
.backgroundColor('#F5F7FA')
}
/** 卡片"打开 App":点击日期区或日程列表触发;添加按钮是 header 行的兄弟节点,其点击不会冒泡到这里 */
private openApp(): void {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: {}
});
}
build() {
Column({ space: 4 }) {
Row({ space: 6 }) {
Text(this.dateText)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
.maxLines(1)
Text(this.lunarText)
.fontSize(11)
.fontColor('#8A8A8A')
.maxLines(1)
Row({ space: 6 }) {
Text(this.dateText)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
.maxLines(1)
Text(this.lunarText)
.fontSize(11)
.fontColor('#8A8A8A')
.maxLines(1)
}
.onClick(() => this.openApp())
Blank()
this.addButton()
}
.width('100%')
@@ -140,6 +177,7 @@ struct Widget4x2Card {
.width('100%')
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
.onClick(() => this.openApp())
} else {
List({ space: 4 }) {
ForEach(this.parseItems(), (item: CardItem2x4, idx: number) => {
@@ -166,6 +204,7 @@ struct Widget4x2Card {
.layoutWeight(1)
.scrollBar(BarState.Off)
.cachedCount(4)
.onClick(() => this.openApp())
}
}
.width('100%')
@@ -173,12 +212,5 @@ struct Widget4x2Card {
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(16)
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: {}
});
})
}
}
+45 -14
View File
@@ -27,6 +27,29 @@ struct Widget4x4Card {
}
}
/** 右上角添加按钮:拉起 App 直接进入新建日程页(阻止冒泡,避免同时打开 App 首页) */
@Builder
addButton() {
Button() {
Text('')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#FFFFFF')
}
.width(26)
.height(26)
.borderRadius(13)
.padding(0)
.backgroundColor('#007DFF')
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: { widgetAction: 'add' }
});
})
}
/** 全天事件行:圆角矩形 + 左侧日历色竖条 + 标题 + “全天”标记(无时间轴) */
@Builder
buildAllDayRow(item: CardItem4x4) {
@@ -113,20 +136,33 @@ struct Widget4x4Card {
.backgroundColor('#F5F7FA')
}
/** 卡片"打开 App":点击日期区或日程列表触发;添加按钮是 header 行的兄弟节点,其点击不会冒泡到这里 */
private openApp(): void {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: {}
});
}
build() {
Column({ space: 6 }) {
Row({ space: 6 }) {
Text(this.dateText)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
Text(this.lunarText)
.fontSize(12)
.fontColor('#8A8A8A')
Row({ space: 6 }) {
Text(this.dateText)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
Text(this.lunarText)
.fontSize(12)
.fontColor('#8A8A8A')
}
.onClick(() => this.openApp())
Blank()
Text('同步日历')
.fontSize(10)
.fontColor('#B0B0B0')
this.addButton()
}
.width('100%')
@@ -143,6 +179,7 @@ struct Widget4x4Card {
.width('100%')
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
.onClick(() => this.openApp())
} else {
List({ space: 4 }) {
ForEach(this.parseItems(), (item: CardItem4x4, idx: number) => {
@@ -169,6 +206,7 @@ struct Widget4x4Card {
.layoutWeight(1)
.scrollBar(BarState.Auto)
.cachedCount(8)
.onClick(() => this.openApp())
}
}
.width('100%')
@@ -176,12 +214,5 @@ struct Widget4x4Card {
.padding(14)
.backgroundColor('#FFFFFF')
.borderRadius(16)
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: {}
});
})
}
}
+45 -14
View File
@@ -27,6 +27,29 @@ struct Widget6x4Card {
}
}
/** 右上角添加按钮:拉起 App 直接进入新建日程页(阻止冒泡,避免同时打开 App 首页) */
@Builder
addButton() {
Button() {
Text('')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#FFFFFF')
}
.width(26)
.height(26)
.borderRadius(13)
.padding(0)
.backgroundColor('#007DFF')
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: { widgetAction: 'add' }
});
})
}
/** 全天事件行:圆角矩形 + 左侧日历色竖条 + 标题 + “全天”标记(无时间轴) */
@Builder
buildAllDayRow(item: CardItem6x4) {
@@ -113,20 +136,33 @@ struct Widget6x4Card {
.backgroundColor('#F5F7FA')
}
/** 卡片"打开 App":点击日期区或日程列表触发;添加按钮是 header 行的兄弟节点,其点击不会冒泡到这里 */
private openApp(): void {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: {}
});
}
build() {
Column({ space: 6 }) {
Row({ space: 6 }) {
Text(this.dateText)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
Text(this.lunarText)
.fontSize(12)
.fontColor('#8A8A8A')
Row({ space: 6 }) {
Text(this.dateText)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
Text(this.lunarText)
.fontSize(12)
.fontColor('#8A8A8A')
}
.onClick(() => this.openApp())
Blank()
Text('同步日历')
.fontSize(10)
.fontColor('#B0B0B0')
this.addButton()
}
.width('100%')
@@ -143,6 +179,7 @@ struct Widget6x4Card {
.width('100%')
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
.onClick(() => this.openApp())
} else {
List({ space: 4 }) {
ForEach(this.parseItems(), (item: CardItem6x4, idx: number) => {
@@ -169,6 +206,7 @@ struct Widget6x4Card {
.layoutWeight(1)
.scrollBar(BarState.Auto)
.cachedCount(12)
.onClick(() => this.openApp())
}
}
.width('100%')
@@ -176,12 +214,5 @@ struct Widget6x4Card {
.padding(14)
.backgroundColor('#FFFFFF')
.borderRadius(16)
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: {}
});
})
}
}