提交
This commit is contained in:
1 parent
7fbf71b6e1
commit
ea5dedf059
172 files changed
+19048
-12677
No files matched your search
@@ -0,0 +1,246 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
批量给 web-admin 列表页添加 watchDebounced 自动搜索。
|
||||
watchDebounced 来自 @vueuse/core,已通过 auto-import 自动导入,无需手动 import。
|
||||
|
||||
用法: python3 scripts/add-auto-search.py [--dry-run]
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
DRY_RUN = "--dry-run" in sys.argv
|
||||
|
||||
BASE = os.path.join(os.path.dirname(__file__), "..", "web-admin", "src", "views")
|
||||
|
||||
# 所有需要修改的文件(相对于 web-admin/src/views/)
|
||||
FILES = [
|
||||
# --- basic-info (6) ---
|
||||
"basic-info/collection-region/index.vue",
|
||||
"basic-info/customer/index.vue",
|
||||
"basic-info/collection-protocol-no/index.vue",
|
||||
"basic-info/insurance-company/index.vue",
|
||||
"basic-info/cell-sample-type/index.vue",
|
||||
"basic-info/sample-code/index.vue",
|
||||
# --- pilot-service (6) ---
|
||||
"pilot-service/cell-product-spec/index.vue",
|
||||
"pilot-service/project-price-system/index.vue",
|
||||
"pilot-service/cell-product-price/index.vue",
|
||||
"pilot-service/channel/index.vue",
|
||||
"pilot-service/checkup-institution/index.vue",
|
||||
"pilot-service/cell-product-type/index.vue",
|
||||
# --- quality-inspection (9) ---
|
||||
"quality-inspection/third-party-company/index.vue",
|
||||
"quality-inspection/qc-material-usage/index.vue",
|
||||
"quality-inspection/storage-release-review/index.vue",
|
||||
"quality-inspection/qc-task/index.vue",
|
||||
"quality-inspection/sample-reception/index.vue",
|
||||
"quality-inspection/qc-material/index.vue",
|
||||
"quality-inspection/lab-test-item/index.vue",
|
||||
"quality-inspection/sample-reception-check-item/index.vue",
|
||||
"quality-inspection/qc-work-order/index.vue",
|
||||
# --- cell-storage (9) ---
|
||||
"cell-storage/material-stock-log/index.vue",
|
||||
"cell-storage/storage-entry-info/index.vue",
|
||||
"cell-storage/fullmoon-todo/index.vue",
|
||||
"cell-storage/material/index.vue",
|
||||
"cell-storage/protocol-audit/index.vue",
|
||||
"cell-storage/storage-cert/index.vue",
|
||||
"cell-storage/payment-info/index.vue",
|
||||
"cell-storage/sample-reception-info/index.vue",
|
||||
"cell-storage/protocol/index.vue",
|
||||
# --- production (11) ---
|
||||
"production/process-category/index.vue",
|
||||
"production/process/index.vue",
|
||||
"production/consumable/index.vue",
|
||||
"production/consumable-pack/index.vue",
|
||||
"production/cell-product/index.vue",
|
||||
"production/output-type/index.vue",
|
||||
"production/production-work-order/index.vue",
|
||||
"production/reagent/index.vue",
|
||||
"production/production-task/index.vue",
|
||||
"production/sop/index.vue",
|
||||
"production/process-route/index.vue",
|
||||
# --- operations (2) ---
|
||||
"operations/exhibition-appointment/index.vue",
|
||||
"operations/clean-room/index.vue",
|
||||
# --- research-donation (2) ---
|
||||
"research-donation/list/index.vue",
|
||||
"research-donation/audit/index.vue",
|
||||
# --- system (17) ---
|
||||
"system/leave/index.vue",
|
||||
"system/role/index.vue",
|
||||
"system/dict/index.vue",
|
||||
"system/unit/index.vue",
|
||||
"system/dept/index.vue",
|
||||
"system/site/index.vue",
|
||||
"system/menu/index.vue",
|
||||
"system/order/index.vue",
|
||||
"system/product/index.vue",
|
||||
"system/user/index.vue",
|
||||
"system/post/index.vue",
|
||||
"system/express/index.vue",
|
||||
"system/category/index.vue",
|
||||
"system/workflow/process/index.vue",
|
||||
"system/workflow/task-completed/index.vue",
|
||||
"system/workflow/task-pending/index.vue",
|
||||
"system/workflow/my-applications/index.vue",
|
||||
]
|
||||
|
||||
# 特殊文件:有额外的 dateRange ref 需要监听
|
||||
DATE_RANGE_FILES = [
|
||||
"cell-storage/material-stock-log/index.vue",
|
||||
"quality-inspection/qc-material-usage/index.vue",
|
||||
]
|
||||
|
||||
# 特殊文件:使用 filterForm 而非 searchForm
|
||||
FILTER_FORM_FILES = {
|
||||
"system/leave/index.vue": "filterForm",
|
||||
}
|
||||
|
||||
|
||||
def detect_form_var(filepath: str, content: str) -> str:
|
||||
"""检测搜索表单的变量名"""
|
||||
rel = os.path.relpath(filepath, BASE)
|
||||
if rel in FILTER_FORM_FILES:
|
||||
return FILTER_FORM_FILES[rel]
|
||||
# 查找 const xxxForm = reactive 或 const xxxFilter = reactive
|
||||
m = re.search(r"const\s+(\w*(?:Form|Filter|filter))\s*=\s*reactive", content)
|
||||
if m:
|
||||
return m.group(1)
|
||||
# 默认 searchForm
|
||||
return "searchForm"
|
||||
|
||||
|
||||
def detect_pagination_var(content: str) -> str:
|
||||
"""检测分页变量名"""
|
||||
m = re.search(r"const\s+(\w+)\s*=\s*reactive\s*\(\{[^}]*page\s*:", content)
|
||||
if not m:
|
||||
m = re.search(r"const\s+(\w+)\s*=\s*reactive\s*<[^>]*>\s*\(\{[^}]*page\s*:", content)
|
||||
if not m:
|
||||
m = re.search(r"const\s+(\w+)\s*=\s*reactive\s*\{[^}]*page\s*:", content)
|
||||
return m.group(1) if m else "pagination"
|
||||
|
||||
|
||||
def detect_load_fn(content: str, form_var: str) -> str:
|
||||
"""检测数据加载函数名(在 handleSearch 中调用的函数)"""
|
||||
# 查找 handleSearch 函数体中调用的函数
|
||||
# 模式: function handleSearch() { ... xxx() } 或 const handleSearch = () => { ... xxx() }
|
||||
pattern = rf"(?:function\s+handleSearch|const\s+handleSearch\s*=\s*(?:\([^)]*\)\s*=>|\(\)\s*=>))\s*\{{[^}}]*?(\w+)\(\)"
|
||||
m = re.search(pattern, content)
|
||||
if m:
|
||||
return m.group(1)
|
||||
# 回退:查找 pagination.page = 1 后面紧跟的函数调用
|
||||
pattern2 = r"pagination\.page\s*=\s*1\s*\n?\s*(\w+)\(\)"
|
||||
m2 = re.search(pattern2, content)
|
||||
if m2:
|
||||
return m2.group(1)
|
||||
return "loadData"
|
||||
|
||||
|
||||
def build_watch_block(form_var: str, pagination_var: str, load_fn: str, has_date_range: bool = False) -> str:
|
||||
"""生成 watchDebounced 代码块"""
|
||||
lines = [
|
||||
"",
|
||||
" // 输入检索条件时自动搜索(防抖 300ms)",
|
||||
" watchDebounced(",
|
||||
f" {form_var},",
|
||||
" () => {",
|
||||
f" {pagination_var}.page = 1",
|
||||
f" {load_fn}()",
|
||||
" },",
|
||||
" { debounce: 300, deep: true }",
|
||||
" )",
|
||||
]
|
||||
if has_date_range:
|
||||
lines += [
|
||||
"",
|
||||
" // 日期范围变更时自动搜索",
|
||||
" watch(",
|
||||
" dateRange,",
|
||||
" () => {",
|
||||
f" {pagination_var}.page = 1",
|
||||
f" {load_fn}()",
|
||||
" }",
|
||||
" )",
|
||||
]
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def process_file(rel_path: str) -> bool:
|
||||
"""处理单个文件,返回是否修改"""
|
||||
filepath = os.path.join(BASE, rel_path)
|
||||
if not os.path.exists(filepath):
|
||||
print(f" SKIP (not found): {rel_path}")
|
||||
return False
|
||||
|
||||
with open(filepath, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
# 已经有 watchDebounced 的跳过
|
||||
if "watchDebounced" in content:
|
||||
print(f" SKIP (already has watchDebounced): {rel_path}")
|
||||
return False
|
||||
|
||||
# 检测变量名
|
||||
form_var = detect_form_var(filepath, content)
|
||||
pagination_var = detect_pagination_var(content)
|
||||
load_fn = detect_load_fn(content, form_var)
|
||||
has_date_range = rel_path in DATE_RANGE_FILES
|
||||
|
||||
# 生成 watch 代码块
|
||||
watch_block = build_watch_block(form_var, pagination_var, load_fn, has_date_range)
|
||||
|
||||
# 查找插入点:onMounted 之前
|
||||
# 匹配多种 onMounted 写法
|
||||
on_mounted_patterns = [
|
||||
r"(\n)(\s*onMounted\s*\()", # onMounted(() => {
|
||||
r"(\n)(\s*onMounted\()", # onMounted(() => {
|
||||
]
|
||||
|
||||
inserted = False
|
||||
for pattern in on_mounted_patterns:
|
||||
match = re.search(pattern, content)
|
||||
if match:
|
||||
insert_pos = match.start(1)
|
||||
content = content[:insert_pos] + watch_block + content[insert_pos:]
|
||||
inserted = True
|
||||
break
|
||||
|
||||
if not inserted:
|
||||
print(f" SKIP (no onMounted found): {rel_path}")
|
||||
return False
|
||||
|
||||
if DRY_RUN:
|
||||
print(f" WOULD MODIFY: {rel_path} (form={form_var}, pagination={pagination_var}, load={load_fn})")
|
||||
else:
|
||||
with open(filepath, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
print(f" DONE: {rel_path} (form={form_var}, pagination={pagination_var}, load={load_fn})")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
mode = "DRY RUN" if DRY_RUN else "LIVE"
|
||||
print(f"=== Adding auto-search to list pages ({mode}) ===")
|
||||
print(f"Files to process: {len(FILES)}")
|
||||
print()
|
||||
|
||||
modified = 0
|
||||
skipped = 0
|
||||
for f in FILES:
|
||||
if process_file(f):
|
||||
modified += 1
|
||||
else:
|
||||
skipped += 1
|
||||
|
||||
print()
|
||||
print(f"=== Summary: {modified} modified, {skipped} skipped (total: {len(FILES)}) ===")
|
||||
if DRY_RUN:
|
||||
print("=== This was a dry run. Remove --dry-run to apply changes. ===")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user