init
This commit is contained in:
82
docs/baidu.md
Normal file
82
docs/baidu.md
Normal file
@@ -0,0 +1,82 @@
|
||||
这个任务非常适合用 **Playwright** 来实现,因为它对页面加载的等待机制非常智能。
|
||||
|
||||
为了保持代码的健壮性,我为你编写了一个独立的脚本。它遵循了我们之前规划的逻辑:**启动浏览器 -> 模拟输入 -> 触发搜索 -> 等待结果渲染 -> 全屏截图**。
|
||||
|
||||
### 🐍 Python 自动化脚本实现
|
||||
|
||||
```python
|
||||
import os
|
||||
import time
|
||||
from playwright.sync_api import sync_playwright
|
||||
from datetime import datetime
|
||||
|
||||
def search_baidu_and_screenshot(keyword="java教程"):
|
||||
# 1. 准备截图目录
|
||||
save_dir = f"./data/screenshots/{datetime.now().strftime('%Y-%m-%d')}"
|
||||
if not os.path.exists(save_dir):
|
||||
os.makedirs(save_dir)
|
||||
|
||||
file_path = os.path.join(save_dir, f"baidu_search_{keyword}.png")
|
||||
|
||||
with sync_playwright() as p:
|
||||
# 启动浏览器 (headless=False 可以让你看到操作过程)
|
||||
print("[*] 正在启动 Chromium 浏览器...")
|
||||
browser = p.chromium.launch(headless=False)
|
||||
context = browser.new_context(viewport={'width': 1280, 'height': 800})
|
||||
page = context.new_page()
|
||||
|
||||
try:
|
||||
# 2. 访问百度
|
||||
print(f"[*] 正在访问百度...")
|
||||
page.goto("https://www.baidu.com", wait_until="networkidle")
|
||||
|
||||
# 3. 定位搜索框并输入关键字
|
||||
# 百度搜索框的 ID 通常是 'kw'
|
||||
print(f"[*] 输入搜索关键词: {keyword}")
|
||||
page.fill("#kw", keyword)
|
||||
|
||||
# 4. 点击“百度一下”按钮
|
||||
# 百度搜索按钮的 ID 通常是 'su'
|
||||
page.click("#su")
|
||||
|
||||
# 5. 等待搜索结果加载
|
||||
# 我们等待结果列表容器出现,确保内容不是空白
|
||||
print("[*] 等待搜索结果渲染...")
|
||||
page.wait_for_selector("#content_left", timeout=10000)
|
||||
|
||||
# 稍微额外等待一下,让图片或样式加载更完整
|
||||
time.sleep(2)
|
||||
|
||||
# 6. 截图并保存
|
||||
print(f"[*] 正在保存截图至: {file_path}")
|
||||
page.screenshot(path=file_path, full_page=True)
|
||||
print("[√] 任务完成!")
|
||||
|
||||
except Exception as e:
|
||||
print(f"[!] 操作过程中发生错误: {e}")
|
||||
# 发生错误时截取当前页面备查
|
||||
page.screenshot(path=os.path.join(save_dir, "error_state.png"))
|
||||
|
||||
finally:
|
||||
browser.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
search_baidu_and_screenshot("java教程")
|
||||
```
|
||||
|
||||
### 💡 开发要点解析:
|
||||
|
||||
1. **选择器 (Selectors)**:
|
||||
* 百度搜索框的 ID 是 `#kw`。
|
||||
* 百度搜索按钮的 ID 是 `#su`。
|
||||
* 搜索结果的主体容器 ID 是 `#content_left`。使用 `wait_for_selector` 是为了防止在页面还没跳转完就执行截图。
|
||||
2. **全屏截图 (`full_page=True`)**:
|
||||
* 这个参数非常有用,它会自动滚动页面并拼接,将整个搜索结果列表(包括滚动条下方的内容)完整保存下来。
|
||||
3. **视口设置 (`viewport`)**:
|
||||
* 设置固定的分辨率可以保证不同环境下截图的一致性,方便后续交给 **Umi-OCR** 进行固定区域的文字识别。
|
||||
4. **环境准备**:
|
||||
如果你还没有安装 Playwright 运行环境,请执行以下命令:
|
||||
```bash
|
||||
pip install playwright
|
||||
playwright install chromium
|
||||
```
|
||||
88
docs/md转公众号.md
Normal file
88
docs/md转公众号.md
Normal file
@@ -0,0 +1,88 @@
|
||||
把 Markdown 转化成适合公众号发布的 HTML,其实有个“坑”:公众号的后台编辑器对 CSS 的支持比较刻薄(很多标准的 CSS 样式会被过滤)。因此,最稳妥的方法是使用**行内样式(Inline CSS)**。
|
||||
|
||||
我们可以使用 Python 的 `markdown` 库配合 `premailer`(用于将 CSS 自动注入到 HTML 标签的 `style` 属性中)来实现。
|
||||
|
||||
### 准备工作
|
||||
|
||||
你需要安装两个库:
|
||||
```bash
|
||||
pip install markdown premailer
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Python 实现代码
|
||||
|
||||
这段代码不仅会转换格式,还会为你预设一套适合阅读的“公众号风”样式:
|
||||
|
||||
```python
|
||||
import markdown
|
||||
from premailer import transform
|
||||
|
||||
def md_to_wechat_html(md_text):
|
||||
# 1. 定义基本的 CSS 样式(根据公众号审美习惯调整)
|
||||
css = """
|
||||
<style>
|
||||
.rich_media_content { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; line-height: 1.6; color: #333; }
|
||||
h2 { border-bottom: 2px solid #007aff; padding-bottom: 5px; margin-top: 30px; color: #007aff; }
|
||||
h3 { color: #007aff; margin-top: 20px; }
|
||||
p { margin: 15px 0; }
|
||||
blockquote { border-left: 4px solid #ddd; padding-left: 15px; color: #666; font-style: italic; margin: 20px 0; }
|
||||
code { background-color: #f8f8f8; color: #c7254e; padding: 2px 4px; border-radius: 3px; }
|
||||
pre { background-color: #282c34; color: #abb2bf; padding: 15px; border-radius: 5px; overflow-x: auto; }
|
||||
img { max-width: 100%; display: block; margin: 20px auto; }
|
||||
</style>
|
||||
"""
|
||||
|
||||
# 2. 将 Markdown 转为 HTML(启用表格、代码高亮等常用扩展)
|
||||
html_content = markdown.markdown(
|
||||
md_text,
|
||||
extensions=['extra', 'codehilite', 'toc']
|
||||
)
|
||||
|
||||
# 3. 组合成完整的 HTML 结构
|
||||
full_html = f"""
|
||||
<html>
|
||||
<body>
|
||||
<div class="rich_media_content">
|
||||
{css}
|
||||
{html_content}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
# 4. 使用 premailer 将 CSS 转化为行内样式(公众号最爱的格式)
|
||||
wechat_friendly_html = transform(full_html)
|
||||
|
||||
return wechat_friendly_html
|
||||
|
||||
# 测试使用
|
||||
if __name__ == "__main__":
|
||||
test_md = """
|
||||
## 这是一个标题
|
||||
这是一段正文,包含 **粗体** 和 `行内代码`。
|
||||
|
||||
> 这是一个引言块。
|
||||
|
||||
### 代码示例
|
||||
```python
|
||||
print("Hello WeChat!")
|
||||
```
|
||||
"""
|
||||
|
||||
result = md_to_wechat_html(test_md)
|
||||
with open("output.html", "w", encoding="utf-8") as f:
|
||||
f.write(result)
|
||||
print("转换成功!请打开 output.html 复制内容到公众号后台。")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 避坑小贴士
|
||||
|
||||
1. **图片链接**:Markdown 里的本地图片链接直接转过去是没用的。你需要先手动上传图片到公众号素材库,或者使用图床,把 MD 里的地址换成 URL。
|
||||
2. **代码高亮**:公众号对 `pre` 和 `code` 标签的渲染比较特殊。如果上面的代码块样式不够完美,建议考虑使用专门的插件(如 **Markdown Here**)或者将代码块截图上传。
|
||||
3. **直接粘贴**:运行代码生成的 `output.html` 后,用浏览器打开它,**直接全选复制**,然后粘贴到公众号编辑器里即可,格式基本能保持 90% 以上的一致。
|
||||
|
||||
如果你希望样式更精致一点(比如添加特定的配色方案),需要我帮你调整上面的 `css` 变量部分吗?
|
||||
78
docs/md转公众号优化.md
Normal file
78
docs/md转公众号优化.md
Normal file
@@ -0,0 +1,78 @@
|
||||
看到你提供的 HTML 结构了。之所以在公众号后台不显示图片,是因为微信的编辑器有一套非常特殊的**图片延迟加载机制**。
|
||||
|
||||
你代码中的图片标签是这样的:
|
||||
`<img src="http://..." data-src="http://..." alt="">`
|
||||
|
||||
**问题核心在于:**
|
||||
1. **协议问题**:你的七牛云链接是 `http`。现在微信后台基本强制要求 `https`,否则会拦截或显示破损图标。
|
||||
2. **关键属性缺失**:微信除了 `data-src`,通常还需要一个 `data-type`(指定图片格式,如 png/jpeg)或者 `style` 必须包含 `width: 100%` 以防图片被压成 0 像素。
|
||||
3. **双层嵌套限制**:你提供的代码里有两个重复的 `<div class="rich_media_content">` 容器层级,这可能会导致微信后台解析 CSS 时出错。
|
||||
|
||||
### 解决方案:针对公众号优化的 Python 转换逻辑
|
||||
|
||||
我们需要用 `BeautifulSoup` 来强制修正这些图片标签,并统一把 `http` 替换为 `https`。
|
||||
|
||||
```python
|
||||
import markdown
|
||||
import re
|
||||
from bs4 import BeautifulSoup
|
||||
from premailer import transform
|
||||
|
||||
def fix_wechat_images(html_content):
|
||||
soup = BeautifulSoup(html_content, 'html.parser')
|
||||
for img in soup.find_all('img'):
|
||||
src = img.get('src', '')
|
||||
|
||||
# 1. 强制将 http 转换为 https
|
||||
if src.startswith('http://'):
|
||||
src = src.replace('http://', 'https://')
|
||||
|
||||
# 2. 补全微信必须的属性
|
||||
img['src'] = src
|
||||
img['data-src'] = src
|
||||
|
||||
# 3. 强制给图片加行内样式,防止塌陷
|
||||
img['style'] = "display: block; margin: 20px auto; width: 100% !important; height: auto !important; visibility: visible !important;"
|
||||
|
||||
# 4. 移除可能导致冲突的 class
|
||||
if img.get('class'):
|
||||
del img['class']
|
||||
|
||||
return str(soup)
|
||||
|
||||
def md_to_wechat_final(md_text):
|
||||
# 基础 Markdown 转换
|
||||
html = markdown.markdown(md_text, extensions=['extra', 'fenced_code', 'attr_list'])
|
||||
|
||||
# 注入 CSS
|
||||
css = """
|
||||
<style>
|
||||
.rich_media_content { font-size: 16px; line-height: 1.75; color: #333; }
|
||||
h1 { font-size: 24px; font-weight: bold; color: #007aff; border-bottom: 2px solid #007aff; padding-bottom: 10px; margin: 1.5em 0 0.5em; }
|
||||
h4 { font-size: 16px; font-weight: bold; border-left: 4px solid #007aff; padding-left: 10px; margin: 1em 0; }
|
||||
blockquote { background: #f8f9fa; border-left: 4px solid #007aff; padding: 15px; color: #666; }
|
||||
pre { background: #2b2b2b; color: #f8f8f2; padding: 15px; border-radius: 6px; overflow-x: auto; }
|
||||
</style>
|
||||
"""
|
||||
|
||||
full_html = f'<div class="rich_media_content">{css}{html}</div>'
|
||||
|
||||
# 修正图片并转换行内样式
|
||||
fixed_html = fix_wechat_images(full_html)
|
||||
return transform(fixed_html)
|
||||
|
||||
# 使用方式
|
||||
# final_output = md_to_wechat_final(your_md_content)
|
||||
```
|
||||
|
||||
### 操作上的“致命”细节
|
||||
|
||||
哪怕代码写对了,**操作不对图片也出不来**。请务必遵守以下步骤:
|
||||
|
||||
1. **检查七牛云 HTTPS**:确保你的七牛云域名已经配置了 SSL 证书。如果 `https://img.yidaima.cn/...` 在浏览器里打不开,图片永远也进不了公众号。
|
||||
2. **不要在编辑器里“粘贴源码”**:
|
||||
* 微信公众号后台**没有**“查看源码”模式。
|
||||
* 你需要用浏览器(推荐 Chrome)打开生成的 `.html` 文件。
|
||||
* 在浏览器页面上 **Ctrl+A(全选)** -> **Ctrl+C(复制)**。
|
||||
* 在公众号正文框里直接 **Ctrl+V(粘贴)**。
|
||||
3. **防盗链白名单**:如果粘贴后显示“此图片来自非官方渠道”,你需要去七牛云后台关闭“Referer 防盗链”,或者将 `servicewechat.com` 和 `mp.weixin.qq.com` 加入白名单。
|
||||
81
docs/plan.md
Normal file
81
docs/plan.md
Normal file
@@ -0,0 +1,81 @@
|
||||
这是一个非常明智的选择。**Umi-OCR** 相比于直接调用 `PaddleOCR` 的库,最大的优势在于它提供了一个非常成熟的 **HTTP API 接口**(或者离线命令行接口),这使得你的 Python 自动化脚本可以保持轻量化,不需要在本地环境安装庞大且容易起冲突的深度学习库。
|
||||
|
||||
以下是针对 **Umi-OCR** 集成的更新版开发指南 MD 文档:
|
||||
|
||||
---
|
||||
|
||||
# 🚀 桌面自动化脚本开发指南 (Umi-OCR 集成版)
|
||||
|
||||
## 1. 系统架构说明
|
||||
本脚本采用 **Umi-OCR (HTTP 服务模式)** 作为感知核心。脚本通过发送截图到 Umi-OCR 的本地 API,获取 JSON 格式的识别结果(文字内容及坐标)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心技术栈
|
||||
* **OCR 引擎**: [Umi-OCR](https://github.com/hiroi-sora/Umi-OCR) (需提前启动 HTTP 服务)。
|
||||
* **浏览器控制**: Playwright (用于操作 Web 端 DMS/ERP)。
|
||||
* **桌面控制**: PyAutoGUI / Mouse (用于点击 OCR 识别出的坐标)。
|
||||
* **通信**: `requests` (用于调用 Umi-OCR API)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 目录结构规范
|
||||
```text
|
||||
project_root/
|
||||
├── config/ # 配置文件 (yaml/json)
|
||||
├── core/
|
||||
│ ├── ocr_client.py # 封装 Umi-OCR API 调用逻辑
|
||||
│ ├── browser.py # Playwright 页面操作
|
||||
│ └── actions.py # 封装“识别文字并点击”的高级动作
|
||||
├── config.yaml # 存放 Umi-OCR 地址 (默认 http://127.0.0.1:1224/api/ocr)
|
||||
├── data/ # 存放临时截图、下载的文件
|
||||
├── assets/ # 存放用于识别的图标/模板图片
|
||||
├── utils/ # 日志、时间处理等工具类
|
||||
└── main.py # 业务主流程
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键模块开发逻辑
|
||||
|
||||
### 4.1 OCR 调用逻辑 (`ocr_client.py`)
|
||||
> **AI 指令**:请实现一个 `UmiClient` 类,要求:
|
||||
* 使用 `requests` 向 `http://127.0.0.1:1224/api/ocr` 发送 Base64 编码的图片。
|
||||
* 解析返回的 JSON,提取 `data` 列表中的 `text` 和 `box`(四个顶点的坐标)。
|
||||
* 提供一个 `find_text(target_name)` 方法,返回该文字在屏幕上的中心点 `(x, y)`。
|
||||
|
||||
### 4.2 自动化执行逻辑 (`actions.py`)
|
||||
> **AI 指令**:结合 `PyAutoGUI` 和 `ocr_client.py`:
|
||||
* 实现 `click_text(text)`:截图 -> OCR 识别 -> 匹配目标 -> 点击。
|
||||
* 实现 `wait_for_text(text, timeout=20)`:在规定时间内循环检测屏幕是否出现目标文字。
|
||||
|
||||
---
|
||||
|
||||
## 5. 开发约束
|
||||
1. **服务检测**:脚本启动时需检测 Umi-OCR 端口是否占用,若未启动则抛出错误提醒。
|
||||
2. **区域 OCR**:为了提高效率,支持“局部截图 OCR”,而不是每次都截全屏。
|
||||
3. **坐标转换**:Umi-OCR 返回的是相对图片的坐标,需确保点击时与 Windows 屏幕坐标对齐。
|
||||
|
||||
---
|
||||
|
||||
## 6. 第一步:Umi-OCR API 调用代码参考
|
||||
你可以让 AI 基于以下片段进行扩展:
|
||||
|
||||
```python
|
||||
import requests
|
||||
import base64
|
||||
|
||||
def call_umi_ocr(image_path):
|
||||
url = "http://127.0.0.1:1224/api/ocr"
|
||||
with open(image_path, "rb") as f:
|
||||
img64 = base64.b64encode(f.read()).decode('utf-8')
|
||||
|
||||
payload = {
|
||||
"base64": img64,
|
||||
"options": {"data_format": "dict"}
|
||||
}
|
||||
response = requests.post(url, json=payload)
|
||||
return response.json()
|
||||
```
|
||||
|
||||
---
|
||||
7
docs/step1.md
Normal file
7
docs/step1.md
Normal file
@@ -0,0 +1,7 @@
|
||||
1.打开浏览器,访问网址:https://feast.yidaima.cn/login
|
||||
2.输入用户名:wangpeng,密码:Feastcoding@123。
|
||||
3.点击登录
|
||||
4.点击菜单工作室运营,然后再打开源码管理页面。
|
||||
5.在源码管理页面,搜索项目名称:【A167】基于Springboot + vue3实现的宿舍报修系统。
|
||||
6.在列表上找到【A167】基于Springboot + vue3实现的宿舍报修系统这条数据,点击查看。
|
||||
7.在详情页鼠标滚动到最下面,点击FeastCoding按钮。
|
||||
3
docs/step2.md
Normal file
3
docs/step2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
1.获取剪切板内容
|
||||
2.将剪切板内容转换为公众号文章格式,调用工具类md_to_wechat.py
|
||||
3.推送到公众号草稿箱
|
||||
0
docs/step3.md
Normal file
0
docs/step3.md
Normal file
84
docs/公众号.md
Normal file
84
docs/公众号.md
Normal file
@@ -0,0 +1,84 @@
|
||||
在 Python 中推送文章到微信公众号草稿箱,主要通过微信提供的 **草稿箱 API** 实现。
|
||||
|
||||
这个过程通常分为三步:**获取 Access Token**、**上传封面图(素材)**、以及 **新增草稿**。
|
||||
|
||||
---
|
||||
|
||||
### 1. 前期准备
|
||||
你需要先在 [微信公众平台](https://mp.weixin.qq.com/) 获取以下信息:
|
||||
* **AppID**
|
||||
* **AppSecret**
|
||||
* **白名单配置**:确保你运行代码的服务器 IP 已加入公众号后台的 IP 白名单。
|
||||
|
||||
### 2. 核心流程与代码实现
|
||||
|
||||
我们可以使用 Python 的 `requests` 库来完成。
|
||||
|
||||
#### 第一步:获取 Access Token
|
||||
这是调用所有 API 的“通行证”。
|
||||
|
||||
```python
|
||||
import requests
|
||||
import json
|
||||
|
||||
def get_access_token(appid, secret):
|
||||
url = f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}"
|
||||
res = requests.get(url).json()
|
||||
return res.get('access_token')
|
||||
```
|
||||
|
||||
#### 第二步:上传封面图片
|
||||
草稿箱要求文章必须有封面图,且封面图需要先上传到微信服务器获取 `thumb_media_id`。
|
||||
|
||||
```python
|
||||
def upload_thumb(access_token, image_path):
|
||||
url = f"https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={access_token}&type=image"
|
||||
files = {'media': open(image_path, 'rb')}
|
||||
res = requests.post(url, files=files).json()
|
||||
return res.get('media_id') # 这就是 thumb_media_id
|
||||
```
|
||||
|
||||
#### 第三步:推送至草稿箱
|
||||
最后,将文章标题、正文(HTML 格式)和封面 ID 提交。
|
||||
|
||||
```python
|
||||
def add_draft(access_token, title, content, thumb_id):
|
||||
url = f"https://api.weixin.qq.com/cgi-bin/draft/add?access_token={access_token}"
|
||||
|
||||
# 文章数据结构
|
||||
articles = {
|
||||
"articles": [
|
||||
{
|
||||
"title": title,
|
||||
"author": "YourName",
|
||||
"digest": "摘要内容",
|
||||
"content": content, # 支持 HTML 格式
|
||||
"content_source_url": "", # 阅读原文链接
|
||||
"thumb_media_id": thumb_id,
|
||||
"need_open_comment": 0 # 是否打开评论
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# 微信 API 要求发送 JSON 字符串,且处理中文需确保编码正确
|
||||
data = json.dumps(articles, ensure_ascii=False).encode('utf-8')
|
||||
res = requests.post(url, data=data).json()
|
||||
return res
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. 常见问题提示
|
||||
|
||||
* **图片问题**:如果你在 `content`(正文)里引用了外部图片链接,微信可能会屏蔽它们。建议先通过 `cgi-bin/media/uploadimg` 接口将图片上传到微信图床,获取微信内部链接后再放入 HTML 中。
|
||||
* **API 限制**:草稿箱 API 每天的调用次数有限(通常为 10,000 次),对于个人/小团队来说完全够用。
|
||||
* **HTML 标签**:微信正文支持的 HTML 比较基础,复杂的 CSS 样式可能会被过滤,建议使用标准的 `p`, `span`, `strong`, `img` 等标签。
|
||||
|
||||
---
|
||||
|
||||
### 快速总结工具
|
||||
| 步骤 | API 接口 | 目的 |
|
||||
| :--- | :--- | :--- |
|
||||
| 1 | `/cgi-bin/token` | 获取授权凭证 |
|
||||
| 2 | `/cgi-bin/material/add_material` | 获取封面图 ID |
|
||||
| 3 | `/cgi-bin/draft/add` | 写入草稿箱 |
|
||||
231
docs/编辑器.md
Normal file
231
docs/编辑器.md
Normal file
@@ -0,0 +1,231 @@
|
||||
我来先查看一下这个项目的具体实现,然后为你设计一个完整的Python实现方案。
|
||||
基于对 doocs/md 项目的分析,我为你设计了一个完整的 Python 实现方案。这是一个桌面端微信 Markdown 编辑器,包含你要求的所有功能。
|
||||
|
||||
## 技术选型建议
|
||||
|
||||
**GUI 框架**: 推荐使用 **PyQt6/PySide6** 或 **Tkinter + CustomTkinter**
|
||||
- PyQt6: 功能强大,适合复杂应用
|
||||
- CustomTkinter: 现代化外观,开发快速
|
||||
|
||||
**Markdown 渲染**:
|
||||
- `markdown` + `pygments` (代码高亮)
|
||||
- 或直接嵌入 `WebEngine` 用 JavaScript 渲染
|
||||
|
||||
---
|
||||
|
||||
## 完整提示词 (Prompt)
|
||||
|
||||
```markdown
|
||||
# 微信 Markdown 编辑器 - Python 桌面应用开发
|
||||
|
||||
## 项目概述
|
||||
使用 Python 开发一个仿照 https://github.com/doocs/md 的微信 Markdown 编辑器桌面应用。支持实时预览、多主题切换、自定义样式,专为微信公众号排版优化。
|
||||
|
||||
## 技术栈要求
|
||||
- **GUI 框架**: PyQt6 (推荐) 或 CustomTkinter
|
||||
- **Markdown 解析**: markdown + pymdownx 扩展 + pygments
|
||||
- **预览引擎**: QWebEngineView (PyQt6) 或 WebView (Tkinter)
|
||||
- **配置存储**: JSON 配置文件
|
||||
- **代码高亮**: Pygments (支持 100+ 主题)
|
||||
|
||||
## 核心功能模块
|
||||
|
||||
### 1. 编辑器界面布局
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 菜单栏: 文件 | 编辑 | 格式 | 主题 | 设置 | 帮助 │
|
||||
├──────────────────┬──────────────────┬───────────────────────┤
|
||||
│ │ │ │
|
||||
│ Markdown │ 预览/手机 │ 设置面板 │
|
||||
│ 编辑区 │ 模拟预览 │ (可折叠) │
|
||||
│ (左侧) │ (中间) │ (右侧) │
|
||||
│ │ │ │
|
||||
│ - 行号显示 │ - 微信样式渲染 │ - 主题选择 │
|
||||
│ - 语法高亮 │ - 手机框模拟 │ - 字体设置 │
|
||||
│ - 自动保存 │ - 一键复制HTML │ - 代码块主题 │
|
||||
│ │ │ - 自定义CSS │
|
||||
└──────────────────┴──────────────────┴───────────────────────┘
|
||||
```
|
||||
|
||||
### 2. 必须实现的功能清单
|
||||
|
||||
#### A. 主题系统
|
||||
- [ ] **预设主题** (至少5个):
|
||||
- 默认主题 (类似微信默认)
|
||||
- 优雅主题 (简约商务风)
|
||||
- 科技主题 (暗色代码风格)
|
||||
- 文艺主题 (衬线字体)
|
||||
- 节日主题 (可切换配色)
|
||||
- [ ] **主题色自定义**: 主色调、强调色、背景色选择器
|
||||
- [ ] **实时预览**: 切换主题即时生效
|
||||
|
||||
#### B. 字体设置
|
||||
- [ ] **正文字体**: 提供系统字体列表选择
|
||||
- [ ] **标题字体**: 可独立设置或跟随正文
|
||||
- [ ] **代码字体**: 等宽字体选择 (推荐: Consolas, Fira Code, JetBrains Mono)
|
||||
- [ ] **字号调节**: 正文字号 (12px-20px), 标题相对比例
|
||||
|
||||
#### C. 代码块样式
|
||||
- [ ] **Mac 风格代码块开关**: 是否显示 macOS 窗口控制按钮 (红黄绿圆点)
|
||||
- [ ] **代码主题选择**:
|
||||
- 亮色主题: default, github, vs, xcode
|
||||
- 暗色主题: monokai, dracula, one-dark, nord
|
||||
- [ ] **代码行号显示**: 可选开启/关闭
|
||||
- [ ] **代码复制按钮**: 悬浮显示复制图标
|
||||
|
||||
#### D. 自定义 CSS
|
||||
- [ ] **CSS 编辑器**: 内置代码编辑器输入自定义样式
|
||||
- [ ] **实时生效**: 输入 CSS 即时预览效果
|
||||
- [ ] **导入/导出**: 支持保存为 .css 文件
|
||||
- [ ] **重置功能**: 一键恢复默认样式
|
||||
|
||||
#### E. 微信专用功能
|
||||
- [ ] **微信样式重置**: 自动添加微信兼容性 CSS
|
||||
- [ ] **图片处理**: 支持本地图片转 Base64 或图床上传
|
||||
- [ ] **一键复制**: 生成适合粘贴到公众号后台的 HTML
|
||||
- [ ] **手机预览**: 模拟 iPhone 界面预览效果
|
||||
|
||||
### 3. 详细界面组件
|
||||
|
||||
#### 设置面板 (右侧抽屉/面板)
|
||||
```python
|
||||
settings_panel = {
|
||||
"外观设置": {
|
||||
"主题选择": ["下拉菜单", "预设主题列表"],
|
||||
"主题色": ["颜色选择器", "支持十六进制输入"],
|
||||
"自定义主题": ["保存当前配置为新主题", "删除自定义主题"]
|
||||
},
|
||||
"字体设置": {
|
||||
"正文字体": ["系统字体下拉框", "中文字体优先"],
|
||||
"正文字号": ["滑块: 12-20px", "数字输入框"],
|
||||
"标题字体": ["同正文/独立选择", "复选框"],
|
||||
"标题缩放": ["滑块: 1.0-2.0倍"],
|
||||
"代码字体": ["等宽字体列表"]
|
||||
},
|
||||
"代码块设置": {
|
||||
"Mac风格": ["开关按钮", "控制是否显示三个圆点"],
|
||||
"代码主题": ["下拉菜单", "按亮/暗分类"],
|
||||
"显示行号": ["开关"],
|
||||
"代码背景": ["颜色选择", "圆角设置"]
|
||||
},
|
||||
"高级设置": {
|
||||
"自定义CSS": ["文本编辑区", "语法高亮"],
|
||||
"导入CSS": ["文件选择按钮"],
|
||||
"导出配置": ["保存当前所有设置"],
|
||||
"重置默认": ["确认后恢复出厂设置"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 数据结构设计
|
||||
|
||||
```python
|
||||
# 配置文件结构 (config.json)
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"editor": {
|
||||
"font_family": "PingFang SC, Microsoft YaHei",
|
||||
"font_size": 14,
|
||||
"auto_save": true,
|
||||
"auto_save_interval": 30
|
||||
},
|
||||
"preview": {
|
||||
"theme": "default", # 当前主题ID
|
||||
"custom_themes": [
|
||||
{
|
||||
"id": "custom_1",
|
||||
"name": "我的主题",
|
||||
"primary_color": "#07C160",
|
||||
"background": "#ffffff",
|
||||
"text_color": "#333333",
|
||||
"css_override": "..."
|
||||
}
|
||||
],
|
||||
"font": {
|
||||
"body": "PingFang SC",
|
||||
"heading": "PingFang SC",
|
||||
"code": "Consolas",
|
||||
"body_size": 16,
|
||||
"heading_scale": 1.3
|
||||
},
|
||||
"code_block": {
|
||||
"mac_style": true,
|
||||
"theme": "github",
|
||||
"line_numbers": false,
|
||||
"background": "#f6f8fa",
|
||||
"border_radius": 6
|
||||
},
|
||||
"custom_css": "/* 用户自定义CSS */"
|
||||
},
|
||||
"recent_files": ["path/to/file1.md", "path/to/file2.md"]
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 核心类设计
|
||||
|
||||
```python
|
||||
# 主要类结构
|
||||
class WechatMarkdownEditor(QMainWindow):
|
||||
"""主窗口"""
|
||||
def __init__(self):
|
||||
self.editor = MarkdownEditor() # 编辑区
|
||||
self.preview = PreviewWidget() # 预览区
|
||||
self.settings = SettingsPanel() # 设置面板
|
||||
self.theme_manager = ThemeManager() # 主题管理器
|
||||
|
||||
class ThemeManager:
|
||||
"""主题管理"""
|
||||
def load_themes(self) -> List[Theme]
|
||||
def apply_theme(self, theme_id: str)
|
||||
def save_custom_theme(self, theme: Theme)
|
||||
def export_css(self, theme: Theme) -> str
|
||||
|
||||
class PreviewGenerator:
|
||||
"""预览生成器"""
|
||||
def markdown_to_html(self, md_content: str) -> str
|
||||
def apply_wechat_style(self, html: str) -> str
|
||||
def inject_custom_css(self, html: str, css: str) -> str
|
||||
def generate_mac_code_block(self, code: str, lang: str) -> str
|
||||
```
|
||||
|
||||
### 6. 微信样式 CSS 模板
|
||||
|
||||
```css
|
||||
/* 微信文章基础样式 */
|
||||
.wechat-article {
|
||||
max-width: 677px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
font-family: {{body_font}};
|
||||
font-size: {{body_size}}px;
|
||||
line-height: 1.8;
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/* Mac 风格代码块 */
|
||||
.mac-code-block {
|
||||
position: relative;
|
||||
background: #f6f8fa;
|
||||
border-radius: 6px;
|
||||
padding: 16px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.mac-code-block::before {
|
||||
content: "● ● ●";
|
||||
color: #ff5f56 #ffbd2e #27c93f;
|
||||
letter-spacing: 4px;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
/* 代码高亮主题变量 */
|
||||
.code-theme-{{theme_name}} {
|
||||
--bg: {{code_bg}};
|
||||
--text: {{code_text}};
|
||||
--keyword: {{keyword_color}};
|
||||
--string: {{string_color}};
|
||||
--comment:
|
||||
Reference in New Issue
Block a user