500 lines
16 KiB
JavaScript
500 lines
16 KiB
JavaScript
// ==UserScript==
|
||
// @name 企业信息自动填写工具
|
||
// @namespace http://tampermonkey.net/
|
||
// @version 0.1
|
||
// @description 从剪贴板读取JSON数据并自动填写表单
|
||
// @author You
|
||
// @match https://intraecrm.yw.zj.chinamobile.com/page/newGroupAddCustome*
|
||
// @grant none
|
||
// ==/UserScript==
|
||
|
||
(function () {
|
||
"use strict";
|
||
|
||
/**
|
||
{
|
||
"企业名称": "杭州奥杰装饰工程有限公司",
|
||
"统一社会信用代码": "9133011031131201XU",
|
||
"法定代表人": "曾显军",
|
||
"经营状态": "开业",
|
||
"成立日期": "2014-08-05",
|
||
"行政区划": "浙江省杭州市余杭区",
|
||
"注册资本": "200万(元)",
|
||
"实缴资本": "200万(元)",
|
||
"企业类型": "有限责任公司(自然人独资)",
|
||
"所属行业": "批发业",
|
||
"工商注册号": "330184000311238",
|
||
"组织机构代码": "31131201-X",
|
||
"纳税人识别号": "9133011031131201XU",
|
||
"纳税人资质": "增值税一般纳税人",
|
||
"营业期限": "2014-08-05 至 2034-08-04",
|
||
"核准日期": "2020-08-24",
|
||
"参保人数": "3人",
|
||
"登记机关": "杭州市余杭区市场监督管理局",
|
||
"曾用名": "杭州茂复建材有限公司",
|
||
"注册地址": "浙江省杭州市余杭区五常街道郭家兜路8号1幢4楼408室",
|
||
"经营范围": "设计、施工:建筑工程、室内外装饰工程、幕墙工程;销售:建筑材料,装饰材料,石材,五金;服务:铝合金门窗上门安装,建筑工程技术咨询,国内广告设计和制作。(依法须经批准的项目,经相关部门批准后方可开展经营活动)"
|
||
}
|
||
*/
|
||
// 添加字段映射配置 - 新增代码
|
||
const FIELD_MAPPING = {
|
||
企业名称: { names: ["EC_CUST_NAME", "GROUP_NAME"] },
|
||
统一社会信用代码: { name: "CUST_CERT_CODE" },
|
||
法定代表人: { name: "LEGAL_CUST_NAME" },
|
||
注册地址: { name: "CUST_CERT_ADDRESS" },
|
||
证件有效期: { name: "CUST_CERT_EXPIRE", type: "date" },
|
||
集团客户状态: {
|
||
name: "GROUP_STATUS",
|
||
default: "潜在集团客户", // 添加默认值配置
|
||
},
|
||
"区县(网格平台)": {
|
||
name: "GRID_COUNTY_ID",
|
||
default: "余杭",
|
||
},
|
||
"网格(网格平台)": {
|
||
name: "GRID_ID",
|
||
default: "余杭未来科技城网格",
|
||
},
|
||
"片区(业务大厅)": {
|
||
name: "CHNL_REGION_DETAIL",
|
||
default: "余杭未来科技城网格",
|
||
},
|
||
"营业期限":{
|
||
name: "CUST_CERT_EXPIRE"
|
||
},
|
||
"电话":{
|
||
name:"CONT_PHONE"
|
||
},
|
||
"集团二级类型": {
|
||
name: "GROUP_TYPE2",
|
||
default: "小微企业",
|
||
}
|
||
};
|
||
|
||
function showAutoCloseMessage(message, type = "info") {
|
||
// 创建一个自动关闭的提示框替代 alert
|
||
const alertBox = document.createElement("div");
|
||
alertBox.textContent = message;
|
||
alertBox.style.position = "fixed";
|
||
alertBox.style.top = "50%";
|
||
alertBox.style.left = "50%";
|
||
alertBox.style.transform = "translate(-50%, -50%)";
|
||
|
||
// 根据消息类型设置不同颜色
|
||
if (type === "success") {
|
||
alertBox.style.backgroundColor = "#52c41a";
|
||
} else if (type === "error") {
|
||
alertBox.style.backgroundColor = "#f5222d";
|
||
} else {
|
||
alertBox.style.backgroundColor = "#1890ff";
|
||
}
|
||
|
||
alertBox.style.color = "white";
|
||
alertBox.style.padding = "10px 20px";
|
||
alertBox.style.borderRadius = "4px";
|
||
alertBox.style.zIndex = "10001";
|
||
alertBox.style.boxShadow = "0 2px 8px rgba(0,0,0,0.15)";
|
||
alertBox.style.transition = "opacity 0.3s";
|
||
|
||
document.body.appendChild(alertBox);
|
||
|
||
// 2秒后自动关闭
|
||
setTimeout(() => {
|
||
if (document.body.contains(alertBox)) {
|
||
// 添加淡出效果
|
||
alertBox.style.opacity = "0";
|
||
// 真正移除元素
|
||
setTimeout(() => {
|
||
if (document.body.contains(alertBox)) {
|
||
document.body.removeChild(alertBox);
|
||
}
|
||
}, 300);
|
||
}
|
||
}, 2000);
|
||
}
|
||
|
||
// 创建按钮容器
|
||
function createButtonContainer() {
|
||
const container = document.createElement("div");
|
||
container.id = "tool-container";
|
||
Object.assign(container.style, {
|
||
position: "fixed",
|
||
right: "20px",
|
||
bottom: "20px",
|
||
zIndex: "9999",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
gap: "10px",
|
||
width: "40px",
|
||
height: "40px",
|
||
backgroundColor: "#4CAF50",
|
||
borderRadius: "50%",
|
||
transition: "all 0.3s ease",
|
||
overflow: "hidden",
|
||
cursor: "move",
|
||
});
|
||
|
||
// +号指示器
|
||
const plusSign = document.createElement("div");
|
||
plusSign.textContent = "+";
|
||
Object.assign(plusSign.style, {
|
||
color: "white",
|
||
fontSize: "24px",
|
||
textAlign: "center",
|
||
lineHeight: "40px",
|
||
width: "100%",
|
||
});
|
||
container.appendChild(plusSign);
|
||
|
||
// 添加JSON输入框
|
||
const jsonInput = document.createElement("textarea");
|
||
jsonInput.placeholder = "粘贴JSON数据...";
|
||
Object.assign(jsonInput.style, {
|
||
width: "100%",
|
||
height: "100px",
|
||
padding: "8px",
|
||
borderRadius: "4px",
|
||
border: "1px solid #ddd",
|
||
resize: "vertical",
|
||
marginBottom: "5px",
|
||
display: "none", // 默认隐藏
|
||
position: "relative",
|
||
zIndex: "10000", // 确保在最上层显示
|
||
});
|
||
|
||
// 悬停展开效果
|
||
container.addEventListener("mouseenter", () => {
|
||
container.style.width = "180px";
|
||
container.style.height = "auto";
|
||
container.style.borderRadius = "8px";
|
||
|
||
// 强制显示输入框
|
||
jsonInput.style.display = "block";
|
||
});
|
||
|
||
container.addEventListener("mouseleave", () => {
|
||
container.style.width = "40px";
|
||
container.style.height = "40px";
|
||
container.style.borderRadius = "50%";
|
||
jsonInput.style.display = "none";
|
||
});
|
||
container.appendChild(jsonInput);
|
||
|
||
// 拖拽功能实现
|
||
let isDragging = false;
|
||
let offsetX, offsetY;
|
||
|
||
container.addEventListener("mousedown", (e) => {
|
||
if (e.target === plusSign || e.target === container) {
|
||
isDragging = true;
|
||
const rect = container.getBoundingClientRect();
|
||
offsetX = e.clientX - rect.left;
|
||
offsetY = e.clientY - rect.top;
|
||
container.style.cursor = "grabbing";
|
||
e.stopPropagation();
|
||
e.preventDefault();
|
||
}
|
||
});
|
||
|
||
document.addEventListener("mousemove", (e) => {
|
||
if (!isDragging) return;
|
||
container.style.left = e.clientX - offsetX + "px";
|
||
container.style.top = e.clientY - offsetY + "px";
|
||
container.style.right = "auto";
|
||
container.style.bottom = "auto";
|
||
});
|
||
|
||
document.addEventListener("mouseup", () => {
|
||
if (isDragging) {
|
||
isDragging = false;
|
||
container.style.cursor = "move";
|
||
}
|
||
});
|
||
|
||
// 创建功能按钮
|
||
function createButton(text, onClick) {
|
||
const button = document.createElement("button");
|
||
button.textContent = text;
|
||
Object.assign(button.style, {
|
||
padding: "10px",
|
||
border: "none",
|
||
borderRadius: "4px",
|
||
backgroundColor: "white",
|
||
color: "#333",
|
||
cursor: "pointer",
|
||
width: "100%",
|
||
transition: "backgroundColor 0.2s",
|
||
});
|
||
button.addEventListener(
|
||
"mouseenter",
|
||
() => (button.style.backgroundColor = "#f0f0f0")
|
||
);
|
||
button.addEventListener(
|
||
"mouseleave",
|
||
() => (button.style.backgroundColor = "white")
|
||
);
|
||
button.addEventListener("click", onClick);
|
||
return button;
|
||
}
|
||
|
||
// autoClickToAuditTab
|
||
const autoClickToAuditTabButton = createButton(
|
||
"自动点击审核建档tab",
|
||
async () => {
|
||
try {
|
||
// 1. 点击审核建档tab
|
||
const auditTab = Array.from(
|
||
document.querySelectorAll("div, span")
|
||
).find((el) => el.textContent.trim() === "审核建档");
|
||
if (!auditTab) {
|
||
throw new Error("未找到审核建档tab");
|
||
}
|
||
auditTab.click();
|
||
|
||
// 2. 等待页面加载完成
|
||
await waitForElementToDisappear("table:contains(页面信息加载中...)");
|
||
|
||
// 5. 点击手输证件按钮
|
||
const idButton = Array.from(document.querySelectorAll("button")).find(
|
||
(btn) => btn.textContent.includes("手输证件")
|
||
);
|
||
if (idButton) {
|
||
idButton.click();
|
||
} else {
|
||
console.warn("未找到手输证件按钮");
|
||
}
|
||
} catch (error) {
|
||
alert("点击失败: " + error.message);
|
||
console.error("自动点击错误:", error);
|
||
}
|
||
}
|
||
);
|
||
// 添加按钮到容器
|
||
container.appendChild(autoClickToAuditTabButton);
|
||
|
||
// 自动填写表单按钮
|
||
const autoFillButton = createButton("自动填写表单", async () => {
|
||
try {
|
||
// 获取JSON数据(优先使用输入框内容)
|
||
let jsonData = jsonInput.value.trim();
|
||
if (!jsonData) {
|
||
// 输入框为空时从剪贴板读取
|
||
jsonData = await navigator.clipboard.readText();
|
||
}
|
||
const companyInfo = JSON.parse(jsonData);
|
||
// 遍历字段映射配置而非JSON数据 - 修改这里
|
||
let filledCount = 0;
|
||
for (const [fieldKey, config] of Object.entries(FIELD_MAPPING)) {
|
||
// 获取值(JSON数据优先,其次使用默认值)
|
||
let value =
|
||
companyInfo[fieldKey] !== undefined
|
||
? companyInfo[fieldKey]
|
||
: config.default;
|
||
|
||
if("营业期限" == fieldKey){
|
||
value = getCustCertExpire(value)
|
||
}
|
||
if (value !== undefined) {
|
||
fillFormField(fieldKey, value);
|
||
filledCount++;
|
||
}
|
||
}
|
||
|
||
showAutoCloseMessage(
|
||
"表单填写完成!共填充 " + Object.keys(companyInfo).length + " 个字段",'success'
|
||
);
|
||
} catch (error) {
|
||
alert("填写失败: " + error.message);
|
||
console.error("自动填写错误:", error);
|
||
}
|
||
});
|
||
|
||
// 添加按钮到容器
|
||
container.appendChild(autoFillButton);
|
||
document.body.appendChild(container);
|
||
}
|
||
|
||
// 等待元素消失
|
||
function waitForElementToDisappear(selector) {
|
||
return new Promise((resolve, reject) => {
|
||
const checkInterval = setInterval(() => {
|
||
const element = document.querySelector(selector);
|
||
if (!element || !element.offsetParent) {
|
||
clearInterval(checkInterval);
|
||
resolve();
|
||
}
|
||
}, 300);
|
||
|
||
// 设置超时(30秒)
|
||
setTimeout(() => {
|
||
clearInterval(checkInterval);
|
||
reject(new Error("等待超时,页面加载未完成"));
|
||
}, 30000);
|
||
});
|
||
}
|
||
|
||
function getCustCertExpire(value){
|
||
if (value !== undefined) {
|
||
const businessTerm = value;
|
||
const endDate = parseEndDate(businessTerm);
|
||
|
||
// 检查是否需要设置为20年后的日期
|
||
if (!endDate || endDate === "9999-01-01" || endDate === "9999-1-1") {
|
||
const currentDate = new Date();
|
||
currentDate.setFullYear(currentDate.getFullYear() + 20);
|
||
const formattedDate = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2, '0')}-${String(currentDate.getDate()).padStart(2, '0')}`;
|
||
return formattedDate
|
||
} else {
|
||
return endDate
|
||
}
|
||
}
|
||
}
|
||
|
||
// 添加营业期限解析函数
|
||
function parseEndDate(businessTerm) {
|
||
if (!businessTerm || typeof businessTerm !== "string") return null;
|
||
|
||
// 分割"至"前后的日期
|
||
const parts = businessTerm.split('至').map(part => part.trim());
|
||
if (parts.length < 2) return null;
|
||
|
||
const endDateStr = parts[1];
|
||
// 验证日期格式并补全位数
|
||
if (/^\d{4}(-\d{1,2}){2}$/.test(endDateStr)) {
|
||
const [year, month, day] = endDateStr.split('-').map(Number);
|
||
return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
// 表单字段填充函数
|
||
function fillFormField(fieldName, value) {
|
||
// 优先使用字段映射 - 新增代码
|
||
const fieldConfig = FIELD_MAPPING[fieldName];
|
||
let opt = false;
|
||
if (fieldConfig) {
|
||
const doOpt = function (fieldConfigFieldName) {
|
||
// 按name属性精确查找
|
||
const input = document.querySelector(
|
||
`input[name="${fieldConfigFieldName}"], textarea[name="${fieldConfigFieldName}"], select[name="${fieldConfigFieldName}"]`
|
||
);
|
||
if (input) {
|
||
// 日期字段特殊处理
|
||
if (fieldConfig.type === "date" && value) {
|
||
// 直接设置值并触发WdatePicker所需事件
|
||
input.value = value;
|
||
input.dispatchEvent(new Event("focus"));
|
||
input.dispatchEvent(new Event("blur"));
|
||
} else if (input.tagName === "SELECT") {
|
||
Array.from(input.options).forEach((option) => {
|
||
if (option.value === value || option.textContent === value) {
|
||
option.selected = true;
|
||
}
|
||
});
|
||
// 触发change事件使选择生效
|
||
input.dispatchEvent(new Event("change"));
|
||
} else {
|
||
setInputValue(input, value);
|
||
}
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
if (fieldConfig.names) {
|
||
// 遍历names数组填充所有关联字段
|
||
fieldConfig.names.forEach((fieldConfigFieldName) => {
|
||
let optTmp = doOpt(fieldConfigFieldName);
|
||
if (optTmp) {
|
||
opt = true;
|
||
}
|
||
});
|
||
}
|
||
if (fieldConfig.name) {
|
||
let optTmp = doOpt(fieldConfig.name);
|
||
if (optTmp) {
|
||
opt = true;
|
||
}
|
||
}
|
||
}
|
||
if (opt) {
|
||
return true;
|
||
}
|
||
// 尝试通过label文本匹配
|
||
const labels = document.querySelectorAll("label");
|
||
for (const label of labels) {
|
||
if (label.textContent.trim().includes(fieldName)) {
|
||
const input =
|
||
label.querySelector("input, textarea, select") ||
|
||
document.getElementById(label.htmlFor);
|
||
if (input) {
|
||
setInputValue(input, value);
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 尝试通过input的placeholder匹配
|
||
const placeholders = document.querySelectorAll(
|
||
"input[placeholder], textarea[placeholder]"
|
||
);
|
||
for (const input of placeholders) {
|
||
if (input.placeholder.includes(fieldName)) {
|
||
setInputValue(input, value);
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// 尝试通过input的name属性匹配
|
||
const nameInputs = document.querySelectorAll(
|
||
`input[name*=${fieldName}], textarea[name*=${fieldName}]`
|
||
);
|
||
if (nameInputs.length > 0) {
|
||
setInputValue(nameInputs[0], value);
|
||
return true;
|
||
}
|
||
|
||
console.log(`未找到字段: ${fieldName}`);
|
||
return false;
|
||
}
|
||
|
||
// 设置输入框值
|
||
function setInputValue(input, value) {
|
||
if (!input) return;
|
||
|
||
// 根据输入框类型设置值
|
||
if (input.type === "checkbox") {
|
||
input.checked = value === "true" || value === true || value === "1";
|
||
} else if (input.type === "radio") {
|
||
const radio = document.querySelector(
|
||
`input[name="${input.name}"][value="${value}"]`
|
||
);
|
||
if (radio) radio.checked = true;
|
||
} else if (input.tagName === "SELECT") {
|
||
Array.from(input.options).forEach((option) => {
|
||
if (option.value === value || option.textContent === value) {
|
||
option.selected = true;
|
||
}
|
||
});
|
||
} else if (
|
||
input.tagName === "TEXTAREA" ||
|
||
input.type === "text" ||
|
||
input.type === "number" ||
|
||
input.type === "email"
|
||
) {
|
||
input.value = value;
|
||
// 触发输入事件以确保表单验证和相关逻辑执行
|
||
input.dispatchEvent(new Event("input", { bubbles: true }));
|
||
input.dispatchEvent(new Event("change", { bubbles: true }));
|
||
|
||
// 日期字段额外触发focus/blur事件 - 新增代码
|
||
if (input.classList.contains("Wdate")) {
|
||
input.dispatchEvent(new Event("focus"));
|
||
input.dispatchEvent(new Event("blur"));
|
||
}
|
||
}
|
||
}
|
||
|
||
// 初始化工具
|
||
createButtonContainer();
|
||
})(); |