diff --git a/README.md b/README.md
index d632887..c72a11b 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,8 @@
-
+
+
OpenPrint
@@ -32,6 +33,9 @@
> 纯前端架构,无需服务器,无需数据库,一个浏览器即可运行。
+
+*所见即所得的打印模板设计器,拖拽控件、实时预览*
+
---
## 目录
@@ -57,6 +61,9 @@
告别手动拖拽,直接描述需求即可生成专业打印模板。支持快递面单、物流标签、仓储单据、零售小票等多种场景。
+
+*AI 自然语言生成打印模板,一句话完成面单设计*
+
```
用户输入:"帮我生成一张快递面单,含收件人、寄件人和运单号条码"
AI 输出: 自动创建模板 → 布局文本控件 → 添加条码 → 一键使用
@@ -66,10 +73,16 @@ AI 输出: 自动创建模板 → 布局文本控件 → 添加条码 → 一
跨地域多门店远程打印,模板统一管理。浏览器直接打印,免装驱动。云端打印队列,断线自动重试,权限管控,打印日志审计。
+
+*多门店远程打印,模板统一管理,打印队列监控*
+
### 📊 Web 报表设计
分组表、交叉表、主从表等多级报表结构,支持求和/平均/计数等汇总函数,嵌入柱状图/折线图/饼图,条件格式高亮数据预警,多数据源拼接。
+
+*分组报表、交叉表、图表,满足复杂数据展示需求*
+
---
## 功能特性
@@ -118,7 +131,7 @@ AI 输出: 自动创建模板 → 布局文本控件 → 添加条码 → 一
```bash
# 克隆仓库
-git clone https://github.com/your-repo/open-print.git
+git clone https://gitee.com/haiming236/openprint.git
cd open-print
# 安装依赖
@@ -136,7 +149,7 @@ pnpm preview
### 在线演示
-访问 [open-print.example.com/demo](https://open-print.example.com/demo) 在线体验设计器。
+访问 [https://openprint.yy360.space](https://openprint.yy360.space) 在线体验设计器。
---
@@ -298,6 +311,9 @@ OpenPrint 提供配套的 **C++ Qt 桌面打印客户端**,支持:
- **HTTP 接口** — 通过 REST API 接收打印任务
- **跨平台** — Windows / Linux / macOS
+
+*C++ Qt 桌面客户端,静默打印,批量处理*
+
### 技术栈

@@ -316,6 +332,9 @@ OpenPrint 提供标准 HTTP API,3 分钟即可完成 ERP 对接:
2. **导出模板文件** — 导出 `.json` 模板文件
3. **API 对接** — ERP 系统通过 HTTP 推送数据 + 模板 ID,触发打印
+
+*标准 HTTP API 对接,3 分钟接入 ERP 系统*
+
### API 示例
```http
@@ -404,7 +423,7 @@ pnpm vitest --coverage
## 许可证
-[MIT License](LICENSE)
+[GPL3.0 License](LICENSE)
Copyright (c) 2025 OpenPrint
@@ -414,7 +433,7 @@ Copyright (c) 2025 OpenPrint
OpenPrint — 让打印变得简单高效
- GitHub ·
- Gitee ·
- 在线演示
-
\ No newline at end of file
+ GitHub ·
+ Gitee ·
+ 在线演示
+
diff --git a/screenshots/README.md b/screenshots/README.md
new file mode 100644
index 0000000..4d6d6df
--- /dev/null
+++ b/screenshots/README.md
@@ -0,0 +1,12 @@
+# 截图素材
+
+将以下截图文件放入此目录,替换 README 中的配图:
+
+| 文件 | 说明 | 建议尺寸 |
+|------|------|----------|
+| `designer-overview.png` | 设计器界面全貌,展示控件库 + 画布 + 属性面板 | 1920×1080 |
+| `ai-assistant.png` | AI 助手聊天窗口 + 生成的面单模板 | 1200×800 |
+| `cloud-print.png` | 云打印架构拓扑图 | 1200×800 |
+| `report-design.png` | 报表设计效果(表格 + 图表) | 1200×800 |
+| `desktop-client.png` | C++ Qt 桌面客户端界面 | 1200×800 |
+| `erp-integration.png` | ERP 对接流程示意图 | 1200×800 |
\ No newline at end of file
diff --git a/screenshots/ai-assistant.png b/screenshots/ai-assistant.png
new file mode 100644
index 0000000..ef87363
Binary files /dev/null and b/screenshots/ai-assistant.png differ
diff --git a/screenshots/cloud-print.jpg b/screenshots/cloud-print.jpg
new file mode 100644
index 0000000..9b739ab
Binary files /dev/null and b/screenshots/cloud-print.jpg differ
diff --git a/screenshots/designer-overview.png b/screenshots/designer-overview.png
new file mode 100644
index 0000000..e5f0d62
Binary files /dev/null and b/screenshots/designer-overview.png differ
diff --git a/screenshots/desktop-client.jpg b/screenshots/desktop-client.jpg
new file mode 100644
index 0000000..ad07a3a
Binary files /dev/null and b/screenshots/desktop-client.jpg differ
diff --git a/screenshots/erp-integration.jpg b/screenshots/erp-integration.jpg
new file mode 100644
index 0000000..9704b23
Binary files /dev/null and b/screenshots/erp-integration.jpg differ
diff --git a/screenshots/report-design.png b/screenshots/report-design.png
new file mode 100644
index 0000000..38ba268
Binary files /dev/null and b/screenshots/report-design.png differ
diff --git a/src/core/chartkit/bar.ts b/src/core/chartkit/bar.ts
index 894b04c..a9d815e 100644
--- a/src/core/chartkit/bar.ts
+++ b/src/core/chartkit/bar.ts
@@ -4,7 +4,7 @@
* 输出一串 (按序列分组并排)+ 坐标轴 + 可选网格 + 图例 + 数据标签。
* 全部用逻辑坐标(viewBox),实际尺寸由外层容器缩放,矢量清晰。
*/
-import { escapeXml, fmt, niceMax, seriesColor, truncate, legendStartX, xAxisLabelPos } from './core'
+import { escapeXml, fmt, niceMax, seriesColor, truncate, legendStartX } from './core'
import type { ChartModel } from './types'
export function renderBar(model: ChartModel): string {
@@ -21,7 +21,7 @@ export function renderBar(model: ChartModel): string {
const titleH = title ? 22 : 0
const mTop = 10 + titleH
const mRight = 16
- const mBottom = (showAxis ? 34 : 18) + legendH
+ const mBottom = (showAxis ? 38 : 22) + legendH
const mLeft = showAxis ? 44 : 16
const px0 = mLeft
@@ -86,16 +86,15 @@ export function renderBar(model: ChartModel): string {
parts.push(`${fmt(val)}`)
}
}
- // x 轴标签
+ // x 轴标签:始终以类目为基准居中于对应条带正下方,并与图表留一点间距
if (showAxis) {
- const pos = xAxisLabelPos(opt.labelAlign, px0 + band * c, px0 + band * (c + 1), cx)
- parts.push(`${escapeXml(truncate(String(cats[c] ?? '')))}`)
+ parts.push(`${escapeXml(truncate(String(cats[c] ?? '')))}`)
}
}
// 图例
if (showLegend) {
- const align = opt.labelAlign ?? 'left'
+ const align = opt.labelAlign ?? 'center'
let totalW = 0
for (let s = 0; s < sCount; s++) {
const name = model.series[s]!.name || `系列${s + 1}`
@@ -103,7 +102,7 @@ export function renderBar(model: ChartModel): string {
}
const startX = legendStartX(align, W, totalW, px0)
let lx = startX
- let ly = py1 + (showAxis ? 24 : 10)
+ let ly = py1 + (showAxis ? 30 : 16)
for (let s = 0; s < sCount; s++) {
const name = model.series[s]!.name || `系列${s + 1}`
const color = seriesColor(model.series[s]!, s, opt)
diff --git a/src/core/chartkit/core.ts b/src/core/chartkit/core.ts
index bc44389..7896d06 100644
--- a/src/core/chartkit/core.ts
+++ b/src/core/chartkit/core.ts
@@ -117,15 +117,3 @@ export function legendStartX(
if (align === 'right') return Math.max(leftPad, W - totalW - 8)
return leftPad
}
-
-/** x 轴类目标签的水平对齐 → SVG text-anchor 与基准 x */
-export function xAxisLabelPos(
- align: 'left' | 'center' | 'right' | undefined,
- bandLeft: number,
- bandRight: number,
- bandCenter: number,
-): { x: number; anchor: 'start' | 'middle' | 'end' } {
- if (align === 'left') return { x: bandLeft + 4, anchor: 'start' }
- if (align === 'right') return { x: bandRight - 4, anchor: 'end' }
- return { x: bandCenter, anchor: 'middle' }
-}
diff --git a/src/core/chartkit/line.ts b/src/core/chartkit/line.ts
index 2c6af4a..3e1641a 100644
--- a/src/core/chartkit/line.ts
+++ b/src/core/chartkit/line.ts
@@ -4,7 +4,7 @@
* 多序列折线 + 坐标轴 + 可选网格 + 图例 + 数据标签。
* 支持 smooth(Catmull-Rom 平滑曲线)与 area(折线下方面积填充)。
*/
-import { escapeXml, fmt, niceMax, seriesColor, truncate, legendStartX, xAxisLabelPos } from './core'
+import { escapeXml, fmt, niceMax, seriesColor, truncate, legendStartX } from './core'
import type { ChartModel } from './types'
interface Pt { x: number; y: number }
@@ -43,7 +43,7 @@ export function renderLine(model: ChartModel): string {
const titleH = title ? 22 : 0
const mTop = 10 + titleH
const mRight = 16
- const mBottom = (showAxis ? 34 : 18) + legendH
+ const mBottom = (showAxis ? 38 : 22) + legendH
const mLeft = showAxis ? 44 : 16
const px0 = mLeft
@@ -101,8 +101,8 @@ export function renderLine(model: ChartModel): string {
parts.push(``)
for (let c = 0; c < n; c++) {
const x = px0 + band * (c + 0.5)
- const pos = xAxisLabelPos(opt.labelAlign, px0 + band * c, px0 + band * (c + 1), x)
- parts.push(`${escapeXml(truncate(String(cats[c] ?? '')))}`)
+ // x 轴类目标签:始终以类目为基准居中于对应点正下方,并与图表留一点间距
+ parts.push(`${escapeXml(truncate(String(cats[c] ?? '')))}`)
}
}
@@ -132,7 +132,7 @@ export function renderLine(model: ChartModel): string {
}
if (showLegend) {
- const align = opt.labelAlign ?? 'left'
+ const align = opt.labelAlign ?? 'center'
let totalW = 0
for (let s = 0; s < seriesPts.length; s++) {
const name = seriesPts[s]!.name || `系列${s + 1}`
@@ -140,7 +140,7 @@ export function renderLine(model: ChartModel): string {
}
const startX = legendStartX(align, W, totalW, px0)
let lx = startX
- let ly = py1 + (showAxis ? 24 : 10)
+ let ly = py1 + (showAxis ? 30 : 16)
for (let s = 0; s < seriesPts.length; s++) {
const name = seriesPts[s]!.name || `系列${s + 1}`
const color = seriesPts[s]!.color
diff --git a/src/core/chartkit/pie.ts b/src/core/chartkit/pie.ts
index fbcdc24..ee8f41f 100644
--- a/src/core/chartkit/pie.ts
+++ b/src/core/chartkit/pie.ts
@@ -63,7 +63,7 @@ export function renderPie(model: ChartModel): string {
}
if (showLegend) {
- const align = opt.labelAlign ?? 'left'
+ const align = opt.labelAlign ?? 'center'
let totalW = 0
for (let i = 0; i < data.length; i++) {
const name = cats[i] ?? `类目${i + 1}`
diff --git a/src/design/panels/props/ChartProps.vue b/src/design/panels/props/ChartProps.vue
index a7db255..0cc062c 100644
--- a/src/design/panels/props/ChartProps.vue
+++ b/src/design/panels/props/ChartProps.vue
@@ -113,7 +113,7 @@ const valueLabel = computed({
set: (v: boolean) => patchOption('valueLabel', v),
})
const labelAlign = computed({
- get: () => control.value?.options?.labelAlign ?? 'left',
+ get: () => control.value?.options?.labelAlign ?? 'center',
set: (v: 'left' | 'center' | 'right') => patchOption('labelAlign', v),
})
const smooth = computed({
@@ -220,7 +220,7 @@ const donut = computed({
- 标签对齐
+ 图例对齐