Skip to content

feat: add entry URL scan shortcut#46

Draft
rexxara wants to merge 35 commits into
feature/OfflinePlusfrom
rex/offline-plus-debug
Draft

feat: add entry URL scan shortcut#46
rexxara wants to merge 35 commits into
feature/OfflinePlusfrom
rex/offline-plus-debug

Conversation

@rexxara

@rexxara rexxara commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Add a scan button to the home URL setting, confirm scanned text before applying it, and keep this scan entry silent without changing other scan flows.

Rex Lei added 20 commits June 4, 2026 14:28
Add a scan button to the home URL setting, confirm scanned text before applying it, and keep this scan entry silent without changing other scan flows.
Add a native offline form entry page and expose the menu text as the enterprise-facing offline form entry.

Introduce the historical form list experience with search, management mode, deletion selection, drag-sort support, project/version metadata, themed card edges, and deterministic identicon rendering from the form key.

Replace the old raw JSON list item/parser shape with explicit offline form definition models, including definition files, index items, computed display metadata, records, and a serializer boundary for reading/writing local JSON files.

Update the offline form import path so PatternInput carries schemaVersion, imported definitions are written through the local file helper, repeated imports can reuse existing computed metadata, and the lightweight index stays separate from full form definition content.

Update the custom form loading/saving path to read the new local definition file structure and preserve schema version information for future submitted record files.

Move offline UI strings into resources and add Chinese comments around the new helper/model/adapter responsibilities for reviewability.
- 将离线填报菜单直接进入表单列表页,移除原来的 OfflineEntryActivity 双入口占位页
- 调整离线填报 UI 流程:表单列表页只保留搜索和拖拽排序;点击表单后进入填报记录页;填报记录页顶部提供填报新单入口;右上角配置管理直接进入表单配置详情页;表单配置详情页展示基础信息、原始配置,并在底部提供删除表单配置按钮
- 新增 OfflineProjectRecordActivity,用于展示指定表单下的历史填报记录
- 新增 OfflineFormConfigDetailActivity,用于查看表单配置详情并二次确认删除配置及历史数据
- 将表单列表数据源从 HAC_OfflinePlusList.json 调整为扫描各表单目录下的 definition.json
- 新增 offlinePlus/order.json 作为轻量排序文件,只保存 patternId 顺序
- 删除旧的 OfflineFormDefinitionIndex 模型和列表索引序列化逻辑
- 导入同一 patternId 的表单配置时保留原主题色和原排序位置,新表单追加到末尾
- 提交填报数据时写入本地 records/{recordId}.json,并在保存成功后返回记录页
- 增加本地填报记录 JSON 的序列化与反序列化逻辑
- 删除表单配置时同步删除项目目录、历史填报数据,并清理 order.json 中的残留顺序
- 移除列表页批量管理、checkbox 和列表页删除入口,避免高频页面误删配置
- 补充离线填报相关字符串资源,替换表单页硬编码提示文案
- 增强本地文件删除逻辑,递归删除子文件失败时返回失败
- 增加主题色解析兜底,避免非法颜色值导致列表渲染崩溃
- 将离线填报相关 Activity 移入 container.offlineform 包,减少 container 根包下的业务页面堆积
- 同步 AndroidManifest 中离线填报 Activity 的声明路径
- 更新 MainActivity 和 OfflinePlusCardAdapter 对离线填报 Activity 的 import
- 统一离线填报 layout 资源命名,使用 offline_form_* 前缀聚合模块相关布局
- 更新 CustomFormActivity、OfflinePlusListActivity、OfflineProjectRecordActivity 和 OfflinePlusCardAdapter 的 R.layout 引用
- 新增 strings_offline_form.xml,集中存放 offline_* 文案
- 从主 strings.xml 移除 offline_* 文案,保留原资源名不变,避免影响调用方
Add Lombok annotation processing for the Android app and convert offline form DTO/model classes to Lombok-generated boilerplate instead of handwritten getters, setters, and constructors.

Use fastjson object serialization for local offline form records and order metadata so record.json and order.json no longer need manual org.json field-by-field parsing.

Keep an explicit serializer boundary for definition.json customForm because form items are polymorphic BaseFormItem instances, while simplifying the rest of the definition file conversion to fastjson JSONObject/JSONArray.

Remove derived or null-fallback getters from offline form models where default field values already provide the intended empty state, and update theme access to use computed.theme directly.

Note: this commit intentionally excludes the unstaged MainActivity offline menu visibility change and untracked local files.
Replace the historical offline record cards with a white card-hosted table that supports horizontally scrollable data columns and a fixed narrow action column. The action column now uses a compact overflow menu for edit and delete, while the data row itself can still be tapped to edit the record.

Add current-version record editing by passing recordId into CustomFormActivity, loading the existing record values into supported form items, and overwriting the same record file while preserving recordId, createdAt, and schemaVersion. Old-version records remain blocked from editing.

Add single-record read and delete helpers for records/{recordId}.json so the history table can edit and remove individual saved records without touching the form definition.

Introduce computed.displayColumns as a flat list of field ids. Pattern import can provide initial display columns, definition serialization persists them, and the config detail page exposes checkbox-based column visibility editing that writes back to definition.json.

Rework the config detail screen into separate white card sections for basic information, display columns, raw configuration, and delete actions. Add a custom vector icon for the new-record entry card and adjust related offline strings.

Verification: git diff --cached --check passed. Gradle build was not run.
Introduce a handler registry for offline form item behavior so parsing, serialization, editable rendering, and read-only rendering are owned by each form item type instead of scattered across adapters and serializers.

Move text and select ViewHolder implementations into their type-specific folders, add dedicated text/password/select handlers, and centralize item type/view type constants and shared JSON field mapping.

Render offline record table values through each form item handler so select values display labels and password values remain masked in read-only views.
本次提交将离线填报表单从平铺 formItems 扩展为 steps + group/text/field 的结构,并补齐 Android 侧导入、渲染、历史列表展示和默认显示列逻辑。

按文件说明:

- app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java:改为按 step 分页渲染表单,支持上一步/下一步/提交;切换步骤时校验当前 step,提交时从完整 definition 收集所有 field 值;编辑历史记录时回填所有 step 下的 field。

- app/src/main/java/com/huozige/lab/container/offlineform/OfflineFormConfigDetailActivity.java:配置详情页统计和显示列配置改为基于 flatten 后的所有 field,适配 steps/group 嵌套结构。

- app/src/main/java/com/huozige/lab/container/offlineform/OfflineProjectRecordActivity.java:历史记录表的列标题、列值和只读表单项展示改为基于 flatten 后的 field;复用统一 dp 工具,避免本地重复尺寸转换方法。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/ReadOnlyFormItemViews.java:只读表单项视图复用统一 dp 工具,保持历史列表展示尺寸一致。

- app/src/main/java/com/huozige/lab/container/offlineform/model/OfflineFormDefinition.java:表单定义模型从 formItems 调整为 steps,用于承载多步骤和嵌套节点。

