Compare commits

...

6 Commits

Author SHA1 Message Date
wangjia b0a74f3607 chore: release v1.0.26
Deploy / build-linux-web (push) Successful in 55s
Deploy / build-windows (push) Successful in 2m2s
Deploy / build-macos (push) Successful in 1m17s
Deploy / build-android (push) Successful in 1m30s
Deploy / build-ios (push) Successful in 6s
Deploy / release-deploy (push) Successful in 1m43s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 22:40:54 +08:00
wangjia 543bd2712f chore: update todo list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 22:40:17 +08:00
wangjia fab7bd21dd feat: #13 公开商品 API 补充 code/barcode/batch.quantity,报错反馈携带商品和门店信息
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 22:39:59 +08:00
wangjia 3b2ebc0202 fix(web): 注册页 API URL 改用 site.appBaseUrl,修正成功提示导航路径
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 22:33:16 +08:00
wangjia ff32c8a845 fix(client): 公开页页脚「关于岩美」链接改为 AppConfig.aboutUrl 配置项
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 22:27:38 +08:00
wangjia af64e29459 fix(client): 公开页页脚「关于岩美」链接修正为 jiu.51yanmei.com
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:19:33 +08:00
9 changed files with 139 additions and 108 deletions
+11
View File
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.26] - 2026-06-08
### 新功能
- 公开商品 API 新增商品编码、条码、当前库存数量字段,供扫码页及第三方集成使用
- 公开页「商品报错」「意见反馈」提交时自动携带门店编号和商品信息,方便运营追踪
### 修复
- 注册页 API 地址改为配置文件驱动,支持分离部署场景(不再依赖 window.location.origin
- 注册成功提示的客户端导航路径由「系统设置 → 关于」修正为「系统设置」
- 公开页页脚「关于岩美」链接改为配置项,不再硬编码
## [1.0.25] - 2026-06-08
### 新功能
+23 -21
View File
@@ -17,16 +17,17 @@ func NewErrorReportHandler(db *gorm.DB) *ErrorReportHandler {
}
type submitErrorRequest struct {
ErrorType string `json:"error_type" binding:"required"`
AppVersion string `json:"app_version"`
Platform string `json:"platform"`
Username string `json:"username"`
ShopID uint64 `json:"shop_id"`
ShopNo string `json:"shop_no"`
Role string `json:"role"`
ErrorMsg string `json:"error_msg" binding:"required"`
StackTrace string `json:"stack_trace"`
OccurredAt int64 `json:"occurred_at"` // Unix 毫秒
ErrorType string `json:"error_type" binding:"required"`
AppVersion string `json:"app_version"`
Platform string `json:"platform"`
Username string `json:"username"`
ShopID uint64 `json:"shop_id"`
ShopNo string `json:"shop_no"`
Role string `json:"role"`
ProductInfo string `json:"product_info"`
ErrorMsg string `json:"error_msg" binding:"required"`
StackTrace string `json:"stack_trace"`
OccurredAt int64 `json:"occurred_at"` // Unix 毫秒
}
// Submit POST /api/v1/public/errors
@@ -49,17 +50,18 @@ func (h *ErrorReportHandler) Submit(c *gin.Context) {
}
report := model.ErrorReport{
ErrorType: req.ErrorType,
AppVersion: req.AppVersion,
Platform: req.Platform,
Username: req.Username,
ShopID: req.ShopID,
ShopNo: req.ShopNo,
Role: req.Role,
ClientIP: c.ClientIP(),
ErrorMsg: req.ErrorMsg,
StackTrace: stack,
OccurredAt: occurredAt,
ErrorType: req.ErrorType,
AppVersion: req.AppVersion,
Platform: req.Platform,
Username: req.Username,
ShopID: req.ShopID,
ShopNo: req.ShopNo,
Role: req.Role,
ProductInfo: req.ProductInfo,
ClientIP: c.ClientIP(),
ErrorMsg: req.ErrorMsg,
StackTrace: stack,
OccurredAt: occurredAt,
}
if err := h.db.Create(&report).Error; err != nil {
+3
View File
@@ -72,6 +72,7 @@ func (h *PublicHandler) GetProduct(c *gin.Context) {
"production_date": pdStr,
"batch_no": inv.BatchNo,
"in_stock_date": inv.CreatedAt.Format("2006-01-02"),
"quantity": inv.Quantity,
}
}
@@ -100,6 +101,8 @@ func (h *PublicHandler) GetProduct(c *gin.Context) {
"data": gin.H{
"id": product.ID,
"name": product.Name,
"code": product.Code,
"barcode": product.Barcode,
"series": product.Series,
"spec": product.Spec,
"brand": product.Brand,
+3 -2
View File
@@ -12,8 +12,9 @@ type ErrorReport struct {
Username string `gorm:"size:50;index" json:"username"`
ShopID uint64 `gorm:"index" json:"shop_id"`
ShopNo string `gorm:"size:50" json:"shop_no"`
Role string `gorm:"size:20" json:"role"`
ClientIP string `gorm:"size:60" json:"client_ip"`
Role string `gorm:"size:20" json:"role"`
ProductInfo string `gorm:"size:200" json:"product_info"`
ClientIP string `gorm:"size:60" json:"client_ip"`
ErrorMsg string `gorm:"type:text;not null" json:"error_msg"`
StackTrace string `gorm:"type:text" json:"stack_trace"`
OccurredAt time.Time `json:"occurred_at"`
+5
View File
@@ -34,6 +34,11 @@ class AppConfig {
defaultValue: '',
);
static const aboutUrl = String.fromEnvironment(
'ABOUT_URL',
defaultValue: 'https://jiu.51yanmei.com',
);
static String get baseUrl => _baseUrl;
static String get apiBaseUrl => '$_baseUrl/api/v1';
static String get healthUrl => '$_baseUrl/health';
@@ -70,13 +70,22 @@ class _PublicProductScreenState extends State<PublicProductScreen> {
title: title,
hint: hint,
onSubmit: (msg) async {
final shopNo = (_data?['shop'] as Map<String, dynamic>?)?['code'] as String? ?? '';
final productName = _data?['name'] as String? ?? '';
final productCode = _data?['code'] as String? ?? '';
final productInfo = [
if (productName.isNotEmpty) productName,
if (productCode.isNotEmpty) productCode,
if (widget.publicId.isNotEmpty) widget.publicId,
].join(' / ');
await _dio.post(
'${AppConfig.apiBaseUrl}/public/errors',
data: {
'error_type': errorType,
'error_msg': msg,
'platform': 'web-scan',
'shop_no': (_data?['shop'] as Map<String, dynamic>?)?['code'] as String? ?? '',
'shop_no': shopNo,
if (productInfo.isNotEmpty) 'product_info': productInfo,
},
);
},
@@ -1484,7 +1493,7 @@ class _Footer extends StatelessWidget {
const _FooterDivider(),
_FooterTextLink(text: '意见反馈', onTap: onFeedback),
const _FooterDivider(),
_FooterTextLink(text: '关于岩美', url: 'https://www.yanmei.com'),
_FooterTextLink(text: '关于岩美', url: AppConfig.aboutUrl),
],
),
],
+68 -68
View File
@@ -102,8 +102,8 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
<div class="header-meta">生成于 2026-06-08 · 真相源 todo/todo.json</div>
<div class="stats">
<div class="stat-pill"><strong>15</strong>全部</div>
<div class="stat-pill"><strong>5</strong>未完成</div>
<div class="stat-pill"><strong>10</strong>已完成</div>
<div class="stat-pill"><strong>1</strong>未完成</div>
<div class="stat-pill"><strong>14</strong>已完成</div>
</div>
</div>
</header>
@@ -132,7 +132,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
<div class="wrap">
<div class="section-title">📋 未完成(5</div>
<div class="section-title">📋 未完成(1</div>
<ul class="todo-list" id="pendingList">
<li class="todo-card"
@@ -153,69 +153,18 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
</div>
</div>
</li>
</ul>
<li class="todo-card"
data-id="3"
data-level="low"
data-tags="前端,Web"
data-done="0">
<div class="card-header">
<span class="item-title">注册接口同源依赖问题</span>
<span class="tag t-low">一般 / 优化</span>
</div>
<div class="item-desc">用 window.location.origin+'/api/v1/public/register',要求同源部署;分离部署时指错。需确认部署形态。</div>
<div class="card-footer">
<div class="tag-row"><span class="tag t-tag" data-tag="前端">前端</span> <span class="tag t-tag" data-tag="Web">Web</span></div>
<div class="item-meta">
<span class="meta-date">🕐 2026-06-08</span>
<div class="done-section">
<div class="section-title done-title">✅ 已完成(14</div>
<button class="done-toggle" id="doneToggle">▾ 展开已完成列表</button>
<ul class="todo-list hidden" id="doneList">
</div>
</div>
</li>
<li class="todo-card"
data-id="5"
data-level="low"
data-tags="前端,Web"
data-done="0">
<div class="card-header">
<span class="item-title">页脚双份维护</span>
<span class="tag t-low">一般 / 优化</span>
</div>
<div class="item-desc">njk 站点用 footer.njk 读变量,功能页把页脚硬编码各写一份,改一处不同步。根因同「两套模板」。</div>
<div class="card-footer">
<div class="tag-row"><span class="tag t-tag" data-tag="前端">前端</span> <span class="tag t-tag" data-tag="Web">Web</span></div>
<div class="item-meta">
<span class="meta-date">🕐 2026-06-08</span>
</div>
</div>
</li>
<li class="todo-card"
data-id="6"
data-level="low"
data-tags="前端,Web"
data-done="0">
<div class="card-header">
<span class="item-title">注册成功提示路径需核对</span>
<span class="tag t-low">一般 / 优化</span>
</div>
<div class="item-desc">提示「忘记门店编码可在「系统设置→关于」查看」,需与实际客户端菜单路径一致。</div>
<div class="card-footer">
<div class="tag-row"><span class="tag t-tag" data-tag="前端">前端</span> <span class="tag t-tag" data-tag="Web">Web</span></div>
<div class="item-meta">
<span class="meta-date">🕐 2026-06-08</span>
</div>
</div>
</li>
<li class="todo-card"
<li class="todo-card done"
data-id="13"
data-level="low"
data-tags="后端,iOS,Android"
data-done="0">
data-done="1">
<div class="card-header">
<span class="item-title">公开商品 API 补充 batch.quantity 和 product code/barcode</span>
<span class="tag t-low">一般 / 优化</span>
@@ -225,17 +174,68 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span> <span class="tag t-tag" data-tag="iOS">iOS</span> <span class="tag t-tag" data-tag="Android">Android</span></div>
<div class="item-meta">
<span class="meta-date">🕐 2026-06-08</span>
<span class="meta-date">✅ 完成 2026-06-08 · <span class="ver-badge">v1.0.25</span></span>
</div>
</div>
</li>
<li class="todo-card done"
data-id="6"
data-level="low"
data-tags="前端,Web"
data-done="1">
<div class="card-header">
<span class="item-title">注册成功提示路径需核对</span>
<span class="tag t-low">一般 / 优化</span>
</div>
<div class="item-desc">提示「忘记门店编码可在「系统设置→关于」查看」,需与实际客户端菜单路径一致。</div>
<div class="card-footer">
<div class="tag-row"><span class="tag t-tag" data-tag="前端">前端</span> <span class="tag t-tag" data-tag="Web">Web</span></div>
<div class="item-meta">
<span class="meta-date">🕐 2026-06-08</span>
<span class="meta-date">✅ 完成 2026-06-08 · <span class="ver-badge">v1.0.25</span></span>
</div>
</div>
</li>
<li class="todo-card done"
data-id="5"
data-level="low"
data-tags="前端,Web"
data-done="1">
<div class="card-header">
<span class="item-title">页脚双份维护</span>
<span class="tag t-low">一般 / 优化</span>
</div>
<div class="item-desc">njk 站点用 footer.njk 读变量,功能页把页脚硬编码各写一份,改一处不同步。根因同「两套模板」。</div>
<div class="card-footer">
<div class="tag-row"><span class="tag t-tag" data-tag="前端">前端</span> <span class="tag t-tag" data-tag="Web">Web</span></div>
<div class="item-meta">
<span class="meta-date">🕐 2026-06-08</span>
<span class="meta-date">✅ 完成 2026-06-08 · <span class="ver-badge">v1.0.25</span></span>
</div>
</div>
</li>
<li class="todo-card done"
data-id="3"
data-level="low"
data-tags="前端,Web"
data-done="1">
<div class="card-header">
<span class="item-title">注册接口同源依赖问题</span>
<span class="tag t-low">一般 / 优化</span>
</div>
<div class="item-desc">用 window.location.origin+'/api/v1/public/register',要求同源部署;分离部署时指错。需确认部署形态。</div>
<div class="card-footer">
<div class="tag-row"><span class="tag t-tag" data-tag="前端">前端</span> <span class="tag t-tag" data-tag="Web">Web</span></div>
<div class="item-meta">
<span class="meta-date">🕐 2026-06-08</span>
<span class="meta-date">✅ 完成 2026-06-08 · <span class="ver-badge">v1.0.25</span></span>
</div>
</div>
</li>
</ul>
<div class="done-section">
<div class="section-title done-title">✅ 已完成(10</div>
<button class="done-toggle" id="doneToggle">▾ 展开已完成列表</button>
<ul class="todo-list hidden" id="doneList">
<li class="todo-card done"
data-id="18"
data-level="low"
+13 -13
View File
@@ -1,7 +1,7 @@
{
"meta": {
"title": "酒库管理系统 — 项目 TODO",
"updated_at": "2026-06-08T00:06:15.371Z"
"updated_at": "2026-06-08T14:40:04.464Z"
},
"seq": 18,
"items": [
@@ -42,9 +42,9 @@
"Web"
],
"created_at": "2026-06-07T17:30:32.237Z",
"done": false,
"completed_at": null,
"version": null
"done": true,
"completed_at": "2026-06-08T14:33:22.523Z",
"version": "v1.0.25"
},
{
"id": 4,
@@ -70,9 +70,9 @@
"Web"
],
"created_at": "2026-06-07T17:30:32.334Z",
"done": false,
"completed_at": null,
"version": null
"done": true,
"completed_at": "2026-06-08T14:33:22.584Z",
"version": "v1.0.25"
},
{
"id": 6,
@@ -84,9 +84,9 @@
"Web"
],
"created_at": "2026-06-07T17:30:32.381Z",
"done": false,
"completed_at": null,
"version": null
"done": true,
"completed_at": "2026-06-08T14:33:22.648Z",
"version": "v1.0.25"
},
{
"id": 8,
@@ -145,9 +145,9 @@
"Android"
],
"created_at": "2026-06-07T18:12:43.136Z",
"done": false,
"completed_at": null,
"version": null
"done": true,
"completed_at": "2026-06-08T14:40:04.464Z",
"version": "v1.0.25"
},
{
"id": 14,
+2 -2
View File
@@ -161,7 +161,7 @@ pageStyle: |
</table>
</div>
<p class="success-note">如忘记门店编码,登录后可在「系统设置 → 关于」中查看。</p>
<p class="success-note">如忘记门店编码,登录后可在「系统设置」中查看。</p>
<a href="/app/" class="btn btn-primary" style="display:inline-flex;align-items:center;gap:8px;">
<i data-lucide="log-in" class="icon"></i>前往登录
</a>
@@ -172,7 +172,7 @@ pageStyle: |
<script>
(function() {
var API_URL = window.location.origin + '/api/v1/public/register';
var API_URL = "{{ site.appBaseUrl }}/api/v1/public/register";
function $(id) { return document.getElementById(id); }