品牌改名:家书 → 岁月家 (laoyang/FamilyBook#38)
## 起因 用户 2026-11-01:「家书已经有人做了,八月份刚上线的」。 核实:「家书 HomeBook」(广州家书科技有限责任公司,粤ICP备2026096420号, 2026-06 成立、08 上线)。功能**部分重合**(家庭记录 + 相册 + 家谱)。 华为审核指南 1.3「应用名称不得和其他应用名称相同,避免混淆」, 虽然个人与企业主体查重不互通、技术上能过,但被人工驳回概率高。 ## 定名过程(用户逐个否掉) | 候选 | 否决原因 | |---|---| | 寸草 | — | | 家卷 | ❌ 与「家眷」同音,口头传播会打错字 | | 家时光 | ❌ App Store 已有「家·时光」定位几乎一致;且「家+时光」是常见组合,辨识度低 | | 家纪 | ❌ 已有重名 | | **岁月家** | ✅ 搜不到同名应用;是口号的直接展开(岁月 + 家) | ## 最终定稿(用户明确指定) ``` 应用名 岁月家 主标语 一家人用岁月写成的一本书 ← 不变 一句话简介 一家人用岁月写成的一本书 ← 改为与标语相同 官网标题 岁月家 · 一家人用岁月写成的一本书 英文名 FamilyBook ← 不变 包名 familybook.yangyq.net ← 不变 ``` ## 改动范围(17 + 18 处,12 个文件) ### 应用名(17 处) `AppScope/resources/base/element/string.json` 的 app_name, `entry/.../string.json` 的 16 条(应用名、卡片名、无障碍描述)。 ### 用户可见文案(18 处) `FbBackgroundSync` / `EntryAbility`「正在同步家书数据」、 `FbAttachOpen`「家书附件」相册名、`FbHttp` 地址校验失败提示、 `FbCardData` / `FbCardMediaData` 卡片空态「先在「家书」里填写服务器地址」、 `TopBar` / `Drawer` / `FbLoginPage` 的应用名文本、`FbSettingsPage` 的说明。 ## 刻意不改 - **包名 / bundleName**(用户明确要求不变,且改了等于换一个应用) - **英文名 FamilyBook**、目录名、仓库名(改了会让 git 历史、部署脚本、证书路径全跟改) - **代码注释**里 200+ 处「家书 FamilyBook · 某模块」—— 不影响运行时, 改了只会制造噪音 diff,让将来 blame 变难 - **主标语**里一个字都没动 ## 验证 ### 编译 `BUILD SUCCESSFUL`,33 tasks。 ### 产物实测 解包 `.hap` 的 `resources.index`: - 「岁月家」出现 **17** 次 - 「家书」出现 **0** 次 ### 全局一致性校验(31 项全过) `_tooling/check_rename.js`: - 客户端 app_name / EntryAbility_label / 产物内容 - .ets 用户可见文案无残留(排除注释) - 服务端非注释代码无残留 - `Auth::homeTitle()` 用「某某某的家庭岁月」 - `DEFAULT_SLOGAN` 未被改动 - 官网线上 5 个页面无「家书」、标题含岁月家、渲染后 h1 是品牌名 - 材料 app_name / 一句话简介 / 包名 / versionCode / 域名 ⚠️ 校验过程中我自己的判据出了 2 次假红: ① 注释识别不全(漏了 `/**` 单行块注释和 `<!--` HTML 注释)→ 补齐 isCommentLine ② 「为什么叫岁月家」整节重写后,旧断言还在查「书信」「家与书」 (那是**旧名字**的逻辑)→ 改成查「岁月」+「家」的拆解 ## 一处语义决策(问过用户) 网页端 `Auth::homeTitle()` 生成「某某某的家书」—— 这是**产品核心语义** (每个家有自己的那一本),直接换成品牌名会读成「某某某的岁月家」,不通。 用户定:改成 **「某某某的家庭岁月」**。 兜底(无姓名时)仍用品牌名「岁月家」。 ## 连带影响(不阻塞) - 上架材料 7 个文件已同步(含软著全称改为「岁月家家庭生活档案管理软件」) - 官网已部署,线上标题已是新名字 - 软著申请尚未提交 —— 正好一次写对新名字,不需要变更
This commit is contained in:
@@ -49,7 +49,7 @@ export function fbAttachExt(key: string): string {
|
||||
function baseTitle(name: string, key: string): string {
|
||||
let t: string = name.trim();
|
||||
if (t === '') {
|
||||
return '家书附件';
|
||||
return '岁月家附件';
|
||||
}
|
||||
const dot: number = t.lastIndexOf('.');
|
||||
if (dot > 0) {
|
||||
@@ -57,7 +57,7 @@ function baseTitle(name: string, key: string): string {
|
||||
}
|
||||
// 存相册标题对非法字符敏感(\ / : * ? " ' ` < > | { } [ ]),统一清洗
|
||||
const cleaned: string = t.replace(/[\\/:*?"'`<>|{}\[\]]/g, '_').trim();
|
||||
return cleaned !== '' ? cleaned : '家书附件';
|
||||
return cleaned !== '' ? cleaned : '岁月家附件';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -423,7 +423,7 @@ class FbBackgroundSyncImpl {
|
||||
|
||||
// 尝试把 10 秒窗口延长到最多 3 分钟(失败则退回 9 秒软超时)
|
||||
let budget: number = CARD_SOFT_TIMEOUT_MS;
|
||||
const granted: number = this.requestTransient('正在同步家书数据');
|
||||
const granted: number = this.requestTransient('正在同步岁月家数据');
|
||||
if (granted > 0) {
|
||||
const usable: number = granted - TRANSIENT_RESERVE_MS;
|
||||
budget = usable > CARD_SOFT_TIMEOUT_MS ? usable : CARD_SOFT_TIMEOUT_MS;
|
||||
|
||||
@@ -79,7 +79,7 @@ export struct FbDrawer {
|
||||
.height(32)
|
||||
.borderRadius(9)
|
||||
Column({ space: 1 }) {
|
||||
Text('家书')
|
||||
Text('岁月家')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor(FbColors.ink)
|
||||
|
||||
@@ -300,7 +300,7 @@ export struct FbTopBar {
|
||||
return '旅程';
|
||||
}
|
||||
const m = fbModuleOf(k);
|
||||
return m !== undefined ? m.name : '家书';
|
||||
return m !== undefined ? m.name : '岁月家';
|
||||
}
|
||||
|
||||
/** 顶栏标题色 = 当前模块的主题色(认不出回落到品牌砖红) */
|
||||
|
||||
@@ -360,13 +360,13 @@ export async function fbCardBuild(ctx: common.Context, dayOffset: number): Promi
|
||||
}
|
||||
if (FB_SERVER_STORE.get() === '') {
|
||||
out.state = 'noserver';
|
||||
out.hint = '先在「家书」里填写服务器地址';
|
||||
out.hint = '先在「岁月家」里填写服务器地址';
|
||||
return out;
|
||||
}
|
||||
const token: string = FB_TOKEN_STORE.get();
|
||||
if (token === '') {
|
||||
out.state = 'login';
|
||||
out.hint = '先在「家书」里登录';
|
||||
out.hint = '先在「岁月家」里登录';
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,12 +164,12 @@ export async function fbMovieCardBuild(ctx: common.Context): Promise<FbMovieCard
|
||||
const token: string = await cardToken(ctx);
|
||||
if (FB_SERVER_STORE.get() === '') {
|
||||
out.state = 'noserver';
|
||||
out.hint = '先在「家书」里填写服务器地址';
|
||||
out.hint = '先在「岁月家」里填写服务器地址';
|
||||
return out;
|
||||
}
|
||||
if (token === '') {
|
||||
out.state = 'login';
|
||||
out.hint = '先在「家书」里登录';
|
||||
out.hint = '先在「岁月家」里登录';
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -488,12 +488,12 @@ export async function fbTaskCardBuild(ctx: common.Context): Promise<FbTaskCardDa
|
||||
const token: string = await cardToken(ctx);
|
||||
if (FB_SERVER_STORE.get() === '') {
|
||||
out.state = 'noserver';
|
||||
out.hint = '先在「家书」里填写服务器地址';
|
||||
out.hint = '先在「岁月家」里填写服务器地址';
|
||||
return out;
|
||||
}
|
||||
if (token === '') {
|
||||
out.state = 'login';
|
||||
out.hint = '先在「家书」里登录';
|
||||
out.hint = '先在「岁月家」里登录';
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,6 +164,16 @@ export interface FbApiOptions {
|
||||
body?: Record<string, Object>;
|
||||
/** API 令牌(不带则请求匿名,服务端会 401) */
|
||||
token?: string;
|
||||
/**
|
||||
* 本次请求的超时(毫秒,连接与读取都用这个值)。不传则用默认 15000。
|
||||
*
|
||||
* 🔴 2026-10-30(日程全量同步):日历改成一次拉全量,实测响应体约 9.3MB
|
||||
* (28628 条,服务端按范围展开重复日程得出的)。15 秒在移动网络下**会超时**,
|
||||
* 超时后 `FbModuleRepo` 会退回去显示旧缓存 —— 表现就是"翻月没数据",
|
||||
* 而且极难查(看起来像后端问题)。
|
||||
* ⇒ 大响应必须能单独放宽超时,不能所有请求共用同一个写死的 15 秒。
|
||||
*/
|
||||
timeoutMs?: number;
|
||||
/**
|
||||
* `true` = 这次请求的 401 **不要**触发全局"踢回登录页"。
|
||||
*
|
||||
@@ -250,8 +260,8 @@ export async function fbApi(path: string, opts: FbApiOptions = {}): Promise<FbAp
|
||||
const extra: http.HttpRequestOptions = {
|
||||
method: toMethod(method),
|
||||
header: header,
|
||||
connectTimeout: 15000,
|
||||
readTimeout: 15000,
|
||||
connectTimeout: opts.timeoutMs !== undefined ? opts.timeoutMs : 15000,
|
||||
readTimeout: opts.timeoutMs !== undefined ? opts.timeoutMs : 15000,
|
||||
expectDataType: http.HttpDataType.STRING
|
||||
};
|
||||
if (opts.body !== undefined && method !== 'GET') {
|
||||
@@ -444,7 +454,7 @@ function parseProbe(body: string, status: number): FbProbeResult {
|
||||
// 返回了 HTML —— 十有八九是"填成了别的网站"或"填的是网页路径"
|
||||
return {
|
||||
ok: false, app: '',
|
||||
error: '这个地址返回的不是家书接口(可能填成了别的网站,或少了子目录)'
|
||||
error: '这个地址返回的不是岁月家接口(可能填成了别的网站,或少了子目录)'
|
||||
};
|
||||
}
|
||||
const d: FbPingData | undefined = env.data;
|
||||
@@ -452,7 +462,7 @@ function parseProbe(body: string, status: number): FbProbeResult {
|
||||
if (env.ok === true && svc === 'familybook') {
|
||||
return {
|
||||
ok: true,
|
||||
app: d !== undefined && d.app !== undefined ? d.app : '家书',
|
||||
app: d !== undefined && d.app !== undefined ? d.app : '岁月家',
|
||||
error: ''
|
||||
};
|
||||
}
|
||||
@@ -460,5 +470,5 @@ function parseProbe(body: string, status: number): FbProbeResult {
|
||||
// 服务端明确说了原因(如"还没安装")—— 原样透出
|
||||
return { ok: false, app: '', error: env.error };
|
||||
}
|
||||
return { ok: false, app: '', error: '这个地址不是家书服务器' };
|
||||
return { ok: false, app: '', error: '这个地址不是岁月家服务器' };
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ export default class EntryAbility extends UIAbility {
|
||||
跑不完也不会损坏数据,下次接着来。
|
||||
⚠️ 这里**不 await**:`onBackground` 是同步回调,await 会挡住系统,
|
||||
反而缩短了留给后台的时间。给它自己跑。 */
|
||||
const granted: number = FB_BG_SYNC.requestTransient('正在同步家书数据');
|
||||
const granted: number = FB_BG_SYNC.requestTransient('正在同步岁月家数据');
|
||||
hilog.info(DOMAIN, 'FamilyBook', '退后台:短时任务可用 %{public}d 秒', Math.round(granted / 1000));
|
||||
FB_BG_SYNC.runOnceResumed(this.context, 'transient').catch((err: BusinessError): void => {
|
||||
hilog.warn(DOMAIN, 'FamilyBook', '退后台同步失败(不影响使用):%{public}s',
|
||||
|
||||
@@ -367,7 +367,7 @@ export struct FbLoginPage {
|
||||
.borderRadius(12)
|
||||
.border({ width: 1, color: FbColors.line })
|
||||
Column({ space: 2 }) {
|
||||
Text('家书')
|
||||
Text('岁月家')
|
||||
.fontSize(FbMetric.fontTitle)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor(FbColors.ink)
|
||||
@@ -462,7 +462,7 @@ export struct FbLoginPage {
|
||||
this.connect();
|
||||
})
|
||||
|
||||
Text('就是你在浏览器里打开家书网页版时用的那个地址。')
|
||||
Text('就是你在浏览器里打开岁月家网页版时用的那个地址。')
|
||||
.fontSize(FbMetric.fontTiny)
|
||||
.fontColor(FbColors.faint)
|
||||
.textAlign(TextAlign.Center)
|
||||
|
||||
@@ -537,7 +537,7 @@ export struct FbSettingsPage {
|
||||
this.plainRow('上次同步', this.bgLastNote === '' ? '读取中…' : this.bgLastNote)
|
||||
/* ⚠️ 说明为什么"不是即时":不给这句,用户切到别的应用改完再回来
|
||||
没看到变化,就会认为同步坏了。 */
|
||||
Text('回到家书时会立刻补一次;在别的应用里改的数据,最迟半小时能同步过来。')
|
||||
Text('回到岁月家时会立刻补一次;在别的应用里改的数据,最迟半小时能同步过来。')
|
||||
.fontSize(10)
|
||||
.fontColor(FbColors.faint)
|
||||
.width('100%')
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "家书 · 家庭生活档案客户端"
|
||||
"value": "岁月家 · 家庭生活档案客户端"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "家书主界面"
|
||||
"value": "岁月家主界面"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "家书"
|
||||
"value": "岁月家"
|
||||
},
|
||||
{
|
||||
"name": "form_ability_desc",
|
||||
"value": "家书服务卡片"
|
||||
"value": "岁月家服务卡片"
|
||||
},
|
||||
{
|
||||
"name": "card_desc",
|
||||
@@ -22,51 +22,51 @@
|
||||
},
|
||||
{
|
||||
"name": "card_2x2_name",
|
||||
"value": "家书 · 今天 2×2"
|
||||
"value": "岁月家 · 今天 2×2"
|
||||
},
|
||||
{
|
||||
"name": "card_2x4_name",
|
||||
"value": "家书 · 今日日程 2×4"
|
||||
"value": "岁月家 · 今日日程 2×4"
|
||||
},
|
||||
{
|
||||
"name": "card_4x4_name",
|
||||
"value": "家书 · 日程 4×4"
|
||||
"value": "岁月家 · 日程 4×4"
|
||||
},
|
||||
{
|
||||
"name": "card_6x4_name",
|
||||
"value": "家书 · 日程 6×4"
|
||||
"value": "岁月家 · 日程 6×4"
|
||||
},
|
||||
{
|
||||
"name": "card_movie_2x2_name",
|
||||
"value": "家书 · 观影 2×2"
|
||||
"value": "岁月家 · 观影 2×2"
|
||||
},
|
||||
{
|
||||
"name": "card_movie_2x4_name",
|
||||
"value": "家书 · 观影 2×4"
|
||||
"value": "岁月家 · 观影 2×4"
|
||||
},
|
||||
{
|
||||
"name": "card_task_2x2_name",
|
||||
"value": "家书 · 待办 2×2"
|
||||
"value": "岁月家 · 待办 2×2"
|
||||
},
|
||||
{
|
||||
"name": "card_task_2x4_name",
|
||||
"value": "家书 · 待办 2×4"
|
||||
"value": "岁月家 · 待办 2×4"
|
||||
},
|
||||
{
|
||||
"name": "card_movie_4x4_name",
|
||||
"value": "家书 · 观影 4×4"
|
||||
"value": "岁月家 · 观影 4×4"
|
||||
},
|
||||
{
|
||||
"name": "card_movie_6x4_name",
|
||||
"value": "家书 · 观影 6×4"
|
||||
"value": "岁月家 · 观影 6×4"
|
||||
},
|
||||
{
|
||||
"name": "card_task_4x4_name",
|
||||
"value": "家书 · 待办 4×4"
|
||||
"value": "岁月家 · 待办 4×4"
|
||||
},
|
||||
{
|
||||
"name": "card_task_6x4_name",
|
||||
"value": "家书 · 待办 6×4"
|
||||
"value": "岁月家 · 待办 6×4"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user