- app/src/main/java/com/huozige/lab/container/offlineform/model/OfflineFormDefinitionFactory.java:插件传入 DTO 转内部 definition 时递归构建 step、group、text、field 节点,并继续委托表单项 handler 创建 field 模型。

- app/src/main/java/com/huozige/lab/container/offlineform/model/OfflineFormDefinitionFlattener.java:新增 definition/step 扁平化工具,用于从树形结构提取所有可填报 field,以及生成当前 step 的渲染列表。

- app/src/main/java/com/huozige/lab/container/offlineform/model/OfflineFormDisplayItem.java:新增表单渲染中间模型,保存扁平节点、层级深度和展示编号,供 FormAdapter 渲染 group/text/field。

- app/src/main/java/com/huozige/lab/container/offlineform/model/OfflineFormNode.java:新增离线表单节点模型,支持 group、text、field 三种节点类型。

- app/src/main/java/com/huozige/lab/container/offlineform/model/OfflineFormStep.java:新增离线表单步骤模型,保存 stepId、标题和当前步骤的节点树。

- app/src/main/java/com/huozige/lab/container/offlineform/model/PatternInput.java:插件输入模型从 formItems 调整为 steps,承接新的多步骤 schema。

- app/src/main/java/com/huozige/lab/container/offlineform/model/PatternNodeInput.java:新增插件输入节点 DTO,用于接收 group/text/field 节点及其 children/field 配置。

- app/src/main/java/com/huozige/lab/container/offlineform/model/PatternStepInput.java:新增插件输入步骤 DTO,用于接收 stepId、标题和 items。

- app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/FormItemInput.java:为 select options 增加 fastjson 字段映射,确保插件传入 options 能落到 selectOptionsList。

- app/src/main/java/com/huozige/lab/container/offlineform/util/OfflineFormUiUnitHelper.java:新增离线填报动态 UI 的 dp 转 px 工具,收敛多个类里的重复 dp 方法。

- app/src/main/java/com/huozige/lab/container/proxy/OfflinePlusProxy.java:导入新 schema 后默认将所有 field 作为历史列表显示列;重复导入时保留已有 computed 配置。

- app/src/main/java/com/huozige/lab/container/proxy/support/offlinecustomform/FormAdapter.java:渲染数据源改为 OfflineFormDisplayItem;根 group 渲染为 card,子 group 在 card 内按缩进展示;支持 text 节点、field handler 渲染、展开收起三角图标和展开收起动画。

- app/src/main/java/com/huozige/lab/container/proxy/support/offlinecustomform/OfflinePlusCardAdapter.java:复用统一 dp 工具,删除本地重复尺寸转换方法。

- app/src/main/java/com/huozige/lab/container/proxy/support/offlinecustomform/helper/OfflineFormJsonSerializer.java:definition.json 序列化/反序列化支持 steps、items、children、field 和 text/group 节点,并保持 field 节点委托表单项 registry 处理。

- app/src/main/res/layout/offline_form_custom_form_activity.xml:表单页底部操作区调整为上一步和下一步/提交按钮,支持 step 导航。

- app/src/main/res/values/colors.xml:补充离线表单页面、文本说明和 group 渲染使用的颜色资源。

- app/src/main/res/values/strings_offline_form.xml:补充上一步、下一步等多步骤表单操作文案。

验证:

- 已执行 git diff --cached --check,通过。

- 未执行 Gradle build,按当前要求不跑 build。
本次提交补齐离线填报恢复在线后的数据提取入口,并将填报记录状态收敛为枚举,便于区分草稿、已提交和已导出。

按文件说明:

- app/src/main/java/com/huozige/lab/container/offlineform/model/OfflineFormRecord.java:将 status 字段从 String 改为 OfflineFormRecordStatus 枚举;默认状态为 DRAFT;提交保存创建的记录状态为 SUBMITTED,避免继续散落硬编码状态字符串。

- app/src/main/java/com/huozige/lab/container/offlineform/model/OfflineFormRecordStatus.java:新增离线填报记录状态枚举,包含 DRAFT、SUBMITTED、EXPORTED 三个状态,分别表示草稿、已提交和已导出。

- app/src/main/java/com/huozige/lab/container/proxy/OfflinePlusProxy.java:新增 WebView 同步接口 offlinePlusGetRecords(projectId),用于按项目编号返回本地所有填报记录 JSON;新增 offlinePlusMarkRecordExported(projectId, recordId),用于在活字格侧完成提取后把指定记录标记为 EXPORTED。

接口说明:

- window.offlinePlus.offlinePlusGetRecords(projectId):返回 records JSON 字符串;projectId 当前对应本地 patternId。

- window.offlinePlus.offlinePlusMarkRecordExported(projectId, recordId):成功返回 success,参数为空或记录不存在时返回错误字符串。

验证:

- 已执行 git diff --cached --check,通过。

- 未执行 Gradle build,按当前要求不跑 build。
本次提交在离线表单配置详情页增加记录清理能力,用于按当前表单清理低风险的草稿记录和已导出记录。两个操作均需要点击按钮后在确认弹框中确认,避免误触。

按文件说明:

- app/src/main/java/com/huozige/lab/container/offlineform/OfflineFormConfigDetailActivity.java:在配置详情页注册清理草稿和清理已导出数据两个按钮事件;点击后弹出确认框,确认后按对应 OfflineFormRecordStatus 调用文件 helper 删除记录,并用 Toast 返回删除数量。

- app/src/main/java/com/huozige/lab/container/proxy/support/offlinecustomform/helper/OfflineFormFileHelper.java:新增 deleteRecordsByStatus(context, patternId, status),统一按记录状态遍历并删除当前表单目录下匹配的 record 文件,避免页面层直接处理文件细节。

- app/src/main/res/layout/offline_form_config_detail_activity.xml:在配置详情页新增记录清理卡片,包含清理所有草稿和清理所有已导出数据两个蓝色按钮;删除表单配置按钮仍保持红色,用于区分高风险删除配置操作。

- app/src/main/res/values/strings_offline_form.xml:新增记录清理标题、两个按钮文案、两个确认弹框文案和删除数量 Toast 文案。

验证:

- 已执行 git diff --cached --check,通过。

- 未执行 Gradle build,按当前要求不跑 build。
本次提交在离线填报记录页展示草稿卡片,并在多步骤表单点击下一步时保存草稿,使用户可以从草稿继续填报。提交时草稿会转为已提交记录,历史记录表只展示非草稿记录。

按文件说明:

- app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java:在非最后一步点击下一步时保存草稿;如果当前 step 及之前 step 没有任何 field,则不创建新草稿;已有草稿继续填报时更新同一条记录;点击提交时将记录状态改为 SUBMITTED;编辑已提交记录时不会在下一步时降级成草稿。

- app/src/main/java/com/huozige/lab/container/offlineform/OfflineProjectRecordActivity.java:读取记录后拆分 DRAFT 和非草稿记录;在填报新单下方渲染草稿卡片;点击草稿卡片整体继续填报并从 step1 打开;草稿卡片右侧提供更多菜单,包含继续填报和删除;历史填报表只显示非草稿记录。

