抓变化
This commit is contained in:
parent
3ce40dd036
commit
a59c925d56
42
preload.js
42
preload.js
|
|
@ -1,29 +1,29 @@
|
||||||
const { contextBridge, ipcRenderer } = require('electron');
|
const {contextBridge, ipcRenderer} = require('electron');
|
||||||
|
|
||||||
// 暴露安全的API给渲染进程
|
// 暴露安全的API给渲染进程
|
||||||
contextBridge.exposeInMainWorld('electronAPI', {
|
contextBridge.exposeInMainWorld('electronAPI', {
|
||||||
// 文件操作
|
// 文件操作
|
||||||
selectExcelFile: () => ipcRenderer.invoke('select-excel-file'),
|
selectExcelFile: () => ipcRenderer.invoke('select-excel-file'),
|
||||||
|
|
||||||
// 数据库操作
|
// 数据库操作
|
||||||
getProjects: () => ipcRenderer.invoke('get-projects'),
|
getProjects: () => ipcRenderer.invoke('get-projects'),
|
||||||
getProjectsRange: () => ipcRenderer.invoke('get-projects-range'),
|
getProjectsRange: () => ipcRenderer.invoke('get-projects-range'),
|
||||||
getTreeStructure: () => ipcRenderer.invoke('get-tree-structure'),
|
getTreeStructure: () => ipcRenderer.invoke('get-tree-structure'),
|
||||||
filterProjects: (filters) => ipcRenderer.invoke('filter-projects', filters),
|
filterProjects: (filters) => ipcRenderer.invoke('filter-projects', filters),
|
||||||
updateProject: (project) => ipcRenderer.invoke('update-project', project),
|
updateProject: (project) => ipcRenderer.invoke('update-project', project),
|
||||||
deleteProject: (projectId) => ipcRenderer.invoke('delete-project', projectId),
|
deleteProject: (projectId) => ipcRenderer.invoke('delete-project', projectId),
|
||||||
|
|
||||||
// Excel处理
|
// Excel处理
|
||||||
importExcel: (filePath) => ipcRenderer.invoke('import-excel', filePath),
|
importExcel: (filePath) => ipcRenderer.invoke('import-excel', filePath),
|
||||||
|
|
||||||
// 数据清除
|
// 数据清除
|
||||||
clearAllData: () => ipcRenderer.invoke('clear-all-data'),
|
clearAllData: () => ipcRenderer.invoke('clear-all-data'),
|
||||||
|
|
||||||
// 事件监听
|
// 事件监听
|
||||||
onImportProgress: (callback) => {
|
onImportProgress: (callback) => {
|
||||||
// 移除之前的监听器,避免重复
|
// 移除之前的监听器,避免重复
|
||||||
ipcRenderer.removeAllListeners('import-progress');
|
ipcRenderer.removeAllListeners('import-progress');
|
||||||
// 添加新的监听器
|
// 添加新的监听器
|
||||||
ipcRenderer.on('import-progress', (event, data) => callback(data));
|
ipcRenderer.on('import-progress', (event, data) => callback(data));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
20
src/App.js
20
src/App.js
|
|
@ -29,6 +29,8 @@ function App() {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [isDarkMode] = useState(true); // 固定使用深色主题
|
const [isDarkMode] = useState(true); // 固定使用深色主题
|
||||||
const [lastImportedFilePath, setLastImportedFilePath] = useState(null); // 记录最后导入的文件路径
|
const [lastImportedFilePath, setLastImportedFilePath] = useState(null); // 记录最后导入的文件路径
|
||||||
|
// 根据选中的节点筛选项目数据
|
||||||
|
let select = {};
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -111,8 +113,6 @@ function App() {
|
||||||
const key = selectedKeys[0];
|
const key = selectedKeys[0];
|
||||||
setSelectedNode(key);
|
setSelectedNode(key);
|
||||||
|
|
||||||
// 根据选中的节点筛选项目数据
|
|
||||||
let filters = {};
|
|
||||||
|
|
||||||
if (key === 'headquarters') {
|
if (key === 'headquarters') {
|
||||||
// 总部节点,显示所有数据
|
// 总部节点,显示所有数据
|
||||||
|
|
@ -120,17 +120,17 @@ function App() {
|
||||||
} else if (key.startsWith('unit-')) {
|
} else if (key.startsWith('unit-')) {
|
||||||
// 单位节点,筛选该单位的数据
|
// 单位节点,筛选该单位的数据
|
||||||
const unit = key.replace('unit-', '');
|
const unit = key.replace('unit-', '');
|
||||||
filters = {unit};
|
select = {unit};
|
||||||
} else if (key.startsWith('construction-')) {
|
} else if (key.startsWith('construction-')) {
|
||||||
// 建设单位节点,筛选该建设单位的数据
|
// 建设单位节点,筛选该建设单位的数据
|
||||||
const parts = key.split('-');
|
const parts = key.split('-');
|
||||||
const unit = parts[1];
|
const unit = parts[1];
|
||||||
const constructionUnit = parts.slice(2).join('-');
|
const constructionUnit = parts.slice(2).join('-');
|
||||||
filters = {unit, constructionUnit};
|
select = {unit, constructionUnit};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应用筛选
|
// 应用筛选
|
||||||
filterProjects(filters);
|
filterProjects(select);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -159,16 +159,17 @@ function App() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应用筛选
|
// 应用筛选
|
||||||
filterProjects(filters);
|
filterProjects({ ...filters, ...select });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理项目搜索
|
// 处理项目搜索
|
||||||
const handleSearch = (text) => {
|
const handleSearch = (text) => {
|
||||||
setSearchText(text);
|
|
||||||
|
|
||||||
|
setSearchText(text);
|
||||||
|
console.log(select)
|
||||||
// 根据搜索文本筛选项目数据
|
// 根据搜索文本筛选项目数据
|
||||||
const filters = {subProjectName: text};
|
const filters = {subProjectName: text};
|
||||||
filterProjects(filters);
|
filterProjects({ ...filters, ...select });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理项目选择
|
// 处理项目选择
|
||||||
|
|
@ -261,6 +262,7 @@ function App() {
|
||||||
const progressMessage = document.getElementById('import-progress-message');
|
const progressMessage = document.getElementById('import-progress-message');
|
||||||
|
|
||||||
if (progressBar && progressMessage) {
|
if (progressBar && progressMessage) {
|
||||||
|
const antProgressText = progressBar.querySelector('.ant-progress-text');
|
||||||
// 更新进度条
|
// 更新进度条
|
||||||
const antProgress = progressBar.querySelector('.ant-progress-bg');
|
const antProgress = progressBar.querySelector('.ant-progress-bg');
|
||||||
if (antProgress) {
|
if (antProgress) {
|
||||||
|
|
@ -270,7 +272,7 @@ function App() {
|
||||||
|
|
||||||
// 更新文本
|
// 更新文本
|
||||||
progressMessage.textContent = data.message;
|
progressMessage.textContent = data.message;
|
||||||
|
antProgressText.textContent = `${data.progress}%`;
|
||||||
// 如果导入完成,关闭对话框并重新加载数据
|
// 如果导入完成,关闭对话框并重新加载数据
|
||||||
if (data.status === 'complete') {
|
if (data.status === 'complete') {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, {useEffect} from 'react';
|
import React, {useEffect} from 'react';
|
||||||
import {Modal, Form, Input, Select, Switch, Button} from 'antd';
|
import {Modal, Form, Input, Select, Switch, Button, InputNumber} from 'antd';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
@ -104,14 +104,26 @@ const ProjectDetailForm = ({visible, project, onCancel, onSave}) => {
|
||||||
<Form.Item label="下次梳理时间" name="next_review_time">
|
<Form.Item label="下次梳理时间" name="next_review_time">
|
||||||
<Input placeholder="YYYY-MM-DD"/>
|
<Input placeholder="YYYY-MM-DD"/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="参建人数" name="participants_count">
|
<Form.Item label="参建人数" name="participants_count"
|
||||||
<Input type="number"/>
|
rules={[
|
||||||
|
{type: 'number', min: 1, message: '必须为正整数'},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<InputNumber min={1} precision={0} style={{width: '100%'}}/>
|
||||||
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="新班组进场数量" name="new_team_count">
|
<Form.Item label="新班组进场数量" name="new_team_count" rules={[
|
||||||
<Input type="number"/>
|
{type: 'number', min: 1, message: '必须为正整数'},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<InputNumber min={1} precision={0} style={{width: '100%'}}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="新人进场数量" name="new_person_count">
|
<Form.Item label="新人进场数量" name="new_person_count" rules={[
|
||||||
<Input type="number"/>
|
{type: 'number', min: 1, message: '必须为正整数'},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<InputNumber min={1} precision={0} style={{width: '100%'}}/>
|
||||||
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="带班人姓名、电话" name="leader_info">
|
<Form.Item label="带班人姓名、电话" name="leader_info">
|
||||||
<Input/>
|
<Input/>
|
||||||
|
|
@ -144,19 +156,50 @@ const ProjectDetailForm = ({visible, project, onCancel, onSave}) => {
|
||||||
|
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<div>
|
<div>
|
||||||
<p style={{fontSize: '20px', fontWeight: 'bold'}}>人的变化</p>
|
<p style={{fontSize: '20px', fontWeight: 'bold'}}>人的变化</p><Form.Item
|
||||||
<Form.Item label="新进班组数量" name="new_team">
|
label="新进班组数量"
|
||||||
<Input type="number"/>
|
name="new_team"
|
||||||
|
rules={[
|
||||||
|
{ message: '请输入新进班组数量'},
|
||||||
|
{type: 'number', min: 1, message: '必须为正整数'},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<InputNumber min={1} precision={0} style={{width: '100%'}}/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
label="新进班组骨干数量"
|
||||||
|
name="new_members"
|
||||||
|
rules={[
|
||||||
|
{message: '请输入新进班组骨干数量'},
|
||||||
|
{type: 'number', min: 1, message: '必须为正整数'},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<InputNumber min={1} precision={0} style={{width: '100%'}}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="新进班组骨干数量" name="new_members">
|
|
||||||
<Input type="number"/>
|
<Form.Item
|
||||||
|
label="新进高空人员数量"
|
||||||
|
name="new_high_altitude"
|
||||||
|
rules={[
|
||||||
|
{message: '请输入新进高空人员数量'},
|
||||||
|
{type: 'number', min: 1, message: '必须为正整数'},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<InputNumber min={1} precision={0} style={{width: '100%'}}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="新进高空人员数量" name="new_high_altitude">
|
|
||||||
<Input type="number"/>
|
<Form.Item
|
||||||
</Form.Item>
|
label="新进一般人员数量"
|
||||||
<Form.Item label="新进一般人员数量" name="new_hired_general">
|
name="new_hired_general"
|
||||||
<Input type="number"/>
|
rules={[
|
||||||
|
{message: '请输入新进一般人员数量'},
|
||||||
|
{type: 'number', min: 1, message: '必须为正整数'},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<InputNumber min={1} precision={0} style={{width: '100%'}}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -202,13 +202,46 @@ class ExcelService {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
// 如果是日期类型,转换为ISO格式
|
// 如果是日期类型,转换为ISO格式
|
||||||
if (fieldName === '实际开工时间' || fieldName === '计划竣工时间' || fieldName === '完成时间' || fieldName === '下次梳理时间(注意与 隐患提示/工作要求 对应)') {
|
if (
|
||||||
const date = new Date(value);
|
fieldName === '实际开工时间' ||
|
||||||
if (!isNaN(date.getTime())) {
|
fieldName === '计划竣工时间' ||
|
||||||
|
fieldName === '完成时间' ||
|
||||||
|
fieldName === '下次梳理时间(注意与 隐患提示/工作要求 对应)'
|
||||||
|
) {
|
||||||
|
if (value == null) return ''; // 空值处理
|
||||||
|
|
||||||
return date.toISOString().split('T')[0]; // 只保留日期部分
|
// ✅ Excel 日期序列号(一般从 25569 开始)
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
if (value > 1e12 && value < 1e14) {
|
||||||
|
// ✅ 毫秒级时间戳
|
||||||
|
const date = new Date(value);
|
||||||
|
if (!isNaN(date.getTime())) return date.toISOString().split('T')[0];
|
||||||
|
} else {
|
||||||
|
// ✅ Excel 序列号转日期(从 1900-01-01 起,第1天是 1)
|
||||||
|
const utcDays = Math.floor(value - 25569);
|
||||||
|
const utcValue = utcDays * 86400; // 转秒
|
||||||
|
const date = new Date(utcValue * 1000);
|
||||||
|
if (!isNaN(date.getTime())) return date.toISOString().split('T')[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
let parsed = new Date(value);
|
||||||
|
if (!isNaN(parsed.getTime())) return parsed.toISOString().split('T')[0];
|
||||||
|
|
||||||
|
// ✅ 支持“5-12”、“5月12日” 等格式
|
||||||
|
const matched = value.match(/^(\d{1,2})[月/-](\d{1,2})/);
|
||||||
|
if (matched) {
|
||||||
|
const year = new Date().getFullYear(); // 默认今年
|
||||||
|
const mm = matched[1].padStart(2, '0');
|
||||||
|
const dd = matched[2].padStart(2, '0');
|
||||||
|
return `${year}-${mm}-${dd}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ''; // 未能解析,返回空字符串
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -270,7 +303,10 @@ class ExcelService {
|
||||||
processedRows++;
|
processedRows++;
|
||||||
if (processedRows % 10 === 0 || processedRows === totalRows) {
|
if (processedRows % 10 === 0 || processedRows === totalRows) {
|
||||||
const progress = Math.floor(50 + (processedRows / totalRows) * 20); // 50%-70%的进度
|
const progress = Math.floor(50 + (processedRows / totalRows) * 20); // 50%-70%的进度
|
||||||
|
|
||||||
if (global.mainWindow) {
|
if (global.mainWindow) {
|
||||||
|
|
||||||
|
console.log("进度+++",progress)
|
||||||
global.mainWindow.webContents.send('import-progress', {
|
global.mainWindow.webContents.send('import-progress', {
|
||||||
status: 'saving',
|
status: 'saving',
|
||||||
progress: progress,
|
progress: progress,
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ code {
|
||||||
.ant-tree {
|
.ant-tree {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
color: var(--vscode-text) !important;
|
color: var(--vscode-text) !important;
|
||||||
}
|
}mm
|
||||||
|
|
||||||
.ant-tree-node-content-wrapper:hover {
|
.ant-tree-node-content-wrapper:hover {
|
||||||
background-color: var(--vscode-hover-item) !important;
|
background-color: var(--vscode-hover-item) !important;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue