| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- #!/usr/bin/env python3
- """为 web-admin 中缺少序号的 el-table 批量插入序号列。"""
- from __future__ import annotations
- import re
- import sys
- from pathlib import Path
- ROOT = Path(__file__).resolve().parents[1] / "src"
- SKIP_FILES = {
- ROOT / "components/bx/base/BaseTable.vue",
- }
- def find_table_spans(text: str) -> list[tuple[int, int]]:
- spans: list[tuple[int, int]] = []
- for m in re.finditer(r"<el-table(?:\s|>)", text):
- start = m.start()
- end_m = re.search(r"</el-table>", text[start:])
- if not end_m:
- continue
- spans.append((start, start + end_m.end()))
- return spans
- def extract_first_column(block: str) -> tuple[int, int, str] | None:
- table_open = re.search(r"<el-table\b[^>]*>", block)
- if not table_open:
- return None
- pos = table_open.end()
- m = re.search(r"(\s*)<el-table-column\b", block[pos:])
- if not m:
- return None
- col_start = pos + m.start() + len(m.group(1))
- rest = block[col_start:]
- self_close = re.match(r"(<el-table-column\b[^>]*?/>)", rest, re.DOTALL)
- if self_close:
- col_end = col_start + len(self_close.group(1))
- return col_start, col_end, block[col_start:col_end]
- open_end = rest.find(">")
- if open_end == -1:
- return None
- close = rest.find("</el-table-column>", open_end)
- if close == -1:
- return None
- col_end = col_start + close + len("</el-table-column>")
- return col_start, col_end, block[col_start:col_end]
- def leading_indent(block: str, col_start: int) -> str:
- line_start = block.rfind("\n", 0, col_start) + 1
- return re.match(r"[ \t]*", block[line_start:col_start]).group(0)
- def build_index_column(indent: str, paginated: bool) -> str:
- if paginated:
- return (
- f"{indent}<el-table-column\n"
- f"{indent} type=\"index\"\n"
- f"{indent} label=\"序号\"\n"
- f"{indent} width=\"68\"\n"
- f"{indent} align=\"center\"\n"
- f"{indent} header-align=\"center\"\n"
- f"{indent} :index=\"(index) => (pagination.page - 1) * pagination.pageSize + index + 1\"\n"
- f"{indent}/>"
- )
- return (
- f'{indent}<el-table-column type="index" label="序号" width="68" '
- f'align="center" header-align="center" />'
- )
- def should_use_pagination(block: str, file_text: str) -> bool:
- if "pagination.page" not in file_text:
- return False
- table_open = re.search(r"<el-table\b[^>]*>", block)
- if not table_open:
- return False
- opening = table_open.group(0)
- if 'size="small"' in opening or "size='small'" in opening:
- return False
- if "sub-table" in opening:
- return False
- return True
- def insert_index_into_block(block: str, file_text: str) -> str | None:
- if 'type="index"' in block or "type='index'" in block:
- return None
- first = extract_first_column(block)
- if not first:
- return None
- col_start, col_end, first_col = first
- indent = leading_indent(block, col_start)
- paginated = should_use_pagination(block, file_text)
- index_col = build_index_column(indent, paginated)
- is_select = re.search(r'type="(selection|radio)"', first_col) is not None
- if is_select:
- insert_at = col_end
- new_block = block[:insert_at] + "\n" + index_col + block[insert_at:]
- else:
- line_start = block.rfind("\n", 0, col_start) + 1
- new_block = block[:line_start] + index_col + "\n" + block[line_start:]
- return new_block
- def process_file(path: Path) -> bool:
- if path in SKIP_FILES:
- return False
- text = path.read_text(encoding="utf-8")
- if not re.search(r"<el-table(?:\s|>)", text):
- return False
- spans = find_table_spans(text)
- if not spans:
- return False
- changed = False
- offset = 0
- for start, end in spans:
- start += offset
- end += offset
- block = text[start:end]
- new_block = insert_index_into_block(block, text)
- if not new_block:
- continue
- text = text[:start] + new_block + text[end:]
- offset += len(new_block) - len(block)
- changed = True
- if changed:
- path.write_text(text, encoding="utf-8")
- return changed
- def main() -> int:
- changed_files: list[str] = []
- for path in sorted(ROOT.rglob("*.vue")):
- if process_file(path):
- changed_files.append(str(path.relative_to(ROOT.parents[0])))
- print(f"Updated {len(changed_files)} files")
- for f in changed_files:
- print(f" {f}")
- return 0
- if __name__ == "__main__":
- sys.exit(main())
|