- app/src/main/java/com/huozige/lab/container/offlineform/model/OfflineFormRecord.java:新增 createDraft(patternId, schemaVersion, values),用于创建 DRAFT 状态的草稿记录。

- app/src/main/res/drawable/ic_offline_draft_record.xml:新增草稿卡片图标,用于和填报新单入口图标区分。

- app/src/main/res/layout/offline_form_project_record_activity.xml:在填报新单卡片下方新增 draftListLayout 容器,用于按数量展示多个草稿卡片。

- app/src/main/res/values/strings_offline_form.xml:新增草稿标题、草稿上次保存时间文案和继续填报菜单文案。

验证:

- 已执行 git diff --cached --check,通过。

- 未执行 Gradle build,按当前要求不跑 build。
本次提交为离线填报历史记录表增加分页能力,并将每页条数作为 computed 配置保存到 definition.json 中,与 theme 和 displayColumns 保持同级。测试阶段分页选项包含 1、10、20、50、100。

按文件说明:

- app/src/main/java/com/huozige/lab/container/offlineform/model/OfflineComputedInfo.java:新增 recordPageSize 字段和默认值 DEFAULT_RECORD_PAGE_SIZE=10,用于保存历史记录表每页显示数量。

- app/src/main/java/com/huozige/lab/container/proxy/support/offlinecustomform/helper/OfflineFormJsonSerializer.java:序列化 definition.json 时将 computed.recordPageSize 写入本地配置文件,保证分页设置可持久化。

- app/src/main/java/com/huozige/lab/container/proxy/OfflinePlusProxy.java:导入或重复导入表单配置时保留已有 recordPageSize;新配置默认使用 10,避免重新导入时丢失用户在配置管理页设置的分页条数。

- app/src/main/java/com/huozige/lab/container/offlineform/OfflineFormConfigDetailActivity.java:配置管理页新增分页大小下拉选择,选项为 1、10、20、50、100;选择后立即写回 definition.json,并刷新原始配置展示。

- app/src/main/res/layout/offline_form_config_detail_activity.xml:新增历史记录每页条数配置卡片,放在基础信息和显示列配置之间,使用 Spinner 展示可选分页大小。

- app/src/main/java/com/huozige/lab/container/offlineform/OfflineProjectRecordActivity.java:历史记录表按 computed.recordPageSize 分页渲染;记录数小于等于分页大小时不显示分页条;超过分页大小时显示上一页、页码信息和下一页;草稿卡片不参与历史记录分页。

- app/src/main/res/values/strings_offline_form.xml:新增分页按钮、页码信息和配置标题文案。

验证:

- 已执行 git diff --cached --check,通过。

- 未执行 Gradle build,按当前要求不跑 build。
实现内容:
- 将填报记录按状态拆分为历史填报记录和已导出记录两个同级区域。
- 抽取 OfflineRecordTableView 作为可复用记录表组件,分别实例化历史记录表和已导出记录表。
- 记录表组件内部维护分页状态,分页时只刷新表格行和分页按钮状态,不重建外层 Card、HorizontalScrollView 和分页栏,避免横向滚动条闪烁或回到起点。
- 已导出记录只支持查看和删除,点击记录行进入 JSON 详情页,操作菜单仅保留删除。
- 历史填报记录继续支持编辑和删除。

文件变更:
- app/src/main/java/com/huozige/lab/container/offlineform/OfflineProjectRecordActivity.java:保留页面级数据加载、草稿渲染、记录状态分组和两个记录表实例挂载;移除原本散落在 Activity 内的表格、分页、行渲染逻辑。
- app/src/main/java/com/huozige/lab/container/offlineform/OfflineRecordTableView.java:新增可复用记录表组件,集中处理表头、字段展示、操作列、分页和只读/可编辑行为差异。
- app/src/main/java/com/huozige/lab/container/offlineform/OfflineExportedRecordDetailActivity.java:新增已导出记录详情页,按 patternId 和 recordId 读取本地记录并展示序列化 JSON。
- app/src/main/res/layout/offline_exported_record_detail_activity.xml:新增 JSON 详情页布局,使用可选择的等宽文本展示记录内容。
- app/src/main/res/layout/offline_form_project_record_activity.xml:新增已导出记录一级标题和独立表格容器,使其与历史填报记录同级展示。
- app/src/main/res/values/strings_offline_form.xml:新增已导出记录标题、详情页标题和记录缺失提示文案。
- app/src/main/AndroidManifest.xml:注册已导出记录详情页 Activity。

验证:
- 已执行 git diff --check --cached,未发现空白或补丁格式问题。
- 已用 rg 检查分页按钮逻辑位于 OfflineRecordTableView 内部,未保留 scrollX/scrollTo/setOnScrollChangeListener 修补逻辑。
- 未执行 Gradle build。
实现内容:
- WebView 获取离线记录时只返回已提交记录,避免草稿和已导出记录参与上传流程。
- 标记记录为已导出时增加状态校验,只允许 SUBMITTED 转为 EXPORTED。
- 对已导出记录重复标记时返回 record already exported.。
- 对草稿或其他非提交状态记录标记导出时返回 record is not submitted.。

文件变更:
- app/src/main/java/com/huozige/lab/container/proxy/OfflinePlusProxy.java:新增已提交记录过滤逻辑,并在 offlinePlusMarkRecordExported 中增加导出状态流转校验,保证取数和标记导出的 API 只处理正确生命周期阶段的数据。

验证:
- 已执行 git diff --check --cached,未发现空白或补丁格式问题。
- 已用 rg 确认 offlinePlusGetRecords、offlinePlusMarkRecordExported、filterSubmittedRecords 和新增返回信息均存在。
- 未执行 Gradle build。
本次提交完成离线填报表单项扩展和填报页交互调整:新增 datePicker、timePicker、imageItem 三类表单项;图片项支持拍照、压缩、元数据保存和只读数量展示;填报页去掉底部上一步/下一步,改用顶部 tabs 切换 step,并把最终保存提交入口放到右上角。

文件说明:

