Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:55:46 +08:00
commit b710247ba7
27 changed files with 6516 additions and 0 deletions

View File

@@ -0,0 +1,856 @@
/**
* 通用代码
* 包含工具函数和UI组件
*/
// ==================== 工具函数 ====================
/**
* 从URL查询参数中获取指定参数的值
* @param {string} name - 参数名称
* @returns {string|null} 参数值或null
*/
function getUrlParameter(name) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name);
}
/**
* 防抖函数
* @param {Function} func - 要防抖的函数
* @param {number} wait - 等待时间(毫秒)
* @returns {Function} 防抖后的函数
*/
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
/**
* 显示Toast消息
* @param {string} message - 消息内容
* @param {string} type - 消息类型 ('success', 'error', 'warning', 'info')
* @param {number} duration - 显示时长毫秒默认3000
*/
function showToast(message, type = 'info', duration = 3000) {
// 创建toast容器如果不存在
let toastContainer = document.getElementById('toast-container');
if (!toastContainer) {
toastContainer = document.createElement('div');
toastContainer.id = 'toast-container';
toastContainer.className = 'fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 z-50 space-y-2';
document.body.appendChild(toastContainer);
}
// 创建toast元素
const toast = document.createElement('div');
const bgColor = {
success: 'bg-green-500',
error: 'bg-red-500',
warning: 'bg-yellow-500',
info: 'bg-blue-500'
}[type] || 'bg-blue-500';
toast.className = `${bgColor} text-white px-4 py-2 rounded-lg shadow-lg transform transition-all duration-300 translate-x-full opacity-0`;
toast.textContent = message;
// 添加到容器
toastContainer.appendChild(toast);
// 显示动画
setTimeout(() => {
toast.classList.remove('translate-x-full', 'opacity-0');
}, 100);
// 自动隐藏
setTimeout(() => {
toast.classList.add('translate-x-full', 'opacity-0');
setTimeout(() => {
if (toast.parentNode) {
toast.parentNode.removeChild(toast);
}
}, 300);
}, duration);
}
/**
* 验证表单字段
* @param {Object} data - 表单数据
* @param {Object} rules - 验证规则
* @returns {Object} 验证结果 {isValid: boolean, errors: Object}
*/
function validateForm(data, rules) {
const errors = {};
let isValid = true;
for (const field in rules) {
const value = data[field];
const rule = rules[field];
// 必填验证
if (rule.required && (!value || value.toString().trim() === '')) {
errors[field] = rule.message || `${field}是必填项`;
isValid = false;
continue;
}
// 数字验证
if (rule.type === 'number' && value !== undefined && value !== '') {
const num = Number(value);
if (isNaN(num)) {
errors[field] = `${field}必须是数字`;
isValid = false;
continue;
}
if (rule.min !== undefined && num < rule.min) {
errors[field] = `${field}不能小于${rule.min}`;
isValid = false;
continue;
}
if (rule.max !== undefined && num > rule.max) {
errors[field] = `${field}不能大于${rule.max}`;
isValid = false;
continue;
}
}
// 字符串长度验证
if (rule.type === 'string' && value) {
if (rule.minLength && value.length < rule.minLength) {
errors[field] = `${field}长度不能少于${rule.minLength}个字符`;
isValid = false;
continue;
}
if (rule.maxLength && value.length > rule.maxLength) {
errors[field] = `${field}长度不能超过${rule.maxLength}个字符`;
isValid = false;
continue;
}
}
}
return { isValid, errors };
}
/**
* 深拷贝对象
* @param {any} obj - 要拷贝的对象
* @returns {any} 拷贝后的对象
*/
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (obj instanceof Date) {
return new Date(obj.getTime());
}
if (obj instanceof Array) {
return obj.map(item => deepClone(item));
}
if (typeof obj === 'object') {
const cloned = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloned[key] = deepClone(obj[key]);
}
}
return cloned;
}
return obj;
}
// ==================== UI组件 ====================
/**
* 顶部导航栏组件
*/
class HeaderNav {
constructor() {
this.element = document.getElementById('header-nav');
this.backBtn = document.getElementById('back-btn');
this.init();
}
/**
* 初始化导航栏事件
*/
init() {
this.backBtn.addEventListener('click', () => {
// 返回上一页或关闭页面
if (window.history.length > 1) {
window.history.back();
} else {
window.close();
}
});
}
}
/**
* 工单选择器组件
*/
class WorkOrderSelector {
constructor(onSelect) {
this.element = document.getElementById('work-order-selector');
this.selectedText = document.getElementById('selected-work-order-text');
this.dropdownArrow = document.getElementById('dropdown-arrow');
this.scanBtn = document.getElementById('scan-btn');
this.onSelect = onSelect;
this.selectedWorkOrder = null;
this.init();
}
/**
* 初始化选择器事件
*/
init() {
// 点击选择器展开下拉菜单
this.element.addEventListener('click', (e) => {
// 如果点击的是扫码按钮,不展开下拉菜单
if (e.target.closest('#scan-btn')) {
return;
}
this.onSelect();
});
// 扫码按钮事件
this.scanBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.handleScan();
});
}
/**
* 处理扫码功能
*/
handleScan() {
showToast('扫码功能开发中...', 'info');
// TODO: 实现扫码功能
}
/**
* 更新选中的工单显示
* @param {Object} workOrder - 工单对象
*/
updateSelected(workOrder) {
this.selectedWorkOrder = workOrder;
if (workOrder) {
this.selectedText.textContent = workOrder.id;
this.selectedText.className = 'text-gray-800 ml-2 font-medium';
} else {
this.selectedText.textContent = '请选择';
this.selectedText.className = 'text-gray-500 ml-2';
}
}
/**
* 切换下拉箭头状态
* @param {boolean} expanded - 是否展开
*/
toggleArrow(expanded) {
if (expanded) {
this.dropdownArrow.classList.add('rotate');
} else {
this.dropdownArrow.classList.remove('rotate');
}
}
}
/**
* 工单下拉菜单组件
*/
class WorkOrderDropdown {
constructor(onConfirm, onClose) {
this.element = document.getElementById('work-order-dropdown');
this.closeBtn = document.getElementById('close-dropdown');
this.searchInput = document.getElementById('search-input');
this.workOrderList = document.getElementById('work-order-list');
this.selectAllCheckbox = document.getElementById('select-all');
this.selectedCount = document.getElementById('selected-count');
this.confirmBtn = document.getElementById('confirm-selection');
this.onConfirm = onConfirm;
this.onClose = onClose;
this.workOrders = [];
this.filteredWorkOrders = [];
this.selectedWorkOrders = new Set();
this.init();
}
/**
* 初始化下拉菜单事件
*/
init() {
// 关闭按钮事件
this.closeBtn.addEventListener('click', () => {
this.hide();
});
// 点击背景关闭
this.element.addEventListener('click', (e) => {
if (e.target === this.element) {
this.hide();
}
});
// 搜索功能
this.searchInput.addEventListener('input', debounce((e) => {
this.filterWorkOrders(e.target.value);
}, 300));
// 全选功能
this.selectAllCheckbox.addEventListener('change', (e) => {
this.toggleSelectAll(e.target.checked);
});
// 确定按钮事件
this.confirmBtn.addEventListener('click', () => {
this.confirmSelection();
});
// ESC键关闭
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && this.isVisible()) {
this.hide();
}
});
}
/**
* 显示下拉菜单
*/
show() {
this.element.classList.remove('hidden');
this.element.classList.add('show');
document.body.style.overflow = 'hidden';
// 聚焦搜索框
setTimeout(() => {
this.searchInput.focus();
}, 300);
}
/**
* 隐藏下拉菜单
*/
hide() {
this.element.classList.remove('show');
document.body.style.overflow = '';
setTimeout(() => {
this.element.classList.add('hidden');
}, 300);
this.onClose();
}
/**
* 检查是否可见
* @returns {boolean}
*/
isVisible() {
return !this.element.classList.contains('hidden');
}
/**
* 设置工单数据
* @param {Array} workOrders - 工单数组
*/
setWorkOrders(workOrders) {
this.workOrders = workOrders;
this.filteredWorkOrders = [...workOrders];
this.renderWorkOrderList();
}
/**
* 过滤工单
* @param {string} searchTerm - 搜索关键词
*/
filterWorkOrders(searchTerm) {
const term = searchTerm.toLowerCase().trim();
if (!term) {
this.filteredWorkOrders = [...this.workOrders];
} else {
this.filteredWorkOrders = this.workOrders.filter(wo =>
wo.id.toLowerCase().includes(term) ||
(wo.name && wo.name.toLowerCase().includes(term))
);
}
this.renderWorkOrderList();
}
/**
* 渲染工单列表
*/
renderWorkOrderList() {
this.workOrderList.innerHTML = '';
if (this.filteredWorkOrders.length === 0) {
const emptyDiv = document.createElement('div');
emptyDiv.className = 'text-center py-8 text-gray-500';
emptyDiv.textContent = '没有找到匹配的工单';
this.workOrderList.appendChild(emptyDiv);
return;
}
this.filteredWorkOrders.forEach(workOrder => {
const item = this.createWorkOrderItem(workOrder);
this.workOrderList.appendChild(item);
});
this.updateSelectAllState();
}
/**
* 创建工单列表项
* @param {Object} workOrder - 工单对象
* @returns {HTMLElement}
*/
createWorkOrderItem(workOrder) {
const item = document.createElement('div');
item.className = 'work-order-item flex items-center space-x-3';
item.dataset.workOrderId = workOrder.id;
const isSelected = this.selectedWorkOrders.has(workOrder.id);
if (isSelected) {
item.classList.add('selected');
}
item.innerHTML = `
<input type="radio" name="work-order" value="${workOrder.id}"
class="checkbox-primary focus:ring-2" ${isSelected ? 'checked' : ''}>
<span class="flex-1 text-gray-800">${workOrder.id}</span>
`;
// 点击事件
item.addEventListener('click', () => {
this.selectWorkOrder(workOrder.id);
});
return item;
}
/**
* 选择工单
* @param {string} workOrderId - 工单ID
*/
selectWorkOrder(workOrderId) {
// 单选模式:清除之前的选择
this.selectedWorkOrders.clear();
this.selectedWorkOrders.add(workOrderId);
// 更新UI
this.workOrderList.querySelectorAll('.work-order-item').forEach(item => {
const radio = item.querySelector('input[type="radio"]');
const isSelected = item.dataset.workOrderId === workOrderId;
item.classList.toggle('selected', isSelected);
radio.checked = isSelected;
});
this.updateSelectedCount();
this.updateConfirmButton();
}
/**
* 切换全选状态
* @param {boolean} selectAll - 是否全选
*/
toggleSelectAll(selectAll) {
if (selectAll) {
this.filteredWorkOrders.forEach(wo => {
this.selectedWorkOrders.add(wo.id);
});
} else {
this.selectedWorkOrders.clear();
}
this.renderWorkOrderList();
this.updateSelectedCount();
this.updateConfirmButton();
}
/**
* 更新全选状态
*/
updateSelectAllState() {
const visibleCount = this.filteredWorkOrders.length;
const selectedVisibleCount = this.filteredWorkOrders.filter(wo =>
this.selectedWorkOrders.has(wo.id)
).length;
this.selectAllCheckbox.checked = visibleCount > 0 && selectedVisibleCount === visibleCount;
this.selectAllCheckbox.indeterminate = selectedVisibleCount > 0 && selectedVisibleCount < visibleCount;
}
/**
* 更新选中数量显示
*/
updateSelectedCount() {
this.selectedCount.textContent = `已选择${this.selectedWorkOrders.size}`;
}
/**
* 更新确定按钮状态
*/
updateConfirmButton() {
this.confirmBtn.disabled = this.selectedWorkOrders.size === 0;
}
/**
* 确认选择
*/
confirmSelection() {
if (this.selectedWorkOrders.size === 0) {
showToast('请选择工单', 'warning');
return;
}
const selectedIds = Array.from(this.selectedWorkOrders);
const selectedWorkOrder = this.workOrders.find(wo => wo.id === selectedIds[0]);
this.onConfirm(selectedWorkOrder);
this.hide();
}
/**
* 重置选择状态
*/
reset() {
this.selectedWorkOrders.clear();
this.searchInput.value = '';
this.filteredWorkOrders = [...this.workOrders];
this.renderWorkOrderList();
this.updateSelectedCount();
this.updateConfirmButton();
}
}
/**
* 物料信息组件
*/
class MaterialInfo {
constructor() {
this.element = document.getElementById('material-info');
this.workOrderId = document.getElementById('selected-work-order-id');
this.materialName = document.getElementById('material-name');
this.materialCode = document.getElementById('material-code');
this.qualifiedCount = document.getElementById('qualified-count');
this.defectiveCount = document.getElementById('defective-count');
this.pendingCount = document.getElementById('pending-count');
}
/**
* 显示物料信息
* @param {Object} data - 物料数据
*/
show(data) {
this.workOrderId.textContent = data.workOrderId;
this.materialName.textContent = data.materialName;
this.materialCode.textContent = data.materialCode;
this.qualifiedCount.textContent = data.qualifiedCount || 0;
this.defectiveCount.textContent = data.defectiveCount || 0;
this.pendingCount.textContent = data.pendingCount || 0;
this.element.classList.remove('hidden');
}
/**
* 隐藏物料信息
*/
hide() {
this.element.classList.add('hidden');
}
}
/**
* 报工表单组件
*/
class ReportForm {
constructor() {
this.element = document.getElementById('report-form');
this.quantityInput = document.getElementById('quantity');
this.auxiliaryQuantityInput = document.getElementById('auxiliary-quantity');
this.remarkInput = document.getElementById('remark');
this.workingHoursInput = document.getElementById('working-hours');
this.reportStartTimeInput = document.getElementById('report-start-time');
this.reportEndTimeInput = document.getElementById('report-end-time');
this.auxName = document.getElementById('auxName');
this.init();
}
/**
* 初始化表单事件
*/
init() {
// 数字输入验证
[this.quantityInput, this.auxiliaryQuantityInput].forEach(input => {
if (input) {
input.addEventListener('input', (e) => {
this.validateNumberInput(e.target);
});
}
});
// 表单字段变化时的验证
this.getAllInputs().forEach(input => {
if (input) {
input.addEventListener('blur', () => {
this.validateField(input);
});
}
});
}
/**
* 验证数字输入
* @param {HTMLInputElement} input - 输入元素
*/
validateNumberInput(input) {
if (!input) return;
const value = parseFloat(input.value);
if (isNaN(value) || value < 0) {
input.classList.add('border-red-500');
this.showFieldError(input, '请输入有效的数字');
} else {
input.classList.remove('border-red-500');
this.hideFieldError(input);
}
}
/**
* 验证单个字段
* @param {HTMLInputElement} input - 输入元素
*/
validateField(input) {
if (!input) return false;
const value = input.value.trim();
const isRequired = input.previousElementSibling?.querySelector('.text-red-500');
if (isRequired && !value) {
input.classList.add('border-red-500');
this.showFieldError(input, '此字段为必填项');
return false;
} else {
input.classList.remove('border-red-500');
this.hideFieldError(input);
return true;
}
}
/**
* 显示字段错误
* @param {HTMLInputElement} input - 输入元素
* @param {string} message - 错误消息
*/
showFieldError(input, message) {
let errorElement = input.parentNode.querySelector('.field-error');
if (!errorElement) {
errorElement = document.createElement('div');
// errorElement.className = 'field-error text-red-500 text-sm mt-1';
errorElement.className = 'field-error text-red-500 text-sm mt-1 w-full';
input.parentNode.appendChild(errorElement);
}
errorElement.textContent = message;
}
/**
* 隐藏字段错误
* @param {HTMLInputElement} input - 输入元素
*/
hideFieldError(input) {
const errorElement = input.parentNode.querySelector('.field-error');
if (errorElement) {
errorElement.remove();
}
}
/**
* 获取所有输入元素
* @returns {HTMLInputElement[]}
*/
getAllInputs() {
return [
this.quantityInput,
this.auxiliaryQuantityInput,
this.remarkInput,
this.workingHoursInput,
this.reportStartTimeInput,
this.reportEndTimeInput,
].filter(input => input !== null && input !== undefined);
}
/**
* 获取表单数据
* @returns {Object}
*/
getData() {
return {
quantity: parseFloat(this.quantityInput?.value) || 0,
auxiliaryQuantity: parseFloat(this.auxiliaryQuantityInput?.value) || 0,
remark: this.remarkInput?.value?.trim() || '',
workingHours: parseFloat(this.workingHoursInput?.value) || 0,
reportStartTime: this.reportStartTimeInput?.value?.trim() || '',
reportEndTimeInput: this.reportEndTimeInput?.value?.trim() || '',
};
}
/**
* 设置表单数据
* @param {Object} data - 表单数据
*/
setData(data) {
if (this.quantityInput) {
this.quantityInput.value = data.quantity || '';
}
if (this.auxiliaryQuantityInput) {
this.auxiliaryQuantityInput.value = data.auxiliaryQuantity || '';
}
}
setAuxName(data) {
if (this.auxName) {
this.auxName.innerText = data.auxName || '公斤';
}
}
/**
* 验证整个表单
* @returns {Object} 验证结果
*/
validate() {
const data = this.getData();
const rules = {
quantity: { required: true, type: 'number', min: 0 },
auxiliaryQuantity: { required: true, type: 'number', min: 0 }
};
return validateForm(data, rules);
}
/**
* 显示表单
*/
show() {
this.element.classList.remove('hidden');
}
/**
* 隐藏表单
*/
hide() {
this.element.classList.add('hidden');
}
/**
* 重置表单
*/
reset() {
this.getAllInputs().forEach(input => {
input.value = '';
input.classList.remove('border-red-500');
this.hideFieldError(input);
});
}
}
const GlobalLoading = {
element: null,
init() {
if (this.element) return;
this.element = document.createElement('div');
this.element.id = 'global-loading';
this.element.innerHTML = `
<div class="loading-backdrop"></div>
<div class="loading-spinner">
<div class="spinner"></div>
<div class="loading-text">加载中...</div>
</div>
`;
// 添加样式
const style = document.createElement('style');
style.textContent = `
#global-loading {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 9999;
display: none;
}
.loading-backdrop {
position: absolute;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
}
.loading-spinner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #007bff;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 10px;
}
.loading-text {
color: white;
font-size: 14px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
body.loading-active {
overflow: hidden;
}
`;
document.head.appendChild(style);
document.body.appendChild(this.element);
},
show(text = '加载中...') {
this.init();
const textElement = this.element.querySelector('.loading-text');
if (textElement) {
textElement.textContent = text;
}
this.element.style.display = 'block';
document.body.classList.add('loading-active');
},
hide() {
if (this.element) {
this.element.style.display = 'none';
document.body.classList.remove('loading-active');
}
}
};

