2026-10-18 03:35:39 +08:00
|
|
|
/**
|
|
|
|
|
* 家书 FamilyBook · 影院列表浮层(鸿蒙端)
|
|
|
|
|
*
|
|
|
|
|
* 观影模块的"影院管理"入口(Web 端在观影页的设置里)。
|
|
|
|
|
*
|
|
|
|
|
* 🔴 为什么影院**不占抽屉里的位置**:
|
|
|
|
|
* 它不是独立模块,是"观影"的一部分 —— 一家影院只有"在哪、
|
|
|
|
|
* 叫什么、在那看过几部"这三个属性,独立成一页太空。
|
|
|
|
|
* ⇒ 做成观影页里的浮层(与详情、设置同一套交互)。
|
|
|
|
|
*
|
|
|
|
|
* ⚠️ 数据来自**本地库**(观影同步时一起落库的 `cinemas` 表),
|
|
|
|
|
* 不是现拉接口 —— 见 `FbMovieRepo.cinemaList()` 的说明。
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { FbColors, FbMetric } from '../common/Theme';
|
2026-10-19 08:29:44 +08:00
|
|
|
import { FbModuleDef, fbModuleOf, fbThemeVars } from '../model/Modules';
|
2026-10-18 03:35:39 +08:00
|
|
|
import { FbCinemaItem } from '../data/FbMovieRepo';
|
2026-10-19 08:29:44 +08:00
|
|
|
import { FbSheetRing } from './FbSheetRing';
|
2026-10-18 03:35:39 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 贴底卡片的手势区缓冲(vp)。
|
|
|
|
|
*
|
|
|
|
|
* 🔴 应用开了全屏布局且**隐藏了系统手势条**(见 EntryAbility)——
|
|
|
|
|
* 手势区不再有任何视觉提示,贴底的卡片必须自己让出这一段,
|
|
|
|
|
* 否则最后一排按钮会被"从下往上滑"误触。
|
|
|
|
|
*/
|
|
|
|
|
const FB_SHEET_BOTTOM_GAP: number = 16;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ComponentV2
|
|
|
|
|
export struct FbCinemaSheet {
|
|
|
|
|
/** 影院列表 */
|
|
|
|
|
@Param cinemas: FbCinemaItem[] = [];
|
|
|
|
|
/** 关闭回调 */
|
|
|
|
|
@Event onClose: () => void = (): void => {
|
|
|
|
|
};
|
|
|
|
|
|
2026-10-19 08:29:44 +08:00
|
|
|
/**
|
|
|
|
|
* 卡片外圈描边环的颜色(hex,'' = 用观影模块色)。
|
|
|
|
|
*
|
|
|
|
|
* ⚠️ 必须是字符串:环色要直接当背景色(`FbColors.brand` 是 `Resource`,用不了)。
|
|
|
|
|
*/
|
|
|
|
|
@Param accent: string = '';
|
|
|
|
|
|
|
|
|
|
/** 环色:显式给了就用给的,否则取观影模块色(影院属于观影) */
|
|
|
|
|
private accentColor(): string {
|
|
|
|
|
if (this.accent !== '') {
|
|
|
|
|
return this.accent;
|
|
|
|
|
}
|
|
|
|
|
const m: FbModuleDef | undefined = fbModuleOf('movies');
|
|
|
|
|
return fbThemeVars(m !== undefined ? m.color : '#A84A28').brand;
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-18 03:35:39 +08:00
|
|
|
build() {
|
|
|
|
|
// FB_WRAP_CENTER:把卡片**垂直居中**(用户 2026-10-16 要求:浮在屏幕中间)。
|
|
|
|
|
// ⚠️ 居中放在**组件内部**做,而不是改宿主的 Stack 对齐 ——
|
|
|
|
|
// 宿主 Stack 里还有别的子元素(日程页的悬浮 +),改对齐会连带挪走它们。
|
|
|
|
|
// ⚠️ 外层铺满 + Center;内层仍是那张 92% 宽的圆角卡。
|
|
|
|
|
Column() {
|
2026-10-19 08:29:44 +08:00
|
|
|
// 🔴 2026-10-19:卡片外面加**主题色环**(用户:「所有弹框都加线」),
|
|
|
|
|
// 由共用组件 `FbSheetRing` 统一给;这一层只负责 92% 宽度。
|
|
|
|
|
Column() {
|
|
|
|
|
FbSheetRing({ radius: FbMetric.radius, ringColor: this.accentColor() }) {
|
|
|
|
|
Column({ space: 0 }) {
|
|
|
|
|
// ---- 标题 ----
|
|
|
|
|
Row() {
|
|
|
|
|
Column({ space: 2 }) {
|
|
|
|
|
Text('影院')
|
|
|
|
|
.fontSize(FbMetric.fontTitle)
|
|
|
|
|
.fontWeight(FontWeight.Medium)
|
|
|
|
|
.fontColor(FbColors.ink)
|
|
|
|
|
Text(this.cinemas.length.toString() + ' 家 · 按名字排序')
|
|
|
|
|
.fontSize(FbMetric.fontTiny)
|
|
|
|
|
.fontColor(FbColors.faint)
|
|
|
|
|
}
|
|
|
|
|
.alignItems(HorizontalAlign.Start)
|
|
|
|
|
.layoutWeight(1)
|
2026-10-18 03:35:39 +08:00
|
|
|
|
2026-10-19 08:29:44 +08:00
|
|
|
Text('关闭')
|
|
|
|
|
.fontSize(FbMetric.fontSmall)
|
|
|
|
|
.fontColor(FbColors.muted)
|
|
|
|
|
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
|
|
|
|
|
.backgroundColor(FbColors.inputBg)
|
|
|
|
|
.borderRadius(FbMetric.radiusS)
|
|
|
|
|
.onClick((): void => {
|
|
|
|
|
this.onClose();
|
|
|
|
|
})
|
|
|
|
|
}
|
2026-10-18 03:35:39 +08:00
|
|
|
.width('100%')
|
2026-10-19 08:29:44 +08:00
|
|
|
.alignItems(VerticalAlign.Center)
|
|
|
|
|
|
|
|
|
|
Divider()
|
|
|
|
|
.color(FbColors.line)
|
|
|
|
|
.margin({ top: 12, bottom: 4 })
|
|
|
|
|
|
|
|
|
|
// ---- 列表 ----
|
|
|
|
|
// ⚠️ 用 List 而不是 ForEach 堆在 Column 里:影院可能几十家,
|
|
|
|
|
// List 才会**按需渲染**(进视口才建),Column 会一次全建。
|
|
|
|
|
if (this.cinemas.length === 0) {
|
|
|
|
|
Text('还没有影院。同步观影记录后,去过的地方会自动出现在这里。')
|
|
|
|
|
.fontSize(FbMetric.fontSmall)
|
|
|
|
|
.fontColor(FbColors.faint)
|
|
|
|
|
.width('100%')
|
|
|
|
|
.padding({ top: 32, bottom: 32, left: 12, right: 12 })
|
|
|
|
|
.textAlign(TextAlign.Center)
|
|
|
|
|
} else {
|
|
|
|
|
List({ space: 0 }) {
|
|
|
|
|
ForEach(this.cinemas, (c: FbCinemaItem, idx: number) => {
|
|
|
|
|
ListItem() {
|
|
|
|
|
Column({ space: 0 }) {
|
|
|
|
|
Row({ space: 12 }) {
|
|
|
|
|
// 色点:每家影院一个色(与 Web 端一致,便于在别处一眼认出来)
|
|
|
|
|
Column()
|
|
|
|
|
.width(10)
|
|
|
|
|
.height(10)
|
|
|
|
|
.backgroundColor(c.color)
|
|
|
|
|
.borderRadius(5)
|
|
|
|
|
Column({ space: 3 }) {
|
|
|
|
|
Row({ space: 8 }) {
|
|
|
|
|
Text(c.name)
|
|
|
|
|
.fontSize(FbMetric.fontBody)
|
|
|
|
|
.fontColor(FbColors.ink)
|
|
|
|
|
.maxLines(1)
|
|
|
|
|
if (c.movieCount > 0) {
|
|
|
|
|
Text(c.movieCount.toString() + ' 部')
|
|
|
|
|
.fontSize(10)
|
|
|
|
|
.fontColor(FbColors.faint)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.alignItems(VerticalAlign.Center)
|
|
|
|
|
|
|
|
|
|
// 场所 / 地址(有才显示)
|
|
|
|
|
if (c.place !== '' || c.address !== '') {
|
|
|
|
|
Text(c.place !== '' ? c.place : c.address)
|
|
|
|
|
.fontSize(FbMetric.fontTiny)
|
|
|
|
|
.fontColor(FbColors.muted)
|
|
|
|
|
.maxLines(1)
|
|
|
|
|
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
|
|
|
|
}
|
2026-10-18 03:35:39 +08:00
|
|
|
}
|
2026-10-19 08:29:44 +08:00
|
|
|
.alignItems(HorizontalAlign.Start)
|
|
|
|
|
.layoutWeight(1)
|
2026-10-18 03:35:39 +08:00
|
|
|
}
|
2026-10-19 08:29:44 +08:00
|
|
|
.width('100%')
|
|
|
|
|
.padding({ left: 4, right: 4, top: 11, bottom: 11 })
|
2026-10-18 03:35:39 +08:00
|
|
|
.alignItems(VerticalAlign.Center)
|
|
|
|
|
|
2026-10-19 08:29:44 +08:00
|
|
|
if (idx < this.cinemas.length - 1) {
|
|
|
|
|
Divider()
|
|
|
|
|
.strokeWidth(0.5)
|
|
|
|
|
.color(FbColors.line)
|
2026-10-18 03:35:39 +08:00
|
|
|
}
|
|
|
|
|
}
|
2026-10-19 08:29:44 +08:00
|
|
|
.width('100%')
|
2026-10-18 03:35:39 +08:00
|
|
|
}
|
2026-10-19 08:29:44 +08:00
|
|
|
}, (c: FbCinemaItem): string => 'cin_' + c.id.toString())
|
2026-10-18 03:35:39 +08:00
|
|
|
}
|
2026-10-19 08:29:44 +08:00
|
|
|
.width('100%')
|
|
|
|
|
.layoutWeight(1)
|
|
|
|
|
.scrollBar(BarState.Off)
|
|
|
|
|
.edgeEffect(EdgeEffect.Spring)
|
|
|
|
|
}
|
2026-10-18 03:35:39 +08:00
|
|
|
}
|
|
|
|
|
// 🔴 用户 2026-10-16:「它应该弹出一个**圆角的、浮在上面的卡片**……
|
|
|
|
|
// **不要让它左右充满整个屏幕,下面也不要挨着屏幕**,
|
|
|
|
|
// 而是放在**屏幕中间**,采用**圆角浮窗**式的形式。」
|
|
|
|
|
// ⇒ 不再贴底满宽:左右留边、四角圆角、垂直居中(由宿主的 Stack 对齐)。
|
2026-10-19 08:29:44 +08:00
|
|
|
.width('100%')
|
|
|
|
|
.constraintSize({ maxHeight: '72%' })
|
|
|
|
|
.padding({ left: 18, right: 18, top: 18, bottom: 20 + FB_SHEET_BOTTOM_GAP })
|
|
|
|
|
.alignItems(HorizontalAlign.Start)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-10-18 03:35:39 +08:00
|
|
|
.width('92%')
|
|
|
|
|
}
|
|
|
|
|
.width('100%')
|
|
|
|
|
.height('100%')
|
|
|
|
|
.justifyContent(FlexAlign.Center)
|
|
|
|
|
.hitTestBehavior(HitTestMode.Transparent)
|
|
|
|
|
}
|
|
|
|
|
}
|