app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java:接入 TabLayout 步骤切换;切换 tab 时复用草稿保存逻辑;新增右上角带图标和文案的保存 action view;保存时校验所有 step 并提交为已提交记录;接入图片拍照回调和图片字段回填。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemJsonKeys.java:补充 imageItem 的 maxCount、compression、maxLongEdge、jpegQuality、maxFileSizeKb、minQuality 等 JSON key。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemRegistry.java:注册 datePicker、timePicker、imageItem 三类 handler,让配置解析、编辑态渲染、definition 写回和只读展示继续通过统一 registry 分发。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemType.java:新增 datePicker、timePicker、imageItem 的 itemType 枚举值。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemViewType.java:新增三个表单项对应的 RecyclerView viewType 固定值。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageCaptureCallback.java:定义图片拍照成功后的回调接口,供 Activity 把压缩后的图片元数据回传给 ViewHolder。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageCaptureHost.java:定义图片表单项请求拍照的宿主接口,避免 ViewHolder 直接管理 ActivityResultLauncher。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageFormItemHandler.java:实现 imageItem 的输入模型转换、definition JSON 输出、options 读取、编辑 ViewHolder 创建和历史表只读数量展示。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageViewHolder.java:实现图片列表编辑 UI,支持拍照入口、最大数量限制、图片缩略图展示、移除图片值和必填错误展示。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/OfflineImageFileHelper.java:实现拍照 URI 解码、图片压缩、本地离线附件目录写入、图片元数据生成和本地图片文件解析。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/picker/DatePickerFormItemHandler.java:实现 datePicker 类型 handler,指定日期选择模式和固定 viewType。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/picker/PickerFormItemHandler.java:抽取 datePicker/timePicker 共用 handler 逻辑,负责基础模型转换、JSON 输出、只读展示和编辑 ViewHolder 创建。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/picker/PickerMode.java:定义 picker ViewHolder 使用的日期/时间模式枚举。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/picker/PickerViewHolder.java:实现日期/时间选择编辑 UI,分别弹出系统 DatePickerDialog 和 TimePickerDialog,并把结果保存为 yyyy-MM-dd 或 HH:mm。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/picker/TimePickerFormItemHandler.java:实现 timePicker 类型 handler,指定时间选择模式和固定 viewType。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/FormItemInput.java:扩展插件输入 DTO,接收 imageItem 的 maxCount 和 compression 配置。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageCompressionOptions.java:新增图片压缩配置模型,提供默认最长边、JPEG 质量、目标大小和最低质量。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageFormItem.java:新增图片列表表单项模型,负责图片元数据数组 JSON 序列化、反序列化、必填校验和最大数量校验。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageFormItemValue.java:新增单张图片元数据模型,保存 fileId、localPath、fileName、mimeType、size、width、height、createdAt。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/PickerFormItem.java:新增日期/时间共用值模型,负责字符串值保存和必填校验。

app/src/main/res/drawable/ic_offline_save.xml:新增右上角保存 action 使用的白色保存图标。

app/src/main/res/layout/custom_form_item_form_image.xml:新增 imageItem 编辑态布局,包含标题、必填标记、图片列表、拍照按钮和错误提示。

app/src/main/res/layout/custom_form_item_form_picker.xml:新增 datePicker/timePicker 编辑态布局,包含标题、必填标记、可点击值区域和错误提示。

app/src/main/res/layout/offline_form_custom_form_activity.xml:去掉底部上一步/下一步区域,新增顶部 TabLayout 展示 step。

验证:

已执行 git diff --cached --check,无输出。未执行 Gradle build。
本次提交为离线填报页面恢复并调整上一项/下一项能力。导航只针对当前 step 的第一层 group、text、formItem,不处理嵌套 group 内部子项;按钮固定在屏幕底部,点击时按当前纵向滚动位置实时计算目标项并滚动到对应根节点。

app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java:新增底部上一项/下一项点击逻辑;根据当前 NestedScrollView 的 scrollY 和 RecyclerView 根 item 的纵坐标动态计算上一项或下一项,不保存 current position 状态;切换目标后执行平滑滚动并对目标根节点播放短暂高亮动画;切换 step 时重置滚动位置;根据当前 step 第一层 item 数量大于 1 控制底部导航栏显示;为每个 step 底部提示区设置约 35% 屏幕高度,保证最后一项也能被滚动到可视区域。

app/src/main/res/layout/offline_form_custom_form_activity.xml:将表单内容包在 NestedScrollView 中,并在 RecyclerView 下方增加到底了提示区作为底部留白;新增固定在屏幕底部的上一项/下一项导航容器,按钮等宽显示,避免占用 tabs 下方空间,也避免按钮被 0dp 宽度压缩不可见。

app/src/main/res/values/strings_offline_form.xml:将旧的上一步/下一步文案替换为当前根节点导航使用的上一项/下一项;新增到底了提示文案;删除已无引用的提交按钮文案和历史记录摘要文案,减少离线表单资源里的废弃项。

验证:已执行 git diff --cached --check;已逐项扫描 strings_offline_form.xml,当前没有未引用的离线表单 string 资源;未执行 Gradle build。
本次提交在离线填报页增加当前 step 内的未填写项目过滤能力。过滤入口放在 step tabs 行右侧,切换 step 时默认恢复显示全部项目;过滤结果只影响当前 step 的展示列表,不修改 definition 原始数据,也不改变保存和提交数据结构。

app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java:新增仅未填 Switch 的初始化、监听和 step 切换重置逻辑;切换 step 时临时移除监听并显式渲染一次,避免依赖 setChecked 的副作用;渲染当前 step 时根据开关状态过滤第一层 root item,root formItem 为空才显示,root group 递归检查内部 formItem 只要有未填写项就显示,root text 在仅未填模式下隐藏;底部上一项/下一项导航自然基于过滤后的第一层列表工作。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/BaseFormItem.java:新增 isEmpty 抽象方法,把表单项是否为空定义为所有表单类型必须提供的模型能力,避免页面层根据 itemType 写分散判断。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/TextFormItem.java:实现文本/密码表单项的 isEmpty,按 value 为空或 trim 后为空判断未填写,并让必填校验复用该判断。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/SelectFormItem.java:实现选择框表单项的 isEmpty,按 selectedValue 为空判断未填写,并让必填校验复用该判断。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/PickerFormItem.java:实现日期/时间选择类表单项的 isEmpty,按 value 为空或 trim 后为空判断未填写,并让必填校验复用该判断。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageFormItem.java:实现图片表单项的 isEmpty,按图片列表为空判断未填写,避免把空图片序列化结果 [] 误判为已填写,并让必填校验复用该判断。

app/src/main/res/layout/offline_form_custom_form_activity.xml:将原来的单独 TabLayout 包装成水平 step bar,在 tabs 右侧增加仅未填 Switch;tabs 继续占用剩余宽度,开关固定显示在右侧,保持筛选入口和 step 切换处于同一行。

app/src/main/res/values/strings_offline_form.xml:新增仅未填开关文案,供离线填报页顶部筛选入口使用。

验证:已执行 git diff --cached --check;已逐项扫描 strings_offline_form.xml,当前没有未引用的离线表单 string 资源;已扫描 BaseFormItem 子类,当前只有 TextFormItem、SelectFormItem、PickerFormItem、ImageFormItem 四个子类且均已实现 isEmpty;未执行 Gradle build。
OfflineFormJsonSerializer: preserves the field node title from imported raw config without copying it into field.title, keeping the saved field payload shape unchanged.

OfflineFormDisplayItem and OfflineFormDefinitionFlattener: keep field display items tied to their source node so display title can prefer field.title and fall back to the node title.

