Files
ctbjrj/tools/migrate_logic.py
T

323 lines
12 KiB
Python
Raw Permalink 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.
# -*- coding: utf-8 -*-
"""
事件/逻辑代码迁移:旧项目 主窗口*.cs + 对话框 → 新项目(停靠面板版)。
策略:能复制就复制,只做三类最小改动:
1) namespace MyApp → 成套报价软件;partial class 主窗口 → MainForm
2) 旧构造函数拆到 MainForm.cs(加 CreateDockWindows/Load 接线)
3) 停靠窗口控件在 MainForm 上生成公开别名属性(this.xxx 继续可用)
旧 ui.cs 尾部的 SQLite 加载方法一并带过来。
"""
import io
import os
import re
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import migrate_ui as mu
SRC_DIR = os.path.dirname(mu.SRC)
DST = mu.DST_PROJECT
def read(p):
return io.open(p, encoding="utf-8-sig").read()
def write(p, s):
io.open(p, "w", encoding="utf-8-sig", newline="\r\n").write(s)
def rename_common(s):
s = s.replace("namespace MyApp", "namespace 成套报价软件")
s = s.replace("public partial class 主窗口", "public partial class MainForm")
return s
# ---------------------------------------------------------------- 1) 别名文件
def gen_aliases():
text = read(mu.SRC)
decls, begin_inits, blocks, top, edges, ts_edges = mu.parse(text)
ctrl_blocks, form_block = mu.classify(blocks)
ch = mu.build_children(edges)
decl_types = dict(decls)
# MainForm 自身已有成员(避免别名冲突)
taken = set(["tabControl1", "tabPage1", "tabPage2", "tabPage3", "tabPage4", "tabPage5",
"tabPage6", "statusStrip1", "dockSurface1", "components",
"InitializeComponent", "CreateDockWindows_dockSurface1", "DockSurface1ActiveContentChanged"])
for n, _t in decls:
if n in mu.subtree("tabControl1", ch) or n in mu.subtree("statusStrip1", ch):
taken.add(n)
wfields = []
props = []
for idx, (cls, tab, title) in enumerate(mu.DOCK_MAP, 1):
members = mu.subtree(tab, ch)
members.remove(tab)
mset = set(members)
ordered = [n for n, _t in decls if n in mset]
for parent, kids in ts_edges:
if parent in mset:
ordered += [k for k in kids if k not in ordered]
wfields.append("\t\tinternal %s w%d;" % (cls, idx))
for n in ordered:
if n in taken:
print("!! 别名冲突跳过:", n)
continue
props.append("\t\tpublic %s %s { get { return w%d.%s; } }" % (decl_types[n], n, idx, n))
taken.add(n)
L = []
a = L.append
a("// 旧 主窗口 逻辑代码通过 this.<控件名> 访问控件;")
a("// 控件已迁入 9 个停靠窗口,这里用别名属性转发,逻辑代码无需改动。")
a("// 停靠窗口实例字段由 MainForm.dockSurface1.DockWindows.cs 在创建后赋值。")
a("namespace 成套报价软件")
a("{")
a("\tpublic partial class MainForm")
a("\t{")
L.extend(wfields)
a("")
L.extend(props)
a("\t}")
a("}")
write(os.path.join(DST, "MainForm.控件别名.cs"), "\n".join(L))
print("生成 MainForm.控件别名.cs:实例字段 %d 个,别名属性 %d 个" % (len(wfields), len(props)))
# ---------------------------------------------------------------- 2) 停靠窗口字段改 public
def publify_fields():
pat = re.compile(r"\t\tprivate (?!System\.ComponentModel\.IContainer)([\w.]+) ([\w\u4e00-\u9fff]+);")
for cls, _tab, _title in mu.DOCK_MAP:
p = os.path.join(DST, "DockWindows", cls, cls + ".Designer.cs")
s = read(p)
s2, n = pat.subn(r"\t\tpublic \1 \2;", s)
write(p, s2)
print("%s: %d 个字段改为 public" % (cls, n))
# ---------------------------------------------------------------- 3) 记录停靠窗口实例
def patch_dockwindows_cs():
p = os.path.join(DST, "DockWindows", "MainForm.dockSurface1.DockWindows.cs")
s = read(p)
n = 0
for idx, (cls, _tab, _title) in enumerate(mu.DOCK_MAP, 1):
old = "var w%d = new %s();" % (idx, cls)
new = old + "\n\t\t\tthis.w%d = w%d;" % (idx, idx)
if old in s and new not in s:
s = s.replace(old, new)
n += 1
write(p, s)
print("MainForm.dockSurface1.DockWindows.cs: 接线 %d 处" % n)
# ---------------------------------------------------------------- 4) MainForm.cs + 主窗口.cs
def split_main():
src = read(os.path.join(SRC_DIR, "主窗口.cs"))
lines = src.split("\n")
ctor_start = None
for i, l in enumerate(lines):
if re.match(r"\s*public 主窗口\(\)", l):
ctor_start = i
break
assert ctor_start is not None, "找不到旧构造函数"
# ctor 结束:InitSelectionPage(); 后的第一个 ' }'
ctor_end = None
for i in range(ctor_start, len(lines)):
if "InitSelectionPage();" in lines[i]:
for j in range(i, min(i + 5, len(lines))):
if lines[j].strip() == "}":
ctor_end = j
break
break
assert ctor_end is not None, "找不到构造函数结束"
usings = [l for l in lines[:ctor_start] if l.startswith("using ")]
ctor_body = lines[ctor_start + 3:ctor_end] # 跳过签名/{/InitializeComponent();
# 新 MainForm.cs
L = []
a = L.append
a("/*")
a(" * 由SharpDevelop创建。")
a(" * 用户: 099978")
a(" * 日期: 2026-08-25")
a(" *")
a(" * 主窗体构造函数(由旧项目 主窗口.cs 迁移)。")
a(" */")
L.extend(usings)
a("")
a("namespace 成套报价软件")
a("{")
a("\t/// <summary>")
a("\t/// 主窗体:构造函数迁移自旧项目 主窗口.cs(事件挂接全部保留)。")
a("\t/// </summary>")
a("\tpublic partial class MainForm : Form")
a("\t{")
a("\t\tpublic MainForm()")
a("\t\t{")
a("\t\t\tInitializeComponent();")
a("\t\t\tCreateDockWindows_dockSurface1();")
a("")
a("\t\t\t// 旧 ui.cs 设计器注入的 SQLite 数据加载(Load 事件)")
a("\t\t\tthis.Load += (s, e) => LoadAllSqliteData();")
a("")
L.extend(ctor_body)
a("")
a("\t\tvoid DockSurface1ActiveContentChanged(object sender, EventArgs e)")
a("\t\t{")
a("")
a("\t\t}")
a("\t}")
a("}")
write(os.path.join(DST, "MainForm.cs"), "\n".join(L))
# 主窗口.cs(去掉构造函数的其余逻辑)
rest = lines[:ctor_start] + [" // 构造函数已迁至 MainForm.cs", ""] + lines[ctor_end + 1:]
write(os.path.join(DST, "主窗口.cs"), rename_common("\n".join(rest)))
print("生成 MainForm.cs 与 主窗口.cs(构造函数 %d-%d 行)" % (ctor_start + 1, ctor_end + 1))
# ---------------------------------------------------------------- 5) 其余 partial 与工具类
def copy_partials():
files = ["主窗口.菜单与库.cs", "主窗口.公式重算.cs", "主窗口.母排与备份.cs", "主窗口.项目导入导出.cs", "价格格式化.cs"]
for f in files:
write(os.path.join(DST, f), rename_common(read(os.path.join(SRC_DIR, f))))
print("复制", f)
# ---------------------------------------------------------------- 6) ui.cs 尾部 SQLite 加载
def port_sqlite_tail():
lines = read(mu.SRC).split("\n")
start = None
for i, l in enumerate(lines):
if "加载所有 SQLite 设计数据绑定" in l:
start = i
break
assert start is not None
tail = lines[start:]
while tail and tail[-1].strip() in ("}", ""):
tail.pop()
L = ["// 旧 主窗口.ui.cs 尾部的 SQLite 设计数据加载方法(设计器注入,逻辑不变)。"]
L.append("namespace 成套报价软件")
L.append("{")
L.append("\tpublic partial class MainForm")
L.append("\t{")
L.extend(tail)
L.append("\t}")
L.append("}")
write(os.path.join(DST, "主窗口.SQLite加载.cs"), "\n".join(L))
print("生成 主窗口.SQLite加载.cs(%d 行)" % len(tail))
# ---------------------------------------------------------------- 7) 对话框
DIALOGS = [
("xiangmu", ["新建项目", "修改项目", "甲方报表", "调系数", "导入报价", "元件排序", "调母排"]),
("shezhi", ["企业信息"]),
("ku", ["用户库元件编辑"]),
("GCS母排计算", ["GCS母排计算窗口", "GCS推荐铜排窗口"]),
]
def copy_dialogs():
for sub, names in DIALOGS:
for name in names:
for ext in (".cs", ".ui.cs"):
s = read(os.path.join(SRC_DIR, sub, name + ext))
s = rename_common(s)
# 类型引用 主窗口 → MainForm(注释里的中文连写不受影响)
s = re.sub(r"主窗口(?=[\s\.\)\[_,;])", "MainForm", s)
dst_sub = os.path.join(DST, sub)
if not os.path.isdir(dst_sub):
os.makedirs(dst_sub)
write(os.path.join(dst_sub, name + ext), s)
print("复制", sub + "\\" + name + ext)
# ---------------------------------------------------------------- 8) csproj
CSPROJ_COMPILE = [
"主窗口.cs", "主窗口.菜单与库.cs", "主窗口.公式重算.cs", "主窗口.母排与备份.cs",
"主窗口.项目导入导出.cs", "主窗口.SQLite加载.cs", "MainForm.控件别名.cs", "价格格式化.cs",
]
for sub, names in DIALOGS:
for name in names:
CSPROJ_COMPILE.append(sub + "\\" + name + ".cs")
CSPROJ_COMPILE.append(sub + "\\" + name + ".ui.cs")
LIB_REFS = [
"System.Data.SQLite", "NPOI", "NPOI.OOXML", "NPOI.OpenXml4Net", "NPOI.OpenXmlFormats",
"DotNetZip", "ICSharpCode.SharpZipLib", "unvell.ReoGrid", "CJZZ.Controls",
]
def patch_csproj():
p = os.path.join(DST, "成套报价软件.csproj")
s = read(p)
s = s.replace("<PlatformTarget>x86</PlatformTarget>", "<PlatformTarget>x64</PlatformTarget>")
# System.Data.SQLite 从 SD bin(x86) 改为 lib\x64 版
s = re.sub(
r"<Reference Include=\"System\.Data\.SQLite\">\s*<HintPath>.*?</HintPath>\s*</Reference>",
lambda m: '<Reference Include="System.Data.SQLite">\n <HintPath>lib\\System.Data.SQLite.dll</HintPath>\n <Private>True</Private>\n </Reference>',
s, flags=re.S)
# 追加 lib 引用(插到 WeifenLuo.ThemeVS2015 引用块之后)
ref_xml = ""
for name in LIB_REFS:
ref_xml += ' <Reference Include="%s">\n <HintPath>lib\\%s.dll</HintPath>\n <Private>True</Private>\n </Reference>\n' % (name, name)
ref_xml += ' <Reference Include="System.IO.Compression" />\n <Reference Include="System.IO.Compression.FileSystem" />\n'
anchor = "</Reference>\n </ItemGroup>"
idx = s.rfind(anchor)
s = s[:idx + len("</Reference>\n")] + ref_xml + " </ItemGroup>" + s[idx + len(anchor):]
# 追加 Compile 条目
comp_xml = ""
for f in CSPROJ_COMPILE:
comp_xml += ' <Compile Include="%s" />\n' % f
anchor2 = ' <Compile Include="Program.cs" />'
s = s.replace(anchor2, comp_xml + anchor2)
write(p, s)
print("csproj 已更新(x64 + %d 引用 + %d 编译项)" % (len(LIB_REFS) + 2, len(CSPROJ_COMPILE)))
# ---------------------------------------------------------------- 9) verify_build.rsp
def gen_rsp():
L = ["# csc 编译验证(UTF-8)", "/target:winexe", "/platform:x64", "/utf8output", "/nologo", "/warn:0",
"/out:bin\\Debug\\成套报价软件.exe"]
for fw in ["System.dll", "System.Core.dll", "System.Data.dll", "System.Drawing.dll",
"System.Windows.Forms.dll", "System.Xml.dll", "System.IO.Compression.dll",
"System.IO.Compression.FileSystem.dll"]:
L.append("/r:" + fw)
for name in ["Smart.CustomComponents", "WeifenLuo.WinFormsUI.Docking", "WeifenLuo.WinFormsUI.Docking.ThemeVS2015"]:
L.append('/r:"C:\\Program Files (x86)\\SharpDevelop\\5.2\\bin\\%s.dll"' % name)
for name in ["AdvancedDataGridView", "Microsoft.Web.WebView2.Core", "Microsoft.Web.WebView2.WinForms"] + LIB_REFS:
L.append('/r:"lib\\%s.dll"' % name)
for f in ["MainForm.cs", "MainForm.Designer.cs", "Program.cs", "Properties\\AssemblyInfo.cs"] + CSPROJ_COMPILE:
L.append(f)
for cls, _t, _ti in mu.DOCK_MAP:
L.append("DockWindows\\%s\\%s.cs" % (cls, cls))
L.append("DockWindows\\%s\\%s.Designer.cs" % (cls, cls))
L.append("DockWindows\\MainForm.dockSurface1.DockWindows.cs")
write(os.path.join(HERE, "verify_build.rsp"), "\n".join(L) + "\n")
print("verify_build.rsp 已重新生成")
if __name__ == "__main__":
gen_aliases()
publify_fields()
patch_dockwindows_cs()
split_main()
copy_partials()
port_sqlite_tail()
copy_dialogs()
patch_csproj()
gen_rsp()
print("完成")