mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-08 08:36:37 +08:00
fix: 配置版本列表按 created_at 倒序展示
This commit is contained in:
@@ -18,6 +18,8 @@ sidebar: false
|
|||||||
|
|
||||||
### 修复
|
### 修复
|
||||||
|
|
||||||
|
- 配置版本列表按 `created_at` 倒序展示,最新发布版本固定显示在列表顶部。
|
||||||
|
|
||||||
- 修复 WAF 规则组 PoW 策略发布后边缘不生效:统一 WAF 绑定站点名与 OpenResty 路由 `site_name` 解析逻辑,并为所有已启用网站生成 `site_rule_groups` 条目(含仅依赖全局规则组的站点)。
|
- 修复 WAF 规则组 PoW 策略发布后边缘不生效:统一 WAF 绑定站点名与 OpenResty 路由 `site_name` 解析逻辑,并为所有已启用网站生成 `site_rule_groups` 条目(含仅依赖全局规则组的站点)。
|
||||||
|
|
||||||
- 收敛子代理站点标识双轨逻辑:新增 `routeidentity` 统一包,`proxy_route`、`config_version`、`uptimekuma`、`flared` 与 OpenResty 渲染共用 `ResolveSiteName` / `DecodeDomains`;移除废弃 `RenderPoWConfig`;PoW Lua 与 WAF 一致仅依赖 `$openflare_waf_site`。
|
- 收敛子代理站点标识双轨逻辑:新增 `routeidentity` 统一包,`proxy_route`、`config_version`、`uptimekuma`、`flared` 与 OpenResty 渲染共用 `ResolveSiteName` / `DecodeDomains`;移除废弃 `RenderPoWConfig`;PoW Lua 与 WAF 一致仅依赖 `$openflare_waf_site`。
|
||||||
|
|||||||
@@ -80,6 +80,15 @@ export default function ConfigVersionsPage() {
|
|||||||
[preview, diff],
|
[preview, diff],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const sortedVersions = useMemo(
|
||||||
|
() =>
|
||||||
|
[...versions].sort(
|
||||||
|
(left, right) =>
|
||||||
|
new Date(right.created_at).getTime() - new Date(left.created_at).getTime(),
|
||||||
|
),
|
||||||
|
[versions],
|
||||||
|
)
|
||||||
|
|
||||||
const fetchVersions = useCallback(async () => {
|
const fetchVersions = useCallback(async () => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
setError(null)
|
setError(null)
|
||||||
@@ -240,7 +249,7 @@ export default function ConfigVersionsPage() {
|
|||||||
<div className="border border-dashed shadow-none rounded-lg overflow-hidden bg-background">
|
<div className="border border-dashed shadow-none rounded-lg overflow-hidden bg-background">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<LoadingStateWithBorder />
|
<LoadingStateWithBorder />
|
||||||
) : versions.length === 0 ? (
|
) : sortedVersions.length === 0 ? (
|
||||||
<EmptyStateWithBorder
|
<EmptyStateWithBorder
|
||||||
title="暂无历史版本"
|
title="暂无历史版本"
|
||||||
description="当前还没有可查看的发布记录,请先触发一次配置发布。"
|
description="当前还没有可查看的发布记录,请先触发一次配置发布。"
|
||||||
@@ -258,7 +267,7 @@ export default function ConfigVersionsPage() {
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{versions.map((version) => (
|
{sortedVersions.map((version) => (
|
||||||
<TableRow
|
<TableRow
|
||||||
key={version.id}
|
key={version.id}
|
||||||
className="border-dashed hover:bg-muted/10 transition-colors"
|
className="border-dashed hover:bg-muted/10 transition-colors"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Rain-kl/Wavelet/internal/apps/openflare/waf"
|
"github.com/Rain-kl/Wavelet/internal/apps/openflare/waf"
|
||||||
"github.com/Rain-kl/Wavelet/internal/db"
|
"github.com/Rain-kl/Wavelet/internal/db"
|
||||||
@@ -38,6 +39,40 @@ func setupConfigVersionTestDB(t *testing.T) func() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestListConfigVersionsOrdersByCreatedAtDesc(t *testing.T) {
|
||||||
|
cleanup := setupConfigVersionTestDB(t)
|
||||||
|
defer cleanup()
|
||||||
|
ctx := context.Background()
|
||||||
|
conn := db.DB(ctx)
|
||||||
|
require.NotNil(t, conn)
|
||||||
|
|
||||||
|
newer := &model.ConfigVersion{
|
||||||
|
Version: "20260102-001",
|
||||||
|
SnapshotJSON: "{}",
|
||||||
|
RenderedConfig: "route {}",
|
||||||
|
Checksum: "checksum-newer",
|
||||||
|
CreatedBy: "tester",
|
||||||
|
CreatedAt: time.Date(2026, 1, 2, 12, 0, 0, 0, time.UTC),
|
||||||
|
}
|
||||||
|
older := &model.ConfigVersion{
|
||||||
|
Version: "20260101-001",
|
||||||
|
SnapshotJSON: "{}",
|
||||||
|
RenderedConfig: "route {}",
|
||||||
|
Checksum: "checksum-older",
|
||||||
|
CreatedBy: "tester",
|
||||||
|
CreatedAt: time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC),
|
||||||
|
}
|
||||||
|
require.NoError(t, conn.Create(newer).Error)
|
||||||
|
require.NoError(t, conn.Create(older).Error)
|
||||||
|
require.Greater(t, older.ID, newer.ID)
|
||||||
|
|
||||||
|
versions, err := ListConfigVersions(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, versions, 2)
|
||||||
|
assert.Equal(t, newer.Version, versions[0].Version)
|
||||||
|
assert.Equal(t, older.Version, versions[1].Version)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPublishConfigVersionCreatesVersion(t *testing.T) {
|
func TestPublishConfigVersionCreatesVersion(t *testing.T) {
|
||||||
cleanup := setupConfigVersionTestDB(t)
|
cleanup := setupConfigVersionTestDB(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func handleLogicError(c *gin.Context, err error) bool {
|
func handleLogicError(c *gin.Context, err error) bool {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
@@ -21,7 +20,7 @@ func handleLogicError(c *gin.Context, err error) bool {
|
|||||||
|
|
||||||
// ListConfigVersionsHandler lists config versions.
|
// ListConfigVersionsHandler lists config versions.
|
||||||
// @Summary 获取配置版本列表
|
// @Summary 获取配置版本列表
|
||||||
// @Description 返回所有已发布的 OpenResty 配置版本摘要,需要管理员权限
|
// @Description 返回所有已发布的 OpenResty 配置版本摘要,按创建时间倒序排列,需要管理员权限
|
||||||
// @Tags openflare-config-version
|
// @Tags openflare-config-version
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security SessionCookie
|
// @Security SessionCookie
|
||||||
@@ -187,4 +186,4 @@ func CleanupConfigVersionsHandler(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, response.OK(result))
|
c.JSON(http.StatusOK, response.OK(result))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func (ConfigVersion) TableName() string {
|
|||||||
return "of_config_versions"
|
return "of_config_versions"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListConfigVersionSummaries returns config version summaries ordered by id desc.
|
// ListConfigVersionSummaries returns config version summaries ordered by created_at desc.
|
||||||
func ListConfigVersionSummaries(ctx context.Context) ([]*ConfigVersionSummary, error) {
|
func ListConfigVersionSummaries(ctx context.Context) ([]*ConfigVersionSummary, error) {
|
||||||
conn := db.DB(ctx)
|
conn := db.DB(ctx)
|
||||||
if conn == nil {
|
if conn == nil {
|
||||||
@@ -50,7 +50,7 @@ func ListConfigVersionSummaries(ctx context.Context) ([]*ConfigVersionSummary, e
|
|||||||
var versions []*ConfigVersionSummary
|
var versions []*ConfigVersionSummary
|
||||||
err := conn.Model(&ConfigVersion{}).
|
err := conn.Model(&ConfigVersion{}).
|
||||||
Select("id", "version", "checksum", "is_active", "created_by", "created_at").
|
Select("id", "version", "checksum", "is_active", "created_by", "created_at").
|
||||||
Order("id desc").
|
Order("created_at desc, id desc").
|
||||||
Find(&versions).Error
|
Find(&versions).Error
|
||||||
return versions, err
|
return versions, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user