Files
cmsp/main.go
T
QiuSWandClaude Opus 5 2cefa67001 feat: 初始化 Wails v2 + Vue3 骨架与 SQLite 存储 (#4)
建立可运行、可构建的 Go 骨架,供后续 R1~R5 在其上叠加。

后端:
- main.go / app.go:Wails v2 窗口与 14 个前端可调方法。Wails 专有 API
  只出现在这两个文件,internal/ 对 Wails 零依赖,便于将来迁移 v3
- internal/config:config.yaml 的读写、校验、脱敏。保存时按固定模板
  渲染以保留注释,不用 yaml.Marshal
- internal/store:SQLite(modernc.org/sqlite,无需 CGO)。建表迁移、
  商品仓储、KV。重复同步不会覆盖本地下载与上传状态
- internal/logx:9 条脱敏规则,覆盖淘宝 token、Cookie、Authorization、
  密码和图片 base64;并发安全的内存日志缓冲

前端(Vue 3 + Naive UI,按已确认原型 v4):
- Sidebar:176px 可折叠,仅商品列表与参数设置两项,底部是登录状态的
  唯一显示位置
- ProductListView:两行工具栏(四项筛选 + 重置搜索 / 四个操作按钮)、
  商品表格、分页
- SettingsView:四张卡片,路径用文件与目录选择框
- LogWindow:运行日志子窗口,按级别过滤、自动滚动、导出

配置改用 YAML:分 huohanhan / taobao / download 三段。taobao 段刻意
没有账号密码字段,并有单元测试挡住后续加入。

构建相关:
- .gitignore 只忽略 build/bin/,不忽略 build/。Wails 把 build/ 当源码
  目录(图标、manifest),忽略掉会让别人克隆后构建失败
- .gitignore 忽略 config.yaml、payloads/ 和 *.har(含真实手机号与凭据)

未实现的下载数据、下载视频、上传数据三个方法返回明确的「还没实现」,
不静默失败。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LbdtsD3ohhSMy3KPoCgARq
2026-09-02 15:59:54 +08:00

90 lines
2.9 KiB
Go
Raw 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.
// cmsp 是一个 Windows 桌面工具:把货憨憨 ERP 里指定 Shopee 店铺的商品,
// 按商品主图到淘宝搜同款,抓取同款商品详情页的介绍视频,下载到本地,
// 再批量上传回货憨憨对应商品,使 Shopee 商品页刷新后能看到视频。
//
// 从哪里开始读:
//
// main.go 这里,负责启动窗口
// app.go 暴露给前端的方法清单
// internal/config/ 参数设置的读写与校验
// internal/store/ SQLite,所有状态的唯一事实来源
// internal/logx/ 带脱敏的日志
// frontend/src/ 界面
//
// 完整说明见 Wiki:https://git.ilapage.cn/chengma/cmsp/wiki
package main
import (
"embed"
"log"
"os"
"path/filepath"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
"github.com/wailsapp/wails/v2/pkg/options/windows"
)
// 把编译好的前端打包进可执行文件,这样发给同事就是单个 exe,
// 不用再带一堆网页文件。
//
//go:embed all:frontend/dist
var assets embed.FS
func main() {
app := NewApp()
// 窗口尺寸对应已确认的原型:1440x900。
// MinWidth 设成 1200 是因为工具栏上行有六个筛选控件,
// 再窄就会挤在一起看不清。
err := wails.Run(&options.App{
Title: "cmsp — Shopee 商品视频工具",
Width: 1440,
Height: 900,
MinWidth: 1200,
MinHeight: 700,
AssetServer: &assetserver.Options{
Assets: assets,
},
OnStartup: app.startup,
OnShutdown: app.shutdown,
// Bind 里的对象会被生成成 JavaScript 给前端调用。
// 新增可供前端调用的方法,就写成 App 的公开方法,不用改这里。
Bind: []any{
app,
},
Windows: &windows.Options{
// 关掉右键菜单里的「检查」等开发者项,避免同事误点。
// 需要调试时用 wails dev,那时会自动打开。
DisableWindowIcon: false,
},
})
if err != nil {
// 走到这里说明窗口没能创建,界面上什么都看不到,
// 所以要同时写到控制台和文件,否则同事只会看到程序一闪而过。
log.Println("启动失败:", err)
writeStartupError(err)
}
}
// writeStartupError 把启动失败的原因写到程序目录下的文件里。
//
// 双击 exe 启动时没有控制台,报错会一闪而过。留个文件,
// 同事能直接把它发给维护者。
func writeStartupError(runErr error) {
exe, err := os.Executable()
if err != nil {
return
}
path := filepath.Join(filepath.Dir(exe), "启动失败.txt")
_ = writeTextFile(path, "cmsp 启动失败:\n"+runErr.Error()+"\n")
}
// writeTextFile 用 UTF-8 写一个文本文件。
//
// 单独抽出来是因为 app.go 导出日志时也要用。
func writeTextFile(path, content string) error {
return os.WriteFile(path, []byte(content), 0o600)
}