diff --git a/ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue b/ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
index 0764c18..89602f8 100644
--- a/ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
+++ b/ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
@@ -225,12 +225,18 @@
:auto-upload="false"
:limit="1"
:file-list="idCardFileList"
+ accept=".xls,.xlsx"
+ :on-change="handleIdCardFileChange"
+ :on-remove="handleIdCardFileRemove"
>
选择文件
支持 .xls、.xlsx 文件
+
+ 正在解析身份证文件...
+
取消
-
+
确认拉取
@@ -758,6 +768,123 @@ export default {
this.parsingIdCardFile = false;
this.pullBankInfoLoading = false;
},
+ parseIdCardText(text) {
+ return Array.from(
+ new Set(
+ (text || "")
+ .split(/[\n,,]+/)
+ .map((item) => item.trim())
+ .filter(Boolean)
+ )
+ );
+ },
+ mergeIdCards(currentText, parsedIdCards) {
+ const merged = [
+ ...this.parseIdCardText(currentText),
+ ...((parsedIdCards || [])
+ .map((item) => String(item || "").trim())
+ .filter(Boolean)),
+ ];
+ return Array.from(new Set(merged)).join(", ");
+ },
+ async handleIdCardFileChange(file, fileList) {
+ const latestFile = (fileList || []).slice(-1);
+ const currentFile = latestFile[0] || file;
+ const fileName = (currentFile && currentFile.name) || "";
+ const isExcel = /\.(xls|xlsx)$/i.test(fileName);
+
+ if (!isExcel) {
+ this.idCardFileList = [];
+ this.$message.error("仅支持上传 .xls 或 .xlsx 文件");
+ return;
+ }
+
+ if (!currentFile || !currentFile.raw) {
+ this.idCardFileList = [];
+ this.$message.error("未获取到有效文件");
+ return;
+ }
+
+ this.idCardFileList = latestFile;
+ this.parsingIdCardFile = true;
+
+ try {
+ const res = await parseIdCardFile(currentFile.raw);
+ const parsedIdCards =
+ (res && res.data && Array.isArray(res.data.idCards) && res.data.idCards) ||
+ [];
+ this.pullBankInfoForm.idCardText = this.mergeIdCards(
+ this.pullBankInfoForm.idCardText,
+ parsedIdCards
+ );
+ this.$message.success(
+ `身份证文件解析成功,共 ${parsedIdCards.length} 条有效身份证`
+ );
+ } catch (error) {
+ this.idCardFileList = [];
+ this.$message.error(
+ "身份证文件解析失败:" +
+ ((error && error.message) || "未知错误")
+ );
+ } finally {
+ this.parsingIdCardFile = false;
+ }
+ },
+ handleIdCardFileRemove() {
+ this.idCardFileList = [];
+ this.parsingIdCardFile = false;
+ },
+ buildFinalIdCardList() {
+ return this.parseIdCardText(this.pullBankInfoForm.idCardText);
+ },
+ async handleConfirmPullBankInfo() {
+ const idCards = this.buildFinalIdCardList();
+ const [startDate, endDate] = this.pullBankInfoForm.dateRange || [];
+
+ if (idCards.length === 0) {
+ this.$message.warning("请至少输入一个身份证号");
+ return;
+ }
+
+ if (!startDate || !endDate) {
+ this.$message.warning("请选择完整的时间跨度");
+ return;
+ }
+
+ this.pullBankInfoLoading = true;
+
+ try {
+ const payload = {
+ projectId: this.projectId,
+ idCards,
+ startDate,
+ endDate,
+ };
+ const res = await pullBankInfo(payload);
+
+ this.pullBankInfoDialogVisible = false;
+ this.resetPullBankInfoForm();
+ this.$message.success((res && res.msg) || "拉取任务已提交");
+
+ await Promise.all([this.loadStatistics(), this.loadFileList()]);
+
+ const hasPollingRecords =
+ this.statistics.uploading > 0 ||
+ this.statistics.parsing > 0 ||
+ this.fileUploadList.some((item) =>
+ ["uploading", "parsing"].includes(item.fileStatus)
+ );
+
+ if (hasPollingRecords) {
+ this.startPolling();
+ }
+ } catch (error) {
+ this.pullBankInfoLoading = false;
+ this.$message.error(
+ "拉取本行信息失败:" + ((error && error.message) || "未知错误")
+ );
+ }
+ },
/** 拉取本行信息 */
handleFetchBankInfo() {
this.resetPullBankInfoForm();
@@ -1412,6 +1539,12 @@ export default {
}
}
+.parse-tip {
+ margin-top: 8px;
+ font-size: 12px;
+ color: #909399;
+}
+
// 响应式
@media (max-width: 1200px) {
.upload-section .upload-cards {