OfflineFormConfigDetailActivity, OfflineRecordTableView, and FormAdapter: use the display-title helper for config display columns, record table headers, and form rendering while leaving the underlying BaseFormItem title unchanged.
app/src/main/java/com/huozige/lab/container/offlineform/OfflineProjectRecordActivity.java:在项目填报记录页右上角菜单新增原始配置,让原始 JSON 入口和配置管理处于同一级菜单,符合这次要求的导航层级。

app/src/main/java/com/huozige/lab/container/offlineform/OfflineFormRawConfigActivity.java:新增只读的原始配置页面,专门读取并格式化 definition.json,避免把原始 JSON 展示继续混在配置管理页的编辑和清理操作里。

app/src/main/res/layout/offline_form_raw_config_activity.xml:新增最小化的可滚动、等宽字体、可选择文本布局,用于查看原始 JSON,不增加额外无关控件。

app/src/main/java/com/huozige/lab/container/offlineform/OfflineFormConfigDetailActivity.java:移除原始配置刷新和 JSON 格式化逻辑,因为配置详情页不再负责渲染原始配置内容。

app/src/main/res/layout/offline_form_config_detail_activity.xml:删除配置详情页中的原始配置卡片,让该页面只保留基础信息、显示列、分页条数和清理删除等配置管理能力。

app/src/main/AndroidManifest.xml:注册 OfflineFormRawConfigActivity,确保项目填报记录页新增的菜单项可以正常打开原始配置页面。
@rexxara rexxara force-pushed the rex/offline-plus-debug branch from 2cb9025 to 65e3774 Compare June 11, 2026 07:34
Rex Lei added 9 commits June 11, 2026 16:30
app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemJsonKeys.java:新增 includeSeconds 常量,避免时间选择字段的秒数配置使用散落字符串。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/picker/PickerFormItemHandler.java:读取并写回时间选择字段的 includeSeconds 配置,让本地 definition.json 能保留是否包含秒的设置。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/picker/PickerViewHolder.java:日期选择默认使用打开选择器当下日期并保存为 yyyy/M/d;时间选择默认使用打开选择器当下时间,不包含秒时继续使用系统原生选择器,包含秒时保存为 HH:mm:ss。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/FormItemInput.java:在导入表单定义时承接插件传入的 includeSeconds 字段。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/PickerFormItem.java:在表单项模型上保存 includeSeconds,供渲染层决定使用原生时分选择器还是时分秒选择器。
app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java:拍照保存图片时不再传入 recordId,因为图片文件改为保存在当前项目的 files 目录下,不再按单条记录建立子目录;同时在加载表单定义后把当前项目编号写入图片表单项的运行时模型,供预览时定位项目内 files 目录使用。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageViewHolder.java:预览图片时显式传入图片表单项所属的项目编号,保证文件路径解析到 offlinePlus/{项目编号}/files/{文件名},与新的项目目录结构一致。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/OfflineImageFileHelper.java:图片文件从 recordId/fieldId 多级目录改为当前项目 files 目录平铺保存,文件名由项目编号、图片字段编号和 GUID 组成;保存结果只返回文件名,删除 localPath、尺寸、大小、mimeType、创建时间等不应进入记录值的元数据。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageFormItem.java:图片字段值从对象数组改为文件名字符串数组,记录中只保留定位文件所需的最小信息;读取记录时根据文件名数组重建运行时图片项,供列表展示和预览使用。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageFormItemValue.java:图片运行时值只保留 fileName,去掉 localPath、fileId、mimeType、大小、宽高、创建时间等冗余字段,避免记录值携带可由文件本身或目录规则得到的信息。
支持不压缩图片
图片列表性能优化
图片列表ui优化
删除历史填报记录 已导出填报记录 草稿时候删除对应填报记录里的图片

变更理由:
- app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java
  增加图片上传入口的 ActivityResult 处理,让图片表单项在允许上传时可以从系统图片选择器取图;上传和拍照统一通过离线图片文件保存逻辑落到当前项目 files 目录,保持记录值只保存文件标识。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemJsonKeys.java
  增加 allowImageUpload 和 enableCompression 配置键,保证 Android 端可以识别设计器下发的图片上传开关和压缩开关。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageCaptureHost.java
  扩展图片宿主接口,补充上传图片回调入口,使 ViewHolder 不直接依赖 Activity 实现细节。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageFormItemHandler.java
  解析和序列化图片项的上传开关、压缩开关配置,让 definition.json 中的图片项配置能正确进入运行时模型,也能在本地重写定义时保留。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageViewHolder.java
  调整图片列表为两列卡片布局,隐藏随机文件名;拍照、上传、删除按钮改为图标加文案;删除按钮移动到图片下方并与预览贴合;预览图改用 Glide 加载固定尺寸缩略图,避免滚动时主线程直接解原图造成卡顿;删除单张图片时同步删除本地文件。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/OfflineImageFileHelper.java
  图片文件改为保存到项目 files 目录下的平铺结构,文件名包含表单项目和字段标识便于定位;记录值只保存 fileName;当未启用压缩时直接复制原图,启用压缩时才按原有质量和尺寸参数生成 JPEG;同时提供按 fileName 解析和删除本地图片文件的方法。

- app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/FormItemInput.java
  增加 allowImageUpload 输入字段,承接 definition.json 中图片项是否允许上传的配置。

- app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageCompressionOptions.java
  增加 enableCompression 开关,并默认关闭,让图片压缩设置默认保持原图保存。

- app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageFormItem.java
  增加 allowImageUpload 运行时属性,让图片项模型能驱动上传按钮显隐;图片值继续输出为文件名数组,保持记录数据尽可能少。

- app/src/main/java/com/huozige/lab/container/proxy/support/offlinecustomform/helper/OfflineFormFileHelper.java
  删除单条记录时先读取记录内容,记录 JSON 删除成功后,根据当前表单定义里的 imageItem 字段解析图片文件名并删除 files 目录中的对应文件;批量删除草稿或已导出记录复用 deleteRecord,因此也会同步清理图片。

- app/src/main/res/drawable/ic_delete_image.xml
  增加删除按钮图标,用于图片卡片下方删除操作,避免纯文字按钮识别性不足。

- app/src/main/res/drawable/ic_upload_image.xml
  增加上传按钮图标,用于图片项上传入口,和拍照按钮形成一致的图标加文案样式。

- app/src/main/res/drawable/offline_image_delete_button_bg.xml
  增加删除按钮背景,只保留底部圆角,顶部直角用于和图片预览无缝贴合,形成一个整体卡片。

- app/src/main/res/layout/custom_form_item_form_image.xml
  图片项操作区改为拍照、上传两个图标加文案按钮;上传按钮默认隐藏,由 allowImageUpload 配置控制;保留错误提示区域,避免影响表单校验展示。

验证:
- 已执行 git diff --cached --check,通过。
- 按要求未执行 Gradle 编译,未新增测试。
变更理由:
- app/build.gradle
  增加 androidx.viewpager2 和 PhotoView 依赖,用成熟组件替换手写图片预览手势逻辑;ViewPager2 负责左右滑动切图,PhotoView 负责缩放、拖拽、双击放大等常用图片预览交互。

