扫码签名模块

This commit is contained in:
hayu 2025-06-16 17:24:31 +08:00
parent a9fd1062d4
commit a75576160f
7 changed files with 428 additions and 0 deletions

View File

@ -144,6 +144,9 @@
<activity
android:name="com.bonus.gzvis.app.fragment.pay.SecondActivity"
android:screenOrientation="portrait" />
<activity android:name="com.bonus.gzvis.app.util.CustomScannerActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
<meta-data
android:name="com.baidu.lbsapi.API_KEY"

View File

@ -0,0 +1,264 @@
package com.bonus.gzvis.app.fragment.person.attendance;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import com.bonus.gzvis.app.base.BaseFragment;
import com.bonus.gzvis.app.util.CustomScannerActivity;
import com.bonus.gzvis.app.util.DateTimeHelper;
import com.bonus.gzvis.app.util.GlideUtil;
import com.bonus.gzvis.app.util.SignatureView;
import com.bonus.gzvis.app.util.StringHelper;
import com.bonus.gzvis.app.util.WorkConfig;
import com.bonus.gzvis.app.util.XToastUtils;
import com.bumptech.glide.Glide;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import com.xuexiang.xpage.annotation.Page;
import com.xuexiang.xpage.enums.CoreAnim;
import org.easydarwin.easypusher.R;
import java.io.File;
import java.io.IOException;
import butterknife.BindView;
import okhttp3.FormBody;
/**
* 二维码扫描与签名Fragment
*/
@Page(name = "扫码签名", anim = CoreAnim.none)
public class ScanFragment extends BaseFragment {
private static final int CAMERA_PERMISSION_REQUEST_CODE = 100;
@BindView(R.id.title)
TextView title;
@BindView(R.id.back) TextView back;
@BindView(R.id.add) TextView add;
@BindView(R.id.signature_image) ImageView signatureImage;
@BindView(R.id.btn_upload) Button btnUpload;
private final String signaturePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/signature/";
private final String signatureName = DateTimeHelper.getNowDateHMS() + "_signature.jpg";
private boolean hasSignature = false;
private String key="";
@Override
protected int getLayoutId() {
return R.layout.activity_scan;
}
@Override
protected void initViews() {
setupTitle();
setupSignatureView();
}
private void setupTitle() {
title.setText("扫描");
back.setOnClickListener(v -> popToBack());
add.setOnClickListener(v -> checkCameraPermission());
}
private void setupSignatureView() {
// 初始化签名按钮点击事件
signatureImage.setOnClickListener(v -> showSignatureDialog());
// 初始化上传按钮点击事件
btnUpload.setOnClickListener(v -> {
if (hasSignature) {
uploadSignature();
} else {
XToastUtils.error("请先完成签名");
}
});
// 检查是否有已保存的签名
checkExistingSignature();
}
private void checkExistingSignature() {
File signatureFile = new File(signaturePath + signatureName);
if (signatureFile.exists()) {
loadSignatureImage(signatureFile.getAbsolutePath());
hasSignature = true;
}
}
private void showSignatureDialog() {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.activity_sign_aotograp, null);
AlertDialog dialog = new AlertDialog.Builder(getActivity()).create();
SignatureView signatureView = view.findViewById(R.id.signature);
// 确保签名目录存在
File dir = new File(signaturePath);
if (!dir.exists()) {
dir.mkdirs();
}
// 自动清除签名板
view.post(signatureView::clear);
// 设置按钮点击事件
view.findViewById(R.id.clear).setOnClickListener(v -> signatureView.clear());
view.findViewById(R.id.next_btn).setOnClickListener(v -> saveSignature(signatureView, dialog));
dialog.setView(view);
dialog.show();
}
private void saveSignature(SignatureView signatureView, AlertDialog dialog) {
if (!signatureView.getSigstatus()) {
XToastUtils.error("请在签名区域填写签名!");
return;
}
String path = signaturePath + signatureName;
try {
if (signatureView.save(path)) {
signatureView.clear();
XToastUtils.success("签名保存成功");
loadSignatureImage(path);
hasSignature = true;
dialog.dismiss();
} else {
dialog.dismiss();
XToastUtils.error("签名保存失败");
}
} catch (IOException e) {
e.printStackTrace();
XToastUtils.error("保存出错: " + e.getMessage());
}
}
private void loadSignatureImage(String path) {
if (path.startsWith("http")) {
GlideUtil.GlideWithPlaceHolder(getActivity(), path).into(signatureImage);
} else {
Bitmap bitmap = BitmapFactory.decodeFile(path);
if (bitmap != null) {
signatureImage.setImageBitmap(bitmap);
} else {
signatureImage.setImageResource(R.drawable.add_ic);
}
}
}
/**
* 上传
*/
private void uploadSignature() {
try {
String uploadUrl = WorkConfig.getGzramaUrl() + "personAtt/transferAutograph";
if ("".equals(key)){
XToastUtils.warning("请先扫描二维码获取信息");
return;
}
if (hasSignature) {
File signatureFile = new File(signaturePath + signatureName);
if (signatureFile.exists()) {
XToastUtils.success("开始上传签名...");
// 这里添加实际上传代码
String url = uploadFileNew(signaturePath+signatureName,"grap");
System.err.println("签名地址:"+url);
if (!"".equals(url)){
FormBody body = new FormBody.Builder()
.add("key",strIsEmty(key,1))
.add("value1",strIsEmty(url,1))
.build();
String result = service.httpPost(uploadUrl,body);
System.out.println(result);
if(!StringHelper.isEmptyAndNull(result)){
org.json.JSONObject jsonObject = new org.json.JSONObject(result);
int res = jsonObject.getInt("res");
if (res == 1){
XToastUtils.success("上传成功");
popToBack();
} else {
XToastUtils.error("上传失败,请重试");
}
}
} else {
XToastUtils.error("签名上传失败,请重试");
}
} else {
XToastUtils.error("签名文件不存在");
hasSignature = false;
}
}
} catch (Exception e) {
e.printStackTrace();
XToastUtils.error("上传失败,请重试");
}
}
private void checkCameraPermission() {
if (ContextCompat.checkSelfPermission(
requireContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
startQrScanner();
} else {
requestPermissions(new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startQrScanner();
} else {
XToastUtils.error("需要相机权限才能扫描二维码");
}
}
}
private void startQrScanner() {
try {
IntentIntegrator integrator = IntentIntegrator.forSupportFragment(this)
.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)
.setPrompt("将二维码放入框内扫描")
.setCameraId(0)
.setBeepEnabled(false)
.setBarcodeImageEnabled(false)
.setOrientationLocked(true)
.setCaptureActivity(CustomScannerActivity.class);
integrator.initiateScan();
} catch (Exception e) {
XToastUtils.error("启动扫描失败: " + e.getMessage());
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result != null) {
if (result.getContents() == null) {
key="";
XToastUtils.info("扫描已取消");
} else {
key=result.getContents();
System.out.println("二维码内容:"+key);
XToastUtils.success("获取成功");
}
}
}
}