View File

@@ -0,0 +1,457 @@
/**
* 主应用逻辑
* 管理页面状态、组件交互和业务流程
*/
class MainApp {
constructor() {
// 应用状态
this.state = {
currentView: 'empty', // empty, material, form
selectedWorkOrder: null,
materialData: null,
formData: null,
isLoading: false
};
// 组件实例
this.components = {};
// 初始化应用
this.init();
}
/**
* 初始化应用
*/
async init() {
try {
console.log('初始化报工应用...');
// 等待认证服务初始化完成
if (authService && !authService.isAuthenticated()) {
await this.waitForAuth();
}
// 初始化组件
this.initComponents();
// 绑定事件
this.bindEvents();
// 预加载数据
this.preloadData();
console.log('报工应用初始化完成');
} catch (error) {
console.error('应用初始化失败:', error);
showToast('应用初始化失败,请刷新页面重试', 'error');
}
}
/**
* 等待认证完成
*/
async waitForAuth() {
let retries = 0;
const maxRetries = 10;
while (!authService.isAuthenticated() && retries < maxRetries) {
await new Promise(resolve => setTimeout(resolve, 500));
retries++;
}
if (!authService.isAuthenticated()) {
console.warn('认证超时,继续使用离线模式');
}
}
/**
* 初始化组件
*/
initComponents() {
// 初始化顶部导航栏
this.components.headerNav = new HeaderNav();
// 初始化工单选择器
this.components.workOrderSelector = new WorkOrderSelector(() => {
this.showWorkOrderDropdown();
});
// 初始化工单下拉菜单
this.components.workOrderDropdown = new WorkOrderDropdown(
(workOrder) => this.onWorkOrderSelected(workOrder),
() => this.onWorkOrderDropdownClosed()
);
// 初始化物料信息组件
this.components.materialInfo = new MaterialInfo();
// 初始化报工表单组件
this.components.reportForm = new ReportForm();
console.log('组件初始化完成');
}
/**
* 绑定事件
*/
bindEvents() {
// 提交按钮事件
const submitBtn = document.getElementById('submit-btn');
if (submitBtn) {
submitBtn.addEventListener('click', () => {
this.handleSubmit();
});
}
// 网络状态变化事件
window.addEventListener('online', () => {
console.log('网络已连接');
showToast('网络已连接', 'success');
});
window.addEventListener('offline', () => {
console.log('网络已断开');
showToast('网络已断开,将使用离线模式', 'warning');
});
console.log('事件绑定完成');
}
/**
* 预加载数据
*/
async preloadData() {
try {
// 预加载工单数据
if (workOrderService) {
await workOrderService.preloadWorkOrders();
}
} catch (error) {
console.error('预加载数据失败:', error);
}
}
/**
* 显示工单下拉菜单
*/
async showWorkOrderDropdown() {
try {
this.setLoading(true);
// 获取工单列表
const workOrderData = await workOrderService.getWorkOrderList();
// 设置工单数据到下拉菜单
this.components.workOrderDropdown.setWorkOrders(workOrderData.workOrders);
// 显示下拉菜单
this.components.workOrderDropdown.show();
// 更新选择器箭头状态
this.components.workOrderSelector.toggleArrow(true);
} catch (error) {
console.error('加载工单列表失败:', error);
showToast('加载工单列表失败', 'error');
} finally {
this.setLoading(false);
}
}
/**
* 工单选择事件处理
* @param {Object} workOrder - 选中的工单
*/
async onWorkOrderSelected(workOrder) {
try {
console.log('选择工单:', workOrder);
this.setLoading(true);
// 更新状态
this.state.selectedWorkOrder = workOrder;
// 更新工单选择器显示
this.components.workOrderSelector.updateSelected(workOrder);
// 从工单数据中提取物料信息工单数据中已包含materialInfo
const materialData = this.extractMaterialDataFromWorkOrder(workOrder);
this.state.materialData = materialData;
// 切换到物料和表单视图
this.switchToMaterialView();
// 初始化表单数据
this.initializeFormData();
} catch (error) {
console.error('处理工单选择失败:', error);
showToast('处理工单选择失败', 'error');
} finally {
this.setLoading(false);
}
}
/**
* 从工单数据中提取物料信息
* @param {Object} workOrder - 工单对象
* @returns {Object} 物料数据
*/
extractMaterialDataFromWorkOrder(workOrder) {
// 从materialInfo中提取详细信息
const materialInfo = workOrder.materialInfo || {};
const materialBaseInfo = materialInfo.baseInfo || {};
// 提取单位转换关系
const conversions = materialInfo.conversions || [];
let unit = '个';
let auxiliaryUnit = '公斤';
if (conversions.length > 0) {
const firstConversion = conversions[0];
unit = firstConversion.fromUnitName || '个';
auxiliaryUnit = firstConversion.toUnitName || '公斤';
}
return {
workOrderId: workOrder.workOrderId || workOrder.id,
workOrderCode: workOrder.workOrderCode || workOrder.id,
materialId: workOrder.materialId || materialBaseInfo.id,
materialName: workOrder.materialName || materialBaseInfo.name || '',
materialCode: workOrder.materialCode || materialBaseInfo.code || '',
materialSpec: materialBaseInfo.specification || '',
unit: unit,
auxiliaryUnit: auxiliaryUnit,
conversions: conversions,
// 数量信息
qualifiedCount: workOrder.qualifiedQuantity || 0,
qualifiedCountDisplay: workOrder.qualifiedQuantityDisplay || '0',
defectiveCount: workOrder.disqualifiedQuantity || 0,
defectiveCountDisplay: workOrder.disqualifiedQuantityDisplay || '0',
pendingCount: Math.max(0, (workOrder.totalQuantity || 0) - (workOrder.qualifiedQuantity || 0) - (workOrder.disqualifiedQuantity || 0)),
totalCount: workOrder.totalQuantity,
unitId: materialInfo?.unit?.id
};
}
/**
* 工单下拉菜单关闭事件处理
*/
onWorkOrderDropdownClosed() {
// 更新选择器箭头状态
this.components.workOrderSelector.toggleArrow(false);
}
/**
* 切换到物料视图
*/
switchToMaterialView() {
// 隐藏空状态
const emptyState = document.getElementById('empty-state');
if (emptyState) {
emptyState.classList.add('hidden');
}
// 显示物料信息
this.components.materialInfo.show(this.state.materialData);
// 显示报工表单
this.components.reportForm.show();
// 显示提交按钮
const submitSection = document.getElementById('submit-section');
if (submitSection) {
submitSection.classList.remove('hidden');
}
// 更新状态
this.state.currentView = 'material';
this.components.reportForm.setAuxName({ auxName: this.state.materialData.unit });
}
/**
* 切换到空状态视图
*/
switchToEmptyView() {
// 显示空状态
const emptyState = document.getElementById('empty-state');
if (emptyState) {
emptyState.classList.remove('hidden');
}
// 隐藏物料信息
this.components.materialInfo.hide();
// 隐藏报工表单
this.components.reportForm.hide();
// 隐藏提交按钮
const submitSection = document.getElementById('submit-section');
if (submitSection) {
submitSection.classList.add('hidden');
}
// 重置状态
this.state.currentView = 'empty';
this.state.selectedWorkOrder = null;
this.state.materialData = null;
this.state.formData = null;
// 重置工单选择器
this.components.workOrderSelector.updateSelected(null);
console.log('切换到空状态视图');
}
/**
* 初始化表单数据
*/
initializeFormData() {
// 直接从 HTML 读取值,不设置默认值
const formData = this.components.reportForm.getData();
this.state.formData = formData;
}
/**
* 处理提交事件
*/
async handleSubmit() {
try {
// 验证表单
const validation = this.components.reportForm.validate();
if (!validation.isValid) {
const errorMessage = Object.values(validation.errors)[0];
showToast(errorMessage, 'error');
return;
}
// 获取表单数据
const formData = this.components.reportForm.getData();
console.log('表单数据:', formData);
// 构建报工数据
const reportData = {
workOrderId: this.state.selectedWorkOrder.workOrderId, // 使用数字类型的工单ID
workOrderCode: this.state.selectedWorkOrder.workOrderCode, // 同时传递工单编号作为备用
materialId: this.state.materialData.materialId,
quantity: formData.quantity,
auxiliaryQuantity: formData.auxiliaryQuantity,
remark: formData.remark,
workHour: formData.workingHours,
workHourUnit: 2,
auxUnitId1: this.state.materialData.unitId,
reportStartTime: formData.reportStartTime,
reportEndTime: formData.reportEndTimeInput
};
console.log('提交报工数据:', reportData);
// this.setLoading(true);
GlobalLoading.show('提交中...');
// 提交报工
const result = await reportService.submitReport(reportData);
console.log('报工提交结果:', result);
if (result.success) {
// 提交成功,重置表单
this.handleSubmitSuccess(result);
} else {
throw new Error(result.message || '提交失败');
}
} catch (error) {
console.error('提交报工失败:', error);
showToast(error.message || '提交失败', 'error');
} finally {
// this.setLoading(false);
GlobalLoading.hide();
}
}
/**
* 处理提交成功
* @param {Object} result - 提交结果
*/
handleSubmitSuccess(result) {
// 显示成功消息
showToast('报工提交成功', 'success');
// 重置表单
this.components.reportForm.reset();
// 重新初始化表单数据
this.initializeFormData();
}
/**
* 设置加载状态
* @param {boolean} loading - 是否加载中
*/
setLoading(loading) {
this.state.isLoading = loading;
// 更新提交按钮状态
const submitBtn = document.getElementById('submit-btn');
if (submitBtn) {
submitBtn.disabled = loading;
submitBtn.textContent = loading ? '提交中...' : '提交';
}
// 可以添加全局加载指示器
if (loading) {
document.body.style.cursor = 'wait';
} else {
document.body.style.cursor = '';
}
}
/**
* 重置应用状态
*/
reset() {
this.switchToEmptyView();
this.components.workOrderDropdown.reset();
console.log('应用状态已重置');
}
/**
* 获取应用状态
* @returns {Object}
*/
getState() {
return deepClone(this.state);
}
/**
* 销毁应用
*/
destroy() {
// 清理事件监听器
// 清理组件
// 清理定时器等
console.log('应用已销毁');
}
}
// 页面加载完成后初始化应用
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM加载完成初始化应用...');
// 创建全局应用实例
window.MainApp = new MainApp();
// 开发模式下暴露服务到全局
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
window.authService = authService;
window.apiService = apiService;
window.workOrderService = workOrderService;
window.reportService = reportService;
console.log('开发模式:服务已暴露到全局');
}
});