- app/src/main/AndroidManifest.xml
  注册 OfflineImagePreviewActivity,让图片列表点击后可以进入独立的全屏图片预览页面。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageViewHolder.java
  给图片预览区域增加点击入口,并把当前图片项的文件名列表和点击索引传给预览页;同时处理空文件名导致的索引偏移,保证打开预览时定位到用户点击的图片。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/OfflineImageFileHelper.java
  增加按 fileName 解析本地图片文件的重载,方便预览页直接根据记录值中的文件名定位 files 目录下的图片文件。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/OfflineImagePreviewActivity.java
  新增全屏图片预览页面,使用 ViewPager2 + PhotoView + Glide 展示图片;支持左右滑图、缩放、拖拽、双击放大、旋转和重置,删除之前手写手势控件带来的体验和维护问题。

- app/src/main/java/com/huozige/lab/container/proxy/support/capture/CameraViewActivity.java
  接入拍照页返回按钮,并将照片/录像模式下不可用的按钮改为 GONE,避免隐藏控件继续占位影响底部操作区布局。

- app/src/main/res/drawable/camera_capture_button_bg.xml
  新增拍照/录像主按钮背景,使用白色和半透明描边,替代过于显眼的蓝色按钮,接近常见系统相机的视觉风格。

- app/src/main/res/drawable/camera_overlay_button_bg.xml
  新增相机页顶部返回和切换摄像头按钮的半透明深色圆角背景,保证按钮覆盖在相机画面上仍然清晰可见。

- app/src/main/res/drawable/offline_image_action_button_bg.xml
  新增图片表单拍照/上传操作按钮背景,统一圆角样式,并支持按钮按权重铺满一行。

- app/src/main/res/layout/activity_camera_view.xml
  将拍照页改为全屏相机预览,顶部增加返回按钮,底部改为半透明操作区;拍照/录像按钮居中显示并采用白灰相机风格,切换摄像头固定在右侧,提升拍照入口的可用性和观感。

- app/src/main/res/layout/custom_form_item_form_image.xml
  将拍照、上传按钮改为同一行按权重布局;开启上传时两个按钮各占一半,未开启上传时拍照按钮自动占满整行,并使用统一圆角背景。

- app/src/main/res/layout/offline_image_preview_activity.xml
  新增全屏预览页面布局,主体使用 ViewPager2 承载图片预览,顶部提供返回、序号和重置,底部提供左右旋转操作。

验证:
- 已执行 git diff --cached --check,通过。
- 按要求未执行 Gradle 编译,未新增测试。
变更理由:
- app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java
  将图片上传入口从单选改为多选,并按图片项剩余 maxCount 截断保存,避免用户一次选择过多图片破坏数量限制;新增图片预览页 ActivityResult 回调,用预览页返回的文件名列表更新表单项;图片拍照、上传、预览删除和排序后统一触发草稿保存,保证记录值和界面顺序一致。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageCaptureCallback.java
  将图片回调从单张图片改为图片列表,承接多选上传一次返回多张图片的场景,避免循环多次触发 UI 刷新。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageCaptureHost.java
  增加预览图片和图片变更通知接口,让图片项 ViewHolder 不直接依赖 Activity 实现细节;预览删除和排序后可以通过宿主统一回写草稿。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageViewHolder.java
  将图片列表改为内嵌 RecyclerView 双列网格,减少动态创建 View 的复杂度;新增长按拖拽排序,并用 remove/add 移动语义替代 swap,修复拖动最后一张到第一张后保存时中间图片闪动换位的问题;点击、删除时读取当前 adapter position,避免拖拽后使用旧位置导致操作错图;增加加载失败占位展示。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/OfflineImageFileHelper.java
  增加按 fileName 删除本地图片文件的方法,供预览页删除当前图片时直接清理 files 目录中的物理文件。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/OfflineImagePreviewActivity.java
  在全屏预览页增加删除当前图片能力,删除后同步移除物理文件并通过 ActivityResult 返回最新文件名列表;适配图片列表删除后的 ViewPager 数据刷新和序号更新。

- app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageFormItem.java
  增加按文件名列表重建图片值的方法,用于接收预览页删除后的结果,保持记录值仍然只保存 fileName 数组。

- app/src/main/java/com/huozige/lab/container/proxy/support/capture/CameraViewActivity.java
  拍照后不再立即返回表单,而是先展示拍后确认层;用户可以重拍或确认使用照片,重拍时删除临时照片,确认后才把照片返回给表单,减少误拍图片进入记录。

- app/src/main/res/drawable/offline_image_error_bg.xml
  新增图片加载失败占位背景,让图片文件缺失或加载失败时有明确视觉反馈,而不是空白卡片。

- app/src/main/res/layout/activity_camera_view.xml
  增加拍后确认预览层和“重拍 / 使用照片”操作区,配合 CameraViewActivity 完成拍照确认流程。

- app/src/main/res/layout/custom_form_item_form_image.xml
  将图片列表容器替换为 RecyclerView,支持双列复用渲染和拖拽排序。

- app/src/main/res/layout/custom_form_item_image_card.xml
  新增图片卡片 item 布局,统一定义预览图、加载失败占位和删除按钮,避免在 Java 中手工拼装复杂视图。

- app/src/main/res/layout/offline_image_preview_activity.xml
  在预览页顶部增加删除入口,支持用户直接在预览时删除当前图片。

验证:
- 已执行 git diff --cached --check,通过。
- 按要求未执行 Gradle 编译,未新增测试。
app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java:拍照入口把图片字段的水印配置传入相机页面,让水印在拍照确认预览前就写入临时照片;拍照和上传保存统一调用 saveImage,避免两个无差别保存方法造成理解成本。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemJsonKeys.java:补充 watermark、enableTimestamp、items 三个 JSON 字段常量,统一图片水印配置在序列化和反序列化时使用的字段名。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageFormItemHandler.java:读取图片字段的水印配置并写入 ImageFormItem,保存定义时也输出水印配置,保证下发配置和本地 definition.json 重新读取后都能保留水印规则。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/OfflineImageFileHelper.java:新增水印绘制和写文件逻辑,在照片保存前把水印直接写入图片;自定义水印字段按 key:value 逐行生成,时间戳由相机页追加在最后;同时将图片保存方法合并为 saveImage,去掉拍照和上传两个无差别包装方法。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/FormItemInput.java:增加 watermark 输入字段,用于承接运行时 JSON 中图片字段的水印配置。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageFormItem.java:增加 watermark 属性,让图片表单项在运行时持有水印配置,供拍照入口生成水印内容。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageWatermarkField.java:新增自定义水印字段模型,保存每个水印项的 key 和 value,支持按字段逐行显示。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageWatermarkOptions.java:新增图片水印配置模型,保存是否启用时间戳和自定义字段列表,匹配设计端下发的 JSON 结构。

