feat(attraction): 实现景点和分类管理功能
- 新增景点分页查询接口和按ID查询功能 - 完善景点分类树形结构管理和父子分类关联 - 优化景点管理页面实现分页、搜索和表格展示 - 添加景点分类层级显示和树形选择器组件 - 集成富文本编辑器用于景点详情内容编辑 - 重构API调用方式统一使用RESTful风格接口 - 更新数据库配置添加MyBatis日志输出支持 - 调整开发环境配置密码和日志级别设置
This commit is contained in:
parent
47106d88c8
commit
3e72c5b6c7
|
|
@ -0,0 +1,111 @@
|
|||
# AGENTS.md — Tourism Promotion Management System
|
||||
|
||||
> 旅游宣传管理系统 — 毕业设计项目. Full-stack tourism platform with admin dashboard and user-facing web app.
|
||||
|
||||
## Project Structure
|
||||
|
||||
Three independent subsystems in one repo (not a monorepo with shared packages):
|
||||
|
||||
| Directory | Stack | Dev Port | UI Framework |
|
||||
|-----------|-------|----------|--------------|
|
||||
| `tourism-server/` | SpringBoot 4.0.6 + JDK 21 | 8080 | — |
|
||||
| `tourism-admin/` | Vue 3.5 + Vite 6 + TS 5.7 | 3000 | **Ant Design Vue 4** |
|
||||
| `tourism-web/` | Vue 3.5 + Vite 6 + TS 5.7 | 3001 | **Element Plus 2.9** |
|
||||
|
||||
**Critical**: `tourism-admin` and `tourism-web` use **different UI frameworks**. Do not swap components between them.
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Backend (`tourism-server/`)
|
||||
```bash
|
||||
mvn install -DskipTests
|
||||
mvn spring-boot:run
|
||||
```
|
||||
- Main class: `com.tourism.TourismApplication`
|
||||
- Application config: `application.yml` + `application-dev.yml`
|
||||
- Active profile: `dev`
|
||||
- Maven uses Aliyun + HuaweiCloud + Spring Milestones/Snapshots repositories
|
||||
|
||||
### Admin Frontend (`tourism-admin/`)
|
||||
```bash
|
||||
pnpm install # packageManager is pnpm@10.23.0
|
||||
pnpm dev # port 3000
|
||||
```
|
||||
- Uses **pnpm** (not npm/yarn). `packageManager` field enforces this.
|
||||
- Build: `pnpm build` (runs `vue-tsc -b && vite build`)
|
||||
- Lint: `pnpm lint` (eslint with .vue,.ts extensions)
|
||||
|
||||
### Web Frontend (`tourism-web/`)
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm dev # port 3001
|
||||
```
|
||||
- Build: `pnpm build` (runs `vue-tsc -b && vite build`)
|
||||
- No lint script configured
|
||||
|
||||
## API & Auth
|
||||
|
||||
- Both frontends proxy `/api` to `http://localhost:8080`
|
||||
- Auth: **Sa-Token** (v1.45.0). Token sent in `token` header (not `Authorization`)
|
||||
- Admin login mock: username `admin` / password `123456`
|
||||
- Backend response format: `{ code: 200, msg: "...", data: ... }`
|
||||
- 401 unauthenticated → redirect to login page
|
||||
|
||||
## Backend Architecture
|
||||
|
||||
- Package root: `com.tourism`
|
||||
- Modules by domain: `user/`, `attraction/`, `product/`, `order/`, `travel/`, `admin/`, `payment/`, `file/`, `common/`
|
||||
- Each module: `entity/`, `mapper/`, `service/`, `service/impl/`, `controller/`, `dto/`
|
||||
- ORM: MyBatis-Plus 3.5.15 with logical delete (`isDeleted` field, 0=not deleted, 1=deleted)
|
||||
- DB: MySQL 8.0 (`tourism_platform`), init script: `tourism_platform.sql` at repo root
|
||||
- Passwords encrypted with `spring-security-crypto` (BCrypt)
|
||||
- File storage: RustFS (configured in `application.yml`)
|
||||
- Payment: Alipay sandbox SDK
|
||||
- JSON: Fastjson2
|
||||
- DTO mapping: MapStruct 1.6.3 + Lombok (both require annotation processor in Maven)
|
||||
- API docs: Knife4j (Swagger UI alternative), available when server runs
|
||||
|
||||
## Database Setup
|
||||
|
||||
```bash
|
||||
mysql -u root -p < tourism_platform.sql
|
||||
```
|
||||
|
||||
Default credentials (override in `application-dev.yml`):
|
||||
- URL: `jdbc:mysql://localhost:3306/tourism_platform`
|
||||
- Username: `root`
|
||||
- Password: `root` (in base config), `123456` (in dev profile)
|
||||
|
||||
## Frontend Architecture
|
||||
|
||||
### tourism-admin
|
||||
- Entry: `src/main.ts`
|
||||
- Router: `src/router/index.ts` (all routes in one file)
|
||||
- State: Pinia (`stores/user.ts`, `stores/app.ts`)
|
||||
- Icons: `@ant-design/icons-vue` (all registered globally)
|
||||
- Charts: ECharts + vue-echarts
|
||||
- **MockJS**: `src/mock/index.ts` provides mock data for all admin APIs. Imported in `main.ts`.
|
||||
- Styles: SCSS (`src/assets/styles/index.scss`)
|
||||
|
||||
### tourism-web
|
||||
- Entry: `src/main.ts`
|
||||
- Router: `src/router/index.ts`
|
||||
- State: Pinia (`stores/user.ts`, `stores/cart.ts`)
|
||||
- Icons: `@element-plus/icons-vue`
|
||||
- Styles: SCSS (`src/assets/styles/index.scss`)
|
||||
|
||||
## Design Systems
|
||||
|
||||
Design specs are in `design-system/` directory:
|
||||
- `design-system/tourism-admin/MASTER.md` — Purple theme (#7C3AED), Fira Code/Sans, data-dense dashboard style
|
||||
- `design-system/tourism-web/MASTER.md` — Sky blue theme (#0EA5E9), Noto Sans Thai, motion-driven storytelling style
|
||||
|
||||
## Important Notes
|
||||
|
||||
- **No tests exist** in any subsystem. Add tests if required.
|
||||
- **No CI/CD** configured.
|
||||
- Both frontends use `noUnusedLocals: false` and `noUnusedParameters: false` in tsconfig.
|
||||
- Admin uses `unplugin-auto-import` and `unplugin-vue-components` (auto-import Vue APIs and components).
|
||||
- All `@/` aliases resolve to `src/`.
|
||||
- `tourism_platform.sql` at repo root is the single source of truth for database schema.
|
||||
- This is a graduation project (毕业设计). Code may be simplified; prioritize clarity and functionality over enterprise patterns.
|
||||
|
|
@ -11,6 +11,8 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"ant-design-vue": "^4.2.6",
|
||||
"axios": "^1.7.0",
|
||||
"dayjs": "^1.11.0",
|
||||
|
|
@ -30,5 +32,6 @@
|
|||
"unplugin-vue-components": "^32.1.0",
|
||||
"vite": "^6.1.0",
|
||||
"vue-tsc": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"packageManager": "pnpm@10.23.0+sha512.21c4e5698002ade97e4efe8b8b4a89a8de3c85a37919f957e7a0f30f38fbc5bbdd05980ffe29179b2fb6e6e691242e098d945d1601772cad0fef5fb6411e2a4b"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ importers:
|
|||
'@ant-design/icons-vue':
|
||||
specifier: ^7.0.1
|
||||
version: 7.0.1(vue@3.5.34(typescript@5.7.3))
|
||||
'@wangeditor/editor':
|
||||
specifier: ^5.1.23
|
||||
version: 5.1.23
|
||||
'@wangeditor/editor-for-vue':
|
||||
specifier: ^5.1.12
|
||||
version: 5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.34(typescript@5.7.3))
|
||||
ant-design-vue:
|
||||
specifier: ^4.2.6
|
||||
version: 4.2.6(vue@3.5.34(typescript@5.7.3))
|
||||
|
|
@ -309,42 +315,36 @@ packages:
|
|||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.6':
|
||||
resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.6':
|
||||
resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.6':
|
||||
resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.6':
|
||||
resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.6':
|
||||
resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.6':
|
||||
resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==}
|
||||
|
|
@ -402,79 +402,66 @@ packages:
|
|||
resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.60.4':
|
||||
resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.60.4':
|
||||
resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-loong64-musl@4.60.4':
|
||||
resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-musl@4.60.4':
|
||||
resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.60.4':
|
||||
resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.60.4':
|
||||
resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.60.4':
|
||||
resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-openbsd-x64@4.60.4':
|
||||
resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==}
|
||||
|
|
@ -509,12 +496,35 @@ packages:
|
|||
'@simonwep/pickr@1.8.2':
|
||||
resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==}
|
||||
|
||||
'@transloadit/prettier-bytes@0.0.7':
|
||||
resolution: {integrity: sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==}
|
||||
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
|
||||
'@types/event-emitter@0.3.5':
|
||||
resolution: {integrity: sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==}
|
||||
|
||||
'@types/node@25.9.1':
|
||||
resolution: {integrity: sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==}
|
||||
|
||||
'@uppy/companion-client@2.2.2':
|
||||
resolution: {integrity: sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==}
|
||||
|
||||
'@uppy/core@2.3.4':
|
||||
resolution: {integrity: sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==}
|
||||
|
||||
'@uppy/store-default@2.1.1':
|
||||
resolution: {integrity: sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==}
|
||||
|
||||
'@uppy/utils@4.1.3':
|
||||
resolution: {integrity: sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==}
|
||||
|
||||
'@uppy/xhr-upload@2.1.3':
|
||||
resolution: {integrity: sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==}
|
||||
peerDependencies:
|
||||
'@uppy/core': ^2.3.3
|
||||
|
||||
'@vitejs/plugin-vue@5.2.4':
|
||||
resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
|
|
@ -574,6 +584,93 @@ packages:
|
|||
'@vue/shared@3.5.34':
|
||||
resolution: {integrity: sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==}
|
||||
|
||||
'@wangeditor/basic-modules@1.1.7':
|
||||
resolution: {integrity: sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==}
|
||||
peerDependencies:
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
lodash.throttle: ^4.1.1
|
||||
nanoid: ^3.2.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/code-highlight@1.0.3':
|
||||
resolution: {integrity: sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==}
|
||||
peerDependencies:
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/core@1.1.19':
|
||||
resolution: {integrity: sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==}
|
||||
peerDependencies:
|
||||
'@uppy/core': ^2.1.1
|
||||
'@uppy/xhr-upload': ^2.0.3
|
||||
dom7: ^3.0.0
|
||||
is-hotkey: ^0.2.0
|
||||
lodash.camelcase: ^4.3.0
|
||||
lodash.clonedeep: ^4.5.0
|
||||
lodash.debounce: ^4.0.8
|
||||
lodash.foreach: ^4.5.0
|
||||
lodash.isequal: ^4.5.0
|
||||
lodash.throttle: ^4.1.1
|
||||
lodash.toarray: ^4.4.0
|
||||
nanoid: ^3.2.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/editor-for-vue@5.1.12':
|
||||
resolution: {integrity: sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==}
|
||||
peerDependencies:
|
||||
'@wangeditor/editor': '>=5.1.0'
|
||||
vue: ^3.0.5
|
||||
|
||||
'@wangeditor/editor@5.1.23':
|
||||
resolution: {integrity: sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==}
|
||||
|
||||
'@wangeditor/list-module@1.0.5':
|
||||
resolution: {integrity: sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==}
|
||||
peerDependencies:
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/table-module@1.1.4':
|
||||
resolution: {integrity: sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==}
|
||||
peerDependencies:
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
lodash.isequal: ^4.5.0
|
||||
lodash.throttle: ^4.1.1
|
||||
nanoid: ^3.2.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/upload-image-module@1.0.2':
|
||||
resolution: {integrity: sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==}
|
||||
peerDependencies:
|
||||
'@uppy/core': ^2.0.3
|
||||
'@uppy/xhr-upload': ^2.0.3
|
||||
'@wangeditor/basic-modules': 1.x
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
lodash.foreach: ^4.5.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
'@wangeditor/video-module@1.1.4':
|
||||
resolution: {integrity: sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==}
|
||||
peerDependencies:
|
||||
'@uppy/core': ^2.1.4
|
||||
'@uppy/xhr-upload': ^2.0.7
|
||||
'@wangeditor/core': 1.x
|
||||
dom7: ^3.0.0
|
||||
nanoid: ^3.2.0
|
||||
slate: ^0.72.0
|
||||
snabbdom: ^3.1.0
|
||||
|
||||
acorn@8.16.0:
|
||||
resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
|
@ -641,6 +738,10 @@ packages:
|
|||
csstype@3.2.3:
|
||||
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
|
||||
|
||||
d@1.0.2:
|
||||
resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
dayjs@1.11.21:
|
||||
resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==}
|
||||
|
||||
|
|
@ -670,6 +771,9 @@ packages:
|
|||
dom-scroll-into-view@2.0.1:
|
||||
resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==}
|
||||
|
||||
dom7@3.0.0:
|
||||
resolution: {integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -697,6 +801,17 @@ packages:
|
|||
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es5-ext@0.10.64:
|
||||
resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
es6-iterator@2.0.3:
|
||||
resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
|
||||
|
||||
es6-symbol@3.1.4:
|
||||
resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
esbuild@0.25.12:
|
||||
resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -706,15 +821,25 @@ packages:
|
|||
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
esniff@2.0.1:
|
||||
resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
estree-walker@2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
|
||||
estree-walker@3.0.3:
|
||||
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
|
||||
|
||||
event-emitter@0.3.5:
|
||||
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
|
||||
|
||||
exsolve@1.0.8:
|
||||
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
|
||||
|
||||
ext@1.7.0:
|
||||
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
|
||||
|
||||
fdir@6.5.0:
|
||||
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
|
@ -773,10 +898,19 @@ packages:
|
|||
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
|
||||
hasBin: true
|
||||
|
||||
html-void-elements@2.0.1:
|
||||
resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==}
|
||||
|
||||
https-proxy-agent@5.0.1:
|
||||
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
i18next@20.6.1:
|
||||
resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==}
|
||||
|
||||
immer@9.0.21:
|
||||
resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
|
||||
|
||||
immutable@5.1.5:
|
||||
resolution: {integrity: sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==}
|
||||
|
||||
|
|
@ -788,10 +922,20 @@ packages:
|
|||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-hotkey@0.2.0:
|
||||
resolution: {integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==}
|
||||
|
||||
is-plain-object@3.0.1:
|
||||
resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-plain-object@5.0.0:
|
||||
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-url@1.2.4:
|
||||
resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==}
|
||||
|
||||
js-tokens@4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
|
||||
|
|
@ -805,6 +949,28 @@ packages:
|
|||
lodash-es@4.18.1:
|
||||
resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
|
||||
|
||||
lodash.camelcase@4.3.0:
|
||||
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
|
||||
|
||||
lodash.clonedeep@4.5.0:
|
||||
resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==}
|
||||
|
||||
lodash.debounce@4.0.8:
|
||||
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
|
||||
|
||||
lodash.foreach@4.5.0:
|
||||
resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==}
|
||||
|
||||
lodash.isequal@4.5.0:
|
||||
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
|
||||
deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead.
|
||||
|
||||
lodash.throttle@4.1.1:
|
||||
resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
|
||||
|
||||
lodash.toarray@4.4.0:
|
||||
resolution: {integrity: sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==}
|
||||
|
||||
lodash@4.18.1:
|
||||
resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
|
||||
|
||||
|
|
@ -823,6 +989,9 @@ packages:
|
|||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime-match@1.0.2:
|
||||
resolution: {integrity: sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==}
|
||||
|
||||
mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
|
@ -844,6 +1013,9 @@ packages:
|
|||
muggle-string@0.4.1:
|
||||
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
|
||||
|
||||
namespace-emitter@2.0.1:
|
||||
resolution: {integrity: sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==}
|
||||
|
||||
nanoid@3.3.12:
|
||||
resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
|
|
@ -852,6 +1024,9 @@ packages:
|
|||
nanopop@2.4.2:
|
||||
resolution: {integrity: sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==}
|
||||
|
||||
next-tick@1.1.0:
|
||||
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||
|
||||
|
|
@ -890,6 +1065,13 @@ packages:
|
|||
resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
preact@10.29.2:
|
||||
resolution: {integrity: sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==}
|
||||
|
||||
prismjs@1.30.0:
|
||||
resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
proxy-from-env@2.1.0:
|
||||
resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==}
|
||||
engines: {node: '>=10'}
|
||||
|
|
@ -923,10 +1105,25 @@ packages:
|
|||
shallow-equal@1.2.1:
|
||||
resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==}
|
||||
|
||||
slate-history@0.66.0:
|
||||
resolution: {integrity: sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==}
|
||||
peerDependencies:
|
||||
slate: '>=0.65.3'
|
||||
|
||||
slate@0.72.8:
|
||||
resolution: {integrity: sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==}
|
||||
|
||||
snabbdom@3.6.3:
|
||||
resolution: {integrity: sha512-W2lHLLw2qR2Vv0DcMmcxXqcfdBaIcoN+y/86SmHv8fn4DazEQSH6KN3TjZcWvwujW56OHiiirsbHWZb4vx/0fg==}
|
||||
engines: {node: '>=12.17.0'}
|
||||
|
||||
source-map-js@1.2.1:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
ssr-window@3.0.0:
|
||||
resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==}
|
||||
|
||||
strip-literal@3.1.0:
|
||||
resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
|
||||
|
||||
|
|
@ -937,6 +1134,9 @@ packages:
|
|||
resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==}
|
||||
engines: {node: '>=12.22'}
|
||||
|
||||
tiny-warning@1.0.3:
|
||||
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
||||
|
||||
tinyglobby@0.2.16:
|
||||
resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
|
@ -944,6 +1144,9 @@ packages:
|
|||
tslib@2.3.0:
|
||||
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
|
||||
|
||||
type@2.7.3:
|
||||
resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==}
|
||||
|
||||
typescript@5.7.3:
|
||||
resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==}
|
||||
engines: {node: '>=14.17'}
|
||||
|
|
@ -1099,6 +1302,9 @@ packages:
|
|||
webpack-virtual-modules@0.6.2:
|
||||
resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
|
||||
|
||||
wildcard@1.1.2:
|
||||
resolution: {integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==}
|
||||
|
||||
zrender@5.6.1:
|
||||
resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==}
|
||||
|
||||
|
|
@ -1375,12 +1581,45 @@ snapshots:
|
|||
core-js: 3.49.0
|
||||
nanopop: 2.4.2
|
||||
|
||||
'@transloadit/prettier-bytes@0.0.7': {}
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
'@types/event-emitter@0.3.5': {}
|
||||
|
||||
'@types/node@25.9.1':
|
||||
dependencies:
|
||||
undici-types: 7.24.6
|
||||
|
||||
'@uppy/companion-client@2.2.2':
|
||||
dependencies:
|
||||
'@uppy/utils': 4.1.3
|
||||
namespace-emitter: 2.0.1
|
||||
|
||||
'@uppy/core@2.3.4':
|
||||
dependencies:
|
||||
'@transloadit/prettier-bytes': 0.0.7
|
||||
'@uppy/store-default': 2.1.1
|
||||
'@uppy/utils': 4.1.3
|
||||
lodash.throttle: 4.1.1
|
||||
mime-match: 1.0.2
|
||||
namespace-emitter: 2.0.1
|
||||
nanoid: 3.3.12
|
||||
preact: 10.29.2
|
||||
|
||||
'@uppy/store-default@2.1.1': {}
|
||||
|
||||
'@uppy/utils@4.1.3':
|
||||
dependencies:
|
||||
lodash.throttle: 4.1.1
|
||||
|
||||
'@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4)':
|
||||
dependencies:
|
||||
'@uppy/companion-client': 2.2.2
|
||||
'@uppy/core': 2.3.4
|
||||
'@uppy/utils': 4.1.3
|
||||
nanoid: 3.3.12
|
||||
|
||||
'@vitejs/plugin-vue@5.2.4(vite@6.4.2(@types/node@25.9.1)(sass@1.100.0))(vue@3.5.34(typescript@5.7.3))':
|
||||
dependencies:
|
||||
vite: 6.4.2(@types/node@25.9.1)(sass@1.100.0)
|
||||
|
|
@ -1472,6 +1711,114 @@ snapshots:
|
|||
|
||||
'@vue/shared@3.5.34': {}
|
||||
|
||||
'@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
is-url: 1.2.4
|
||||
lodash.throttle: 4.1.1
|
||||
nanoid: 3.3.12
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/code-highlight@1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
prismjs: 1.30.0
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@types/event-emitter': 0.3.5
|
||||
'@uppy/core': 2.3.4
|
||||
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
|
||||
dom7: 3.0.0
|
||||
event-emitter: 0.3.5
|
||||
html-void-elements: 2.0.1
|
||||
i18next: 20.6.1
|
||||
is-hotkey: 0.2.0
|
||||
lodash.camelcase: 4.3.0
|
||||
lodash.clonedeep: 4.5.0
|
||||
lodash.debounce: 4.0.8
|
||||
lodash.foreach: 4.5.0
|
||||
lodash.isequal: 4.5.0
|
||||
lodash.throttle: 4.1.1
|
||||
lodash.toarray: 4.4.0
|
||||
nanoid: 3.3.12
|
||||
scroll-into-view-if-needed: 2.2.31
|
||||
slate: 0.72.8
|
||||
slate-history: 0.66.0(slate@0.72.8)
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/editor-for-vue@5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.34(typescript@5.7.3))':
|
||||
dependencies:
|
||||
'@wangeditor/editor': 5.1.23
|
||||
vue: 3.5.34(typescript@5.7.3)
|
||||
|
||||
'@wangeditor/editor@5.1.23':
|
||||
dependencies:
|
||||
'@uppy/core': 2.3.4
|
||||
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
|
||||
'@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/code-highlight': 1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/list-module': 1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/table-module': 1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/upload-image-module': 1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/video-module': 1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
is-hotkey: 0.2.0
|
||||
lodash.camelcase: 4.3.0
|
||||
lodash.clonedeep: 4.5.0
|
||||
lodash.debounce: 4.0.8
|
||||
lodash.foreach: 4.5.0
|
||||
lodash.isequal: 4.5.0
|
||||
lodash.throttle: 4.1.1
|
||||
lodash.toarray: 4.4.0
|
||||
nanoid: 3.3.12
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/list-module@1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/table-module@1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
lodash.isequal: 4.5.0
|
||||
lodash.throttle: 4.1.1
|
||||
nanoid: 3.3.12
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/upload-image-module@1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@uppy/core': 2.3.4
|
||||
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
|
||||
'@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
lodash.foreach: 4.5.0
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
'@wangeditor/video-module@1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)':
|
||||
dependencies:
|
||||
'@uppy/core': 2.3.4
|
||||
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
|
||||
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
|
||||
dom7: 3.0.0
|
||||
nanoid: 3.3.12
|
||||
slate: 0.72.8
|
||||
snabbdom: 3.6.3
|
||||
|
||||
acorn@8.16.0: {}
|
||||
|
||||
agent-base@6.0.2:
|
||||
|
|
@ -1555,6 +1902,11 @@ snapshots:
|
|||
|
||||
csstype@3.2.3: {}
|
||||
|
||||
d@1.0.2:
|
||||
dependencies:
|
||||
es5-ext: 0.10.64
|
||||
type: 2.7.3
|
||||
|
||||
dayjs@1.11.21: {}
|
||||
|
||||
de-indent@1.0.2: {}
|
||||
|
|
@ -1572,6 +1924,10 @@ snapshots:
|
|||
|
||||
dom-scroll-into-view@2.0.1: {}
|
||||
|
||||
dom7@3.0.0:
|
||||
dependencies:
|
||||
ssr-window: 3.0.0
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
|
|
@ -1600,6 +1956,24 @@ snapshots:
|
|||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.3
|
||||
|
||||
es5-ext@0.10.64:
|
||||
dependencies:
|
||||
es6-iterator: 2.0.3
|
||||
es6-symbol: 3.1.4
|
||||
esniff: 2.0.1
|
||||
next-tick: 1.1.0
|
||||
|
||||
es6-iterator@2.0.3:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
es6-symbol: 3.1.4
|
||||
|
||||
es6-symbol@3.1.4:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
ext: 1.7.0
|
||||
|
||||
esbuild@0.25.12:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.25.12
|
||||
|
|
@ -1631,14 +2005,30 @@ snapshots:
|
|||
|
||||
escape-string-regexp@5.0.0: {}
|
||||
|
||||
esniff@2.0.1:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
event-emitter: 0.3.5
|
||||
type: 2.7.3
|
||||
|
||||
estree-walker@2.0.2: {}
|
||||
|
||||
estree-walker@3.0.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
|
||||
event-emitter@0.3.5:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
|
||||
exsolve@1.0.8: {}
|
||||
|
||||
ext@1.7.0:
|
||||
dependencies:
|
||||
type: 2.7.3
|
||||
|
||||
fdir@6.5.0(picomatch@4.0.4):
|
||||
optionalDependencies:
|
||||
picomatch: 4.0.4
|
||||
|
|
@ -1690,6 +2080,8 @@ snapshots:
|
|||
|
||||
he@1.2.0: {}
|
||||
|
||||
html-void-elements@2.0.1: {}
|
||||
|
||||
https-proxy-agent@5.0.1:
|
||||
dependencies:
|
||||
agent-base: 6.0.2
|
||||
|
|
@ -1697,6 +2089,12 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
i18next@20.6.1:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.7
|
||||
|
||||
immer@9.0.21: {}
|
||||
|
||||
immutable@5.1.5: {}
|
||||
|
||||
is-extglob@2.1.1:
|
||||
|
|
@ -1707,8 +2105,14 @@ snapshots:
|
|||
is-extglob: 2.1.1
|
||||
optional: true
|
||||
|
||||
is-hotkey@0.2.0: {}
|
||||
|
||||
is-plain-object@3.0.1: {}
|
||||
|
||||
is-plain-object@5.0.0: {}
|
||||
|
||||
is-url@1.2.4: {}
|
||||
|
||||
js-tokens@4.0.0: {}
|
||||
|
||||
js-tokens@9.0.1: {}
|
||||
|
|
@ -1721,6 +2125,20 @@ snapshots:
|
|||
|
||||
lodash-es@4.18.1: {}
|
||||
|
||||
lodash.camelcase@4.3.0: {}
|
||||
|
||||
lodash.clonedeep@4.5.0: {}
|
||||
|
||||
lodash.debounce@4.0.8: {}
|
||||
|
||||
lodash.foreach@4.5.0: {}
|
||||
|
||||
lodash.isequal@4.5.0: {}
|
||||
|
||||
lodash.throttle@4.1.1: {}
|
||||
|
||||
lodash.toarray@4.4.0: {}
|
||||
|
||||
lodash@4.18.1: {}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
|
|
@ -1735,6 +2153,10 @@ snapshots:
|
|||
|
||||
mime-db@1.52.0: {}
|
||||
|
||||
mime-match@1.0.2:
|
||||
dependencies:
|
||||
wildcard: 1.1.2
|
||||
|
||||
mime-types@2.1.35:
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
|
|
@ -1758,10 +2180,14 @@ snapshots:
|
|||
|
||||
muggle-string@0.4.1: {}
|
||||
|
||||
namespace-emitter@2.0.1: {}
|
||||
|
||||
nanoid@3.3.12: {}
|
||||
|
||||
nanopop@2.4.2: {}
|
||||
|
||||
next-tick@1.1.0: {}
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
optional: true
|
||||
|
||||
|
|
@ -1803,6 +2229,10 @@ snapshots:
|
|||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
preact@10.29.2: {}
|
||||
|
||||
prismjs@1.30.0: {}
|
||||
|
||||
proxy-from-env@2.1.0: {}
|
||||
|
||||
quansync@0.2.11: {}
|
||||
|
|
@ -1858,8 +2288,23 @@ snapshots:
|
|||
|
||||
shallow-equal@1.2.1: {}
|
||||
|
||||
slate-history@0.66.0(slate@0.72.8):
|
||||
dependencies:
|
||||
is-plain-object: 5.0.0
|
||||
slate: 0.72.8
|
||||
|
||||
slate@0.72.8:
|
||||
dependencies:
|
||||
immer: 9.0.21
|
||||
is-plain-object: 5.0.0
|
||||
tiny-warning: 1.0.3
|
||||
|
||||
snabbdom@3.6.3: {}
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
ssr-window@3.0.0: {}
|
||||
|
||||
strip-literal@3.1.0:
|
||||
dependencies:
|
||||
js-tokens: 9.0.1
|
||||
|
|
@ -1868,6 +2313,8 @@ snapshots:
|
|||
|
||||
throttle-debounce@5.0.2: {}
|
||||
|
||||
tiny-warning@1.0.3: {}
|
||||
|
||||
tinyglobby@0.2.16:
|
||||
dependencies:
|
||||
fdir: 6.5.0(picomatch@4.0.4)
|
||||
|
|
@ -1875,6 +2322,8 @@ snapshots:
|
|||
|
||||
tslib@2.3.0: {}
|
||||
|
||||
type@2.7.3: {}
|
||||
|
||||
typescript@5.7.3: {}
|
||||
|
||||
ufo@1.6.4: {}
|
||||
|
|
@ -2003,6 +2452,8 @@ snapshots:
|
|||
|
||||
webpack-virtual-modules@0.6.2: {}
|
||||
|
||||
wildcard@1.1.2: {}
|
||||
|
||||
zrender@5.6.1:
|
||||
dependencies:
|
||||
tslib: 2.3.0
|
||||
|
|
|
|||
|
|
@ -1,29 +1,40 @@
|
|||
import http from './index'
|
||||
|
||||
export function getAttractionList() {
|
||||
return http.get('/attraction/list')
|
||||
// 景点管理
|
||||
export function getAttractionPage(params: any) {
|
||||
return http.get('/attraction/page', { params })
|
||||
}
|
||||
export function getAttractionById(id: number) {
|
||||
return http.get(`/attraction/${id}`)
|
||||
}
|
||||
export function createAttraction(data: any) {
|
||||
return http.post('/attraction/create', data)
|
||||
return http.post('/attraction', data)
|
||||
}
|
||||
export function updateAttraction(data: any) {
|
||||
return http.post('/attraction/update', data)
|
||||
return http.put('/attraction', data)
|
||||
}
|
||||
export function deleteAttraction(id: number) {
|
||||
return http.post('/attraction/delete', { id })
|
||||
return http.delete(`/attraction/${id}`)
|
||||
}
|
||||
|
||||
// 景点分类管理
|
||||
export function getAttractionCategoryList() {
|
||||
return http.get('/attraction/category/list')
|
||||
}
|
||||
export function getAttractionCategoryTree() {
|
||||
return http.get('/attraction/category/tree')
|
||||
}
|
||||
export function getAttractionCategoryById(id: number) {
|
||||
return http.get(`/attraction/category/${id}`)
|
||||
}
|
||||
export function createAttractionCategory(data: any) {
|
||||
return http.post('/attraction/category/create', data)
|
||||
return http.post('/attraction/category', data)
|
||||
}
|
||||
export function updateAttractionCategory(data: any) {
|
||||
return http.post('/attraction/category/update', data)
|
||||
return http.put('/attraction/category', data)
|
||||
}
|
||||
export function deleteAttractionCategory(id: number) {
|
||||
return http.post('/attraction/category/delete', { id })
|
||||
return http.delete(`/attraction/category/${id}`)
|
||||
}
|
||||
|
||||
export function getTicketList() {
|
||||
|
|
|
|||
|
|
@ -130,21 +130,28 @@ Mock.mock(/\/api\/user\/update/, 'post', () => success(null))
|
|||
Mock.mock(/\/api\/user\/status/, 'post', () => success(null))
|
||||
|
||||
// 景点管理
|
||||
Mock.mock(/\/api\/attraction\/list/, 'get', () => {
|
||||
// 景点管理 - 分页列表
|
||||
Mock.mock(/\/api\/attraction\/page/, 'get', () => {
|
||||
const list = Mock.mock({
|
||||
'records|10-15': [
|
||||
{
|
||||
id: '@id',
|
||||
name: '@pick(["黄山风景区", "故宫博物院", "西湖景区", "张家界国家森林公园", "九寨沟", "鼓浪屿", "丽江古城", "长城", "颐和园", "泰山风景区", "峨眉山", "布达拉宫", "敦煌莫高窟", "桂林漓江", "三亚天涯海角"])',
|
||||
category: '@pick(["自然风光", "人文历史", "城市地标", "主题乐园", "自然风光", "人文历史"])',
|
||||
level: '@pick(["5A", "4A", "5A"])',
|
||||
province: '@pick(["安徽", "北京", "浙江", "湖南", "四川", "福建", "云南", "山东", "西藏", "甘肃", "广西", "海南"])',
|
||||
categoryId: '@integer(1, 5)',
|
||||
categoryName: '@pick(["自然风光", "人文历史", "城市地标", "主题乐园", "博物馆"])',
|
||||
city: '@pick(["黄山市", "北京市", "杭州市", "张家界市", "阿坝州", "厦门市", "丽江市", "泰安市", "桂林市"])',
|
||||
ticketPrice: '@integer(30, 300)',
|
||||
recommended: '@pick([0, 1])',
|
||||
status: '@pick([0, 1])',
|
||||
salesCount: '@integer(1000, 50000)',
|
||||
address: '@county(true)',
|
||||
coverImage: '@image("300x200")',
|
||||
description: '@csentence(20, 50)',
|
||||
openTime: '@pick(["08:00-17:00", "08:30-17:30", "09:00-18:00"])',
|
||||
playTime: '@pick(["2-3小时", "半天", "1天", "2天"])',
|
||||
tags: '@pick(["5A景区", "世界遗产", "国家地质公园", "历史文化", "自然风光"])',
|
||||
isHot: '@pick([0, 1])',
|
||||
isRecommend: '@pick([0, 1])',
|
||||
status: '@pick([0, 1])',
|
||||
viewCount: '@integer(1000, 50000)',
|
||||
favoriteCount: '@integer(100, 5000)',
|
||||
score: '@float(3, 5, 1, 1)',
|
||||
createTime: '@datetime("yyyy-MM-dd HH:mm:ss")',
|
||||
},
|
||||
],
|
||||
|
|
@ -152,9 +159,38 @@ Mock.mock(/\/api\/attraction\/list/, 'get', () => {
|
|||
return pageSuccess(list.records, list.records.length)
|
||||
})
|
||||
|
||||
Mock.mock(/\/api\/attraction\/create/, 'post', () => success(null))
|
||||
Mock.mock(/\/api\/attraction\/update/, 'post', () => success(null))
|
||||
Mock.mock(/\/api\/attraction\/delete/, 'post', () => success(null))
|
||||
// 景点管理 - 根据ID查询
|
||||
Mock.mock(/\/api\/attraction\/\d+/, 'get', () => {
|
||||
return success({
|
||||
id: '@id',
|
||||
name: '@pick(["黄山风景区", "故宫博物院", "西湖景区"])',
|
||||
categoryId: 1,
|
||||
categoryName: '自然风光',
|
||||
city: '黄山市',
|
||||
address: '@county(true)',
|
||||
latitude: '@float(25, 40, 2, 6)',
|
||||
longitude: '@float(100, 120, 2, 6)',
|
||||
coverImage: '@image("300x200")',
|
||||
images: '[]',
|
||||
videoUrl: '',
|
||||
description: '@cparagraph(2, 5)',
|
||||
openTime: '08:00-17:00',
|
||||
playTime: '2-3小时',
|
||||
trafficInfo: '@cparagraph(1, 3)',
|
||||
tags: '5A景区,世界遗产',
|
||||
isHot: 1,
|
||||
isRecommend: 1,
|
||||
status: 1,
|
||||
viewCount: 12560,
|
||||
favoriteCount: 3200,
|
||||
score: 4.8,
|
||||
createTime: '@datetime("yyyy-MM-dd HH:mm:ss")',
|
||||
})
|
||||
})
|
||||
|
||||
Mock.mock(/\/api\/attraction/, 'post', () => success(null))
|
||||
Mock.mock(/\/api\/attraction/, 'put', () => success(null))
|
||||
Mock.mock(/\/api\/attraction\/\d+/, 'delete', () => success(null))
|
||||
|
||||
// 景点分类
|
||||
Mock.mock(/\/api\/attraction\/category\/list/, 'get', () => {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ const routes: RouteRecordRaw[] = [
|
|||
component: () => import('@/views/attraction/AttractionView.vue'),
|
||||
meta: { title: '景点管理', icon: 'Location' },
|
||||
},
|
||||
{
|
||||
path: 'attraction/form',
|
||||
name: 'AttractionForm',
|
||||
component: () => import('@/views/attraction/AttractionFormView.vue'),
|
||||
meta: { title: '景点表单', icon: 'Location', hidden: true },
|
||||
},
|
||||
{
|
||||
path: 'attraction/category',
|
||||
name: 'AttractionCategory',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,377 @@
|
|||
<template>
|
||||
<a-card :title="isEdit ? '编辑景点' : '新增景点'">
|
||||
<a-form :model="form" :label-col="{ span: 3 }" :wrapper-col="{ span: 21 }">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="16">
|
||||
<a-divider orientation="left">基本信息</a-divider>
|
||||
<a-form-item label="景点名称" required>
|
||||
<a-input v-model:value="form.name" placeholder="请输入景点名称" />
|
||||
</a-form-item>
|
||||
<a-form-item label="所属分类" required>
|
||||
<a-tree-select
|
||||
v-model:value="form.categoryId"
|
||||
:tree-data="categoryTree"
|
||||
:field-names="{ children: 'children', label: 'name', value: 'id' }"
|
||||
placeholder="请选择分类"
|
||||
allow-clear
|
||||
tree-default-expand-all
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="所在城市" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }" required>
|
||||
<a-input v-model:value="form.city" placeholder="如:杭州市" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="详细地址" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }" required>
|
||||
<a-input v-model:value="form.address" placeholder="请输入详细地址" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="纬度" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||
<a-input-number v-model:value="form.latitude" :precision="6" style="width: 100%" placeholder="纬度" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="经度" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||
<a-input-number v-model:value="form.longitude" :precision="6" style="width: 100%" placeholder="经度" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-divider orientation="left">媒体资源</a-divider>
|
||||
<a-form-item label="封面图片">
|
||||
<a-input v-model:value="form.coverImage" placeholder="请输入封面图片URL" @change="updatePreview" />
|
||||
</a-form-item>
|
||||
<a-form-item label="图片列表">
|
||||
<a-textarea
|
||||
v-model:value="form.images"
|
||||
:rows="3"
|
||||
placeholder='JSON数组格式,如:["url1", "url2", "url3"]'
|
||||
@change="updatePreview"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="宣传视频">
|
||||
<a-input v-model:value="form.videoUrl" placeholder="请输入视频URL" />
|
||||
</a-form-item>
|
||||
|
||||
<a-divider orientation="left">详情信息</a-divider>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="开放时间" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||
<a-input v-model:value="form.openTime" placeholder="如:08:00-17:00" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="游玩时长" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||
<a-input v-model:value="form.playTime" placeholder="如:2-3小时" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item label="景点介绍">
|
||||
<a-textarea v-model:value="form.description" :rows="5" placeholder="请输入景点介绍" />
|
||||
</a-form-item>
|
||||
<a-form-item label="交通信息">
|
||||
<a-textarea v-model:value="form.trafficInfo" :rows="3" placeholder="请输入交通信息" />
|
||||
</a-form-item>
|
||||
<a-form-item label="标签">
|
||||
<a-input v-model:value="form.tags" placeholder="多个标签用逗号分隔,如:5A景区,世界遗产,自然风光" />
|
||||
</a-form-item>
|
||||
|
||||
<a-divider orientation="left">其他设置</a-divider>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="8">
|
||||
<a-form-item label="热门">
|
||||
<a-switch v-model:checked="form.isHot" :checked-value="1" :unchecked-value="0" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="推荐">
|
||||
<a-switch v-model:checked="form.isRecommend" :checked-value="1" :unchecked-value="0" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="上架状态">
|
||||
<a-switch
|
||||
v-model:checked="form.status"
|
||||
:checked-value="1"
|
||||
:unchecked-value="0"
|
||||
checked-children="上架"
|
||||
un-checked-children="下架"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="8">
|
||||
<a-card title="预览" size="small">
|
||||
<div class="preview-cover">
|
||||
<img v-if="preview.coverImage" :src="preview.coverImage" alt="封面预览" />
|
||||
<div v-else class="preview-placeholder">封面预览</div>
|
||||
</div>
|
||||
<div class="preview-info">
|
||||
<h3>{{ form.name || '景点名称' }}</h3>
|
||||
<p class="preview-city">{{ form.city || '所在城市' }} · {{ form.address || '详细地址' }}</p>
|
||||
<p class="preview-desc">{{ form.description || '景点介绍...' }}</p>
|
||||
<div class="preview-tags">
|
||||
<a-tag v-for="tag in previewTags" :key="tag" size="small">{{ tag }}</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
<a-divider />
|
||||
<div class="preview-images">
|
||||
<p class="preview-section-title">图片列表</p>
|
||||
<div v-if="previewImages.length > 0" class="preview-image-list">
|
||||
<img v-for="(img, idx) in previewImages" :key="idx" :src="img" alt="景点图片" />
|
||||
</div>
|
||||
<div v-else class="preview-placeholder-small">暂无图片</div>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-form-item :wrapper-col="{ offset: 3, span: 21 }" style="margin-top: 24px;">
|
||||
<a-space>
|
||||
<a-button type="primary" :loading="saveLoading" @click="handleSave">保存</a-button>
|
||||
<a-button @click="handleCancel">取消</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {
|
||||
createAttraction,
|
||||
updateAttraction,
|
||||
getAttractionById,
|
||||
getAttractionCategoryTree,
|
||||
} from '@/api/attraction'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const isEdit = ref(false)
|
||||
const saveLoading = ref(false)
|
||||
const categoryTree = ref<any[]>([])
|
||||
|
||||
const form = reactive({
|
||||
id: undefined as number | undefined,
|
||||
name: '',
|
||||
categoryId: undefined as number | undefined,
|
||||
city: '',
|
||||
address: '',
|
||||
latitude: undefined as number | undefined,
|
||||
longitude: undefined as number | undefined,
|
||||
coverImage: '',
|
||||
images: '',
|
||||
videoUrl: '',
|
||||
description: '',
|
||||
openTime: '',
|
||||
playTime: '',
|
||||
trafficInfo: '',
|
||||
tags: '',
|
||||
isHot: 0,
|
||||
isRecommend: 0,
|
||||
status: 1,
|
||||
})
|
||||
|
||||
const preview = reactive({
|
||||
coverImage: '',
|
||||
})
|
||||
|
||||
const previewTags = computed(() => {
|
||||
if (!form.tags) return []
|
||||
return form.tags.split(',').map((t) => t.trim()).filter(Boolean)
|
||||
})
|
||||
|
||||
const previewImages = computed(() => {
|
||||
try {
|
||||
const arr = JSON.parse(form.images || '[]')
|
||||
return Array.isArray(arr) ? arr : []
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
function updatePreview() {
|
||||
preview.coverImage = form.coverImage
|
||||
}
|
||||
|
||||
async function fetchCategoryTree() {
|
||||
try {
|
||||
const res: any = await getAttractionCategoryTree()
|
||||
categoryTree.value = res.data || []
|
||||
} catch (e) {
|
||||
console.error('获取分类失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchDetail(id: number) {
|
||||
try {
|
||||
const res: any = await getAttractionById(id)
|
||||
const data = res.data
|
||||
Object.assign(form, {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
categoryId: data.categoryId,
|
||||
city: data.city,
|
||||
address: data.address,
|
||||
latitude: data.latitude,
|
||||
longitude: data.longitude,
|
||||
coverImage: data.coverImage || '',
|
||||
images: data.images || '',
|
||||
videoUrl: data.videoUrl || '',
|
||||
description: data.description || '',
|
||||
openTime: data.openTime || '',
|
||||
playTime: data.playTime || '',
|
||||
trafficInfo: data.trafficInfo || '',
|
||||
tags: data.tags || '',
|
||||
isHot: data.isHot,
|
||||
isRecommend: data.isRecommend,
|
||||
status: data.status,
|
||||
})
|
||||
updatePreview()
|
||||
} catch (e) {
|
||||
message.error('获取景点详情失败')
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSave() {
|
||||
if (!form.name.trim()) {
|
||||
message.error('请输入景点名称')
|
||||
return
|
||||
}
|
||||
if (!form.categoryId) {
|
||||
message.error('请选择分类')
|
||||
return
|
||||
}
|
||||
if (!form.city.trim()) {
|
||||
message.error('请输入所在城市')
|
||||
return
|
||||
}
|
||||
if (!form.address.trim()) {
|
||||
message.error('请输入详细地址')
|
||||
return
|
||||
}
|
||||
|
||||
saveLoading.value = true
|
||||
try {
|
||||
const data = { ...form }
|
||||
if (isEdit.value) {
|
||||
await updateAttraction(data)
|
||||
message.success('更新成功')
|
||||
} else {
|
||||
await createAttraction(data)
|
||||
message.success('创建成功')
|
||||
}
|
||||
router.push('/attraction/list')
|
||||
} finally {
|
||||
saveLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
router.push('/attraction/list')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchCategoryTree()
|
||||
const id = route.query.id
|
||||
if (id) {
|
||||
isEdit.value = true
|
||||
fetchDetail(Number(id))
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.preview-cover {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 16px;
|
||||
background: #f5f5f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-placeholder {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.preview-info {
|
||||
h3 {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.preview-city {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.preview-desc {
|
||||
margin: 0 0 12px 0;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.preview-section-title {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.preview-image-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
|
||||
img {
|
||||
width: 80px;
|
||||
height: 60px;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-placeholder-small {
|
||||
color: #bbb;
|
||||
font-size: 12px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,88 +1,140 @@
|
|||
<template>
|
||||
<a-card title="景点列表">
|
||||
<template #extra>
|
||||
<a-input-search v-model:value="search" placeholder="搜索景点" style="width: 200px; margin-right: 8px" @search="fetchData" />
|
||||
<a-button type="primary" @click="openDialog(false)">新增景点</a-button>
|
||||
<a-input-search
|
||||
v-model:value="searchKeyword"
|
||||
placeholder="搜索景点名称"
|
||||
style="width: 220px; margin-right: 8px"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<a-button type="primary" @click="handleAdd">新增景点</a-button>
|
||||
</template>
|
||||
<a-table :data-source="tableData" :columns="columns" :loading="loading" :pagination="false" row-key="id" />
|
||||
<a-table
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
row-key="id"
|
||||
@change="handleTableChange"
|
||||
/>
|
||||
</a-card>
|
||||
|
||||
<a-modal v-model:visible="showDialog" :title="isEdit ? '编辑景点' : '新增景点'" width="600px" @ok="handleSave" @cancel="showDialog = false">
|
||||
<a-form :model="form" label-col="{ span: 4 }" wrapper-col="{ span: 20 }">
|
||||
<a-form-item label="景点名称"><a-input v-model:value="form.name" /></a-form-item>
|
||||
<a-form-item label="分类">
|
||||
<a-select v-model:value="form.category" style="width: 100%">
|
||||
<a-select-option value="自然风光">自然风光</a-select-option>
|
||||
<a-select-option value="人文历史">人文历史</a-select-option>
|
||||
<a-select-option value="城市地标">城市地标</a-select-option>
|
||||
<a-select-option value="主题乐园">主题乐园</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="等级">
|
||||
<a-select v-model:value="form.level" style="width: 100%">
|
||||
<a-select-option value="5A">5A</a-select-option>
|
||||
<a-select-option value="4A">4A</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="门票价格"><a-input-number v-model:value="form.ticketPrice" :min="0" /></a-form-item>
|
||||
<a-form-item label="推荐"><a-switch v-model:checked="form.recommended" :checked-value="1" :unchecked-value="0" /></a-form-item>
|
||||
<a-form-item label="描述"><a-textarea v-model:value="form.description" /></a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, h, onMounted, reactive } from 'vue'
|
||||
import { getAttractionList, createAttraction, updateAttraction, deleteAttraction } from '@/api/attraction'
|
||||
import { useRouter } from 'vue-router'
|
||||
import {
|
||||
getAttractionPage,
|
||||
deleteAttraction,
|
||||
} from '@/api/attraction'
|
||||
import { message, Modal } from 'ant-design-vue'
|
||||
|
||||
const router = useRouter()
|
||||
const tableData = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
const search = ref('')
|
||||
const showDialog = ref(false)
|
||||
const isEdit = ref(false)
|
||||
const form = reactive({ id: 0, name: '', category: '自然风光', level: '4A', ticketPrice: 80, recommended: 0, description: '' })
|
||||
const searchKeyword = ref('')
|
||||
|
||||
const pagination = reactive({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
showTotal: (total: number) => `共 ${total} 条`,
|
||||
})
|
||||
|
||||
const columns = [
|
||||
{ title: 'ID', dataIndex: 'id', width: 80 },
|
||||
{ title: '景点名称', dataIndex: 'name', minWidth: 160 },
|
||||
{ title: '分类', dataIndex: 'category', width: 100 },
|
||||
{ title: '等级', dataIndex: 'level', width: 80 },
|
||||
{ title: '省份', dataIndex: 'province', width: 80 },
|
||||
{ title: '门票价格', dataIndex: 'ticketPrice', width: 100, customRender: ({ text }: any) => '¥' + text },
|
||||
{ title: '销量', dataIndex: 'salesCount', width: 100 },
|
||||
{ title: '推荐', dataIndex: 'recommended', width: 80, customRender: ({ text }: any) => text === 1 ? h('a-tag', { color: 'gold' }, '是') : h('a-tag', { color: 'default' }, '否') },
|
||||
{ title: '状态', dataIndex: 'status', width: 80, customRender: ({ text }: any) => text === 1 ? h('a-tag', { color: 'green' }, '上架') : h('a-tag', { color: 'red' }, '下架') },
|
||||
{ title: '创建时间', dataIndex: 'createTime', width: 180 },
|
||||
{ title: '操作', width: 180, fixed: 'right', customRender: ({ record }: any) => h('span', null, [h('a', { onClick: () => handleEdit(record) }, '编辑'), h('a-divider', { type: 'vertical' }), h('a', { onClick: () => handleDelete(record) }, '删除')]) },
|
||||
{ title: 'ID', dataIndex: 'id', width: 70 },
|
||||
{ title: '景点名称', dataIndex: 'name', width: 160, ellipsis: true },
|
||||
{ title: '分类', dataIndex: 'categoryName', width: 100 },
|
||||
{ title: '城市', dataIndex: 'city', width: 100 },
|
||||
{
|
||||
title: '封面',
|
||||
dataIndex: 'coverImage',
|
||||
width: 80,
|
||||
customRender: ({ text }: any) =>
|
||||
text ? h('img', { src: text, style: 'width: 50px; height: 36px; object-fit: cover; border-radius: 4px;' }) : h('span', { style: 'color: #999;' }, '无'),
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
width: 80,
|
||||
customRender: ({ text }: any) =>
|
||||
text === 1 ? h('a-tag', { color: 'green' }, '上架') : h('a-tag', { color: 'red' }, '下架'),
|
||||
},
|
||||
{
|
||||
title: '热门',
|
||||
dataIndex: 'isHot',
|
||||
width: 70,
|
||||
customRender: ({ text }: any) =>
|
||||
text === 1 ? h('a-tag', { color: 'red' }, '是') : h('a-tag', { color: 'default' }, '否'),
|
||||
},
|
||||
{
|
||||
title: '推荐',
|
||||
dataIndex: 'isRecommend',
|
||||
width: 70,
|
||||
customRender: ({ text }: any) =>
|
||||
text === 1 ? h('a-tag', { color: 'gold' }, '是') : h('a-tag', { color: 'default' }, '否'),
|
||||
},
|
||||
{ title: '浏览量', dataIndex: 'viewCount', width: 90 },
|
||||
{ title: '收藏量', dataIndex: 'favoriteCount', width: 90 },
|
||||
{ title: '评分', dataIndex: 'score', width: 70, customRender: ({ text }: any) => text },
|
||||
{ title: '创建时间', dataIndex: 'createTime', width: 170 },
|
||||
{
|
||||
title: '操作',
|
||||
width: 160,
|
||||
fixed: 'right',
|
||||
customRender: ({ record }: any) =>
|
||||
h('span', { style: { display: 'flex', gap: '12px' } }, [
|
||||
h('a', { onClick: () => handleEdit(record) }, '编辑'),
|
||||
h('a', { style: { color: '#ff4d4f' }, onClick: () => handleDelete(record) }, '删除'),
|
||||
]),
|
||||
},
|
||||
]
|
||||
|
||||
async function fetchData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res: any = await getAttractionList()
|
||||
let list = res.data.records
|
||||
if (search.value) list = list.filter((r: any) => r.name.includes(search.value))
|
||||
tableData.value = list
|
||||
} finally { loading.value = false }
|
||||
const res: any = await getAttractionPage({
|
||||
current: pagination.current,
|
||||
size: pagination.pageSize,
|
||||
keyword: searchKeyword.value || undefined,
|
||||
})
|
||||
tableData.value = res.data.records || []
|
||||
pagination.total = res.data.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function openDialog(edit: boolean) {
|
||||
isEdit.value = edit
|
||||
if (!edit) Object.assign(form, { id: 0, name: '', category: '自然风光', level: '4A', ticketPrice: 80, recommended: 0, description: '' })
|
||||
showDialog.value = true
|
||||
function handleSearch() {
|
||||
pagination.current = 1
|
||||
fetchData()
|
||||
}
|
||||
|
||||
function handleEdit(row: any) { Object.assign(form, row); openDialog(true) }
|
||||
function handleTableChange(pag: any) {
|
||||
pagination.current = pag.current
|
||||
pagination.pageSize = pag.pageSize
|
||||
fetchData()
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
router.push('/attraction/form')
|
||||
}
|
||||
|
||||
function handleEdit(row: any) {
|
||||
router.push(`/attraction/form?id=${row.id}`)
|
||||
}
|
||||
|
||||
function handleDelete(row: any) {
|
||||
Modal.confirm({ title: '确认删除该景点?', onOk: async () => { await deleteAttraction(row.id); message.success('删除成功'); fetchData() } })
|
||||
}
|
||||
|
||||
async function handleSave() {
|
||||
if (isEdit.value) await updateAttraction(form); else await createAttraction(form)
|
||||
message.success(isEdit.value ? '更新成功' : '创建成功')
|
||||
showDialog.value = false; fetchData()
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: `确定删除景点「${row.name}」吗?`,
|
||||
onOk: async () => {
|
||||
await deleteAttraction(row.id)
|
||||
message.success('删除成功')
|
||||
fetchData()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(fetchData)
|
||||
|
|
|
|||
|
|
@ -1,55 +1,188 @@
|
|||
<template>
|
||||
<a-card title="景点分类">
|
||||
<template #extra><a-button type="primary" @click="openDialog(false)">新增分类</a-button></template>
|
||||
<a-table :data-source="tableData" :columns="columns" :loading="loading" :pagination="false" row-key="id" />
|
||||
<template #extra>
|
||||
<a-button type="primary" @click="openDialog(false)">新增分类</a-button>
|
||||
</template>
|
||||
<a-table
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:pagination="false"
|
||||
row-key="id"
|
||||
:children-column-name="'children'"
|
||||
default-expand-all-rows
|
||||
/>
|
||||
</a-card>
|
||||
|
||||
<a-modal v-model:visible="showDialog" :title="isEdit ? '编辑分类' : '新增分类'" @ok="handleSave" @cancel="showDialog = false">
|
||||
<a-form :model="form" label-col="{ span: 4 }" wrapper-col="{ span: 20 }">
|
||||
<a-form-item label="分类名称"><a-input v-model:value="form.name" /></a-form-item>
|
||||
<a-form-item label="排序"><a-input-number v-model:value="form.sort" :min="1" /></a-form-item>
|
||||
<a-form-item label="状态"><a-switch v-model:checked="form.status" :checked-value="1" :unchecked-value="0" /></a-form-item>
|
||||
<a-modal
|
||||
v-model:visible="showDialog"
|
||||
:title="isEdit ? '编辑分类' : '新增分类'"
|
||||
width="520px"
|
||||
@ok="handleSave"
|
||||
@cancel="showDialog = false"
|
||||
>
|
||||
<a-form :model="form" :label-col="{ span: 5 }" :wrapper-col="{ span: 19 }">
|
||||
<a-form-item label="分类名称" required>
|
||||
<a-input v-model:value="form.name" placeholder="请输入分类名称" />
|
||||
</a-form-item>
|
||||
<a-form-item label="父级分类">
|
||||
<a-tree-select
|
||||
v-model:value="form.parentId"
|
||||
:tree-data="categoryOptions"
|
||||
:field-names="{ children: 'children', label: 'name', value: 'id' }"
|
||||
placeholder="请选择父级分类(不选则为顶级分类)"
|
||||
allow-clear
|
||||
tree-default-expand-all
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序">
|
||||
<a-input-number v-model:value="form.sort" :min="0" style="width: 100%" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, h, onMounted, reactive } from 'vue'
|
||||
import { getAttractionCategoryList, createAttractionCategory, updateAttractionCategory, deleteAttractionCategory } from '@/api/attraction'
|
||||
import { ref, h, onMounted, reactive, computed } from 'vue'
|
||||
import {
|
||||
getAttractionCategoryTree,
|
||||
createAttractionCategory,
|
||||
updateAttractionCategory,
|
||||
deleteAttractionCategory,
|
||||
} from '@/api/attraction'
|
||||
import { message, Modal } from 'ant-design-vue'
|
||||
|
||||
const tableData = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
const showDialog = ref(false)
|
||||
const isEdit = ref(false)
|
||||
const form = reactive({ id: 0, name: '', sort: 1, status: 1 })
|
||||
const currentEditId = ref<number | undefined>(undefined)
|
||||
const form = reactive({
|
||||
id: undefined as number | undefined,
|
||||
name: '',
|
||||
parentId: undefined as number | undefined,
|
||||
sort: 0,
|
||||
})
|
||||
|
||||
const columns = [
|
||||
{ title: 'ID', dataIndex: 'id', width: 80 },
|
||||
{ title: '分类名称', dataIndex: 'name' },
|
||||
{ title: '分类名称', dataIndex: 'name', width: 200 },
|
||||
{ title: '层级', dataIndex: 'level', width: 80, customRender: ({ text }: any) => `第${text}级` },
|
||||
{ title: '排序', dataIndex: 'sort', width: 80 },
|
||||
{ title: '状态', dataIndex: 'status', width: 100, customRender: ({ text }: any) => text === 1 ? h('a-tag', { color: 'green' }, '启用') : h('a-tag', { color: 'red' }, '禁用') },
|
||||
{ title: '创建时间', dataIndex: 'createTime', width: 180 },
|
||||
{ title: '操作', width: 180, customRender: ({ record }: any) => h('span', null, [h('a', { onClick: () => handleEdit(record) }, '编辑'), h('a-divider', { type: 'vertical' }), h('a', { onClick: () => handleDelete(record) }, '删除')]) },
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
width: 180,
|
||||
customRender: ({ text }: any) => text || '-',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: 240,
|
||||
customRender: ({ record }: any) =>
|
||||
h('span', { style: { display: 'flex', gap: '12px' } }, [
|
||||
h('a', { onClick: () => handleAddChild(record) }, '添加子类'),
|
||||
h('a', { onClick: () => handleEdit(record) }, '编辑'),
|
||||
h('a', { style: { color: '#ff4d4f' }, onClick: () => handleDelete(record) }, '删除'),
|
||||
]),
|
||||
},
|
||||
]
|
||||
|
||||
// 树形选择器数据源:编辑时排除自身及子节点,避免循环引用
|
||||
const categoryOptions = computed(() => {
|
||||
if (!currentEditId.value) return tableData.value
|
||||
return filterTree(tableData.value, currentEditId.value)
|
||||
})
|
||||
|
||||
function filterTree(tree: any[], excludeId: number): any[] {
|
||||
return tree
|
||||
.filter((node) => node.id !== excludeId)
|
||||
.map((node) => {
|
||||
const copy = { ...node }
|
||||
if (copy.children && copy.children.length > 0) {
|
||||
copy.children = filterTree(copy.children, excludeId)
|
||||
}
|
||||
return copy
|
||||
})
|
||||
}
|
||||
|
||||
async function fetchData() {
|
||||
loading.value = true
|
||||
try { const res: any = await getAttractionCategoryList(); tableData.value = res.data.records } finally { loading.value = false }
|
||||
try {
|
||||
const res: any = await getAttractionCategoryTree()
|
||||
tableData.value = res.data || []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function openDialog(edit: boolean) {
|
||||
function openDialog(edit: boolean, parentId?: number) {
|
||||
isEdit.value = edit
|
||||
if (!edit) Object.assign(form, { id: 0, name: '', sort: 1, status: 1 })
|
||||
if (!edit) {
|
||||
currentEditId.value = undefined
|
||||
Object.assign(form, {
|
||||
id: undefined,
|
||||
name: '',
|
||||
parentId: parentId ?? undefined,
|
||||
sort: 0,
|
||||
})
|
||||
}
|
||||
showDialog.value = true
|
||||
}
|
||||
function handleEdit(row: any) { Object.assign(form, row); openDialog(true) }
|
||||
function handleDelete(row: any) {
|
||||
Modal.confirm({ title: '确认删除该分类?', onOk: async () => { await deleteAttractionCategory(row.id); message.success('删除成功'); fetchData() } })
|
||||
|
||||
function handleAddChild(row: any) {
|
||||
currentEditId.value = undefined
|
||||
openDialog(false, row.id)
|
||||
}
|
||||
|
||||
function handleEdit(row: any) {
|
||||
isEdit.value = true
|
||||
currentEditId.value = row.id
|
||||
Object.assign(form, {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
parentId: row.parentId === 0 ? undefined : row.parentId,
|
||||
sort: row.sort,
|
||||
})
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
function handleDelete(row: any) {
|
||||
if (row.children && row.children.length > 0) {
|
||||
message.error('请先删除子分类')
|
||||
return
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: `确定删除分类「${row.name}」吗?`,
|
||||
onOk: async () => {
|
||||
await deleteAttractionCategory(row.id)
|
||||
message.success('删除成功')
|
||||
fetchData()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function handleSave() {
|
||||
if (isEdit.value) await updateAttractionCategory(form); else await createAttractionCategory(form)
|
||||
message.success(isEdit.value ? '更新成功' : '创建成功'); showDialog.value = false; fetchData()
|
||||
if (!form.name.trim()) {
|
||||
message.error('请输入分类名称')
|
||||
return
|
||||
}
|
||||
|
||||
const data = {
|
||||
...form,
|
||||
parentId: form.parentId ?? 0,
|
||||
}
|
||||
|
||||
if (isEdit.value) {
|
||||
await updateAttractionCategory(data)
|
||||
message.success('更新成功')
|
||||
} else {
|
||||
await createAttractionCategory(data)
|
||||
message.success('创建成功')
|
||||
}
|
||||
showDialog.value = false
|
||||
fetchData()
|
||||
}
|
||||
|
||||
onMounted(fetchData)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ public class AttractionCategoryServiceImpl extends ServiceImpl<AttractionCategor
|
|||
|
||||
BeanUtils.copyProperties(dto, category, "id");
|
||||
|
||||
if (category.getParentId() == null) {
|
||||
category.setParentId(0L);
|
||||
}
|
||||
|
||||
// 重新计算层级
|
||||
if (category.getParentId() == 0L) {
|
||||
category.setLevel(1);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
spring:
|
||||
datasource:
|
||||
username: root
|
||||
password: orbit123
|
||||
password: 123456
|
||||
|
||||
logging:
|
||||
level:
|
||||
com.tourism: debug
|
||||
com.baomidou.mybatisplus: debug
|
||||
#logging:
|
||||
# level:
|
||||
# com.tourism: debug
|
||||
# com.baomidou.mybatisplus: debug
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ mybatis-plus:
|
|||
logic-not-delete-value: 0
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
|
||||
sa-token:
|
||||
token-name: token
|
||||
|
|
|
|||
Loading…
Reference in New Issue