View File

@ -100,6 +100,7 @@ public class AppPageConfig {
FaceComponents.add(new PageInfo("考勤打卡", "", "attendance", CoreAnim.slide, 2));
FaceComponents.add(new PageInfo("考勤统计", "", "attendance_statistics", CoreAnim.slide, 2));
FaceComponents.add(new PageInfo("上班与休息", "", "rest", CoreAnim.slide, 2));
FaceComponents.add(new PageInfo("扫码签名", "", "rest", CoreAnim.slide, 2));
} else {
//首页
mComponents.add(new PageInfo("分包商入场", "", "ein_sub", CoreAnim.slide, 2));
@ -146,6 +147,7 @@ public class AppPageConfig {
FaceComponents.add(new PageInfo("考勤打卡", "", "attendance", CoreAnim.slide, 2));
FaceComponents.add(new PageInfo("考勤统计", "", "attendance_statistics", CoreAnim.slide, 2));
FaceComponents.add(new PageInfo("上班与休息", "", "rest", CoreAnim.slide, 2));
FaceComponents.add(new PageInfo("扫码签名", "", "rest", CoreAnim.slide, 2));
} else {
//首页
mComponents.add(new PageInfo("分包商入场", "", "ein_sub", CoreAnim.slide, 2));

View File

@ -0,0 +1,45 @@
package com.bonus.gzvis.app.util;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.google.zxing.client.android.Intents;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
import org.easydarwin.easypusher.R;
public class CustomScannerActivity extends AppCompatActivity {
private DecoratedBarcodeView barcodeView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_scanner);
// 强制竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
barcodeView = findViewById(R.id.zxing_barcode_scanner);
barcodeView.initializeFromIntent(getIntent());
barcodeView.decodeSingle(result -> {
Intent resultIntent = new Intent();
resultIntent.putExtra(Intents.Scan.RESULT, result.getText());
setResult(RESULT_OK, resultIntent);
finish();
});
}
@Override
protected void onResume() {
super.onResume();
barcodeView.resume();
}
@Override
protected void onPause() {
super.onPause();
barcodeView.pause();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.journeyapps.barcodescanner.DecoratedBarcodeView
android:id="@+id/zxing_barcode_scanner"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#efefef"
android:focusableInTouchMode="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<!-- 标题栏 -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorPrimary">
<TextView
android:id="@+id/back"
android:layout_width="40dp"
android:layout_height="30dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:background="@drawable/back" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="扫描"
android:textColor="#FFFFFF"
android:textSize="20sp" />
<TextView
android:id="@+id/add"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:background="@drawable/scan" />
</RelativeLayout>
<!-- 主内容区域(居中显示) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
android:padding="20dp">
<!-- 签名区域 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="签名:"
android:textSize="20sp"/>
<ImageView
android:id="@+id/signature_image"
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_marginTop="10dp"
android:src="@drawable/add_ic"
android:scaleType="fitCenter"
android:contentDescription="签名图片" />
</LinearLayout>
<!-- 操作按钮 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:orientation="horizontal">
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
style="@style/SuperButton.Blue"
android:id="@+id/btn_upload"
android:layout_width="200dp"
android:layout_height="45dp"
android:text="上传" />
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="150dp"/>
</LinearLayout>
</LinearLayout>
</FrameLayout>