Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
a96f9d9
basic custom form
Dec 15, 2025
2c2d9f8
add OfflinePlus menu
Dec 16, 2025
0cb4783
add list page
Dec 24, 2025
e2ef5ce
list json file
Jan 19, 2026
75ee287
json object
Jan 27, 2026
23142a0
basic feature
Feb 3, 2026
5767aa4
add allPattern method
Mar 9, 2026
56c7a1f
build
Jun 3, 2026
52f3bca
change visible
Jun 3, 2026
ff017dc
feat: add entry URL scan shortcut
Jun 4, 2026
0707a17
feat: add offline form definition management flow
Jun 4, 2026
45dcc90
feat(offline): 重构离线填报入口和本地配置存储
Jun 5, 2026
10ad386
refactor(offline): 整理离线填报模块文件结构
Jun 5, 2026
a310dda
move class define into one folder
Jun 5, 2026
935c1ab
refactor(offline): simplify form models and json persistence
Jun 5, 2026
f46cfae
feat(offline): add editable record table and display column settings
Jun 5, 2026
b40adb8
refactor(offline): centralize form item handlers
Jun 8, 2026
13dfc31
feat(offline-form): 支持多步骤嵌套离线表单渲染
Jun 8, 2026
7e11135
feat(offline-form): 增加离线记录提取和导出状态
Jun 8, 2026
82a1e66
feat(offline-form): 支持清理草稿和已导出记录
Jun 8, 2026
360e7bf
feat(offline-form): 支持草稿填报续写
Jun 8, 2026
8a2fa5e
feat(offline-form): 支持历史记录分页配置
Jun 8, 2026
3f6287f
feat(offline-form): 拆分历史和已导出记录表
Jun 8, 2026
492344e
feat(offline-form): 收紧离线记录导出状态流转
Jun 8, 2026
5826f6a
feat(offline-form): 增加日期时间图片表单项并改为步骤页签
Jun 10, 2026
cf2ae97
feat(offline-form): 增加表单根节点快速导航
Jun 11, 2026
bfdd9e6
feat(offline-form): 支持仅查看未填写项目
Jun 11, 2026
61f795d
Support field node title fallback
Jun 11, 2026
65e3774
调整离线表单原始配置入口
Jun 11, 2026
37fd481
支持离线表单时间选择秒数配置
Jun 11, 2026
2364907
精简离线图片记录并平铺项目图片文件
Jun 11, 2026
905848b
支持图片上传
Jun 11, 2026
c903fa3
优化离线图片预览和拍照界面
Jun 12, 2026
1b55dde
增强离线图片项的预览删除、上传和排序体验
Jun 12, 2026
d070fef
支持离线图片拍照水印
Jun 12, 2026
921f89b
支持离线文件上传表单项
Jun 12, 2026
1fe93fb
refactor(offline): 抽取离线填报界面文案资源
Jun 13, 2026
242dd40
实现离线表单手册和签名资源
Jun 13, 2026
8d7d4f1
新增完整设备信息桥接接口
Jun 13, 2026
1155cb9
补齐离线表单列表桥接
Jun 13, 2026
5e122e8
新增离线表单数据导出桥接
Jun 13, 2026
f80dff8
支持标记离线记录已导出
Jun 13, 2026
de82628
支持删除已读离线记录
Jun 13, 2026
9187140
支持删除离线表单项目
Jun 13, 2026
637a0c3
修正离线表单数据导出参数校验
Jun 15, 2026
f1b5ae4
支持离线表单附件导出
Jun 15, 2026
be04e6c
修正离线图片保存方向
Jun 15, 2026
697239e
refactor(offline): 收敛相机水印和确认参数
Jun 15, 2026
0594a37
fix(offline): improve manual PDF saving process and error handling
Jun 15, 2026
b2cd7c2
refactor(offline): 收敛离线附件文件处理逻辑
Jun 15, 2026
a658ad4
refactor(offline): 合并离线附件值对象和回调类型
Jun 15, 2026
08899ff
refactor(offline): 模型化离线表单数据层
Jun 16, 2026
7af9266
refactor(offline): simplify attachment path construction by removing …
Jun 16, 2026
d548b34
refactor(offline): simplify offline attachment utilities
Jun 16, 2026
819cf57
fix(offline): support filled record filtering
Jun 17, 2026
e79237f
feat(offline): 支持按字段搜索过滤表单
Jun 17, 2026
97def91
Merge pull request #46 from kadbbz/rex/offline-plus-debug
rexxara Jun 17, 2026
a423c5a
调整离线表单列表卡片操作入口
Jun 24, 2026
34cbd6e
点击卡片跳转历史最新填报记录
Jul 1, 2026
de17876
修改数据校验一最外层group为最小检验单元
Jul 2, 2026
2aac251
添加删除按钮
Jul 2, 2026
00f10a4
隐藏详情按钮
Jul 3, 2026
a294f07
隐藏版本号
Jul 3, 2026
6480d4b
批量导出
Jul 8, 2026
8449d11
已导出卡片点击不触发逻辑
Jul 8, 2026
4d1de05
离线表单添加list
Jul 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 8 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ android {
//noinspection ExpiredTargetSdkVersion
targetSdk 29 // 超过29后,文件权限要大改
versionCode 4
versionName '1.21.0-release'
versionName '1.21.3-release'
manifestPlaceholders = [
JPUSH_PKGNAME : applicationId,
JPUSH_APPKEY : "599fe3f0f0f55d42155fae05", //JPush上注册的包名对应的Appkey,与包名相关,如果修改package name,需要自行注册极光推送账号,并修改这个选项
Expand Down Expand Up @@ -73,16 +73,22 @@ dependencies {
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.preference:preference:1.2.1'
implementation 'androidx.activity:activity:1.9.3'
implementation 'androidx.biometric:biometric:1.2.0-alpha05' //生物识别
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.viewpager2:viewpager2:1.1.0'
// 其他类库
implementation 'commons-io:commons-io:2.16.1' // 文件与路径处理
implementation 'com.github.getActivity:XXPermissions:18.2' // 权限控制
implementation files('libs/LPAPI-2024-10-21-R.jar') // 德佟打印机
implementation 'com.github.REBOOTERS:Matisse:v0.6.0' // 图片选择
implementation 'com.github.bumptech.glide:glide:4.16.0' // matisse依赖
implementation 'io.getstream:photoview:1.0.3' // 图片预览缩放
implementation 'com.github.jenly1314:zxing-lite:3.1.1' // 二维码识别:扫描
implementation 'com.github.jenly1314:camera-scan:1.1.1' // 二维码识别:识别
implementation 'com.github.david-serrano:locationprovider:1.2' // 读取GPS
implementation 'com.alibaba:fastjson:2.0.49' // JSON处理
compileOnly 'org.projectlombok:lombok:1.18.34' // 简化离线填报模型类模板代码
annotationProcessor 'org.projectlombok:lombok:1.18.34'
implementation 'com.github.DImuthuUpe:AndroidPdfViewer:3.1.0-beta.1' // 预览PDF
implementation 'cn.jiguang.sdk:jpush:5.3.1' // 极光推送
implementation 'com.google.firebase:firebase-messaging:24.1.0' // 极光推送
Expand All @@ -93,5 +99,4 @@ dependencies {
implementation 'com.vinaygaba:rubberstamp:1.0.0' // 图片水印
implementation 'com.github.DantSu:ESCPOS-ThermalPrinter-Android:3.3.0' // ECS蓝牙打印机
implementation 'com.github.zhaolewei:ZlwAudioRecorder:v1.08' // 录音机
implementation 'androidx.biometric:biometric:1.2.0-alpha05' //
}
}
4 changes: 2 additions & 2 deletions app/release/output-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"filters": [],
"attributes": [],
"versionCode": 4,
"versionName": "1.20.2-release",
"outputFile": "hac-1.20.2-release.apk"
"versionName": "1.21.3-release",
"outputFile": "hac-1.21.3-release.apk"
}
],
"elementType": "File"
Expand Down
18 changes: 17 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,22 @@
<activity
android:name=".proxy.support.biometric.BiometricAuthActivity"
android:exported="false" />
<activity android:name=".offlineform.CustomFormActivity"
android:exported="false" />
<activity android:name=".offlineform.OfflinePlusListActivity"
android:exported="false" />
<activity android:name=".offlineform.OfflinePlusExportListActivity"
android:exported="false" />
<activity android:name=".offlineform.OfflineProjectRecordActivity"
android:exported="false" />
<activity android:name=".offlineform.OfflineFormConfigDetailActivity"
android:exported="false" />
<activity android:name=".offlineform.OfflineFormRawConfigActivity"
android:exported="false" />
<activity android:name=".offlineform.OfflineExportedRecordDetailActivity"
android:exported="false" />
<activity android:name=".offlineform.formitem.image.OfflineImagePreviewActivity"
android:exported="false" />

