mds页面整合

This commit is contained in:
2026-05-15 20:55:23 +08:00
parent 0254ddc55d
commit 6e4d97dc0e
20 changed files with 2061 additions and 372 deletions
+104
View File
@@ -368,6 +368,105 @@ INTERNAL_FIELDS = {'memo', 'sys_user', 'sys_date', 'sys_stamp'}
EXCLUDE_FIELDS = ['_createtime', '_updatetime', 'sys_date', 'sys_stamp']
def extract_all_fields(schema_class, model_class) -> List[Dict[str, Any]]:
"""
从Schema和Model提取完整的字段元数据
Args:
schema_class: Pydantic Schema类
model_class: Tortoise Model类
Returns:
字段元数据列表
"""
fields = []
if not schema_class or not model_class:
return fields
# 获取字段映射
field_map = get_field_map(model_class)
for field_name, field_info in schema_class.model_fields.items():
if field_name.startswith('_'):
continue
# 判断字段类型
annotation = field_info.annotation
data_type = 'string'
# 判断数据类型
if isinstance(annotation, type):
if issubclass(annotation, (int, float)):
data_type = 'number'
elif issubclass(annotation, Enum):
data_type = 'enum'
# 获取枚举选项
enum_options = None
if data_type == 'enum' and hasattr(annotation, 'get_options'):
enum_options = annotation.get_options()
# 判断是否必填
is_required = field_info.is_required()
# 获取范围约束
ge = getattr(field_info, 'ge', None)
gt = getattr(field_info, 'gt', None)
le = getattr(field_info, 'le', None)
lt = getattr(field_info, 'lt', None)
# 获取最大长度
max_length = getattr(field_info, 'max_length', None)
# 获取描述
description = field_info.description or field_name
# 构建字段元数据
field_meta = {
"field": field_name,
"title": description,
"description": description,
"data_type": data_type,
"is_required": is_required,
"is_internal": False,
"enum_options": enum_options,
"range": {
"ge": ge,
"gt": gt,
"le": le,
"lt": lt
},
"max_length": max_length
}
fields.append(field_meta)
# 添加内部字段
internal_fields_config = {
'_staging_id', '_source_system', '_source_id', '_status',
'_error_msg', '_transform_rules', '_retry_count',
'_createtime', '_updatetime', '_synced_id', '_synced_time'
}
for field_name in internal_fields_config:
if field_name in model_class._meta.fields_map:
field = model_class._meta.fields_map[field_name]
fields.append({
"field": field_name,
"title": field.description or field_name,
"description": field.description or field_name,
"data_type": 'string',
"is_required": False,
"is_internal": True,
"enum_options": None,
"range": None,
"max_length": None
})
return fields
def generate_validation_rules_doc(table_key: str, config: Dict) -> Dict[str, Any]:
"""
生成完整的校验规则文档
@@ -386,6 +485,7 @@ def generate_validation_rules_doc(table_key: str, config: Dict) -> Dict[str, Any
doc = {
"table_name": extract_display_name_from_model(model_class),
"table_key": table_key,
"fields": [],
"required_fields": [],
"enum_fields": [],
@@ -396,6 +496,10 @@ def generate_validation_rules_doc(table_key: str, config: Dict) -> Dict[str, Any
"business_keys": []
}
# 完整字段元数据
if schema_class and model_class:
doc["fields"] = extract_all_fields(schema_class, model_class)
# 必填字段
if schema_class:
required_fields = extract_required_fields(schema_class)
+72 -21
View File
@@ -9,6 +9,71 @@ import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# MDS 页面配置字典
MDS_PAGE_CONFIG = {
"material": {
"page_title": "物料数据清洗管理",
"keyword_placeholder": "搜索物料号或描述...",
"config_file": "material.config.js"
},
"workcenter": {
"page_title": "工作中心数据清洗管理",
"keyword_placeholder": "搜索工作中心或描述...",
"config_file": "workcenter.config.js"
},
"mat-ver": {
"page_title": "产线版本数据清洗管理",
"keyword_placeholder": "搜索物料号或版本号...",
"config_file": "mat-ver.config.js"
},
"mat-wc": {
"page_title": "工艺路线数据清洗管理",
"keyword_placeholder": "搜索物料号或工作中心...",
"config_file": "mat-wc.config.js"
},
"mat-wc-bom": {
"page_title": "BOM数据清洗管理",
"keyword_placeholder": "搜索父件或子件料号...",
"config_file": "mat-wc-bom.config.js"
},
"mold": {
"page_title": "模具数据清洗管理",
"keyword_placeholder": "搜索模具编号或描述...",
"config_file": "mold.config.js"
},
"mat-wc-mold": {
"page_title": "机台模具数据清洗管理",
"keyword_placeholder": "搜索物料号或模具编号...",
"config_file": "mat-wc-mold.config.js"
}
}
def render_mds_page(page_key):
"""使用模板渲染MDS页面"""
template_path = os.path.join(BASE_DIR, "static", "mds", "pages", "template.html")
with open(template_path, "r", encoding="utf-8") as f:
template = f.read()
config = MDS_PAGE_CONFIG[page_key]
# 准备替换变量
replacements = {
"{page_title}": config["page_title"],
"{keyword_placeholder}": config["keyword_placeholder"],
"{config_file}": config["config_file"]
}
# 设置导航栏高亮
for key in MDS_PAGE_CONFIG.keys():
replacements[f"{{{key.replace('-', '_')}_active}}"] = "active" if key == page_key else ""
# 执行替换
html = template
for old, new in replacements.items():
html = html.replace(old, new)
return html
router = APIRouter()
@@ -55,42 +120,28 @@ def register_routes(app):
@app.get("/mds/material", response_class=HTMLResponse, include_in_schema=False)
async def mds_material():
file_path = os.path.join(BASE_DIR, "static", "mds", "pages", "material.html")
with open(file_path, "r", encoding="utf-8") as f:
return f.read()
return render_mds_page("material")
@app.get("/mds/workcenter", response_class=HTMLResponse, include_in_schema=False)
async def mds_workcenter():
file_path = os.path.join(BASE_DIR, "static", "mds", "pages", "workcenter.html")
with open(file_path, "r", encoding="utf-8") as f:
return f.read()
return render_mds_page("workcenter")
@app.get("/mds/mat-ver", response_class=HTMLResponse, include_in_schema=False)
async def mds_mat_ver():
file_path = os.path.join(BASE_DIR, "static", "mds", "pages", "mat-ver.html")
with open(file_path, "r", encoding="utf-8") as f:
return f.read()
return render_mds_page("mat-ver")
@app.get("/mds/mat-wc", response_class=HTMLResponse, include_in_schema=False)
async def mds_mat_wc():
file_path = os.path.join(BASE_DIR, "static", "mds", "pages", "mat-wc.html")
with open(file_path, "r", encoding="utf-8") as f:
return f.read()
return render_mds_page("mat-wc")
@app.get("/mds/mat-wc-bom", response_class=HTMLResponse, include_in_schema=False)
async def mds_mat_wc_bom():
file_path = os.path.join(BASE_DIR, "static", "mds", "pages", "mat-wc-bom.html")
with open(file_path, "r", encoding="utf-8") as f:
return f.read()
return render_mds_page("mat-wc-bom")
@app.get("/mds/mold", response_class=HTMLResponse, include_in_schema=False)
async def mds_mold():
file_path = os.path.join(BASE_DIR, "static", "mds", "pages", "mold.html")
with open(file_path, "r", encoding="utf-8") as f:
return f.read()
return render_mds_page("mold")
@app.get("/mds/mat-wc-mold", response_class=HTMLResponse, include_in_schema=False)
async def mds_mat_wc_mold():
file_path = os.path.join(BASE_DIR, "static", "mds", "pages", "mat-wc-mold.html")
with open(file_path, "r", encoding="utf-8") as f:
return f.read()
return render_mds_page("mat-wc-mold")
+207 -1
View File
@@ -1094,6 +1094,7 @@ async def batch_update_staging(request: Request, table_name: str, data: dict = B
| 2026-05-13 | v2.5 | 重大更新:多账套同步支持、前端内存泄漏修复、None值累加全面修复、错误信息格式统一、刷新同步逻辑优化 |
| 2026-05-14 | v3.0 | **架构级重构**:校验逻辑从硬编码转为配置驱动,通过Pydantic Schema自动提取校验规则,大幅提升可维护性和扩展性 |
| 2026-05-15 | v3.1 | **两阶段校验增强**:新增合规性校验、关联校验分阶段处理,新增校验规则文档化API,完善前端通用组件库 |
| 2026-05-15 | v3.2 | **前端架构重构**:通用控制器 + 配置驱动,所有表共用同一套代码,新增表只需编写配置文件 |
---
@@ -1841,7 +1842,212 @@ stats["rejected"] = stats.get("compliance_error", 0) + stats.get("relation_error
---
## 十二、v2.3版本更新详情
## 十二、v3.2版本更新详情
### 12.1 前端架构重构概览
**核心设计理念**:所有表共用同一套代码,新增表只需编写配置文件。
**架构演进**
| 阶段 | 实现方式 | 新增表成本 |
|------|----------|------------|
| v2.5- | 每个表单独编写JS + HTML | 数百行代码 |
| v3.0 | 配置驱动后端校验 | 数行配置 |
| v3.2 | 配置驱动前后端 | 仅需配置文件 |
### 12.2 配置文件设计
**新增配置目录**`static/mds/configs/`
**配置文件结构**
```javascript
// material.config.js
const MDS_PAGE_CONFIG = {
tableKey: 't_material',
tableDisplayName: '物料',
display: {
columns: [
{ field: '_status', title: '状态', width: '80px' },
{ field: '_createtime', title: '创建时间', width: '180px', sortable: true },
{ field: 'materialno', title: '物料号', width: '100px', sortable: true },
{ field: 'description', title: '物料描述', width: '150px' },
// ... 更多字段
],
defaultSortField: '_createtime',
defaultSortDir: 'desc',
advancedFilterCategories: {
stringFields: [...],
enumFields: [...],
dateFields: [...]
}
},
edit: {
fields: [...]
}
};
```
**配置文件清单**
| 配置文件 | 对应表 |
|----------|--------|
| `material.config.js` | t_material |
| `workcenter.config.js` | t_workcenter |
| `mat-ver.config.js` | t_mat_ver |
| `mat-wc.config.js` | t_mat_wc |
| `mat-wc-bom.config.js` | t_mat_wc_bom |
| `mold.config.js` | t_mold |
| `mat-wc-mold.config.js` | t_mat_wc_mold |
### 12.3 通用页面控制器
**新增核心文件**`mds-page-controller.js`1219行)
**控制器架构**
```javascript
class MDSPageController {
constructor(config) {
this.config = config;
this.tableKey = config.tableKey;
this.tableDisplayName = config.tableDisplayName;
this.tableMeta = null;
this.dataTable = null;
this.statusCard = null;
this.fieldValues = {};
this.nullFields = new Set();
this.init();
}
async init() {
await this.loadTableMeta();
this.initStatusCard();
this.initDataTable();
this.bindEvents();
}
// 从 /rules/{tableKey} API 加载校验规则元数据
async loadTableMeta() {
const response = await callApi(`/rules/${this.tableKey}`);
if (response.success === 1) {
this.tableMeta = response.data;
}
}
// 动态获取字段信息(从API元数据或配置文件)
getFieldLabel(fieldName) { ... }
getFieldType(fieldName) { ... }
getEnumOptions(fieldName) { ... }
isRequiredField(fieldName) { ... }
// 核心功能
loadData() { ... }
validateData() { ... }
approveData() { ... }
syncToProduction() { ... }
}
```
**核心特性**
1. **元数据驱动**:从 `/rules/{tableKey}` API 动态加载字段信息、枚举选项、必填字段
2. **配置驱动**:表特定配置(列定义、排序、筛选等)完全外部化
3. **完整功能**:数据加载、校验、审批、同步、编辑、删除等所有功能通用化
4. **模板页面**`template.html` 作为所有表的统一入口
### 12.4 页面模板化
**文件变更**
| 变更 | 说明 |
|------|------|
| 重命名 | `material.html``template.html` |
| 删除 | mat-ver.html、mat-wc-bom.html、mat-wc-mold.html、mat-wc.html、mold.html、workcenter.html |
**模板页面使用**
```html
<!-- template.html -->
<!DOCTYPE html>
<html>
<head>
<title>MDS - {{config.tableDisplayName}}</title>
<!-- 通用资源引用 -->
<script src="../configs/{{tableKey}}.config.js"></script>
<script src="../js/mds-page-controller.js"></script>
</head>
<body>
<!-- 通用模板结构 -->
</body>
</html>
```
### 12.5 后端配合更新
**新增路由**
```python
# routes_register.py
# 新增表的API路由注册
```
**全局常量更新**
```python
# globalconst.py
# 表配置更新
```
### 12.6 新增表开发流程(v3.2版本)
**新增表只需3步**
```
1. 后端:定义Schema + 配置 STAGING_TABLE_CONFIG
2. 前端:编写 {tableKey}.config.js 配置文件
3. 完成!
```
**对比v2.5版本**
| 阶段 | v2.5及之前 | v3.2 |
|------|------------|------|
| 后端 | 100+行代码 | Schema + 配置 |
| 前端 | 500+行代码 | 仅配置文件 |
| 总计 | >600行代码 | <100行配置 |
### 12.7 修改文件清单
| 文件 | 变更类型 | 核心改动 |
|------|----------|----------|
| `_base.py` | 优化 | 配合前端重构 |
| `routes_register.py` | 优化 | 新增路由注册 |
| `globalconst.py` | 优化 | 全局常量更新 |
| `mds-page-controller.js` | **新增** | 通用页面控制器(1219行) |
| `material.config.js` | **新增** | 物料表配置 |
| `workcenter.config.js` | **新增** | 工作中心表配置 |
| `mat-ver.config.js` | **新增** | 产线版本表配置 |
| `mat-wc.config.js` | **新增** | 工艺路线表配置 |
| `mat-wc-bom.config.js` | **新增** | 物料清单表配置 |
| `mold.config.js` | **新增** | 模具表配置 |
| `mat-wc-mold.config.js` | **新增** | 机台模具关联表配置 |
| `material.js` | 优化 | 简化为配置驱动 |
| `template.html` | **重命名** | `material.html``template.html` |
| 5个旧页面文件 | **删除** | 不再需要单独的页面文件 |
---
## 十三、v2.3版本更新详情
### 9.1 校验错误详情展示
+57
View File
@@ -10,6 +10,13 @@ NONE_AND_EMPTY = {None, ""}
class YesNoEnum(str, Enum):
YES = "Y"
NO = "N"
@classmethod
def get_options(cls):
return [
{"value": "Y", "label": "是(Y)"},
{"value": "N", "label": "否(N)"}
]
class LotSizeEnum(str, Enum):
@@ -29,11 +36,39 @@ class LotSizeEnum(str, Enum):
M1 = "M1" # 按1月合并
M2 = "M2" # 按2月合并
M3 = "M3" # 按3月合并
@classmethod
def get_options(cls):
return [
{"value": "EX", "label": "一对一(EX)"},
{"value": "FX", "label": "固定批(FX)"},
{"value": "VB", "label": "重订货点(VB)"},
{"value": "D1", "label": "按1天合并(D1)"},
{"value": "D2", "label": "按2天合并(D2)"},
{"value": "D3", "label": "按3天合并(D3)"},
{"value": "D4", "label": "按4天合并(D4)"},
{"value": "D5", "label": "按5天合并(D5)"},
{"value": "D6", "label": "按6天合并(D6)"},
{"value": "W1", "label": "按1周合并(W1)"},
{"value": "W2", "label": "按2周合并(W2)"},
{"value": "W3", "label": "按3周合并(W3)"},
{"value": "W4", "label": "按4周合并(W4)"},
{"value": "M1", "label": "按1月合并(M1)"},
{"value": "M2", "label": "按2月合并(M2)"},
{"value": "M3", "label": "按3月合并(M3)"}
]
class ProductCategoryEnum(str, Enum):
MTO = "MTO" # MTO
MTS = "MTS" # MTS
@classmethod
def get_options(cls):
return [
{"value": "MTO", "label": "按订单生产(MTO)"},
{"value": "MTS", "label": "按库存生产(MTS)"}
]
class SupplyTypeEnum(str, Enum):
@@ -67,16 +102,38 @@ class AbcEnum(str, Enum):
A = "A"
B = "B"
C = "C"
@classmethod
def get_options(cls):
return [
{"value": "A", "label": "A类"},
{"value": "B", "label": "B类"},
{"value": "C", "label": "C类"}
]
class EfEnum(str, Enum):
E = "E"
F = "F"
@classmethod
def get_options(cls):
return [
{"value": "E", "label": "自制件(E)"},
{"value": "F", "label": "采购件(F)"}
]
class SfEnum(str, Enum):
S = "S"
F = "F"
@classmethod
def get_options(cls):
return [
{"value": "S", "label": "S"},
{"value": "F", "label": "F"}
]
class StaticString(str, Enum):
+39
View File
@@ -0,0 +1,39 @@
const MDS_PAGE_CONFIG = {
tableKey: 't_mat_ver',
tableDisplayName: '产线版本',
display: {
columns: [
{ field: '_status', title: '状态', width: '80px' },
{ field: '_createtime', title: '创建时间', width: '180px', sortable: true },
{ field: 'materialno', title: '物料号', width: '120px', sortable: true },
{ field: 'matver', title: '版本号', width: '80px', sortable: true },
{ field: 'description', title: '描述', width: '200px' },
{ field: 'active', title: '激活', width: '80px' },
{ field: 'lotfrom', title: '批量下限', width: '100px' },
{ field: 'lotto', title: '批量上限', width: '100px' },
{ field: '_source_system', title: '来源', width: '80px' }
],
defaultSortField: '_createtime',
defaultSortDir: 'desc',
advancedFilterCategories: {
stringFields: [
{ value: 'MaterialNo', label: '物料号' },
{ value: 'MatVer', label: '版本号' },
{ value: 'Description', label: '描述' }
],
numberFields: [
{ value: 'LotFrom', label: '批量下限' },
{ value: 'LotTo', label: '批量上限' }
],
enumFields: [
{ value: 'Active', label: '激活', options: [
{ value: 'Y', label: '是' },
{ value: 'N', label: '否' }
]}
]
}
}
};
+46
View File
@@ -0,0 +1,46 @@
const MDS_PAGE_CONFIG = {
tableKey: 't_mat_wc_bom',
tableDisplayName: 'BOM',
display: {
columns: [
{ field: '_status', title: '状态', width: '80px' },
{ field: '_createtime', title: '创建时间', width: '180px', sortable: true },
{ field: 'productno', title: '父件料号', width: '120px', sortable: true },
{ field: 'matver', title: '版本号', width: '80px' },
{ field: 'itemno', title: '工序号', width: '80px' },
{ field: 'materialno', title: '子件料号', width: '120px' },
{ field: 'qty', title: '用量', width: '100px' },
{ field: 'scrap', title: '损耗率', width: '80px' },
{ field: 'mto', title: 'MTO', width: '80px' },
{ field: 'alt', title: '替代料', width: '80px' },
{ field: '_source_system', title: '来源', width: '80px' }
],
defaultSortField: '_createtime',
defaultSortDir: 'desc',
advancedFilterCategories: {
stringFields: [
{ value: 'ProductNo', label: '父件料号' },
{ value: 'MatVer', label: '版本号' },
{ value: 'ItemNo', label: '工序号' },
{ value: 'MaterialNo', label: '子件料号' }
],
numberFields: [
{ value: 'Qty', label: '用量' },
{ value: 'Scrap', label: '损耗率' }
],
enumFields: [
{ value: 'MTO', label: 'MTO', options: [
{ value: 'Y', label: '是' },
{ value: 'N', label: '否' }
]},
{ value: 'Alt', label: '替代料', options: [
{ value: 'Y', label: '是' },
{ value: 'N', label: '否' }
]}
]
}
}
};
+35
View File
@@ -0,0 +1,35 @@
const MDS_PAGE_CONFIG = {
tableKey: 't_mat_wc_mold',
tableDisplayName: '机台模具',
display: {
columns: [
{ field: '_status', title: '状态', width: '80px' },
{ field: '_createtime', title: '创建时间', width: '180px', sortable: true },
{ field: 'materialno', title: '物料号', width: '120px', sortable: true },
{ field: 'workcenter', title: '工作中心', width: '100px' },
{ field: 'itemno', title: '工序号', width: '80px' },
{ field: 'moldno', title: '模具编号', width: '120px' },
{ field: 'basesec', title: 'UPH', width: '100px' },
{ field: 'priority', title: '优先级', width: '80px' },
{ field: '_source_system', title: '来源', width: '80px' }
],
defaultSortField: '_createtime',
defaultSortDir: 'desc',
advancedFilterCategories: {
stringFields: [
{ value: 'MaterialNo', label: '物料号' },
{ value: 'WorkCenter', label: '工作中心' },
{ value: 'ItemNo', label: '工序号' },
{ value: 'MoldNo', label: '模具编号' }
],
numberFields: [
{ value: 'BaseSec', label: 'UPH' },
{ value: 'Priority', label: '优先级' }
],
enumFields: []
}
}
};
+41
View File
@@ -0,0 +1,41 @@
const MDS_PAGE_CONFIG = {
tableKey: 't_mat_wc',
tableDisplayName: '工艺路线',
display: {
columns: [
{ field: '_status', title: '状态', width: '80px' },
{ field: '_createtime', title: '创建时间', width: '180px', sortable: true },
{ field: 'materialno', title: '物料号', width: '120px', sortable: true },
{ field: 'matver', title: '版本号', width: '80px' },
{ field: 'itemno', title: '工序号', width: '80px' },
{ field: 'workcenter', title: '工作中心', width: '100px' },
{ field: 'sf', title: '串并行', width: '80px' },
{ field: 'basesec', title: '基础工时', width: '100px' },
{ field: 'sortno', title: '排序', width: '80px' },
{ field: '_source_system', title: '来源', width: '80px' }
],
defaultSortField: '_createtime',
defaultSortDir: 'desc',
advancedFilterCategories: {
stringFields: [
{ value: 'MaterialNo', label: '物料号' },
{ value: 'MatVer', label: '版本号' },
{ value: 'ItemNo', label: '工序号' },
{ value: 'WorkCenter', label: '工作中心' }
],
numberFields: [
{ value: 'BaseSec', label: '基础工时' },
{ value: 'SortNo', label: '排序' }
],
enumFields: [
{ value: 'SF', label: '串并行', options: [
{ value: 'S', label: '串行' },
{ value: 'P', label: '并行' }
]}
]
}
}
};
+111
View File
@@ -0,0 +1,111 @@
const MDS_PAGE_CONFIG = {
tableKey: 't_material',
tableDisplayName: '物料',
display: {
columns: [
{ field: '_status', title: '状态', width: '80px' },
{ field: '_createtime', title: '创建时间', width: '180px', sortable: true },
{ field: 'materialno', title: '物料号', width: '100px', sortable: true },
{ field: 'description', title: '物料描述', width: '150px' },
{ field: 'size', title: '规格' },
{ field: 'plant', title: '工厂', width: '70px' },
{ field: 'planner', title: '计划员' },
{ field: 'fifo', title: 'FIFO', width: '50px' },
{ field: 'leadday', title: '提前期', width: '60px' },
{ field: 'expday', title: '保质期', width: '60px' },
{ field: 'grday', title: '质检期', width: '60px' },
{ field: 'abc', title: 'ABC', width: '50px' },
{ field: 'unit', title: '单位', width: '50px' },
{ field: 'price', title: '价格', width: '80px' },
{ field: 'groupno', title: '型号' },
{ field: 'type', title: '类型', width: '50px' },
{ field: 'phantom', title: '虚拟件', width: '60px' },
{ field: 'phantommin', title: '虚拟时间', width: '70px' },
{ field: 'firmday', title: '固定天数', width: '60px' },
{ field: 'daygap', title: '拆分天数', width: '60px' },
{ field: 'candelay', title: '可延迟', width: '60px' },
{ field: 'lotsize', title: '批量策略', width: '70px' },
{ field: 'lotfix', title: '固定批', width: '60px' },
{ field: 'lotmin', title: '最小批', width: '60px' },
{ field: 'lotmax', title: '最大批', width: '60px' },
{ field: 'lotround', title: '取整值', width: '60px' },
{ field: 'lotss', title: '安全库存', width: '60px' },
{ field: 'lotpoint', title: '订货点', width: '60px' },
{ field: 'lottop', title: '最大库存', width: '60px' },
{ field: 'planitem', title: '产品组' },
{ field: 'preday', title: '向前冲销', width: '60px' },
{ field: 'subday', title: '向后冲销', width: '60px' },
{ field: 'free1', title: '自定义1' },
{ field: 'free2', title: '自定义2' },
{ field: 'free3', title: '自定义3' },
{ field: '_source_system', title: '来源', width: '80px' }
],
defaultSortField: '_createtime',
defaultSortDir: 'desc',
advancedFilterCategories: {
stringFields: [
{ value: 'MaterialNo', label: '物料号' },
{ value: 'Description', label: '物料描述' },
{ value: 'Plant', label: '工厂' },
{ value: 'Planner', label: '计划员' },
{ value: 'Unit', label: '单位' }
],
numberFields: [
{ value: 'LeadDay', label: '提前期' },
{ value: 'ExpDay', label: '保质期' },
{ value: 'GRDay', label: '质检期' },
{ value: 'Price', label: '价格' },
{ value: 'PhantomMin', label: '虚拟时间' },
{ value: 'FirmDay', label: '固定天' },
{ value: 'DayGap', label: '拆分天' },
{ value: 'LotFix', label: '固定批' },
{ value: 'LotMin', label: '最小批' },
{ value: 'LotMax', label: '最大批' }
],
enumFields: [
{ value: 'ABC', label: 'ABC分类', options: [
{ value: 'A', label: 'A类' },
{ value: 'B', label: 'B类' },
{ value: 'C', label: 'C类' }
]},
{ value: 'Type', label: '类型', options: [
{ value: 'E', label: '自制件(E)' },
{ value: 'F', label: '采购件(F)' }
]},
{ value: 'Phantom', label: '虚拟件', options: [
{ value: 'Y', label: '是(Y)' },
{ value: 'N', label: '否(N)' }
]},
{ value: 'CanDelay', label: '可延迟', options: [
{ value: 'Y', label: '是(Y)' },
{ value: 'N', label: '否(N)' }
]},
{ value: 'LotSize', label: '批量策略', options: [
{ value: 'EX', label: '一对一(EX)' },
{ value: 'FX', label: '固定批(FX)' },
{ value: 'VB', label: '重订货点(VB)' },
{ value: 'D1', label: '按1天合并(D1)' },
{ value: 'D2', label: '按2天合并(D2)' },
{ value: 'D3', label: '按3天合并(D3)' },
{ value: 'D4', label: '按4天合并(D4)' },
{ value: 'D5', label: '按5天合并(D5)' },
{ value: 'D6', label: '按6天合并(D6)' },
{ value: 'W1', label: '按1周合并(W1)' },
{ value: 'W2', label: '按2周合并(W2)' },
{ value: 'W3', label: '按3周合并(W3)' },
{ value: 'W4', label: '按4周合并(W4)' },
{ value: 'M1', label: '按1月合并(M1)' },
{ value: 'M2', label: '按2月合并(M2)' },
{ value: 'M3', label: '按3月合并(M3)' }
]},
{ value: 'FIFO', label: 'FIFO', options: [
{ value: '0', label: '最近原则' },
{ value: '1', label: 'FIFO' }
]}
]
}
}
};
+46
View File
@@ -0,0 +1,46 @@
const MDS_PAGE_CONFIG = {
tableKey: 't_mold',
tableDisplayName: '模具',
display: {
columns: [
{ field: '_status', title: '状态', width: '80px' },
{ field: '_createtime', title: '创建时间', width: '180px', sortable: true },
{ field: 'moldno', title: '模具编号', width: '120px', sortable: true },
{ field: 'moldname', title: '描述', width: '200px' },
{ field: 'type', title: '类型', width: '100px' },
{ field: 'status', title: '状态', width: '100px' },
{ field: 'moldnum', title: '穴数', width: '80px' },
{ field: 'qty', title: '台数', width: '80px' },
{ field: '_source_system', title: '来源', width: '80px' }
],
defaultSortField: '_createtime',
defaultSortDir: 'desc',
advancedFilterCategories: {
stringFields: [
{ value: 'MoldNo', label: '模具编号' },
{ value: 'MoldName', label: '描述' }
],
numberFields: [
{ value: 'MoldNum', label: '穴数' },
{ value: 'Qty', label: '台数' }
],
enumFields: [
{ value: 'Type', label: '类型', options: [
{ value: '注塑', label: '注塑' },
{ value: '冲压', label: '冲压' },
{ value: '压铸', label: '压铸' },
{ value: '夹具', label: '夹具' }
]},
{ value: 'Status', label: '状态', options: [
{ value: '空闲', label: '空闲' },
{ value: '生产中', label: '生产中' },
{ value: '维修中', label: '维修中' },
{ value: '报废', label: '报废' }
]}
]
}
}
};
+40
View File
@@ -0,0 +1,40 @@
const MDS_PAGE_CONFIG = {
tableKey: 't_workcenter',
tableDisplayName: '工作中心',
display: {
columns: [
{ field: '_status', title: '状态', width: '80px' },
{ field: '_createtime', title: '创建时间', width: '180px', sortable: true },
{ field: 'workcenter', title: '工作中心', width: '120px', sortable: true },
{ field: 'description', title: '描述', width: '200px' },
{ field: 'bottleneck', title: '瓶颈', width: '80px' },
{ field: 'finite', title: '有限产能', width: '100px' },
{ field: 'capacity', title: '产能', width: '100px' },
{ field: '_source_system', title: '来源', width: '80px' }
],
defaultSortField: '_createtime',
defaultSortDir: 'desc',
advancedFilterCategories: {
stringFields: [
{ value: 'WorkCenter', label: '工作中心' },
{ value: 'Description', label: '描述' }
],
numberFields: [
{ value: 'Capacity', label: '产能' }
],
enumFields: [
{ value: 'Bottleneck', label: '瓶颈', options: [
{ value: 'Y', label: '是' },
{ value: 'N', label: '否' }
]},
{ value: 'Finite', label: '有限产能', options: [
{ value: 'Y', label: '是' },
{ value: 'N', label: '否' }
]}
]
}
}
};
+22 -23
View File
@@ -374,18 +374,17 @@ async function syncData() {
}
const stats = response.data;
const validatedCount = stats.validated || 0;
const validatedCount = stats.relation_pass || stats.validated || 0;
const retryExceeded = stats.retry_exceeded || 0;
if (validatedCount === 0) {
showMessage('没有校验通过的记录可同步', 'warning');
return;
showMessage('没有外键通过的记录可推送', 'warning');
}
// 如果有超过重试次数的记录,询问是否重置
let resetRetry = false;
if (retryExceeded > 0) {
resetRetry = confirm(`${retryExceeded}条记录的重试次数已达上限,是否重置重试次数后同步\n\n点击"确定"重置并同步,点击"取消"跳过这些记录`);
resetRetry = confirm(`${retryExceeded}条记录的重试次数已达上限,是否重置重试次数后推送\n\n点击"确定"重置并推送,点击"取消"跳过这些记录`);
}
const { mode, targetDbs } = await showSyncModeDialog(validatedCount);
@@ -394,7 +393,7 @@ async function syncData() {
const targetDbParam = targetDbs.join(',');
const totalCount = validatedCount * targetDbs.length;
showProgress(mode === 'incremental' ? '增量同步中' : '刷新同步中', totalCount);
showProgress(mode === 'incremental' ? '增量推送中' : '刷新推送中', totalCount);
let totalSynced = 0;
let totalFailed = 0;
@@ -405,14 +404,14 @@ async function syncData() {
// 刷新模式只调用一次,增量模式循环调用
if (mode === 'refresh') {
// 刷新模式:一次性同步
// 刷新模式:一次性推送
setProgressIndeterminate(true);
const syncResponse = await callApi(baseUrl, 'POST');
setProgressIndeterminate(false);
if (syncResponse.success !== 1) {
hideProgress();
showMessage(syncResponse.message || '同步失败', 'danger');
showMessage(syncResponse.message || '推送失败', 'danger');
} else {
const syncStats = syncResponse.data;
totalSynced = syncStats.total_synced || 0;
@@ -421,9 +420,9 @@ async function syncData() {
// 根据成功/失败显示不同消息
if (totalFailed > 0) {
showMessage(`同步完成: ${targetDbs.length}个账套, 成功${totalSynced}条, 失败${totalFailed}条(部分记录缺少必填字段)`, 'warning');
showMessage(`推送完成: ${targetDbs.length}个账套, 成功${totalSynced}条, 失败${totalFailed}条(部分记录缺少必填字段)`, 'warning');
} else {
showMessage(`同步完成: ${targetDbs.length}个账套, 成功${totalSynced}`, 'success');
showMessage(`推送完成: ${targetDbs.length}个账套, 成功${totalSynced}`, 'success');
}
}
} else {
@@ -438,7 +437,7 @@ async function syncData() {
if (syncResponse.success !== 1) {
hideProgress();
showMessage(syncResponse.message || '同步失败', 'danger');
showMessage(syncResponse.message || '推送失败', 'danger');
break;
}
@@ -463,9 +462,9 @@ async function syncData() {
// 根据成功/失败显示不同消息
if (totalFailed > 0) {
showMessage(`同步完成: ${targetDbs.length}个账套, 成功${totalSynced}条, 失败${totalFailed}条(部分记录缺少必填字段)`, 'warning');
showMessage(`推送完成: ${targetDbs.length}个账套, 成功${totalSynced}条, 失败${totalFailed}条(部分记录缺少必填字段)`, 'warning');
} else {
showMessage(`同步完成: ${targetDbs.length}个账套, 成功${totalSynced}`, 'success');
showMessage(`推送完成: ${targetDbs.length}个账套, 成功${totalSynced}`, 'success');
}
}
@@ -486,7 +485,7 @@ async function showSyncModeDialog(validatedCount) {
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">选择同步模式</h5>
<h5 class="modal-title">选择推送模式</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
@@ -500,35 +499,35 @@ async function showSyncModeDialog(validatedCount) {
</div>
`).join('')}
</div>
<div class="form-text">默认全选可取消勾选排除不需要同步的账套</div>
<div class="form-text">默认全选可取消勾选排除不需要推送的账套</div>
</div>
<hr>
<div class="mb-3">
<label class="form-label fw-bold">同步模式</label>
<label class="form-label fw-bold">推送模式</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="syncMode" id="modeIncremental" value="incremental" checked>
<label class="form-check-label" for="modeIncremental">
<strong>增量同步</strong> <span class="badge bg-primary">${validatedCount}</span>
<strong>增量推送</strong> <span class="badge bg-primary">${validatedCount}</span>
</label>
<div class="text-muted small mt-1">同步校验通过的新数据保留正式表现有数据</div>
<div class="text-muted small mt-1">推送校验通过的新数据保留正式表现有数据</div>
</div>
</div>
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="radio" name="syncMode" id="modeRefresh" value="refresh">
<label class="form-check-label" for="modeRefresh">
<strong>刷新同步</strong> <span class="badge bg-warning text-dark">${validatedCount}</span>
<strong>刷新推送</strong> <span class="badge bg-warning text-dark">${validatedCount}</span>
</label>
<div class="text-muted small mt-1">清空正式表后重新同步校验通过的数据</div>
<div class="text-muted small mt-1">清空正式表后重新推送校验通过的数据</div>
</div>
</div>
<div class="alert alert-warning small mb-0">
<i class="bi bi-exclamation-triangle"></i> <strong></strong>
<i class="bi bi-exclamation-triangle"></i> <strong></strong>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="confirmSyncBtn">开始同步</button>
<button type="button" class="btn btn-primary" id="confirmSyncBtn">开始推送</button>
</div>
</div>
</div>
@@ -562,7 +561,7 @@ async function showSyncModeDialog(validatedCount) {
}
async function syncAllData() {
if (!confirm('确定要同步所有校验通过的数据吗?')) return;
if (!confirm('确定要推送所有校验通过的数据吗?')) return;
showLoading();
@@ -571,7 +570,7 @@ async function syncAllData() {
hideLoading();
handleResponse(response, (data) => {
showMessage('所有表同步完成', 'success');
showMessage('所有表推送完成', 'success');
dataTable.refresh();
statusCard.refresh();
});
File diff suppressed because it is too large Load Diff
-51
View File
@@ -1,51 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>产线版本数据清洗管理</title>
<link href="/static/mds/css/bootstrap.min.css" rel="stylesheet">
<script src="/static/mds/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-2">
<div class="container-fluid">
<a class="navbar-brand" href="/mds">📊 数据清洗管理系统</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="/mds/material">📦 物料</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/workcenter">🏭 工作中心</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="/mds/mat-ver">📋 产线版本</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc">🛠️ 工艺路线</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-bom">📐 BOM</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mold">🔧 模具</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-mold">🔩 机台模具</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="alert alert-info text-center py-5">
<h3>产线版本数据清洗管理</h3>
<p class="mb-0">功能开发中,敬请期待...</p>
</div>
</div>
</body>
</html>
-51
View File
@@ -1,51 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BOM数据清洗管理</title>
<link href="/static/mds/css/bootstrap.min.css" rel="stylesheet">
<script src="/static/mds/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-2">
<div class="container-fluid">
<a class="navbar-brand" href="/mds">📊 数据清洗管理系统</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="/mds/material">📦 物料</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/workcenter">🏭 工作中心</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-ver">📋 产线版本</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc">🛠️ 工艺路线</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="/mds/mat-wc-bom">📐 BOM</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mold">🔧 模具</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-mold">🔩 机台模具</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="alert alert-info text-center py-5">
<h3>BOM数据清洗管理</h3>
<p class="mb-0">功能开发中,敬请期待...</p>
</div>
</div>
</body>
</html>
-51
View File
@@ -1,51 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>机台模具关联数据清洗管理</title>
<link href="/static/mds/css/bootstrap.min.css" rel="stylesheet">
<script src="/static/mds/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-2">
<div class="container-fluid">
<a class="navbar-brand" href="/mds">📊 数据清洗管理系统</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="/mds/material">📦 物料</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/workcenter">🏭 工作中心</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-ver">📋 产线版本</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc">🛠️ 工艺路线</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-bom">📐 BOM</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mold">🔧 模具</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="/mds/mat-wc-mold">🔩 机台模具</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="alert alert-info text-center py-5">
<h3>机台模具关联数据清洗管理</h3>
<p class="mb-0">功能开发中,敬请期待...</p>
</div>
</div>
</body>
</html>
-51
View File
@@ -1,51 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>工艺路线数据清洗管理</title>
<link href="/static/mds/css/bootstrap.min.css" rel="stylesheet">
<script src="/static/mds/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-2">
<div class="container-fluid">
<a class="navbar-brand" href="/mds">📊 数据清洗管理系统</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="/mds/material">📦 物料</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/workcenter">🏭 工作中心</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-ver">📋 产线版本</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="/mds/mat-wc">🛠️ 工艺路线</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-bom">📐 BOM</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mold">🔧 模具</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-mold">🔩 机台模具</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="alert alert-info text-center py-5">
<h3>工艺路线数据清洗管理</h3>
<p class="mb-0">功能开发中,敬请期待...</p>
</div>
</div>
</body>
</html>
-51
View File
@@ -1,51 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模具数据清洗管理</title>
<link href="/static/mds/css/bootstrap.min.css" rel="stylesheet">
<script src="/static/mds/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-2">
<div class="container-fluid">
<a class="navbar-brand" href="/mds">📊 数据清洗管理系统</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="/mds/material">📦 物料</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/workcenter">🏭 工作中心</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-ver">📋 产线版本</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc">🛠️ 工艺路线</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-bom">📐 BOM</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="/mds/mold">🔧 模具</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-mold">🔩 机台模具</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="alert alert-info text-center py-5">
<h3>模具数据清洗管理</h3>
<p class="mb-0">功能开发中,敬请期待...</p>
</div>
</div>
</body>
</html>
@@ -3,12 +3,11 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>物料数据清洗管理</title>
<title>{page_title}</title>
<link href="/static/mds/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="/static/mds/css/custom.css">
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-2">
<div class="container-fluid">
<a class="navbar-brand" href="/mds">📊 数据清洗管理系统</a>
@@ -18,57 +17,58 @@
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link active" href="/mds/material">📦 物料</a>
<a class="nav-link {material_active}" href="/mds/material">📦 物料</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/workcenter">🏭 工作中心</a>
<a class="nav-link {workcenter_active}" href="/mds/workcenter">🏭 工作中心</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-ver">📋 产线版本</a>
<a class="nav-link {mat_ver_active}" href="/mds/mat-ver">📋 产线版本</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc">🛠️ 工艺路线</a>
<a class="nav-link {mat_wc_active}" href="/mds/mat-wc">🛠️ 工艺路线</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-bom">📐 BOM</a>
<a class="nav-link {mat_wc_bom_active}" href="/mds/mat-wc-bom">📐 BOM</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mold">🔧 模具</a>
<a class="nav-link {mold_active}" href="/mds/mold">🔧 模具</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-mold">🔩 机台模具</a>
<a class="nav-link {mat_wc_mold_active}" href="/mds/mat-wc-mold">🔩 机台模具</a>
</li>
</ul>
<div class="d-flex gap-2">
<button class="btn btn-outline-light btn-sm" style="width:100px" id="validateAllBtn">校验全部</button>
<button class="btn btn-outline-light btn-sm" style="width:100px" id="syncAllBtn">同步全部</button>
<button class="btn btn-outline-light btn-sm" style="width:100px" id="syncAllBtn">推送全部</button>
</div>
</div>
</div>
</nav>
<div class="container-fluid py-2">
<!-- 状态统计卡片 -->
<div class="row mb-2">
<div class="col-12" id="statusCardContainer"></div>
</div>
<!-- 操作按钮 + 筛选区域 -->
<div class="filter-bar mb-2">
<div class="row g-2 align-items-center">
<div class="col-auto">
<button class="btn btn-primary btn-sm" style="width:100px" data-bs-toggle="modal" data-bs-target="#uploadModal">导入</button>
<button class="btn btn-success btn-sm" style="width:100px" id="validateBtn">校验</button>
<button class="btn btn-info btn-sm" style="width:100px" id="syncBtn">同步</button>
<button class="btn btn-info btn-sm" style="width:100px" id="syncBtn">推送</button>
<button class="btn btn-outline-warning btn-sm" style="width:100px" id="rulesBtn">校验规则</button>
</div>
<div class="col-auto ms-auto">
<button class="btn btn-outline-info btn-sm" style="width:100px" id="downloadTemplateBtn">下载模板</button>
</div>
<div class="col-auto">
<select class="form-select form-select-sm" id="statusFilter" style="width:100px">
<option value="">全部状态</option>
<option value="pending">待处理</option>
<option value="validated">校验通过</option>
<option value="rejected">校验失败</option>
<option value="synced">同步</option>
<option value="synced">推送</option>
</select>
</div>
<div class="col-auto">
@@ -81,7 +81,7 @@
</select>
</div>
<div class="col-auto flex-grow-1">
<input type="text" class="form-control form-control-sm" id="keywordInput" placeholder="搜索物料号或描述...">
<input type="text" class="form-control form-control-sm" id="keywordInput" placeholder="{keyword_placeholder}">
</div>
<div class="col-auto">
<button class="btn btn-primary btn-sm" id="searchBtn">查询</button>
@@ -91,11 +91,9 @@
</div>
</div>
<!-- 数据列表区域 -->
<div class="data-table-container" id="tableContainer"></div>
</div>
<!-- 上传弹窗 -->
<div class="modal fade" id="uploadModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
@@ -125,7 +123,6 @@
</div>
</div>
<!-- 精准筛选弹窗 -->
<div class="modal fade" id="advancedFilterModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
@@ -177,7 +174,6 @@
</div>
</div>
<!-- 批量编辑弹窗 -->
<div class="modal fade" id="batchEditModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
@@ -203,7 +199,6 @@
</div>
</div>
<!-- 编辑弹窗 -->
<div class="modal fade" id="editModal" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content">
@@ -228,6 +223,12 @@
<script src="/static/mds/js/api-client.js"></script>
<script src="/static/mds/js/data-table.js"></script>
<script src="/static/mds/js/status-card.js"></script>
<script src="/static/mds/js/material.js"></script>
<script src="/static/mds/configs/{config_file}"></script>
<script src="/static/mds/js/mds-page-controller.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
new MDSPageController(MDS_PAGE_CONFIG);
});
</script>
</body>
</html>
-51
View File
@@ -1,51 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>工作中心数据清洗管理</title>
<link href="/static/mds/css/bootstrap.min.css" rel="stylesheet">
<script src="/static/mds/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-2">
<div class="container-fluid">
<a class="navbar-brand" href="/mds">📊 数据清洗管理系统</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="/mds/material">📦 物料</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="/mds/workcenter">🏭 工作中心</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-ver">📋 产线版本</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc">🛠️ 工艺路线</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-bom">📐 BOM</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mold">🔧 模具</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/mds/mat-wc-mold">🔩 机台模具</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="alert alert-info text-center py-5">
<h3>工作中心数据清洗管理</h3>
<p class="mb-0">功能开发中,敬请期待...</p>
</div>
</div>
</body>
</html>