app/src/main/java/com/huozige/lab/container/proxy/support/capture/CameraViewActivity.java:接收图片字段水印配置,拍照完成后先把水印写入临时照片再进入确认预览,确保预览图片和最终保存图片上的水印一致。
app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java:接入文件上传字段的系统多文件选择器,按 fileItemConfig 选择文件并在保存前校验数量、扩展名、大小和同名文件;为文件字段写入 patternId,让附件能定位到项目 files 目录;同时把图片/文件附件字段统一到更准确的 applyPatternIdToAttachmentItems 命名。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemJsonKeys.java:增加 fileItemConfig 字段常量,让文件上传配置在本地 definition.json 的 options 中有统一字段名。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemRegistry.java:注册 FileFormItemHandler,让 fileItem 能参与表单定义解析、编辑态渲染和只读态渲染。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemType.java:增加 fileItem 表单类型,匹配设计端下发的文件上传字段类型。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/OfflineFormItemViewType.java:增加文件上传字段的 RecyclerView viewType,避免与现有文本、选择、图片等字段渲染类型冲突。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/file/FileExtensionIconView.java:新增文件扩展名图标组件,由组件接收扩展名并绘制到文件图标上,避免文件列表只显示静态通用图标。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/file/FileFormItemHandler.java:新增 fileItem 的字段处理器,负责从运行时 JSON 和本地 options 读取 fileItemConfig,并输出本地 definition.json 所需结构。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/file/FileUploadCallback.java:新增文件上传回调接口,让 Activity 将系统选择器返回的文件保存结果传回文件字段 ViewHolder。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/file/FileUploadHost.java:新增文件上传宿主接口,让文件字段 ViewHolder 通过页面宿主发起上传并通知文件列表变更保存草稿。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/file/FileViewHolder.java:新增文件上传字段编辑态 UI,支持上传按钮、文件列表、四面圆角删除按钮、点击文件调用系统应用打开,以及删除列表项时同步删除本地文件。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/file/OfflineFileHelper.java:新增离线文件附件工具,负责从 Uri 读取原文件名、校验扩展名和大小、保存到项目 files 目录、解析扩展名、推算选择器 MIME 类型并删除本地附件文件。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/FileFormItem.java:新增文件上传字段模型,记录值按原文件名到本地文件名的键值对保存,并支持必填和最大数量校验。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/FileFormItemValue.java:新增单个上传文件的中间值模型,用于保存系统选择器返回后的原文件名和本地文件名。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/FileItemConfig.java:新增文件上传配置模型,承接 maxCount、allowedExtensions、maxFileSizeKb 三个设计时配置。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/FormItemInput.java:增加 fileItemConfig 输入字段,让运行时 JSON 中的文件上传配置能进入字段模型。

app/src/main/java/com/huozige/lab/container/proxy/support/offlinecustomform/helper/OfflineFormFileHelper.java:扩展删除记录时的附件清理逻辑,从只识别 imageItem 改为同时识别 fileItem,避免删除草稿、历史或已导出记录后残留文件附件。

app/src/main/res/drawable/ic_upload_file.xml:新增上传文件按钮图标,用于区分文件上传入口和图片上传入口。

app/src/main/res/drawable/offline_file_delete_button_bg.xml:新增文件删除按钮背景,四个角均为圆角,避免复用图片删除按钮的非对称圆角样式。

app/src/main/res/layout/custom_form_item_file_row.xml:新增文件列表行布局,展示扩展名图标、原文件名、文件类型大小信息和删除按钮。

app/src/main/res/layout/custom_form_item_form_file.xml:新增文件上传字段整体布局,包含标题、必填标识、文件列表、上传按钮和错误提示。
变更理由:
- app/src/main/res/values/strings_offline_form.xml
  集中新增离线填报图片、文件、预览、相机确认、选择器、只读计数、错误提示和 contentDescription 文案,减少 Java/XML 中继续散落中文硬编码的风险。

- app/src/main/java/com/huozige/lab/container/offlineform/CustomFormActivity.java
  将图片保存失败、图片数量上限、同名文件、文件保存失败、部分文件未添加和默认步骤标题改为资源引用,避免表单主页面继续堆用户可见硬编码文案。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/file/FileFormItemHandler.java
  将文件只读态的数量展示改为资源格式化,保证历史记录表中的文件计数文案和离线表单资源统一维护。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/file/FileViewHolder.java
  将文件上传不可用、数量上限、文件不存在、打开文件 chooser、无可用应用等用户提示改为资源引用,收敛文件上传字段 UI 文案。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/file/OfflineFileHelper.java
  将文件大小超限、类型不支持、未命名文件、读取失败等异常文案改为资源引用,让文件保存校验失败时的用户可见错误可统一调整。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageFormItemHandler.java
  将图片只读态的数量展示改为资源格式化,避免图片字段和文件字段的只读文案继续平行硬编码。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/ImageViewHolder.java
  将拍照/上传入口不可用和图片数量上限提示改为资源引用,收敛图片字段编辑态文案。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/OfflineImageFileHelper.java
  将图片读取失败异常改为资源引用,保持图片附件保存失败信息和离线表单资源一致。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/image/OfflineImagePreviewActivity.java
  将预览页图片文件不存在提示改为资源引用,避免预览页单独维护中文提示。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/picker/PickerViewHolder.java
  将时、分、秒列标签改为资源引用,为时间选择器文案后续本地化留出统一入口。

- app/src/main/java/com/huozige/lab/container/offlineform/formitem/select/SelectViewHolder.java
  将无可选项错误和选择对话框标题改为资源引用,减少选择字段 ViewHolder 内硬编码展示文案。

- app/src/main/java/com/huozige/lab/container/proxy/support/capture/CameraViewActivity.java
  将离线图片拍照确认流程中的用户可见 Toast 改为资源引用;日志文案保持不动,避免扩大本次纯 UI 文案重构范围。

- app/src/main/java/com/huozige/lab/container/proxy/support/offlinecustomform/OfflinePlusCardAdapter.java
  将表单卡片中的项目编号/版本号展示改为资源格式化,避免列表卡片元信息中文拼接散落在 adapter 中。

- app/src/main/res/layout/activity_camera_view.xml
  将相机返回、重拍、使用照片按钮文案改为资源引用,收敛拍照确认 UI 文案。

- app/src/main/res/layout/custom_form_item_file_row.xml
  将文件行图标、删除按钮文案和无障碍描述改为资源引用,避免文件列表 item 布局硬编码中文。

- app/src/main/res/layout/custom_form_item_form_file.xml
  将文件上传字段标题占位、上传按钮和 contentDescription 改为资源引用,统一文件字段布局文案。

- app/src/main/res/layout/custom_form_item_form_image.xml
  将图片字段标题占位、拍照/上传按钮和 contentDescription 改为资源引用,统一图片字段布局文案。

- app/src/main/res/layout/custom_form_item_form_picker.xml
  将 picker 字段标题占位改为资源引用,保持各表单项布局的标题占位文案一致。

- app/src/main/res/layout/custom_form_item_form_select.xml
  将选择字段标题占位和默认 hint 改为资源引用,避免选择字段布局单独硬编码。