<provider
android:name="androidx.core.content.FileProvider"
Expand Down Expand Up @@ -191,4 +207,4 @@

</application>

</manifest>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public class HACQRCodeScanActivity extends BarcodeCameraScanActivity {
* 存放条码类型的Extra名称
*/
public static final String EXTRA_KEY_SCAN_HINTS = "hints";
// 允许不同扫码入口单独控制是否播放扫码提示音,默认保持原有的播放行为。
public static final String EXTRA_KEY_PLAY_BEEP = "playBeep";
/**
* 仅处理QR码,速度更快
*/
Expand All @@ -43,8 +45,8 @@ protected void onResume(){
@Override
public void initCameraScan(@NonNull CameraScan<Result> cameraScan) {
super.initCameraScan(cameraScan);
// 根据需要设置CameraScan相关配置
cameraScan.setPlayBeep(true);
// 根据调用入口传入的参数决定是否播放提示音;未传时默认播放。
cameraScan.setPlayBeep(getIntent().getBooleanExtra(EXTRA_KEY_PLAY_BEEP, true));
}

@Nullable
Expand Down
17 changes: 16 additions & 1 deletion app/src/main/java/com/huozige/lab/container/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.elvishew.xlog.XLog;
import com.hjq.permissions.Permission;
import com.huozige.lab.container.offlineform.OfflinePlusListActivity;
import com.huozige.lab.container.platform.AbstractStaticFilesCacheFilter;
import com.huozige.lab.container.platform.AbstractWebInterop;
import com.huozige.lab.container.platform.hzg.HZGCacheFilter;
Expand Down Expand Up @@ -61,6 +62,7 @@ public class MainActivity extends BaseActivity {
static final int MENU_ID_SETTINGS = 2;
static final int MENU_ID_HELP = 3;
static final int MENU_ID_ABOUT = 4;
static final int MENU_ID_OFFLINE_PLUS = 5;

@SuppressLint({"JavascriptInterface", "SetJavaScriptEnabled"})
@Override
Expand Down Expand Up @@ -250,6 +252,11 @@ public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_ID_SETTINGS, MENU_ID_SETTINGS, getString(R.string.ui_menu_settings));
}

// 超级离线模式
if (ConfigManager.getInstance().getOfflinePlusMenuVisible()) {
menu.add(0, MENU_ID_OFFLINE_PLUS, MENU_ID_OFFLINE_PLUS, getString(R.string.ui_menu_offlineplus));
}

// 帮助
if (!ConfigManager.getInstance().getHelpUrl().isEmpty()) {
menu.add(0, MENU_ID_HELP, MENU_ID_HELP, getString(R.string.ui_menu_help));
Expand Down Expand Up @@ -332,6 +339,14 @@ public boolean onOptionsItemSelected(MenuItem item) {
_webView.loadUrl(ConfigManager.getInstance().getAboutUrl());
}
break;
case MENU_ID_OFFLINE_PLUS:
if (DeviceUtility.isOfflineMode()) {
// 普通离线模式不允许执行后退操作
Toast.makeText(this, "应用处于普通离线模式,无法打开【离线填报入口】页面。", Toast.LENGTH_LONG).show();
} else {
startActivity(new Intent(this, OfflinePlusListActivity.class));
}
break;
// 你可以在这里处理新创建菜单的点击事件
}

Expand Down Expand Up @@ -361,4 +376,4 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.preference.PreferenceDataStore;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;

import com.elvishew.xlog.XLog;
import com.hjq.permissions.Permission;
import com.huozige.lab.container.utilities.ConfigManager;
import com.huozige.lab.container.utilities.DeviceUtility;
import com.huozige.lab.container.utilities.LifecycleUtility;
import com.huozige.lab.container.utilities.PermissionsUtility;
import com.huozige.lab.container.utilities.UiUtility;
import com.huozige.lab.container.preferences.ScanEditTextPreference;
import com.king.camera.scan.CameraScan;

import javax.annotation.Nullable;

Expand Down Expand Up @@ -143,6 +149,26 @@ public boolean onOptionsItemSelected(MenuItem item) {
*/
public static class SettingsFragment extends PreferenceFragmentCompat {

private ScanEditTextPreference _entryPreference;

// 首页地址扫码页返回后先让用户确认,确认后才写入设置项。
private final ActivityResultLauncher<Intent> _arcZxingLite = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
Intent data = result.getData();
if (data == null || _entryPreference == null) {
return;
}

String url = CameraScan.parseScanResult(data);
new AlertDialog.Builder(requireActivity())
.setTitle(R.string.url_title)
.setMessage(url)
.setPositiveButton(R.string.ui_button_ok, (dialogInterface, i) -> _entryPreference.setText(url))
.setNegativeButton(R.string.ui_button_cancel, (dialogInterface, i) -> {
// 什么都不干
})
.show();
});

@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// 对接ConfigManager实现数据存取
Expand All @@ -151,6 +177,23 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {

// 默认逻辑
setPreferencesFromResource(R.xml.root_preferences, rootKey);

// 只给首页地址(key=E)绑定扫码按钮,其他设置项仍保持普通输入行为。
_entryPreference = findPreference(ConfigManager.PREFERENCE_KEY_APP_ENTRY_URL);
if (_entryPreference != null) {
_entryPreference.setScanClickListener(view -> {
PermissionsUtility.asyncRequirePermissions(requireActivity(), new String[]{
Permission.CAMERA,
Permission.NOTIFICATION_SERVICE
}, () -> {
Intent intent = new Intent(requireActivity(), HACQRCodeScanActivity.class);
intent.putExtra(HACQRCodeScanActivity.EXTRA_KEY_SCAN_HINTS, HACQRCodeScanActivity.EXTRA_QR_CODE_HINTS);
// 这里是手动录入首页地址的辅助扫码入口,不播放提示音,避免设置页里突然响一声。
intent.putExtra(HACQRCodeScanActivity.EXTRA_KEY_PLAY_BEEP, false);
_arcZxingLite.launch(intent);
});
});
}
}
}

Expand Down Expand Up @@ -183,4 +226,4 @@ public String getString(String key, @Nullable String defValue) {
return ConfigManager.getInstance().getStringValue(key, defValue);
}
}
}
}
Loading