Files
bj_power/_inject_detail.py
T
SunYF 672cd23329 feat: 新增多类功能并优化现有流程
1. 工序工位支持0号上线位,更新解析逻辑与注释
2. 物料清单模块重命名为产品物料清单并优化文案
3. WMS与工位端新增用户/角色详情抽屉组件
4. 工单模块新增自动生成工单号、工位分组选择器
5. 日排产支持批量生成与详情查看
6. 工单列表重构操作菜单与表单优化
2026-09-18 13:54:30 +08:00

147 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# 为列表页自动注入「详情」按钮 + DetailDrawer 抽屉。
# 字段从已有 <el-table-column> 抽取(中文 label 复用,type:time 自动识别)。
import re, sys, os
SKIP_LABELS = {'操作', '图片', '操作人', '附件', '明细', '记录', '步骤'}
def parse_columns(tpl):
fields = []
seen = set()
col_re = re.compile(r'<el-table-column\b([^>]*?)(/?>)', re.S)
i = 0
while True:
m = col_re.search(tpl, i)
if not m:
break
attrs = m.group(1)
closing = m.group(2)
if closing == '/>':
block = m.group(0)
i = m.end()
else:
k = tpl.find('</el-table-column>', m.end())
if k < 0:
i = m.end()
continue
block = tpl[m.start():k + len('</el-table-column>')]
i = k + len('</el-table-column>')
m_prop = re.search(r'prop="([^"]+)"', block)
m_label = re.search(r'label="([^"]+)"', block)
m_time = re.search(r'fmtTime\(row\.(\w+)\)', block)
m_dynamic = re.search(r':label=', block)
if not m_label or m_dynamic:
continue
label = m_label.group(1)
if label in SKIP_LABELS:
continue
if m_time:
key = m_time.group(1)
if key not in seen:
fields.append({'key': key, 'label': label, 'type': 'time'})
seen.add(key)
continue
if m_prop:
key = m_prop.group(1)
if key not in seen:
fields.append({'key': key, 'label': label})
seen.add(key)
return fields
def fmt_field(f):
if f.get('type') == 'time':
return " { key: '%s', label: '%s', type: 'time' }," % (f['key'], f['label'])
return " { key: '%s', label: '%s' }," % (f['key'], f['label'])
def inject(path):
s = open(path, encoding='utf-8').read()
if 'DetailDrawer' in s:
print(' SKIP (already has DetailDrawer):', path)
return False
if 'openDetail(' in s:
print(' SKIP (already has openDetail):', path)
return False
# script + template
m_script = re.search(r'<script setup>(.*?)</script>', s, re.S)
m_tpl = re.search(r'<template>(.*?)</template>', s, re.S)
if not m_script or not m_tpl:
print(' SKIP (no script/template):', path)
return False
script = m_script.group(1)
tpl = m_tpl.group(1)
fields = parse_columns(tpl)
if not fields:
print(' SKIP (no columns parsed):', path)
return False
# 1) import
imports = list(re.finditer(r"^\s*import .* from '[^']+'\s*$", script, re.M))
if not imports:
print(' SKIP (no import lines):', path)
return False
last_import = imports[-1]
ins_import = "import DetailDrawer from '../components/DetailDrawer.vue'\n"
# 若路径是 ../../components(子目录页)则调整
if '../components/' not in script and '../../components/' in s:
ins_import = "import DetailDrawer from '../../components/DetailDrawer.vue'\n"
script_new = script[:last_import.end()] + "\n" + ins_import + script[last_import.end():]
# 2) openDetail + detail state before </script>
fields_block = ",\n".join(fmt_field(f) for f in fields)
open_detail = (
"\n// 详情抽屉\n"
"const detail = reactive({ show: false, title: '', fields: [], row: null })\n"
"function openDetail(row) {\n"
" detail.row = row\n"
" detail.title = `详情 · #${row.id}`\n"
" detail.fields = [\n" + fields_block + "\n ]\n"
" detail.show = true\n"
"}\n"
)
script_new = script_new.rstrip()
if not script_new.endswith('}'):
script_new = script_new + "\n"
script_new = script_new + open_detail
# 3) 详情 column right after <el-table
detail_col = (
" <el-table-column label=\"详情\" width=\"80\" align=\"center\">\n"
" <template #default=\"{ row }\">\n"
" <el-button link type=\"primary\" size=\"small\" @click=\"openDetail(row)\">详情</el-button>\n"
" </template>\n"
" </el-table-column>\n"
)
mt = re.search(r'<el-table\b[^>]*>', tpl)
if not mt:
print(' SKIP (no el-table):', path)
return False
# 插入到 <el-table ...> 之后(同一行或下一行)
insert_pos = mt.end()
tpl_new = tpl[:insert_pos] + "\n" + detail_col + tpl[insert_pos:]
# 4) DetailDrawer before last </div> in template
last_div = tpl_new.rfind('</div>')
drawer = (
"\n <DetailDrawer :visible=\"detail.show\" @update:visible=\"detail.show = $event\"\n"
" :title=\"detail.title\" :fields=\"detail.fields\" :data=\"detail.row\" />\n"
)
tpl_new = tpl_new[:last_div] + drawer + tpl_new[last_div:]
new_s = s
new_s = new_s[:m_script.start(1)] + script_new + new_s[m_script.end(1):]
# 重新定位 templatescript 长度变化不影响 template 区域位置,因 template 在 script 之后)
new_s = new_s[:m_tpl.start(1)] + tpl_new + new_s[m_tpl.end(1):]
open(path, 'w', encoding='utf-8').write(new_s)
print(' OK fields=%d : %s' % (len(fields), path))
return True
if __name__ == '__main__':
for p in sys.argv[1:]:
print('FILE', p)
try:
inject(p)
except Exception as e:
print(' ERROR', p, e)