@web-mods/articles 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,250 @@
1
+ # @web-module/articles
2
+
3
+ 文章管理组件库,提供完整的文章 CRUD 管理界面(列表、编辑、详情)以及服务端 HTML 渲染能力。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ pnpm add @web-module/articles
9
+ ```
10
+
11
+ > **Peer dependencies**:`react >=18`、`react-dom >=18`
12
+ >
13
+ > `react-router` 仅在 **react-router 环境**下需要(见下方适配说明)。`dayjs`、`lucide-react`、`@monaco-editor/react` 均已打包在内,无需单独安装。
14
+
15
+ ---
16
+
17
+ ## 快速开始
18
+
19
+ ### 1. 配置 ArticleService(可选)
20
+
21
+ 组件库内置了指向 `https://api-blog.aisee.live` 的默认 service,**`service` prop 不传即使用默认值,无需任何配置**。
22
+
23
+ 只有以下情况才需要手动配置:
24
+
25
+ **自定义 API 地址:**
26
+ ```ts
27
+ import { createArticleService } from '@web-module/articles'
28
+ const articleService = createArticleService('https://your-api.example.com')
29
+ // 然后传给 Provider:<ArticlesProvider service={articleService} ...>
30
+ ```
31
+
32
+ **完全自定义请求逻辑**(如附带鉴权 Header、适配不同数据格式等):
33
+
34
+ ```ts
35
+ import type { ArticleService } from '@web-module/articles'
36
+
37
+ const articleService: ArticleService = {
38
+ getList: (params) => api.get('/news', { params }), // 返回 { items, total }
39
+ getById: (id) => api.get(`/news/${id}`),
40
+ create: (data) => api.post('/news', data),
41
+ update: (id, data) => api.put(`/news/${id}`, data),
42
+ delete: (id) => api.delete(`/news/${id}`),
43
+ getByPathname: (pathname) => api.get(`/news/detail?pathname=${pathname}`), // 可选,服务端渲染时使用
44
+ }
45
+ ```
46
+
47
+ `getList` 返回格式:
48
+
49
+ ```ts
50
+ { items: Article[], total?: number }
51
+ ```
52
+
53
+ ### 2. 配置路由
54
+
55
+ 以 React Router v7 为例,用 `layout` 包裹所有文章相关路由:
56
+
57
+ ```ts
58
+ // routes.ts
59
+ import { layout, route, prefix } from '@react-router/dev/routes'
60
+
61
+ export default [
62
+ layout('./pages/articles/layout.tsx', [
63
+ route('articles', './pages/articles/index.tsx'),
64
+ route('articles/create', './pages/articles/edit.tsx'),
65
+ route('articles/:id/edit', './pages/articles/edit.tsx'),
66
+ route('articles/:id/detail', './pages/articles/detail.tsx'),
67
+ ]),
68
+ ]
69
+ ```
70
+
71
+ ### 3. 创建 Layout(注入 Provider)
72
+
73
+ 组件库支持两种框架环境,写法略有不同:
74
+
75
+ #### React Router v7
76
+
77
+ 用 `ReactRouterAdapter` 桥接路由,这是唯一需要 `react-router` 的地方:
78
+
79
+ ```tsx
80
+ // pages/articles/layout.tsx
81
+ import { Outlet } from 'react-router'
82
+ import { ArticlesProvider, ReactRouterAdapter } from '@web-module/articles'
83
+ import '@web-module/articles/style.css'
84
+
85
+ export default function ArticlesLayout() {
86
+ return (
87
+ <ArticlesProvider basePath="/articles">
88
+ <ReactRouterAdapter>
89
+ <Outlet />
90
+ </ReactRouterAdapter>
91
+ </ArticlesProvider>
92
+ )
93
+ }
94
+ ```
95
+
96
+ #### Next.js(或其他非 react-router 框架)
97
+
98
+ 通过 Provider 的 `navigate` prop 注入路由能力,页面组件通过 `id` prop 接收参数:
99
+
100
+ ```tsx
101
+ // app/articles/layout.tsx
102
+ 'use client'
103
+ import { useRouter } from 'next/navigation'
104
+ import { ArticlesProvider } from '@web-module/articles'
105
+ import '@web-module/articles/style.css'
106
+
107
+ export default function ArticlesLayout({ children }: { children: React.ReactNode }) {
108
+ const router = useRouter()
109
+ return (
110
+ <ArticlesProvider basePath="/articles" navigate={(path) => router.push(path)}>
111
+ {children}
112
+ </ArticlesProvider>
113
+ )
114
+ }
115
+ ```
116
+
117
+ ```tsx
118
+ // app/articles/[id]/edit/page.tsx
119
+ 'use client'
120
+ import { useParams } from 'next/navigation'
121
+ import { ArticleEdit } from '@web-module/articles'
122
+
123
+ export default function EditPage() {
124
+ const { id } = useParams<{ id: string }>()
125
+ return <ArticleEdit id={id} />
126
+ }
127
+ ```
128
+
129
+ ### 4. 使用页面组件
130
+
131
+ ```tsx
132
+ // React Router:无需传 props,路由参数由 ReactRouterAdapter 自动注入
133
+ import { ArticleList, ArticleEdit, ArticleDetail } from '@web-module/articles'
134
+ export default function ListPage() { return <ArticleList /> }
135
+ export default function EditPage() { return <ArticleEdit /> }
136
+ export default function DetailPage() { return <ArticleDetail /> }
137
+
138
+ // Next.js / 其他框架:通过 id prop 传入
139
+ export default function EditPage() { return <ArticleEdit id={id} /> }
140
+ export default function DetailPage() { return <ArticleDetail id={id} /> }
141
+ ```
142
+
143
+ ---
144
+
145
+ ## ArticlesProvider 配置项
146
+
147
+ | 属性 | 类型 | 必填 | 说明 |
148
+ |------|------|------|------|
149
+ | `basePath` | `string` | ✅ | 文章路由根路径,如 `/articles` |
150
+ | `service` | `ArticleService` | — | 数据服务,不传默认使用内置 `https://api-blog.aisee.live` |
151
+ | `navigate` | `(path: string) => void` | — | 非 react-router 环境必传,由框架路由实现跳转 |
152
+ | `previewBaseUrl` | `string` | — | 预览 iframe 注入 `<base href="..."`,用于正确加载相对路径资源 |
153
+ | `previewTailwind` | `boolean` | — | 预览时自动注入 Tailwind CDN,适合内容使用了 Tailwind 类名的场景 |
154
+
155
+ ```tsx
156
+ <ArticlesProvider
157
+ basePath="/blog/articles"
158
+ previewBaseUrl="https://example.com"
159
+ previewTailwind={true}
160
+ >
161
+ ...
162
+ </ArticlesProvider>
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Article 数据结构
168
+
169
+ ```ts
170
+ interface Article {
171
+ id: string
172
+ pathname: string // 前台访问路径,如 about-us
173
+ content: string // 完整 HTML 内容
174
+ host?: string // 可跳转的网站地址,如 https://example.com
175
+ createdAt?: string
176
+ updatedAt?: string
177
+ }
178
+ ```
179
+
180
+ ---
181
+
182
+ ## 服务端渲染(Server-side Rendering)
183
+
184
+ > 适用于 Next.js Route Handler、Remix、Cloudflare Workers 等支持 Web `Request/Response` API 的环境。
185
+
186
+ 从独立的 `server` 入口引入,**不包含任何 React 依赖**,可安全在服务端使用:
187
+
188
+ ```ts
189
+ import { renderArticleByPathname } from '@web-module/articles/server'
190
+ ```
191
+
192
+ ### Next.js 示例
193
+
194
+ ```ts
195
+ // app/[slug]/route.ts
196
+ import { renderArticleByPathname, defaultArticleService } from '@web-module/articles/server'
197
+
198
+ export async function GET(_req: Request, { params }: { params: Promise<{ slug: string }> }) {
199
+ const { slug } = await params
200
+ return renderArticleByPathname(slug, defaultArticleService, {
201
+ faviconHref: '/favicon.svg', // 可选,自动注入 favicon
202
+ })
203
+ }
204
+ ```
205
+
206
+ 如需自定义 API 地址:
207
+
208
+ ```ts
209
+ import { renderArticleByPathname, createArticleService } from '@web-module/articles/server'
210
+
211
+ const service = createArticleService('https://your-api.example.com')
212
+
213
+ export async function GET(_req: Request, { params }: { params: Promise<{ slug: string }> }) {
214
+ const { slug } = await params
215
+ return renderArticleByPathname(slug, service)
216
+ }
217
+ ```
218
+
219
+ 访问 `https://your-site.com/about-us` 时,浏览器直接渲染 manage 后台编辑的 HTML 内容,无任何框架包裹。
220
+
221
+ ### renderArticleByPathname 参数
222
+
223
+ | 参数 | 类型 | 说明 |
224
+ |------|------|------|
225
+ | `pathname` | `string` | 文章路径 |
226
+ | `service` | `ArticleService` | 需实现 `getByPathname` 方法 |
227
+ | `options.faviconHref` | `string` | 自动注入 favicon,如 `/favicon.svg` |
228
+ | `options.notFoundHtml` | `string` | 自定义 404 页面 HTML,不传则使用内置样式 |
229
+
230
+ ---
231
+
232
+ ## 样式
233
+
234
+ 组件库使用 Tailwind CSS 构建,样式已编译打包至 `dist/style.css`。在 Layout 中引入一次即可,框架会在构建时将其内联进 `<head>`,**不会有样式闪烁(FOUC)**:
235
+
236
+ ```ts
237
+ import '@web-module/articles/style.css'
238
+ ```
239
+
240
+ ---
241
+
242
+ ## 发布新版本(维护者)
243
+
244
+ ```bash
245
+ pnpm release # patch 升版本 1.0.x → 1.0.x+1
246
+ pnpm release:minor # minor 升版本 1.0.x → 1.1.0
247
+ pnpm release:major # major 升版本 1.x.x → 2.0.0
248
+ ```
249
+
250
+ 流程:构建 → 升版本号 → git commit → publish → git push。
@@ -0,0 +1,13 @@
1
+ import { type ReactNode } from 'react';
2
+ export interface ConfirmOptions {
3
+ title: ReactNode;
4
+ content?: ReactNode;
5
+ okText?: string;
6
+ cancelText?: string;
7
+ okType?: 'default' | 'danger';
8
+ onOk?: () => void | Promise<void>;
9
+ onCancel?: () => void;
10
+ }
11
+ export declare function useModal(): readonly [{
12
+ confirm: (options: ConfirmOptions) => void;
13
+ }, import("react").ReactPortal | null];
@@ -0,0 +1 @@
1
+ export declare function ToastContainer(): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,8 @@
1
+ import { type ReactNode } from 'react';
2
+ interface TooltipProps {
3
+ title: ReactNode;
4
+ children: ReactNode;
5
+ placement?: 'top' | 'bottom';
6
+ }
7
+ export declare function Tooltip({ title, children, placement }: TooltipProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,15 @@
1
+ export type ToastType = 'success' | 'error' | 'warning';
2
+ export interface ToastItem {
3
+ id: string;
4
+ type: ToastType;
5
+ content: string;
6
+ }
7
+ type Listener = (toasts: ToastItem[]) => void;
8
+ export declare const message: {
9
+ success: (content: string) => void;
10
+ error: (content: string) => void;
11
+ warning: (content: string) => void;
12
+ };
13
+ export declare function subscribeToast(listener: Listener): () => void;
14
+ export declare function getToasts(): ToastItem[];
15
+ export {};
@@ -0,0 +1,15 @@
1
+ import { type ReactNode } from "react";
2
+ import type { ArticlesConfig, ArticlesProviderProps } from "../types";
3
+ /**
4
+ * 文章模块根 Provider。
5
+ *
6
+ * **react-router 环境**:在 Provider 内部用 <ReactRouterAdapter> 包裹子路由,
7
+ * 无需传 navigate。
8
+ *
9
+ * **其他框架(如 Next.js)**:传入 navigate,再给 ArticleEdit / ArticleDetail
10
+ * 组件传 id prop。
11
+ */
12
+ export declare function ArticlesProvider({ children, basePath, service, previewBaseUrl, previewTailwind, navigate, }: {
13
+ children: ReactNode;
14
+ } & ArticlesProviderProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare function useArticlesConfig(): ArticlesConfig;
package/dist/index.cjs ADDED
@@ -0,0 +1,135 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),c=require("react"),fe=require("./server.cjs"),pe=require("react-router"),nt=require("react-dom"),Se=c.createContext({navigate:()=>{},params:{},locationState:null});function Ce(){return c.useContext(Se)}let ee=[];const ke=new Set;function Pe(){ke.forEach(e=>e([...ee]))}function xe(e,r){const n=Math.random().toString(36).slice(2);ee=[...ee,{id:n,type:e,content:r}],Pe(),setTimeout(()=>{ee=ee.filter(s=>s.id!==n),Pe()},3e3)}const F={success:e=>xe("success",e),error:e=>xe("error",e),warning:e=>xe("warning",e)};function st(e){return ke.add(e),()=>{ke.delete(e)}}function at(){return ee}const it={success:"bg-emerald-500",error:"bg-red-500",warning:"bg-amber-500"},ot={success:"✓",error:"✕",warning:"⚠"};function ct(){const[e,r]=c.useState(at());return c.useEffect(()=>st(r),[]),e.length===0?null:t.jsx("div",{className:"fixed top-4 right-4 z-[9999] flex flex-col gap-2 pointer-events-none",children:e.map(n=>t.jsxs("div",{className:`flex items-center gap-2 px-4 py-2.5 rounded-lg shadow-lg text-sm text-white font-medium pointer-events-auto ${it[n.type]}`,children:[t.jsx("span",{className:"shrink-0 font-bold",children:ot[n.type]}),n.content]},n.id))})}const We=c.createContext(null);function lt({children:e,basePath:r,service:n=fe.defaultArticleService,previewBaseUrl:s,previewTailwind:o,navigate:u}){const g=t.jsxs(We.Provider,{value:{basePath:r,service:n,previewBaseUrl:s,previewTailwind:o},children:[e,t.jsx(ct,{})]});return u?t.jsx(Se.Provider,{value:{navigate:u,params:{},locationState:null},children:g}):g}function Oe(){const e=c.useContext(We);if(!e)throw new Error("useArticlesConfig must be used within ArticlesProvider");return e}function ut({children:e}){const r=pe.useNavigate(),n=pe.useParams(),s=pe.useLocation();return t.jsx(Se.Provider,{value:{navigate:(o,u)=>r(o,u),params:n,locationState:s.state},children:e})}/**
2
+ * @license lucide-react v1.11.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const Ve=(...e)=>e.filter((r,n,s)=>!!r&&r.trim()!==""&&s.indexOf(r)===n).join(" ").trim();/**
7
+ * @license lucide-react v1.11.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const dt=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();/**
12
+ * @license lucide-react v1.11.0 - ISC
13
+ *
14
+ * This source code is licensed under the ISC license.
15
+ * See the LICENSE file in the root directory of this source tree.
16
+ */const ht=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(r,n,s)=>s?s.toUpperCase():n.toLowerCase());/**
17
+ * @license lucide-react v1.11.0 - ISC
18
+ *
19
+ * This source code is licensed under the ISC license.
20
+ * See the LICENSE file in the root directory of this source tree.
21
+ */const De=e=>{const r=ht(e);return r.charAt(0).toUpperCase()+r.slice(1)};/**
22
+ * @license lucide-react v1.11.0 - ISC
23
+ *
24
+ * This source code is licensed under the ISC license.
25
+ * See the LICENSE file in the root directory of this source tree.
26
+ */var ge={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
27
+ * @license lucide-react v1.11.0 - ISC
28
+ *
29
+ * This source code is licensed under the ISC license.
30
+ * See the LICENSE file in the root directory of this source tree.
31
+ */const ft=e=>{for(const r in e)if(r.startsWith("aria-")||r==="role"||r==="title")return!0;return!1},mt=c.createContext({}),pt=()=>c.useContext(mt),xt=c.forwardRef(({color:e,size:r,strokeWidth:n,absoluteStrokeWidth:s,className:o="",children:u,iconNode:g,...k},$)=>{const{size:C=24,strokeWidth:m=2,absoluteStrokeWidth:S=!1,color:H="currentColor",className:P=""}=pt()??{},T=s??S?Number(n??m)*24/Number(r??C):n??m;return c.createElement("svg",{ref:$,...ge,width:r??C??ge.width,height:r??C??ge.height,stroke:e??H,strokeWidth:T,className:Ve("lucide",P,o),...!u&&!ft(k)&&{"aria-hidden":"true"},...k},[...g.map(([R,z])=>c.createElement(R,z)),...Array.isArray(u)?u:[u]])});/**
32
+ * @license lucide-react v1.11.0 - ISC
33
+ *
34
+ * This source code is licensed under the ISC license.
35
+ * See the LICENSE file in the root directory of this source tree.
36
+ */const V=(e,r)=>{const n=c.forwardRef(({className:s,...o},u)=>c.createElement(xt,{ref:u,iconNode:r,className:Ve(`lucide-${dt(De(e))}`,`lucide-${e}`,s),...o}));return n.displayName=De(e),n};/**
37
+ * @license lucide-react v1.11.0 - ISC
38
+ *
39
+ * This source code is licensed under the ISC license.
40
+ * See the LICENSE file in the root directory of this source tree.
41
+ */const gt=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],Ye=V("arrow-left",gt);/**
42
+ * @license lucide-react v1.11.0 - ISC
43
+ *
44
+ * This source code is licensed under the ISC license.
45
+ * See the LICENSE file in the root directory of this source tree.
46
+ */const yt=[["path",{d:"m16 18 6-6-6-6",key:"eg8j8"}],["path",{d:"m8 6-6 6 6 6",key:"ppft3o"}]],qe=V("code",yt);/**
47
+ * @license lucide-react v1.11.0 - ISC
48
+ *
49
+ * This source code is licensed under the ISC license.
50
+ * See the LICENSE file in the root directory of this source tree.
51
+ */const bt=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],vt=V("copy",bt);/**
52
+ * @license lucide-react v1.11.0 - ISC
53
+ *
54
+ * This source code is licensed under the ISC license.
55
+ * See the LICENSE file in the root directory of this source tree.
56
+ */const wt=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],jt=V("external-link",wt);/**
57
+ * @license lucide-react v1.11.0 - ISC
58
+ *
59
+ * This source code is licensed under the ISC license.
60
+ * See the LICENSE file in the root directory of this source tree.
61
+ */const Nt=[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],$e=V("eye",Nt);/**
62
+ * @license lucide-react v1.11.0 - ISC
63
+ *
64
+ * This source code is licensed under the ISC license.
65
+ * See the LICENSE file in the root directory of this source tree.
66
+ */const kt=[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]],$t=V("file-text",kt);/**
67
+ * @license lucide-react v1.11.0 - ISC
68
+ *
69
+ * This source code is licensed under the ISC license.
70
+ * See the LICENSE file in the root directory of this source tree.
71
+ */const Mt=[["polyline",{points:"22 12 16 12 14 15 10 15 8 12 2 12",key:"o97t9d"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"oot6mr"}]],St=V("inbox",Mt);/**
72
+ * @license lucide-react v1.11.0 - ISC
73
+ *
74
+ * This source code is licensed under the ISC license.
75
+ * See the LICENSE file in the root directory of this source tree.
76
+ */const Ct=[["path",{d:"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71",key:"1cjeqo"}],["path",{d:"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71",key:"19qd67"}]],Ot=V("link",Ct);/**
77
+ * @license lucide-react v1.11.0 - ISC
78
+ *
79
+ * This source code is licensed under the ISC license.
80
+ * See the LICENSE file in the root directory of this source tree.
81
+ */const Pt=[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]],Dt=V("loader-circle",Pt);/**
82
+ * @license lucide-react v1.11.0 - ISC
83
+ *
84
+ * This source code is licensed under the ISC license.
85
+ * See the LICENSE file in the root directory of this source tree.
86
+ */const Et=[["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2",key:"48i651"}],["line",{x1:"8",x2:"16",y1:"21",y2:"21",key:"1svkeh"}],["line",{x1:"12",x2:"12",y1:"17",y2:"21",key:"vw1qmm"}]],Ue=V("monitor",Et);/**
87
+ * @license lucide-react v1.11.0 - ISC
88
+ *
89
+ * This source code is licensed under the ISC license.
90
+ * See the LICENSE file in the root directory of this source tree.
91
+ */const Lt=[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]],At=V("pencil",Lt);/**
92
+ * @license lucide-react v1.11.0 - ISC
93
+ *
94
+ * This source code is licensed under the ISC license.
95
+ * See the LICENSE file in the root directory of this source tree.
96
+ */const Tt=[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]],_t=V("plus",Tt);/**
97
+ * @license lucide-react v1.11.0 - ISC
98
+ *
99
+ * This source code is licensed under the ISC license.
100
+ * See the LICENSE file in the root directory of this source tree.
101
+ */const zt=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],Rt=V("rotate-ccw",zt);/**
102
+ * @license lucide-react v1.11.0 - ISC
103
+ *
104
+ * This source code is licensed under the ISC license.
105
+ * See the LICENSE file in the root directory of this source tree.
106
+ */const Ht=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],ye=V("search",Ht);/**
107
+ * @license lucide-react v1.11.0 - ISC
108
+ *
109
+ * This source code is licensed under the ISC license.
110
+ * See the LICENSE file in the root directory of this source tree.
111
+ */const It=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],Ee=V("shield-check",It);/**
112
+ * @license lucide-react v1.11.0 - ISC
113
+ *
114
+ * This source code is licensed under the ISC license.
115
+ * See the LICENSE file in the root directory of this source tree.
116
+ */const Wt=[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2",ry:"2",key:"1yt0o3"}],["path",{d:"M12 18h.01",key:"mhygvu"}]],Fe=V("smartphone",Wt);/**
117
+ * @license lucide-react v1.11.0 - ISC
118
+ *
119
+ * This source code is licensed under the ISC license.
120
+ * See the LICENSE file in the root directory of this source tree.
121
+ */const Vt=[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2",ry:"2",key:"76otgf"}],["line",{x1:"12",x2:"12.01",y1:"18",y2:"18",key:"1dp563"}]],Be=V("tablet",Vt);function Yt(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var ue={exports:{}},qt=ue.exports,Le;function Ut(){return Le||(Le=1,(function(e,r){(function(n,s){e.exports=s()})(qt,(function(){var n=1e3,s=6e4,o=36e5,u="millisecond",g="second",k="minute",$="hour",C="day",m="week",S="month",H="quarter",P="year",T="date",R="Invalid Date",z=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,q=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,_={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(b){var a=["th","st","nd","rd"],i=b%100;return"["+b+(a[(i-20)%10]||a[i]||a[0])+"]"}},p=function(b,a,i){var d=String(b);return!d||d.length>=a?b:""+Array(a+1-d.length).join(i)+b},A={s:p,z:function(b){var a=-b.utcOffset(),i=Math.abs(a),d=Math.floor(i/60),l=i%60;return(a<=0?"+":"-")+p(d,2,"0")+":"+p(l,2,"0")},m:function b(a,i){if(a.date()<i.date())return-b(i,a);var d=12*(i.year()-a.year())+(i.month()-a.month()),l=a.clone().add(d,S),v=i-l<0,N=a.clone().add(d+(v?-1:1),S);return+(-(d+(i-l)/(v?l-N:N-l))||0)},a:function(b){return b<0?Math.ceil(b)||0:Math.floor(b)},p:function(b){return{M:S,y:P,w:m,d:C,D:T,h:$,m:k,s:g,ms:u,Q:H}[b]||String(b||"").toLowerCase().replace(/s$/,"")},u:function(b){return b===void 0}},O="en",y={};y[O]=_;var w="$isDayjsObject",I=function(b){return b instanceof Y||!(!b||!b[w])},E=function b(a,i,d){var l;if(!a)return O;if(typeof a=="string"){var v=a.toLowerCase();y[v]&&(l=v),i&&(y[v]=i,l=v);var N=a.split("-");if(!l&&N.length>1)return b(N[0])}else{var f=a.name;y[f]=a,l=f}return!d&&l&&(O=l),l||!d&&O},x=function(b,a){if(I(b))return b.clone();var i=typeof a=="object"?a:{};return i.date=b,i.args=arguments,new Y(i)},M=A;M.l=E,M.i=I,M.w=function(b,a){return x(b,{locale:a.$L,utc:a.$u,x:a.$x,$offset:a.$offset})};var Y=(function(){function b(i){this.$L=E(i.locale,null,!0),this.parse(i),this.$x=this.$x||i.x||{},this[w]=!0}var a=b.prototype;return a.parse=function(i){this.$d=(function(d){var l=d.date,v=d.utc;if(l===null)return new Date(NaN);if(M.u(l))return new Date;if(l instanceof Date)return new Date(l);if(typeof l=="string"&&!/Z$/i.test(l)){var N=l.match(z);if(N){var f=N[2]-1||0,j=(N[7]||"0").substring(0,3);return v?new Date(Date.UTC(N[1],f,N[3]||1,N[4]||0,N[5]||0,N[6]||0,j)):new Date(N[1],f,N[3]||1,N[4]||0,N[5]||0,N[6]||0,j)}}return new Date(l)})(i),this.init()},a.init=function(){var i=this.$d;this.$y=i.getFullYear(),this.$M=i.getMonth(),this.$D=i.getDate(),this.$W=i.getDay(),this.$H=i.getHours(),this.$m=i.getMinutes(),this.$s=i.getSeconds(),this.$ms=i.getMilliseconds()},a.$utils=function(){return M},a.isValid=function(){return this.$d.toString()!==R},a.isSame=function(i,d){var l=x(i);return this.startOf(d)<=l&&l<=this.endOf(d)},a.isAfter=function(i,d){return x(i)<this.startOf(d)},a.isBefore=function(i,d){return this.endOf(d)<x(i)},a.$g=function(i,d,l){return M.u(i)?this[d]:this.set(l,i)},a.unix=function(){return Math.floor(this.valueOf()/1e3)},a.valueOf=function(){return this.$d.getTime()},a.startOf=function(i,d){var l=this,v=!!M.u(d)||d,N=M.p(i),f=function(G,W){var Q=M.w(l.$u?Date.UTC(l.$y,W,G):new Date(l.$y,W,G),l);return v?Q:Q.endOf(C)},j=function(G,W){return M.w(l.toDate()[G].apply(l.toDate("s"),(v?[0,0,0,0]:[23,59,59,999]).slice(W)),l)},D=this.$W,h=this.$M,L=this.$D,J="set"+(this.$u?"UTC":"");switch(N){case P:return v?f(1,0):f(31,11);case S:return v?f(1,h):f(0,h+1);case m:var U=this.$locale().weekStart||0,K=(D<U?D+7:D)-U;return f(v?L-K:L+(6-K),h);case C:case T:return j(J+"Hours",0);case $:return j(J+"Minutes",1);case k:return j(J+"Seconds",2);case g:return j(J+"Milliseconds",3);default:return this.clone()}},a.endOf=function(i){return this.startOf(i,!1)},a.$set=function(i,d){var l,v=M.p(i),N="set"+(this.$u?"UTC":""),f=(l={},l[C]=N+"Date",l[T]=N+"Date",l[S]=N+"Month",l[P]=N+"FullYear",l[$]=N+"Hours",l[k]=N+"Minutes",l[g]=N+"Seconds",l[u]=N+"Milliseconds",l)[v],j=v===C?this.$D+(d-this.$W):d;if(v===S||v===P){var D=this.clone().set(T,1);D.$d[f](j),D.init(),this.$d=D.set(T,Math.min(this.$D,D.daysInMonth())).$d}else f&&this.$d[f](j);return this.init(),this},a.set=function(i,d){return this.clone().$set(i,d)},a.get=function(i){return this[M.p(i)]()},a.add=function(i,d){var l,v=this;i=Number(i);var N=M.p(d),f=function(h){var L=x(v);return M.w(L.date(L.date()+Math.round(h*i)),v)};if(N===S)return this.set(S,this.$M+i);if(N===P)return this.set(P,this.$y+i);if(N===C)return f(1);if(N===m)return f(7);var j=(l={},l[k]=s,l[$]=o,l[g]=n,l)[N]||1,D=this.$d.getTime()+i*j;return M.w(D,this)},a.subtract=function(i,d){return this.add(-1*i,d)},a.format=function(i){var d=this,l=this.$locale();if(!this.isValid())return l.invalidDate||R;var v=i||"YYYY-MM-DDTHH:mm:ssZ",N=M.z(this),f=this.$H,j=this.$m,D=this.$M,h=l.weekdays,L=l.months,J=l.meridiem,U=function(W,Q,re,oe){return W&&(W[Q]||W(d,v))||re[Q].slice(0,oe)},K=function(W){return M.s(f%12||12,W,"0")},G=J||function(W,Q,re){var oe=W<12?"AM":"PM";return re?oe.toLowerCase():oe};return v.replace(q,(function(W,Q){return Q||(function(re){switch(re){case"YY":return String(d.$y).slice(-2);case"YYYY":return M.s(d.$y,4,"0");case"M":return D+1;case"MM":return M.s(D+1,2,"0");case"MMM":return U(l.monthsShort,D,L,3);case"MMMM":return U(L,D);case"D":return d.$D;case"DD":return M.s(d.$D,2,"0");case"d":return String(d.$W);case"dd":return U(l.weekdaysMin,d.$W,h,2);case"ddd":return U(l.weekdaysShort,d.$W,h,3);case"dddd":return h[d.$W];case"H":return String(f);case"HH":return M.s(f,2,"0");case"h":return K(1);case"hh":return K(2);case"a":return G(f,j,!0);case"A":return G(f,j,!1);case"m":return String(j);case"mm":return M.s(j,2,"0");case"s":return String(d.$s);case"ss":return M.s(d.$s,2,"0");case"SSS":return M.s(d.$ms,3,"0");case"Z":return N}return null})(W)||N.replace(":","")}))},a.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},a.diff=function(i,d,l){var v,N=this,f=M.p(d),j=x(i),D=(j.utcOffset()-this.utcOffset())*s,h=this-j,L=function(){return M.m(N,j)};switch(f){case P:v=L()/12;break;case S:v=L();break;case H:v=L()/3;break;case m:v=(h-D)/6048e5;break;case C:v=(h-D)/864e5;break;case $:v=h/o;break;case k:v=h/s;break;case g:v=h/n;break;default:v=h}return l?v:M.a(v)},a.daysInMonth=function(){return this.endOf(S).$D},a.$locale=function(){return y[this.$L]},a.locale=function(i,d){if(!i)return this.$L;var l=this.clone(),v=E(i,d,!0);return v&&(l.$L=v),l},a.clone=function(){return M.w(this.$d,this)},a.toDate=function(){return new Date(this.valueOf())},a.toJSON=function(){return this.isValid()?this.toISOString():null},a.toISOString=function(){return this.$d.toISOString()},a.toString=function(){return this.$d.toUTCString()},b})(),Z=Y.prototype;return x.prototype=Z,[["$ms",u],["$s",g],["$m",k],["$H",$],["$W",C],["$M",S],["$y",P],["$D",T]].forEach((function(b){Z[b[1]]=function(a){return this.$g(a,b[0],b[1])}})),x.extend=function(b,a){return b.$i||(b(a,Y,x),b.$i=!0),x},x.locale=E,x.isDayjs=I,x.unix=function(b){return x(1e3*b)},x.en=y[O],x.Ls=y,x.p={},x}))})(ue)),ue.exports}var Ft=Ut();const Me=Yt(Ft);function Ze(){const[e,r]=c.useState(!1),[n,s]=c.useState(!1),o=c.useRef({title:""}),u={confirm:S=>{o.current=S,s(!1),r(!0)}},g=async()=>{var S,H;s(!0);try{await((H=(S=o.current).onOk)==null?void 0:H.call(S)),r(!1)}finally{s(!1)}},k=()=>{var S,H;(H=(S=o.current).onCancel)==null||H.call(S),r(!1)},$=o.current,C=$.okType==="danger",m=e?nt.createPortal(t.jsxs("div",{className:"fixed inset-0 z-[9998] flex items-center justify-center",children:[t.jsx("div",{className:"absolute inset-0 bg-black/40",onClick:k}),t.jsxs("div",{className:"relative bg-white rounded-2xl shadow-xl w-full max-w-md mx-4 p-6",children:[t.jsx("div",{className:"text-base font-semibold text-gray-800 mb-2",children:$.title}),$.content&&t.jsx("div",{className:"text-sm text-gray-600 mt-3",children:$.content}),t.jsxs("div",{className:"flex justify-end gap-2 mt-5",children:[t.jsx("button",{className:"px-4 py-1.5 rounded-lg border border-gray-200 text-sm text-gray-600 hover:bg-gray-50 transition-colors cursor-pointer",onClick:k,children:$.cancelText??"取消"}),t.jsx("button",{disabled:n,className:`px-4 py-1.5 rounded-lg text-white text-sm font-medium transition-colors disabled:opacity-50 cursor-pointer ${C?"bg-red-500 hover:bg-red-600":"bg-blue-500 hover:bg-blue-600"}`,onClick:g,children:n?"处理中…":$.okText??"确定"})]})]})]}),document.body):null;return[u,m]}const Bt=()=>{const{navigate:e}=Ce(),{basePath:r,service:n}=Oe(),[s,o]=Ze(),[u,g]=c.useState(""),[k,$]=c.useState(""),[C,m]=c.useState(!1),[S,H]=c.useState([]),[P,T]=c.useState({current:1,size:15,total:0}),R=p=>{const A=p.trim();if(!A)return"";try{return new URL(A.startsWith("http")?A:`https://${A}`).origin}catch{return A}},z=async(p=P.current,A=P.size,O=u,y=k)=>{m(!0);try{const w={page:p,size:A};O&&(w.pathname=O);const I=R(y);I&&(w.host=I);const E=await n.getList(w);H(E.items),T(x=>({...x,current:p,size:A,total:E.total??x.total}))}catch(w){F.error(w.message||"获取数据失败")}finally{m(!1)}};c.useEffect(()=>{z(1)},[]);const q=p=>{s.confirm({title:"确认删除",content:`确认删除 /${p.pathname}?`,okText:"删除",okType:"danger",cancelText:"取消",onOk:async()=>{await n.delete(p.id),F.success("删除成功"),z(1)}})},_=Math.ceil(P.total/P.size)||1;return t.jsxs("div",{className:"bg-white rounded-xl shadow-sm border border-gray-100 p-5",children:[o,t.jsxs("form",{className:"flex items-center gap-2 mb-5",onSubmit:p=>{p.preventDefault(),z(1)},children:[t.jsxs("div",{className:"relative w-52",children:[t.jsx(ye,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-gray-400"}),t.jsx("input",{className:"w-full pl-9 pr-3 py-1.5 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/30 focus:border-blue-400 transition",placeholder:"搜索 Pathname",value:u,onChange:p=>g(p.target.value)})]}),t.jsxs("div",{className:"relative w-52",children:[t.jsx(ye,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-gray-400"}),t.jsx("input",{className:"w-full pl-9 pr-3 py-1.5 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/30 focus:border-blue-400 transition",placeholder:"搜索 Website URL",value:k,onChange:p=>$(p.target.value)})]}),t.jsxs("button",{type:"submit",className:"flex items-center gap-1.5 px-3 py-1.5 bg-blue-500 hover:bg-blue-600 text-white text-sm rounded-lg transition cursor-pointer",children:[t.jsx(ye,{className:"w-3.5 h-3.5"}),"搜索"]}),t.jsxs("button",{type:"button",className:"flex items-center gap-1.5 px-3 py-1.5 border border-gray-200 hover:bg-gray-50 text-gray-600 text-sm rounded-lg transition cursor-pointer",onClick:()=>{g(""),$(""),z(1,P.size,"","")},children:[t.jsx(Rt,{className:"w-3.5 h-3.5"}),"重置"]}),t.jsx("div",{className:"flex-1"}),t.jsxs("button",{type:"button",className:"flex items-center gap-1.5 px-3 py-1.5 bg-blue-500 hover:bg-blue-600 text-white text-sm rounded-lg transition cursor-pointer",onClick:()=>e(`${r}/create`),children:[t.jsx(_t,{className:"w-3.5 h-3.5"}),"新增"]})]}),t.jsx("div",{className:"relative",children:t.jsxs("table",{className:"w-full text-sm",children:[t.jsx("thead",{children:t.jsxs("tr",{className:"border-b border-gray-100",children:[t.jsx("th",{className:"text-left py-2.5 px-3 font-medium text-gray-400 text-xs uppercase tracking-wide w-44",children:"Pathname"}),t.jsx("th",{className:"text-left py-2.5 px-3 font-medium text-gray-400 text-xs uppercase tracking-wide w-44",children:"Website URL"}),t.jsx("th",{className:"text-left py-2.5 px-3 font-medium text-gray-400 text-xs uppercase tracking-wide",children:"HTML 摘要"}),t.jsx("th",{className:"text-left py-2.5 px-3 font-medium text-gray-400 text-xs uppercase tracking-wide w-44",children:"创建时间"}),t.jsx("th",{className:"text-left py-2.5 px-3 font-medium text-gray-400 text-xs uppercase tracking-wide w-56",children:"操作"})]})}),t.jsx("tbody",{children:C?t.jsx("tr",{children:t.jsx("td",{colSpan:5,className:"py-16 text-center",children:t.jsxs("div",{className:"flex flex-col items-center gap-2 text-gray-400",children:[t.jsx(Dt,{className:"w-6 h-6 text-blue-400 animate-spin"}),t.jsx("span",{className:"text-sm",children:"加载中…"})]})})}):S.length===0?t.jsx("tr",{children:t.jsx("td",{colSpan:5,className:"py-16 text-center",children:t.jsxs("div",{className:"flex flex-col items-center gap-2 text-gray-300",children:[t.jsx(St,{className:"w-10 h-10"}),t.jsx("span",{className:"text-sm",children:"暂无数据"})]})})}):S.map(p=>{const A=(p.content||"").replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim().slice(0,80);return t.jsxs("tr",{className:"border-b border-gray-50 hover:bg-gray-50/60 transition-colors",children:[t.jsx("td",{className:"py-3 px-3",children:t.jsxs("span",{className:"font-mono text-xs text-gray-700",children:["/",p.pathname]})}),t.jsx("td",{className:"py-3 px-3",children:p.host?t.jsxs("a",{href:p.host,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 max-w-[160px] text-xs text-blue-600 underline underline-offset-2 hover:text-blue-800 transition-colors",title:p.host,children:[t.jsx("span",{className:"truncate",children:p.host.replace(/^https?:\/\//,"")}),t.jsx(jt,{className:"w-3 h-3 shrink-0"})]}):t.jsx("span",{className:"text-xs text-gray-300",children:"—"})}),t.jsx("td",{className:"py-3 px-3",children:A?t.jsx("span",{className:"text-sm text-gray-500 truncate block max-w-sm",title:A,children:A}):t.jsx("span",{className:"text-xs text-gray-300",children:"暂无内容"})}),t.jsx("td",{className:"py-3 px-3 text-xs text-gray-400",children:p.createdAt?Me(p.createdAt).format("YYYY/MM/DD HH:mm"):"—"}),t.jsx("td",{className:"py-3 px-3",children:t.jsxs("div",{className:"flex items-center gap-1.5",children:[p.host&&t.jsx("button",{className:"px-2.5 py-1 text-xs border border-gray-200 rounded-md hover:bg-gray-50 text-gray-600 transition cursor-pointer",onClick:()=>window.open(`${p.host.replace(/\/$/,"")}/${p.pathname}`,"_blank"),children:"跳转"}),t.jsx("button",{className:"px-2.5 py-1 text-xs border border-gray-200 rounded-md hover:bg-gray-50 text-gray-600 transition cursor-pointer",onClick:()=>e(`${r}/${p.id}/detail`,{state:{record:p}}),children:"详情"}),t.jsx("button",{className:"px-2.5 py-1 text-xs bg-blue-500 hover:bg-blue-600 text-white rounded-md transition cursor-pointer",onClick:()=>e(`${r}/${p.id}/edit`,{state:{record:p}}),children:"编辑"}),t.jsx("button",{className:"px-2.5 py-1 text-xs bg-red-500 hover:bg-red-600 text-white rounded-md transition cursor-pointer",onClick:()=>q(p),children:"删除"})]})})]},p.id)})})]})}),P.total>0&&t.jsxs("div",{className:"flex items-center justify-between pt-4 mt-2 border-t border-gray-100",children:[t.jsxs("span",{className:"text-xs text-gray-400",children:["共 ",P.total," 条"]}),t.jsxs("div",{className:"flex items-center gap-1",children:[t.jsx("button",{className:"px-2.5 py-1 text-xs border border-gray-200 rounded-md hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed text-gray-600 transition cursor-pointer",disabled:P.current<=1,onClick:()=>z(P.current-1),children:"上一页"}),t.jsxs("span",{className:"px-3 py-1 text-xs text-gray-500",children:[P.current," / ",_]}),t.jsx("button",{className:"px-2.5 py-1 text-xs border border-gray-200 rounded-md hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed text-gray-600 transition cursor-pointer",disabled:P.current>=_,onClick:()=>z(P.current+1),children:"下一页"}),t.jsx("select",{className:"ml-2 text-xs border border-gray-200 rounded-md px-1.5 py-1 text-gray-600 focus:outline-none focus:ring-1 focus:ring-blue-400 cursor-pointer",value:P.size,onChange:p=>z(1,Number(p.target.value)),children:[10,15,20,50].map(p=>t.jsxs("option",{value:p,children:[p," 条/页"]},p))})]})]})]})};async function Ae(e){const r=new AbortController,n=setTimeout(()=>r.abort(),1e4);try{const s=await fetch("https://validator.w3.org/nu/?out=json",{method:"POST",headers:{"Content-Type":"text/html; charset=utf-8","User-Agent":"AiSee-Manage/1.0"},body:e,signal:r.signal});if(!s.ok)throw new Error(`W3C validator responded with ${s.status}`);const g=((await s.json()).messages||[]).filter(k=>k.type==="error");return{isValid:g.length===0,errors:g}}catch(s){return console.error("W3C 校验请求失败:",s),{isValid:!0,errors:[],networkError:!0}}finally{clearTimeout(n)}}function Te(e,r){(r==null||r>e.length)&&(r=e.length);for(var n=0,s=Array(r);n<r;n++)s[n]=e[n];return s}function Zt(e){if(Array.isArray(e))return e}function Jt(e,r,n){return(r=rr(r))in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function Kt(e,r){var n=e==null?null:typeof Symbol<"u"&&e[Symbol.iterator]||e["@@iterator"];if(n!=null){var s,o,u,g,k=[],$=!0,C=!1;try{if(u=(n=n.call(e)).next,r!==0)for(;!($=(s=u.call(n)).done)&&(k.push(s.value),k.length!==r);$=!0);}catch(m){C=!0,o=m}finally{try{if(!$&&n.return!=null&&(g=n.return(),Object(g)!==g))return}finally{if(C)throw o}}return k}}function Gt(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
122
+ In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function _e(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);r&&(s=s.filter(function(o){return Object.getOwnPropertyDescriptor(e,o).enumerable})),n.push.apply(n,s)}return n}function ze(e){for(var r=1;r<arguments.length;r++){var n=arguments[r]!=null?arguments[r]:{};r%2?_e(Object(n),!0).forEach(function(s){Jt(e,s,n[s])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):_e(Object(n)).forEach(function(s){Object.defineProperty(e,s,Object.getOwnPropertyDescriptor(n,s))})}return e}function Qt(e,r){if(e==null)return{};var n,s,o=Xt(e,r);if(Object.getOwnPropertySymbols){var u=Object.getOwnPropertySymbols(e);for(s=0;s<u.length;s++)n=u[s],r.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function Xt(e,r){if(e==null)return{};var n={};for(var s in e)if({}.hasOwnProperty.call(e,s)){if(r.indexOf(s)!==-1)continue;n[s]=e[s]}return n}function er(e,r){return Zt(e)||Kt(e,r)||nr(e,r)||Gt()}function tr(e,r){if(typeof e!="object"||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var s=n.call(e,r);if(typeof s!="object")return s;throw new TypeError("@@toPrimitive must return a primitive value.")}return(r==="string"?String:Number)(e)}function rr(e){var r=tr(e,"string");return typeof r=="symbol"?r:r+""}function nr(e,r){if(e){if(typeof e=="string")return Te(e,r);var n={}.toString.call(e).slice(8,-1);return n==="Object"&&e.constructor&&(n=e.constructor.name),n==="Map"||n==="Set"?Array.from(e):n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Te(e,r):void 0}}function sr(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function Re(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);r&&(s=s.filter(function(o){return Object.getOwnPropertyDescriptor(e,o).enumerable})),n.push.apply(n,s)}return n}function He(e){for(var r=1;r<arguments.length;r++){var n=arguments[r]!=null?arguments[r]:{};r%2?Re(Object(n),!0).forEach(function(s){sr(e,s,n[s])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Re(Object(n)).forEach(function(s){Object.defineProperty(e,s,Object.getOwnPropertyDescriptor(n,s))})}return e}function ar(){for(var e=arguments.length,r=new Array(e),n=0;n<e;n++)r[n]=arguments[n];return function(s){return r.reduceRight(function(o,u){return u(o)},s)}}function ne(e){return function r(){for(var n=this,s=arguments.length,o=new Array(s),u=0;u<s;u++)o[u]=arguments[u];return o.length>=e.length?e.apply(this,o):function(){for(var g=arguments.length,k=new Array(g),$=0;$<g;$++)k[$]=arguments[$];return r.apply(n,[].concat(o,k))}}}function de(e){return{}.toString.call(e).includes("Object")}function ir(e){return!Object.keys(e).length}function ae(e){return typeof e=="function"}function or(e,r){return Object.prototype.hasOwnProperty.call(e,r)}function cr(e,r){return de(r)||X("changeType"),Object.keys(r).some(function(n){return!or(e,n)})&&X("changeField"),r}function lr(e){ae(e)||X("selectorType")}function ur(e){ae(e)||de(e)||X("handlerType"),de(e)&&Object.values(e).some(function(r){return!ae(r)})&&X("handlersType")}function dr(e){e||X("initialIsRequired"),de(e)||X("initialType"),ir(e)&&X("initialContent")}function hr(e,r){throw new Error(e[r]||e.default)}var fr={initialIsRequired:"initial state is required",initialType:"initial state should be an object",initialContent:"initial state shouldn't be an empty object",handlerType:"handler should be an object or a function",handlersType:"all handlers should be a functions",selectorType:"selector should be a function",changeType:"provided value of changes should be an object",changeField:'it seams you want to change a field in the state which is not specified in the "initial" state',default:"an unknown error accured in `state-local` package"},X=ne(hr)(fr),ce={changes:cr,selector:lr,handler:ur,initial:dr};function mr(e){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};ce.initial(e),ce.handler(r);var n={current:e},s=ne(gr)(n,r),o=ne(xr)(n),u=ne(ce.changes)(e),g=ne(pr)(n);function k(){var C=arguments.length>0&&arguments[0]!==void 0?arguments[0]:function(m){return m};return ce.selector(C),C(n.current)}function $(C){ar(s,o,u,g)(C)}return[k,$]}function pr(e,r){return ae(r)?r(e.current):r}function xr(e,r){return e.current=He(He({},e.current),r),r}function gr(e,r,n){return ae(r)?r(e.current):Object.keys(n).forEach(function(s){var o;return(o=r[s])===null||o===void 0?void 0:o.call(r,e.current[s])}),n}var yr={create:mr},br={paths:{vs:"https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs"}};function vr(e){return function r(){for(var n=this,s=arguments.length,o=new Array(s),u=0;u<s;u++)o[u]=arguments[u];return o.length>=e.length?e.apply(this,o):function(){for(var g=arguments.length,k=new Array(g),$=0;$<g;$++)k[$]=arguments[$];return r.apply(n,[].concat(o,k))}}}function wr(e){return{}.toString.call(e).includes("Object")}function jr(e){return e||Ie("configIsRequired"),wr(e)||Ie("configType"),e.urls?(Nr(),{paths:{vs:e.urls.monacoBase}}):e}function Nr(){console.warn(Je.deprecation)}function kr(e,r){throw new Error(e[r]||e.default)}var Je={configIsRequired:"the configuration object is required",configType:"the configuration object should be an object",default:"an unknown error accured in `@monaco-editor/loader` package",deprecation:`Deprecation warning!
123
+ You are using deprecated way of configuration.
124
+
125
+ Instead of using
126
+ monaco.config({ urls: { monacoBase: '...' } })
127
+ use
128
+ monaco.config({ paths: { vs: '...' } })
129
+
130
+ For more please check the link https://github.com/suren-atoyan/monaco-loader#config
131
+ `},Ie=vr(kr)(Je),$r={config:jr},Mr=function(){for(var r=arguments.length,n=new Array(r),s=0;s<r;s++)n[s]=arguments[s];return function(o){return n.reduceRight(function(u,g){return g(u)},o)}};function Ke(e,r){return Object.keys(r).forEach(function(n){r[n]instanceof Object&&e[n]&&Object.assign(r[n],Ke(e[n],r[n]))}),ze(ze({},e),r)}var Sr={type:"cancelation",msg:"operation is manually canceled"};function be(e){var r=!1,n=new Promise(function(s,o){e.then(function(u){return r?o(Sr):s(u)}),e.catch(o)});return n.cancel=function(){return r=!0},n}var Cr=["monaco"],Or=yr.create({config:br,isInitialized:!1,resolve:null,reject:null,monaco:null}),Ge=er(Or,2),ie=Ge[0],me=Ge[1];function Pr(e){var r=$r.config(e),n=r.monaco,s=Qt(r,Cr);me(function(o){return{config:Ke(o.config,s),monaco:n}})}function Dr(){var e=ie(function(r){var n=r.monaco,s=r.isInitialized,o=r.resolve;return{monaco:n,isInitialized:s,resolve:o}});if(!e.isInitialized){if(me({isInitialized:!0}),e.monaco)return e.resolve(e.monaco),be(ve);if(window.monaco&&window.monaco.editor)return Qe(window.monaco),e.resolve(window.monaco),be(ve);Mr(Er,Ar)(Tr)}return be(ve)}function Er(e){return document.body.appendChild(e)}function Lr(e){var r=document.createElement("script");return e&&(r.src=e),r}function Ar(e){var r=ie(function(s){var o=s.config,u=s.reject;return{config:o,reject:u}}),n=Lr("".concat(r.config.paths.vs,"/loader.js"));return n.onload=function(){return e()},n.onerror=r.reject,n}function Tr(){var e=ie(function(n){var s=n.config,o=n.resolve,u=n.reject;return{config:s,resolve:o,reject:u}}),r=window.require;r.config(e.config),r(["vs/editor/editor.main"],function(n){var s=n.m||n;Qe(s),e.resolve(s)},function(n){e.reject(n)})}function Qe(e){ie().monaco||me({monaco:e})}function _r(){return ie(function(e){var r=e.monaco;return r})}var ve=new Promise(function(e,r){return me({resolve:e,reject:r})}),Xe={config:Pr,init:Dr,__getMonacoInstance:_r},zr={wrapper:{display:"flex",position:"relative",textAlign:"initial"},fullWidth:{width:"100%"},hide:{display:"none"}},we=zr,Rr={container:{display:"flex",height:"100%",width:"100%",justifyContent:"center",alignItems:"center"}},Hr=Rr;function Ir({children:e}){return c.createElement("div",{style:Hr.container},e)}var Wr=Ir,Vr=Wr;function Yr({width:e,height:r,isEditorReady:n,loading:s,_ref:o,className:u,wrapperProps:g}){return c.createElement("section",{style:{...we.wrapper,width:e,height:r},...g},!n&&c.createElement(Vr,null,s),c.createElement("div",{ref:o,style:{...we.fullWidth,...!n&&we.hide},className:u}))}var qr=Yr,et=c.memo(qr);function Ur(e){c.useEffect(e,[])}var tt=Ur;function Fr(e,r,n=!0){let s=c.useRef(!0);c.useEffect(s.current||!n?()=>{s.current=!1}:e,r)}var B=Fr;function se(){}function te(e,r,n,s){return Br(e,s)||Zr(e,r,n,s)}function Br(e,r){return e.editor.getModel(rt(e,r))}function Zr(e,r,n,s){return e.editor.createModel(r,n,s?rt(e,s):void 0)}function rt(e,r){return e.Uri.parse(r)}function Jr({original:e,modified:r,language:n,originalLanguage:s,modifiedLanguage:o,originalModelPath:u,modifiedModelPath:g,keepCurrentOriginalModel:k=!1,keepCurrentModifiedModel:$=!1,theme:C="light",loading:m="Loading...",options:S={},height:H="100%",width:P="100%",className:T,wrapperProps:R={},beforeMount:z=se,onMount:q=se}){let[_,p]=c.useState(!1),[A,O]=c.useState(!0),y=c.useRef(null),w=c.useRef(null),I=c.useRef(null),E=c.useRef(q),x=c.useRef(z),M=c.useRef(!1);tt(()=>{let a=Xe.init();return a.then(i=>(w.current=i)&&O(!1)).catch(i=>(i==null?void 0:i.type)!=="cancelation"&&console.error("Monaco initialization: error:",i)),()=>y.current?b():a.cancel()}),B(()=>{if(y.current&&w.current){let a=y.current.getOriginalEditor(),i=te(w.current,e||"",s||n||"text",u||"");i!==a.getModel()&&a.setModel(i)}},[u],_),B(()=>{if(y.current&&w.current){let a=y.current.getModifiedEditor(),i=te(w.current,r||"",o||n||"text",g||"");i!==a.getModel()&&a.setModel(i)}},[g],_),B(()=>{let a=y.current.getModifiedEditor();a.getOption(w.current.editor.EditorOption.readOnly)?a.setValue(r||""):r!==a.getValue()&&(a.executeEdits("",[{range:a.getModel().getFullModelRange(),text:r||"",forceMoveMarkers:!0}]),a.pushUndoStop())},[r],_),B(()=>{var a,i;(i=(a=y.current)==null?void 0:a.getModel())==null||i.original.setValue(e||"")},[e],_),B(()=>{let{original:a,modified:i}=y.current.getModel();w.current.editor.setModelLanguage(a,s||n||"text"),w.current.editor.setModelLanguage(i,o||n||"text")},[n,s,o],_),B(()=>{var a;(a=w.current)==null||a.editor.setTheme(C)},[C],_),B(()=>{var a;(a=y.current)==null||a.updateOptions(S)},[S],_);let Y=c.useCallback(()=>{var d;if(!w.current)return;x.current(w.current);let a=te(w.current,e||"",s||n||"text",u||""),i=te(w.current,r||"",o||n||"text",g||"");(d=y.current)==null||d.setModel({original:a,modified:i})},[n,r,o,e,s,u,g]),Z=c.useCallback(()=>{var a;!M.current&&I.current&&(y.current=w.current.editor.createDiffEditor(I.current,{automaticLayout:!0,...S}),Y(),(a=w.current)==null||a.editor.setTheme(C),p(!0),M.current=!0)},[S,C,Y]);c.useEffect(()=>{_&&E.current(y.current,w.current)},[_]),c.useEffect(()=>{!A&&!_&&Z()},[A,_,Z]);function b(){var i,d,l,v;let a=(i=y.current)==null?void 0:i.getModel();k||((d=a==null?void 0:a.original)==null||d.dispose()),$||((l=a==null?void 0:a.modified)==null||l.dispose()),(v=y.current)==null||v.dispose()}return c.createElement(et,{width:P,height:H,isEditorReady:_,loading:m,_ref:I,className:T,wrapperProps:R})}var Kr=Jr;c.memo(Kr);function Gr(e){let r=c.useRef();return c.useEffect(()=>{r.current=e},[e]),r.current}var Qr=Gr,le=new Map;function Xr({defaultValue:e,defaultLanguage:r,defaultPath:n,value:s,language:o,path:u,theme:g="light",line:k,loading:$="Loading...",options:C={},overrideServices:m={},saveViewState:S=!0,keepCurrentModel:H=!1,width:P="100%",height:T="100%",className:R,wrapperProps:z={},beforeMount:q=se,onMount:_=se,onChange:p,onValidate:A=se}){let[O,y]=c.useState(!1),[w,I]=c.useState(!0),E=c.useRef(null),x=c.useRef(null),M=c.useRef(null),Y=c.useRef(_),Z=c.useRef(q),b=c.useRef(),a=c.useRef(s),i=Qr(u),d=c.useRef(!1),l=c.useRef(!1);tt(()=>{let f=Xe.init();return f.then(j=>(E.current=j)&&I(!1)).catch(j=>(j==null?void 0:j.type)!=="cancelation"&&console.error("Monaco initialization: error:",j)),()=>x.current?N():f.cancel()}),B(()=>{var j,D,h,L;let f=te(E.current,e||s||"",r||o||"",u||n||"");f!==((j=x.current)==null?void 0:j.getModel())&&(S&&le.set(i,(D=x.current)==null?void 0:D.saveViewState()),(h=x.current)==null||h.setModel(f),S&&((L=x.current)==null||L.restoreViewState(le.get(u))))},[u],O),B(()=>{var f;(f=x.current)==null||f.updateOptions(C)},[C],O),B(()=>{!x.current||s===void 0||(x.current.getOption(E.current.editor.EditorOption.readOnly)?x.current.setValue(s):s!==x.current.getValue()&&(l.current=!0,x.current.executeEdits("",[{range:x.current.getModel().getFullModelRange(),text:s,forceMoveMarkers:!0}]),x.current.pushUndoStop(),l.current=!1))},[s],O),B(()=>{var j,D;let f=(j=x.current)==null?void 0:j.getModel();f&&o&&((D=E.current)==null||D.editor.setModelLanguage(f,o))},[o],O),B(()=>{var f;k!==void 0&&((f=x.current)==null||f.revealLine(k))},[k],O),B(()=>{var f;(f=E.current)==null||f.editor.setTheme(g)},[g],O);let v=c.useCallback(()=>{var f;if(!(!M.current||!E.current)&&!d.current){Z.current(E.current);let j=u||n,D=te(E.current,s||e||"",r||o||"",j||"");x.current=(f=E.current)==null?void 0:f.editor.create(M.current,{model:D,automaticLayout:!0,...C},m),S&&x.current.restoreViewState(le.get(j)),E.current.editor.setTheme(g),k!==void 0&&x.current.revealLine(k),y(!0),d.current=!0}},[e,r,n,s,o,u,C,m,S,g,k]);c.useEffect(()=>{O&&Y.current(x.current,E.current)},[O]),c.useEffect(()=>{!w&&!O&&v()},[w,O,v]),a.current=s,c.useEffect(()=>{var f,j;O&&p&&((f=b.current)==null||f.dispose(),b.current=(j=x.current)==null?void 0:j.onDidChangeModelContent(D=>{l.current||p(x.current.getValue(),D)}))},[O,p]),c.useEffect(()=>{if(O){let f=E.current.editor.onDidChangeMarkers(j=>{var h;let D=(h=x.current.getModel())==null?void 0:h.uri;if(D&&j.find(L=>L.path===D.path)){let L=E.current.editor.getModelMarkers({resource:D});A==null||A(L)}});return()=>{f==null||f.dispose()}}return()=>{}},[O,A]);function N(){var f,j;(f=b.current)==null||f.dispose(),H?S&&le.set(u,x.current.saveViewState()):(j=x.current.getModel())==null||j.dispose(),x.current.dispose()}return c.createElement(et,{width:P,height:T,isEditorReady:O,loading:$,_ref:M,className:R,wrapperProps:z})}var en=Xr,tn=c.memo(en),rn=tn;function he({title:e,children:r,placement:n="top"}){const[s,o]=c.useState(!1);return e?t.jsxs("div",{className:"relative inline-flex",onMouseEnter:()=>o(!0),onMouseLeave:()=>o(!1),children:[r,s&&t.jsx("div",{className:`absolute left-1/2 -translate-x-1/2 z-50 px-2 py-1 bg-gray-800/90 text-white text-xs rounded-md whitespace-nowrap pointer-events-none ${n==="top"?"bottom-full mb-1.5":"top-full mt-1.5"}`,children:e})]}):t.jsx(t.Fragment,{children:r})}const je=[{key:"desktop",icon:t.jsx(Ue,{size:13}),label:"Desktop",width:null},{key:"tablet",icon:t.jsx(Be,{size:13}),label:"Tablet",width:768},{key:"mobile",icon:t.jsx(Fe,{size:13}),label:"Mobile",width:390}],nn=({id:e,record:r})=>{const{navigate:n,params:s,locationState:o}=Ce(),u=e??s.id,{basePath:g,service:k,previewBaseUrl:$,previewTailwind:C}=Oe(),m=!!u,[S,H]=Ze(),[P,T]=c.useState(!1),[R,z]=c.useState(r??(o==null?void 0:o.record)??null),[q,_]=c.useState(""),[p,A]=c.useState(""),[O,y]=c.useState(""),[w,I]=c.useState(""),[E,x]=c.useState("code"),[M,Y]=c.useState(!1),[Z,b]=c.useState("desktop"),[a,i]=c.useState(!1),[d,l]=c.useState(null),v=(h,L)=>{const J=$?`<base href="${$}">`:"",U=L?`<meta name="viewport" content="width=${L}, initial-scale=1">`:"",K=L?"<style>*,*::before,*::after{box-sizing:border-box}img,video,svg,canvas,audio{max-width:100%;height:auto}pre{white-space:pre-wrap;word-break:break-word;overflow-x:auto}table{display:block;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}</style>":"",G=C&&!h.includes("cdn.tailwindcss.com")?'<script src="https://cdn.tailwindcss.com"><\/script>':"",W=J+U+K+G;return W?h.includes("</head>")?h.replace("</head>",`${W}
132
+ </head>`):W+h:h},N=async()=>{if(!w.trim()){F.warning("请先输入 HTML 代码");return}i(!0),l(null);try{const h=await Ae(w);l(h),h.networkError?F.warning("W3C 校验服务不可用"):h.isValid&&F.success("W3C 校验通过")}finally{i(!1)}};c.useEffect(()=>{m&&(R?(_(R.pathname||""),A(R.host||""),I(R.content||"")):k.getById(u).then(h=>{z(h),_(h.pathname||""),A(h.host||""),I(h.content||"")}).catch(h=>{F.error(h.message||"获取数据失败"),n(g)}))},[u]);const f=()=>n(g),j=!q.trim(),D=async()=>{if(!q.trim()){y("请输入 pathname");return}if(!w.trim()){Y(!0),F.error("请输入 HTML 代码");return}T(!0);const h=await Ae(w);if(T(!1),h.networkError)F.warning("W3C 校验服务不可用,已跳过校验");else if(!h.isValid&&!await new Promise(J=>{S.confirm({title:"W3C 校验发现问题",content:t.jsxs("div",{className:"mt-1",children:[t.jsx("p",{className:"text-gray-600 mb-2",children:"检测到以下 W3C 标准问题,仍要保存吗?"}),t.jsxs("ul",{className:"space-y-1",children:[h.errors.slice(0,5).map((U,K)=>t.jsxs("li",{className:"flex items-start gap-1.5 text-red-500 text-sm",children:[t.jsx("span",{className:"shrink-0",children:"✕"}),t.jsxs("span",{children:[U.lastLine?`第 ${U.lastLine} 行:`:"",U.message]})]},K)),h.errors.length>5&&t.jsxs("li",{className:"text-gray-400 text-xs mt-1",children:["还有 ",h.errors.length-5," 个问题…"]})]})]}),okText:"仍然保存",cancelText:"返回修改",onOk:()=>J(!0),onCancel:()=>J(!1)})}))return;T(!0);try{const L={pathname:q.trim(),content:w,host:(p==null?void 0:p.trim())||void 0};m&&R?(await k.update(R.id,L),F.success("编辑成功")):(await k.create(L),F.success("添加成功")),n(g)}catch(L){F.error(L.message||"保存失败")}finally{T(!1)}};return t.jsxs(t.Fragment,{children:[H,t.jsxs("div",{className:"w-full bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden flex flex-col",style:{height:"calc(100vh - 90px)"},children:[t.jsxs("div",{className:"shrink-0 flex items-center justify-between px-6 py-4 border-b border-gray-100 bg-gray-50/60",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("button",{className:"flex items-center justify-center w-7 h-7 rounded-lg text-gray-400 hover:text-gray-700 hover:bg-gray-200 transition -ml-1 cursor-pointer",onClick:f,children:t.jsx(Ye,{size:15})}),t.jsxs("div",{children:[t.jsx("div",{className:"text-base font-semibold text-gray-800 leading-tight",children:m?"编辑 Article":"新增 Article"}),m&&R&&t.jsxs("div",{className:"text-xs text-gray-400 mt-0.5 font-mono",children:["/",R.pathname]})]})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("button",{className:"px-4 py-1.5 border border-gray-200 rounded-lg text-sm text-gray-600 hover:bg-gray-50 transition cursor-pointer",onClick:f,children:"取消"}),t.jsx("button",{disabled:j||P,className:"px-4 py-1.5 bg-blue-500 hover:bg-blue-600 text-white text-sm rounded-lg transition disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer",onClick:D,children:P?"保存中…":"保存"})]})]}),t.jsx("div",{className:"shrink-0 px-6 pt-5 pb-4 border-b border-gray-100",children:t.jsxs("div",{className:"flex gap-4",children:[t.jsxs("div",{className:"flex-1",children:[t.jsxs("label",{className:"block text-sm font-medium text-gray-700 mb-1.5",children:["Pathname",t.jsx("span",{className:"text-xs text-gray-400 font-normal ml-1.5",children:"前台网站路径"})]}),t.jsxs("div",{className:`flex items-center border rounded-lg transition focus-within:ring-2 focus-within:ring-blue-500/30 focus-within:border-blue-400 ${O?"border-red-400 ring-2 ring-red-500/20":"border-gray-200"}`,children:[t.jsx("span",{className:"pl-3 text-gray-400 select-none text-sm shrink-0",children:"/"}),t.jsx("input",{className:"flex-1 pr-3 py-1.5 text-sm bg-transparent focus:outline-none",placeholder:"例如 about-us",value:q,onChange:h=>{_(h.target.value),O&&y("")}})]}),O&&t.jsx("p",{className:"text-red-500 text-xs mt-1",children:O})]}),t.jsxs("div",{className:"flex-1",children:[t.jsxs("label",{className:"block text-sm font-medium text-gray-700 mb-1.5",children:["Website URL",t.jsx("span",{className:"text-xs text-gray-400 font-normal ml-1.5",children:"可跳转的网站地址"})]}),t.jsx("input",{className:"w-full px-3 py-1.5 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/30 focus:border-blue-400 transition",placeholder:"例如 https://aisee.live",value:p,onChange:h=>A(h.target.value)})]})]})}),t.jsx("div",{className:"shrink-0 border-b border-gray-100 bg-gray-50/40",children:t.jsxs("div",{className:"flex items-center justify-between px-6 py-2",children:[t.jsx("div",{className:"flex items-center gap-3",children:t.jsxs("div",{className:"flex items-center bg-gray-100/80 rounded-lg p-0.5 gap-0.5 border border-gray-200/60",children:[t.jsxs("button",{className:`flex items-center gap-1.5 px-3 py-1 rounded-md text-xs font-medium transition-all duration-150 select-none cursor-pointer ${E==="code"?"bg-white text-gray-800 shadow-sm ring-1 ring-gray-200/50":"text-gray-400 hover:text-gray-600 hover:bg-white/50"}`,onClick:()=>x("code"),children:[t.jsx(qe,{size:11})," Code"]}),t.jsxs("button",{className:`flex items-center gap-1.5 px-3 py-1 rounded-md text-xs font-medium transition-all duration-150 select-none ${E==="preview"?"bg-white text-gray-800 shadow-sm ring-1 ring-gray-200/50 cursor-pointer":w?"text-gray-400 hover:text-gray-600 hover:bg-white/50 cursor-pointer":"text-gray-300 cursor-not-allowed"}`,onClick:()=>x("preview"),disabled:!w,children:[t.jsx($e,{size:11})," 预览"]})]})}),E==="preview"&&w&&t.jsx("div",{className:"flex items-center bg-gray-100/80 rounded-lg p-0.5 gap-0.5 border border-gray-200/60",children:je.map(h=>t.jsx(he,{title:h.label,children:t.jsx("button",{className:`flex items-center justify-center w-7 h-6 rounded-md text-xs transition-all duration-150 select-none cursor-pointer ${Z===h.key?"bg-white text-gray-800 shadow-sm ring-1 ring-gray-200/50":"text-gray-400 hover:text-gray-600 hover:bg-white/50"}`,onClick:()=>b(h.key),children:h.icon})},h.key))}),E==="code"&&t.jsxs("div",{className:"flex items-center gap-2",children:[w&&t.jsxs("span",{className:"text-xs text-gray-400",children:[w.split(`
133
+ `).length," 行 ·"," ",w.length," 字符"]}),d&&!d.networkError&&(d.isValid?t.jsxs("span",{className:"flex items-center gap-1 px-2 py-0.5 rounded-full bg-green-50 border border-green-200 text-green-600 text-xs",children:[t.jsx(Ee,{size:11})," 校验通过"]}):t.jsx(he,{title:t.jsxs("ul",{className:"m-0 pl-0 list-none space-y-1 max-w-xs",children:[d.errors.slice(0,5).map((h,L)=>t.jsxs("li",{className:"text-xs",children:[h.lastLine?`第 ${h.lastLine} 行:`:"",h.message]},L)),d.errors.length>5&&t.jsxs("li",{className:"text-gray-400 text-xs",children:["还有"," ",d.errors.length-5," ","个问题…"]})]}),children:t.jsxs("span",{className:"flex items-center gap-1 px-2 py-0.5 rounded-full bg-red-50 border border-red-200 text-red-500 text-xs cursor-default",children:["✕"," ",d.errors.length," ","个问题"]})})),t.jsxs("button",{disabled:!w||a,className:"flex items-center gap-1.5 px-2.5 py-1 text-xs border border-gray-200 rounded-lg hover:bg-gray-50 text-gray-600 transition disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer",onClick:N,children:[t.jsx(Ee,{size:12}),a?"校验中…":"W3C 校验"]})]})]})}),t.jsxs("div",{className:"flex-1 min-h-0 relative",children:[t.jsx("div",{className:"absolute inset-0",style:{display:E==="code"?"block":"none",outline:M?"2px solid #ff4d4f":"none"},children:t.jsx(rn,{height:"100%",language:"html",theme:"vs-dark",value:w,onChange:h=>{I(h??""),M&&Y(!1),d&&l(null)},options:{fontSize:13,minimap:{enabled:!1},wordWrap:"on",scrollBeyondLastLine:!1,automaticLayout:!0,tabSize:2,formatOnPaste:!0,lineNumbers:"on",renderWhitespace:"none",smoothScrolling:!0,cursorBlinking:"smooth",padding:{top:12,bottom:12}}})}),E==="preview"&&(w?t.jsx("div",{className:"absolute inset-0 overflow-auto bg-gray-100/60 flex justify-center",children:Z!=="desktop"?t.jsx("div",{className:"flex flex-col items-center py-6 h-full",children:t.jsx("iframe",{srcDoc:v(w,je.find(h=>h.key===Z).width),sandbox:"allow-same-origin allow-scripts",title:"HTML 预览",style:{width:`${je.find(h=>h.key===Z).width}px`,height:"100%",minHeight:0,border:"1px solid #e5e7eb",borderRadius:10,background:"#fff",boxShadow:"0 4px 24px 0 rgba(0,0,0,0.10)",flexShrink:0}})}):t.jsx("iframe",{srcDoc:v(w),sandbox:"allow-same-origin allow-scripts",title:"HTML 预览",style:{width:"100%",height:"100%",border:"none",background:"#fff",display:"block"}})}):t.jsxs("div",{className:"flex flex-col items-center justify-center h-full text-gray-300 gap-3 select-none",children:[t.jsx($e,{size:36}),t.jsx("span",{className:"text-sm",children:"请先输入 HTML 代码"})]}))]})]})]})},Ne=[{key:"desktop",icon:t.jsx(Ue,{size:13}),label:"Desktop",width:null},{key:"tablet",icon:t.jsx(Be,{size:13}),label:"Tablet",width:768},{key:"mobile",icon:t.jsx(Fe,{size:13}),label:"Mobile",width:390}],sn=({id:e,record:r})=>{const{navigate:n,params:s,locationState:o}=Ce(),u=e??s.id,{basePath:g,service:k,previewBaseUrl:$,previewTailwind:C}=Oe(),[m,S]=c.useState(r??(o==null?void 0:o.record)??null),[H,P]=c.useState(!1),[T,R]=c.useState("preview"),[z,q]=c.useState("desktop");c.useEffect(()=>{!m&&u&&(P(!0),k.getById(u).then(S).catch(y=>{F.error(y.message||"获取数据失败"),n(g)}).finally(()=>P(!1)))},[u]);const _=()=>n(g),p=()=>n(`${g}/${u}/edit`,{state:{record:m}}),A=()=>{m!=null&&m.content&&(navigator.clipboard.writeText(m.content),F.success("已复制到剪贴板"))},O=(y,w)=>{const I=$?`<base href="${$}">`:"",E=w?`<meta name="viewport" content="width=${w}, initial-scale=1">`:"",x=w?"<style>*,*::before,*::after{box-sizing:border-box}img,video,svg,canvas,audio{max-width:100%;height:auto}pre{white-space:pre-wrap;word-break:break-word;overflow-x:auto}table{display:block;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}</style>":"",M=C&&!y.includes("cdn.tailwindcss.com")?'<script src="https://cdn.tailwindcss.com"><\/script>':"",Y=I+E+x+M;return Y?y.includes("</head>")?y.replace("</head>",`${Y}
134
+ </head>`):Y+y:y};return H?t.jsx("div",{className:"flex items-center justify-center h-64 text-gray-400 text-sm",children:"加载中…"}):t.jsxs("div",{className:"w-full bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden flex flex-col",style:{height:"calc(100vh - 90px)"},children:[t.jsxs("div",{className:"flex items-center justify-between px-5 py-3.5 border-b border-gray-100 bg-white shrink-0",children:[t.jsxs("div",{className:"flex items-center gap-3 min-w-0",children:[t.jsx("button",{className:"flex items-center justify-center w-7 h-7 rounded-lg text-gray-400 hover:text-gray-700 hover:bg-gray-100 transition -ml-1 shrink-0 cursor-pointer",onClick:_,children:t.jsx(Ye,{size:15})}),t.jsx("div",{className:"flex items-center justify-center w-8 h-8 rounded-lg shrink-0",style:{background:"linear-gradient(135deg, #60a5fa, #818cf8)"},children:t.jsx($t,{size:13,className:"text-white"})}),t.jsxs("div",{className:"min-w-0",children:[t.jsx("div",{className:"font-semibold text-gray-800 text-sm leading-tight",children:"Article 详情"}),t.jsx("div",{className:"flex items-center gap-1 mt-0.5",children:t.jsxs("span",{className:"inline-flex items-center gap-1 px-1.5 py-0 rounded bg-blue-50 border border-blue-100 text-blue-600 font-mono text-xs leading-5 truncate max-w-[300px]",children:[t.jsx(Ot,{size:9}),"/",m==null?void 0:m.pathname]})})]})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[T==="preview"&&t.jsx("div",{className:"flex items-center bg-gray-100/80 rounded-lg p-0.5 gap-0.5 border border-gray-200/60",children:Ne.map(y=>t.jsx(he,{title:y.label,children:t.jsx("button",{className:`flex items-center justify-center w-7 h-6 rounded-md text-xs transition-all duration-150 select-none cursor-pointer ${z===y.key?"bg-white text-gray-800 shadow-sm ring-1 ring-gray-200/50":"text-gray-400 hover:text-gray-600 hover:bg-white/50"}`,onClick:()=>q(y.key),children:y.icon})},y.key))}),t.jsx("div",{className:"flex items-center bg-gray-100/80 rounded-lg p-0.5 gap-0.5 border border-gray-200/60",children:["preview","code"].map(y=>t.jsx("button",{className:`flex items-center gap-1.5 px-3 py-1 rounded-md text-xs font-medium transition-all duration-150 select-none cursor-pointer ${T===y?"bg-white text-gray-800 shadow-sm ring-1 ring-gray-200/50":"text-gray-400 hover:text-gray-600 hover:bg-white/50"}`,onClick:()=>R(y),children:y==="preview"?t.jsxs(t.Fragment,{children:[t.jsx($e,{size:11})," 预览"]}):t.jsxs(t.Fragment,{children:[t.jsx(qe,{size:11})," Code"]})},y))}),T==="code"&&t.jsx(he,{title:"复制代码",children:t.jsx("button",{className:"flex items-center justify-center w-7 h-7 rounded-lg text-gray-400 hover:text-blue-500 hover:bg-blue-50 transition cursor-pointer",onClick:A,children:t.jsx(vt,{size:14})})})]})]}),t.jsx("div",{className:`flex-1 min-h-0 ${T==="preview"?"bg-gray-100/70":""}`,children:T==="preview"?t.jsx("div",{className:"w-full h-full flex justify-center overflow-auto py-0",children:z!=="desktop"?t.jsx("div",{className:"flex flex-col items-center py-6 h-full",children:t.jsx("iframe",{srcDoc:O((m==null?void 0:m.content)||"",Ne.find(y=>y.key===z).width),sandbox:"allow-same-origin allow-scripts",title:"HTML 预览",style:{width:`${Ne.find(y=>y.key===z).width}px`,height:"100%",minHeight:0,border:"1px solid #e5e7eb",borderRadius:10,background:"#fff",boxShadow:"0 4px 24px 0 rgba(0,0,0,0.10)",flexShrink:0}})}):t.jsx("iframe",{srcDoc:O((m==null?void 0:m.content)||""),sandbox:"allow-same-origin allow-scripts",title:"HTML 预览",style:{width:"100%",height:"100%",border:"none",background:"#fff",display:"block"}})}):t.jsxs("div",{className:"h-full flex flex-col",style:{background:"#1e1e2e"},children:[t.jsxs("div",{className:"shrink-0 flex items-center justify-between px-4 py-2 border-b",style:{borderColor:"#2d2d3e",background:"#252536"},children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsxs("div",{className:"flex gap-1.5",children:[t.jsx("span",{className:"w-3 h-3 rounded-full bg-red-400/80 inline-block"}),t.jsx("span",{className:"w-3 h-3 rounded-full bg-yellow-400/80 inline-block"}),t.jsx("span",{className:"w-3 h-3 rounded-full bg-green-400/80 inline-block"})]}),t.jsx("span",{className:"text-xs font-mono ml-2",style:{color:"#6c7086"},children:"index.html"})]}),t.jsx("span",{className:"text-xs font-mono",style:{color:"#6c7086"},children:m!=null&&m.content?`${m.content.split(`
135
+ `).length} 行 · ${m.content.length} 字符`:"空"})]}),t.jsx("div",{className:"flex-1 overflow-auto",children:t.jsx("pre",{className:"m-0 p-5 text-xs font-mono whitespace-pre-wrap break-all leading-relaxed",style:{color:"#cdd6f4"},children:(m==null?void 0:m.content)||t.jsx("span",{style:{color:"#585b70"},children:"// 暂无内容"})})})]})}),t.jsxs("div",{className:"shrink-0 flex items-center justify-between px-5 py-2.5 border-t border-gray-100 bg-gray-50/60",children:[t.jsxs("div",{className:"flex items-center gap-4 text-xs text-gray-400",children:[(m==null?void 0:m.createdAt)&&t.jsxs("span",{children:["创建于"," ",Me(m.createdAt).format("YYYY/MM/DD HH:mm")]}),(m==null?void 0:m.updatedAt)&&t.jsxs("span",{children:["更新于"," ",Me(m.updatedAt).format("YYYY/MM/DD HH:mm")]})]}),t.jsxs("button",{className:"flex items-center gap-1.5 px-3 py-1.5 text-xs border border-gray-200 rounded-lg hover:bg-gray-50 text-gray-600 transition cursor-pointer",onClick:p,children:[t.jsx(At,{size:12}),"编辑"]})]})]})};exports.createArticleService=fe.createArticleService;exports.defaultArticleService=fe.defaultArticleService;exports.renderArticleByPathname=fe.renderArticleByPathname;exports.ArticleDetail=sn;exports.ArticleEdit=nn;exports.ArticleList=Bt;exports.ArticlesProvider=lt;exports.ReactRouterAdapter=ut;
@@ -0,0 +1,10 @@
1
+ import './style.css';
2
+ export { ArticlesProvider } from './context';
3
+ export { ReactRouterAdapter } from './router/ReactRouterAdapter';
4
+ export { default as ArticleList } from './pages/ArticleList';
5
+ export { default as ArticleEdit } from './pages/ArticleEdit';
6
+ export { default as ArticleDetail } from './pages/ArticleDetail';
7
+ export type { Article, ArticleService, ArticlesConfig } from './types';
8
+ export { createArticleService, defaultArticleService } from './service';
9
+ export { renderArticleByPathname } from './renderArticle';
10
+ export type { RenderArticleOptions } from './renderArticle';