提交 d8150ad8 authored 作者: 王鹏飞's avatar 王鹏飞

feat: 新增APP配置,升级Vite并重命名Web端目录

上级 a9f6b8ac
...@@ -2,20 +2,20 @@ ...@@ -2,20 +2,20 @@
## Project Structure & Module Organization ## Project Structure & Module Organization
This pnpm monorepo contains two independent React 19 apps: `apps/admin` (JavaScript/JSX) and `apps/learning` (TypeScript). Each app owns its routes, API clients, state, assets, and tests; do not import from another app’s `src` directory. Within an app, place domain features in `src/modules/<domain>/`, reusable UI in `src/components/`, and cross-cutting hooks and utilities in `src/hooks/` and `src/utils/`. Shared code belongs in `packages/` only when both apps use it. Admin WangEditor features stay under `apps/admin/src/components/editor/wangeditor-customer/features/`. This pnpm monorepo contains two independent React 19 apps: `apps/admin` (JavaScript/JSX) and `apps/web` (TypeScript). Each app owns its routes, API clients, state, assets, and tests; do not import from another app’s `src` directory. Within an app, place domain features in `src/modules/<domain>/`, reusable UI in `src/components/`, and cross-cutting hooks and utilities in `src/hooks/` and `src/utils/`. Shared code belongs in `packages/` only when both apps use it. Admin WangEditor features stay under `apps/admin/src/components/editor/wangeditor-customer/features/`.
## Build, Test, and Development Commands ## Build, Test, and Development Commands
- `pnpm dev` starts both Vite apps; use `pnpm dev:admin` or `pnpm dev:learning` for one app. - `pnpm dev` starts both Vite apps; use `pnpm dev:admin` or `pnpm dev:web` for one app.
- `pnpm build` builds Learning and then Admin; `pnpm build:learning` and `pnpm build:admin` build separately. - `pnpm build` builds Web and then Admin; `pnpm build:web` and `pnpm build:admin` build separately.
- `pnpm test` runs both app test suites; `pnpm test:learning` and `pnpm test:admin` run one suite. - `pnpm test` runs both app test suites; `pnpm test:web` and `pnpm test:admin` run one suite.
- `pnpm lint:check` runs read-only Oxlint checks. `pnpm lint:learning` and `pnpm lint:admin` apply fixes, so inspect the diff afterward. - `pnpm lint:check` runs read-only Oxlint checks. `pnpm lint:web` and `pnpm lint:admin` apply fixes, so inspect the diff afterward.
- `pnpm typecheck:learning` runs the strict Learning TypeScript check. - `pnpm typecheck:web` runs the strict Web TypeScript check.
- Format an app with `pnpm --filter @ebook/learning format` or `pnpm --filter @ebook/admin format`. - Format an app with `pnpm --filter @ebook/web format` or `pnpm --filter @ebook/admin format`.
## Coding Style & Naming Conventions ## Coding Style & Naming Conventions
Use two-space indentation, single quotes, and no semicolons; Oxfmt is authoritative. Prefer functional React components. Name components `PascalCase`, hooks `useXxx`, and utilities `camelCase`. Keep Learning TypeScript-first, avoid `any`, put server state in React Query, URL state in nuqs, and shared transient state in Zustand. Follow the surrounding JavaScript/JSX style in Admin. Both apps use Ant Design 6; check existing components and tokens before adding custom UI. Use two-space indentation, single quotes, and no semicolons; Oxfmt is authoritative. Prefer functional React components. Name components `PascalCase`, hooks `useXxx`, and utilities `camelCase`. Keep Web TypeScript-first, avoid `any`, put server state in React Query, URL state in nuqs, and shared transient state in Zustand. Follow the surrounding JavaScript/JSX style in Admin. Both apps use Ant Design 6; check existing components and tokens before adding custom UI.
## Testing Guidelines ## Testing Guidelines
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
"dependencies": { "dependencies": {
"@ant-design/icons": "^6.3.2", "@ant-design/icons": "^6.3.2",
"@chuangkit/chuangkit-design": "^2.0.8", "@chuangkit/chuangkit-design": "^2.0.8",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@ezijing/ai-react": "^1.0.40", "@ezijing/ai-react": "^1.0.40",
"@fortaine/fetch-event-source": "^3.0.6", "@fortaine/fetch-event-source": "^3.0.6",
"@remixicon/react": "^4.9.0", "@remixicon/react": "^4.9.0",
...@@ -58,7 +61,7 @@ ...@@ -58,7 +61,7 @@
"oxfmt": "^0.64.0", "oxfmt": "^0.64.0",
"oxlint": "^1.79.0", "oxlint": "^1.79.0",
"typescript": "^7.0.2", "typescript": "^7.0.2",
"vite": "^8.2.2", "vite": "^8.3.4",
"vite-plugin-mkcert": "^2.1.0", "vite-plugin-mkcert": "^2.1.0",
"vitest": "^4.1.10" "vitest": "^4.1.10"
} }
......
import { Button, Upload, message } from 'antd' import { Button, Spin, Tooltip, Upload, message } from 'antd'
import { PlusOutlined } from '@ant-design/icons'
import { useState } from 'react' import { useState } from 'react'
import { uploadFile } from '@/utils/oss' import { uploadFile } from '@/utils/oss'
import './index.less' import './index.less'
export default function UploadImage({ value, onChange }) { export default function UploadImage({ value, onChange, compact }) {
const [uploading, setUploading] = useState(false) const [uploading, setUploading] = useState(false)
const uploadProps = { const uploadProps = {
...@@ -36,6 +37,22 @@ export default function UploadImage({ value, onChange }) { ...@@ -36,6 +37,22 @@ export default function UploadImage({ value, onChange }) {
}, },
} }
if (compact) {
let content = <PlusOutlined />
if (uploading) content = <Spin size='small' />
else if (value) content = <img src={value} alt='' />
return (
<Tooltip title='点击上传图标,jpg/png,不超过1M'>
<Upload {...uploadProps}>
<div className='upload-image__compact' data-filled={value ? 'true' : 'false'}>
{content}
</div>
</Upload>
</Tooltip>
)
}
return ( return (
<div className='upload-image'> <div className='upload-image'>
{value && <img src={value} width={88} height={88} style={{ borderRadius: 5 }} />} {value && <img src={value} width={88} height={88} style={{ borderRadius: 5 }} />}
......
...@@ -12,4 +12,42 @@ ...@@ -12,4 +12,42 @@
font-size: 12px; font-size: 12px;
} }
} }
&__compact {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
overflow: hidden;
color: rgb(0 0 0 / 45%);
background-color: #fafafa;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
transition: border-color 0.2s;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
&:hover {
border-color: #aa1941;
}
&[data-filled='true']:hover::after {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-size: 12px;
content: '替换';
background-color: rgb(0 0 0 / 45%);
}
}
} }
...@@ -115,8 +115,10 @@ export default function AdvertFormDrawer({ ...@@ -115,8 +115,10 @@ export default function AdvertFormDrawer({
> >
<RangePicker /> <RangePicker />
</Form.Item> </Form.Item>
<Form.Item name='url' label='广告链接地址' rules={[{ max: 500, message: '最大长度500' }]}> <Form.Item name='url' label='广告链接地址' rules={[
<Input autoComplete='off' placeholder='请输入广告链接地址' /> { max: 500, message: '最大长度500' },
]}>
<Input autoComplete='off' placeholder='请输入网页或应用链接(可留空)' />
</Form.Item> </Form.Item>
<Form.Item wrapperCol={{ offset: 11, span: 16 }}> <Form.Item wrapperCol={{ offset: 11, span: 16 }}>
<Space size={20}> <Space size={20}>
......
import axios from '@/utils/axios'
export async function getHomeConfig() {
const response = await axios.post('/api/admin/system/portal/getInfo', {})
return response.data
}
export async function saveHomeConfig(config) {
return axios.post('/api/admin/system/portal/save', config)
}
export async function getProductsConfig() {
const response = await axios.post('/api/admin/system/portal/getProducts', {})
return response.data
}
export function saveProductsConfig(config) {
return axios.post('/api/admin/system/portal/saveProducts', config)
}
export async function getAchievementsConfig() {
const response = await axios.post('/api/admin/system/portal/getAchievements', {})
return response.data
}
export function saveAchievementsConfig(config) {
return axios.post('/api/admin/system/portal/saveAchievements', config)
}
import { Form, Input, Modal, Select, Switch } from 'antd'
import UploadImage from '@/components/uploadImage'
export default function HomeConfigEditModal({
editing,
form,
onCancel,
onOk,
entryLabel = '入口',
}) {
const isModule = editing?.kind === 'module'
const action = editing?.index === null ? '新增' : '编辑'
const title = `${action}${isModule ? '模块' : entryLabel}`
const nameLabel = isModule ? '模块名称' : `${entryLabel}名称`
return (
<Modal
title={title}
open={!!editing}
onCancel={onCancel}
onOk={onOk}
okText='确定'
cancelText='取消'
width={560}
>
<Form form={form} layout='vertical'>
{!isModule && (
<Form.Item name='icon' label='图标' className='portal-preview__icon-upload'>
<UploadImage compact />
</Form.Item>
)}
<Form.Item
name='name'
label={nameLabel}
rules={[{ required: true, whitespace: true, message: '请填写名称' }]}
>
<Input maxLength={100} />
</Form.Item>
{isModule ? (
<>
<Form.Item
name='style'
label='展示样式'
rules={[{ required: true, message: '请选择展示样式' }]}
>
<Select
options={[
{ value: 'grid', label: '图标网格' },
{ value: 'cards', label: '图片卡片' },
]}
/>
</Form.Item>
<Form.Item name='more_name' label='标题右侧名称'>
<Input />
</Form.Item>
<Form.Item name='more_target' label='标题右侧链接'>
<Input />
</Form.Item>
</>
) : (
<>
<Form.Item name='description' label='介绍'>
<Input.TextArea rows={2} maxLength={300} />
</Form.Item>
<Form.Item name='target' label='跳转链接'>
<Input />
</Form.Item>
<Form.Item name='require_login' label='需要登录' valuePropName='checked'>
<Switch />
</Form.Item>
</>
)}
<Form.Item name='enabled' label='启用' valuePropName='checked'>
<Switch />
</Form.Item>
</Form>
</Modal>
)
}
import { Alert, Button, Drawer, Input, Space } from 'antd'
import { CodeOutlined } from '@ant-design/icons'
export default function HomeConfigJsonDrawer({ open, text, error, onClose, onApply, onChange }) {
return (
<Drawer
title={
<Space>
<CodeOutlined />
<span>编辑首页配置 JSON</span>
</Space>
}
open={open}
size={880}
className='portal-json'
onClose={onClose}
destroyOnHidden
footer={
<div className='portal-json__footer'>
<Space>
<Button onClick={onClose}>取消</Button>
<Button type='primary' onClick={onApply}>
应用到表单
</Button>
</Space>
</div>
}
>
<Input.TextArea
className='portal-json__input'
aria-label='首页配置 JSON'
value={text}
onChange={(event) => onChange(event.target.value)}
spellCheck={false}
/>
{error && <Alert type='error' title='JSON 格式有误' description={error} showIcon />}
</Drawer>
)
}
import {
DndContext,
closestCenter,
KeyboardSensor,
PointerSensor,
useSensor,
useSensors,
} from '@dnd-kit/core'
import {
arrayMove,
SortableContext,
useSortable,
sortableKeyboardCoordinates,
rectSortingStrategy,
verticalListSortingStrategy,
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
export function SortableList({ items, onChange, vertical = false, children }) {
const sensors = useSensors(
useSensor(PointerSensor, { activationConstraint: { distance: 6 } }),
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
)
return (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={({ active, over }) => {
if (!over || active.id === over.id) return
onChange(
arrayMove(
items,
items.findIndex((item) => item._key === active.id),
items.findIndex((item) => item._key === over.id),
),
)
}}
>
<SortableContext
items={items.map((item) => item._key)}
strategy={vertical ? verticalListSortingStrategy : rectSortingStrategy}
>
{children}
</SortableContext>
</DndContext>
)
}
export function SortableItem({ id, disabled, className, children }) {
const {
attributes,
listeners,
setNodeRef,
setActivatorNodeRef,
transform,
transition,
isDragging,
} = useSortable({ id, disabled })
return (
<div
ref={setNodeRef}
className={className}
style={{
transform: CSS.Transform.toString(transform),
transition,
position: 'relative',
zIndex: isDragging ? 10 : undefined,
opacity: isDragging ? 0.8 : undefined,
}}
>
{children({ ref: setActivatorNodeRef, ...attributes, ...listeners })}
</div>
)
}
import { lazy } from 'react'
import { Navigate, useRoutes } from 'react-router'
const AppConfigView = lazy(() => import('./views/AppConfigView'))
export default function PortalRoutes() {
return useRoutes([
{ index: true, Component: AppConfigView },
{ path: 'products', element: <Navigate replace to='/setting/portal?tab=products' /> },
{ path: 'achievements', element: <Navigate replace to='/setting/portal?tab=achievements' /> },
{ path: '*', element: <Navigate replace to='/setting/portal' /> },
])
}
import { useEffect, useState } from 'react'
import { nanoid } from 'nanoid'
import { Button, Form, Input, Modal, Popconfirm, Space, Spin, Switch, Tag, message } from 'antd'
import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons'
import { usePermission } from '@/hooks/usePermission'
import { getAchievementsConfig, saveAchievementsConfig } from '../api'
import { SortableList, SortableItem } from '../components/SortableList'
import './homeConfig.less'
export default function AchievementsConfigView() {
const [categories, setCategories] = useState([])
const [editing, setEditing] = useState(null)
const [form] = Form.useForm()
const [loading, setLoading] = useState(true)
const [loaded, setLoaded] = useState(false)
const [saving, setSaving] = useState(false)
const allowed = usePermission()
const canSave = allowed('/setting/portal/achievements/save')
const canEdit = canSave && loaded && !saving
const title = editing?.index === null ? '新增栏目' : '编辑栏目'
useEffect(() => {
getAchievementsConfig()
.then((config) => {
setCategories(
config.categories.map((category) => ({ enabled: 1, ...category, _key: nanoid() })),
)
setLoaded(true)
})
.catch(() => {})
.finally(() => setLoading(false))
}, [])
const edit = (index = null) => {
form.resetFields()
const category = index === null ? { name: '', type_tag: '', enabled: 1 } : categories[index]
form.setFieldsValue({ ...category, enabled: !!category.enabled })
setEditing({ index })
}
const apply = async () => {
const values = await form.validateFields()
values.enabled = Number(values.enabled)
setCategories((current) =>
editing.index === null
? [...current, { ...values, _key: nanoid() }]
: current.map((category, index) =>
index === editing.index ? { ...category, ...values } : category,
),
)
setEditing(null)
}
const save = async () => {
setSaving(true)
try {
await saveAchievementsConfig({
categories: categories.map(({ _key, ...category }) => category),
})
message.success('已保存')
} catch {
} finally {
setSaving(false)
}
}
return (
<div className='portal-preview'>
{loading ? (
<Spin />
) : (
<div className='portal-preview__canvas'>
<SortableList items={categories} onChange={setCategories} vertical>
{categories.map((category, index) => (
<SortableItem
key={category._key}
id={category._key}
disabled={!canEdit}
className='portal-preview__module'
>
{(handle) => (
<div className='portal-preview__heading' style={{ marginBottom: 0 }}>
<h3
className={canEdit ? 'portal-preview__module-title' : undefined}
{...handle}
>
{category.name}
</h3>
{!category.enabled && <Tag>已停用</Tag>}
<span className='portal-preview__more'>{category.type_tag}</span>
{canEdit && (
<Space className='portal-preview__module-actions' size={0}>
<Button
type='text'
icon={<EditOutlined />}
aria-label='编辑栏目'
onClick={() => edit(index)}
/>
<Popconfirm
title='删除此栏目?'
onConfirm={() =>
setCategories((current) => current.filter((_, i) => i !== index))
}
>
<Button type='text' icon={<DeleteOutlined />} aria-label='删除栏目' />
</Popconfirm>
</Space>
)}
</div>
)}
</SortableItem>
))}
</SortableList>
{canEdit && (
<Button block type='dashed' icon={<PlusOutlined />} onClick={() => edit()}>
新增栏目
</Button>
)}
</div>
)}
{canSave && (
<div className='portal-preview__save'>
<Button type='primary' disabled={!loaded} loading={saving} onClick={save}>
保存
</Button>
</div>
)}
<Modal
title={title}
open={!!editing}
onCancel={() => setEditing(null)}
onOk={apply}
okText='确定'
cancelText='取消'
>
<Form form={form} layout='vertical'>
<Form.Item
name='name'
label='栏目名称'
rules={[{ required: true, whitespace: true, message: '请填写栏目名称' }]}
>
<Input />
</Form.Item>
<Form.Item name='type_tag' label='CMS 分类标识'>
<Input />
</Form.Item>
<Form.Item name='enabled' label='启用' valuePropName='checked'>
<Switch />
</Form.Item>
</Form>
</Modal>
</div>
)
}
import { Tabs } from 'antd'
import { useSearchParams } from 'react-router'
import HomeConfigView from './HomeConfigView'
import ProductsConfigView from './ProductsConfigView'
import AchievementsConfigView from './AchievementsConfigView'
const items = [
{ key: 'home', label: '首页', children: <HomeConfigView /> },
{ key: 'products', label: '产品中心', children: <ProductsConfigView /> },
{ key: 'achievements', label: '成果中心', children: <AchievementsConfigView /> },
]
export default function AppConfigView() {
const [params, setParams] = useSearchParams()
const tab = params.get('tab') || 'home'
return (
<Tabs
activeKey={tab}
items={items}
onChange={(key) => setParams(key === 'home' ? {} : { tab: key })}
/>
)
}
import { useEffect, useState } from 'react'
import { nanoid } from 'nanoid'
import { Button, Form, Popconfirm, Space, Spin, Tag, message } from 'antd'
import {
AppstoreOutlined,
CodeOutlined,
DeleteOutlined,
EditOutlined,
PlusOutlined,
} from '@ant-design/icons'
import { usePermission } from '@/hooks/usePermission'
import { getHomeConfig, saveHomeConfig } from '../api'
import HomeConfigEditModal from '../components/HomeConfigEditModal'
import HomeConfigJsonDrawer from '../components/HomeConfigJsonDrawer'
import { SortableList, SortableItem } from '../components/SortableList'
import './homeConfig.less'
const bySort = (a, b) => a.sort - b.sort
const sortedModules = (modules) =>
modules
.slice()
.sort(bySort)
.map((module) => ({
...module,
_key: nanoid(),
items: module.items
.slice()
.sort(bySort)
.map((item) => ({ ...item, _key: nanoid() })),
}))
export default function HomeConfigView() {
const [modules, setModules] = useState([])
const [loading, setLoading] = useState(true)
const [loaded, setLoaded] = useState(false)
const [saving, setSaving] = useState(false)
const [editing, setEditing] = useState(null)
const [form] = Form.useForm()
const [jsonOpen, setJsonOpen] = useState(false)
const [jsonText, setJsonText] = useState('')
const [jsonError, setJsonError] = useState('')
const allowed = usePermission()
const canSave = allowed('/setting/portal/save')
const canEdit = canSave && loaded && !saving
const getConfig = () => ({
modules: modules.map(({ _key, ...module }, index) => ({
...module,
sort: (index + 1) * 10,
items: module.items.map(({ type: _type, _key, ...item }, itemIndex) => ({
...item,
sort: (itemIndex + 1) * 10,
})),
})),
})
useEffect(() => {
getHomeConfig()
.then((config) => {
setModules(sortedModules(config.modules))
setLoaded(true)
})
.catch(() => {})
.finally(() => setLoading(false))
}, [])
const save = async () => {
setSaving(true)
try {
await saveHomeConfig(getConfig())
message.success('APP首页配置已保存')
} catch {
// The shared request client displays API errors.
} finally {
setSaving(false)
}
}
const editModule = (index = null) => {
form.resetFields()
const module =
index === null
? { name: '', style: 'grid', enabled: 1, more_name: '', more_target: '' }
: modules[index]
form.setFieldsValue({ ...module, enabled: !!module.enabled })
setEditing({ kind: 'module', index })
}
const editEntry = (moduleIndex, index = null) => {
form.resetFields()
const item =
index === null
? { name: '', description: '', icon: '', target: '', enabled: 1, require_login: 1 }
: modules[moduleIndex].items[index]
form.setFieldsValue({ ...item, enabled: !!item.enabled, require_login: !!item.require_login })
setEditing({ kind: 'entry', moduleIndex, index })
}
const applyEdit = async () => {
let values
try {
values = await form.validateFields()
} catch {
return
}
values.enabled = Number(values.enabled)
if (editing.kind === 'entry') values.require_login = Number(values.require_login)
setModules((current) => {
const next = [...current]
if (editing.kind === 'module') {
if (editing.index === null) next.push({ ...values, _key: nanoid(), items: [] })
else next[editing.index] = { ...next[editing.index], ...values }
} else {
const module = next[editing.moduleIndex]
const items = [...module.items]
if (editing.index === null) items.push({ ...values, _key: nanoid() })
else items[editing.index] = { ...items[editing.index], ...values }
next[editing.moduleIndex] = { ...module, items }
}
return next
})
setEditing(null)
}
const removeModule = (index) => setModules((current) => current.filter((_, i) => i !== index))
const removeEntry = (moduleIndex, index) =>
setModules((current) =>
current.map((module, i) =>
i === moduleIndex
? { ...module, items: module.items.filter((_, j) => j !== index) }
: module,
),
)
const editJson = () => {
setJsonText(JSON.stringify(getConfig(), null, 2))
setJsonError('')
setJsonOpen(true)
}
const applyJson = () => {
try {
const config = JSON.parse(jsonText)
if (!Array.isArray(config?.modules)) throw new Error('配置需要包含 modules 数组')
setModules(sortedModules(config.modules))
setLoaded(true)
setJsonOpen(false)
} catch (error) {
setJsonError(error.message)
}
}
return (
<div className='classify portal-preview'>
{loading ? (
<Spin />
) : (
<>
<div className='portal-preview__canvas'>
<SortableList items={modules} onChange={setModules} vertical>
{modules.map((module, moduleIndex) => (
<SortableItem
key={module._key}
id={module._key}
disabled={!canEdit}
className={`portal-preview__module ${!module.enabled ? 'portal-preview__module--disabled' : ''}`}
>
{(moduleHandle) => (
<>
<div className='portal-preview__heading'>
<h3
className={canEdit ? 'portal-preview__module-title' : undefined}
{...moduleHandle}
aria-label={`${module.name},拖动排序`}
>
{module.name}
</h3>
{!module.enabled && <Tag>已停用</Tag>}
{module.more_name && (
<span className='portal-preview__more'>{module.more_name} ›</span>
)}
<Space className='portal-preview__module-actions' size={0}>
<Button
type='text'
icon={<EditOutlined />}
disabled={!canEdit}
onClick={() => editModule(moduleIndex)}
aria-label='编辑模块'
/>
<Popconfirm
title='删除此模块及其所有入口?'
onConfirm={() => removeModule(moduleIndex)}
disabled={!canEdit}
>
<Button
type='text'
icon={<DeleteOutlined />}
disabled={!canEdit}
aria-label='删除模块'
/>
</Popconfirm>
</Space>
</div>
<SortableList
items={module.items}
onChange={(items) =>
setModules((current) =>
current.map((value, index) =>
index === moduleIndex ? { ...value, items } : value,
),
)
}
>
<div
className={`portal-preview__entries portal-preview__entries--${module.style}`}
>
{module.items.map((item, index) => (
<SortableItem
key={item._key}
id={item._key}
disabled={!canEdit}
className={`portal-preview__entry ${!item.enabled ? 'portal-preview__entry--disabled' : ''}`}
>
{(entryHandle) => (
<>
<button
className='portal-preview__tile'
{...entryHandle}
disabled={!canEdit}
onClick={() => editEntry(moduleIndex, index)}
>
<span
className={`portal-preview__icon portal-preview__icon--${index % 4}`}
>
{item.icon ? (
<img src={item.icon} alt='' draggable={false} />
) : (
<AppstoreOutlined />
)}
</span>
<span className='portal-preview__text'>
<strong>{item.name}</strong>
{module.style === 'cards' && item.description && (
<small>{item.description}</small>
)}
{!item.enabled && <em>已停用</em>}
</span>
</button>
{canEdit && (
<Popconfirm
title='删除此入口?'
onConfirm={() => removeEntry(moduleIndex, index)}
>
<Button
className='portal-preview__remove'
type='text'
size='small'
icon={<DeleteOutlined />}
aria-label={`删除${item.name}`}
/>
</Popconfirm>
)}
</>
)}
</SortableItem>
))}
{canEdit && (
<button
className='portal-preview__add-entry'
onClick={() => editEntry(moduleIndex)}
>
<PlusOutlined />
<span>新增入口</span>
</button>
)}
</div>
</SortableList>
</>
)}
</SortableItem>
))}
</SortableList>
{modules.length === 0 && <div className='portal-preview__empty'>暂无模块</div>}
{canSave && (
<Button
type='dashed'
block
icon={<PlusOutlined />}
onClick={() => editModule()}
disabled={!canEdit}
style={{ marginTop: 16, height: 44 }}
>
新增模块
</Button>
)}
</div>
{canSave && (
<div className='portal-preview__save'>
<Button icon={<CodeOutlined />} onClick={editJson} disabled={!canEdit}>
编辑 JSON
</Button>
<Button type='primary' disabled={!loaded} onClick={save} loading={saving}>
保存
</Button>
</div>
)}
</>
)}
<HomeConfigEditModal
editing={editing}
form={form}
onCancel={() => setEditing(null)}
onOk={applyEdit}
/>
<HomeConfigJsonDrawer
open={jsonOpen}
text={jsonText}
error={jsonError}
onClose={() => setJsonOpen(false)}
onApply={applyJson}
onChange={(text) => {
setJsonText(text)
setJsonError('')
}}
/>
</div>
)
}
import { useEffect, useState } from 'react'
import { nanoid } from 'nanoid'
import { Button, Form, Popconfirm, Select, Spin, message } from 'antd'
import { AppstoreOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons'
import { usePermission } from '@/hooks/usePermission'
import { getProductsConfig, saveProductsConfig } from '../api'
import HomeConfigEditModal from '../components/HomeConfigEditModal'
import { SortableList, SortableItem } from '../components/SortableList'
import './homeConfig.less'
export default function ProductsConfigView() {
const [items, setItems] = useState([])
const [style, setStyle] = useState('grid')
const [loading, setLoading] = useState(true)
const [loaded, setLoaded] = useState(false)
const [saving, setSaving] = useState(false)
const [editing, setEditing] = useState(null)
const [form] = Form.useForm()
const allowed = usePermission()
const canEdit = allowed('/setting/portal/products/save') && loaded && !saving
useEffect(() => {
getProductsConfig()
.then((config) => {
setStyle(config.style)
setItems(
config.items.sort((a, b) => a.sort - b.sort).map((item) => ({ ...item, _key: nanoid() })),
)
setLoaded(true)
})
.catch(() => {})
.finally(() => setLoading(false))
}, [])
const edit = (index = null) => {
form.resetFields()
const item = index === null ? { enabled: 1, require_login: 0 } : items[index]
form.setFieldsValue({ ...item, enabled: !!item.enabled, require_login: !!item.require_login })
setEditing({ kind: 'entry', index })
}
const apply = async () => {
const values = await form.validateFields()
values.enabled = Number(values.enabled)
values.require_login = Number(values.require_login)
setItems((current) =>
editing.index === null
? [...current, { ...values, _key: nanoid() }]
: current.map((item, index) => (index === editing.index ? { ...item, ...values } : item)),
)
setEditing(null)
}
const save = async () => {
setSaving(true)
try {
await saveProductsConfig({
style,
items: items.map(({ _key, ...item }, index) => ({ ...item, sort: (index + 1) * 10 })),
})
message.success('已保存')
} catch {
} finally {
setSaving(false)
}
}
return (
<div className='portal-preview'>
{loading ? (
<Spin />
) : (
<div className='portal-preview__canvas'>
<div className='portal-preview__module'>
<div className='portal-preview__heading'>
<h3>产品中心</h3>
<Select
value={style}
onChange={setStyle}
disabled={!canEdit}
style={{ marginLeft: 'auto', width: 140 }}
options={[
{ value: 'grid', label: '图标网格' },
{ value: 'cards', label: '图片卡片' },
]}
/>
</div>
<SortableList items={items} onChange={setItems}>
<div className={`portal-preview__entries portal-preview__entries--${style}`}>
{items.map((item, index) => (
<SortableItem
key={item._key}
id={item._key}
disabled={!canEdit}
className={`portal-preview__entry ${!item.enabled ? 'portal-preview__entry--disabled' : ''}`}
>
{(handle) => (
<>
<button
className='portal-preview__tile'
{...handle}
disabled={!canEdit}
onClick={() => edit(index)}
>
<span
className={`portal-preview__icon portal-preview__icon--${index % 4}`}
>
{item.icon ? (
<img src={item.icon} alt='' draggable={false} />
) : (
<AppstoreOutlined />
)}
</span>
<span className='portal-preview__text'>
<strong>{item.name}</strong>
{style === 'cards' && item.description && (
<small>{item.description}</small>
)}
{!item.enabled && <em>已停用</em>}
</span>
</button>
{canEdit && (
<Popconfirm
title='删除此产品?'
onConfirm={() =>
setItems((current) => current.filter((_, i) => i !== index))
}
>
<Button
className='portal-preview__remove'
type='text'
icon={<DeleteOutlined />}
aria-label='删除产品'
/>
</Popconfirm>
)}
</>
)}
</SortableItem>
))}
{canEdit && (
<button className='portal-preview__add-entry' onClick={() => edit()}>
<PlusOutlined />
<span>新增产品</span>
</button>
)}
</div>
</SortableList>
</div>
</div>
)}
{allowed('/setting/portal/products/save') && (
<div className='portal-preview__save'>
<Button type='primary' disabled={!loaded} loading={saving} onClick={save}>
保存
</Button>
</div>
)}
<HomeConfigEditModal
editing={editing}
form={form}
onCancel={() => setEditing(null)}
onOk={apply}
entryLabel='产品'
/>
</div>
)
}
.portal-preview {
&__canvas {
max-width: 615px;
margin: 0 auto;
padding: 24px;
background: #f5f7fa;
border-radius: 16px;
}
&__module {
padding: 20px;
margin-bottom: 16px;
border-radius: 16px;
background: white;
&:last-child {
margin-bottom: 0;
}
&--disabled {
background: #fafafa;
border: 1px dashed #cbd0d8;
}
}
&__heading {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 20px;
h3 {
margin: 0;
font-size: 18px;
font-weight: 600;
line-height: 100%;
color: #253041;
padding-left: 10px;
border-left: 3px solid #aa1941;
}
}
&__module-actions {
margin-left: 8px;
}
&__entries {
display: grid;
gap: 16px 12px;
&--grid {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
&--cards {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
&__entry {
position: relative;
&--disabled .portal-preview__tile {
opacity: 0.5;
}
}
&__tile {
width: 100%;
height: 100%;
border: 1px solid transparent;
border-radius: 12px;
background: transparent;
cursor: pointer;
padding: 12px 8px;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
color: #343b47;
font: inherit;
&:hover,
&:focus-visible {
border-color: #dcb6c2;
background: #fffafb;
outline: none;
}
&:disabled {
cursor: default;
}
}
&__icon {
display: flex;
align-items: center;
justify-content: center;
width: 60px;
height: 60px;
border-radius: 14px;
background: #fcf3f6;
color: #aa1941;
font-size: 28px;
flex-shrink: 0;
img {
width: 42px;
height: 42px;
object-fit: contain;
}
&--1 {
background: #f7f3fc;
}
&--2 {
background: #f1f7fd;
}
&--3 {
background: #f1f9f5;
}
}
&__text {
display: flex;
flex-direction: column;
gap: 6px;
text-align: center;
strong {
font-size: 13px;
font-weight: 500;
line-height: 1.5;
overflow-wrap: anywhere;
}
small {
color: #85858e;
font-size: 12px;
line-height: 1.5;
overflow-wrap: anywhere;
}
em {
font-style: normal;
color: #89919d;
font-size: 11px;
}
}
&__entries--cards &__tile {
flex-direction: row;
align-items: center;
background: #faf6f8;
padding: 18px 14px;
gap: 12px;
}
&__entries--cards &__text {
text-align: left;
}
&__entries--cards &__icon {
width: 48px;
height: 48px;
background: transparent;
}
&__remove {
position: absolute;
top: 0;
right: 0;
opacity: 0;
color: #89919d;
}
&__entry:hover &__remove,
&__entry:focus-within &__remove {
opacity: 1;
}
&__add-entry {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
min-height: 100px;
border: 1px dashed #d6dbe3;
border-radius: 12px;
background: transparent;
color: #89919d;
cursor: pointer;
font: inherit;
font-size: 12px;
&:hover {
color: #aa1941;
border-color: #aa1941;
}
}
&__empty {
padding: 60px 16px;
text-align: center;
color: #89919d;
}
&__save {
display: flex;
justify-content: center;
gap: 12px;
margin-top: 24px;
}
@media (max-width: 640px) {
&__canvas {
padding: 12px;
}
&__module {
padding: 12px;
}
&__entries--grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
&__entries--cards {
grid-template-columns: 1fr;
}
}
}
.portal-json {
max-width: 100vw;
.ant-drawer-body {
display: flex;
flex-direction: column;
gap: 16px;
padding: 20px 24px;
min-height: 0;
}
&__input.ant-input {
flex: 1;
min-height: 240px;
resize: none;
font:
13px / 22px 'SFMono-Regular',
Consolas,
monospace;
}
&__footer {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 8px 0;
}
}
.portal-preview__icon-upload {
.upload-image__compact {
width: 112px;
height: 112px;
border-radius: 12px;
font-size: 28px;
img {
padding: 12px;
object-fit: contain;
}
}
}
.portal-preview__module-title {
flex: 1;
cursor: grab;
touch-action: none;
&:active {
cursor: grabbing;
}
}
.portal-preview__tile:not(:disabled) {
touch-action: none;
&:active {
cursor: grabbing;
}
}
.portal-preview__module-actions {
opacity: 0;
pointer-events: none;
}
.portal-preview__module:hover,
.portal-preview__module:focus-within {
.portal-preview__module-actions {
opacity: 1;
pointer-events: auto;
}
}
@media (hover: none) {
.portal-preview__module-actions,
.portal-preview__add-entry,
.portal-preview__remove {
opacity: 1;
pointer-events: auto;
}
}
.portal-preview__more {
margin-left: auto;
color: #85858e;
font-size: 13px;
}
...@@ -2,6 +2,7 @@ import { lazy } from 'react' ...@@ -2,6 +2,7 @@ import { lazy } from 'react'
import { Navigate, useRoutes } from 'react-router' import { Navigate, useRoutes } from 'react-router'
import ModuleBoundary from '@/router/ModuleBoundary' import ModuleBoundary from '@/router/ModuleBoundary'
const PortalRoutes = lazy(() => import('./portal/routes'))
const SettingsLayout = lazy(() => import('./SettingsLayout')) const SettingsLayout = lazy(() => import('./SettingsLayout'))
const HelpRoutes = lazy(() => import('./help/routes')) const HelpRoutes = lazy(() => import('./help/routes'))
const AppliedRoutes = lazy(() => import('./applied/routes')) const AppliedRoutes = lazy(() => import('./applied/routes'))
...@@ -18,6 +19,7 @@ export default function SettingsRoutes() { ...@@ -18,6 +19,7 @@ export default function SettingsRoutes() {
Component: SettingsLayout, Component: SettingsLayout,
children: [ children: [
{ index: true, element: <Navigate to='/setting/applied' /> }, { index: true, element: <Navigate to='/setting/applied' /> },
{ path: 'portal/*', Component: PortalRoutes },
{ path: 'help/*', Component: HelpRoutes }, { path: 'help/*', Component: HelpRoutes },
{ path: 'applied/*', Component: AppliedRoutes }, { path: 'applied/*', Component: AppliedRoutes },
{ path: 'personalized-setting/*', Component: PersonalizedRoutes }, { path: 'personalized-setting/*', Component: PersonalizedRoutes },
......
# Learning application boundaries # Web application boundaries
Flutter `book-app` is the functional source of truth. Preserve its business behavior and API contracts while adapting interaction to desktop browsers; do not copy Flutter widgets mechanically. Flutter `book-app` is the functional source of truth. Preserve its business behavior and API contracts while adapting interaction to desktop browsers; do not copy Flutter widgets mechanically.
......
{ {
"name": "@ebook/learning", "name": "@ebook/web",
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"type": "module", "type": "module",
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
"oxfmt": "^0.64.0", "oxfmt": "^0.64.0",
"oxlint": "^1.79.0", "oxlint": "^1.79.0",
"typescript": "^7.0.2", "typescript": "^7.0.2",
"vite": "^8.2.2", "vite": "^8.3.4",
"vite-plugin-mkcert": "^2.1.0", "vite-plugin-mkcert": "^2.1.0",
"vitest": "^4.1.10" "vitest": "^4.1.10"
} }
......
...@@ -27,7 +27,7 @@ export default defineConfig(({ mode }) => { ...@@ -27,7 +27,7 @@ export default defineConfig(({ mode }) => {
}, },
}, },
build: { build: {
outDir: '../../dist/learning', outDir: '../../dist/web',
emptyOutDir: true, emptyOutDir: true,
}, },
resolve: { resolve: {
......
| 序号 | 产品 | 功能模块 | 资金预算(人民币) |
| --- | --- | --- | --- |
| 1 | 清控紫荆数智学堂 | **一、AI数字教材在线编辑器系统**<br>1. 支持教材章节目录编排,包括章节新增、名称编辑、顺序调整和删除,并可为章节分配编辑人员。<br>2. 支持教材正文编辑,包括标题、字体、段落格式设置,以及列表、引用、链接和表格插入。<br>▲3. 支持图片、音频和视频上传并插入教材正文,支持以画廊形式组织和展示多张图片。(需要提供功能演示视频)<br>4. 支持在教材正文中插入公式、扩展阅读、文字气泡和图标气泡,并为气泡设置补充说明及相关链接。<br>5. 支持教材编辑内容自动保存和编辑历史记录查看,支持预览章节正文、多媒体资源及练习题的展示效果。<br>▲6. 支持按模板导入Word教材内容,并对导入后的内容进行编辑。(需要提供功能演示视频)<br>▲7. 支持围绕教材内容开展AI问答,提供文本改写、润色、扩写、摘要、翻译、标点检查和内容检查功能。(需要提供功能演示视频)<br>▲8. 支持根据教学内容辅助生成单选题、多选题、判断题、填空题和开放题,生成的题目可预览、编辑后使用。(需要提供功能演示视频)<br>9. 支持围绕教材编写主题检索参考资料,利用研究辅助和写作辅助功能生成参考内容。<br>10. 支持根据文字描述生成图片和视频,生成结果可预览并插入教材正文;支持数字人视频制作。<br>11. 支持题库管理,包括题目新增、编辑、查询和删除,题型包括单选题、多选题、判断题、填空题和开放题。<br>12. 支持题干、选项、答案和解析的维护,题目内容可采用富文本方式编辑。<br>13. 支持从题库选取题目组成教材章节练习,并预览题目内容和作答效果。<br><br>**二、数字教材学习与应用系统使用服务**<br>▲1. 支持网页端、Android客户端和iOS客户端访问数字教材。(需要提供功能演示视频)<br>2. 支持教材分类浏览和搜索,教材列表可展示封面、名称等信息。<br>3. 支持展示教材简介、作者、章节目录和阅读人数等详情信息,并提供阅读、试读和购买入口。<br>4. 支持按章节目录定位和切换学习内容,阅读教材正文。<br>▲5. 支持展示教材中的图片、画廊、公式、表格、扩展阅读和气泡内容,并播放音频和视频。(需要提供功能演示视频)<br>6. 支持教材试读,并根据教材购买状态控制相应章节的阅读权限。<br>7. 支持记录教材阅读进度,继续阅读时可返回最近阅读的章节。<br>8. 支持对教材文字进行划线、高亮和添加笔记,查看已保存的标记,并编辑、删除个人笔记。<br>9. 支持围绕教材内容发表讨论、回复和点赞,查看已有讨论,并删除本人发表的内容。<br>▲10. 支持教材章节练习作答和答案提交,提交后可查看作答结果、答案和解析。(需要提供功能演示视频)<br>11. 支持错题本功能,按教材展示错题数量,并可进入对应教材。<br>12. 支持查看最近阅读的教材及阅读历史。<br>▲13. 支持查看单本教材的学习报告,包括学习进度、阅读时长、笔记数量、划线数量、讨论参与情况和最近阅读章节。(需要提供功能演示视频)<br>14. 支持查看个人已拥有的教材,管理书架和收藏教材。<br>15. 支持在个人中心集中查看笔记和讨论记录,并访问错题本。<br>▲16. 支持用户登录、个人资料和头像修改,以及密码、绑定手机号等账号安全设置。(需要提供功能演示视频)<br>17. 支持查看平台消息和帮助内容,提交使用问题及反馈建议。<br>18. 支持教材购买订单创建、支付及支付结果查询。<br>19. 支持订单列表和详情查询、待支付订单再次支付及退款信息查看。<br>20. 支持个人优惠券、积分、账户余额和账户流水查询,购买教材时可使用适用的优惠券及积分抵扣。<br><br>**三、数字教材发布与管理系统使用服务**<br>1. 支持教材新增、编辑和查询,维护名称、封面、作者、简介等基本信息,并通过分类和标签组织教材。<br>2. 支持教材发布和下架,控制教材对学习用户的开放状态。<br>3. 支持待审核教材及审核任务查询,查看教材内容和审核状态。<br>▲4. 支持教材内容预览,在对应内容位置添加审核批注,并对批注进行回复和处理。(需要提供功能演示视频)<br>5. 支持教材历次审核记录查询,包括审核意见、审核时间和处理结果。<br>6. 支持按教材查询讨论话题,查看话题内容及用户回复,并管理讨论内容。<br>7. 支持用户列表及详情查询、教师信息维护和管理员账号管理。<br>8. 支持会员等级及等级有效期设置,管理用户会员信息。<br>9. 支持角色创建和维护,为不同角色分配功能权限,控制后台功能的使用范围。<br>10. 支持教材订单查询,展示购买人、订单金额、支付状态和支付方式等交易信息,并支持订单导出和退款处理。<br>11. 支持销售金额、订单数量及月度销售统计,展示教材销售和教师业绩排行。<br>12. 支持优惠券配置和发放、积分规则设置及账户充值管理。<br>13. 支持广告位和广告内容管理,设置广告图片、链接、有效期及上下线状态。<br>14. 支持帮助文章、应用版本信息和敏感词维护,以及平台个性化设置。<br>15. 支持用户反馈查询及管理,查看用户提交的问题和建议。<br><br>**四、数字教材出版服务**<br>1. 要求对接正规出版社开展数字教材审校和数字出版服务,包括:数字教材内容素材审核、文字审校、版权审查等三审三校和出版测试数字教材内容中的所有产品功能。<br>一审:责任编辑审读全书稿件,负责三审中的第一个审次,使稿件的内容更完善,体例更严谨,材料更准确,语言文字更通达,逻辑更严密,消除一般性差错,防止出现原则性错误。在教材及资源内容的政治性、知识性、文字规范性、体例格式统一性等方面把好关。<br>二审:应根据书稿内容质量、重点难点和一审加工情况,审读100%的正文和全部插图,对书稿质量及一审报告提出二审意见,解决一审提出的问题。二审人员原则上须具有大学本科以上(含本科)学历,具有编辑工作经历。<br>三审:根据书稿内容质量、重点难点和一、二审加工情况,有针对性地重点审读20%~100%的正文和插图。三审人员原则上须具有大学本科以上(含本科)学历,具有编辑工作经历,担任过二审工作。严格执行一审之后的复审与终审,并由相应加工记录留存。<br>按照“三校”的要求,完成三次校对工作,提升书稿整体质量,再次降低差错率。规范的校对流程和较大规模的专职校对人员,能够完成一校、二校和三校的三校流程,并在每个环节都有相应的记录留存。<br>保证数字教材正常的出版使用和阅读。支持老师正式出版校本数字教材,通过正规出版社数字出版,获得新闻出版总署的正式出版物和ISBN号。正式出版的数字教材,教材推广前需经过教材所有权人的同意,教材通过在线书城可以在其他学校进行推广应用。合作出版社包含中央级出版社、高校出版社、行业类专业出版社。<br>2. 要求所出版数字教材能与清控紫荆数智学堂对接。 | |
...@@ -3,20 +3,20 @@ ...@@ -3,20 +3,20 @@
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
"dev": "pnpm --parallel --filter @ebook/admin --filter @ebook/learning dev", "dev": "pnpm --parallel --filter @ebook/admin --filter @ebook/web dev",
"dev:admin": "pnpm --filter @ebook/admin dev", "dev:admin": "pnpm --filter @ebook/admin dev",
"dev:learning": "pnpm --filter @ebook/learning dev", "dev:web": "pnpm --filter @ebook/web dev",
"build": "pnpm run build:learning && pnpm run build:admin", "build": "pnpm run build:web && pnpm run build:admin",
"build:admin": "pnpm --filter @ebook/admin build", "build:admin": "pnpm --filter @ebook/admin build",
"build:learning": "pnpm --filter @ebook/learning build", "build:web": "pnpm --filter @ebook/web build",
"test": "pnpm run test:learning && pnpm run test:admin", "test": "pnpm run test:web && pnpm run test:admin",
"lint:admin": "pnpm --filter @ebook/admin lint", "lint:admin": "pnpm --filter @ebook/admin lint",
"lint:learning": "pnpm --filter @ebook/learning lint", "lint:web": "pnpm --filter @ebook/web lint",
"lint:check:admin": "pnpm --filter @ebook/admin exec oxlint .", "lint:check:admin": "pnpm --filter @ebook/admin exec oxlint .",
"lint:check:learning": "pnpm --filter @ebook/learning exec oxlint .", "lint:check:web": "pnpm --filter @ebook/web exec oxlint .",
"lint:check": "pnpm run lint:check:admin && pnpm run lint:check:learning", "lint:check": "pnpm run lint:check:admin && pnpm run lint:check:web",
"typecheck:learning": "pnpm --filter @ebook/learning exec tsc -b", "typecheck:web": "pnpm --filter @ebook/web exec tsc -b",
"test:admin": "pnpm --filter @ebook/admin test", "test:admin": "pnpm --filter @ebook/admin test",
"test:learning": "pnpm --filter @ebook/learning test" "test:web": "pnpm --filter @ebook/web test"
} }
} }
...@@ -16,6 +16,15 @@ importers: ...@@ -16,6 +16,15 @@ importers:
'@chuangkit/chuangkit-design': '@chuangkit/chuangkit-design':
specifier: ^2.0.8 specifier: ^2.0.8
version: 2.2.5 version: 2.2.5
'@dnd-kit/core':
specifier: ^6.3.1
version: 6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@dnd-kit/sortable':
specifier: ^10.0.0
version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
'@dnd-kit/utilities':
specifier: ^3.2.2
version: 3.2.2(react@19.2.8)
'@ezijing/ai-react': '@ezijing/ai-react':
specifier: ^1.0.40 specifier: ^1.0.40
version: 1.0.44(debug@4.4.3(supports-color@10.2.2))(react@19.2.8)(supports-color@10.2.2) version: 1.0.44(debug@4.4.3(supports-color@10.2.2))(react@19.2.8)(supports-color@10.2.2)
...@@ -118,7 +127,7 @@ importers: ...@@ -118,7 +127,7 @@ importers:
version: 19.2.4(@types/react@19.2.18) version: 19.2.4(@types/react@19.2.18)
'@vitejs/plugin-react': '@vitejs/plugin-react':
specifier: ^6.0.5 specifier: ^6.0.5
version: 6.0.5(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 6.0.5(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
jsdom: jsdom:
specifier: ^29.1.1 specifier: ^29.1.1
version: 29.1.1 version: 29.1.1
...@@ -135,16 +144,16 @@ importers: ...@@ -135,16 +144,16 @@ importers:
specifier: ^7.0.2 specifier: ^7.0.2
version: 7.0.2 version: 7.0.2
vite: vite:
specifier: ^8.2.2 specifier: ^8.3.4
version: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) version: 8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
vite-plugin-mkcert: vite-plugin-mkcert:
specifier: ^2.1.0 specifier: ^2.1.0
version: 2.1.0(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 2.1.0(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
vitest: vitest:
specifier: ^4.1.10 specifier: ^4.1.10
version: 4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
apps/learning: apps/web:
dependencies: dependencies:
'@ant-design/icons': '@ant-design/icons':
specifier: ^6.3.2 specifier: ^6.3.2
...@@ -157,7 +166,7 @@ importers: ...@@ -157,7 +166,7 @@ importers:
version: 6.23.0(supports-color@10.2.2) version: 6.23.0(supports-color@10.2.2)
antd: antd:
specifier: ^6.5.1 specifier: ^6.5.1
version: 6.5.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8) version: 6.6.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
axios: axios:
specifier: ^1.8.4 specifier: ^1.8.4
version: 1.18.1(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2) version: 1.18.1(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)
...@@ -200,7 +209,7 @@ importers: ...@@ -200,7 +209,7 @@ importers:
version: 19.2.4(@types/react@19.2.18) version: 19.2.4(@types/react@19.2.18)
'@vitejs/plugin-react': '@vitejs/plugin-react':
specifier: ^6.0.5 specifier: ^6.0.5
version: 6.0.5(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 6.0.5(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
jsdom: jsdom:
specifier: ^29.1.1 specifier: ^29.1.1
version: 29.1.1 version: 29.1.1
...@@ -214,14 +223,14 @@ importers: ...@@ -214,14 +223,14 @@ importers:
specifier: ^7.0.2 specifier: ^7.0.2
version: 7.0.2 version: 7.0.2
vite: vite:
specifier: ^8.2.2 specifier: ^8.3.4
version: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) version: 8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
vite-plugin-mkcert: vite-plugin-mkcert:
specifier: ^2.1.0 specifier: ^2.1.0
version: 2.1.0(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 2.1.0(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
vitest: vitest:
specifier: ^4.1.10 specifier: ^4.1.10
version: 4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) version: 4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
packages: packages:
...@@ -336,6 +345,28 @@ packages: ...@@ -336,6 +345,28 @@ packages:
resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==}
engines: {node: '>=20.19.0'} engines: {node: '>=20.19.0'}
'@dnd-kit/accessibility@3.1.1':
resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==}
peerDependencies:
react: '>=16.8.0'
'@dnd-kit/core@6.3.1':
resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
'@dnd-kit/sortable@10.0.0':
resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==}
peerDependencies:
'@dnd-kit/core': ^6.3.0
react: '>=16.8.0'
'@dnd-kit/utilities@3.2.2':
resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
peerDependencies:
react: '>=16.8.0'
'@emotion/hash@0.8.0': '@emotion/hash@0.8.0':
resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==}
...@@ -535,8 +566,8 @@ packages: ...@@ -535,8 +566,8 @@ packages:
'@jridgewell/trace-mapping@0.3.31': '@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
'@oxc-project/types@0.144.0': '@oxc-project/types@0.153.0':
resolution: {integrity: sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==} resolution: {integrity: sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==}
'@oxfmt/binding-android-arm-eabi@0.64.0': '@oxfmt/binding-android-arm-eabi@0.64.0':
resolution: {integrity: sha512-o6uzh/jTOQeAY5TdkAeXdqv7MBRcPxiRA08zrcBtkKj5cSu/FMu0Hl7Q6Fi1KCKyCWZ6lJVjBzdsJvsKltUsGQ==} resolution: {integrity: sha512-o6uzh/jTOQeAY5TdkAeXdqv7MBRcPxiRA08zrcBtkKj5cSu/FMu0Hl7Q6Fi1KCKyCWZ6lJVjBzdsJvsKltUsGQ==}
...@@ -786,12 +817,6 @@ packages: ...@@ -786,12 +817,6 @@ packages:
resolution: {integrity: sha512-D3AGQwdyE58gmvx6waVSXJ80JGO+IY5L2O8HDnSOex7JNlzB3GuN/4hyHNTdhy2qtOhkpbIjmeAN3tL993wKbA==} resolution: {integrity: sha512-D3AGQwdyE58gmvx6waVSXJ80JGO+IY5L2O8HDnSOex7JNlzB3GuN/4hyHNTdhy2qtOhkpbIjmeAN3tL993wKbA==}
engines: {node: '>=14.x'} engines: {node: '>=14.x'}
'@rc-component/cascader@1.17.0':
resolution: {integrity: sha512-3cVNG0zrQF1PoXq262L3wGCU+/YLEC1mGSVHDl577dQmA0ZKkXFbY6nwyXo+beCcM7buo49t24jkr+QZdL7O8w==}
peerDependencies:
react: '>=18.0.0'
react-dom: '>=18.0.0'
'@rc-component/cascader@1.22.0': '@rc-component/cascader@1.22.0':
resolution: {integrity: sha512-SffrA57aS9oub3VuI7ajPhJTPtaNxngSvtRhD40Rd8dwJ5vfWPSrVanWgeepdWFGBt7EHftIK5RUU0u3rCTwWw==} resolution: {integrity: sha512-SffrA57aS9oub3VuI7ajPhJTPtaNxngSvtRhD40Rd8dwJ5vfWPSrVanWgeepdWFGBt7EHftIK5RUU0u3rCTwWw==}
peerDependencies: peerDependencies:
...@@ -840,13 +865,6 @@ packages: ...@@ -840,13 +865,6 @@ packages:
react: '>=16.11.0' react: '>=16.11.0'
react-dom: '>=16.11.0' react-dom: '>=16.11.0'
'@rc-component/form@1.8.5':
resolution: {integrity: sha512-d24EYtvUOBhxEtSd/EqIu9DaMuqrWF2IRIvAFCTM6NQ/GJIYNr8DvEpUSUlv2uPxEJ0ZPwYQ+wwlGIAaiHvdrw==}
engines: {node: '>=8.x'}
peerDependencies:
react: '>=16.9.0'
react-dom: '>=16.9.0'
'@rc-component/form@1.8.6': '@rc-component/form@1.8.6':
resolution: {integrity: sha512-1EXVsSKPZC6kGrIqxVck7kAWM6T65b6et/n5wIcyiaIa41VrDshD0nVLHoBDEIZr2ATQsOP6icb4XQkNFMLBAw==} resolution: {integrity: sha512-1EXVsSKPZC6kGrIqxVck7kAWM6T65b6et/n5wIcyiaIa41VrDshD0nVLHoBDEIZr2ATQsOP6icb4XQkNFMLBAw==}
engines: {node: '>=8.x'} engines: {node: '>=8.x'}
...@@ -860,12 +878,6 @@ packages: ...@@ -860,12 +878,6 @@ packages:
react: '>=16.9.0' react: '>=16.9.0'
react-dom: '>=16.9.0' react-dom: '>=16.9.0'
'@rc-component/image@1.9.0':
resolution: {integrity: sha512-khF7w7xkBH5B1bsBcI1FSUZdkyd1aqpl2eYyILCqCzzQH3XdfehGUaZTnptyaJJfs09/R5hv9jXWyazOMFIClQ==}
peerDependencies:
react: '>=16.9.0'
react-dom: '>=16.9.0'
'@rc-component/input-number@1.6.2': '@rc-component/input-number@1.6.2':
resolution: {integrity: sha512-Gjcq7meZlCOiWN1t1xCC+7/s85humHVokTBI7PJgTfoyw5OWF74y3e6P8PHX104g9+b54jsodFIzyaj6p8LI9w==} resolution: {integrity: sha512-Gjcq7meZlCOiWN1t1xCC+7/s85humHVokTBI7PJgTfoyw5OWF74y3e6P8PHX104g9+b54jsodFIzyaj6p8LI9w==}
peerDependencies: peerDependencies:
...@@ -884,12 +896,6 @@ packages: ...@@ -884,12 +896,6 @@ packages:
react: '>=18.0.0' react: '>=18.0.0'
react-dom: '>=18.0.0' react-dom: '>=18.0.0'
'@rc-component/mentions@1.10.0':
resolution: {integrity: sha512-CI1njYUVY0NjHtLhNoVmXlJyy568Sfep9Wsak6vmGjtT6uazx98djGYlCXz2xkHhEm73g91Y3MTvzUyE5avI7w==}
peerDependencies:
react: '>=16.9.0'
react-dom: '>=16.9.0'
'@rc-component/mentions@1.11.0': '@rc-component/mentions@1.11.0':
resolution: {integrity: sha512-IC2qXuEBMFHxPIXEFfYWj6Sr7UiDZnOqJHCYQBbwPzopBJOPZIR6mV9U4QH1bYQRlKYlYnIsajWDMgVGgWQyWQ==} resolution: {integrity: sha512-IC2qXuEBMFHxPIXEFfYWj6Sr7UiDZnOqJHCYQBbwPzopBJOPZIR6mV9U4QH1bYQRlKYlYnIsajWDMgVGgWQyWQ==}
peerDependencies: peerDependencies:
...@@ -938,26 +944,6 @@ packages: ...@@ -938,26 +944,6 @@ packages:
react: '>=16.9.0' react: '>=16.9.0'
react-dom: '>=16.9.0' react-dom: '>=16.9.0'
'@rc-component/picker@1.11.0':
resolution: {integrity: sha512-6qXGKtoJvO8sUd17m5cyNEbEJub0zflCHnaZTBBmj63DPRZYc0WEHN8rp6hFSl+yMCJS/dJY5G+1fQ8bLCuD7A==}
engines: {node: '>=12.x'}
peerDependencies:
date-fns: '>= 2.x'
dayjs: '>= 1.x'
luxon: '>= 3.x'
moment: '>= 2.x'
react: '>=16.9.0'
react-dom: '>=16.9.0'
peerDependenciesMeta:
date-fns:
optional: true
dayjs:
optional: true
luxon:
optional: true
moment:
optional: true
'@rc-component/picker@1.12.0': '@rc-component/picker@1.12.0':
resolution: {integrity: sha512-0FZGgDiDZFMm2hcfGv4jyjm7yWIj2MiwfeTzLL0vWkO+8cCSKdiM9XhWpkn1aAsoI2EwUy48Oz2cGfvL8ZKrfw==} resolution: {integrity: sha512-0FZGgDiDZFMm2hcfGv4jyjm7yWIj2MiwfeTzLL0vWkO+8cCSKdiM9XhWpkn1aAsoI2EwUy48Oz2cGfvL8ZKrfw==}
engines: {node: '>=12.x'} engines: {node: '>=12.x'}
...@@ -1024,13 +1010,6 @@ packages: ...@@ -1024,13 +1010,6 @@ packages:
react: '*' react: '*'
react-dom: '*' react-dom: '*'
'@rc-component/select@1.8.2':
resolution: {integrity: sha512-HQ9zuYqjfZTlcEMWlU1GAPBajd2OHIMVHyjZSGVTCVARwkfCgvXZMTEn0cduy3L+ejAKkaZluOQvxovZoaJaQw==}
engines: {node: '>=8.x'}
peerDependencies:
react: '*'
react-dom: '*'
'@rc-component/slider@1.1.1': '@rc-component/slider@1.1.1':
resolution: {integrity: sha512-LSzgWGYDgeCDgR4r1XlU29gbYws6HpLnvJd/uMhLeW/vQgxldeR+Wb4uzHDCHiYEbr1bnEHWdjkPxjJRHxuiig==} resolution: {integrity: sha512-LSzgWGYDgeCDgR4r1XlU29gbYws6HpLnvJd/uMhLeW/vQgxldeR+Wb4uzHDCHiYEbr1bnEHWdjkPxjJRHxuiig==}
engines: {node: '>=8.x'} engines: {node: '>=8.x'}
...@@ -1051,13 +1030,6 @@ packages: ...@@ -1051,13 +1030,6 @@ packages:
react: '>=16.9.0' react: '>=16.9.0'
react-dom: '>=16.9.0' react-dom: '>=16.9.0'
'@rc-component/table@1.10.4':
resolution: {integrity: sha512-HwoTnrwc29zeoXkXGhWqzJh8FIibGUxi1jM4LtoSzmR9d5Vv5osUQpZxnXKBP8iOCvyD6BQzZm1nXJRcnrxpAg==}
engines: {node: '>=8.x'}
peerDependencies:
react: '>=18.0.0'
react-dom: '>=18.0.0'
'@rc-component/table@1.11.1': '@rc-component/table@1.11.1':
resolution: {integrity: sha512-OWdS6DMmeWb7bJBGqPxYZpQbzBlBiXZUu2sqo6Ii7Sjs9GeK1IsrXrWk26SL2c6KEseabswdxrRj7WUm9LdECw==} resolution: {integrity: sha512-OWdS6DMmeWb7bJBGqPxYZpQbzBlBiXZUu2sqo6Ii7Sjs9GeK1IsrXrWk26SL2c6KEseabswdxrRj7WUm9LdECw==}
engines: {node: '>=8.x'} engines: {node: '>=8.x'}
...@@ -1065,13 +1037,6 @@ packages: ...@@ -1065,13 +1037,6 @@ packages:
react: '>=18.0.0' react: '>=18.0.0'
react-dom: '>=18.0.0' react-dom: '>=18.0.0'
'@rc-component/tabs@1.11.0':
resolution: {integrity: sha512-hA/drZYOVa/MMIb4M2fWf3yaTyTG4qVuIABmghvEhyfw2nBob5VTH69lMCDjSVKmgODjO6nWlCV+gVn3xBrj5Q==}
engines: {node: '>=8.x'}
peerDependencies:
react: '>=16.9.0'
react-dom: '>=16.9.0'
'@rc-component/tabs@1.12.0': '@rc-component/tabs@1.12.0':
resolution: {integrity: sha512-XL7Kqy5fnUE2WTlO1/fCGrrfNlGFebdr7JseGkEIjzcVMAtIFQJ8sqCSOmxcXstjU6fonD/4rnhZHxj7sDTajQ==} resolution: {integrity: sha512-XL7Kqy5fnUE2WTlO1/fCGrrfNlGFebdr7JseGkEIjzcVMAtIFQJ8sqCSOmxcXstjU6fonD/4rnhZHxj7sDTajQ==}
engines: {node: '>=8.x'} engines: {node: '>=8.x'}
...@@ -1079,12 +1044,6 @@ packages: ...@@ -1079,12 +1044,6 @@ packages:
react: '>=16.9.0' react: '>=16.9.0'
react-dom: '>=16.9.0' react-dom: '>=16.9.0'
'@rc-component/tooltip@1.4.0':
resolution: {integrity: sha512-8Rx5DCctIlLI4raR0I0xHjVTf1aF48+gKCNeAAo5bmF5VoR5YED+A/XEqzXv9KKqrJDRcd3Wndpxh2hyzrTtSg==}
peerDependencies:
react: '>=18.0.0'
react-dom: '>=18.0.0'
'@rc-component/tooltip@1.5.0': '@rc-component/tooltip@1.5.0':
resolution: {integrity: sha512-agQ/+mBqrEQfTX4D3KhQ7j+ZbX4/VHjoJ7Noa2wIdZ1/FbQTOd7Sn92rp+jtCoqAVTLUgSOydePIgZ204gi2EQ==} resolution: {integrity: sha512-agQ/+mBqrEQfTX4D3KhQ7j+ZbX4/VHjoJ7Noa2wIdZ1/FbQTOd7Sn92rp+jtCoqAVTLUgSOydePIgZ204gi2EQ==}
peerDependencies: peerDependencies:
...@@ -1098,25 +1057,12 @@ packages: ...@@ -1098,25 +1057,12 @@ packages:
react: '>=16.9.0' react: '>=16.9.0'
react-dom: '>=16.9.0' react-dom: '>=16.9.0'
'@rc-component/tree-select@1.11.0':
resolution: {integrity: sha512-EhS0X0wtUhBfK4S5TlpSY3MR9ndPMGgujtt1PJW3Ej+ToAlnS/6ohYURtCoXBYGqazUwHmgQGVUDsfpVwhWPkg==}
peerDependencies:
react: '*'
react-dom: '*'
'@rc-component/tree-select@1.16.1': '@rc-component/tree-select@1.16.1':
resolution: {integrity: sha512-a1Oi6EJhqAhdOxxupdJi6fP0RPHMKn5TcfkX2+llaQ4lF4nwfH7b6SCHcnsybaa2s+pk1yZYwVyeOYkDnEBRdg==} resolution: {integrity: sha512-a1Oi6EJhqAhdOxxupdJi6fP0RPHMKn5TcfkX2+llaQ4lF4nwfH7b6SCHcnsybaa2s+pk1yZYwVyeOYkDnEBRdg==}
peerDependencies: peerDependencies:
react: '*' react: '*'
react-dom: '*' react-dom: '*'
'@rc-component/tree@1.3.2':
resolution: {integrity: sha512-bJFj46wEkpBPnWyTm18XmgAgNQ/4YvprxMOPPY2a6rmhGJYxLuNKEFiL5Qej4Qctu9wHJm8WW+v2SYskafE0kA==}
engines: {node: '>=10.x'}
peerDependencies:
react: '*'
react-dom: '*'
'@rc-component/tree@1.4.0': '@rc-component/tree@1.4.0':
resolution: {integrity: sha512-dGsJGDJQedA0BqqVgj3F8BvHXTSZijyhTXdbAdkcx8lynzZkty/CV3Z3LOm/fxz+BCfl3dfGiAQpb7Q5XNvl0Q==} resolution: {integrity: sha512-dGsJGDJQedA0BqqVgj3F8BvHXTSZijyhTXdbAdkcx8lynzZkty/CV3Z3LOm/fxz+BCfl3dfGiAQpb7Q5XNvl0Q==}
engines: {node: '>=10.x'} engines: {node: '>=10.x'}
...@@ -1162,92 +1108,98 @@ packages: ...@@ -1162,92 +1108,98 @@ packages:
peerDependencies: peerDependencies:
react: '>=18.2.0' react: '>=18.2.0'
'@rolldown/binding-android-arm64@1.2.4': '@rolldown/binding-android-arm-eabi@1.2.13':
resolution: {integrity: sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA==} resolution: {integrity: sha512-Vu/NICrgdRvUOeaJZIyB2FP63s6fO/4ud5l8dXmxDx9yDyn+mN0y+gsvsVviSli+T361Aqo0h46EuMoobrwawA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [android]
'@rolldown/binding-android-arm64@1.2.13':
resolution: {integrity: sha512-6LEoIrGy5vvCd2boNnv2soPSUZj/PRvhp8R/t9KlX+mIZxThIE/ZqxrGXxmuNX0FuvQFvLdZr7S4HrYpYBVhEQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@rolldown/binding-darwin-arm64@1.2.4': '@rolldown/binding-darwin-arm64@1.2.13':
resolution: {integrity: sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ==} resolution: {integrity: sha512-CaJSRzlQ6Q+zkDMVA9OkVxBjVoPRCDEE3v0FSJ9kIQBgRjFApA3Si4ijhbNVUji7ZJt+PfO0e46qy4nPInHUPA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@rolldown/binding-darwin-x64@1.2.4': '@rolldown/binding-darwin-x64@1.2.13':
resolution: {integrity: sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg==} resolution: {integrity: sha512-e4r340I5hxSzJkD3YJBxgzq/rJ3wwxwdLLb2FPt1Zpyem20nrQPT11DDEEkazwxaHumH8wpglsp/Ozgj/wT6mw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@rolldown/binding-freebsd-x64@1.2.4': '@rolldown/binding-freebsd-x64@1.2.13':
resolution: {integrity: sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A==} resolution: {integrity: sha512-hoBWDZ4/K/mJKVMbsgUd1jfpA2DiOrJ54mpegObU9TBHBBrtX4FLIXJJQRDPZ/2Dn91GvPob+Z2hwKJzf4E5SQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@rolldown/binding-linux-arm-gnueabihf@1.2.4': '@rolldown/binding-linux-arm-gnueabihf@1.2.13':
resolution: {integrity: sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ==} resolution: {integrity: sha512-oF9fZu3vTWnTiVAkDFxU9PJLt1nh20K9RRpuHsR7ZnE2L7XookBbDBVLojCVSLGbvtSlxeUNnjAj6DbNsKyzbg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@rolldown/binding-linux-arm64-gnu@1.2.4': '@rolldown/binding-linux-arm64-gnu@1.2.13':
resolution: {integrity: sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng==} resolution: {integrity: sha512-DTpb/+jMiqWMPgphn4ksW1zW+XLJ6dJJ9FMvnIk9I291LhCctMPhMYJrP5t9p6C9qa3KXadDdUEZHBaPh3kNxQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@rolldown/binding-linux-arm64-musl@1.2.4': '@rolldown/binding-linux-arm64-musl@1.2.13':
resolution: {integrity: sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w==} resolution: {integrity: sha512-xU+Kvv9N2A3SY35zFh1FWWNjxbadE/BKeqnkXe7vScU4GZsw757BlVmDLITZEq8DPpk6m7uoDYkK7P+x/uU5Ow==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@rolldown/binding-linux-ppc64-gnu@1.2.4': '@rolldown/binding-linux-ppc64-gnu@1.2.13':
resolution: {integrity: sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ==} resolution: {integrity: sha512-XMk/hnhh25oQ756Lclb1Q11h4ll0xC0Esa5w4Vzp+mAE2S3AGJgeM0SonrIgY8fHhjarb6hcoTuwoFG0VVP2ig==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@rolldown/binding-linux-s390x-gnu@1.2.4': '@rolldown/binding-linux-s390x-gnu@1.2.13':
resolution: {integrity: sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw==} resolution: {integrity: sha512-U1BoTHYmlywE2n3HUWjzZ+8EQsKr+OwpxYuDWaubx42tUL8QSL7nOqRz/NVHanibbFP3M1Rxuprz/wNcbMKjqw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@rolldown/binding-linux-x64-gnu@1.2.4': '@rolldown/binding-linux-x64-gnu@1.2.13':
resolution: {integrity: sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ==} resolution: {integrity: sha512-J4cm80Pc6wEwV5AZ42o62sIQgDk+Y7R2s646jIwuvO+4V46QB58N4vVuMPWCBaNgursXLpmUWJV//WQAkPvHBQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@rolldown/binding-linux-x64-musl@1.2.4': '@rolldown/binding-linux-x64-musl@1.2.13':
resolution: {integrity: sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ==} resolution: {integrity: sha512-W0euZS40U4V6JkmEnVCIX9mcsL6cbXQ4X8c2w+MMOIjFg68TXUW+u3RT+2e1t1pv9mg/EP3pDtK3POXdQ7Rxyw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@rolldown/binding-openharmony-arm64@1.2.4': '@rolldown/binding-openharmony-arm64@1.2.13':
resolution: {integrity: sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg==} resolution: {integrity: sha512-do/AF/4n9MRshia3a5aXoy8xM2c6mgfT6D7H/dY6my5z+hfCIR4ab7mk4IRj++nsEQpKy39kd0DQnDq+r692tw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [openharmony] os: [openharmony]
'@rolldown/binding-win32-arm64-msvc@1.2.4': '@rolldown/binding-win32-arm64-msvc@1.2.13':
resolution: {integrity: sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw==} resolution: {integrity: sha512-6FtUf2cJZobutJdxnGYX8z0vtbgqU0b2v8vfBhkXb9wp2MppMFtkunE+IaOntyi01rkIQoPW2GHABtfzsC0BRQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@rolldown/binding-win32-x64-msvc@1.2.4': '@rolldown/binding-win32-x64-msvc@1.2.13':
resolution: {integrity: sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ==} resolution: {integrity: sha512-UKhFaZTeTcbKrb3iU82m17jVcPEAoqDkCN5MBqgPyZSwp/cQmib21crTS0DdH7T1B7wZRWEI89YQAOJMet5yhg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
...@@ -1636,12 +1588,6 @@ packages: ...@@ -1636,12 +1588,6 @@ packages:
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
engines: {node: '>=10'} engines: {node: '>=10'}
antd@6.5.1:
resolution: {integrity: sha512-VZVVF9zYI6S0NHqboVhCoY9Iiqj6dphW1NPB+sEaAf2HuIQ0haXWXj7ZvAXTRDzusktV6+cvvrSZEdRi4twATg==}
peerDependencies:
react: '>=18.0.0'
react-dom: '>=18.0.0'
antd@6.6.0: antd@6.6.0:
resolution: {integrity: sha512-UDwWIbpmrCHB9ZQ+bPh4vQfB6DTI2ulIyoQ0Tc9xxalFblttiNGHl3ySBD9SyV/8+gUjFzfSx1+iU1Fog2i46w==} resolution: {integrity: sha512-UDwWIbpmrCHB9ZQ+bPh4vQfB6DTI2ulIyoQ0Tc9xxalFblttiNGHl3ySBD9SyV/8+gUjFzfSx1+iU1Fog2i46w==}
peerDependencies: peerDependencies:
...@@ -2301,6 +2247,11 @@ packages: ...@@ -2301,6 +2247,11 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true hasBin: true
nanoid@3.3.20:
resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
needle@3.5.0: needle@3.5.0:
resolution: {integrity: sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==} resolution: {integrity: sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==}
engines: {node: '>= 4.4.x'} engines: {node: '>= 4.4.x'}
...@@ -2405,11 +2356,15 @@ packages: ...@@ -2405,11 +2356,15 @@ packages:
resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
engines: {node: '>=12'} engines: {node: '>=12'}
picomatch@4.0.7:
resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==}
engines: {node: '>=12'}
platform@1.3.6: platform@1.3.6:
resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==}
postcss@8.5.26: postcss@8.5.29:
resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==} resolution: {integrity: sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==}
engines: {node: ^10 || ^12 || >=14} engines: {node: ^10 || ^12 || >=14}
preact@10.29.7: preact@10.29.7:
...@@ -2519,8 +2474,8 @@ packages: ...@@ -2519,8 +2474,8 @@ packages:
resize-observer-polyfill@1.5.1: resize-observer-polyfill@1.5.1:
resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
rolldown@1.2.4: rolldown@1.2.13:
resolution: {integrity: sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w==} resolution: {integrity: sha512-/5apOkwWxtACcQtZ5WlrAsKS4JwXVThQPJZ3RqIruRY9UG9M8e0VlXN068xum/JRKA4aIUoJ13ghe/kGCvidiQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true hasBin: true
...@@ -2603,6 +2558,10 @@ packages: ...@@ -2603,6 +2558,10 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
source-map-js@1.2.2:
resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==}
engines: {node: '>=0.10.0'}
source-map-support@0.5.21: source-map-support@0.5.21:
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
...@@ -2794,13 +2753,13 @@ packages: ...@@ -2794,13 +2753,13 @@ packages:
peerDependencies: peerDependencies:
vite: '>=3' vite: '>=3'
vite@8.2.2: vite@8.3.4:
resolution: {integrity: sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==} resolution: {integrity: sha512-IftLE8phJhdNRIGNEV4JCCvfNScoZQVfcXaN8TQropWGJtOHcu+iAB9pHcuGvmEb/kddw0LBe/jS8ztdC6xdiQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
'@types/node': ^20.19.0 || >=22.12.0 '@types/node': ^20.19.0 || >=22.12.0
'@vitejs/devtools': ^0.4.0 || ^0.5.0 '@vitejs/devtools': ^0.7.1
esbuild: ^0.27.0 || ^0.28.0 esbuild: ^0.27.0 || ^0.28.0
jiti: '>=1.21.0' jiti: '>=1.21.0'
less: ^4.0.0 less: ^4.0.0
...@@ -3076,6 +3035,31 @@ snapshots: ...@@ -3076,6 +3035,31 @@ snapshots:
'@csstools/css-tokenizer@4.0.0': {} '@csstools/css-tokenizer@4.0.0': {}
'@dnd-kit/accessibility@3.1.1(react@19.2.8)':
dependencies:
react: 19.2.8
tslib: 2.8.1
'@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@dnd-kit/accessibility': 3.1.1(react@19.2.8)
'@dnd-kit/utilities': 3.2.2(react@19.2.8)
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
tslib: 2.8.1
'@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
dependencies:
'@dnd-kit/core': 6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@dnd-kit/utilities': 3.2.2(react@19.2.8)
react: 19.2.8
tslib: 2.8.1
'@dnd-kit/utilities@3.2.2(react@19.2.8)':
dependencies:
react: 19.2.8
tslib: 2.8.1
'@emotion/hash@0.8.0': {} '@emotion/hash@0.8.0': {}
'@emotion/unitless@0.7.5': {} '@emotion/unitless@0.7.5': {}
...@@ -3201,7 +3185,7 @@ snapshots: ...@@ -3201,7 +3185,7 @@ snapshots:
'@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/sourcemap-codec': 1.5.5
optional: true optional: true
'@oxc-project/types@0.144.0': {} '@oxc-project/types@0.153.0': {}
'@oxfmt/binding-android-arm-eabi@0.64.0': '@oxfmt/binding-android-arm-eabi@0.64.0':
optional: true optional: true
...@@ -3321,15 +3305,6 @@ snapshots: ...@@ -3321,15 +3305,6 @@ snapshots:
dependencies: dependencies:
'@babel/runtime': 7.29.7 '@babel/runtime': 7.29.7
'@rc-component/cascader@1.17.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/select': 1.8.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/tree': 1.3.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
'@rc-component/cascader@1.22.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/cascader@1.22.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/select': 1.10.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rc-component/select': 1.10.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
...@@ -3395,14 +3370,6 @@ snapshots: ...@@ -3395,14 +3370,6 @@ snapshots:
react: 19.2.8 react: 19.2.8
react-dom: 19.2.8(react@19.2.8) react-dom: 19.2.8(react@19.2.8)
'@rc-component/form@1.8.5(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/async-validator': 6.0.0
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
'@rc-component/form@1.8.6(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/form@1.8.6(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/async-validator': 6.0.0 '@rc-component/async-validator': 6.0.0
...@@ -3420,15 +3387,6 @@ snapshots: ...@@ -3420,15 +3387,6 @@ snapshots:
react: 19.2.8 react: 19.2.8
react-dom: 19.2.8(react@19.2.8) react-dom: 19.2.8(react@19.2.8)
'@rc-component/image@1.9.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/motion': 1.3.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/portal': 2.2.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
'@rc-component/input-number@1.6.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/input-number@1.6.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/mini-decimal': 1.1.4 '@rc-component/mini-decimal': 1.1.4
...@@ -3456,16 +3414,6 @@ snapshots: ...@@ -3456,16 +3414,6 @@ snapshots:
react: 19.2.8 react: 19.2.8
react-dom: 19.2.8(react@19.2.8) react-dom: 19.2.8(react@19.2.8)
'@rc-component/mentions@1.10.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/input': 1.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/menu': 1.4.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/trigger': 3.10.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
'@rc-component/mentions@1.11.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/mentions@1.11.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/input': 1.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rc-component/input': 1.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
...@@ -3527,18 +3475,6 @@ snapshots: ...@@ -3527,18 +3475,6 @@ snapshots:
react: 19.2.8 react: 19.2.8
react-dom: 19.2.8(react@19.2.8) react-dom: 19.2.8(react@19.2.8)
'@rc-component/picker@1.11.0(dayjs@1.11.21)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/overflow': 1.0.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/resize-observer': 1.1.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/trigger': 3.10.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
optionalDependencies:
dayjs: 1.11.21
'@rc-component/picker@1.12.0(dayjs@1.11.21)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/picker@1.12.0(dayjs@1.11.21)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/overflow': 1.0.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rc-component/overflow': 1.0.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
...@@ -3603,16 +3539,6 @@ snapshots: ...@@ -3603,16 +3539,6 @@ snapshots:
react: 19.2.8 react: 19.2.8
react-dom: 19.2.8(react@19.2.8) react-dom: 19.2.8(react@19.2.8)
'@rc-component/select@1.8.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/overflow': 1.0.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/trigger': 3.10.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/virtual-list': 1.4.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
'@rc-component/slider@1.1.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/slider@1.1.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
...@@ -3634,16 +3560,6 @@ snapshots: ...@@ -3634,16 +3560,6 @@ snapshots:
react: 19.2.8 react: 19.2.8
react-dom: 19.2.8(react@19.2.8) react-dom: 19.2.8(react@19.2.8)
'@rc-component/table@1.10.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/context': 2.0.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/resize-observer': 1.1.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/virtual-list': 1.4.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
'@rc-component/table@1.11.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/table@1.11.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/context': 2.0.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rc-component/context': 2.0.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
...@@ -3654,17 +3570,6 @@ snapshots: ...@@ -3654,17 +3570,6 @@ snapshots:
react: 19.2.8 react: 19.2.8
react-dom: 19.2.8(react@19.2.8) react-dom: 19.2.8(react@19.2.8)
'@rc-component/tabs@1.11.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/dropdown': 1.0.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/menu': 1.4.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/motion': 1.3.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/resize-observer': 1.1.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
'@rc-component/tabs@1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/tabs@1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/dropdown': 1.0.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rc-component/dropdown': 1.0.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
...@@ -3676,14 +3581,6 @@ snapshots: ...@@ -3676,14 +3581,6 @@ snapshots:
react: 19.2.8 react: 19.2.8
react-dom: 19.2.8(react@19.2.8) react-dom: 19.2.8(react@19.2.8)
'@rc-component/tooltip@1.4.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/trigger': 3.10.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
'@rc-component/tooltip@1.5.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/tooltip@1.5.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/trigger': 3.10.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rc-component/trigger': 3.10.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
...@@ -3701,15 +3598,6 @@ snapshots: ...@@ -3701,15 +3598,6 @@ snapshots:
react: 19.2.8 react: 19.2.8
react-dom: 19.2.8(react@19.2.8) react-dom: 19.2.8(react@19.2.8)
'@rc-component/tree-select@1.11.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/select': 1.8.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/tree': 1.3.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
'@rc-component/tree-select@1.16.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/tree-select@1.16.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/select': 1.10.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rc-component/select': 1.10.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
...@@ -3719,15 +3607,6 @@ snapshots: ...@@ -3719,15 +3607,6 @@ snapshots:
react: 19.2.8 react: 19.2.8
react-dom: 19.2.8(react@19.2.8) react-dom: 19.2.8(react@19.2.8)
'@rc-component/tree@1.3.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
'@rc-component/motion': 1.3.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/virtual-list': 1.4.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
'@rc-component/tree@1.4.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': '@rc-component/tree@1.4.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies: dependencies:
'@rc-component/motion': 1.3.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@rc-component/motion': 1.3.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
...@@ -3784,46 +3663,49 @@ snapshots: ...@@ -3784,46 +3663,49 @@ snapshots:
dependencies: dependencies:
react: 19.2.8 react: 19.2.8
'@rolldown/binding-android-arm64@1.2.4': '@rolldown/binding-android-arm-eabi@1.2.13':
optional: true
'@rolldown/binding-android-arm64@1.2.13':
optional: true optional: true
'@rolldown/binding-darwin-arm64@1.2.4': '@rolldown/binding-darwin-arm64@1.2.13':
optional: true optional: true
'@rolldown/binding-darwin-x64@1.2.4': '@rolldown/binding-darwin-x64@1.2.13':
optional: true optional: true
'@rolldown/binding-freebsd-x64@1.2.4': '@rolldown/binding-freebsd-x64@1.2.13':
optional: true optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.2.4': '@rolldown/binding-linux-arm-gnueabihf@1.2.13':
optional: true optional: true
'@rolldown/binding-linux-arm64-gnu@1.2.4': '@rolldown/binding-linux-arm64-gnu@1.2.13':
optional: true optional: true
'@rolldown/binding-linux-arm64-musl@1.2.4': '@rolldown/binding-linux-arm64-musl@1.2.13':
optional: true optional: true
'@rolldown/binding-linux-ppc64-gnu@1.2.4': '@rolldown/binding-linux-ppc64-gnu@1.2.13':
optional: true optional: true
'@rolldown/binding-linux-s390x-gnu@1.2.4': '@rolldown/binding-linux-s390x-gnu@1.2.13':
optional: true optional: true
'@rolldown/binding-linux-x64-gnu@1.2.4': '@rolldown/binding-linux-x64-gnu@1.2.13':
optional: true optional: true
'@rolldown/binding-linux-x64-musl@1.2.4': '@rolldown/binding-linux-x64-musl@1.2.13':
optional: true optional: true
'@rolldown/binding-openharmony-arm64@1.2.4': '@rolldown/binding-openharmony-arm64@1.2.13':
optional: true optional: true
'@rolldown/binding-win32-arm64-msvc@1.2.4': '@rolldown/binding-win32-arm64-msvc@1.2.13':
optional: true optional: true
'@rolldown/binding-win32-x64-msvc@1.2.4': '@rolldown/binding-win32-x64-msvc@1.2.13':
optional: true optional: true
'@rolldown/pluginutils@1.0.1': {} '@rolldown/pluginutils@1.0.1': {}
...@@ -3993,10 +3875,10 @@ snapshots: ...@@ -3993,10 +3875,10 @@ snapshots:
'@uppy/utils': 4.1.3 '@uppy/utils': 4.1.3
nanoid: 3.3.18 nanoid: 3.3.18
'@vitejs/plugin-react@6.0.5(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))': '@vitejs/plugin-react@6.0.5(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))':
dependencies: dependencies:
'@rolldown/pluginutils': 1.0.1 '@rolldown/pluginutils': 1.0.1
vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) vite: 8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
'@vitest/expect@4.1.10': '@vitest/expect@4.1.10':
dependencies: dependencies:
...@@ -4007,13 +3889,13 @@ snapshots: ...@@ -4007,13 +3889,13 @@ snapshots:
chai: 6.2.2 chai: 6.2.2
tinyrainbow: 3.1.0 tinyrainbow: 3.1.0
'@vitest/mocker@4.1.10(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))': '@vitest/mocker@4.1.10(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))':
dependencies: dependencies:
'@vitest/spy': 4.1.10 '@vitest/spy': 4.1.10
estree-walker: 3.0.3 estree-walker: 3.0.3
magic-string: 0.30.21 magic-string: 0.30.21
optionalDependencies: optionalDependencies:
vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) vite: 8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
'@vitest/pretty-format@4.1.10': '@vitest/pretty-format@4.1.10':
dependencies: dependencies:
...@@ -4218,62 +4100,6 @@ snapshots: ...@@ -4218,62 +4100,6 @@ snapshots:
ansi-styles@5.2.0: {} ansi-styles@5.2.0: {}
antd@6.5.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
dependencies:
'@ant-design/colors': 8.0.1
'@ant-design/cssinjs': 2.1.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@ant-design/cssinjs-utils': 2.1.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@ant-design/fast-color': 3.0.1
'@ant-design/icons': 6.3.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@ant-design/react-slick': 2.0.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@babel/runtime': 7.29.7
'@rc-component/cascader': 1.17.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/checkbox': 2.0.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/collapse': 1.2.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/color-picker': 3.1.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/dialog': 1.10.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/drawer': 1.4.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/dropdown': 1.0.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/form': 1.8.5(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/image': 1.9.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/input': 1.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/input-number': 1.6.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/mentions': 1.10.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/menu': 1.4.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/motion': 1.3.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/mutate-observer': 2.0.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/notification': 2.0.7(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/pagination': 1.4.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/picker': 1.11.0(dayjs@1.11.21)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/progress': 1.0.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/qrcode': 2.0.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/rate': 1.0.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/resize-observer': 1.1.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/segmented': 1.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/select': 1.8.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/slider': 1.1.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/steps': 1.2.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/switch': 1.0.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/table': 1.10.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/tabs': 1.11.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/tooltip': 1.4.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/tour': 2.4.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/tree': 1.3.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/tree-select': 1.11.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/trigger': 3.10.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/upload': 1.1.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@rc-component/util': 1.12.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
clsx: 2.1.1
dayjs: 1.11.21
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
scroll-into-view-if-needed: 3.1.0
throttle-debounce: 5.0.2
transitivePeerDependencies:
- date-fns
- luxon
- moment
antd@6.6.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8): antd@6.6.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
dependencies: dependencies:
'@ant-design/colors': 8.0.1 '@ant-design/colors': 8.0.1
...@@ -4951,6 +4777,8 @@ snapshots: ...@@ -4951,6 +4777,8 @@ snapshots:
nanoid@3.3.18: {} nanoid@3.3.18: {}
nanoid@3.3.20: {}
needle@3.5.0: needle@3.5.0:
dependencies: dependencies:
iconv-lite: 0.6.3 iconv-lite: 0.6.3
...@@ -5050,13 +4878,15 @@ snapshots: ...@@ -5050,13 +4878,15 @@ snapshots:
picomatch@4.0.5: {} picomatch@4.0.5: {}
picomatch@4.0.7: {}
platform@1.3.6: {} platform@1.3.6: {}
postcss@8.5.26: postcss@8.5.29:
dependencies: dependencies:
nanoid: 3.3.18 nanoid: 3.3.20
picocolors: 1.1.1 picocolors: 1.1.1
source-map-js: 1.2.1 source-map-js: 1.2.2
preact@10.29.7: {} preact@10.29.7: {}
...@@ -5165,25 +4995,26 @@ snapshots: ...@@ -5165,25 +4995,26 @@ snapshots:
resize-observer-polyfill@1.5.1: {} resize-observer-polyfill@1.5.1: {}
rolldown@1.2.4: rolldown@1.2.13:
dependencies: dependencies:
'@oxc-project/types': 0.144.0 '@oxc-project/types': 0.153.0
'@rolldown/pluginutils': 1.0.1 '@rolldown/pluginutils': 1.0.1
optionalDependencies: optionalDependencies:
'@rolldown/binding-android-arm64': 1.2.4 '@rolldown/binding-android-arm-eabi': 1.2.13
'@rolldown/binding-darwin-arm64': 1.2.4 '@rolldown/binding-android-arm64': 1.2.13
'@rolldown/binding-darwin-x64': 1.2.4 '@rolldown/binding-darwin-arm64': 1.2.13
'@rolldown/binding-freebsd-x64': 1.2.4 '@rolldown/binding-darwin-x64': 1.2.13
'@rolldown/binding-linux-arm-gnueabihf': 1.2.4 '@rolldown/binding-freebsd-x64': 1.2.13
'@rolldown/binding-linux-arm64-gnu': 1.2.4 '@rolldown/binding-linux-arm-gnueabihf': 1.2.13
'@rolldown/binding-linux-arm64-musl': 1.2.4 '@rolldown/binding-linux-arm64-gnu': 1.2.13
'@rolldown/binding-linux-ppc64-gnu': 1.2.4 '@rolldown/binding-linux-arm64-musl': 1.2.13
'@rolldown/binding-linux-s390x-gnu': 1.2.4 '@rolldown/binding-linux-ppc64-gnu': 1.2.13
'@rolldown/binding-linux-x64-gnu': 1.2.4 '@rolldown/binding-linux-s390x-gnu': 1.2.13
'@rolldown/binding-linux-x64-musl': 1.2.4 '@rolldown/binding-linux-x64-gnu': 1.2.13
'@rolldown/binding-openharmony-arm64': 1.2.4 '@rolldown/binding-linux-x64-musl': 1.2.13
'@rolldown/binding-win32-arm64-msvc': 1.2.4 '@rolldown/binding-openharmony-arm64': 1.2.13
'@rolldown/binding-win32-x64-msvc': 1.2.4 '@rolldown/binding-win32-arm64-msvc': 1.2.13
'@rolldown/binding-win32-x64-msvc': 1.2.13
rtl-css-js@1.16.1: rtl-css-js@1.16.1:
dependencies: dependencies:
...@@ -5266,6 +5097,8 @@ snapshots: ...@@ -5266,6 +5097,8 @@ snapshots:
source-map-js@1.2.1: {} source-map-js@1.2.1: {}
source-map-js@1.2.2: {}
source-map-support@0.5.21: source-map-support@0.5.21:
dependencies: dependencies:
buffer-from: 1.1.2 buffer-from: 1.1.2
...@@ -5454,19 +5287,19 @@ snapshots: ...@@ -5454,19 +5287,19 @@ snapshots:
mz: 2.7.0 mz: 2.7.0
unescape: 1.0.1 unescape: 1.0.1
vite-plugin-mkcert@2.1.0(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)): vite-plugin-mkcert@2.1.0(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)):
dependencies: dependencies:
debug: 4.4.3(supports-color@10.2.2) debug: 4.4.3(supports-color@10.2.2)
supports-color: 10.2.2 supports-color: 10.2.2
undici: 8.10.0 undici: 8.10.0
vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) vite: 8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0): vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0):
dependencies: dependencies:
lightningcss: 1.33.0 lightningcss: 1.33.0
picomatch: 4.0.5 picomatch: 4.0.7
postcss: 8.5.26 postcss: 8.5.29
rolldown: 1.2.4 rolldown: 1.2.13
tinyglobby: 0.2.17 tinyglobby: 0.2.17
optionalDependencies: optionalDependencies:
'@types/node': 22.20.1 '@types/node': 22.20.1
...@@ -5475,10 +5308,10 @@ snapshots: ...@@ -5475,10 +5308,10 @@ snapshots:
less: 4.6.7 less: 4.6.7
terser: 5.49.0 terser: 5.49.0
vitest@4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)): vitest@4.1.10(@types/node@22.20.1)(jsdom@29.1.1)(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)):
dependencies: dependencies:
'@vitest/expect': 4.1.10 '@vitest/expect': 4.1.10
'@vitest/mocker': 4.1.10(vite@8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)) '@vitest/mocker': 4.1.10(vite@8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0))
'@vitest/pretty-format': 4.1.10 '@vitest/pretty-format': 4.1.10
'@vitest/runner': 4.1.10 '@vitest/runner': 4.1.10
'@vitest/snapshot': 4.1.10 '@vitest/snapshot': 4.1.10
...@@ -5495,7 +5328,7 @@ snapshots: ...@@ -5495,7 +5328,7 @@ snapshots:
tinyexec: 1.2.4 tinyexec: 1.2.4
tinyglobby: 0.2.17 tinyglobby: 0.2.17
tinyrainbow: 3.1.0 tinyrainbow: 3.1.0
vite: 8.2.2(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0) vite: 8.3.4(@types/node@22.20.1)(esbuild@0.28.1)(less@4.6.7)(terser@5.49.0)
why-is-node-running: 2.3.0 why-is-node-running: 2.3.0
optionalDependencies: optionalDependencies:
'@types/node': 22.20.1 '@types/node': 22.20.1
......
...@@ -7,4 +7,4 @@ allowBuilds: ...@@ -7,4 +7,4 @@ allowBuilds:
esbuild: true esbuild: true
minimumReleaseAgeExclude: minimumReleaseAgeExclude:
- vite@8.2.2 - vite@8.3.4
# center-book # center-book
清控紫荆数字教材前端 Monorepo,包含管理端和 PC 学习端两个独立应用。 清控紫荆数字教材前端 Monorepo,包含管理端和 Web 端两个独立应用。
## 应用 ## 应用
- `apps/admin`:管理端,React 19、JavaScript/JSX、Ant Design 6,构建到 `dist/admin`。 - `apps/admin`:管理端,React 19、JavaScript/JSX、Ant Design 6,构建到 `dist/admin`。
- `apps/learning`:学习端,React 19、TypeScript、React Query、nuqs、Ant Design 6,构建到 `dist/learning`。 - `apps/web`:Web 端,React 19、TypeScript、React Query、nuqs、Ant Design 6,构建到 `dist/web`。
两个应用拥有独立的路由、状态、API 客户端和构建产物,不直接引用对方的 `src`。 两个应用拥有独立的路由、状态、API 客户端和构建产物,不直接引用对方的 `src`。
...@@ -15,11 +15,11 @@ ...@@ -15,11 +15,11 @@
pnpm install pnpm install
pnpm dev pnpm dev
pnpm dev:admin pnpm dev:admin
pnpm dev:learning pnpm dev:web
pnpm test pnpm test
pnpm lint:check pnpm lint:check
pnpm typecheck:learning pnpm typecheck:web
pnpm build pnpm build
``` ```
管理端在 `/admin/` 部署,学习端在 `/` 部署。后续模块代码请遵循 [AGENTS.md](./AGENTS.md) 中的目录、请求、状态和测试约定。 管理端在 `/admin/` 部署,Web 端在 `/` 部署。后续模块代码请遵循 [AGENTS.md](./AGENTS.md) 中的目录、请求、状态和测试约定。
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论