- app/src/main/res/layout/custom_form_item_form_text.xml
  将文本字段标题占位改为资源引用,保持基础字段布局文案一致。

- app/src/main/res/layout/custom_form_item_image_card.xml
  将图片加载失败、删除按钮和 contentDescription 改为资源引用,统一图片卡片 item 文案。

- app/src/main/res/layout/offline_image_preview_activity.xml
  将预览页返回、重置、删除、左转、右转按钮文案改为资源引用,收敛图片预览页面硬编码 UI 文案。

验证:
- git diff --cached --check 通过。
- 当前 staged app string 引用完整性检查通过,所有新增 R.string/@string 引用都能在 res/values 中解析。
- 按本轮重构范围未运行 Gradle 编译。
app/src/main/java/com/huozige/lab/container/proxy/OfflinePlusProxy.java:把离线表单下载入口改为三参,接收手册 PDF URL 和签名 base64;表单定义/签名保存与 PDF 下载拆开,避免签名被下载线程绑住;由安卓端根据当前 WebView URL 解析相对下载地址,下载时带 Cookie,并在进度条中显示 MB 和下载速度。

app/src/main/java/com/huozige/lab/container/proxy/support/offlinecustomform/helper/OfflineFormFileHelper.java:增加 manual.pdf、manual.pdf.tmp、signature.png 的固定文件读写和删除入口,让手册与签名作为独立文件落在表单目录下,不污染 definition.json。

app/src/main/java/com/huozige/lab/container/offlineform/OfflineFormConfigDetailActivity.java:在表单配置详情页检测本地手册和签名文件,存在时展示资源区域;手册走本地 PDF 预览,签名直接展示图片,满足离线查看。

app/src/main/res/layout/offline_form_config_detail_activity.xml:为详情页增加表单资源区、查看手册按钮和签名图片容器,配合本地手册/签名展示。

app/src/main/java/com/huozige/lab/container/proxy/support/pdf/PDFPreviewActivity.java:支持传入本地 PDF 文件路径直接预览,避免离线手册查看时再次走网络下载流程。

app/src/main/java/com/huozige/lab/container/utilities/StringUtils.java:新增公共空白字符串判断工具,替代本次新增代码里的私有 hasText 和散落的 trim().isEmpty 判断。

app/src/main/java/com/huozige/lab/container/offlineform/OfflinePlusListActivity.java:复用 StringUtils 判断搜索框是否为空白,保持原有禁止带搜索条件排序的行为不变。

app/src/main/java/com/huozige/lab/container/offlineform/formitem/file/OfflineFileHelper.java:复用 StringUtils 解析允许扩展名配置,避免重复空白字符串判断。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/FileFormItem.java:复用 StringUtils 判断附件 JSON 值是否为空白,保持空白值解析为空附件列表的语义。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/ImageFormItem.java:复用 StringUtils 判断图片 JSON 值是否为空白,保持空白值解析为空图片列表的语义。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/PickerFormItem.java:复用 StringUtils 判断选择器值是否为空白,保持必填校验语义。

app/src/main/java/com/huozige/lab/container/offlineform/model/formitem/TextFormItem.java:复用 StringUtils 判断文本值是否为空白,保持必填校验语义。

app/src/main/res/values/strings_offline_form.xml:抽出本次新增的手册下载标题、添加失败、下载失败和保存失败文案,避免 Java 代码硬编码用户可见字符串。
Rex Lei added 6 commits June 13, 2026 15:24
DeviceInfoProxy.java:新增 device.getDeviceInfo() 三方页面桥接方法,保留原 device.getSecureId() 行为不变,用于兼容旧的唯一标识命令。

DeviceInfoProxy.java:返回包含 secureId、manufacturer、brand、model、device、product、systemName、androidVersion、androidSdk、packageName、appVersionName、webViewVersionName 的 JSON 字符串,满足设备品牌、型号、系统和应用环境信息输出需求。

DeviceInfoProxy.java:复用 DeviceUtility 已有的 SSAID、包名、APP 版本和 WebView 版本读取逻辑,系统硬件字段直接使用 Android Build 信息,避免新增不必要的工具层。
OfflinePlusProxy.java:将原空实现 getAllPatternsAsync 替换为插件实际调用的 offlinePlusGetPatternsAsync,修复 JS bridge 方法名不一致导致上传命令无法获取设备离线表单列表的问题。

OfflinePlusProxy.java:读取 OfflineFormFileHelper.readDefinitions(context) 作为设备已下载离线表单来源,只提取 patternId 并返回 JSON 字符串数组,保持当前 action 简单,不返回标题、computed 等额外对象数据。

OfflinePlusProxy.java:沿用异步 ticket 回调机制,注册 ticket 后通过 CallbackParams.success 返回项目编号数组,保证插件侧可写入结果变量并继续执行后续命令。
OfflinePlusProxy.java:新增 offlinePlusExportRecordsAsync(projectId, ticket),采用与现有离线表单列表一致的 callback ticket 模式返回数据,避免同步 bridge 写变量失败的问题。

OfflinePlusProxy.java:新增 buildExportRecordsResult(projectId),返回 projectId、已提交记录 records 和项目签名 signature,记录读取复用现有 filterSubmittedRecords 逻辑,暂不处理文件字段导出。

OfflinePlusProxy.java:新增 readSignatureDataUrl(context, patternId),从项目目录的 signature.png 读取签名并转成 data:image/png;base64 字符串;读取失败或不存在时返回空字符串,避免影响记录数据导出。
app/src/main/java/com/huozige/lab/container/proxy/OfflinePlusProxy.java:将标记导出 bridge 改为异步 ticket 入口,匹配上传离线表单命令的回调方式;第二个参数接收逗号分隔的 recordIds 字符串,由安卓端统一拆分并逐条复用单条记录标记逻辑,避免在插件 JS 调用处拆分;复用 StringUtils 做空值判断,并在全部成功时返回 success、部分失败时返回对应记录编号和失败原因,便于活字格侧接收操作结果。
app/src/main/java/com/huozige/lab/container/proxy/OfflinePlusProxy.java:新增 offlinePlusDeleteReadRecordsAsync 异步 bridge,配合上传离线表单命令通过 ticket 接收结果;recordIds 为空时复用 deleteRecordsByStatus 删除项目下所有已读记录,当前模型以 EXPORTED 表示已读/已处理状态;recordIds 有值时由安卓端按英文逗号拆分,只对存在且状态为 EXPORTED 的记录执行删除,其它记录统一返回 record is not read,保持逻辑聚焦在已读状态判断。
app/src/main/java/com/huozige/lab/container/proxy/OfflinePlusProxy.java:新增 offlinePlusDeleteProjectAsync 异步 bridge,供上传离线表单命令按项目编号删除设备上的离线表单项目;实现复用原生配置页删除流程,先删除项目目录,再调用 removeDefinitionOrder 清理排序索引,避免项目列表继续保留已删除项目。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant