# 17 累计试用:算法、持久化和到期联动 听文视频工作台 · 技术架构与实现 · 1.0.2 图示:全试用期累计:文字 OR 照片 全试用期累计:文字 OR 照片 否 是/坏账保护 新增/替换正文 Unicode差异计数 新选择/URL/AI配图 手机图有效批次+选择凭据 私有TrialUsage账本 RLock · pending · fsync · replace 达到任一上限? text_used ≥ 10000 OR photos_used ≥ 10 尚有两项余额 允许制作 · 重复提交不重扣 expired持久锁定 取消在途本机处理 · 停止新制作 保留成品导出与联系 微信wzqy2019 · 不自动付款 图5|累计试用的“任一耗尽”判定。恰好10000字或第10张的记账可返回成功,但随即失效;删除不返额。小屏可横向滚动查看图示 ## 额度定义与饱和边界 全安装共用TrialUsage实例,text上限10000个Unicode码点、photos上限10。expired为持久停止标志,text_used≥10000或photos_used≥10任一即可触发。恰好到边界的计数/选图请求可HTTP200返回expired=true,随后制作入口全部关闭;超过余额的请求HTTP400并将计数饱和至上限。没有“第10张还可再生成一次”的宽限。 到期回调设置所有Control.cancelled并清paused,每个worker入口/关键check_cancel和launch也检查试用。编码循环约0.15秒观察并终止进程组;不能撤回已提交远端收费请求。已有成品/素材仍可读取、保存、分享,pause/cancel/reveal等保留动作不是重新制作。 ## 新增文字算法 added_characters(previous, current): 相同字符串或current为空 → 0 current是previous子序列(纯删除) → 0 previous是current子序列(纯插入) → len(current)-len(previous) 否则去公共前后缀 SequenceMatcher(autojunk=False) 对insert/replace累计当前一侧字符数量 累计已用 = min(10000, 之前已用 + 新增数量) 删除/清空不减少已用,snapshot更新至已接受的当前正文 这是一套内容差异口径,不识别人的移动/替换编辑意图。相同草稿、相同提交不重复扣;删后恢复为新增,清洗只删除时不加不退,撤销恢复可能加额。只有朗读text计数,title/prompt不计本项。Unicode码点不是UTF-16长度或视觉字形;组合emoji可包含多个码点。 正常短MD先做导入格式处理再对处理正文计数;原始文件文本超过10000码点会先发超限计数令到期。input队列逐次计数而非防抖丢掉编辑动作;生成先等textQueue。IME composition期间跳过预编辑计数,compositionend计最终提交内容。恢复草稿先锁控件并初始化accepted snapshot,不重复扣旧草稿。 ## 照片选择凭据 有效手机照片批次经读取/完整图像校验后消费新选张数,返回32位随机hex的photo_receipt。ledger将receipt映射到每项原Base64字符串SHA256列表,不含文件名,不是感知图像哈希。创建/换图带receipt时先检查仍active,然后按有序子序列匹配内容;原批或删减后原顺序子集重复提交不加额,乱序、伪造、增加原批没有内容或超重数重复被拒绝。 不带receipt的兼容直接上传重新消费;未知receipt不能偷偷退化为新扣一次。重新从系统选同图是新选择,删除预选/取消不退款。常规≤10张批次先完整校验再扣,失败不部分替换;单批>10是例外,在解码前按试用超额令到期。 URL/AI新图及AI图重试/重生成/切来源计1,在实际下载/配置/模型调用前完成;因此通过基本校验的新尝试即使远端失败或配置失败也可能已经消耗。图片重试/重生成/切来源及换图的前置在途冲突拒绝,以及空重生成要求、缺少未知收费重发明确同意等前置拒绝,不新扣。新建/api/jobs不同:文字/照片计数发生在ACTIVE检查之前,最终返回409仍可能已扣额,不能泛称所有失败或冲突都不消费。文字不增加照片额度,音频重试、现有图库筛选、confirm不新扣图。 ## 账本结构与写入 { "version": 1, "text_used": 1500, "photos_used": 2, "text_snapshot": "此处为上次已接受正文;示例并非真实用户数据", "receipts": { "<32位随机hex凭据>": ["<每张Base64文本的64位SHA256>"] }, "expired": false } 可加migration_note说明保守迁移/异常原因。账本使用模块级RLock进行进程内读—改—写与凭据验证,pending写入、flush、fsync文件、replace、fsync父目录。计数写在草稿之前,两文件不组成原子事务;若账已写而草稿后续失败,可能已扣额而草稿未保存,代码没有退款机制。 损坏JSON、版本/schema错误、计数类型/范围错误、snapshot/expired/receipts不合法或凭据异常,采取满额+expired安全状态,保留坏文件,不当成新装空账。它不是加密防篡改账本、跨进程锁或远端授权;可阻止正常UI/接口并发漏账,不能宣称无法破解或卸载重置。 ## 旧1.0.1迁移 无新账时,读取现存任务正文合计、最近任务正文与草稿新增差异;按每任务的现存图片数、图库/单图、创建/更换照片事件及图片模型调用次数进行保守照片估计,取必要最大值,裁到额度。缺任务而仍有创建事件等不确定情况fail closed。旧版没有记录每次历史编辑/删除,完全删除且不留证据的输入无法恢复,不能保证精确追溯。 ## 前端锁与退出一致性 恢复中、额度未知、到期和退出pending均锁creationControls。updateUsage对迟到响应采用expired OR、used max、remaining min,使旧活跃响应不能重新解锁。换图的读取、选图计数和提交共用动作锁,避免任务切换和重复计数。 flushDraft先排队正文计数,再保存完整白名单草稿,返回本次saving Promise;尾部catch仅保持队列可用,不掩盖本次保存失败。真正返回退出时exitPending锁输入/清空,等待保存链成功结束后调用finishAfterDraft;失败则留在页面显示错误并恢复控制。到期时flushDraft返回已有保存链,不再执行新计数/草稿写入;等待链结束不等于到期后写入了一份新空草稿。IME未提交候选不作为草稿新内容。 ## 完成联系提示与实际到期 trial-status的completed表示存在符合归档规则的已保存非空MP4,并非重新probe每个文件;completed与expired独立。首次成片联系提示经原生SharedPreferences记录“已实际显示”,跨随机服务端口保持一次性;真正到期优先显示并停止制作。关闭弹窗不解锁。联系微信wzqy2019;无支付、激活、续期或重置接口。 本机卸载/清数据删除账本与提示偏好;另一设备安装没有账号总额共享。正式试用独立包无自动任务迁移。原1.0.1正式版71文件隔离基线现在从Git标签android-v1.0.1核验,因为用户另行授权正式1.0.2更新,不代表当前正式源永远未变。 依据:试用trial_limits.py:10–271、app.py:49–96,469–507,603–647,680–929、static/mobile.js:36–135、试用MainActivity相应桥与退出代码。 --- 招商合作微信:wzqy2019。添加备注:听文合作。 原网页:https://tingwen-creator-studio-102.pages.dev/guide/technical-17