520 lines
13 KiB
Python
520 lines
13 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
批量修复 ~cu-modal / ~show 弹窗隐患。
|
||
替换策略:
|
||
1. 模板中所有 ~cu-modal → 对应的本地类名
|
||
2. 模板中所有 ~show → show (普通类)
|
||
3. 模板中所有 ~bottom-modal → (去除,样式合并到本地类)
|
||
4. 模板中所有 ~cu-dialog → 对应的本地类名
|
||
5. style 中追加完整的自包含弹窗样式
|
||
"""
|
||
|
||
import re
|
||
import os
|
||
|
||
# 每个文件的修复配置
|
||
CONFIGS = {
|
||
"src/components/uploadPics.wpy": {
|
||
"type": "bottom",
|
||
"modal_cls": "uploadpics-mask",
|
||
"dialog_cls": "uploadpics-sheet",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.uploadpics-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: all .3s ease;
|
||
}
|
||
.uploadpics-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.uploadpics-sheet {
|
||
position: absolute;
|
||
left: 0; right: 0; bottom: 0;
|
||
background: #fff;
|
||
border-radius: 32rpx 32rpx 0 0;
|
||
}
|
||
._item {
|
||
padding: 32rpx;
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
text-align: center;
|
||
}
|
||
._cancel {
|
||
border-top: 16rpx solid #f8f8f8;
|
||
margin-bottom: 24rpx;
|
||
color: #999;
|
||
}
|
||
""",
|
||
},
|
||
"src/components/visitorModel.wpy": {
|
||
"type": "center",
|
||
"modal_cls": "visitormodel-mask",
|
||
"dialog_cls": "visitormodel-dialog",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.visitormodel-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity .3s;
|
||
}
|
||
.visitormodel-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.visitormodel-dialog {
|
||
position: absolute;
|
||
top: 50%; left: 50%;
|
||
transform: translate(-50%,-50%) scale(.85);
|
||
width: 680rpx;
|
||
max-width: 100%;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
transition: transform .3s;
|
||
}
|
||
.visitormodel-mask.show .visitormodel-dialog {
|
||
transform: translate(-50%,-50%) scale(1);
|
||
}
|
||
""",
|
||
},
|
||
"src/components/recommendDialog.wpy": {
|
||
"type": "center",
|
||
"modal_cls": "recommend-mask",
|
||
"dialog_cls": "recommend-dialog",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.recommend-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity .3s;
|
||
}
|
||
.recommend-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.recommend-dialog {
|
||
position: absolute;
|
||
top: 50%; left: 50%;
|
||
transform: translate(-50%,-50%) scale(.85);
|
||
width: 680rpx;
|
||
max-width: 100%;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
transition: transform .3s;
|
||
}
|
||
.recommend-mask.show .recommend-dialog {
|
||
transform: translate(-50%,-50%) scale(1);
|
||
}
|
||
""",
|
||
},
|
||
"src/components/shareComponent.wpy": {
|
||
"type": "center",
|
||
"modal_cls": "sharec-mask",
|
||
"dialog_cls": "sharec-dialog",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.sharec-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity .3s;
|
||
}
|
||
.sharec-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.sharec-dialog {
|
||
position: absolute;
|
||
top: 50%; left: 50%;
|
||
transform: translate(-50%,-50%) scale(.85);
|
||
width: 680rpx;
|
||
max-width: 100%;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
transition: transform .3s;
|
||
}
|
||
.sharec-mask.show .sharec-dialog {
|
||
transform: translate(-50%,-50%) scale(1);
|
||
}
|
||
""",
|
||
},
|
||
"src/components/wxShareCom.wpy": {
|
||
"type": "center",
|
||
"modal_cls": "wxsharec-mask",
|
||
"dialog_cls": "wxsharec-dialog",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.wxsharec-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity .3s;
|
||
}
|
||
.wxsharec-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.wxsharec-dialog {
|
||
position: absolute;
|
||
top: 50%; left: 50%;
|
||
transform: translate(-50%,-50%) scale(.85);
|
||
width: 680rpx;
|
||
max-width: 100%;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
transition: transform .3s;
|
||
}
|
||
.wxsharec-mask.show .wxsharec-dialog {
|
||
transform: translate(-50%,-50%) scale(1);
|
||
}
|
||
""",
|
||
},
|
||
"src/components/dynamicOperation.wpy": {
|
||
"type": "bottom",
|
||
"modal_cls": "dynop-mask",
|
||
"dialog_cls": "dynop-sheet",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.dynop-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: all .3s;
|
||
}
|
||
.dynop-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.dynop-sheet {
|
||
position: absolute;
|
||
left: 0; right: 0; bottom: 0;
|
||
background: #fff;
|
||
border-radius: 30rpx 30rpx 0 0;
|
||
width: 100%;
|
||
z-index: 1111;
|
||
view {
|
||
height: 90rpx;
|
||
text-align: center;
|
||
line-height: 100rpx;
|
||
margin: 0 30rpx;
|
||
color: #333;
|
||
}
|
||
view:last-of-type {
|
||
border-top: 1rpx solid #f5f5f5;
|
||
color: #999;
|
||
}
|
||
}
|
||
""",
|
||
},
|
||
"src/components/UnlockingDialog.wpy": {
|
||
"type": "center",
|
||
"modal_cls": "unlock-mask",
|
||
"dialog_cls": "unlock-dialog",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.unlock-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity .3s;
|
||
}
|
||
.unlock-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.unlock-dialog {
|
||
position: absolute;
|
||
top: 50%; left: 50%;
|
||
transform: translate(-50%,-50%) scale(.85);
|
||
width: 680rpx;
|
||
max-width: 100%;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
transition: transform .3s;
|
||
}
|
||
.unlock-mask.show .unlock-dialog {
|
||
transform: translate(-50%,-50%) scale(1);
|
||
}
|
||
""",
|
||
},
|
||
"src/components/loginDialog.wpy": {
|
||
"type": "center",
|
||
"modal_cls": "logindlg-mask",
|
||
"dialog_cls": "logindlg-dialog",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.logindlg-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 9999;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity .3s;
|
||
}
|
||
.logindlg-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.logindlg-dialog {
|
||
position: absolute;
|
||
top: 50%; left: 50%;
|
||
transform: translate(-50%,-50%) scale(.85);
|
||
width: 680rpx;
|
||
max-width: 100%;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
transition: transform .3s;
|
||
}
|
||
.logindlg-mask.show .logindlg-dialog {
|
||
transform: translate(-50%,-50%) scale(1);
|
||
}
|
||
""",
|
||
},
|
||
"src/components/residenceDialog.wpy": {
|
||
"type": "bottom",
|
||
"modal_cls": "residence-mask",
|
||
"dialog_cls": "residence-sheet",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.residence-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: all .3s;
|
||
}
|
||
.residence-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.residence-sheet {
|
||
position: absolute;
|
||
left: 0; right: 0; bottom: 0;
|
||
background: #fff;
|
||
border-radius: 32rpx 32rpx 0 0;
|
||
overflow: hidden;
|
||
}
|
||
""",
|
||
},
|
||
"src/components/dynamicDiscuss.wpy": {
|
||
"type": "bottom",
|
||
"modal_cls": "discs-mask",
|
||
"dialog_cls": "discs-sheet",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.discs-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: all .3s;
|
||
}
|
||
.discs-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.discs-sheet {
|
||
position: absolute;
|
||
left: 0; right: 0; bottom: 0;
|
||
background: #fff;
|
||
border-radius: 20rpx 20rpx 0 0;
|
||
overflow: hidden;
|
||
}
|
||
""",
|
||
},
|
||
"src/components/cu-custom.wpy": {
|
||
"type": "center",
|
||
"modal_cls": "cucust-mask",
|
||
"dialog_cls": "cucust-dialog",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.cucust-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity .3s;
|
||
}
|
||
.cucust-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.cucust-dialog {
|
||
position: absolute;
|
||
top: 50%; left: 50%;
|
||
transform: translate(-50%,-50%) scale(.85);
|
||
width: 680rpx;
|
||
max-width: 100%;
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
transition: transform .3s;
|
||
}
|
||
.cucust-mask.show .cucust-dialog {
|
||
transform: translate(-50%,-50%) scale(1);
|
||
}
|
||
""",
|
||
},
|
||
"src/components/uploadVideo.wpy": {
|
||
"type": "bottom",
|
||
"modal_cls": "uploadvid-mask",
|
||
"dialog_cls": "uploadvid-sheet",
|
||
"trigger": "~show",
|
||
"style_add": """
|
||
.uploadvid-mask {
|
||
position: fixed;
|
||
top: 0; right: 0; bottom: 0; left: 0;
|
||
z-index: 1110;
|
||
background: rgba(0,0,0,.6);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: all .3s;
|
||
}
|
||
.uploadvid-mask.show {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
.uploadvid-sheet {
|
||
position: absolute;
|
||
left: 0; right: 0; bottom: 0;
|
||
background: #fff;
|
||
border-radius: 32rpx 32rpx 0 0;
|
||
}
|
||
""",
|
||
},
|
||
}
|
||
|
||
|
||
def transform_template(content, cfg):
|
||
"""把模板中的 ~cu-modal / ~show / ~bottom-modal / ~cu-dialog 替换掉"""
|
||
modal = cfg["modal_cls"]
|
||
dialog = cfg["dialog_cls"]
|
||
|
||
lines = content.split("\n")
|
||
result = []
|
||
for line in lines:
|
||
orig = line
|
||
|
||
# 1. ~cu-dialog → dialog类名
|
||
line = re.sub(r"~cu-dialog\b", dialog, line)
|
||
|
||
# 2. ~bottom-modal → (去除,样式已在本地)
|
||
line = re.sub(r"~\s*bottom-modal", "", line)
|
||
|
||
# 3. ~cu-modal 处理
|
||
# 情况A: class="~cu-modal ..." (注意前面可能有其他class如 shareComponent的 cu-modal)
|
||
# 情况B: :class="{'~show': ...}" class="~cu-modal"
|
||
# 统一:去掉所有 ~cu-modal,保留其他已有class,在class属性末尾追加modal类名
|
||
if "~cu-modal" in line:
|
||
# 先把 :class={'~show':cond} 里的 ~show 改成 show
|
||
line = re.sub(r":class\s*=\s*\{'~show'\s*:", ":class=\"{'show':", line)
|
||
# {{cond?'~show':''}} → {{cond?'show':''}}
|
||
line = re.sub(r"\?'~show'", "? 'show'", line)
|
||
|
||
# 去除 ~cu-modal,保留其他普通class
|
||
# 匹配 class="... ~cu-modal ..." 或 class="~cu-modal"
|
||
# WePY: class="xxx ~cu-modal yyy" → class="xxx yyy modal_cls"
|
||
# class="~cu-modal xxx" → class="xxx modal_cls"
|
||
# class="~cu-modal" → class="modal_cls"
|
||
|
||
def fix_cu_modal(m):
|
||
raw = m.group(0)
|
||
# 提取已有class值
|
||
cls_val = re.search(r'class="([^"]*)"', raw)
|
||
if not cls_val:
|
||
return raw
|
||
classes = cls_val.group(1)
|
||
# 去掉 ~cu-modal 和多余的空格
|
||
classes = re.sub(r"~\s*cu-modal", "", classes)
|
||
classes = re.sub(r"\s+", " ", classes).strip()
|
||
# 去掉 shareComponent 的普通 cu-modal (不再需要)
|
||
classes = re.sub(r"\bcu-modal\b", "", classes)
|
||
classes = re.sub(r"\s+", " ", classes).strip()
|
||
# 追加本地modal类
|
||
extra = " " + modal if classes else modal
|
||
new_cls = (classes + extra).strip()
|
||
return 'class="' + new_cls + '"'
|
||
|
||
line = re.sub(r'class="[^"]*"', fix_cu_modal, line, count=1)
|
||
|
||
# 4. 单独处理 :class="{'~show': ...}" 的情况(还没处理到的情况)
|
||
line = re.sub(r":class\s*=\s*\{'~show'\s*:", ":class=\"{'show':", line)
|
||
line = re.sub(r"\?'~show':", "? 'show':", line)
|
||
|
||
result.append(line)
|
||
return "\n".join(result)
|
||
|
||
|
||
def append_style(content, style_add):
|
||
"""在 </style> 前追加样式"""
|
||
marker = "</style>"
|
||
if marker in content:
|
||
idx = content.index(marker)
|
||
return content[:idx] + "\n" + style_add + "\n" + marker + content[idx + len(marker):]
|
||
return content
|
||
|
||
|
||
def process_file(filepath, cfg):
|
||
with open(filepath, "r", encoding="utf-8") as f:
|
||
content = f.read()
|
||
|
||
new_content = transform_template(content, cfg)
|
||
new_content = append_style(new_content, cfg["style_add"])
|
||
|
||
with open(filepath, "w", encoding="utf-8") as f:
|
||
f.write(new_content)
|
||
|
||
print(f"✓ {filepath}")
|
||
|
||
|
||
def main():
|
||
base = "/Users/d/fulllink-project/ufutx.love.mp.v2"
|
||
for rel_path, cfg in CONFIGS.items():
|
||
filepath = os.path.join(base, rel_path)
|
||
if os.path.exists(filepath):
|
||
process_file(filepath, cfg)
|
||
else:
|
||
print(f"✗ 文件不存在: {filepath}")
|
||
|
||
if __name__ == "__main__":
|
||
main()
|