Files
fanhongcai c377421a3e 新增农户功能升级:身份证OCR/OSS上传、头像采集、同名村检测、Region热度排序及表单体验优化
- Region 表新增热度列,热门省份优先显示
- 区县下拉按地级市分组、已录区县优先、支持全省搜索
- 组选择内置一组至二十组
- 银行卡号独立行+粗体预览,开户行独立行
- 新增农户类型:农户/个体户/合作社/经营集体/公司
- 身份证正反面支持高拍仪/摄像头OCR与手机扫码上传,附件存本地/OSS
- 新增农户头像采集组件(摄像头/本地上传),预留人脸识别收购扩展
- 同名村弹窗提醒(防选错乡镇)
- 编辑窗体禁止遮罩/Esc误关,整体加宽适配高频操作
- 修复二维码局域网手机无法访问(监听0.0.0.0、局域网IP识别、Vite代理兜底)
2026-08-13 16:07:35 +08:00

140 lines
5.6 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>身份证上传</title>
<style>
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
body { margin: 0; font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
background: #f5f6fa; color: #2c3e50; }
.wrap { max-width: 480px; margin: 0 auto; padding: 24px 16px; }
h1 { font-size: 20px; margin: 0 0 4px; }
.tip { color: #7f8c8d; font-size: 13px; margin-bottom: 20px; }
.card { background: #fff; border-radius: 12px; padding: 16px; margin-bottom: 14px; }
.card h2 { font-size: 14px; margin: 0 0 10px; color: #34495e; }
.upload-btn { display: block; width: 100%; padding: 12px; border: 1.5px dashed #b8c6d6;
border-radius: 8px; background: #fafcff; color: #5a7a99; font-size: 14px;
text-align: center; cursor: pointer; }
.upload-btn.done { border-color: #27ae60; color: #27ae60; background: #f0faf4; }
.upload-btn.has-img { border-color: #2980b9; color: #2980b9; background: #f0f7fd; }
.thumb { margin-top: 10px; }
.thumb img { width: 100%; border-radius: 8px; display: block; }
input[type=file] { display: none; }
.submit { width: 100%; padding: 14px; border: 0; border-radius: 10px; background: #2ecc71;
color: #fff; font-size: 17px; font-weight: 600; cursor: pointer; }
.submit:disabled { background: #bdc3c7; }
#status { margin-top: 14px; padding: 12px; border-radius: 8px; display: none; font-size: 14px; }
#status.ok { display: block; background: #f0faf4; color: #27ae60; }
#status.err { display: block; background: #fdf0ef; color: #e74c3c; }
</style>
</head>
<body>
<div class="wrap">
<h1>身份证上传</h1>
<p class="tip">请将身份证正面(人像面)、反面(国徽面)清晰拍摄后上传</p>
<div class="card">
<h2>正面(人像面)</h2>
<label class="upload-btn" id="frontBtn" for="frontInput">点击拍摄 / 选择正面照</label>
<input type="file" id="frontInput" accept="image/*" capture="environment">
<div class="thumb" id="frontThumb" style="display:none"></div>
</div>
<div class="card">
<h2>反面(国徽面)</h2>
<label class="upload-btn" id="backBtn" for="backInput">点击拍摄 / 选择反面照</label>
<input type="file" id="backInput" accept="image/*" capture="environment">
<div class="thumb" id="backThumb" style="display:none"></div>
</div>
<button class="submit" id="uploadBtn" disabled>上传</button>
<div id="status"></div>
</div>
<script>
(function () {
var code = new URLSearchParams(location.search).get('code') || '';
var front = null, back = null;
function bind(inputId, thumbId, btnId, label) {
var input = document.getElementById(inputId);
var thumb = document.getElementById(thumbId);
var btn = document.getElementById(btnId);
input.addEventListener('change', function () {
var f = input.files && input.files[0];
if (!f) return;
label = f; // 保存所选文件
btn.classList.add('has-img');
btn.textContent = f.name + '(已选,点击可重选)';
thumb.style.display = 'block';
thumb.innerHTML = '<img src="' + URL.createObjectURL(f) + '">';
});
input.label = label;
return input;
}
// 用闭包保存文件
document.getElementById('frontInput').addEventListener('change', function () {
var f = this.files && this.files[0];
if (!f) return;
front = f;
var btn = document.getElementById('frontBtn');
btn.classList.add('has-img');
btn.textContent = '已选正面照,点击重拍';
document.getElementById('frontThumb').style.display = 'block';
document.getElementById('frontThumb').innerHTML = '<img src="' + URL.createObjectURL(f) + '">';
check();
});
document.getElementById('backInput').addEventListener('change', function () {
var f = this.files && this.files[0];
if (!f) return;
back = f;
var btn = document.getElementById('backBtn');
btn.classList.add('has-img');
btn.textContent = '已选反面照,点击重拍';
document.getElementById('backThumb').style.display = 'block';
document.getElementById('backThumb').innerHTML = '<img src="' + URL.createObjectURL(f) + '">';
check();
});
function check() {
document.getElementById('uploadBtn').disabled = !(front || back);
}
function status(ok, msg) {
var el = document.getElementById('status');
el.className = ok ? 'ok' : 'err';
el.textContent = msg;
}
document.getElementById('uploadBtn').addEventListener('click', async function () {
if (!code) { status(false, '二维码缺少参数,已失效,请回电脑端重新生成'); return; }
var btn = this;
btn.disabled = true;
btn.textContent = '上传中…';
var fd = new FormData();
fd.append('code', code);
if (front) fd.append('front', front);
if (back) fd.append('back', back);
try {
var resp = await fetch('/api/uploads/mobile', { method: 'POST', body: fd });
var data = await resp.json();
if (resp.ok && data.ok) {
status(true, '上传成功!请回到电脑端查看识别结果。');
btn.textContent = '已上传';
} else {
status(false, data.message || '上传失败,请重试');
btn.disabled = false;
btn.textContent = '上传';
}
} catch (e) {
status(false, '网络异常,请确认电脑端服务已开启(同一 Wi-Fi)后重试');
btn.disabled = false;
btn.textContent = '上传';
}
});
})();
</script>
</body>
</html>