mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2025-12-08 17:12:28 +08:00
【制作独立jeecg-ai】删除示例代码
This commit is contained in:
@ -1,196 +0,0 @@
|
||||
# PWA 功能说明
|
||||
|
||||
## 概述
|
||||
|
||||
项目集成了 `vite-plugin-pwa` 插件,**适配按需加载**,实现资源缓存优化和离线支持。
|
||||
|
||||
**升级亮点**:通过集成 vite-plugin-pwa 实现渐进式 Web 应用,提升了首屏加载速度,同时异步加载系统资源,点击菜单响应更迅速。
|
||||
|
||||
**核心设计**:只预缓存关键资源,按需加载的路由组件 chunk 通过运行时缓存策略处理,避免预缓存过多资源。
|
||||
|
||||
## 核心文件
|
||||
|
||||
### 构建生成的文件
|
||||
|
||||
- **`sw.js`** - Service Worker 文件,由 `vite-plugin-pwa` 自动生成,包含:
|
||||
- 预缓存资源列表(HTML、CSS、核心 JS、静态资源)
|
||||
- 运行时缓存策略(JS chunk、CSS、图片、API 等)
|
||||
- 缓存清理和更新逻辑
|
||||
|
||||
- **`workbox-*.js`** - Workbox 运行时库,Service Worker 的核心依赖
|
||||
|
||||
- **`manifest.webmanifest`** - PWA 清单文件,定义应用元数据
|
||||
|
||||
### 配置文件
|
||||
|
||||
- **`build/vite/plugin/pwa.ts`** - PWA 插件配置
|
||||
- **预缓存策略**:只缓存关键资源
|
||||
- 入口文件:`index.html`、`manifest.webmanifest`
|
||||
- 核心 JS:入口 JS(`js/index-*.js`)、vendor chunk(`js/*-vendor-*.js`)
|
||||
- 静态资源:CSS、图片、字体等
|
||||
- **不预缓存**:按需加载的路由组件 chunk(避免预缓存过多资源)
|
||||
- **运行时缓存**:按需加载的资源通过运行时缓存策略处理
|
||||
- 按需加载的 JS chunk:NetworkFirst(优先网络,失败后使用缓存)
|
||||
- CSS、图片、API 等:按需缓存
|
||||
- **注册方式**:`injectRegister: 'inline'`(内联到 HTML,避免缓存问题)
|
||||
|
||||
## 功能特性
|
||||
|
||||
1. **资源缓存优化** - 通过缓存策略提升加载速度
|
||||
2. **离线支持** - 缓存静态资源,支持离线访问
|
||||
|
||||
## 缓存策略
|
||||
|
||||
### 预缓存(Precache)
|
||||
|
||||
| 资源类型 | 说明 |
|
||||
|---------|------|
|
||||
| `index.html` | 入口 HTML 文件 |
|
||||
| `manifest.webmanifest` | PWA 清单文件 |
|
||||
| `js/index-*.js` | 入口 JS 文件 |
|
||||
| `js/*-vendor-*.js` | 核心 vendor chunk(Vue、Ant Design Vue 等) |
|
||||
| `assets/index-*.css` | **仅入口 CSS**(主样式文件) |
|
||||
| `favicon.ico`、`logo.png` | **仅关键静态资源**(logo、图标) |
|
||||
|
||||
**重要优化**:
|
||||
- ❌ **不预缓存**:路由组件的 CSS(避免登录页加载全部 CSS)
|
||||
- ❌ **不预缓存**:路由组件的 JS chunk(按需加载)
|
||||
- ❌ **不预缓存**:所有图片和字体(按需加载)
|
||||
- ✅ **只预缓存**:登录页和首屏必需的关键资源
|
||||
|
||||
**效果**:访问登录页时,只加载登录页相关资源,不会预加载系统大部分资源。
|
||||
|
||||
### 运行时缓存(Runtime Cache)
|
||||
|
||||
| 资源类型 | 策略 | 有效期 | 说明 |
|
||||
|---------|------|--------|------|
|
||||
| 按需加载 JS chunk | NetworkFirst | 7天 | 优先网络,失败后使用缓存 |
|
||||
| 路由组件 CSS | CacheFirst | 30天 | **按需加载**,优先缓存 |
|
||||
| 图片 | CacheFirst | 30天 | 优先缓存 |
|
||||
| API 请求 | NetworkFirst | 5分钟 | 优先网络,短时缓存 |
|
||||
| Google Fonts | CacheFirst | 365天 | 长期缓存 |
|
||||
|
||||
**优势**:
|
||||
- ✅ **减少预缓存体积 80%+**:只预缓存关键资源,不预缓存路由组件 CSS/JS
|
||||
- ✅ **登录页加载优化**:访问登录页时只加载登录页资源,不会加载系统大部分资源
|
||||
- ✅ **按需加载**:路由组件的 CSS 和 JS 只在访问对应页面时加载和缓存
|
||||
- ✅ **节省存储空间**:按需加载的 chunk 只在需要时缓存
|
||||
- ✅ **网络优先策略**:确保用户获取最新代码
|
||||
|
||||
## 性能提升分析
|
||||
|
||||
### 首次访问(无缓存)
|
||||
|
||||
- **Service Worker 注册**:~50-100ms(后台异步,不影响页面加载)
|
||||
- **预缓存安装**:~200-500ms(后台进行,关键资源已加载)
|
||||
- **页面加载**:无影响(Service Worker 在后台工作)
|
||||
|
||||
### 二次访问(有缓存)
|
||||
|
||||
| 指标 | 无 PWA | 有 PWA | 提升 |
|
||||
|------|--------|--------|------|
|
||||
| **首屏加载时间** | 2-5s | 0.5-1.5s | **60-70%** ⬇️ |
|
||||
| **关键资源加载** | 网络请求 | 缓存读取 | **90%+** ⬇️ |
|
||||
| **CSS 加载** | 100-300ms | <10ms | **95%+** ⬇️ |
|
||||
| **图片加载** | 200-500ms | <10ms | **95%+** ⬇️ |
|
||||
| **离线访问** | ❌ 不可用 | ✅ 可用 | - |
|
||||
|
||||
### 按需加载优化
|
||||
|
||||
- **预缓存体积**:仅 ~1-3MB(关键资源),而非全部资源(**减少 80%+**)
|
||||
- **Service Worker 安装时间**:减少 **60-80%**
|
||||
- **登录页加载**:只加载登录页资源,**不加载系统大部分资源**
|
||||
- **存储空间**:节省 **70-85%**(不预缓存路由组件 CSS/JS)
|
||||
|
||||
### 实际场景性能提升
|
||||
|
||||
1. **弱网环境(3G/4G)**
|
||||
- 首屏加载:**3-5s → 0.8-1.5s**(提升 60-70%)
|
||||
- 页面切换:**1-2s → 0.2-0.5s**(提升 75-80%)
|
||||
|
||||
2. **离线访问**
|
||||
- 已访问页面:**完全可用**
|
||||
- 未访问页面:**部分可用**(关键资源已缓存)
|
||||
|
||||
3. **重复访问**
|
||||
- 资源加载:**网络 → 缓存**(提升 90%+)
|
||||
- 用户体验:**秒开**(<100ms)
|
||||
|
||||
## 前端体验优化建议
|
||||
|
||||
### 1. 资源加载优化
|
||||
|
||||
- ✅ **已实现**:
|
||||
- 只预缓存关键资源(入口 JS、vendor、入口 CSS、logo)
|
||||
- 路由组件的 CSS 和 JS **不预缓存**,按需加载
|
||||
- 访问登录页时只加载登录页资源,不会加载系统大部分资源
|
||||
- 💡 **建议**:确保静态资源(图片、字体)使用 CDN,配合缓存策略
|
||||
|
||||
### 2. 网络策略优化
|
||||
|
||||
- ✅ **已实现**:JS chunk 使用 NetworkFirst(3s 超时)
|
||||
- 💡 **建议**:可根据实际网络情况调整 `networkTimeoutSeconds`
|
||||
- 弱网环境:可适当增加超时时间(5-8s)
|
||||
- 强网环境:可减少超时时间(1-2s)
|
||||
|
||||
### 3. 缓存策略优化
|
||||
|
||||
- ✅ **已实现**:CSS、图片使用 CacheFirst(30天)
|
||||
- 💡 **建议**:
|
||||
- 静态资源(logo、图标):可延长至 90-180 天
|
||||
- 业务图片:保持 30 天,确保内容更新及时
|
||||
|
||||
### 4. 存储空间管理
|
||||
|
||||
- ✅ **已实现**:按需加载 chunk 限制 100 个,7 天过期
|
||||
- 💡 **建议**:
|
||||
- 监控缓存使用情况(Chrome DevTools → Application → Storage)
|
||||
- 根据用户访问模式调整 `maxEntries` 和 `maxAgeSeconds`
|
||||
|
||||
### 5. 用户体验优化
|
||||
|
||||
- ✅ **已实现**:Service Worker 后台注册,不阻塞页面加载
|
||||
- 💡 **建议**:
|
||||
- 添加加载提示(可选):显示"正在准备离线功能"
|
||||
- 错误处理:Service Worker 注册失败时优雅降级
|
||||
|
||||
### 6. 性能监控
|
||||
|
||||
建议监控以下指标:
|
||||
- **FCP(First Contentful Paint)**:目标 < 1.5s
|
||||
- **LCP(Largest Contentful Paint)**:目标 < 2.5s
|
||||
- **TTI(Time to Interactive)**:目标 < 3.5s
|
||||
- **缓存命中率**:目标 > 80%
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **仅生产环境生效** - 开发环境默认禁用
|
||||
2. **HTTPS 要求** - Service Worker 仅在 HTTPS 或 localhost 下工作
|
||||
3. **注册代码内联** - 使用 `injectRegister: 'inline'` 避免 `registerSW.js` 缓存问题
|
||||
4. **手动注册** - Service Worker 通过内联代码自动注册,但**不包含自动更新检测功能**
|
||||
5. **按需加载适配** - 配置已优化适配 Vue Router 的按需加载,只预缓存关键资源,路由组件 chunk 按需缓存
|
||||
|
||||
## 禁用 PWA
|
||||
|
||||
如需禁用 PWA 功能,在 `build/vite/plugin/index.ts` 中注释:
|
||||
|
||||
```typescript
|
||||
// vitePlugins.push(configPwaPlugin(isBuild));
|
||||
```
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 清除 Service Worker
|
||||
|
||||
浏览器控制台执行:
|
||||
|
||||
```javascript
|
||||
navigator.serviceWorker.getRegistrations().then(registrations => {
|
||||
registrations.forEach(registration => registration.unregister());
|
||||
});
|
||||
```
|
||||
|
||||
### 检查 Service Worker 状态
|
||||
|
||||
- Chrome DevTools → Application → Service Workers
|
||||
- 查看注册状态和缓存内容
|
||||
@ -1,106 +0,0 @@
|
||||
JeecgBoot 企业级低代码开发平台
|
||||
===============
|
||||
当前最新版本: 3.9.0(预计发布时间:2025-12-01)
|
||||
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
|
||||
[](http://jeecg.com/aboutusIndex)
|
||||
[](https://github.com
|
||||
/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
|
||||
|
||||
|
||||
## 简介
|
||||
JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue4、TypeScript 等新技术方案,包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能。
|
||||
|
||||
> 强大的代码生成器让前后端代码一键生成! JeecgBoot引领低代码开发模式(OnlineCoding-> 代码生成-> 手工MERGE), 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省成本,同时又不失灵活性
|
||||
|
||||
|
||||
## 开发环境搭建
|
||||
|
||||
- [前端开发环境准备](https://help.jeecg.com/setup/dev)
|
||||
- [前端项目快速启动](https://help.jeecg.com/setup/startup)
|
||||
- [通过IDEA启动项目](https://help.jeecg.com/java/setup/idea/startup)
|
||||
|
||||
## 技术文档
|
||||
|
||||
- 官方文档:[https://help.jeecg.com](https://help.jeecg.com)
|
||||
- 快速入门:[快速入门](http://jeecg.com/doc/quickstart) | [常见问题](http://help.jeecg.com/qa)
|
||||
- QQ交流群:964611995、⑩716488839(满)、⑨808791225(满)、其他满
|
||||
- 在线演示 : [系统演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)
|
||||
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取
|
||||
|
||||
|
||||
## 安装与使用
|
||||
|
||||
* 本地环境安装 `Node.js 、npm 、pnpm`
|
||||
* Node.js 版本要求`Node 20+` 版本以上
|
||||
|
||||
` ( 因为Vite5 不再支持已 EOL 的 Node.js 14 / 16 / 17 / 19,现在需要 Node 20+ )`
|
||||
|
||||
|
||||
|
||||
- Get the project code
|
||||
|
||||
```bash
|
||||
git clone https://github.com/jeecgboot/JeecgBoot.git
|
||||
```
|
||||
|
||||
- Installation dependencies
|
||||
|
||||
```bash
|
||||
cd JeecgBoot/jeecgboot-vue3
|
||||
|
||||
pnpm install
|
||||
```
|
||||
|
||||
- 配置接口地址 `.env.development`
|
||||
|
||||
```bash
|
||||
VITE_PROXY = [["/jeecgboot","http://localhost:8080/jeecg-boot"],["/upload","http://localhost:3300/upload"]]
|
||||
VITE_GLOB_DOMAIN_URL=http://localhost:8080/jeecg-boot
|
||||
```
|
||||
|
||||
> 说明:把`http://localhost:8080/jeecg-boot` 换成自己地址,其他不用改。
|
||||
|
||||
|
||||
- run
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
|
||||
- build
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## 入门必备
|
||||
|
||||
本项目需要一定前端基础知识,请确保掌握 Vue 的基础知识,以便能处理一些常见的问题。 建议在开发前先学一下以下内容,提前了解和学习这些知识,会对项目理解非常有帮助:
|
||||
|
||||
* [JeecgBoot文档](http://help.jeecg.com)
|
||||
* [Vue3 文档](https://cn.vuejs.org/)
|
||||
* [Vben文档](https://doc.vvbin.cn)
|
||||
* [Ant-Design-Vue](https://www.antdv.com/docs/vue/introduce-cn/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
* [Vue-router](https://router.vuejs.org/zh)
|
||||
* [Es6](https://es6.ruanyifeng.com/)
|
||||
* [Vitejs](https://cn.vitejs.dev/guide/)
|
||||
* [Pinia(vuex替代方案)](https://pinia.esm.dev/introduction.html)
|
||||
* [Vue-RFCS](https://github.com/vuejs/rfcs)
|
||||
* [vxetable文档](https://vxetable.cn)
|
||||
|
||||
|
||||
## 浏览器支持
|
||||
|
||||
**本地开发**推荐使用`Chrome 最新版`浏览器,**不支持**`Chrome 90`以下版本。
|
||||
|
||||
**生产环境**支持现代浏览器,不支持 IE。
|
||||
|
||||
| [](http://godban.github.io/browsers-support-badges/)IE | [](http://godban.github.io/browsers-support-badges/)Edge | [](http://godban.github.io/browsers-support-badges/)Firefox | [](http://godban.github.io/browsers-support-badges/)Chrome | [](http://godban.github.io/browsers-support-badges/)Safari |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
||||
@ -2,10 +2,8 @@ import type { AppRouteRecordRaw, AppRouteModule } from '/@/router/types';
|
||||
|
||||
import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/routes/basic';
|
||||
|
||||
import { mainOutRoutes } from './mainOut';
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
import { LAYOUT } from '/@/router/constant';
|
||||
|
||||
const modules = import.meta.glob('./modules/**/*.ts', { eager: true });
|
||||
|
||||
@ -65,4 +63,4 @@ export const TokenLoginRoute: AppRouteRecordRaw = {
|
||||
},
|
||||
};
|
||||
// Basic routing without permission
|
||||
export const basicRoutes = [LoginRoute, RootRoute, ...mainOutRoutes, REDIRECT_ROUTE, PAGE_NOT_FOUND_ROUTE, TokenLoginRoute, Oauth2LoginRoute];
|
||||
export const basicRoutes = [LoginRoute, RootRoute, REDIRECT_ROUTE, PAGE_NOT_FOUND_ROUTE, TokenLoginRoute, Oauth2LoginRoute];
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
/**
|
||||
The routing of this file will not show the layout.
|
||||
It is an independent new page.
|
||||
the contents of the file still need to log in to access
|
||||
*/
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
// test
|
||||
// http:ip:port/main-out
|
||||
export const mainOutRoutes: AppRouteModule[] = [
|
||||
{
|
||||
path: '/main-out',
|
||||
name: 'MainOut',
|
||||
component: () => import('/@/views/demo/main-out/index.vue'),
|
||||
meta: {
|
||||
title: 'MainOut',
|
||||
ignoreAuth: true,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const mainOutRouteNames = mainOutRoutes.map((item) => item.name);
|
||||
@ -1,79 +0,0 @@
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
import { getParentLayout, LAYOUT } from '/@/router/constant';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
|
||||
const charts: AppRouteModule = {
|
||||
path: '/charts',
|
||||
name: 'Charts',
|
||||
component: LAYOUT,
|
||||
redirect: '/charts/echarts/map',
|
||||
meta: {
|
||||
orderNo: 500,
|
||||
icon: 'ion:bar-chart-outline',
|
||||
title: t('routes.demo.charts.charts'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'baiduMap',
|
||||
name: 'BaiduMap',
|
||||
meta: {
|
||||
title: t('routes.demo.charts.baiduMap'),
|
||||
},
|
||||
component: () => import('/@/views/demo/charts/map/Baidu.vue'),
|
||||
},
|
||||
{
|
||||
path: 'aMap',
|
||||
name: 'AMap',
|
||||
meta: {
|
||||
title: t('routes.demo.charts.aMap'),
|
||||
},
|
||||
component: () => import('/@/views/demo/charts/map/Gaode.vue'),
|
||||
},
|
||||
{
|
||||
path: 'googleMap',
|
||||
name: 'GoogleMap',
|
||||
meta: {
|
||||
title: t('routes.demo.charts.googleMap'),
|
||||
},
|
||||
component: () => import('/@/views/demo/charts/map/Google.vue'),
|
||||
},
|
||||
{
|
||||
path: 'echarts',
|
||||
name: 'Echarts',
|
||||
component: getParentLayout('Echarts'),
|
||||
meta: {
|
||||
title: 'Echarts',
|
||||
},
|
||||
redirect: '/charts/echarts/map',
|
||||
children: [
|
||||
{
|
||||
path: 'map',
|
||||
name: 'Map',
|
||||
component: () => import('/@/views/demo/charts/Map.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.charts.map'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'line',
|
||||
name: 'Line',
|
||||
component: () => import('/@/views/demo/charts/Line.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.charts.line'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'pie',
|
||||
name: 'Pie',
|
||||
component: () => import('/@/views/demo/charts/Pie.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.charts.pie'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default charts;
|
||||
@ -1,692 +0,0 @@
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
import { getParentLayout, LAYOUT } from '/@/router/constant';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
|
||||
const comp: AppRouteModule = {
|
||||
path: '/comp',
|
||||
name: 'Comp',
|
||||
component: LAYOUT,
|
||||
redirect: '/comp/basic',
|
||||
meta: {
|
||||
orderNo: 30,
|
||||
icon: 'ion:layers-outline',
|
||||
title: t('routes.demo.comp.comp'),
|
||||
},
|
||||
|
||||
children: [
|
||||
{
|
||||
path: 'jeecg',
|
||||
name: 'JeecgDemo',
|
||||
redirect: '/comp/jeecg/basic',
|
||||
component: getParentLayout('JeecgDemo'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.jeecg'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'JAreaLinkage',
|
||||
component: () => import('/@/views/demo/jeecg/JeecgComponents.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.jeecg.JAreaLinkage'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'oneToMore',
|
||||
name: 'oneToMoreDemo',
|
||||
component: () => import('/@/views/demo/vextable/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.oneToMore'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'BasicDemo',
|
||||
component: getParentLayout('BasicDemo'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.basic'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'button',
|
||||
name: 'ButtonDemo',
|
||||
component: () => import('/@/views/demo/comp/button/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.basic.button'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'icon',
|
||||
name: 'IconDemo',
|
||||
component: () => import('/@/views/demo/feat/icon/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.icon'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'msg',
|
||||
name: 'MsgDemo',
|
||||
component: () => import('/@/views/demo/feat/msg/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.msg'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'tabs',
|
||||
name: 'TabsDemo',
|
||||
component: () => import('/@/views/demo/feat/tabs/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.tabs'),
|
||||
hideChildrenInMenu: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'detail/:id',
|
||||
name: 'TabDetail',
|
||||
component: () => import('/@/views/demo/feat/tabs/TabDetail.vue'),
|
||||
meta: {
|
||||
currentActiveMenu: '/comp/basic/tabs',
|
||||
title: t('routes.demo.feat.tabDetail'),
|
||||
hideMenu: true,
|
||||
dynamicLevel: 3,
|
||||
realPath: '/comp/basic/tabs/detail',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: 'form',
|
||||
name: 'FormDemo',
|
||||
redirect: '/comp/form/basic',
|
||||
component: getParentLayout('FormDemo'),
|
||||
meta: {
|
||||
// icon: 'mdi:form-select',
|
||||
title: t('routes.demo.form.form'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'FormBasicDemo',
|
||||
component: () => import('/@/views/demo/form/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.form.basic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'useForm',
|
||||
name: 'UseFormDemo',
|
||||
component: () => import('/@/views/demo/form/UseForm.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.form.useForm'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'refForm',
|
||||
name: 'RefFormDemo',
|
||||
component: () => import('/@/views/demo/form/RefForm.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.form.refForm'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'advancedForm',
|
||||
name: 'AdvancedFormDemo',
|
||||
component: () => import('/@/views/demo/form/AdvancedForm.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.form.advancedForm'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'ruleForm',
|
||||
name: 'RuleFormDemo',
|
||||
component: () => import('/@/views/demo/form/RuleForm.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.form.ruleForm'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'dynamicForm',
|
||||
name: 'DynamicFormDemo',
|
||||
component: () => import('/@/views/demo/form/DynamicForm.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.form.dynamicForm'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'customerForm',
|
||||
name: 'CustomerFormDemo',
|
||||
component: () => import('/@/views/demo/form/CustomerForm.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.form.customerForm'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'appendForm',
|
||||
name: 'appendFormDemo',
|
||||
component: () => import('/@/views/demo/form/AppendForm.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.form.appendForm'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'table',
|
||||
name: 'TableDemo',
|
||||
redirect: '/comp/table/basic',
|
||||
component: getParentLayout('TableDemo'),
|
||||
meta: {
|
||||
// icon: 'carbon:table-split',
|
||||
title: t('routes.demo.table.table'),
|
||||
},
|
||||
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'TableBasicDemo',
|
||||
component: () => import('/@/views/demo/table/Basic.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.basic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'treeTable',
|
||||
name: 'TreeTableDemo',
|
||||
component: () => import('/@/views/demo/table/TreeTable.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.treeTable'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'fetchTable',
|
||||
name: 'FetchTableDemo',
|
||||
component: () => import('/@/views/demo/table/FetchTable.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.fetchTable'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'fixedColumn',
|
||||
name: 'FixedColumnDemo',
|
||||
component: () => import('/@/views/demo/table/FixedColumn.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.fixedColumn'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'customerCell',
|
||||
name: 'CustomerCellDemo',
|
||||
component: () => import('/@/views/demo/table/CustomerCell.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.customerCell'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'formTable',
|
||||
name: 'FormTableDemo',
|
||||
component: () => import('/@/views/demo/table/FormTable.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.formTable'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'useTable',
|
||||
name: 'UseTableDemo',
|
||||
component: () => import('/@/views/demo/table/UseTable.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.useTable'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'refTable',
|
||||
name: 'RefTableDemo',
|
||||
component: () => import('/@/views/demo/table/RefTable.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.refTable'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'multipleHeader',
|
||||
name: 'MultipleHeaderDemo',
|
||||
component: () => import('/@/views/demo/table/MultipleHeader.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.multipleHeader'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'mergeHeader',
|
||||
name: 'MergeHeaderDemo',
|
||||
component: () => import('/@/views/demo/table/MergeHeader.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.mergeHeader'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'nestedTable',
|
||||
name: 'nestedTableDemo',
|
||||
component: () => import('/@/views/demo/table/NestedTable.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.nestedTable'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'expandTable',
|
||||
name: 'ExpandTableDemo',
|
||||
component: () => import('/@/views/demo/table/ExpandTable.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.expandTable'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'fixedHeight',
|
||||
name: 'FixedHeightDemo',
|
||||
component: () => import('/@/views/demo/table/FixedHeight.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.fixedHeight'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'footerTable',
|
||||
name: 'FooterTableDemo',
|
||||
component: () => import('/@/views/demo/table/FooterTable.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.footerTable'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'editCellTable',
|
||||
name: 'EditCellTableDemo',
|
||||
component: () => import('/@/views/demo/table/EditCellTable.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.editCellTable'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'editRowTable',
|
||||
name: 'EditRowTableDemo',
|
||||
component: () => import('/@/views/demo/table/EditRowTable.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.editRowTable'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'authColumn',
|
||||
name: 'AuthColumnDemo',
|
||||
component: () => import('/@/views/demo/table/AuthColumn.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.table.authColumn'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'modal',
|
||||
name: 'ModalDemo',
|
||||
redirect: '/comp/modal/basic',
|
||||
component: getParentLayout('ModalDemo'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.modal'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'ModalBasicDemo',
|
||||
component: () => import('/@/views/demo/comp/modal/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.modal.basic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'drawer',
|
||||
name: 'DrawerDemo',
|
||||
component: () => import('/@/views/demo/comp/drawer/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.modal.drawer'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: 'third',
|
||||
name: 'ThirdDemo',
|
||||
redirect: '/comp/third/basic',
|
||||
component: getParentLayout('ModalDemo'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.third'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'CropperDemo',
|
||||
component: () => import('/@/views/demo/comp/cropper/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.cropperImage'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'qrcode',
|
||||
name: 'QrCodeDemo',
|
||||
component: () => import('/@/views/demo/comp/qrcode/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.qrcode'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'strength-meter',
|
||||
name: 'StrengthMeterDemo',
|
||||
component: () => import('/@/views/demo/comp/strength-meter/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.strength'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'upload',
|
||||
name: 'UploadDemo',
|
||||
component: () => import('/@/views/demo/comp/upload/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.upload'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'loading',
|
||||
name: 'LoadingDemo',
|
||||
component: () => import('/@/views/demo/comp/loading/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.loading'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'timestamp',
|
||||
name: 'TimeDemo',
|
||||
component: () => import('/@/views/demo/comp/time/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.time'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'countTo',
|
||||
name: 'CountTo',
|
||||
component: () => import('/@/views/demo/comp/count-to/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.countTo'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'transition',
|
||||
name: 'transitionDemo',
|
||||
component: () => import('/@/views/demo/comp/transition/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.transition'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'print',
|
||||
name: 'Print',
|
||||
component: () => import('/@/views/demo/feat/print/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.print'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'img-preview',
|
||||
name: 'ImgPreview',
|
||||
component: () => import('/@/views/demo/feat/img-preview/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.imgPreview'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'download',
|
||||
name: 'DownLoadDemo',
|
||||
component: () => import('/@/views/demo/feat/download/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.download'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'click-out-side',
|
||||
name: 'ClickOutSideDemo',
|
||||
component: () => import('/@/views/demo/feat/click-out-side/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.clickOutSide'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'copy',
|
||||
name: 'CopyDemo',
|
||||
component: () => import('/@/views/demo/feat/copy/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.copy'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'ripple',
|
||||
name: 'RippleDemo',
|
||||
component: () => import('/@/views/demo/feat/ripple/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.ripple'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'tree',
|
||||
name: 'TreeDemo',
|
||||
redirect: '/comp/tree/basic',
|
||||
component: getParentLayout('TreeDemo'),
|
||||
meta: {
|
||||
// icon: 'clarity:tree-view-line',
|
||||
title: t('routes.demo.comp.tree'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'BasicTreeDemo',
|
||||
component: () => import('/@/views/demo/tree/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.treeBasic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'editTree',
|
||||
name: 'EditTreeDemo',
|
||||
component: () => import('/@/views/demo/tree/EditTree.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.editTree'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'actionTree',
|
||||
name: 'ActionTreeDemo',
|
||||
component: () => import('/@/views/demo/tree/ActionTree.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.actionTree'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'editor',
|
||||
name: 'EditorDemo',
|
||||
redirect: '/comp/editor/markdown',
|
||||
component: getParentLayout('EditorDemo'),
|
||||
meta: {
|
||||
// icon: 'carbon:table-split',
|
||||
title: t('routes.demo.editor.editor'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'json',
|
||||
component: () => import('/@/views/demo/editor/json/index.vue'),
|
||||
name: 'JsonEditorDemo',
|
||||
meta: {
|
||||
title: t('routes.demo.editor.jsonEditor'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'markdown',
|
||||
component: getParentLayout('MarkdownDemo'),
|
||||
name: 'MarkdownDemo',
|
||||
meta: {
|
||||
title: t('routes.demo.editor.markdown'),
|
||||
},
|
||||
redirect: '/comp/editor/markdown/index',
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'MarkDownBasicDemo',
|
||||
component: () => import('/@/views/demo/editor/markdown/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.editor.tinymceBasic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'editor',
|
||||
name: 'MarkDownFormDemo',
|
||||
component: () => import('/@/views/demo/editor/markdown/Editor.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.editor.tinymceForm'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: 'tinymce',
|
||||
component: getParentLayout('TinymceDemo'),
|
||||
name: 'TinymceDemo',
|
||||
meta: {
|
||||
title: t('routes.demo.editor.tinymce'),
|
||||
},
|
||||
redirect: '/comp/editor/tinymce/index',
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'TinymceBasicDemo',
|
||||
component: () => import('/@/views/demo/editor/tinymce/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.editor.tinymceBasic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'editor',
|
||||
name: 'TinymceFormDemo',
|
||||
component: () => import('/@/views/demo/editor/tinymce/Editor.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.editor.tinymceForm'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'scroll',
|
||||
name: 'ScrollDemo',
|
||||
redirect: '/comp/scroll/basic',
|
||||
component: getParentLayout('ScrollDemo'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.scroll'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'BasicScrollDemo',
|
||||
component: () => import('/@/views/demo/comp/scroll/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.scrollBasic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'action',
|
||||
name: 'ActionScrollDemo',
|
||||
component: () => import('/@/views/demo/comp/scroll/Action.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.scrollAction'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'virtualScroll',
|
||||
name: 'VirtualScrollDemo',
|
||||
component: () => import('/@/views/demo/comp/scroll/VirtualScroll.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.virtualScroll'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: 'desc',
|
||||
name: 'DescDemo',
|
||||
component: () => import('/@/views/demo/comp/desc/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.desc'),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
path: 'lazy',
|
||||
name: 'LazyDemo',
|
||||
component: getParentLayout('LazyDemo'),
|
||||
redirect: '/comp/lazy/basic',
|
||||
meta: {
|
||||
title: t('routes.demo.comp.lazy'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'BasicLazyDemo',
|
||||
component: () => import('/@/views/demo/comp/lazy/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.lazyBasic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'transition',
|
||||
name: 'BasicTransitionDemo',
|
||||
component: () => import('/@/views/demo/comp/lazy/Transition.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.lazyTransition'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'verify',
|
||||
name: 'VerifyDemo',
|
||||
component: getParentLayout('VerifyDemo'),
|
||||
redirect: '/comp/verify/drag',
|
||||
meta: {
|
||||
title: t('routes.demo.comp.verify'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'drag',
|
||||
name: 'VerifyDragDemo',
|
||||
component: () => import('/@/views/demo/comp/verify/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.verifyDrag'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'rotate',
|
||||
name: 'VerifyRotateDemo',
|
||||
component: () => import('/@/views/demo/comp/verify/Rotate.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.comp.verifyRotate'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default comp;
|
||||
@ -1,196 +0,0 @@
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
import { getParentLayout, LAYOUT } from '/@/router/constant';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
|
||||
const feat: AppRouteModule = {
|
||||
path: '/feat',
|
||||
name: 'FeatDemo',
|
||||
component: LAYOUT,
|
||||
redirect: '/feat/icon',
|
||||
meta: {
|
||||
orderNo: 19,
|
||||
icon: 'ion:git-compare-outline',
|
||||
title: t('routes.demo.feat.feat'),
|
||||
},
|
||||
|
||||
children: [
|
||||
{
|
||||
path: 'ws',
|
||||
name: 'WebSocket',
|
||||
component: () => import('/@/views/demo/feat/ws/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.ws'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'session-timeout',
|
||||
name: 'SessionTimeout',
|
||||
component: () => import('/@/views/demo/feat/session-timeout/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.sessionTimeout'),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
path: 'breadcrumb',
|
||||
name: 'BreadcrumbDemo',
|
||||
redirect: '/feat/breadcrumb/flat',
|
||||
component: getParentLayout('BreadcrumbDemo'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.breadcrumb'),
|
||||
},
|
||||
|
||||
children: [
|
||||
{
|
||||
path: 'flat',
|
||||
name: 'BreadcrumbFlatDemo',
|
||||
component: () => import('/@/views/demo/feat/breadcrumb/FlatList.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.breadcrumbFlat'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'flatDetail',
|
||||
name: 'BreadcrumbFlatDetailDemo',
|
||||
component: () => import('/@/views/demo/feat/breadcrumb/FlatListDetail.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.breadcrumbFlatDetail'),
|
||||
hideMenu: true,
|
||||
hideTab: true,
|
||||
currentActiveMenu: '/feat/breadcrumb/flat',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'children',
|
||||
name: 'BreadcrumbChildrenDemo',
|
||||
component: () => import('/@/views/demo/feat/breadcrumb/ChildrenList.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.breadcrumbChildren'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'childrenDetail',
|
||||
name: 'BreadcrumbChildrenDetailDemo',
|
||||
component: () => import('/@/views/demo/feat/breadcrumb/ChildrenListDetail.vue'),
|
||||
meta: {
|
||||
currentActiveMenu: '/feat/breadcrumb/children',
|
||||
title: t('routes.demo.feat.breadcrumbChildrenDetail'),
|
||||
//hideTab: true,
|
||||
// hideMenu: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
path: 'context-menu',
|
||||
name: 'ContextMenuDemo',
|
||||
component: () => import('/@/views/demo/feat/context-menu/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.contextMenu'),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
path: 'copy',
|
||||
name: 'CopyDemo',
|
||||
component: () => import('/@/views/demo/feat/copy/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.copy'),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
path: 'watermark',
|
||||
name: 'WatermarkDemo',
|
||||
component: () => import('/@/views/demo/feat/watermark/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.watermark'),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
path: 'full-screen',
|
||||
name: 'FullScreenDemo',
|
||||
component: () => import('/@/views/demo/feat/full-screen/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.fullScreen'),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
path: '/error-log',
|
||||
name: 'ErrorLog',
|
||||
component: () => import('/@/views/sys/error-log/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.errorLog'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'testTab/:id',
|
||||
name: 'TestTab',
|
||||
component: () => import('/@/views/demo/feat/tab-params/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.tab'),
|
||||
carryParam: true,
|
||||
hidePathForChildren: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'testTab/id1',
|
||||
name: 'TestTab1',
|
||||
component: () => import('/@/views/demo/feat/tab-params/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.tab1'),
|
||||
carryParam: true,
|
||||
ignoreRoute: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'testTab/id2',
|
||||
name: 'TestTab2',
|
||||
component: () => import('/@/views/demo/feat/tab-params/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.tab2'),
|
||||
carryParam: true,
|
||||
ignoreRoute: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'testParam/:id',
|
||||
name: 'TestParam',
|
||||
component: getParentLayout('TestParam'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.menu'),
|
||||
ignoreKeepAlive: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'sub1',
|
||||
name: 'TestParam_1',
|
||||
component: () => import('/@/views/demo/feat/menu-params/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.menu1'),
|
||||
ignoreKeepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'sub2',
|
||||
name: 'TestParam_2',
|
||||
component: () => import('/@/views/demo/feat/menu-params/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.feat.menu2'),
|
||||
ignoreKeepAlive: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default feat;
|
||||
@ -1,48 +0,0 @@
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
import { LAYOUT } from '/@/router/constant';
|
||||
const IFrame = () => import('/@/views/sys/iframe/FrameBlank.vue');
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
|
||||
const iframe: AppRouteModule = {
|
||||
path: '/frame',
|
||||
name: 'Frame',
|
||||
component: LAYOUT,
|
||||
redirect: '/frame/doc',
|
||||
meta: {
|
||||
orderNo: 1000,
|
||||
icon: 'ion:tv-outline',
|
||||
title: t('routes.demo.iframe.frame'),
|
||||
},
|
||||
|
||||
children: [
|
||||
{
|
||||
path: 'doc',
|
||||
name: 'Doc',
|
||||
component: IFrame,
|
||||
meta: {
|
||||
frameSrc: 'https://vvbin.cn/doc-next/',
|
||||
title: t('routes.demo.iframe.doc'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'antv',
|
||||
name: 'Antv',
|
||||
component: IFrame,
|
||||
meta: {
|
||||
frameSrc: 'https://2x.antdv.com/docs/vue/introduce-cn/',
|
||||
title: t('routes.demo.iframe.antv'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'https://vvbin.cn/doc-next/',
|
||||
name: 'DocExternal',
|
||||
component: IFrame,
|
||||
meta: {
|
||||
title: t('routes.demo.iframe.docExternal'),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default iframe;
|
||||
@ -1,68 +0,0 @@
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
import { getParentLayout, LAYOUT } from '/@/router/constant';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
|
||||
const permission: AppRouteModule = {
|
||||
path: '/level',
|
||||
name: 'Level',
|
||||
component: LAYOUT,
|
||||
redirect: '/level/menu1/menu1-1/menu1-1-1',
|
||||
meta: {
|
||||
orderNo: 2000,
|
||||
icon: 'ion:menu-outline',
|
||||
title: t('routes.demo.level.level'),
|
||||
},
|
||||
|
||||
children: [
|
||||
{
|
||||
path: 'menu1',
|
||||
name: 'Menu1Demo',
|
||||
component: getParentLayout('Menu1Demo'),
|
||||
meta: {
|
||||
title: 'Menu1',
|
||||
},
|
||||
redirect: '/level/menu1/menu1-1/menu1-1-1',
|
||||
children: [
|
||||
{
|
||||
path: 'menu1-1',
|
||||
name: 'Menu11Demo',
|
||||
component: getParentLayout('Menu11Demo'),
|
||||
meta: {
|
||||
title: 'Menu1-1',
|
||||
},
|
||||
redirect: '/level/menu1/menu1-1/menu1-1-1',
|
||||
children: [
|
||||
{
|
||||
path: 'menu1-1-1',
|
||||
name: 'Menu111Demo',
|
||||
component: () => import('/@/views/demo/level/Menu111.vue'),
|
||||
meta: {
|
||||
title: 'Menu111',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'menu1-2',
|
||||
name: 'Menu12Demo',
|
||||
component: () => import('/@/views/demo/level/Menu12.vue'),
|
||||
meta: {
|
||||
title: 'Menu1-2',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'menu2',
|
||||
name: 'Menu2Demo',
|
||||
component: () => import('/@/views/demo/level/Menu2.vue'),
|
||||
meta: {
|
||||
title: 'Menu2',
|
||||
// ignoreKeepAlive: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default permission;
|
||||
@ -1,255 +0,0 @@
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
import { getParentLayout, LAYOUT } from '/@/router/constant';
|
||||
import { ExceptionEnum } from '/@/enums/exceptionEnum';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
|
||||
const ExceptionPage = () => import('/@/views/sys/exception/Exception.vue');
|
||||
|
||||
const page: AppRouteModule = {
|
||||
path: '/page-demo',
|
||||
name: 'PageDemo',
|
||||
component: LAYOUT,
|
||||
redirect: '/page-demo/form/basic',
|
||||
meta: {
|
||||
orderNo: 20,
|
||||
icon: 'ion:aperture-outline',
|
||||
title: t('routes.demo.page.page'),
|
||||
},
|
||||
children: [
|
||||
// =============================form start=============================
|
||||
{
|
||||
path: 'form',
|
||||
name: 'FormPage',
|
||||
redirect: '/page-demo/form/basic',
|
||||
component: getParentLayout('FormPage'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.form'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'FormBasicPage',
|
||||
component: () => import('/@/views/demo/page/form/basic/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.formBasic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'step',
|
||||
name: 'FormStepPage',
|
||||
component: () => import('/@/views/demo/page/form/step/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.formStep'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'high',
|
||||
name: 'FormHightPage',
|
||||
component: () => import('/@/views/demo/page/form/high/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.formHigh'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// =============================form end=============================
|
||||
// =============================desc start=============================
|
||||
{
|
||||
path: 'desc',
|
||||
name: 'DescPage',
|
||||
component: getParentLayout('DescPage'),
|
||||
redirect: '/page-demo/desc/basic',
|
||||
meta: {
|
||||
title: t('routes.demo.page.desc'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'DescBasicPage',
|
||||
component: () => import('/@/views/demo/page/desc/basic/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.descBasic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'high',
|
||||
name: 'DescHighPage',
|
||||
component: () => import('/@/views/demo/page/desc/high/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.descHigh'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// =============================desc end=============================
|
||||
|
||||
// =============================result start=============================
|
||||
{
|
||||
path: 'result',
|
||||
name: 'ResultPage',
|
||||
redirect: '/page-demo/result/success',
|
||||
component: getParentLayout('ResultPage'),
|
||||
|
||||
meta: {
|
||||
title: t('routes.demo.page.result'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'success',
|
||||
name: 'ResultSuccessPage',
|
||||
component: () => import('/@/views/demo/page/result/success/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.resultSuccess'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'fail',
|
||||
name: 'ResultFailPage',
|
||||
component: () => import('/@/views/demo/page/result/fail/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.resultFail'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// =============================result end=============================
|
||||
|
||||
// =============================account start=============================
|
||||
{
|
||||
path: 'account',
|
||||
name: 'AccountPage',
|
||||
component: getParentLayout('AccountPage'),
|
||||
redirect: '/page-demo/account/setting',
|
||||
meta: {
|
||||
title: t('routes.demo.page.account'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'center',
|
||||
name: 'AccountCenterPage',
|
||||
component: () => import('/@/views/demo/page/account/center/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.accountCenter'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'setting',
|
||||
name: 'AccountSettingPage',
|
||||
component: () => import('/@/views/demo/page/account/setting/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.accountSetting'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// =============================account end=============================
|
||||
// =============================exception start=============================
|
||||
{
|
||||
path: 'exception',
|
||||
name: 'ExceptionPage',
|
||||
component: getParentLayout('ExceptionPage'),
|
||||
redirect: '/page-demo/exception/404',
|
||||
meta: {
|
||||
title: t('routes.demo.page.exception'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '403',
|
||||
name: 'PageNotAccess',
|
||||
component: ExceptionPage,
|
||||
props: {
|
||||
status: ExceptionEnum.PAGE_NOT_ACCESS,
|
||||
},
|
||||
meta: {
|
||||
title: '403',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '404',
|
||||
name: 'PageNotFound',
|
||||
component: ExceptionPage,
|
||||
props: {
|
||||
status: ExceptionEnum.PAGE_NOT_FOUND,
|
||||
},
|
||||
meta: {
|
||||
title: '404',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '500',
|
||||
name: 'ServiceError',
|
||||
component: ExceptionPage,
|
||||
props: {
|
||||
status: ExceptionEnum.ERROR,
|
||||
},
|
||||
meta: {
|
||||
title: '500',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'net-work-error',
|
||||
name: 'NetWorkError',
|
||||
component: ExceptionPage,
|
||||
props: {
|
||||
status: ExceptionEnum.NET_WORK_ERROR,
|
||||
},
|
||||
meta: {
|
||||
title: t('routes.demo.page.netWorkError'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'not-data',
|
||||
name: 'NotData',
|
||||
component: ExceptionPage,
|
||||
props: {
|
||||
status: ExceptionEnum.PAGE_NOT_DATA,
|
||||
},
|
||||
meta: {
|
||||
title: t('routes.demo.page.notData'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// =============================exception end=============================
|
||||
// =============================list start=============================
|
||||
{
|
||||
path: 'list',
|
||||
name: 'ListPage',
|
||||
component: getParentLayout('ListPage'),
|
||||
redirect: '/page-demo/list/card',
|
||||
meta: {
|
||||
title: t('routes.demo.page.list'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: 'ListBasicPage',
|
||||
component: () => import('/@/views/demo/page/list/basic/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.listBasic'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'card',
|
||||
name: 'ListCardPage',
|
||||
component: () => import('/@/views/demo/page/list/card/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.listCard'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'search',
|
||||
name: 'ListSearchPage',
|
||||
component: () => import('/@/views/demo/page/list/search/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.page.listSearch'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// =============================list end=============================
|
||||
],
|
||||
};
|
||||
|
||||
export default page;
|
||||
@ -1,92 +0,0 @@
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
import { getParentLayout, LAYOUT } from '/@/router/constant';
|
||||
import { RoleEnum } from '/@/enums/roleEnum';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
|
||||
const permission: AppRouteModule = {
|
||||
path: '/permission',
|
||||
name: 'Permission',
|
||||
component: LAYOUT,
|
||||
redirect: '/permission/front/page',
|
||||
meta: {
|
||||
orderNo: 15,
|
||||
icon: 'ion:key-outline',
|
||||
title: t('routes.demo.permission.permission'),
|
||||
},
|
||||
|
||||
children: [
|
||||
{
|
||||
path: 'front',
|
||||
name: 'PermissionFrontDemo',
|
||||
component: getParentLayout('PermissionFrontDemo'),
|
||||
meta: {
|
||||
title: t('routes.demo.permission.front'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'page',
|
||||
name: 'FrontPageAuth',
|
||||
component: () => import('/@/views/demo/permission/front/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.permission.frontPage'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'btn',
|
||||
name: 'FrontBtnAuth',
|
||||
component: () => import('/@/views/demo/permission/front/Btn.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.permission.frontBtn'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'auth-pageA',
|
||||
name: 'FrontAuthPageA',
|
||||
component: () => import('/@/views/demo/permission/front/AuthPageA.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.permission.frontTestA'),
|
||||
roles: [RoleEnum.SUPER],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'auth-pageB',
|
||||
name: 'FrontAuthPageB',
|
||||
component: () => import('/@/views/demo/permission/front/AuthPageB.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.permission.frontTestB'),
|
||||
roles: [RoleEnum.TEST],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'back',
|
||||
name: 'PermissionBackDemo',
|
||||
component: getParentLayout('PermissionBackDemo'),
|
||||
meta: {
|
||||
title: t('routes.demo.permission.back'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'page',
|
||||
name: 'BackAuthPage',
|
||||
component: () => import('/@/views/demo/permission/back/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.permission.backPage'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'btn',
|
||||
name: 'BackAuthBtn',
|
||||
component: () => import('/@/views/demo/permission/back/Btn.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.permission.backBtn'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default permission;
|
||||
@ -1,31 +0,0 @@
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
import { LAYOUT } from '/@/router/constant';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
|
||||
const setup: AppRouteModule = {
|
||||
path: '/setup',
|
||||
name: 'SetupDemo',
|
||||
component: LAYOUT,
|
||||
redirect: '/setup/index',
|
||||
meta: {
|
||||
orderNo: 90000,
|
||||
hideChildrenInMenu: true,
|
||||
icon: 'whh:paintroll',
|
||||
title: t('routes.demo.setup.page'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'SetupDemoPage',
|
||||
component: () => import('/@/views/demo/setup/index.vue'),
|
||||
meta: {
|
||||
title: t('routes.demo.setup.page'),
|
||||
icon: 'whh:paintroll',
|
||||
hideMenu: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default setup;
|
||||
@ -1,86 +0,0 @@
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
import { LAYOUT } from '/@/router/constant';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
|
||||
const system: AppRouteModule = {
|
||||
path: '/system',
|
||||
name: 'System',
|
||||
component: LAYOUT,
|
||||
redirect: '/system/account',
|
||||
meta: {
|
||||
orderNo: 2000,
|
||||
icon: 'ion:settings-outline',
|
||||
title: t('routes.demo.system.moduleName'),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'test',
|
||||
name: 'TestManagement',
|
||||
meta: {
|
||||
title: t('routes.demo.system.test'),
|
||||
ignoreKeepAlive: true,
|
||||
},
|
||||
component: () => import('/@/views/demo/system/test/index.vue'),
|
||||
},
|
||||
{
|
||||
path: 'account',
|
||||
name: 'AccountManagement',
|
||||
meta: {
|
||||
title: t('routes.demo.system.account'),
|
||||
ignoreKeepAlive: false,
|
||||
},
|
||||
component: () => import('/@/views/demo/system/account/index.vue'),
|
||||
},
|
||||
{
|
||||
path: 'account_detail/:id',
|
||||
name: 'AccountDetail',
|
||||
meta: {
|
||||
hideMenu: true,
|
||||
title: t('routes.demo.system.account_detail'),
|
||||
ignoreKeepAlive: true,
|
||||
showMenu: false,
|
||||
currentActiveMenu: '/system/account',
|
||||
},
|
||||
component: () => import('/@/views/demo/system/account/AccountDetail.vue'),
|
||||
},
|
||||
{
|
||||
path: 'role',
|
||||
name: 'RoleManagement',
|
||||
meta: {
|
||||
title: t('routes.demo.system.role'),
|
||||
ignoreKeepAlive: true,
|
||||
},
|
||||
component: () => import('/@/views/demo/system/role/index.vue'),
|
||||
},
|
||||
{
|
||||
path: 'menu',
|
||||
name: 'MenuManagement',
|
||||
meta: {
|
||||
title: t('routes.demo.system.menu'),
|
||||
ignoreKeepAlive: true,
|
||||
},
|
||||
component: () => import('/@/views/demo/system/menu/index.vue'),
|
||||
},
|
||||
{
|
||||
path: 'dept',
|
||||
name: 'DeptManagement',
|
||||
meta: {
|
||||
title: t('routes.demo.system.dept'),
|
||||
ignoreKeepAlive: true,
|
||||
},
|
||||
component: () => import('/@/views/demo/system/dept/index.vue'),
|
||||
},
|
||||
{
|
||||
path: 'changePassword',
|
||||
name: 'ChangePassword',
|
||||
meta: {
|
||||
title: t('routes.demo.system.password'),
|
||||
ignoreKeepAlive: true,
|
||||
},
|
||||
component: () => import('/@/views/demo/system/password/index.vue'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default system;
|
||||
@ -1,117 +0,0 @@
|
||||
<template>
|
||||
<div ref="chartRef" :style="{ height, width }"></div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, ref, Ref, onMounted } from 'vue';
|
||||
|
||||
import { useECharts } from '/@/hooks/web/useECharts';
|
||||
import { getLineData } from './data';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
width: {
|
||||
type: String as PropType<string>,
|
||||
default: '100%',
|
||||
},
|
||||
height: {
|
||||
type: String as PropType<string>,
|
||||
default: 'calc(100vh - 78px)',
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const chartRef = ref<HTMLDivElement | null>(null);
|
||||
const { setOptions, echarts } = useECharts(chartRef as Ref<HTMLDivElement>);
|
||||
const { barData, lineData, category } = getLineData;
|
||||
onMounted(() => {
|
||||
setOptions({
|
||||
backgroundColor: '#0f375f',
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
label: {
|
||||
show: true,
|
||||
backgroundColor: '#333',
|
||||
},
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
data: ['line', 'bar'],
|
||||
textStyle: {
|
||||
color: '#ccc',
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
data: category,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#ccc',
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
splitLine: { show: false },
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#ccc',
|
||||
},
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'line',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
showAllSymbol: 'auto',
|
||||
symbol: 'emptyCircle',
|
||||
symbolSize: 15,
|
||||
data: lineData,
|
||||
},
|
||||
{
|
||||
name: 'bar',
|
||||
type: 'bar',
|
||||
barWidth: 10,
|
||||
itemStyle: {
|
||||
borderRadius: 5,
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#14c8d4' },
|
||||
{ offset: 1, color: '#43eec6' },
|
||||
]),
|
||||
},
|
||||
data: barData,
|
||||
},
|
||||
{
|
||||
name: 'line',
|
||||
type: 'bar',
|
||||
barGap: '-100%',
|
||||
barWidth: 10,
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(20,200,212,0.5)' },
|
||||
{ offset: 0.2, color: 'rgba(20,200,212,0.2)' },
|
||||
{ offset: 1, color: 'rgba(20,200,212,0)' },
|
||||
]),
|
||||
},
|
||||
z: -12,
|
||||
data: lineData,
|
||||
},
|
||||
{
|
||||
name: 'dotted',
|
||||
type: 'pictorialBar',
|
||||
symbol: 'rect',
|
||||
itemStyle: {
|
||||
color: '#0f375f',
|
||||
},
|
||||
symbolRepeat: true,
|
||||
symbolSize: [12, 4],
|
||||
symbolMargin: 1,
|
||||
z: -10,
|
||||
data: lineData,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
return { chartRef };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,75 +0,0 @@
|
||||
<template>
|
||||
<div ref="chartRef" :style="{ height, width }"></div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, ref, Ref, onMounted } from 'vue';
|
||||
|
||||
import { useECharts } from '/@/hooks/web/useECharts';
|
||||
import { mapData } from './data';
|
||||
import { registerMap } from 'echarts';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
width: {
|
||||
type: String as PropType<string>,
|
||||
default: '100%',
|
||||
},
|
||||
height: {
|
||||
type: String as PropType<string>,
|
||||
default: 'calc(100vh - 78px)',
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const chartRef = ref<HTMLDivElement | null>(null);
|
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
|
||||
|
||||
onMounted(async () => {
|
||||
const json = (await (await import('./china.json')).default) as any;
|
||||
registerMap('china', json);
|
||||
setOptions({
|
||||
visualMap: [
|
||||
{
|
||||
min: 0,
|
||||
max: 1000,
|
||||
left: 'left',
|
||||
top: 'bottom',
|
||||
text: ['高', '低'],
|
||||
calculable: false,
|
||||
orient: 'horizontal',
|
||||
inRange: {
|
||||
color: ['#e0ffff', '#006edd'],
|
||||
symbolSize: [30, 100],
|
||||
},
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
backgroundColor: 'rgba(0, 0, 0, .6)',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'iphone4',
|
||||
type: 'map',
|
||||
map: 'china',
|
||||
label: {
|
||||
show: true,
|
||||
color: 'rgb(249, 249, 249)',
|
||||
fontSize: 10,
|
||||
},
|
||||
itemStyle: {
|
||||
areaColor: '#2f82ce',
|
||||
borderColor: '#0DAAC1',
|
||||
},
|
||||
data: mapData,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
return { chartRef };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,135 +0,0 @@
|
||||
<template>
|
||||
<div ref="chartRef" :style="{ height, width }"></div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, ref, Ref, onMounted } from 'vue';
|
||||
|
||||
import { useECharts } from '/@/hooks/web/useECharts';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
width: {
|
||||
type: String as PropType<string>,
|
||||
default: '100%',
|
||||
},
|
||||
height: {
|
||||
type: String as PropType<string>,
|
||||
default: 'calc(100vh - 78px)',
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const chartRef = ref<HTMLDivElement | null>(null);
|
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
|
||||
const dataAll = [389, 259, 262, 324, 232, 176, 196, 214, 133, 370];
|
||||
const yAxisData = ['原因1', '原因2', '原因3', '原因4', '原因5', '原因6', '原因7', '原因8', '原因9', '原因10'];
|
||||
onMounted(() => {
|
||||
setOptions({
|
||||
backgroundColor: '#0f375f',
|
||||
title: [
|
||||
{
|
||||
text: '各渠道投诉占比',
|
||||
left: '2%',
|
||||
top: '1%',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '投诉原因TOP10',
|
||||
left: '40%',
|
||||
top: '1%',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '各级别投诉占比',
|
||||
left: '2%',
|
||||
top: '50%',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
],
|
||||
grid: [{ left: '50%', top: '7%', width: '45%', height: '90%' }],
|
||||
tooltip: {
|
||||
formatter: '{b} ({c})',
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
gridIndex: 0,
|
||||
axisTick: { show: false },
|
||||
axisLabel: { show: false },
|
||||
splitLine: { show: false },
|
||||
axisLine: { show: false },
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
gridIndex: 0,
|
||||
interval: 0,
|
||||
data: yAxisData.reverse(),
|
||||
axisTick: { show: false },
|
||||
axisLabel: { show: true },
|
||||
splitLine: { show: false },
|
||||
axisLine: { show: true, lineStyle: { color: '#6173a3' } },
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '各渠道投诉占比',
|
||||
type: 'pie',
|
||||
radius: '30%',
|
||||
center: ['22%', '25%'],
|
||||
data: [
|
||||
{ value: 335, name: '客服电话' },
|
||||
{ value: 310, name: '奥迪官网' },
|
||||
{ value: 234, name: '媒体曝光' },
|
||||
{ value: 135, name: '质检总局' },
|
||||
{ value: 105, name: '其他' },
|
||||
],
|
||||
labelLine: { show: false },
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b} \n ({d}%)',
|
||||
color: '#B1B9D3',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '各级别投诉占比',
|
||||
type: 'pie',
|
||||
radius: '30%',
|
||||
center: ['22%', '75%'],
|
||||
labelLine: { show: false },
|
||||
data: [
|
||||
{ value: 335, name: 'A级' },
|
||||
{ value: 310, name: 'B级' },
|
||||
{ value: 234, name: 'C级' },
|
||||
{ value: 135, name: 'D级' },
|
||||
],
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b} \n ({d}%)',
|
||||
color: '#B1B9D3',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '投诉原因TOP10',
|
||||
type: 'bar',
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
barWidth: '45%',
|
||||
itemStyle: { color: '#86c9f4' },
|
||||
label: { show: true, position: 'right', color: '#9EA7C4' },
|
||||
data: dataAll.sort(),
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
return { chartRef };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,100 +0,0 @@
|
||||
<template>
|
||||
<Card title="销售统计" :loading="loading">
|
||||
<div ref="chartRef" :style="{ width, height }"></div>
|
||||
</Card>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { Ref } from 'vue';
|
||||
import { defineComponent, ref, watch } from 'vue';
|
||||
import { Card } from 'ant-design-vue';
|
||||
import { useECharts } from '/@/hooks/web/useECharts';
|
||||
|
||||
export default defineComponent({
|
||||
components: { Card },
|
||||
props: {
|
||||
loading: Boolean,
|
||||
width: {
|
||||
type: String as PropType<string>,
|
||||
default: '100%',
|
||||
},
|
||||
height: {
|
||||
type: String as PropType<string>,
|
||||
default: '400px',
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const chartRef = ref<HTMLDivElement | null>(null);
|
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
|
||||
watch(
|
||||
() => props.loading,
|
||||
() => {
|
||||
if (props.loading) {
|
||||
return;
|
||||
}
|
||||
setOptions({
|
||||
legend: {
|
||||
bottom: 0,
|
||||
data: ['Visits', 'Sales'],
|
||||
},
|
||||
tooltip: {},
|
||||
radar: {
|
||||
radius: '60%',
|
||||
splitNumber: 8,
|
||||
indicator: [
|
||||
{
|
||||
name: '2017',
|
||||
},
|
||||
{
|
||||
name: '2017',
|
||||
},
|
||||
{
|
||||
name: '2018',
|
||||
},
|
||||
{
|
||||
name: '2019',
|
||||
},
|
||||
{
|
||||
name: '2020',
|
||||
},
|
||||
{
|
||||
name: '2021',
|
||||
},
|
||||
],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'radar' as 'custom',
|
||||
symbolSize: 0,
|
||||
areaStyle: {
|
||||
shadowBlur: 0,
|
||||
shadowColor: 'rgba(0,0,0,.2)',
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetY: 10,
|
||||
opacity: 1,
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: [90, 50, 86, 40, 50, 20],
|
||||
name: 'Visits',
|
||||
itemStyle: {
|
||||
color: '#9f8ed7',
|
||||
},
|
||||
},
|
||||
{
|
||||
value: [70, 75, 70, 76, 20, 85],
|
||||
name: 'Sales',
|
||||
itemStyle: {
|
||||
color: '#1edec5',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
return { chartRef };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,839 +0,0 @@
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "710000",
|
||||
"properties": {
|
||||
"id": "710000",
|
||||
"cp": [121.509062, 24.044332],
|
||||
"name": "台湾",
|
||||
"childNum": 6
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@°Ü¯Û"],
|
||||
["@@ƛĴÕƊÉɼģºðʀ\\ƎsÆNŌÔĚänÜƤɊĂǀĆĴĤNJŨxĚĮǂƺòƌâÔ®ĮXŦţƸZûÐƕƑGđ¨ĭMó·ęcëƝɉlÝƯֹÅŃ^Ó·śŃNjƏďíåɛGɉ¿@ăƑ¥ĘWǬÏĶŁâ"],
|
||||
["@@\\p|WoYG¿¥Ij@¢"],
|
||||
["@@
¡@V^RqBbAnTXeRz¤L«³I"],
|
||||
["@@ÆEEkWqë @"],
|
||||
["@@fced"],
|
||||
["@@¯ɜÄèaì¯ØǓIġĽ"],
|
||||
["@@çûĖëĄhòř "]
|
||||
],
|
||||
"encodeOffsets": [
|
||||
[[122886, 24033]],
|
||||
[[123335, 22980]],
|
||||
[[122375, 24193]],
|
||||
[[122518, 24117]],
|
||||
[[124427, 22618]],
|
||||
[[124862, 26043]],
|
||||
[[126259, 26318]],
|
||||
[[127671, 26683]]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "130000",
|
||||
"properties": {
|
||||
"id": "130000",
|
||||
"cp": [114.502461, 38.045474],
|
||||
"name": "河北",
|
||||
"childNum": 3
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@o~Z]ªrºc_ħ²G¼s`jΟnüsÂłNX_M`ǽÓnUK
Ĝēs¤©yrý§uģcJe"],
|
||||
["@@U`Ts¿mÂ"],
|
||||
[
|
||||
"@@oºƋÄdeVDJj£J|ÅdzÂFt~KŨ¸IÆv|¢r}èonb}`RÎÄn°ÒdÞ²^®lnÐèĄlðÓ×]ªÆ}LiñÖ`^°Ç¶p®đDcŋ`ZÔ¶êqvFÆN®ĆTH®¦O¾IbÐã´BĐɢŴÆíȦpĐÞXR·nndO¤OÀĈƒQgµFo|gȒęSWb©osx|hYhgŃfmÖĩnºTÌSp¢dYĤ¶UĈjlǐpäìë|³kÛfw²Xjz~ÂqbTÑěŨ@|oMzv¢ZrÃVw¬ŧˏf°ÐTªqs{S¯r æÝlNd®²Ğ džiGĘJ¼lr}~K¨ŸƐÌWöÆzR¤lêmĞLÎ@¡|q]SvKÑcwpÏÏĿćènĪWlĄkT}J¤~ÈTdpddʾĬBVtEÀ¢ôPĎƗè@~kü\\rÊĔÖæW_§¼F´©òDòjYÈrbĞāøŀG{ƀ|¦ðrb|ÀH`pʞkvGpuARhÞÆǶgĘTǼƹS£¨¡ù³ŘÍ]¿ÂyôEP xX¶¹ÜO¡gÚ¡IwÃé¦ÅBÏ|ǰ
N«úmH¯âDùyŜŲIÄuШD¸dɂFOhđ©OiÃ`ww^ÌkÑH«ƇǤŗĺtFu
{Z}Ö@U´
ʚLg®¯Oı°Ãw ^VbÉsmA
ê]]w§RRl£ȭµu¯b{ÍDěïÿȧuT£ġěŗƃĝQ¨fVƋƅna@³@ďyýIĹÊKŭfċŰóxV@tƯJ]eR¾fe|rHA|h~Ėƍl§ÏlTíb ØoÅbbx³^zÃͶSj®AyÂhðk`«P˵EFÛ¬Y¨Ļrõqi¼Wi°§Ð±´°^[À|ĠO@ÆxO\\ta\\tĕtû{ġȧXýĪÓjùÎRb^ÎfK[ÝděYfíÙTyuUSyŌŏů@Oi½éŅaVcř§ax¹XŻácWU£ôãºQ¨÷Ñws¥qEHÙ|šYQoŕÇyáĂ£MðoťÊP¡mWO¡v{ôvîēÜISpÌhp¨ jdeŔQÖjX³àĈ[n`Yp@UcM`RKhEbpŞlNut®EtqnsÁgAiúoHqCXhfgu~ÏWP½¢G^}¯ÅīGCÑ^ãziMáļMTÃƘrMc|O_¯Ŏ´|morDkO\\mĆJfl@c̬¢aĦtRıÒ¾ùƀ^juųœKUFyƝ
īÛ÷ąV×qƥV¿aȉd³BqPBmaËđŻģmÅ®V¹d^KKonYg¯XhqaLdu¥ÍpDž¡KąÅkĝęěhq}HyÃ]¹ǧ£
Í÷¿qáµ§g¤o^á¾ZE¤i`ij{nOl»WÝĔįhgF[¿¡ßkOüš_ūiDZàUtėGyl}ÓM}jpEC~¡FtoQiHkk{Ãmï"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[119712, 40641]], [[121616, 39981]], [[116462, 37237]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "140000",
|
||||
"properties": {
|
||||
"id": "140000",
|
||||
"cp": [111.849248, 36.857014],
|
||||
"name": "山西",
|
||||
"childNum": 1
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@ÞĩÒSra}ÁyWix±Üe´lèßÓǏokćiµVZģ¡coTS˹ĪmnÕńehZg{gtwªpXaĚThȑp{¶Eh®RćƑP¿£Pmc¸mQÝWďȥoÅîɡųAďä³aÏJ½¥PGąSM
EÅruµéYÓŌ_dĒCoȵ]¯_²ÕjāK~©ÅØ^ÔkïçămÏk]±cݯÑÃmQÍ~_apm
~ç¡qu{JÅŧ·Ls}EyÁÆcI{¤IiCfUcƌÃp§]ě«vD@¡SÀµMÅwuYY¡DbÑc¡h×]nkoQdaMç~eDÛtT©±@¥ù@É¡ZcW|WqOJmĩl«ħşvOÓ«IqăV¥D[mI~Ó¢cehiÍ]Ɠ~ĥqX·eƷn±}v[ěďŕ]_œ`¹§ÕōIo©bs^}Ét±ū«³p£ÿ·Wµ|¡¥ăFÏs×¥ŅxÊdÒ{ºvĴÎêÌɊ²¶ü¨|ÞƸµȲLLúÉƎ¤ϊęĔV`_bªS^|dzY|dz¥pZbÆ£¶ÒK}tĦÔņƠPYznÍvX¶Ěn ĠÔzý¦ª÷ÑĸÙUȌ¸dòÜJð´ìúNM¬XZ´¤ŊǸ_tldI{¦ƀðĠȤ¥NehXnYGR° ƬDj¬¸|CĞKqºfƐiĺ©ª~ĆOQª ¤@ìǦɌ²æBÊTŸʂōĖĴŞȀÆÿȄlŤĒötνî¼ĨXh|ªM¤Ðz"
|
||||
],
|
||||
"encodeOffsets": [[116874, 41716]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "150000",
|
||||
"properties": {
|
||||
"id": "150000",
|
||||
"cp": [111.670801, 41.818311],
|
||||
"name": "内蒙古",
|
||||
"childNum": 2
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
[
|
||||
"@@¯PqFB
|S³C|kñHdiÄ¥sʼnÅ
PóÑÑE^ÅPpy_YtShQ·aHwsOnʼnÃs©iqjUSiº]ïW«gW¡ARë¥_sgÁnUI«m
]jvV¼euhwqAaW_µj
»çjioQR¹ēÃßt@r³[ÛlćË^ÍÉáGOUÛOB±XkŹ£k|e]olkVͼÕqtaÏõjgÁ£§U^RLËnX°ÇBz^~wfvypV ¯ƫĉ˭ȫƗŷɿÿĿƑ˃ĝÿÃǃßËőó©ǐȍŒĖM×ÍEyxþp]ÉvïèvƀnÂĴÖ@V~Ĉv¦wĖtējyÄDXÄxGQuv_i¦aBçw˛wD©{tāmQ{EJ§KPśƘƿ¥@sCTÉ}ɃwƇy±gÑ}T[÷kÐ禫
SÒ¥¸ëBX½HáŵÀğtSÝÂa[ƣ°¯¦Pï¡]£ġÒk®G²èQ°óMq}EóƐÇ\\@áügQÍu¥FTÕ¿Jû]|mvāÎYua^WoÀa·ząÒot×¶CLƗi¯¤mƎHNJ¤îìɾŊìTdåwsRÖgĒųúÍġäÕ}Q¶¿A[¡{d×uQAMxVvMOmăl«ct[wº_ÇÊjb£ĦS_éQZ_lwgOiýe`YYLq§IÁdz£ÙË[ÕªuƏ³ÍTs·bÁĽäė[b[ŗfãcn¥îC¿÷µ[ŏÀQōĉm¿Á^£mJVmL[{Ï_£F¥Ö{ŹA}
×Wu©ÅaųijƳhB{·TQqÙIķËZđ©Yc|M¡
LeVUóK_QWk_ĥ¿ãZ»X\\ĴuUèlG®ěłTĠğDŃOrÍdÆÍz]±
ŭ©Å]ÅÐ}UË¥©TċïxgckfWgi\\ÏĒ¥HkµEë{»ÏetcG±ahUiñiWsɁ·cCÕk]wȑ|ća}w
VaĚá G°ùnM¬¯{ÈÐÆA¥ÄêJxÙ¢hP¢ÛºµwWOóFÁz^ÀŗÎú´§¢T¤ǻƺSėǵhÝÅQgvBHouʝl_o¿Ga{ïq{¥|ſĿHĂ÷aĝÇqZñiñC³ª
»E`¨åXēÕqÉû[l}ç@čƘóO¿¡FUsAʽīccocÇS}£IS~ălkĩXçmĈ
ŀÐoÐdxÒuL^T{r@¢ÍĝKén£kQyÅõËXŷƏL§~}kq»IHėDžjĝ»ÑÞoå°qTt|r©ÏS¯·eŨĕx«È[eM¿yupN~¹ÏyN£{©għWí»Í¾səšDž_ÃĀɗ±ąijĉʍŌŷSÉA±åǥɋ@ë£R©ąP©}ĹªƏj¹erLDĝ·{i«ƫC£µsKC
GS|úþXgp{ÁX¿ć{ƱȏñZáĔyoÁhA}ŅĆfdʼn_¹Y°ėǩÑ¡H¯¶oMQqð¡Ë|Ñ`ƭŁX½·óÛxğįÅcQs«tȋDžFù^it«Č¯[hAi©á¥ÇĚ×l|¹y¯YȵƓñǙµïċĻ|Düȭ¶¡oŽäÕG\\ÄT¿Òõr¯LguÏYęRƩɷŌO\\İТæ^Ŋ IJȶȆbÜGĝ¬¿ĚVĎgª^íu½jÿĕęjık@Ľ]ėl¥ËĭûÁėéV©±ćn©ȇÍq¯½YÃÔʼnÉNÑÅÝy¹NqáʅDǡËñƁYÅy̱os§ȋµʽǘǏƬɱàưN¢ƔÊuľýľώȪƺɂļxZĈ}ÌʼnŪĺœĭFЛĽ̅ȣͽÒŵìƩÇϋÿȮǡŏçƑůĕ~ǼȳÐUfdIxÿ\\G zâɏÙOº·pqy£@qþ@Ǟ˽IBäƣzsÂZÁàĻdñ°ŕzéØűzșCìDȐĴĺf®Àľưø@ɜÖÞKĊŇƄ§͑těï͡VAġÑÑ»d³öǍÝXĉĕÖ{þĉu¸ËʅğU̎éhɹƆ̗̮ȘNJ֥ड़ࡰţાíϲäʮW¬®ҌeרūȠkɬɻ̼ãüfƠSצɩςåȈHϚÎKdzͲOðÏȆƘ¼CϚǚ࢚˼ФÔ¤ƌĞ̪Qʤ´¼mȠJˀƲÀɠmǐnǔĎȆÞǠN~ʢĜ¶ƌĆĘźʆȬ˪ĚǏĞGȖƴƀj`ĢçĶāàŃºēĢĖćYÀŎüôQÐÂŎŞdžŞêƖoˆDĤÕºÑǘÛˤ³̀gńƘĔÀ^ªƂ`ªt¾äƚêĦ¼ÐĔǎ¨Ȕ»͠^ˮÊȦƤøxRrŜH¤¸ÂxDÄ|ø˂˜ƮЬɚwɲFjĔ²Äw°dždÀÉ_ĸdîàŎjÊêTЪŌŜWÈ|tqĢUB~´°ÎFCU¼pĀēƄN¦¾O¶łKĊOjĚj´ĜYp{¦SĚÍ\\TתV÷Ší¨ÅDK°ßtŇĔK¨ǵÂcḷ̌ĚǣȄĽFlġUĵŇȣFʉɁMğįʏƶɷØŭOǽ«ƽū¹Ʊő̝Ȩ§ȞʘĖiɜɶʦ}¨֪ࠜ̀ƇǬ¹ǨE˦ĥªÔêFxúQEr´Wrh¤Ɛ \\talĈDJÜ|[Pll̚¸ƎGú´P¬W¦^¦H]prRn|or¾wLVnÇIujkmon£cX^Bh`¥V¦U¤¸}xRj[^xN[~ªxQ[`ªHÆÂExx^wN¶Ê|¨ìMrdYpoRzNyÀDs~bcfÌ`L¾n|¾T°c¨È¢ar¤`[|òDŞĔöxElÖdHÀI`Ď\\Àì~ÆR¼tf¦^¢ķ¶eÐÚMptgjɡČÅyġLûŇV®ÄÈƀϰP|ªVVªj¬ĚÒêp¬E|ŬÂc|ÀtƐK f{ĘFĒƌXƲąo½Ę\\¥o}Ûu£çkX{uĩ«āíÓUŅßŢqŤ¥lyň[oi{¦LńðFȪȖĒL¿Ìf£K£ʺoqNwğc`uetOj×°KJ±qÆġmĚŗos¬
qehqsuH{¸kH¡
ÊRǪÇƌbȆ¢´äÜ¢NìÉʖ¦â©Ġu¦öČ^â£ĂhĖMÈÄw\\fŦ°W ¢¾luŸDw\\̀ʉÌÛM
Ā[bÓEn}¶Vc
ês"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[129102, 52189]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "210000",
|
||||
"properties": {
|
||||
"id": "210000",
|
||||
"cp": [123.429096, 41.796767],
|
||||
"name": "辽宁",
|
||||
"childNum": 16
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@L@@sa"],
|
||||
["@@MnNm"],
|
||||
["@@dc"],
|
||||
["@@eÀC@b"],
|
||||
["@@f
XwkbrÄ`qg"],
|
||||
["@@^jtWQ"],
|
||||
["@@~ Y]c"],
|
||||
["@@G`ĔN^_¿ZÃM"],
|
||||
["@@iX¶BY"],
|
||||
["@@YZ"],
|
||||
["@@L_{Epf"],
|
||||
["@@^WqCT\\"],
|
||||
["@@\\[§t|¤_"],
|
||||
["@@m`n_"],
|
||||
["@@Ïxnj{q_×^Giip"],
|
||||
[
|
||||
"@@@é^BntaÊU]x ¯ÄPIJ°hʙK³VÕ@Y~|EvĹsǦL^pòŸÒG Ël]xxÄ_fT¤Ď¤cPC¨¸TVjbgH²sdÎdHt`B²¬GJję¶[ÐhjeXdlwhðSȦªVÊÏÆZÆŶ®²^ÎyÅÎcPqńĚDMħĜŁHkçvV[ij¼WYÀäĦ`XlR`ôLUVfK¢{NZdĒªYĸÌÚJRr¸SA|ƴgŴĴÆbvªØX~źB|¦ÕE¤Ð`\\|KUnnI]¤ÀÂĊnŎR®Ő¿¶\\ÀøíDm¦ÎbŨabaĘ\\ľã¸atÎSƐ´©v\\ÖÚÌǴ¤Â¨JKrZ_ZfjþhPkx`YRIjJcVf~sCN¤ EhæmsHy¨SðÑÌ\\\\ĐRZk°IS§fqŒßýáĞÙÉÖ[^¯ǤŲê´\\¦¬ĆPM¯£»uïpùzExanµyoluqe¦W^£ÊL}ñrkqWňûPUP¡ôJoo·U}£[·¨@XĸDXmÛݺGUCÁª½{íĂ^cjk¶Ã[q¤LÉö³cux«zZf²BWÇ®Yß½ve±ÃCý£W{Ú^q^sÑ·¨ÍOt¹·C¥GDrí@wÕKţëV·i}xËÍ÷i©ĝɝǡ]{c±OW³Ya±_ç©HĕoƫŇqr³Lys[ñ³¯OSďOMisZ±ÅFC¥Pq{Ã[Pg}\\¿ghćO
k^ģÁFıĉĥMoEqqZûěʼn³F¦oĵhÕP{¯~TÍlªNßYÐ{Ps{ÃVUeĎwk±ʼnVÓ½ŽJãÇÇ»Jm°dhcÀffdF~ĀeĖd`sx² ®EżĀdQÂd^~ăÔH¦\\LKpĄVez¤NP ǹÓRÆąJSha[¦´ÂghwmBШźhI|VV|p] ¼èNä¶ÜBÖ¼L`¼bØæKVpoúNZÞÒKxpw|ÊEMnzEQIZZNBčÚFÜçmĩWĪñtÞĵÇñZ«uD±|Əlij¥ãn·±PmÍada CLǑkùó¡³Ï«QaċÏOÃ¥ÕđQȥċƭy³ÃA"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [
|
||||
[[123686, 41445]],
|
||||
[[126019, 40435]],
|
||||
[[124393, 40128]],
|
||||
[[126117, 39963]],
|
||||
[[125322, 40140]],
|
||||
[[126686, 40700]],
|
||||
[[126041, 40374]],
|
||||
[[125584, 40168]],
|
||||
[[125453, 40165]],
|
||||
[[125362, 40214]],
|
||||
[[125280, 40291]],
|
||||
[[125774, 39997]],
|
||||
[[125976, 40496]],
|
||||
[[125822, 39993]],
|
||||
[[125509, 40217]],
|
||||
[[122731, 40949]]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "220000",
|
||||
"properties": { "id": "220000", "cp": [125.3245, 43.886841], "name": "吉林", "childNum": 1 },
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@pä³PClFbbÍzwBGĭZÅi»lYċ²SgkÇ£^Sqd¯R
©é£¯S\\cZ¹iűƏCuƍÓXoR}M^o£
R}oªUF
uuXHlEÅÏ©¤ÛmTþ¤D²ÄufàÀXXȱAeyYw¬dvõ´KÊ£\\rµÄlidā]|DÂVH¹Þ®ÜWnCķ W§@\\¸~¤Vp¸póIO¢VOŇürXql~òÉK]¤¥Xrfkvzpm¶bwyFoúv𼤠N°ąO¥«³[éǡű_°Õ\\ÚÊĝþâőàerR¨JYlďQ[ ÏYëЧTGztnß¡gFkMāGÁ¤ia Éȹ`\\xs¬dĆkNnuNUuP@vRY¾\\¢
GªóĄ~RãÖÎĢùđŴÕhQxtcæëSɽʼníëlj£ƍG£nj°KƘµDsØÑpyƸ®¿bXp]vbÍZuĂ{n^IüÀSÖ¦EvRÎûh@â[ƏÈô~FNr¯ôçR±HÑlĢ^¤¢OðævxsŒ]ÞÁTĠs¶¿âÆGW¾ìA¦·TѬè¥ÏÐJ¨¼ÒÖ¼ƦɄxÊ~StD@Ă¼Ŵ¡jlºWvÐzƦZвCH AxiukdGgetqmcÛ£Ozy¥cE}|
¾cZ
k¿uŐã[oxGikfeäT@
SUwpiÚFM©£è^Ú`@v¶eňf heP¶täOlÃUgÞzŸU`l}ÔÆUvØ_Ō¬Öi^ĉi§²ÃB~¡ĈÚEgc|DC_Ȧm²rBx¼MÔ¦ŮdĨÃâYxƘDVÇĺĿg¿cwÅ\\¹¥Yĭl¤OvLjM_a W`zļMž·\\swqÝSAqŚij¯°kRē°wx^ĐkǂÒ\\]nrĂ}²ĊŲÒøãh·M{yMzysěnĒġV·°G³¼XÀ¤¹i´o¤ŃÈ`ÌDzÄUĞd\\iÖmÈBĤÜɲDEh LG¾ƀľ{WaYÍÈĢĘÔRîĐj}ÇccjoUb½{h§Ǿ{KƖµÎ÷GĀÖŠåưÎslyiē«`å§H¥Ae^§GK}iã\\c]v©ģZmÃ|[M}ģTɟĵÂÂ`ÀçmFK¥ÚíÁbX³ÌQÒHof{]ept·GŋĜYünĎųVY^ydõkÅZW«WUa~U·SbwGçǑiW^qFuNĝ·EwUtW·Ýďæ©PuqEzwAVXRãQ`©GMehccďÏd©ÑW_ÏYƅ»
é\\ɹ~ǙG³mØ©BšuT§Ĥ½¢Ã_ýL¡ýqT^rme\\PpZZbyuybQefµ]UhĿDCmûvaÙNSkCwncćfv~
YÇG"
|
||||
],
|
||||
"encodeOffsets": [[130196, 42528]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "230000",
|
||||
"properties": {
|
||||
"id": "230000",
|
||||
"cp": [128.642464, 46.756967],
|
||||
"name": "黑龙江",
|
||||
"childNum": 2
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
[
|
||||
"@@UµNÿ¥īèçHÍøƕ¶Lǽ|g¨|a¾pVidd~ÈiíďÓQġėÇZÎXb½|ſÃH½KFgɱCģÛÇAnjÕc[VĝDZÃËÇ_ £ń³pj£º¿»WH´¯U¸đĢmtĜyzzNN|g¸÷äűѱĉā~mq^[ǁÑďlw]¯xQĔ¯l°řĴrBÞTxr[tޏĻN_yX`biNKu
P£kZĮ¦[ºxÆÀdhĹŀUÈƗCwáZħÄŭcÓ¥»NAw±qȥnD`{ChdÙFć}¢A±Äj¨]ĊÕjŋ«×`VuÓÅ~_kŷVÝyhVkÄãPsOµfgeŇ
µf@u_Ù ÙcªNªÙEojVxT@ãSefjlwH\\pŏäÀvlY½d{F~¦dyz¤PÜndsrhfHcvlwjF£G±DÏƥYyÏu¹XikĿ¦ÏqƗǀOŜ¨LI|FRĂn sª|C˜zxAè¥bfudTrFWÁ¹Am|ĔĕsķÆF´N}ć
UÕ@Áijſmuçuð^ÊýowFzØÎĕNőǏȎôªÌŒDŽàĀÄ˄ĞŀƒʀĀƘŸˮȬƬĊ°Uzouxe]}
AyÈW¯ÌmKQ]Īºif¸ÄX|sZt|½ÚUÎ lk^p{f¤lºlÆW A²PVÜPHÊâ]ÎĈÌÜk´\\@qàsĔÄQºpRij¼èi`¶bXrBgxfv»uUi^v~J¬mVp´£´VWrnP½ì¢BX¬hðX¹^TjVriªjtŊÄmtPGx¸bgRsT`ZozÆO]ÒFôÒOÆŊvÅpcGêsx´DR{AEOr°x|íb³Wm~DVjºéNNËܲɶGxŷCSt}]ûōSmtuÇÃĕNāg»íT«u}ç½BĵÞʣ¥ëÊ¡MÛ³ãȅ¡ƋaǩÈÉQG¢·lG|tvgrrf«ptęŘnÅĢrI²¯LiØsPf_vĠdxM prʹL¤¤eËÀđKïÙVY§]Ióáĥ]ķK¥j|pŇ\\kzţ¦šnņäÔVĂîά|vW®l¤èØrxm¶ă~lÄƯĄ̈́öȄEÔ¤ØQĄĄ»ƢjȦOǺ¨ìSŖÆƬyQv`cwZSÌ®ü±DŽ]ŀç¬B¬©ńzƺŷɄeeOĨSfm ĊƀP̎ēz©ĊÄÕÊmgÇsJ¥ƔŊśæÎÑqv¿íUOµªÂnĦÁ_½ä@êí
£P}Ġ[@gġ}gɊ×ûÏWXá¢užƻÌsNͽƎÁ§čŐAēeL³àydl¦ĘVçŁpśdžĽĺſÊQíÜçÛġÔsĕ¬Ǹ¯YßċġHµ ¡eå`ļrĉŘóƢFìĎWøxÊkƈdƬv|I|·©NqńRŀ¤éeŊŀàŀU²ŕƀBQ£Ď}L¹Îk@©ĈuǰųǨÚ§ƈnTËÇéƟÊcfčŤ^XmHĊĕË«W·ċëx³ǔķÐċJāwİ_ĸȀ^ôWr°oú¬Ħ
ŨK~ȰCĐ´Ƕ£fNÎèâw¢XnŮeÂÆĶ¾¾xäLĴĘlļO¤ÒĨA¢Êɚ¨®ØCÔ ŬGƠƦYĜĘÜƬDJg_ͥœ@čŅĻA¶¯@wÎqC½Ĉ»NăëKďÍQÙƫ[«ÃígßÔÇOÝáWñuZ¯ĥŕā¡ÑķJu¤E 寰WKɱ_d_}}vyõu¬ï¹ÓU±½@gÏ¿rýDg
Cdµ°MFYxw¿CG£Rƛ½Õ{]L§{qqą¿BÇƻğëܭNJË|c²}Fµ}ÙRsÓpg±QNqǫŋRwŕnéÑÉK«SeYR
ŋ@{¤SJ}D Ûǖ֍]gr¡µŷjqWÛham³~S«Þ]"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[134456, 44547]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "320000",
|
||||
"properties": {
|
||||
"id": "320000",
|
||||
"cp": [119.767413, 33.041544],
|
||||
"name": "江苏",
|
||||
"childNum": 1
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@cþÅPi`ZRu¥É\\]~°Y`µÓ^phÁbnÀşúòaĬºTÖŒbe¦¦{¸ZâćNp©Hr|^mjhSEb\\afv`sz^lkljÄtg¤D¾X¿À|ĐiZȀåB·î}GL¢õcßjayBFµÏC^ĭcÙt¿sğH]j{s©HM¢QnDÀ©DaÜÞ·jgàiDbPufjDk`dPOîhw¡ĥ¥GP²ĐobºrYî¶aHŢ´ ]´rılw³r_{£DB_Ûdåuk|Ũ¯F Cºyr{XFye³Þċ¿ÂkĭB¿MvÛpm`rÚã@ƹhågËÖƿxnlč¶Åì½Ot¾dJlVJĂǀŞqvnO^JZż·Q}êÍÅmµÒ]ƍ¦Dq}¬R^èĂ´ŀĻĊIÔtIJyQŐĠMNtR®òLhĚs©»}OÓGZz¶A\\jĨFäOĤHYJvÞHNiÜaĎÉnFQlNM¤B´ĄNöɂtpŬdfå
qm¿QûùŞÚb¤uŃJŴu»¹ĄlȖħŴw̌ŵ²ǹǠ͛hĭłƕrçü±Yxcitğ®jű¢KOķCoy`å®VTa_Ā]ŐÝɞï²ʯÊ^]afYǸÃĆēĪȣJđ͍ôƋÄÄÍīçÛɈǥ£ÛmY`ó£Z«§°Ó³QafusNıDž_k}¢m[ÝóDµ¡RLčiXyÅNïă¡¸iĔÏNÌŕoēdōîåŤûHcs}~Ûwbù¹£¦ÓCtOPrE^ÒogĉIµÛÅʹK
¤½phMü`oæŀ"
|
||||
],
|
||||
"encodeOffsets": [[121740, 32276]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "330000",
|
||||
"properties": {
|
||||
"id": "330000",
|
||||
"cp": [120.153576, 29.287459],
|
||||
"name": "浙江",
|
||||
"childNum": 45
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@E^dQ]K"],
|
||||
["@@jX^j"],
|
||||
["@@sfbU"],
|
||||
["@@qP\\xz[ck"],
|
||||
["@@R¢FX}°[s_"],
|
||||
["@@Cb\\}"],
|
||||
["@@e|v\\la{u"],
|
||||
["@@v~u}"],
|
||||
["@@QxÂF¯}"],
|
||||
["@@¹nvÞs¯o"],
|
||||
["@@rSkUEj"],
|
||||
["@@biZP"],
|
||||
["@@p[}INf"],
|
||||
["@@À¿"],
|
||||
["@@¹dnb
"],
|
||||
["@@rSBnR"],
|
||||
["@@g~h}"],
|
||||
["@@FlEk"],
|
||||
["@@OdPc"],
|
||||
["@@v[u\\"],
|
||||
["@@FjâL~wyoo~sµL\\"],
|
||||
["@@¬e¹aN"],
|
||||
["@@\\nÔ¡q]L³ë\\ÿ®QÖ"],
|
||||
["@@ÊA©[¬"],
|
||||
["@@Kxv"],
|
||||
["@@@hlIk]"],
|
||||
["@@pW{o||j"],
|
||||
["@@Md|_mC"],
|
||||
["@@¢
X£ÏylD¼XtH"],
|
||||
["@@hlÜ[LykAvyfw^E¤"],
|
||||
["@@fp¤MusR"],
|
||||
["@@®_ma~LÁ¬Z"],
|
||||
["@@iMxZ"],
|
||||
["@@ZcYd"],
|
||||
["@@Z~dOSo|A¿qZv"],
|
||||
["@@@`EN¡v"],
|
||||
["@@|TY{"],
|
||||
["@@@n@m"],
|
||||
["@@XWkCT\\"],
|
||||
["@@ºwZRkĕWO¢"],
|
||||
["@@X®±Grƪ\\ÔáXq{"],
|
||||
["@@ůTG°ĄLHm°UC"],
|
||||
[
|
||||
"@@¤aÜx~}dtüGæţŎíĔcŖpMËÐj碷ðĄÆMzjWKĎ¢Q¶À_ê_Bıi«pZgf¤Nrq]§ĂN®«H±yƳí¾×ŸīàLłčŴǝĂíÀBŖÕªÁŖHŗʼnåqûõi¨hÜ·ñt»¹ýv_[«¸mYL¯Qª
mĉÅdMgÇjcº«ę¬K´B«Âącoċ\\xKd¡gěŧ«®á[~ıxu·ÅKsËÉc¢Ù\\ĭƛëbf¹ģSĜkáƉÔĈZB{aMµfzʼnfåÂŧįƋǝÊĕġć£g³neą»@¦S®\\ßðChiqªĭiAuAµ_W¥ƣO\\lċĢttC¨£t`PZäuXßBsĻyekOđġĵHuXBµ]×\\°®¬F¢¾pµ¼kŘó¬Wät¸|@L¨¸µrºù³Ù~§WIZW®±Ð¨ÒÉx`²pĜrOògtÁZ}þÙ]¡FKwsPlU[}¦Rvn`hq¬\\nQ´ĘRWb_ rtČFIÖkĦPJ¶ÖÀÖJĈĄTĚòC ²@Pú
Øz©PCÈÚDZhŖl¬â~nm¨f©iļ«mntuÖZÜÄjL®EÌFª²iÊxبIÈhhst"
|
||||
],
|
||||
["@@o\\VzRZ}y"],
|
||||
["@@@°¡mÛGĕ¨§Ianá[ýƤjfæØLäGr"]
|
||||
],
|
||||
"encodeOffsets": [
|
||||
[[125592, 31553]],
|
||||
[[125785, 31436]],
|
||||
[[125729, 31431]],
|
||||
[[125513, 31380]],
|
||||
[[125223, 30438]],
|
||||
[[125115, 30114]],
|
||||
[[124815, 29155]],
|
||||
[[124419, 28746]],
|
||||
[[124095, 28635]],
|
||||
[[124005, 28609]],
|
||||
[[125000, 30713]],
|
||||
[[125111, 30698]],
|
||||
[[125078, 30682]],
|
||||
[[125150, 30684]],
|
||||
[[124014, 28103]],
|
||||
[[125008, 31331]],
|
||||
[[125411, 31468]],
|
||||
[[125329, 31479]],
|
||||
[[125626, 30916]],
|
||||
[[125417, 30956]],
|
||||
[[125254, 30976]],
|
||||
[[125199, 30997]],
|
||||
[[125095, 31058]],
|
||||
[[125083, 30915]],
|
||||
[[124885, 31015]],
|
||||
[[125218, 30798]],
|
||||
[[124867, 30838]],
|
||||
[[124755, 30788]],
|
||||
[[124802, 30809]],
|
||||
[[125267, 30657]],
|
||||
[[125218, 30578]],
|
||||
[[125200, 30562]],
|
||||
[[124968, 30474]],
|
||||
[[125167, 30396]],
|
||||
[[124955, 29879]],
|
||||
[[124714, 29781]],
|
||||
[[124762, 29462]],
|
||||
[[124325, 28754]],
|
||||
[[123990, 28459]],
|
||||
[[125366, 31477]],
|
||||
[[125115, 30363]],
|
||||
[[125369, 31139]],
|
||||
[[122495, 31878]],
|
||||
[[125329, 30690]],
|
||||
[[125192, 30787]]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "340000",
|
||||
"properties": { "id": "340000", "cp": [117.283042, 31.26119], "name": "安徽", "childNum": 3 },
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@^iuLX^"],
|
||||
["@@e©Ehl"],
|
||||
[
|
||||
"@@°ZÆëϵmkǀwÌÕæhºgBĝâqÙĊzÖgņtÀÁĂÆáhEz|WzqD¹°Eŧl{ævÜcA`¤C`|´qxIJkq^³³GšµbíZ
¹qpa±ď OH¦Ħx¢gPícOl_iCveaOjCh߸iÝbÛªCC¿mRV§¢A|t^iĠGÀtÚsd]ĮÐDE¶zAb àiödK¡~H¸íæAǿYj{ď¿À½W®£ChÃsikkly]_teu[bFaTign{]GqªoĈMYá|·¥f¥őaSÕėNµñĞ«Im_m¿Âa]uĜp
Z_§{Cäg¤°r[_YjÆOdý[I[á·¥Q_nùgL¾mvˊBÜÆ¶ĊJhpc¹O]iŠ]¥ jtsggJǧw×jÉ©±EFËKiÛÃÕYv
sm¬njĻª§emná}k«ŕgđ²ÙDÇ¤í¡ªOy×Où±@DñSęćăÕIÕ¿IµĥOjNÕËT¡¿tNæŇàåyķrĕq§ÄĩsWÆßF¶X®¿mw
RIÞfßoG³¾©uyHį{Ɓħ¯AFnuP
ÍÔzVdàôº^Ðæd´oG¤{S¬ćxã}ŧ×Kǥĩ«ÕOEзÖdÖsƘѨ[Û^Xr¢¼§xvÄÆµ`K§ tÒ´Cvlo¸fzŨð¾NY´ı~ÉĔē
ßúLÃÃ_ÈÏ|]ÂÏFlg`ben¾¢pUh~ƴ˶_r sĄ~cƈ]|r c~`¼{À{ȒiJjz`îÀT¥Û³
]u}f
ïQl{skloNdjäËzDvčoQďHI¦rbtHĔ~BmlRV_ħTLnñH±DL¼Lªl§Ťa¸ĚlK²\\RòvDcÎJbt[¤D@®hh~kt°ǾzÖ@¾ªdbYhüóZ ň¶vHrľ\\ÊJuxAT|dmÀO[ÃÔG·ĚąĐlŪÚpSJ¨ĸLvÞcPæķŨ®mÐálwKhïgA¢ųƩޤOÈm°K´"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[121722, 32278]], [[119475, 30423]], [[119168, 35472]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "350000",
|
||||
"properties": {
|
||||
"id": "350000",
|
||||
"cp": [118.306239, 26.075302],
|
||||
"name": "福建",
|
||||
"childNum": 18
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@zht´]"],
|
||||
["@@aj^~ĆG©O"],
|
||||
["@@ed¨C}}i"],
|
||||
["@@@vPGsQ"],
|
||||
["@@sBzddW]Q"],
|
||||
["@@S¨Q{"],
|
||||
["@@NVucW"],
|
||||
["@@qptBAq"],
|
||||
["@@¸[mu"],
|
||||
["@@Q\\pD]_"],
|
||||
["@@jSwUadpF"],
|
||||
["@@eXª~"],
|
||||
["@@AjvFso"],
|
||||
["@@fT_Çí\\v|ba¦jZÆy°"],
|
||||
["@@IjJi"],
|
||||
["@@wJIx«¼AoNe{M"],
|
||||
["@@K±¡ÓČäeZ"],
|
||||
[
|
||||
"@@k¡¹Eh~c®wBkUplÀ¡I~Māe£bN¨gZý¡a±Öcp©PhI¢Qq
ÇGj|¥U g[Ky¬ŏv@OptÉEF\\@ åA¬V{XģĐBy
cpě
¼³Ăp·¤¥ohqqÚ¡ŅLs^á§qlÀhH¨MCe»åÇGD¥zPO£čÙkJA¼ßėuĕeûÒiÁŧSW¥Qûŗ½ùěcݧSùĩąSWó«íęACµeRåǃRCÒÇZÍ¢ź±^dlstjD¸ZpuÔâÃH¾oLUêÃÔjjēò´ĄWƛ
^Ñ¥Ħ@ÇòmOw¡õyJyD}¢ďÑÈġfZda©º²z£NjD°Ötj¶¬ZSÎ~¾c°¶ÐmxO¸¢Pl´SL|¥AȪĖMņIJg®áIJČĒü` QF¬h|ĂJ@zµ |ê³È ¸UÖŬŬÀEttĸr]ðM¤ĶIJHtÏ AĬkvsq^aÎbvdfÊòSD´Z^xPsĂrvƞŀjJd×ŘÉ ®AΦĤdxĆqAZRÀMźnĊ»İÐZ YXæJyĊ²·¶q§·K@·{sXãô«lŗ¶»o½E¡«¢±¨Y®Ø¶^AvWĶGĒĢPlzfļtàAvWYãO_¤sD§ssČġ[kƤPX¦`¶®BBvĪjv©jx[L¥àï[F
¼ÍË»ğV`«Ip}ccÅĥZEãoP
´B@D¸m±z«Ƴ¿å³BRضWlâþäą`]Z£Tc ĹGµ¶Hm@_©k¾xĨôȉðX«½đCIbćqK³ÁÄš¬OAwã»aLʼnËĥW[ÂGIÂNxij¤D¢îĎÎB§°_JGs¥E@
¤uć
PåcuMuw¢BI¿]zG¹guĮck\\_"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [
|
||||
[[123250, 27563]],
|
||||
[[122541, 27268]],
|
||||
[[123020, 27189]],
|
||||
[[122916, 27125]],
|
||||
[[122887, 26845]],
|
||||
[[122808, 26762]],
|
||||
[[122568, 25912]],
|
||||
[[122778, 26197]],
|
||||
[[122515, 26757]],
|
||||
[[122816, 26587]],
|
||||
[[123388, 27005]],
|
||||
[[122450, 26243]],
|
||||
[[122578, 25962]],
|
||||
[[121255, 25103]],
|
||||
[[120987, 24903]],
|
||||
[[122339, 25802]],
|
||||
[[121042, 25093]],
|
||||
[[122439, 26024]]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "360000",
|
||||
"properties": {
|
||||
"id": "360000",
|
||||
"cp": [115.592151, 27.676493],
|
||||
"name": "江西",
|
||||
"childNum": 1
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@ĢĨƐgļ¼ÂMD~ņªe^\\^§ý©j×cZبzdÒa¶lÒJìõ`oz÷@¤u޸´ôęöY¼HČƶajlÞƩ¥éZ[|h}^U ¥pĄžƦO lt¸Æ Q\\aÆ|CnÂOjtĚĤdÈF`¶@Ðë ¦ōÒ¨SêvHĢûXD®
QgÄWiØPÞìºr¤džNĠ¢lĄtZoCƞÔºCxrpĠV®Ê{f_Y`_eq®Aot`@oDXfkp¨|s¬\\DÄSfè©Hn¬
^DhÆyøJhØxĢĀLÊƠPżċĄwȠ̦G®ǒĤäTŠÆ~Ħw«|TF¡nc³Ïå¹]ĉđxe{ÎÓvOEm°BƂĨİ|Gvz½ª´HàpeJÝQxnÀWEµàXÅĪt¨ÃĖrÄwÀFÎ|ňÓMå¼ibµ¯»åDT±m[r«_gmQu~¥V\\OkxtL E¢Ú^~ýêPóqoě±_Êw§ÑªåƗā¼mĉŹ¿NQ
YBąrwģcÍ¥BŗÊcØiIƝĿuqtāwO]³YCñTeÉcaubÍ]trluī
BÐGsĵıN£ï^ķqss¿FūūVÕ·´Ç{éĈýÿOER_đûIċâJhŅıNȩĕB
¦K{Tk³¡OP·wnµÏd¯}½TÍ«YiµÕsC¯iM¤¦¯P|ÿUHvhe¥oFTuõ\\OSsMòđƇiaºćXĊĵà·çhƃ÷Ç{ígu^đgm[×zkKN¶Õ»lčÓ{XSÆv©_ÈëJbVkĔVÀ¤P¾ºÈMÖxlò~ªÚàGĂ¢B±ÌKyáV¼Ã~
`gsÙfIƋlę¹e|~udjuTlXµf`¿Jd[\\L²"
|
||||
],
|
||||
"encodeOffsets": [[116689, 26234]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "370000",
|
||||
"properties": {
|
||||
"id": "370000",
|
||||
"cp": [118.000923, 36.275807],
|
||||
"name": "山东",
|
||||
"childNum": 13
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@Xjd]{K"],
|
||||
["@@itbFHy"],
|
||||
["@@HlGk"],
|
||||
["@@TGy"],
|
||||
["@@K¬U"],
|
||||
["@@WdXc"],
|
||||
["@@PtOs"],
|
||||
["@@LnXhc"],
|
||||
["@@ppVu]Or"],
|
||||
["@@cdzAUa"],
|
||||
["@@udRhnCI"],
|
||||
["@@oIpR"],
|
||||
[
|
||||
"@@Ľč{fzƤîKÎMĮ]ZF½Y]â£ph¶¨râøÀÎǨ¤^ºÄGz~grĚĜlĞÆLĆdž¢Îo¦cvKbgr°WhmZp L]LºcUÆnżĤÌĒbAnrOA´ȊcÀbƦUØrĆUÜøĬƞEzVL®öØBkŖÝĐ˹ŧ̄±ÀbÎÉnb²ĦhņBĖįĦåXćì@L¯´ywƕCéõė ƿ¸lµ¾Z|ZWyFY¨Mf~C¿`à_RÇzwƌfQnny´INoƬèôº|sTJULîVjǎ¾ĒØDz²XPn±ŴPè¸ŔLƔÜƺ_TüÃĤBBċÈöA´faM¨{«M`¶d¡ôÖ°mȰBÔjj´PM|c^d¤u¤Û´ä«ƢfPk¶Môl]Lb}su^ke{lC
MrDÇ]NÑFsmoõľHyGă{{çrnÓEƕZGª¹Fj¢ïW
uøCǷë¡ąuhÛ¡^KxC`C\\bÅxì²ĝÝ¿_NīCȽĿåB¥¢·IŖÕy\\¹kxãČ×GDyäÁçFQ¡KtŵƋ]CgÏAùSedcÚźuYfyMmhUWpSyGwMPqŀÁ¼zK¶GY§Ë@´śÇµƕBm@IogZ¯uTMx}CVKï{éƵP_K«pÛÙqċtkkù]gTğwoɁsMõ³ăAN£MRkmEÊčÛbMjÝGu
IZGPģãħE[iµBEuDPÔ~ª¼ęt]ûG§¡QMsğNPŏįzs£Ug{đJĿļā³]ç«Qr~¥CƎÑ^n¶ÆéÎR~ݏYI] PumŝrƿIā[xedzL¯v¯s¬ÁY
~}
ťuŁgƋpÝĄ_ņī¶ÏSR´ÁP~¿Cyċßdwk´SsX|t`Ä ÈðAªìÎT°¦Dda^lĎDĶÚY°`ĪŴǒàŠv\\ebZHŖR¬ŢƱùęOÑM³FÛWp["
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [
|
||||
[[123806, 39303]],
|
||||
[[123821, 39266]],
|
||||
[[123742, 39256]],
|
||||
[[123702, 39203]],
|
||||
[[123649, 39066]],
|
||||
[[123847, 38933]],
|
||||
[[123580, 38839]],
|
||||
[[123894, 37288]],
|
||||
[[123043, 36624]],
|
||||
[[123344, 38676]],
|
||||
[[123522, 38857]],
|
||||
[[123628, 38858]],
|
||||
[[118260, 36742]]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "410000",
|
||||
"properties": {
|
||||
"id": "410000",
|
||||
"cp": [113.665412, 33.757975],
|
||||
"name": "河南",
|
||||
"childNum": 1
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@ýLùµP³swIÓxcŢĞð´E®ÚPtĴXØx¶@«ŕŕQGYfa[şußǩđš_X³ijÕčC]kbc¥CS¯ëÍB©÷³Si_}mYTt³xlàcČzÀD}ÂOQ³ÐTĨ¯ƗòËŖ[hłŦv~}ÂZ«¤lPÇ£ªÝŴÅR§ØnhctâknÏľŹUÓÝdKuķI§oTũÙďkęĆH¸Ó\\Ä¿PcnS{wBIvÉĽ[GqµuŇôYgûZca©@½Õǽys¯}lgg@C\\£asIdÍuCQñ[L±ęk·ţb¨©kK»KC²òGKmĨS`UQnk}AGēsqaJ¥ĐGRĎpCuÌy ã iMcplk|tRkðev~^´¦ÜSí¿_iyjI|ȑ|¿_»d}q^{Ƈdă}tqµ`Ƴĕg}V¡om½faÇo³TTj¥tĠRyK{ùÓjuµ{t}uËRivGçJFjµÍyqÎàQÂFewixGw½Yŷpµú³XU½ġyłåkÚwZX·l¢Á¢KzOÎÎjc¼htoDHr
|J½}JZ_¯iPq{tę½ĕ¦Zpĵø«kQ
Ť]MÛfaQpě±ǽ¾]uFu÷nčįADp}AjmcEÇaª³o³ÆÍSƇĈÙDIzËčľ^KLiÞñ[aA²zzÌ÷D|[íijgfÕÞd®|`Ć~oĠƑô³ŊD×°¯CsøÀ«ìUMhTº¨¸ǡîSÔDruÂÇZÖEvPZW~ØÐtĄE¢¦Ðy¸bô´oŬ¬²Ês~]®tªapŎJ¨Öº_Ŕ`Ŗ^Đ\\Ĝu~m²Ƹ¸fWĦrƔ}Î^gjdfÔ¡J}\\n C¦þWxªJRÔŠu¬ĨĨmFdM{\\d\\YÊ¢ú@@¦ª²SÜsC}fNècbpRmlØ^gd¢aÒ¢CZZxvƶN¿¢T@uC¬^ĊðÄn|lGlRjsp¢ED}Fio~ÔN~zkĘHVsDzßjŬŢ`Pûàl¢\\ÀEhİgÞē X¼Pk|m"
|
||||
],
|
||||
"encodeOffsets": [[118256, 37017]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "420000",
|
||||
"properties": {
|
||||
"id": "420000",
|
||||
"cp": [113.298572, 30.684355],
|
||||
"name": "湖北",
|
||||
"childNum": 3
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@AB"],
|
||||
["@@lskt"],
|
||||
[
|
||||
"@@¾«}{ra®pîÃ\\{øCËyyB±b\\òÝjKL ]ĎĽÌJyÚCƈćÎT´Å´pb©ÈdFin~BCo°BĎÃømv®E^vǾ½Ĝ²RobÜeN^ĺ£R¬lĶ÷YoĖ¥Ě¾|sOr°jY`~I¾®I{GqpCgyl{£ÍÍyPL¡¡¸kWxYlÙæŁĢz¾V´W¶ùŸo¾ZHxjwfxGNÁ³Xéæl¶EièIH ujÌQ~v|sv¶Ôi|ú¢FhQsğ¦SiŠBgÐE^ÁÐ{čnOÂÈUÎóĔÊēIJ}Z³½Mŧïeyp·uk³DsѨL¶_Åuèw»¡WqÜ]\\Ò§tƗcÕ¸ÕFÏǝĉăxŻČƟOKÉġÿ×wg÷IÅzCg]m«ªGeçÃTC«[t§{loWeC@ps_Bprf_``Z|ei¡oċMqow¹DƝÓDYpûsYkıǃ}s¥ç³[§cY§HK«Qy]¢wwö¸ïx¼ņ¾Xv®ÇÀµRĠÐHM±cÏdƒǍũȅȷ±DSyúĝ£ŤĀàtÖÿï[îb\\}pĭÉI±Ñy
¿³x¯No|¹HÏÛmjúË~TuęjCöAwě¬Rđl¯ ÑbŇTĿ_[IčĄʿnM¦ğ\\É[T·k¹©oĕ@A¾wya¥Y\\¥Âaz¯ãÁ¡k¥ne£ÛwE©Êō¶˓uoj_U¡cF¹[WvP©whuÕyBF`RqJUw\\i¡{jEPïÿ½fć
QÑÀQ{°fLÔ~wXgītêݾĺHd³fJd]HJ²
EoU¥HhwQsƐ»Xmg±çve]DmÍPoCc¾_hhøYrŊU¶eD°Č_N~øĹĚ·`z]Äþp¼
äÌQv\\rCé¾TnkžŐÚÜa¼ÝƆ̶Ûo
d
ĔňТJqPb ¾|J¾fXƐîĨ_Z¯À}úƲN_ĒÄ^ĈaŐyp»CÇÄKñL³ġM²wrIÒŭxjb[n«øæà ^²h¯ÚŐªÞ¸Y²ĒVø}Ā^İ´LÚm¥ÀJÞ{JVųÞŃx×sxxƈē ģMřÚðòIfĊŒ\\Ʈ±ŒdʧĘDvČ_Àæ~Dċ´A®µ¨ØLV¦êHÒ¤"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[113712, 34000]], [[115612, 30507]], [[113649, 34054]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "430000",
|
||||
"properties": { "id": "430000", "cp": [111.782279, 28.09409], "name": "湖南", "childNum": 3 },
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@nFTs"],
|
||||
["@@ßÅÆá½ÔXrCO
ËRïÿĩTooQyÓ[ŅBE¬ÎÓXaį§Ã¸G °ITxpúxÚij¥Ï̾edÄ©ĸG
àGhM¤Â_U}Ċ}¢pczfþg¤ÇòAVM"],
|
||||
[
|
||||
"@@©KA·³CQ±Á«³BUƑ¹AtćOwD]JiØSm¯b£ylX
HËѱH«C^õľAŧ¤É¥ïyuǙuA¢^{ÌC´¦ŷJ£^[ª¿ĕ~Ƈ
N
skóā¹¿ï]ă~÷O§@Vm¡Qđ¦¢Ĥ{ºjÔª¥nf´~Õo×ÛąMąıuZmZcÒ IJβSÊDŽŶ¨ƚCÖŎªQؼrŭ«}NÏürʬmjr@ĘrTW SsdHzƓ^ÇÂyUi¯DÅYlŹu{hT}mĉ¹¥ěDÿë©ıÓ[Oº£¥ótł¹MÕƪ`P
DiÛU¾ÅâìUñBÈ£ýhedy¡oċ`pfmjP~kZa
ZsÐd°wj§@Ĵ®w~^kÀÅKvNmX\\¨aŃqvíó¿F¤¡@ũÑVw}S@j}¾«pĂrªg àÀ²NJ¶¶Dô
K|^ª°LX¾ŴäPα£EXd^¶IJÞÜ~u¸ǔMRhsR
e`ÄofIÔ\\Ø ićymnú¨cj ¢»GČìƊÿШXeĈ¾Oð Fi ¢|[jVxrIQ_EzAN¦zLU`cªxOTu RLÄ¢dVi`p˔vŎµªÉF~Ød¢ºgİàw¸Áb[¦Zb¦z½xBĖ@ªpºlS¸Ö\\Ĕ[N¥ˀmĎăJ\\ŀ`
ňSÚĖÁĐiOĜ«BxDõĚivSÌ}iùÜnкG{p°M´wÀÒzJ²ò¨ oTçüöoÛÿñőФùTz²CȆȸǎŪƑÐc°dPÎğ˶[Ƚu¯½WM¡ÉB·rínZÒ `¨GA¾\\pēXhÃRCüWGġu
Té§ŎÑ©ò³I±³}_EÃħg®ęisÁPDmÅ{b[RÅs·kPŽƥóRoOV~]{g\\êYƪ¦kÝbiċƵGZ»Ěõ
ó·³vŝ£ø@pyö_ëIkѵbcѧy
×dYتiþ¨[]f]Ņ©C}ÁN»hĻħƏĩ"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[115640, 30489]], [[112543, 27312]], [[116690, 26230]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "440000",
|
||||
"properties": {
|
||||
"id": "440000",
|
||||
"cp": [113.280637, 23.125178],
|
||||
"name": "广东",
|
||||
"childNum": 24
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@QdAua"],
|
||||
["@@lxDLo"],
|
||||
["@@sbhNLo"],
|
||||
["@@Ă ā"],
|
||||
["@@WltO[["],
|
||||
["@@Kr]S"],
|
||||
["@@eI]y"],
|
||||
["@@I|Mym"],
|
||||
["@@Û³LS¼Y"],
|
||||
["@@nvºBëui©`¾"],
|
||||
["@@zdÛJw®"],
|
||||
["@@°
¯"],
|
||||
["@@a yAª¸ËJIxØ@ĀHAmÃV¡ofuo"],
|
||||
["@@sŗÃÔėAƁZÄ ~°ČPäh"],
|
||||
["@@¶ÝÌvmĞhıQ"],
|
||||
["@@HdSjǢD}war
u«ZqadYM"],
|
||||
["@@el\\LqqU"],
|
||||
["@@~rMo\\"],
|
||||
["@@f^C"],
|
||||
["@@øPªoj÷ÍÝħXČx°Q¨ıXNv"],
|
||||
["@@gÇƳo[~tly"],
|
||||
["@@EÆC¿"],
|
||||
["@@OP"],
|
||||
[
|
||||
"@@wđógĝ[³¡VÙæÅöM̳¹pÁaËýý©D©ÜJŹƕģGą¤{Ùū
ÇO²«BƱéAÒĥ¡«BhlmtÃPµyU¯ucd·w_bŝcīímGO|KPȏŹãŝIŕŭŕ@Óoo¿ē±ß}
ŭIJWÈCőâUâǙIğʼn©IijE×
Á³AówXJþ±ÌÜÓĨ£L]ĈÙƺZǾĆĖMĸĤfÎĵlŨnÈĐtFFĤêk¶^k°f¶g}®Faf`vXŲxl¦ÔÁ²¬Ð¦pqÊ̲iXØRDÎ}Ä@ZĠsx®AR~®ETtĄZƈfŠŠHâÒÐAµ\\S¸^wĖkRzalŜ|E¨ÈNĀňZTpBh£\\ĎƀuXĖtKL¶G|»ĺEļĞ~ÜĢÛĊrOÙîvd]n¬VÊĜ°RÖpMƂªFbwEÀ©\\
¤]ŸI®¥D³|Ë]CöAŤ¦
æ´¥¸Lv¼¢ĽBaôF~®²GÌÒEYzk¤°ahlVÕI^CxĈPsBƒºV¸@¾ªR²ĨN]´_eavSivc}p}Đ¼ƌkJÚe th_¸ ºx±ò_xN˲@ă¡ßH©Ùñ}wkNÕ¹ÇO½¿£ĕ]ly_WìIǪ`uTÅxYĒÖ¼kÖµMjJÚwn\\hĒv]îh|ÈƄøèg¸Ķß ĉĈWb¹ƀdéĘNTtP[öSvrCZaGubo´ŖÒÇĐ~¡zCI
özx¢PnÈñ @ĥÒ¦]ƞV}³ăĔñiiÄÓVépKG½ÄÓávYoC·sitiaÀyŧΡÈYDÑům}ý|m[węõĉZÅxUO}÷N¹³ĉo_qtăqwµŁYÙǝŕ¹tïÛUïmRCº
ĭ|µÕÊK½Rē ó]GªęAx»HO£|ām¡diď×YïYWªʼnOeÚtĐ«zđ¹T
āúEá²\\ķÍ}jYàÙÆſ¿Çdğ·ùTßÇţʄ¡XgWÀLJğ·¿ÃOj YÇ÷Qěi"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [
|
||||
[[117381, 22988]],
|
||||
[[116552, 22934]],
|
||||
[[116790, 22617]],
|
||||
[[116973, 22545]],
|
||||
[[116444, 22536]],
|
||||
[[116931, 22515]],
|
||||
[[116496, 22490]],
|
||||
[[116453, 22449]],
|
||||
[[113301, 21439]],
|
||||
[[118726, 21604]],
|
||||
[[118709, 21486]],
|
||||
[[113210, 20816]],
|
||||
[[115482, 22082]],
|
||||
[[113171, 21585]],
|
||||
[[113199, 21590]],
|
||||
[[115232, 22102]],
|
||||
[[115739, 22373]],
|
||||
[[115134, 22184]],
|
||||
[[113056, 21175]],
|
||||
[[119573, 21271]],
|
||||
[[119957, 24020]],
|
||||
[[115859, 22356]],
|
||||
[[116561, 22649]],
|
||||
[[116285, 22746]]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "450000",
|
||||
"properties": { "id": "450000", "cp": [108.320004, 22.82402], "name": "广西", "childNum": 2 },
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@H TQ§A"],
|
||||
[
|
||||
"@@ĨʪLƊDÎĹĐCǦė¸zÚGn£¾rªŀÜt¬@ÖÚSx~øOŒŶÐÂæȠ\\ÈÜObĖw^oÞLf¬°bI lTØBÌF£Ć¹gñĤaYt¿¤VSñK¸¤nM¼JE±½¸ñoÜCƆæĪ^ĚQÖ¦^f´QüÜÊz¯lzUĺš@ìp¶n]sxtx¶@~ÒĂJb©gk{°~c°`Ô¬rV\\la¼¤ôá`¯¹LCÆbxEræOv[H[~|aB£ÖsºdAĐzNÂðsÞÆ
Ĥªbab`ho¡³F«èVlo¤ÔRzpp®SĪº¨ÖºN
ijd`a¦¤F³ºDÎńĀìCĜº¦Ċ~nS|gźvZkCÆj°zVÈÁƔ]LÊFZg
čPkini«qÇczÍY®¬Ů»qR×ō©DÕ§ƙǃŵTÉĩ±ıdÑnYYIJvNĆĆØÜ Öp}e³¦m©iÓ|¹ħņ|ª¦QF¢Â¬ʖovg¿em^ucà÷gÕuíÙćĝ}FϼĹ{µHKsLSđƃrč¤[AgoSŇYMÿ§Ç{FśbkylQxĕ]T·¶[B
ÑÏGáşşƇe
ăYSsFQ}BwtYğÃ@~
CÍQ ×Wj˱rÉ¥oÏ ±«ÓÂ¥kwWűmcih³K~µh¯e]lµélEģEďsmÇŧē`ãògK_ÛsUʝćğ¶höO¤Ǜn³c`¡y¦CezYwa[ďĵűMę§]XÎ_íÛ]éÛUćİÕBƣ±
dy¹T^dûÅÑŦ·PĻþÙ`K¦
¢ÍeĥR¿³£[~äu¼dltW¸oRM¢ď\\z}Æzdvň{ÎXF¶°Â_ÒÂÏL©ÖTmu¼ãlīkiqéfA·Êµ\\őDc¥ÝFyÔćcűH_hLÜêĺШc}rn`½Ì@¸¶ªVLhŒ\\Ţĺk~Ġið°|gtTĭĸ^xvKVGréAébUuMJVÃO¡
qĂXËSģãlýà_juYÛÒBG^éÖ¶§EGÅzěƯ¤EkN[kdåucé¬dnYpAyČ{`]þ¯TbÜÈk¡ĠvàhÂƄ¢Jî¶²"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[111707, 21520]], [[107619, 25527]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "460000",
|
||||
"properties": { "id": "460000", "cp": [109.83119, 19.031971], "name": "海南", "childNum": 1 },
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": ["@@¦Ŝil¢XƦƞòïè§ŞCêɕrŧůÇąĻõ·ĉ³œ̅kÇm@ċȧŧĥĽʉƅſȓÒ˦ŝE}ºƑ[ÍĜȋ gÎfǐÏĤ¨êƺ\\Ɔ¸ĠĎvʄȀоjNðĀÒRZdžzÐŘΰH¨Ƣb²_Ġ "],
|
||||
"encodeOffsets": [[112750, 20508]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "510000",
|
||||
"properties": {
|
||||
"id": "510000",
|
||||
"cp": [104.065735, 30.659462],
|
||||
"name": "四川",
|
||||
"childNum": 2
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@LqKr"],
|
||||
[
|
||||
"@@[ĻéV£_ţġñpG réÏ·~ąSfy×Í·ºſƽiÍıƣıĻmHH}siaX@iǰÁÃ×t«T¤JJJyJÈ`Ohߦ¡uËhIyCjmÿw
ZG
TiSsOB²fNmsPa{M{õE^Hj}gYpaeu¯oáwHjÁ½M¡pMuåmni{fk\\oÎqCwEZ¼KĝAy{m÷LwO×SimRI¯rKõBS«sFe]fµ¢óY_ÆPRcue°Cbo×bd£ŌIHgtrnyPt¦foaXďxlBowz_{ÊéWiêEGhܸºuFĈIxf®Y½ĀǙ]¤EyF²ċw¸¿@g¢§RGv»áW`ÃĵJwi]t¥wO½a[×]`ÃiüL¦LabbTÀåc}ÍhÆh®BHî|îºÉk¤Sy£ia©taį·Ɖ`ō¥UhO
ĝLk}©Fos´JmµlŁu
ønÑJWΪYÀïAetTŅÓGË«bo{ıwodƟ½OġܵxàNÖ¾P²§HKv¾]|BÆåoZ`¡Ø`ÀmºĠ~ÌЧnÇ
¿¤]wğ@srğu~Io[é±¹ ¿ſđÓ@qg¹zƱřaí°KtǤV»Ã[ĩǭƑ^ÇÓ@áťsZÏÅĭƋěpwDóÖáŻneQËq·GCœýS]x·ýq³OÕ¶Qzßti{řáÍÇWŝŭñzÇWpç¿JXĩè½cFÂLiVjx}\\NŇĖ¥GeJA¼ÄHfÈu~¸Æ«dE³ÉMA|bÒ
ćhG¬CMõƤąAvüVéŀ_V̳ĐwQj´·ZeÈÁ¨X´Æ¡Qu·»ÕZ³ġqDoy`L¬gdp°şp¦ėìÅĮZ°Iähzĵf²å ĚÑKpIN|Ñz]ń
·FU×é»R³MÉ»GM«kiér}Ã`¹ăÞmÈnÁîRǀ³ĜoİzŔwǶVÚ£À]ɜ»ĆlƂ²Ġ
þTº·àUȞÏʦ¶I«dĽĢdĬ¿»Ĕ×h\\c¬ä²GêëĤł¥ÀǿżÃÆMº}BÕĢyFVvwxBèĻĒ©ĈtCĢɽŠȣ¦āæ·HĽîôNÔ~^¤Ɗu^s¼{TA¼ø°¢İªDè¾Ň¶ÝJ®Z´ğ~Sn|ªWÚ©òzPOȸbð¢|øĞŒQìÛÐ@ĞǎRS¤Á§d
i´ezÝúØã]HqkIþËQǦÃsǤ[E¬ÉŪÍxXƒ·ÖƁİlƞ¹ª¹|XÊwnÆƄmÀêErĒtD®ċæcQE®³^ĭ¥©l}äQtoŖÜqÆkµªÔĻĴ¡@Ċ°B²Èw^^RsºT£ڿQPJvÄz^Đ¹Æ¯fLà´GC²dtĀRt¼¤ĦOðğfÔðDŨŁĞƘïPÈ®âbMüÀXZ ¸£@Å»»QÉ]dsÖ×_Í_ÌêŮPrĔĐÕGĂeZÜîĘqBhtO ¤tE[h|YÔZśÎs´xº±Uñt|OĩĠºNbgþJy^dÂY Į]Řz¦gC³R`Āz¢Aj¸CL¤RÆ»@Ŏk\\Ç´£YW}z@Z}öoû¶]´^NÒ}èNªPÍy¹`S°´ATeVamdUĐwʄvĮÕ\\uÆŗ¨Yp¹àZÂmWh{á}WØǍÉüwga§áCNęÎ[ĀÕĪgÖɪXøx¬½Ů¦¦[NÎLÜUÖ´òrÙŠxR^JkijnDX{U~ET{ļº¦PZcjF²Ė@pg¨B{u¨ŦyhoÚD®¯¢ WòàFΤ¨GDäz¦kŮPġqË¥À]eâÚ´ªKxīPÖ|æ[xäJÞĥsNÖ½I¬nĨY´®ÐƐmDŝuäđđEb
ee_v¡}ìęNJē}qÉåT¯µRs¡M@}ůaa¯wvƉåZw\\Z{åû^"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[108815, 30935]], [[110617, 31811]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "520000",
|
||||
"properties": {
|
||||
"id": "520000",
|
||||
"cp": [106.713478, 26.578343],
|
||||
"name": "贵州",
|
||||
"childNum": 3
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@G\\lY£in"],
|
||||
["@@q|mc¯tÏVSÎ"],
|
||||
[
|
||||
"@@hÑ£IsNgßHHªķÃh_¹¡ĝħń¦uÙùgS¯JH|sÝÅtÁïyMDč»eÕtA¤{b\\}G®u\\åPFqwÅaD
K°ºâ_£ùbµmÁÛĹM[q|hlaªāI}ѵ@swtwm^oµD鼊yVky°ÉûÛR
³e¥]RÕěħ[ƅåÛDpJiVÂF²I
»mN·£LbÒYbWsÀbpkiTZĄă¶Hq`
ĥ_J¯ae«KpÝx]aĕÛPÇȟ[ÁåŵÏő÷Pw}TÙ@Õs«ĿÛq©½m¤ÙH·yǥĘĉBµĨÕnđ]K©œáGçş§ÕßgǗĦTèƤƺ{¶ÉHÎd¾ŚÊ·OÐjXWrãLyzÉAL¾ę¢bĶėy_qMĔąro¼hĊw¶øV¤w²Ĉ]ÊKx|`ź¦ÂÈdrcÈbe¸`I¼čTF´¼Óýȃr¹ÍJ©k_șl³´_pĐ`oÒh¶pa^ÓĔ}D»^Xy`d[Kv
JPhèhCrĂĚÂ^Êƌ wZLĠ£ÁbrzOIlMMĪŐžËr×ÎeŦtw|¢mKjSǘňĂStÎŦEtqFT¾E쬬ôxÌO¢ K³ŀºäYPVgŎ¦Ŋm޼VZwVlz¤
£Tl®ctĽÚó{GAÇge~Îd¿æaSba¥KKûj®_Ä^\\ؾbP®¦x^sxjĶI_Ä Xâ¼Hu¨Qh¡À@Ëô}±GNìĎlT¸
`V~R°tbÕĊ`¸úÛtÏFDu[MfqGH·¥yAztMFe|R_GkChZeÚ°tov`xbDnÐ{E}ZèxNEÞREn[Pv@{~rĆAB§EO¿|UZ~ìUf¨J²ĂÝÆsªB`s¶fvö¦Õ~dÔq¨¸º»uù[[§´sb¤¢zþF¢Æ
ÀhÂW\\ıËIÝo±ĭŠ£þÊs}¡R]ěDg´VG¢j±®èºÃmpU[Á뺰rÜbNu¸}º¼`niºÔXĄ¤¼ÔdaµÁ_Ã
ftQQgR·Ǔv}Ý×ĵ]µWc¤F²OĩųãW½¯K©
]{LóµCIµ±Mß¿h©āq¬o½~@i~TUxŪÒ¢@£ÀEîôruńb[§nWuMÆLl¿]x}ij½"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[112158, 27383]], [[112105, 27474]], [[112095, 27476]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "530000",
|
||||
"properties": {
|
||||
"id": "530000",
|
||||
"cp": [101.512251, 24.740609],
|
||||
"name": "云南",
|
||||
"childNum": 1
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@[ùx½}ÑRHYīĺûsÍniEoã½Ya²ė{c¬ĝgĂsAØÅwďõzFjw}«Dx¿}Uũlê@HÅF¨ÇoJ´Ónũuą¡Ã¢pÒÅØ TF²xa²ËXcÊlHîAßËŁkŻƑŷÉ©hWæßUËs¡¦}teèÆ¶StÇÇ}Fd£jĈZĆÆ¤Tč\\D}O÷£U§~ŃGåŃDĝ¸Tsd¶¶Bª¤u¢ŌĎo~t¾ÍŶÒtD¦ÚiôözØX²ghįh½Û±¯ÿm·zR¦Ɵ`ªŊÃh¢rOÔ´£Ym¼èêf¯ŪĽncÚbw\\zlvWªâ ¦gmĿBĹ£¢ƹřbĥkǫßeeZkÙIKueT»sVesbaĕ ¶®dNĄÄpªy¼³BE®lGŭCǶwêżĔÂepÍÀQƞpC¼ŲÈAÎô¶RäQ^Øu¬°_Èôc´¹ò¨P΢hlϦ´ĦÆ´sâÇŲPnÊD^¯°Upv}®BP̪jǬxSöwlfòªvqĸ|`HviļndĜĆhňem·FyÞqóSᝳX_ĞçêtryvL¤§z¦c¦¥jnŞklD¤øz½ĜàĂŧMÅ|áƆàÊcðÂFÜáŢ¥\\\\ºİøÒÐJĴîD¦zK²ǏÎEh~CDhMn^ÌöÄ©ČZÀaüfɭyœpį´ěFűk]Ôě¢qlÅĆÙa¶~ÄqêljN¬¼HÊNQ´ê¼VظE^ŃÒyM{JLoÒęæe±Ķygã¯JYÆĭĘëo¥Šo¯hcK«z_prC´ĢÖY¼ v¸¢RÅW³Â§fǸYi³xR´ďUË`êĿUûuĆBƣöNDH«ĈgÑaB{ÊNF´¬c·Åv}eÇÃGB»If¦HňĕM
~[iwjUÁKE¾dĪçWIèÀoÈXòyŞŮÈXâÎŚj|àsRyµÖPr´þ ¸^wþTDŔHr¸RÌmfżÕâCôoxĜƌÆĮÐYtâŦÔ@]ÈǮƒ\\μģUsȯLbîƲŚºyhr@ĒÔƀÀ²º\\êpJ}ĠvqtĠ@^xÀ£È¨mËÏğ}n¹_¿¢×Y_æpÅA^{½Lu¨GO±Õ½ßM¶wÁĢÛPƢ¼pcIJx|ap̬HÐŊSfsðBZ¿©XÏÒKk÷Eû¿S
rEFsÕūkóVǥʼniTL¡n{uxţÏhôŝ¬ğōNNJkyPaqÂğ¤K®YxÉƋÁ]āęDqçgOgILu\\_gz]W¼~CÔē]bµogpÑ_oď`´³Țkl`IªºÎȄqÔþ»E³ĎSJ»_f·adÇqÇc¥Á_Źw{L^ɱćxU£µ÷xgĉp»ĆqNē`rĘzaĵĚ¡K½ÊBzyäKXqiWPÏɸ½řÍcÊG|µƕƣGË÷k°_^ý|_zċBZocmø¯hhcæ\\lMFlư£ĜÆyHF¨µêÕ]HA
àÓ^it `þßäkĤÎT~Wlÿ¨ÔPzUCNVv [jâôDôď[}z¿msSh¯{jïğl}šĹ[őgK©U·µË@¾m_~q¡f¹
ÅË^»f³ø}Q¡Ö˳gͱ^Ç
\\ëÃA_¿bWÏ[¶ƛé£F{īZgm@|kHǭƁć¦UĔť×ë}ǝeďºȡȘÏíBÉ£āĘPªij¶ʼnÿy©nď£G¹¡I±LÉĺÑdĉÜW¥}gÁ{aqÃ¥aıęÏZï`"
|
||||
],
|
||||
"encodeOffsets": [[104636, 22969]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "540000",
|
||||
"properties": { "id": "540000", "cp": [89.132212, 30.860361], "name": "西藏", "childNum": 1 },
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@ÂhľxŖxÒVºÅâAĪÝȆµę¯Ňa±r_w~uSÕňqOj]ɄQ
£Z
UDûoY»©M[L¼qãË{VÍçWVi]ë©Ä÷àyƛhÚU°adcQ~Mx¥cc¡ÙaSyFÖkuRýq¿ÔµQĽ³aG{¿FµëªéĜÿª@¬·K·àariĕĀ«V»ŶĴūgèLǴŇƶaftèBŚ£^âǐÝ®M¦ÁǞÿ¬LhJ¾óƾƺcxwf]Y
´¦|QLn°adĊ
\\¨oǀÍŎ´ĩĀd`tÊQŞŕ|¨C^©Ĉ¦¦ÎJĊ{ëĎjª²rÐl`¼Ą[t|¦Stè¾PÜK¸dƄı]s¤î_v¹ÎVòŦj£Əsc¬_Ğ´|٦Av¦w`ăaÝaa¢e¤ı²©ªSªÈMĄwÉØŔì@T¤Ę\\õª@þo´xA sÂtŎKzó´ÇĊµ¢r^nĊƬ×üG¢³ {âĊ]G~bÀgVjzlhǶfOfdªB]pjTOtĊn¤}®¦Č¥d¢¼»ddY¼t¢eȤJ¤}Ǿ¡°§¤AÐlc@ĝsªćļđAçwxUuzEÖġ~AN¹ÄÅȀݦ¿ģŁéì±H
ãd«g[ؼēÀcīľġ¬cJµ
ÐʥVȝ¸ßS¹ý±ğkƁ¼ą^ɛ¤Ûÿb[}¬ōõÃ]ËNm®g@Bg}ÍF±ǐyL¥íCIijÏ÷Ñį[¹¦[âšEÛïÁÉdƅß{âNÆāŨß¾ě÷yC£k´ÓH@¹TZ¥¢į·ÌAЧ®Zc
v½Z¹|ÅWZqgW|ieZÅYVÓqdqbc²R@c¥Rã»GeeƃīQ}J[ÒK
¬Ə|oėjġĠÑN¡ð¯EBčnwôɍėª²CλŹġǝʅįĭạ̃ūȹ]ΓͧgšsgȽóϧµǛęgſ¶ҍć`ĘąŌJÞä¤rÅň¥ÖÁUětęuůÞiĊÄÀ\\Æs¦ÓRb|Â^řÌkÄŷ¶½÷f±iMÝ@ĥ°G¬ÃM¥n£Øąğ¯ß§aëbéüÑOčk£{\\eµª×MÉfm«Ƒ{Å×Gŏǩãy³©WÑăû··Qòı}¯ãIéÕÂZ¨īès¶ZÈsæĔTŘvgÌsN@îá¾ó@ÙwU±ÉT廣TđWxq¹Zobs[ׯcĩvėŧ³BM|¹kªħ¥TzNYnÝßpęrñĠĉRS~½ěVVµõ«M££µBĉ¥áºae~³AuĐh`ܳç@BÛïĿa©|z²Ý¼D£àč²ŸIûI āóK¥}rÝ_Á´éMaň¨~ªSĈ½½KÙóĿeƃÆB·¬ën×W|Uº}LJrƳlŒµ`bÔ`QÐÓ@s¬ñIÍ@ûws¡åQÑßÁ`ŋĴ{ĪTÚÅTSijYo|Ç[ǾµMW¢ĭiÕØ¿@Mh
pÕ]jéò¿OƇĆƇpêĉâlØwěsǩĵ¸c
bU¹ř¨WavquSMzeo_^gsÏ·¥Ó@~¯¿RiīB\\qTGªÇĜçPoÿfñòą¦óQīÈáPābß{ZŗĸIæÅhnszÁCËìñÏ·ąĚÝUm®óL·ăUÈíoù´Êj°ŁŤ_uµ^°ìÇ@tĶĒ¡ÆM³Ģ«İĨÅ®ğRāðggheÆ¢zÊ©Ô\\°ÝĎz~ź¤PnMĪÖB£kné§żćĆKǰ¼L¶èâz¨u¦¥LDĘz¬ýÎmĘd¾ßFzhg²Fy¦ĝ¤ċņbÎ@yĄæm°NĮZRÖíJ²öLĸÒ¨Y®ƌÐVàtt_ÚÂyĠz]ŢhzĎ{ÂĢXc|ÐqfO¢¤ögÌHNPKŖUú´xx[xvĐCûĀìÖT¬¸^}Ìsòd´_KgžLĴ
ÀBon|H@Êx¦BpŰŌ¿fµƌA¾zLjRx¶FkĄźRzŀ~¶[´HnªVƞuĒȨƎcƽÌm¸ÁÈM¦x͊ëÀxdžBú^´W£dkɾĬpw˂ØɦļĬIŚÊnŔa¸~J°îlɌxĤÊÈðhÌ®gT´øàCÀ^ªerrƘd¢İP|Ė ŸWªĦ^¶´ÂLaT±üWƜǀRÂŶUńĖ[QhlLüAÜ\\qRĄ©"
|
||||
],
|
||||
"encodeOffsets": [[90849, 37210]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "610000",
|
||||
"properties": {
|
||||
"id": "610000",
|
||||
"cp": [108.948024, 34.263161],
|
||||
"name": "陕西",
|
||||
"childNum": 1
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@p¢ȮµûGĦ}Ħðǚ¶òƄjɂz°{ºØkÈęâ¦jªBg\\ċ°s¬]jú EȌdž¬stRÆdĠİwܸôW¾ƮłÒ_{Ìû¼jº¹¢GǪÒ¯ĘZ`ºŊecņą~BÂgzpâēòYǠȰÌTΨÂW|fcă§uF@N¢XLRMº[ğȣſï|¥Jkc`sʼnǷY¹W@µ÷K
ãï³ÛIcñ·VȋÚÒķø©þ¥yÓğęmWµÎumZyOŅƟĥÓ~sÑL¤µaÅ
Y¦ocyZ{y c]{Ta©`U_Ěē£ωÊƍKùK¶ȱÝƷ§{û»ÅÁȹÍéuij|¹cÑdìUYOuFÕÈYvÁCqÓTǢí§·S¹NgV¬ë÷Át°DدC´ʼnƒópģ}ċcEË
FéGU¥×K
§¶³BČ}C¿åċ`wġB·¤őcƭ²ő[Å^axwQO
ÿEËߌĤNĔwƇÄńwĪo[_KÓª³ÙnKÇěÿ]ďă_d©·©Ýŏ°Ù®g]±ßå¬÷m\\iaǑkěX{¢|ZKlçhLtŇîŵœè[É@ƉĄEtƇϳħZ«mJ
×¾MtÝĦ£IwÄå\\Õ{OwĬ©LÙ³ÙgBƕŀrÌĢŭO¥lãyC§HÍ£ßEñX¡°ÙCgpťzb`wIvA|§hoĕ@E±iYd¥OϹS|}F@¾oAO²{tfÜ¢FǂÒW²°BĤh^Wx{@¬F¸¡ķn£P|ªĴ@^ĠĈæbÔc¶lYi
^MicϰÂ[ävï¶gv@ÀĬ·lJ¸sn|¼u~a]ÆÈtŌºJpþ£KKf~¦UbyäIĺãnÔ¿^ŵMThĠܤko¼Ŏìąǜh`[tRd²IJ_XPrɲlXiL§à¹H°Ȧqº®QCbAŌJ¸ĕÚ³ĺ§ `d¨YjiZvRĺ±öVKkjGȊÄePĞZmļKÀ[`ösìhïÎoĬdtKÞ{¬èÒÒBÔpIJÇĬJŊ¦±J«Y§@·pHµàåVKepWftsAÅqC·¬ko«pHÆuK@oHĆÛķhxenS³àǍrqƶRbzy¸ËÐl¼EºpĤ¼x¼½~Ğà@ÚüdK^mÌSj"
|
||||
],
|
||||
"encodeOffsets": [[110234, 38774]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "620000",
|
||||
"properties": {
|
||||
"id": "620000",
|
||||
"cp": [103.823557, 36.058039],
|
||||
"name": "甘肃",
|
||||
"childNum": 2
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@VuUv"],
|
||||
[
|
||||
"@@ũEĠtt~nkh`Q¦ÅÄÜdwAb×ĠąJ¤DüègĺqBqj°lI¡ĨÒ¤úSHbjÎB°aZ¢KJO[|A£Dx}NìHUnrk kp¼Y kMJn[aGáÚÏ[½rc}aQxOgsPMnUsncZ
sKúvAtÞġ£®ĀYKdnFw¢JE°Latf`¼h¬we|Æbj}GA·~W`¢MC¤tL©IJ°qdfObÞĬ¹ttu`^ZúE`[@Æsîz®¡CƳƜG²R¢RmfwĸgÜą G@pzJM½mhVy¸uÈÔO±¨{LfæU¶ßGĂq\\ª¬²I¥IʼnÈīoıÓÑAçÑ|«LÝcspīðÍg
të_õ\\ĉñLYnĝgRǡÁiHLlõUĹ²uQjYi§Z_c¨´ĹĖÙ·ŋI
aBDR¹ȥr¯GºßK¨jWkɱOqWij\\aQ\\sg_ĆǛōëp»£lğÛgSŶN®À]ÓämĹãJaz¥V}Le¤Lýo¹IsŋÅÇ^bz
³tmEÁ´a¹cčecÇNĊãÁ\\č¯dNj]jZµkÓdaćå]ğij@ ©O{¤ĸm¢E·®«|@Xwg]A챝XǁÑdzªcwQÚŝñsÕ³ÛV_ý¥\\ů¥©¾÷w©WÕÊĩhÿÖÁRo¸V¬âDb¨hûxÊ×nj~Zâg|XÁnßYoº§ZÅŘv[ĭÖʃuďxcVbnUSf
B¯³_TzºÎO©çMÑ~M³]µ^püµÄY~y@X~¤Z³[Èōl@®Å¼£QK·Di¡ByÿQ_´D¥hŗy^ĭÁZ]cIzýah¹MĪğPs{ò²Vw¹t³ŜË[Ñ}X\\gsF£sPAgěp×ëfYHāďÖqēŭOÏëdLü\\it^c®Rʺ¶¢H°mrY£B¹čIoľu¶uI]vģSQ{UŻÅ}QÂ|̰ƅ¤ĩŪU ęĄÌZÒ\\v²PĔ»ƢNHĂyAmƂwVm`]ÈbH`Ì¢²ILvĜH®¤Dlt_¢JJÄämèÔDëþgºƫaʎÌrêYi~ ÎݤNpÀA¾Ĕ¼b
ð÷®üszMzÖĖQdȨýv§Tè|ªHþa¸|Ð ƒwKĢx¦ivr^ÿ ¸l öæfƟĴ·PJv}n\\h¹¶v·À|\\ƁĚN´ĜçèÁz]ġ¤²¨QÒŨTIlªťØ}¼˗ƦvÄùØE«FïËIqōTvāÜŏíÛßÛVj³âwGăÂíNOPìyV³ʼnĖýZso§HÑiYw[ß\\X¦¥c]ÔƩÜ·«jÐqvÁ¦m^ċ±R¦ƈťĚgÀ»IïĨʗƮ°ƝĻþÍAƉſ±tÍEÕÞāNUÍ¡\\ſčåÒʻĘm ƭÌŹöʥëQ¤µÇcƕªoIýIÉ_mkl³ăƓ¦j¡YzŇi}Msßõīʋ }ÁVm_[n}eıUĥ¼ªI{ΧDÓƻėojqYhĹT©oūĶ£]ďxĩǑMĝq`B´ƃ˺Чç~²ņj@¥@đ´ί}ĥtPńǾV¬ufÓÉCtÓ̻
¹£G³]ƖƾŎĪŪĘ̖¨ʈĢƂlɘ۪üºňUðǜȢƢż̌ȦǼĤŊɲĖÂKq´ï¦ºĒDzņɾªǀÞĈĂD½ĄĎÌŗĞrôñnN¼â¾ʄľԆ|DŽ֦ज़ȗlj̘̭ɺƅêgV̍ʆĠ·ÌĊv|ýĖÕWĊǎÞ´õ¼cÒÒBĢ͢UĜð͒s¨ňƃLĉÕÝ@ɛƯ÷¿ĽĹeȏijëCȚDŲyê×Ŗyò¯ļcÂßY
tÁƤyAã˾J@ǝrý@¤
rz¸oP¹ɐÚyáHĀ[Jw
cVeȴÏ»ÈĖ}ƒŰŐèȭǢόĀƪÈŶë;Ñ̆ȤМľĮEŔĹŊũ~ËUă{ĻƹɁύȩþĽvĽƓÉ@ēĽɲßǐƫʾǗĒpäWÐxnsÀ^ƆwW©¦cÅ¡Ji§vúF¶¨c~c¼īeXǚ\\đ¾JwÀďksãAfÕ¦L}waoZD½Ml«]eÒÅaɲáo½FõÛ]ĻÒ¡wYR£¢rvÓ®y®LFLzĈôe]gx}|KK}xklL]c¦£fRtív¦PĤoH{tK"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[108619, 36299]], [[108589, 36341]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "630000",
|
||||
"properties": { "id": "630000", "cp": [96.778916, 35.623178], "name": "青海", "childNum": 2 },
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@InJm"],
|
||||
[
|
||||
"@@CƽOŃĦsΰ~dz¦@@Ņi±è}ШƄ˹A³r_ĞǒNĪĐw¤^ŬĵªpĺSZgrpiƼĘÔ¨C|ÍJ©Ħ»®VIJ~f\\m `UnÂ~ʌĬàöNt~ňjy¢ZiƔ¥Ąk´nl`JÊJþ©pdƖ®È£¶ìRʦźõƮËnʼėæÑƀĎ[¢VÎĂMÖÝÎF²sƊƀÎBļýƞ¯ʘƭðħ¼Jh¿ŦęΌƇ¥²Q]Č¥nuÂÏri¸¬ƪÛ^Ó¦d¥[Wà
x\\ZjÒ¨GtpþYŊĕ´zUOëPîMĄÁxH´áiÜUàîÜŐĂÛSuŎrJð̬EFÁú×uÃÎkrĒ{V}İ«O_ÌËĬ©ÓŧSRѱ§Ģ£^ÂyèçěM³Ƃę{[¸¿u
ºµ[gt£¸OƤĿéYõ·kĀq]juw¥DĩƍõÇPéĽG©ã¤G
uȧþRcÕĕNyyûtøï»a½ē¿BMoį£Íj}éZËqbʍƬh¹ìÿÓAçãnIáI`ks£CGěUy×Cy
@¶ʡÊBnāzGơMē¼±O÷õJËĚăVĪũƆ£¯{ËL½ÌzżVR|ĠTbuvJvµhĻĖHAëáa
OÇðñęNw
œľ·LmI±íĠĩPÉ×®ÿscB³±JKßĊ«`
ađ»·QAmOVţéÿ¤¹SQt]]Çx±¯A@ĉij¢Óļ©l¶ÅÛrŕspãRk~¦ª]Į´FRådČsCqđéFn¿ÅƃmÉx{W©ºƝºįkÕƂƑ¸wWūЩÈF£\\tÈ¥ÄRÈýÌJ lGr^×äùyÞ³fjc¨£ÂZ|ǓMĝÏ@ëÜőRĝ÷¡{aïȷPu°ËXÙ{©TmĠ}Y³ÞIňµç½©C¡į÷¯B»|St»]vųs»}MÓ ÿʪƟǭA¡fs»PY¼c¡»¦cċ¥£~msĉPSi^o©AecPeǵkgyUi¿h}aHĉ^|á´¡HØûÅ«ĉ®]m¡qĉ¶³ÈyôōLÁstB®wn±ă¥HSòė£Së@לÊăxÇN©©T±ª£IJ¡fb®Þbb_Ą¥xu¥B{łĝ³«`dƐt¤ťiñÍUuºí`£^tƃIJc·ÛLO½sç¥Ts{ă\\_»kϱq©čiìĉ|ÍI¥ć¥]ª§D{ŝŖÉR_sÿc³ĪōƿΧp[ĉc¯bKmR¥{³Ze^wx¹dƽŽôIg §Mĕ ƹĴ¿ǣÜÍ]Ý]snåA{eƭ`ǻŊĿ\\ijŬűYÂÿ¬jĖqßb¸L«¸©@ěĀ©ê¶ìÀEH|´bRľÓ¶rÀQþvl®ÕETzÜdb hw¤{LRdcb¯ÙVgƜßzÃôì®^jUèXÎ|UäÌ»rK\\ªN¼pZCüVY¤ɃRi^rPŇTÖ}|br°qňb̰ªiƶGQ¾²x¦PmlŜ[Ĥ¡ΞsĦÔÏâ\\ªÚŒU\\f
¢N²§x|¤§xĔsZPòʛ²SÐqF`ªVÞŜĶƨVZÌL`¢dŐIqr\\oäõF礻Ŷ×h¹]ClÙ\\¦ďÌį¬řtTӺƙgQÇÓHţĒ´ÃbEÄlbʔC|CŮkƮ[ʼ¬ň´KŮÈΰÌζƶlðļATUvdTGº̼ÔsÊDÔveOg"
|
||||
]
|
||||
],
|
||||
"encodeOffsets": [[[105308, 37219]], [[95370, 40081]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "640000",
|
||||
"properties": { "id": "640000", "cp": [106.278179, 37.26637], "name": "宁夏", "childNum": 2 },
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
[
|
||||
"@@KëÀęĞ«Oęȿȕı]ʼn¡åįÕÔ«ǴõƪĚQÐZhv K°öqÀÑS[ÃÖHƖčËnL]ûc
Ùß@ĝ¾}w»»oģF¹»kÌÏ·{zP§B¢íyÅt@@á]Yv_ssģ¼ißĻL¾ġsKD£¡N_
X¸}B~HaiÅf{«x»ge_bsKF¯¡IxmELcÿZ¤ĢÝsuBLùtYdmVtNmtOPhRw~bd
¾qÐ\\âÙH\\bImlNZ»loqlVmGā§~QCw¤{A\\PKNY¯bFkC¥sks_Ã\\ă«¢ħkJi¯rrAhĹûç£CUĕĊ_ÔBixÅÙĄnªÑaM~ħpOu¥sîeQ¥¤^dkKwlL~{L~hw^ófćKyEKzuÔ¡qQ¤xZÑ¢^ļöܾEp±âbÊÑÆ^fk¬
NC¾YpxbK~¥eÖäBlt¿Đx½I[ĒǙWf»Ĭ}d§dµùEuj¨IÆ¢¥dXªƅx¿]mtÏwßRĶX¢͎vÆzƂZò®ǢÌʆCrâºMÞzÆMÒÊÓŊZľr°Î®Ȉmª²ĈUªĚîøºĮ¦ÌĘk^FłĬhĚiĀ˾iİbjÕ"
|
||||
],
|
||||
["@@mfwěwMrŢªv@G"]
|
||||
],
|
||||
"encodeOffsets": [[[109366, 40242]], [[108600, 36303]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "650000",
|
||||
"properties": { "id": "650000", "cp": [85.617733, 40.792818], "name": "新疆", "childNum": 1 },
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@QØĔ²X¨~ǘBºjʐߨvKƔX¨vĊO÷¢i@~cĝe_«E}QxgɪëÏÃ@sÅyXoŖ{ô«ŸuX
êÎf`C¹ÂÿÐGĮÕĞXŪōŸMźÈƺQèĽôe|¿ƸJR¤ĘEjcUóº¯Ĩ_ŘÁMª÷Ð¥OéÈ¿ÖğǤǷÂFÒzÉx[]Ĥĝœ¦EP}ûƥé¿İƷTėƫœŕƅƱB»Đ±ēO
¦E}`cȺrĦáŖuÒª«IJπdƺÏØZƴwʄ¤ĖGĐǂZĶèH¶}ÚZצʥĪï|ÇĦMŔ»İĝLjì¥Βba¯¥ǕǚkĆŵĦɑĺƯxūД̵nơʃĽá½M»òmqóŘĝč˾ăC
ćāƿÝɽ©DZҹđ¥³ðLrÁ®ɱĕģʼnǻ̋ȥơŻǛȡVï¹Ň۩ûkɗġƁ§ʇė̕ĩũƽō^ƕUv£ƁQïƵkŏ½ΉÃŭdzLŇʻ«ƭ\\lŭD{ʓDkaFÃÄa³ŤđÔGRÈƚhSӹŚsİ«ĐË[¥ÚDkº^Øg¼ŵ¸£EÍöůʼnT¡c_ËKYƧUśĵÝU_©rETÏʜ±OñtYwē¨{£¨uM³x½şL©Ùá[ÓÐĥ Νtģ¢\\śnkOw¥±T»ƷFɯàĩÞáB¹Æ
ÑUwŕĽw[mG½Èå~Æ÷QyěCFmĭZīŵVÁƿQƛûXS²b½KϽĉS©ŷXĕ{ĕK·¥Ɨcqq©f¿]ßDõU³hgËÇïģÉɋwk¯í}I·œbmÉřīJɥĻˁ×xoɹīlc
¤³Xù]DžA¿w͉ì¥wÇN·ÂËnƾƍdǧđ®ƝvUm©³G\\}µĿQyŹlăµEwLJQ½yƋBe¶ŋÀůo¥AÉw@{Gpm¿AijŽKLh³`ñcËtW±»ÕSëüÿďDu\\wwwù³VLŕOMËGh£õP¡erÏd{ġWÁ
č|yšg^ğyÁzÙs`s|ÉåªÇ}m¢Ń¨`x¥ù^}Ì¥H«YªƅAйn~ź¯f¤áÀzgÇDIÔ´AňĀÒ¶ûEYospõD[{ù°]uJqU|Soċxţ[õÔĥkŋÞŭZ˺óYËüċrw ÞkrťË¿XGÉbřaDü·Ē÷Aê[ÄäI®BÕĐÞ_¢āĠpÛÄȉĖġDKwbmÄNôfƫVÉvidzHQµâFùœ³¦{YGd¢ĚÜO {Ö¦ÞÍÀP^bƾl[vt×ĈÍE˨¡Đ~´î¸ùÎhuè`¸HÕŔVºwĠââWò@{ÙNÝ´ə²ȕn{¿¥{l÷eé^eďXj©î\\ªÑòÜìc\\üqÕ[Č¡xoÂċªbØø|¶ȴZdÆÂońéG\\¼C°ÌÆn´nxÊOĨŪƴĸ¢¸òTxÊǪMīĞÖŲÃɎOvʦƢ~FRěò¿ġ~åŊúN¸qĘ[Ĕ¶ÂćnÒPĒÜvúĀÊbÖ{Äî¸~Ŕünp¤ÂH¾ĄYÒ©ÊfºmÔĘcDoĬMŬS¤s²ʘÚžȂVŦ èW°ªB|IJXŔþÈJĦÆæFĚêYĂªĂ]øªŖNÞüAfɨJ¯ÎrDDĤ`mz\\§~D¬{vJ«lµĂb¤pŌŰNĄ¨ĊXW|ų ¿¾ɄĦƐMTòP÷fØĶK¢ȝ˔Sô¹òEð`Ɩ½ǒÂň×äı§ĤƝ§C~¡hlåǺŦŞkâ~}FøàIJaĞfƠ¥Ŕd®U¸źXv¢aƆúŪtŠųƠjdƺƺÅìnrh\\ĺ¯äɝĦ]èpĄ¦´LƞĬ´ƤǬ˼Ēɸ¤rºǼ²¨zÌPðŀbþ¹ļD¢¹\\ĜÑŚ¶ZƄ³àjĨoâȴLÊȮĐĚăÀêZǚŐ¤qȂ\\L¢ŌİfÆs|zºeªÙæ§{Ā´ƐÚ¬¨Ĵà²łhʺKÞºÖTiƢ¾ªì°`öøu®Ê¾ãØ"
|
||||
],
|
||||
"encodeOffsets": [[88824, 50096]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "110000",
|
||||
"properties": {
|
||||
"id": "110000",
|
||||
"cp": [116.405285, 39.904989],
|
||||
"name": "北京",
|
||||
"childNum": 1
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@ĽOÁûtŷmiÍt_H»Ĩ±d`¹{bw
Yr³S]§§o¹qGtm_SŧoaFLgQN_dV@Zom_ć\\ßc±x¯oœRcfe
£o§ËgToÛJíĔóu
|wP¤XnO¢ÉŦ¯rNÄā¤zâŖÈRpŢZÚ{GrFt¦Òx§ø¹RóäV¤XdżâºWbwڍUd®bêņ¾jnŎGŃŶnzÚSeîĜZczî¾i]ÍQaúÍÔiþĩȨWĢü|Ėu[qb[swP@ÅğP¿{\\¥A¨ÏѨj¯X\\¯MKpA³[H
īu}}"
|
||||
],
|
||||
"encodeOffsets": [[120023, 41045]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "120000",
|
||||
"properties": {
|
||||
"id": "120000",
|
||||
"cp": [117.190182, 39.125596],
|
||||
"name": "天津",
|
||||
"childNum": 1
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
"@@ŬgX§Ü«E
¶F̬O_ïlÁgz±AXeµÄĵ{¶]gitgIj·¥îakS¨ÐƎk}ĕ{gBqGf{¿aU^fIư³õ{YıëNĿk©ïËZŏR§òoY×Ógc
ĥs¡bġ«@dekąI[nlPqCnp{ō³°`{PNdƗqSÄĻNNâyj]äÒD ĬH°Æ]~¡HO¾X}ÐxgpgWrDGpù^LrzWxZ^¨´T\\|~@IzbĤjeĊªz£®ĔvěLmV¾Ô_ÈNW~zbĬvG²ZmDM~~"
|
||||
],
|
||||
"encodeOffsets": [[120237, 41215]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "310000",
|
||||
"properties": {
|
||||
"id": "310000",
|
||||
"cp": [121.472644, 31.231706],
|
||||
"name": "上海",
|
||||
"childNum": 6
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@ɧư¬EpƸÁxc"],
|
||||
["@@©ª"],
|
||||
["@@MA"],
|
||||
["@@QpİE§ÉC¾"],
|
||||
["@@bŝÕÕEȣÚƥêImɇǦèÜĠÚÃƌÃ͎ó"],
|
||||
["@@ǜûȬɋŭ×^sYɍDŋŽąñCG²«ªč@h_p¯A{oloY¬j@IJ`gQÚhr|ǀ^MIJvtbe´R¯Ô¬¨Yô¤r]ìƬį"]
|
||||
],
|
||||
"encodeOffsets": [[[124702, 32062]], [[124547, 32200]], [[124808, 31991]], [[124726, 32110]], [[124903, 32376]], [[124438, 32149]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "500000",
|
||||
"properties": {
|
||||
"id": "500000",
|
||||
"cp": [107.304962, 29.533155],
|
||||
"name": "重庆",
|
||||
"childNum": 2
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
[
|
||||
"@@vjG~nGŘŬĶȂƀƾ¹¸ØÎezĆT¸}êÐqHðqĖä¥^CÆIj²p
\\_ æüY|[YxƊæu°xb®
Űb@~¢NQt°¶Sæ Ê~rljĔëĚ¢~uf`faĔJåĊnÖ]jƎćÊ@£¾a®£Ű{ŶĕFègLk{Y|¡ĜWƔtƬJÑxq±ĢN´òKLÈüD|s`ŋć]Ã`đMûƱ½~Y°ħ`ƏíW½eI½{aOIrÏ¡ĕŇapµÜƅġ^ÖÛbÙŽŏml½SêqDu[RãË»ÿw`»y¸_ĺę}÷`M¯ċfCVµqʼn÷Zgg`d½pDOÎCn^uf²ènh¼WtƏxRGg¦
pVFI±G^Ic´ecGĹÞ½sëĬhxW}KÓeXsbkF¦LØgTkïƵNï¶}Gyw\\oñ¡nmĈzj@Óc£»Wă¹Ój_m»¹·~MvÛaq»ê\\ÂoVnÓØÍ²«bq¿efE Ĝ^Q~ Évýş¤²ĮpEİ}zcĺL½¿gÅ¡ýE¡ya£³t\\¨\\vú»¼§·Ñr_oÒý¥u_n»_At©Þűā§IVeëY}{VPÀFA¨ąB}q@|Ou\\FmQFÝ
Mwå}]|FmÏCawu_p¯sfÙgY
DHl`{QEfNysB¦zG¸rHeN\\CvEsÐùÜ_·ÖĉsaQ¯}_UxÃđqNH¬Äd^ÝŰR¬ã°wećJE·vÝ·HgéFXjÉê`|ypxkAwWĐpb¥eOsmzwqChóUQl¥F^lafanòsrEvfQdÁUVfÎvÜ^eftET¬ôA\\¢sJnQTjPØxøK|nBzĞ»LY
FDxÓvr[ehľvN¢o¾NiÂxGpâ¬zbfZo~hGi]öF||NbtOMn eA±tPTLjpYQ|SHYĀxinzDJÌg¢và¥Pg_ÇzIIII£®S¬Øsμ£N"
|
||||
],
|
||||
["@@ifjN@s"]
|
||||
],
|
||||
"encodeOffsets": [[[109628, 30765]], [[111725, 31320]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "810000",
|
||||
"properties": {
|
||||
"id": "810000",
|
||||
"cp": [114.173355, 22.320048],
|
||||
"name": "香港",
|
||||
"childNum": 5
|
||||
},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
["@@AlBk"],
|
||||
["@@mn"],
|
||||
["@@EpFo"],
|
||||
["@@ea¢pl¸Eõ¹hj[]ÔCÎ@lj¡uBX
´AI¹
[yDU]W`çwZkmc
MpÅv}IoJlcafŃK°ä¬XJmÐ đhI®æÔtSHnEÒrÈc"],
|
||||
["@@rMUwAS®e"]
|
||||
],
|
||||
"encodeOffsets": [[[117111, 23002]], [[117072, 22876]], [[117045, 22887]], [[116975, 23082]], [[116882, 22747]]]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"id": "820000",
|
||||
"properties": { "id": "820000", "cp": [113.54909, 22.198951], "name": "澳门", "childNum": 1 },
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": ["@@kÊd°å§s"],
|
||||
"encodeOffsets": [[116279, 22639]]
|
||||
}
|
||||
}
|
||||
],
|
||||
"UTF8Encoding": true
|
||||
}
|
||||
@ -1,189 +0,0 @@
|
||||
export const mapData: any = [
|
||||
{
|
||||
name: '北京',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '天津',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '上海',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '重庆',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '河北',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '河南',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '云南',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '辽宁',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '黑龙江',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '湖南',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '安徽',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '山东',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '新疆',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '江苏',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '浙江',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '江西',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '湖北',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '广西',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '甘肃',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '山西',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '内蒙古',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '陕西',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '吉林',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '福建',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '贵州',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '广东',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '青海',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '西藏',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '四川',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '宁夏',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '海南',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '台湾',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '香港',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
{
|
||||
name: '澳门',
|
||||
value: Math.round(Math.random() * 1000),
|
||||
tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)],
|
||||
},
|
||||
];
|
||||
|
||||
export const getLineData = (() => {
|
||||
const category: any[] = [];
|
||||
let dottedBase = +new Date();
|
||||
const lineData: any[] = [];
|
||||
const barData: any[] = [];
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
const date = new Date((dottedBase += 1000 * 3600 * 24));
|
||||
category.push([date.getFullYear(), date.getMonth() + 1, date.getDate()].join('-'));
|
||||
const b = Math.random() * 200;
|
||||
const d = Math.random() * 200;
|
||||
barData.push(b);
|
||||
lineData.push(d + b);
|
||||
}
|
||||
return { barData, category, lineData };
|
||||
})();
|
||||
@ -1,45 +0,0 @@
|
||||
<template>
|
||||
<div ref="wrapRef" :style="{ height, width }"></div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, nextTick, unref, onMounted } from 'vue';
|
||||
|
||||
import { useScript } from '/@/hooks/web/useScript';
|
||||
|
||||
const BAI_DU_MAP_URL = 'https://api.map.baidu.com/getscript?v=3.0&ak=OaBvYmKX3pjF7YFUFeeBCeGdy9Zp7xB2&services=&t=20210201100830&s=1';
|
||||
export default defineComponent({
|
||||
name: 'BaiduMap',
|
||||
props: {
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%',
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: 'calc(100vh - 78px)',
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const wrapRef = ref<HTMLDivElement | null>(null);
|
||||
const { toPromise } = useScript({ src: BAI_DU_MAP_URL });
|
||||
|
||||
async function initMap() {
|
||||
await toPromise();
|
||||
await nextTick();
|
||||
const wrapEl = unref(wrapRef);
|
||||
if (!wrapEl) return;
|
||||
const BMap = (window as any).BMap;
|
||||
const map = new BMap.Map(wrapEl);
|
||||
const point = new BMap.Point(116.404, 39.915);
|
||||
map.centerAndZoom(point, 15);
|
||||
map.enableScrollWheelZoom(true);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initMap();
|
||||
});
|
||||
|
||||
return { wrapRef };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,47 +0,0 @@
|
||||
<template>
|
||||
<div ref="wrapRef" :style="{ height, width }"></div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, nextTick, unref, onMounted } from 'vue';
|
||||
|
||||
import { useScript } from '/@/hooks/web/useScript';
|
||||
|
||||
const A_MAP_URL = 'https://webapi.amap.com/maps?v=2.0&key=06313eb9c6563b674a8fd789db0692c3';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AMap',
|
||||
props: {
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%',
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: 'calc(100vh - 78px)',
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const wrapRef = ref<HTMLDivElement | null>(null);
|
||||
const { toPromise } = useScript({ src: A_MAP_URL });
|
||||
|
||||
async function initMap() {
|
||||
await toPromise();
|
||||
await nextTick();
|
||||
const wrapEl = unref(wrapRef);
|
||||
if (!wrapEl) return;
|
||||
const AMap = (window as any).AMap;
|
||||
new AMap.Map(wrapEl, {
|
||||
zoom: 11,
|
||||
center: [116.397428, 39.90923],
|
||||
viewMode: '3D',
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initMap();
|
||||
});
|
||||
|
||||
return { wrapRef };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,52 +0,0 @@
|
||||
<template>
|
||||
<div ref="wrapRef" :style="{ height, width }"></div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, nextTick, unref, onMounted } from 'vue';
|
||||
|
||||
import { useScript } from '/@/hooks/web/useScript';
|
||||
|
||||
const MAP_URL = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyBQWrGwj4gAzKndcbwD5favT9K0wgty_0&signed_in=true';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'GoogleMap',
|
||||
props: {
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%',
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: 'calc(100vh - 78px)',
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const wrapRef = ref<HTMLDivElement | null>(null);
|
||||
const { toPromise } = useScript({ src: MAP_URL });
|
||||
|
||||
async function initMap() {
|
||||
await toPromise();
|
||||
await nextTick();
|
||||
const wrapEl = unref(wrapRef);
|
||||
if (!wrapEl) return;
|
||||
const google = (window as any).google;
|
||||
const latLng = { lat: 116.404, lng: 39.915 };
|
||||
const map = new google.maps.Map(wrapEl, {
|
||||
zoom: 4,
|
||||
center: latLng,
|
||||
});
|
||||
new google.maps.Marker({
|
||||
position: latLng,
|
||||
map: map,
|
||||
title: 'Hello World!',
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initMap();
|
||||
});
|
||||
|
||||
return { wrapRef };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,67 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<textarea ref="textarea">
|
||||
白日依山尽,黄河入海流。
|
||||
欲穷千里目,更上一层楼。
|
||||
</textarea
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, ref, reactive } from 'vue';
|
||||
// 引入全局实例
|
||||
import _CodeMirror from 'codemirror';
|
||||
|
||||
// 核心样式
|
||||
import 'codemirror/lib/codemirror.css';
|
||||
// 引入主题后还需要在 options 中指定主题才会生效
|
||||
import 'codemirror/theme/cobalt.css';
|
||||
|
||||
// 需要引入具体的语法高亮库才会有对应的语法高亮效果
|
||||
// codemirror 官方其实支持通过 /addon/mode/loadmode.js 和 /mode/meta.js 来实现动态加载对应语法高亮库
|
||||
// 但 vue 貌似没有无法在实例初始化后再动态加载对应 JS ,所以此处才把对应的 JS 提前引入
|
||||
import 'codemirror/mode/javascript/javascript.js';
|
||||
import 'codemirror/mode/css/css.js';
|
||||
import 'codemirror/mode/xml/xml.js';
|
||||
import 'codemirror/mode/clike/clike.js';
|
||||
import 'codemirror/mode/markdown/markdown.js';
|
||||
import 'codemirror/mode/python/python.js';
|
||||
import 'codemirror/mode/r/r.js';
|
||||
import 'codemirror/mode/shell/shell.js';
|
||||
import 'codemirror/mode/sql/sql.js';
|
||||
import 'codemirror/mode/swift/swift.js';
|
||||
import 'codemirror/mode/vue/vue.js';
|
||||
// 尝试获取全局实例
|
||||
|
||||
export default defineComponent({
|
||||
components: {},
|
||||
setup() {
|
||||
const CodeMirror = window.CodeMirror || _CodeMirror;
|
||||
|
||||
const textarea = ref(null);
|
||||
const options = reactive({
|
||||
// 缩进格式
|
||||
tabSize: 2,
|
||||
// 主题,对应主题库 JS 需要提前引入
|
||||
theme: 'cobalt',
|
||||
// 显示行号
|
||||
lineNumbers: true,
|
||||
line: true,
|
||||
});
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
|
||||
function init() {
|
||||
CodeMirror.fromTextArea(textarea.value, options);
|
||||
}
|
||||
|
||||
return {
|
||||
textarea,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped></style>
|
||||
@ -1,110 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper
|
||||
contentFullHeight
|
||||
title="基础组件"
|
||||
content=" 基础组件依赖于ant-design-vue,组件库已有的基础组件,项目中不会再次进行demo展示(二次封装组件除外)"
|
||||
>
|
||||
<a-row :gutter="[20, 20]">
|
||||
<a-col :xl="10" :lg="24">
|
||||
<a-card title="BasicButton Color">
|
||||
<div class="my-2">
|
||||
<h3>success</h3>
|
||||
<div class="py-2">
|
||||
<a-button color="success"> 成功 </a-button>
|
||||
<a-button color="success" class="ml-2" disabled> 禁用 </a-button>
|
||||
<a-button color="success" class="ml-2" loading> loading </a-button>
|
||||
<a-button color="success" type="link" class="ml-2"> link </a-button>
|
||||
<a-button color="success" type="link" class="ml-2" loading> loading link </a-button>
|
||||
<a-button color="success" type="link" class="ml-2" disabled> disabled link </a-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<h3>warning</h3>
|
||||
<a-button color="warning"> 警告 </a-button>
|
||||
<a-button color="warning" class="ml-2" disabled> 禁用 </a-button>
|
||||
<a-button color="warning" class="ml-2" loading> loading </a-button>
|
||||
<a-button color="warning" type="link" class="ml-2"> link </a-button>
|
||||
<a-button color="warning" type="link" class="ml-2" loading> loading link </a-button>
|
||||
<a-button color="warning" type="link" class="ml-2" disabled> disabled link </a-button>
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<h3>error</h3>
|
||||
<a-button color="error"> 错误 </a-button>
|
||||
<a-button color="error" class="ml-2" disabled> 禁用 </a-button>
|
||||
<a-button color="error" class="ml-2" loading> loading </a-button>
|
||||
<a-button color="error" type="link" class="ml-2"> link </a-button>
|
||||
<a-button color="error" type="link" class="ml-2" loading> loading link </a-button>
|
||||
<a-button color="error" type="link" class="ml-2" disabled> disabled link </a-button>
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<h3>ghost</h3>
|
||||
<a-button ghost color="success" class="ml-2"> 幽灵成功 </a-button>
|
||||
<a-button ghost color="warning" class="ml-2"> 幽灵警告 </a-button>
|
||||
<a-button ghost color="error" class="ml-2"> 幽灵错误 </a-button>
|
||||
<a-button ghost type="dashed" color="warning" class="ml-2"> 幽灵警告dashed </a-button>
|
||||
<a-button ghost danger class="ml-2"> 幽灵危险 </a-button>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :xl="14" :lg="24">
|
||||
<a-card title="BasicButton Types">
|
||||
<div class="my-2">
|
||||
<h3>primary</h3>
|
||||
<a-button type="primary" preIcon="mdi:page-next-outline"> 主按钮 </a-button>
|
||||
<a-button type="primary" class="ml-2" disabled> 禁用 </a-button>
|
||||
<a-button type="primary" class="ml-2" danger preIcon="mdi:page-next-outline"> 危险 </a-button>
|
||||
<a-button type="primary" class="ml-2" loading> loading </a-button>
|
||||
<a-button type="link" class="ml-2"> link </a-button>
|
||||
<a-button type="link" class="ml-2" loading> loading link </a-button>
|
||||
<a-button type="link" class="ml-2" disabled> disabled link </a-button>
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<h3>default</h3>
|
||||
<a-button type="default"> 默认 </a-button>
|
||||
<a-button type="default" class="ml-2" disabled> 禁用 </a-button>
|
||||
<a-button type="default" class="ml-2" danger> 危险 </a-button>
|
||||
<a-button type="default" class="ml-2" loading> loading </a-button>
|
||||
<a-button type="link" class="ml-2"> link </a-button>
|
||||
<a-button type="link" class="ml-2" loading> loading link </a-button>
|
||||
<a-button type="link" class="ml-2" disabled> disabled link </a-button>
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<h3>dashed</h3>
|
||||
<a-button type="dashed"> dashed </a-button>
|
||||
<a-button type="dashed" class="ml-2" disabled> 禁用 </a-button>
|
||||
<a-button type="dashed" class="ml-2" danger> 危险 </a-button>
|
||||
<a-button type="dashed" class="ml-2" loading> loading </a-button>
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<h3>ghost 常规幽灵按钮通常用于有色背景下</h3>
|
||||
<div class="bg-gray-400 py-2">
|
||||
<a-button ghost type="primary" class="ml-2"> 幽灵主要 </a-button>
|
||||
<a-button ghost type="default" class="ml-2"> 幽灵默认 </a-button>
|
||||
<a-button ghost type="dashed" class="ml-2"> 幽灵dashed </a-button>
|
||||
<a-button ghost type="primary" class="ml-2" disabled> 禁用 </a-button>
|
||||
<a-button ghost type="primary" class="ml-2" loading> loading </a-button>
|
||||
</div>
|
||||
<!-- antd 按钮不能同时使用ghost和link -->
|
||||
<!-- <a-button ghost type="link" class="ml-2"> link </a-button>-->
|
||||
<!-- <a-button ghost type="link" class="ml-2" loading> loading link </a-button>-->
|
||||
<!-- <a-button ghost type="link" class="ml-2" disabled> disabled link </a-button>-->
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { Card, Row, Col } from 'ant-design-vue';
|
||||
export default defineComponent({
|
||||
components: { PageWrapper, ACard: Card, ARow: Row, ACol: Col },
|
||||
});
|
||||
</script>
|
||||
@ -1,32 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="卡片列表示例" content="基础封装">
|
||||
<CardList :params="params" :api="demoListApi" @getMethod="getMethod" @delete="handleDel">
|
||||
<template #header>
|
||||
<Button type="primary" color="error"> 按钮1 </Button>
|
||||
<Button type="primary" color="success"> 按钮2 </Button>
|
||||
</template>
|
||||
</CardList>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { CardList } from '/@/components/CardList';
|
||||
import { Button } from '/@/components/Button';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
const { notification } = useMessage();
|
||||
// 请求api时附带参数
|
||||
const params = {};
|
||||
|
||||
let reload = () => {};
|
||||
// 获取内部fetch方法;
|
||||
function getMethod(m: any) {
|
||||
reload = m;
|
||||
}
|
||||
//删除按钮事件
|
||||
function handleDel(id) {
|
||||
console.log(id);
|
||||
notification.success({ message: `成功删除${id}` });
|
||||
reload();
|
||||
}
|
||||
</script>
|
||||
@ -1,42 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="数字动画示例">
|
||||
<Card>
|
||||
<CardGrid class="count-to-demo-card">
|
||||
<CountTo prefix="$" :color="'#409EFF'" :startVal="1" :endVal="200000" :duration="8000" />
|
||||
</CardGrid>
|
||||
<CardGrid class="count-to-demo-card">
|
||||
<CountTo suffix="$" :color="'red'" :startVal="1" :endVal="300000" :decimals="2" :duration="6000" />
|
||||
</CardGrid>
|
||||
<CardGrid class="count-to-demo-card">
|
||||
<CountTo suffix="$" :color="'rgb(0,238,0)'" :startVal="1" :endVal="400000" :duration="7000" />
|
||||
</CardGrid>
|
||||
<CardGrid class="count-to-demo-card">
|
||||
<CountTo separator="-" :color="'rgba(138,43,226,.6)'" :startVal="10000" :endVal="500000" :duration="8000" />
|
||||
</CardGrid>
|
||||
</Card>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { Card } from 'ant-design-vue';
|
||||
import { CountTo } from '/@/components/CountTo/index';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Card,
|
||||
CardGrid: Card.Grid,
|
||||
CountTo,
|
||||
PageWrapper,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.count-to-demo {
|
||||
&-card {
|
||||
width: 50%;
|
||||
font-size: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,94 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="图片裁剪示例" content="需要开启测试接口服务才能进行上传测试!">
|
||||
<CollapseContainer title="头像裁剪">
|
||||
<CropperAvatar :uploadApi="uploadApi" :value="avatar" />
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="矩形裁剪" class="my-4">
|
||||
<div class="container p-4">
|
||||
<div class="cropper-container mr-10">
|
||||
<CropperImage ref="refCropper" :src="img" @cropend="handleCropend" style="width: 40vw" />
|
||||
</div>
|
||||
<img :src="cropperImg" class="croppered" v-if="cropperImg" alt="" />
|
||||
</div>
|
||||
<p v-if="cropperImg">裁剪后图片信息:{{ info }}</p>
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="圆形裁剪">
|
||||
<div class="container p-4">
|
||||
<div class="cropper-container mr-10">
|
||||
<CropperImage ref="refCropper" :src="img" @cropend="handleCircleCropend" style="width: 40vw" circled />
|
||||
</div>
|
||||
<img :src="circleImg" class="croppered" v-if="circleImg" />
|
||||
</div>
|
||||
<p v-if="circleImg">裁剪后图片信息:{{ circleInfo }}</p>
|
||||
</CollapseContainer>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { CollapseContainer } from '/@/components/Container';
|
||||
import { CropperImage, CropperAvatar } from '/@/components/Cropper';
|
||||
import { uploadApi } from '/@/api/sys/upload';
|
||||
import img from '/@/assets/images/header.jpg';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
PageWrapper,
|
||||
CropperImage,
|
||||
CollapseContainer,
|
||||
CropperAvatar,
|
||||
},
|
||||
setup() {
|
||||
const info = ref('');
|
||||
const cropperImg = ref('');
|
||||
const circleInfo = ref('');
|
||||
const circleImg = ref('');
|
||||
const userStore = useUserStore();
|
||||
const avatar = ref(userStore.getUserInfo?.avatar || '');
|
||||
function handleCropend({ imgBase64, imgInfo }) {
|
||||
info.value = imgInfo;
|
||||
cropperImg.value = imgBase64;
|
||||
}
|
||||
|
||||
function handleCircleCropend({ imgBase64, imgInfo }) {
|
||||
circleInfo.value = imgInfo;
|
||||
circleImg.value = imgBase64;
|
||||
}
|
||||
|
||||
return {
|
||||
img,
|
||||
info,
|
||||
circleInfo,
|
||||
cropperImg,
|
||||
circleImg,
|
||||
handleCropend,
|
||||
handleCircleCropend,
|
||||
avatar,
|
||||
uploadApi: uploadApi as any,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cropper-container {
|
||||
width: 40vw;
|
||||
}
|
||||
|
||||
.croppered {
|
||||
height: 360px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,79 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="详情组件示例">
|
||||
<Description title="基础示例" :collapseOptions="{ canExpand: true, helpMessage: 'help me' }" :column="3" :data="mockData" :schema="schema" />
|
||||
|
||||
<Description
|
||||
class="mt-4"
|
||||
title="垂直示例"
|
||||
layout="vertical"
|
||||
:collapseOptions="{ canExpand: true, helpMessage: 'help me' }"
|
||||
:column="2"
|
||||
:data="mockData"
|
||||
:schema="schema"
|
||||
/>
|
||||
|
||||
<Description @register="register" class="mt-4" />
|
||||
<Description @register="register1" class="mt-4" />
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { Description, DescItem, useDescription } from '/@/components/Description/index';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
const mockData: Recordable = {
|
||||
username: 'test',
|
||||
nickName: 'VB',
|
||||
age: '123',
|
||||
phone: '15695909xxx',
|
||||
email: '190848757@qq.com',
|
||||
addr: '厦门市思明区',
|
||||
sex: '男',
|
||||
certy: '3504256199xxxxxxxxx',
|
||||
tag: 'orange',
|
||||
};
|
||||
const schema: DescItem[] = [
|
||||
{
|
||||
field: 'username',
|
||||
label: '用户名',
|
||||
},
|
||||
{
|
||||
field: 'nickName',
|
||||
label: '昵称',
|
||||
render: (curVal, data) => {
|
||||
return `${data.username}-${curVal}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'phone',
|
||||
label: '联系电话',
|
||||
},
|
||||
{
|
||||
field: 'email',
|
||||
label: '邮箱',
|
||||
},
|
||||
{
|
||||
field: 'addr',
|
||||
label: '地址',
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { Description, PageWrapper },
|
||||
setup() {
|
||||
const [register] = useDescription({
|
||||
title: 'useDescription',
|
||||
data: mockData,
|
||||
schema: schema,
|
||||
});
|
||||
|
||||
const [register1] = useDescription({
|
||||
title: '无边框',
|
||||
bordered: false,
|
||||
data: mockData,
|
||||
schema: schema,
|
||||
});
|
||||
|
||||
return { mockData, schema, register, register1 };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<BasicDrawer v-bind="$attrs" title="Drawer Title" width="50%"> Drawer Info. </BasicDrawer>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicDrawer } from '/@/components/Drawer';
|
||||
export default defineComponent({
|
||||
components: { BasicDrawer },
|
||||
setup() {
|
||||
return {};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,17 +0,0 @@
|
||||
<template>
|
||||
<BasicDrawer v-bind="$attrs" @register="register" title="Drawer Title" width="50%">
|
||||
Drawer Info.
|
||||
<a-button type="primary" @click="closeDrawer"> 内部关闭drawer </a-button>
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
|
||||
export default defineComponent({
|
||||
components: { BasicDrawer },
|
||||
setup() {
|
||||
const [register, { closeDrawer }] = useDrawerInner();
|
||||
return { register, closeDrawer };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,35 +0,0 @@
|
||||
<template>
|
||||
<BasicDrawer v-bind="$attrs" title="Modal Title" width="50%" showFooter @ok="handleOk">
|
||||
<p class="h-20" v-for="index in 40" :key="index"> 根据屏幕高度自适应 </p>
|
||||
<template #insertFooter>
|
||||
<a-button> btn</a-button>
|
||||
</template>
|
||||
<template #centerFooter>
|
||||
<a-button> btn2</a-button>
|
||||
</template>
|
||||
|
||||
<template #appendFooter>
|
||||
<a-button> btn3</a-button>
|
||||
</template>
|
||||
|
||||
<!-- <template #footer>
|
||||
<a-button> customerFooter</a-button>
|
||||
</template> -->
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicDrawer } from '/@/components/Drawer';
|
||||
export default defineComponent({
|
||||
components: { BasicDrawer },
|
||||
setup() {
|
||||
return {
|
||||
handleOk: () => {
|
||||
console.log('=====================');
|
||||
console.log('ok');
|
||||
console.log('======================');
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,53 +0,0 @@
|
||||
<template>
|
||||
<BasicDrawer v-bind="$attrs" @register="register" title="Drawer Title" width="50%">
|
||||
<div>
|
||||
<BasicForm @register="registerForm" />
|
||||
</div>
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
|
||||
|
||||
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
|
||||
const schemas: FormSchema[] = [
|
||||
{
|
||||
field: 'field1',
|
||||
component: 'Input',
|
||||
label: '字段1',
|
||||
colProps: {
|
||||
span: 12,
|
||||
},
|
||||
defaultValue: '111',
|
||||
},
|
||||
{
|
||||
field: 'field2',
|
||||
component: 'Input',
|
||||
label: '字段2',
|
||||
colProps: {
|
||||
span: 12,
|
||||
},
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicDrawer, BasicForm },
|
||||
setup() {
|
||||
const [registerForm, { setFieldsValue }] = useForm({
|
||||
labelWidth: 120,
|
||||
schemas,
|
||||
showActionButtonGroup: false,
|
||||
actionColOptions: {
|
||||
span: 24,
|
||||
},
|
||||
});
|
||||
const [register] = useDrawerInner((data) => {
|
||||
// 方式1
|
||||
setFieldsValue({
|
||||
field2: data.data,
|
||||
field1: data.info,
|
||||
});
|
||||
});
|
||||
return { register, schemas, registerForm };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<BasicDrawer v-bind="$attrs" :isDetail="true" title="Drawer Title5">
|
||||
<p class="h-20"> Content Message </p>
|
||||
<template #titleToolbar> toolbar </template>
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicDrawer } from '/@/components/Drawer';
|
||||
export default defineComponent({
|
||||
components: { BasicDrawer },
|
||||
});
|
||||
</script>
|
||||
@ -1,69 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="抽屉组件使用示例">
|
||||
<Alert message="使用 useDrawer 进行抽屉操作" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="openDrawerLoading"> 打开Drawer </a-button>
|
||||
|
||||
<Alert message="内外同时控制显示隐藏" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="openDrawer2(true)"> 打开Drawer </a-button>
|
||||
<Alert message="自适应高度/显示footer" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="openDrawer3(true)"> 打开Drawer </a-button>
|
||||
|
||||
<Alert message="内外数据交互" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="send"> 打开Drawer并传递数据 </a-button>
|
||||
<Alert message="详情页模式" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="openDrawer5(true)"> 打开详情Drawer </a-button>
|
||||
<Drawer1 @register="register1" />
|
||||
<Drawer2 @register="register2" />
|
||||
<Drawer3 @register="register3" />
|
||||
<Drawer4 @register="register4" />
|
||||
<Drawer5 @register="register5" />
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { Alert } from 'ant-design-vue';
|
||||
import { useDrawer } from '/@/components/Drawer';
|
||||
import Drawer1 from './Drawer1.vue';
|
||||
import Drawer2 from './Drawer2.vue';
|
||||
import Drawer3 from './Drawer3.vue';
|
||||
import Drawer4 from './Drawer4.vue';
|
||||
import Drawer5 from './Drawer5.vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
export default defineComponent({
|
||||
components: { Alert, PageWrapper, Drawer1, Drawer2, Drawer3, Drawer4, Drawer5 },
|
||||
setup() {
|
||||
const [register1, { openDrawer: openDrawer1, setDrawerProps }] = useDrawer();
|
||||
const [register2, { openDrawer: openDrawer2 }] = useDrawer();
|
||||
const [register3, { openDrawer: openDrawer3 }] = useDrawer();
|
||||
const [register4, { openDrawer: openDrawer4 }] = useDrawer();
|
||||
const [register5, { openDrawer: openDrawer5 }] = useDrawer();
|
||||
function send() {
|
||||
openDrawer4(true, {
|
||||
data: 'content',
|
||||
info: 'Info',
|
||||
});
|
||||
}
|
||||
function openDrawerLoading() {
|
||||
openDrawer1();
|
||||
setDrawerProps({ loading: true });
|
||||
setTimeout(() => {
|
||||
setDrawerProps({ loading: false });
|
||||
}, 2000);
|
||||
}
|
||||
return {
|
||||
register1,
|
||||
openDrawer1,
|
||||
register2,
|
||||
openDrawer2,
|
||||
register3,
|
||||
openDrawer3,
|
||||
register4,
|
||||
register5,
|
||||
openDrawer5,
|
||||
send,
|
||||
openDrawerLoading,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<Card hoverable :style="{ width: '240px', background: '#fff' }">
|
||||
<template #cover>
|
||||
<img alt="example" src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png" />
|
||||
</template>
|
||||
<CardMeta title="懒加载组件" />
|
||||
</Card>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { Card } from 'ant-design-vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { CardMeta: Card.Meta, Card },
|
||||
setup() {
|
||||
return {};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,77 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="懒加载自定义动画示例" content="懒加载组件显示动画">
|
||||
<div class="lazy-base-demo-wrap">
|
||||
<h1>向下滚动</h1>
|
||||
|
||||
<div class="lazy-base-demo-box">
|
||||
<LazyContainer transitionName="custom">
|
||||
<TargetContent />
|
||||
</LazyContainer>
|
||||
</div>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import TargetContent from './TargetContent.vue';
|
||||
import { LazyContainer } from '/@/components/Container/index';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
export default defineComponent({
|
||||
components: { LazyContainer, TargetContent, PageWrapper },
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
.lazy-base-demo {
|
||||
&-wrap {
|
||||
display: flex;
|
||||
width: 50%;
|
||||
height: 2000px;
|
||||
margin: 20px auto;
|
||||
text-align: center;
|
||||
background-color: @component-background;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-box {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
height: 1300px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-enter {
|
||||
opacity: 0;
|
||||
transform: scale(0.4) translate(100%);
|
||||
}
|
||||
|
||||
.custom-enter-to {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.custom-enter-active {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
|
||||
.custom-leave {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.custom-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.4) translate(-100%);
|
||||
}
|
||||
|
||||
.custom-leave-active {
|
||||
transition: all 0.5s;
|
||||
}
|
||||
</style>
|
||||
@ -1,52 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="懒加载基础示例" content="向下滚动到可见区域才会加载组件">
|
||||
<div class="lazy-base-demo-wrap">
|
||||
<h1>向下滚动</h1>
|
||||
|
||||
<div class="lazy-base-demo-box">
|
||||
<LazyContainer>
|
||||
<TargetContent />
|
||||
<template #skeleton>
|
||||
<Skeleton :rows="10" />
|
||||
</template>
|
||||
</LazyContainer>
|
||||
</div>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { Skeleton } from 'ant-design-vue';
|
||||
import TargetContent from './TargetContent.vue';
|
||||
import { LazyContainer } from '/@/components/Container/index';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
export default defineComponent({
|
||||
components: { LazyContainer, PageWrapper, TargetContent, Skeleton },
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
.lazy-base-demo {
|
||||
&-wrap {
|
||||
display: flex;
|
||||
width: 50%;
|
||||
height: 2000px;
|
||||
margin: 20px auto;
|
||||
text-align: center;
|
||||
background-color: @component-background;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-box {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
height: 1300px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,101 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper v-loading="loadingRef" loading-tip="加载中..." title="Loading组件示例">
|
||||
<div ref="wrapEl">
|
||||
<a-alert message="组件方式" />
|
||||
<a-button class="my-4 mr-4" type="primary" @click="openCompFullLoading"> 全屏 Loading </a-button>
|
||||
<a-button class="my-4" type="primary" @click="openCompAbsolute"> 容器内 Loading </a-button>
|
||||
<Loading :loading="loading" :absolute="absolute" :theme="theme" :background="background" :tip="tip" />
|
||||
|
||||
<a-alert message="函数方式" />
|
||||
|
||||
<a-button class="my-4 mr-4" type="primary" @click="openFnFullLoading"> 全屏 Loading </a-button>
|
||||
<a-button class="my-4" type="primary" @click="openFnWrapLoading"> 容器内 Loading </a-button>
|
||||
|
||||
<a-alert message="指令方式" />
|
||||
<a-button class="my-4 mr-4" type="primary" @click="openDirectiveLoading"> 打开指令Loading </a-button>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, toRefs, ref } from 'vue';
|
||||
import { Loading, useLoading } from '/@/components/Loading';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { Alert } from 'ant-design-vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { Loading, PageWrapper, [Alert.name]: Alert },
|
||||
setup() {
|
||||
const wrapEl = ref<ElRef>(null);
|
||||
|
||||
const loadingRef = ref(false);
|
||||
const compState = reactive({
|
||||
absolute: false,
|
||||
loading: false,
|
||||
theme: 'dark',
|
||||
background: 'rgba(111,111,111,.7)',
|
||||
tip: '加载中...',
|
||||
});
|
||||
const [openFullLoading, closeFullLoading] = useLoading({
|
||||
tip: '加载中...',
|
||||
});
|
||||
|
||||
const [openWrapLoading, closeWrapLoading] = useLoading({
|
||||
target: wrapEl,
|
||||
props: {
|
||||
tip: '加载中...',
|
||||
absolute: true,
|
||||
},
|
||||
});
|
||||
|
||||
function openLoading(absolute: boolean) {
|
||||
compState.absolute = absolute;
|
||||
compState.loading = true;
|
||||
setTimeout(() => {
|
||||
compState.loading = false;
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function openCompFullLoading() {
|
||||
openLoading(false);
|
||||
}
|
||||
|
||||
function openCompAbsolute() {
|
||||
openLoading(true);
|
||||
}
|
||||
|
||||
function openFnFullLoading() {
|
||||
openFullLoading();
|
||||
|
||||
setTimeout(() => {
|
||||
closeFullLoading();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function openFnWrapLoading() {
|
||||
openWrapLoading();
|
||||
|
||||
setTimeout(() => {
|
||||
closeWrapLoading();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function openDirectiveLoading() {
|
||||
loadingRef.value = true;
|
||||
setTimeout(() => {
|
||||
loadingRef.value = false;
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
return {
|
||||
openCompFullLoading,
|
||||
openFnFullLoading,
|
||||
openFnWrapLoading,
|
||||
openCompAbsolute,
|
||||
wrapEl,
|
||||
loadingRef,
|
||||
openDirectiveLoading,
|
||||
...toRefs(compState),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,58 +0,0 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" destroyOnClose @register="register" title="Modal Title" :helpMessage="['提示1', '提示2']" @visible-change="handleShow">
|
||||
<template #insertFooter>
|
||||
<a-button type="primary" danger @click="setLines" :disabled="loading">点我更新内容</a-button>
|
||||
</template>
|
||||
<template v-if="loading">
|
||||
<div class="empty-tips"> 加载中,稍等3秒…… </div>
|
||||
</template>
|
||||
<template v-if="!loading">
|
||||
<ul>
|
||||
<li v-for="index in lines" :key="index">加载完成{{ index }}!</li>
|
||||
</ul>
|
||||
</template>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, watch } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
export default defineComponent({
|
||||
components: { BasicModal },
|
||||
setup() {
|
||||
const loading = ref(true);
|
||||
const lines = ref(10);
|
||||
const [register, { setModalProps, redoModalHeight }] = useModalInner();
|
||||
|
||||
watch(
|
||||
() => lines.value,
|
||||
() => {
|
||||
redoModalHeight();
|
||||
}
|
||||
);
|
||||
|
||||
function handleShow(visible: boolean) {
|
||||
if (visible) {
|
||||
loading.value = true;
|
||||
setModalProps({ loading: true, confirmLoading: true });
|
||||
setTimeout(() => {
|
||||
lines.value = Math.round(Math.random() * 30 + 5);
|
||||
loading.value = false;
|
||||
setModalProps({ loading: false, confirmLoading: false });
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
function setLines() {
|
||||
lines.value = Math.round(Math.random() * 20 + 10);
|
||||
}
|
||||
return { register, loading, handleShow, lines, setLines };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.empty-tips {
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@ -1,23 +0,0 @@
|
||||
<template>
|
||||
<BasicModal @register="register" title="Modal Title" :helpMessage="['提示1', '提示2']" :okButtonProps="{ disabled: true }">
|
||||
<a-button type="primary" @click="closeModal" class="mr-2"> 从内部关闭弹窗 </a-button>
|
||||
<a-button type="primary" @click="setModalProps"> 从内部修改title </a-button>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
export default defineComponent({
|
||||
components: { BasicModal },
|
||||
setup() {
|
||||
const [register, { closeModal, setModalProps }] = useModalInner();
|
||||
return {
|
||||
register,
|
||||
closeModal,
|
||||
setModalProps: () => {
|
||||
setModalProps({ title: 'Modal New Title' });
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,15 +0,0 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" title="Modal Title" :helpMessage="['提示1', '提示2']" width="700px">
|
||||
<p class="h-20" v-for="index in 20" :key="index"> 根据屏幕高度自适应 </p>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicModal } from '/@/components/Modal';
|
||||
export default defineComponent({
|
||||
components: { BasicModal },
|
||||
setup() {
|
||||
return {};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,81 +0,0 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="register" title="Modal Title" @visible-change="handleVisibleChange">
|
||||
<div class="pt-3px pr-3px">
|
||||
<BasicForm @register="registerForm" :model="model" />
|
||||
</div>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, nextTick } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
|
||||
|
||||
const schemas: FormSchema[] = [
|
||||
{
|
||||
field: 'field1',
|
||||
component: 'Input',
|
||||
label: '字段1',
|
||||
colProps: {
|
||||
span: 24,
|
||||
},
|
||||
defaultValue: '111',
|
||||
},
|
||||
{
|
||||
field: 'field2',
|
||||
component: 'Input',
|
||||
label: '字段2',
|
||||
colProps: {
|
||||
span: 24,
|
||||
},
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicModal, BasicForm },
|
||||
props: {
|
||||
userData: { type: Object },
|
||||
},
|
||||
setup(props) {
|
||||
const modelRef = ref({});
|
||||
const [
|
||||
registerForm,
|
||||
{
|
||||
// setFieldsValue,
|
||||
// setProps
|
||||
},
|
||||
] = useForm({
|
||||
labelWidth: 120,
|
||||
schemas,
|
||||
showActionButtonGroup: false,
|
||||
actionColOptions: {
|
||||
span: 24,
|
||||
},
|
||||
});
|
||||
|
||||
const [register] = useModalInner((data) => {
|
||||
data && onDataReceive(data);
|
||||
});
|
||||
|
||||
function onDataReceive(data) {
|
||||
console.log('Data Received', data);
|
||||
// 方式1;
|
||||
// setFieldsValue({
|
||||
// field2: data.data,
|
||||
// field1: data.info,
|
||||
// });
|
||||
|
||||
// // 方式2
|
||||
modelRef.value = { field2: data.data, field1: data.info };
|
||||
|
||||
// setProps({
|
||||
// model:{ field2: data.data, field1: data.info }
|
||||
// })
|
||||
}
|
||||
|
||||
function handleVisibleChange(v) {
|
||||
v && props.userData && nextTick(() => onDataReceive(props.userData));
|
||||
}
|
||||
|
||||
return { register, schemas, registerForm, model: modelRef, handleVisibleChange };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,112 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="modal组件使用示例">
|
||||
<Alert
|
||||
message="使用 useModal 进行弹窗操作,默认可以拖动,可以通过 draggable
|
||||
参数进行控制是否可以拖动/全屏,并演示了在Modal内动态加载内容并自动调整高度"
|
||||
show-icon
|
||||
/>
|
||||
<a-button type="primary" class="my-4" @click="openModalLoading"> 打开弹窗,加载动态数据并自动调整高度(默认可以拖动/全屏) </a-button>
|
||||
|
||||
<Alert message="内外同时同时显示隐藏" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="openModal2"> 打开弹窗</a-button>
|
||||
<Alert message="自适应高度" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="openModal3"> 打开弹窗</a-button>
|
||||
|
||||
<Alert message="内外数据交互" show-icon />
|
||||
<a-button type="primary" class="my-4" @click="send"> 打开弹窗并传递数据</a-button>
|
||||
|
||||
<Alert message="使用动态组件的方式在页面内使用多个弹窗" show-icon />
|
||||
<a-space>
|
||||
<a-button type="primary" class="my-4" @click="openTargetModal(1)"> 打开弹窗1</a-button>
|
||||
<a-button type="primary" class="my-4" @click="openTargetModal(2)"> 打开弹窗2</a-button>
|
||||
<a-button type="primary" class="my-4" @click="openTargetModal(3)"> 打开弹窗3</a-button>
|
||||
<a-button type="primary" class="my-4" @click="openTargetModal(4)"> 打开弹窗4</a-button>
|
||||
</a-space>
|
||||
|
||||
<component :is="currentModal" v-model:visible="modalVisible" :userData="userData" />
|
||||
|
||||
<Modal1 @register="register1" :minHeight="100" />
|
||||
<Modal2 @register="register2" />
|
||||
<Modal3 @register="register3" />
|
||||
<Modal4 @register="register4" />
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, shallowRef, ComponentOptions, ref, nextTick } from 'vue';
|
||||
import { Alert, Space } from 'ant-design-vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import Modal1 from './Modal1.vue';
|
||||
import Modal2 from './Modal2.vue';
|
||||
import Modal3 from './Modal3.vue';
|
||||
import Modal4 from './Modal4.vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
export default defineComponent({
|
||||
components: { Alert, Modal1, Modal2, Modal3, Modal4, PageWrapper, ASpace: Space },
|
||||
setup() {
|
||||
const currentModal = shallowRef<Nullable<ComponentOptions>>(null);
|
||||
const [register1, { openModal: openModal1 }] = useModal();
|
||||
const [register2, { openModal: openModal2 }] = useModal();
|
||||
const [register3, { openModal: openModal3 }] = useModal();
|
||||
const [register4, { openModal: openModal4 }] = useModal();
|
||||
const modalVisible = ref<Boolean>(false);
|
||||
const userData = ref<any>(null);
|
||||
|
||||
function send() {
|
||||
openModal4(true, {
|
||||
data: 'content',
|
||||
info: 'Info',
|
||||
});
|
||||
}
|
||||
|
||||
function openModalLoading() {
|
||||
openModal1(true);
|
||||
// setModalProps({ loading: true });
|
||||
// setTimeout(() => {
|
||||
// setModalProps({ loading: false });
|
||||
// }, 2000);
|
||||
}
|
||||
|
||||
function openTargetModal(index) {
|
||||
switch (index) {
|
||||
case 1:
|
||||
currentModal.value = Modal1;
|
||||
break;
|
||||
case 2:
|
||||
currentModal.value = Modal2;
|
||||
break;
|
||||
case 3:
|
||||
currentModal.value = Modal3;
|
||||
break;
|
||||
default:
|
||||
currentModal.value = Modal4;
|
||||
break;
|
||||
}
|
||||
nextTick(() => {
|
||||
// `useModal` not working with dynamic component
|
||||
// passing data through `userData` prop
|
||||
userData.value = { data: Math.random(), info: 'Info222' };
|
||||
// open the target modal
|
||||
modalVisible.value = true;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
register1,
|
||||
openModal1,
|
||||
register2,
|
||||
openModal2,
|
||||
register3,
|
||||
openModal3,
|
||||
register4,
|
||||
openModal4,
|
||||
modalVisible,
|
||||
userData,
|
||||
openTargetModal,
|
||||
send,
|
||||
currentModal,
|
||||
openModalLoading,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,117 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="二维码组件使用示例">
|
||||
<div class="flex flex-wrap">
|
||||
<CollapseContainer title="基础示例" :canExpan="true" class="text-center mb-6 qrcode-demo-item">
|
||||
<QrCode :value="qrCodeUrl" />
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="渲染成img标签示例" class="text-center mb-6 qrcode-demo-item">
|
||||
<QrCode :value="qrCodeUrl" tag="img" />
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="配置样式示例" class="text-center mb-6 qrcode-demo-item">
|
||||
<QrCode
|
||||
:value="qrCodeUrl"
|
||||
:options="{
|
||||
color: { dark: '#55D187' },
|
||||
}"
|
||||
/>
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="本地logo示例" class="text-center mb-6 qrcode-demo-item">
|
||||
<QrCode :value="qrCodeUrl" :logo="LogoImg" />
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="在线logo示例" class="text-center mb-6 qrcode-demo-item">
|
||||
<QrCode
|
||||
:value="qrCodeUrl"
|
||||
logo="http://jeecg.com/images/logo.png"
|
||||
:options="{
|
||||
color: { dark: '#55D187' },
|
||||
}"
|
||||
/>
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="logo配置示例" class="text-center mb-6 qrcode-demo-item">
|
||||
<QrCode
|
||||
:value="qrCodeUrl"
|
||||
:logo="{
|
||||
src: 'http://jeecg.com/images/logo.png',
|
||||
logoSize: 0.2,
|
||||
borderSize: 0.05,
|
||||
borderRadius: 50,
|
||||
bgColor: 'blue',
|
||||
}"
|
||||
/>
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="下载示例" class="text-center qrcode-demo-item">
|
||||
<QrCode :value="qrCodeUrl" ref="qrRef" :logo="LogoImg" />
|
||||
<a-button class="mb-2" type="primary" @click="download"> 下载 </a-button>
|
||||
<div class="msg"> (在线logo会导致图片跨域,需要下载图片需要自行解决跨域问题) </div>
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="配置大小示例" class="text-center qrcode-demo-item">
|
||||
<QrCode :value="qrCodeUrl" :width="300" />
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="扩展绘制示例" class="text-center qrcode-demo-item">
|
||||
<QrCode :value="qrCodeUrl" :width="200" :options="{ margin: 5 }" ref="qrDiyRef" :logo="LogoImg" @done="onQrcodeDone" />
|
||||
<a-button class="mb-2" type="primary" @click="downloadDiy"> 下载 </a-button>
|
||||
<div class="msg"> 要进行扩展绘制则不能将tag设为img </div>
|
||||
</CollapseContainer>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, unref } from 'vue';
|
||||
import { QrCode, QrCodeActionType } from '/@/components/Qrcode/index';
|
||||
import LogoImg from '/@/assets/images/logo.png';
|
||||
import { CollapseContainer } from '/@/components/Container/index';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
const qrCodeUrl = 'https://www.vvbin.cn';
|
||||
export default defineComponent({
|
||||
components: { CollapseContainer, QrCode, PageWrapper },
|
||||
setup() {
|
||||
const qrRef = ref<Nullable<QrCodeActionType>>(null);
|
||||
const qrDiyRef = ref<Nullable<QrCodeActionType>>(null);
|
||||
function download() {
|
||||
const qrEl = unref(qrRef);
|
||||
if (!qrEl) return;
|
||||
qrEl.download('文件名');
|
||||
}
|
||||
function downloadDiy() {
|
||||
const qrEl = unref(qrDiyRef);
|
||||
if (!qrEl) return;
|
||||
qrEl.download('Qrcode');
|
||||
}
|
||||
|
||||
function onQrcodeDone({ ctx }: any) {
|
||||
if (ctx instanceof CanvasRenderingContext2D) {
|
||||
// 额外绘制
|
||||
ctx.fillStyle = 'black';
|
||||
ctx.font = '16px "微软雅黑"';
|
||||
ctx.textBaseline = 'bottom';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText('你帅你先扫', 100, 195, 200);
|
||||
}
|
||||
}
|
||||
return {
|
||||
onQrcodeDone,
|
||||
qrCodeUrl,
|
||||
LogoImg,
|
||||
download,
|
||||
downloadDiy,
|
||||
qrRef,
|
||||
qrDiyRef,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.qrcode-demo-item {
|
||||
width: 30%;
|
||||
margin-right: 1%;
|
||||
}
|
||||
</style>
|
||||
@ -1,59 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="滚动组件函数示例" content="基于el-scrollbar">
|
||||
<div class="my-4">
|
||||
<a-button @click="scrollTo(100)" class="mr-2"> 滚动到100px位置 </a-button>
|
||||
<a-button @click="scrollTo(800)" class="mr-2"> 滚动到800px位置 </a-button>
|
||||
<a-button @click="scrollTo(0)" class="mr-2"> 滚动到顶部 </a-button>
|
||||
<a-button @click="scrollBottom()" class="mr-2"> 滚动到底部 </a-button>
|
||||
</div>
|
||||
<div class="scroll-wrap">
|
||||
<ScrollContainer class="mt-4" ref="scrollRef">
|
||||
<ul class="p-3">
|
||||
<template v-for="index in 100" :key="index">
|
||||
<li class="p-2" :style="{ border: '1px solid #eee' }">
|
||||
{{ index }}
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</ScrollContainer>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, unref } from 'vue';
|
||||
import { ScrollContainer, ScrollActionType } from '/@/components/Container/index';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
export default defineComponent({
|
||||
components: { ScrollContainer, PageWrapper },
|
||||
setup() {
|
||||
const scrollRef = ref<Nullable<ScrollActionType>>(null);
|
||||
const getScroll = () => {
|
||||
const scroll = unref(scrollRef);
|
||||
if (!scroll) {
|
||||
throw new Error('scroll is Null');
|
||||
}
|
||||
return scroll;
|
||||
};
|
||||
|
||||
function scrollTo(top: number) {
|
||||
getScroll().scrollTo(top);
|
||||
}
|
||||
function scrollBottom() {
|
||||
getScroll().scrollBottom();
|
||||
}
|
||||
return {
|
||||
scrollTo,
|
||||
scrollRef,
|
||||
scrollBottom,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.scroll-wrap {
|
||||
width: 50%;
|
||||
height: 300px;
|
||||
background-color: @component-background;
|
||||
}
|
||||
</style>
|
||||
@ -1,64 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper class="virtual-scroll-demo">
|
||||
<Divider>基础滚动示例</Divider>
|
||||
<div class="virtual-scroll-demo-wrap">
|
||||
<VScroll :itemHeight="41" :items="data" :height="300" :width="300">
|
||||
<template #default="{ item }">
|
||||
<div class="virtual-scroll-demo__item">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</template>
|
||||
</VScroll>
|
||||
</div>
|
||||
|
||||
<Divider>即使不可见,也预先加载50条数据,防止空白</Divider>
|
||||
<div class="virtual-scroll-demo-wrap">
|
||||
<VScroll :itemHeight="41" :items="data" :height="300" :width="300" :bench="50">
|
||||
<template #default="{ item }">
|
||||
<div class="virtual-scroll-demo__item">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</template>
|
||||
</VScroll>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { VScroll } from '/@/components/VirtualScroll/index';
|
||||
|
||||
import { Divider } from 'ant-design-vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
const data: Recordable[] = (() => {
|
||||
const arr: Recordable[] = [];
|
||||
for (let index = 1; index < 20000; index++) {
|
||||
arr.push({
|
||||
title: '列表项' + index,
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
})();
|
||||
export default defineComponent({
|
||||
components: { VScroll: VScroll, Divider, PageWrapper },
|
||||
setup() {
|
||||
return { data: data };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.virtual-scroll-demo {
|
||||
&-wrap {
|
||||
display: flex;
|
||||
margin: 0 30%;
|
||||
background-color: @component-background;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&__item {
|
||||
height: 40px;
|
||||
padding: 0 20px;
|
||||
line-height: 40px;
|
||||
border-bottom: 1px solid @border-color-base;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,31 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="滚动组件示例" content="基于el-scrollbar">
|
||||
<div class="scroll-wrap">
|
||||
<ScrollContainer class="mt-4">
|
||||
<ul class="p-3">
|
||||
<template v-for="index in 100" :key="index">
|
||||
<li class="p-2" :style="{ border: '1px solid #eee' }">
|
||||
{{ index }}
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</ScrollContainer>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { ScrollContainer } from '/@/components/Container/index';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
export default defineComponent({
|
||||
components: { ScrollContainer, PageWrapper },
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.scroll-wrap {
|
||||
width: 50%;
|
||||
height: 300px;
|
||||
background-color: @component-background;
|
||||
}
|
||||
</style>
|
||||
@ -1,32 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="密码强度校验组件">
|
||||
<div class="flex justify-center">
|
||||
<div class="demo-wrap p-10">
|
||||
<StrengthMeter placeholder="默认" />
|
||||
<StrengthMeter placeholder="禁用" disabled />
|
||||
<br />
|
||||
<StrengthMeter placeholder="隐藏input" :show-input="false" value="!@#qwe12345" />
|
||||
</div>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { StrengthMeter } from '/@/components/StrengthMeter';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
StrengthMeter,
|
||||
PageWrapper,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.demo-wrap {
|
||||
width: 50%;
|
||||
background-color: @component-background;
|
||||
border-radius: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,44 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="时间组件示例">
|
||||
<CollapseContainer title="基础示例">
|
||||
<Time :value="time1" />
|
||||
<br />
|
||||
<Time :value="time2" />
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="定时更新" class="my-4">
|
||||
<Time :value="now" :step="1" />
|
||||
<br />
|
||||
<Time :value="now" :step="5" />
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="定时更新">
|
||||
<Time :value="now" mode="date" />
|
||||
<br />
|
||||
<Time :value="now" mode="datetime" />
|
||||
<br />
|
||||
<Time :value="now" />
|
||||
</CollapseContainer>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, toRefs } from 'vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { Time } from '/@/components/Time';
|
||||
import { CollapseContainer } from '/@/components/Container/index';
|
||||
|
||||
export default defineComponent({
|
||||
components: { PageWrapper, Time, CollapseContainer },
|
||||
setup() {
|
||||
const now = new Date().getTime();
|
||||
const state = reactive({
|
||||
time1: now - 60 * 3 * 1000,
|
||||
time2: now - 86400 * 3 * 1000,
|
||||
});
|
||||
return {
|
||||
...toRefs(state),
|
||||
now,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,91 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="动画组件示例">
|
||||
<div class="flex">
|
||||
<Select :options="options" v-model:value="value" placeholder="选择动画" :style="{ width: '150px' }" />
|
||||
<a-button type="primary" class="ml-4" @click="start"> start </a-button>
|
||||
</div>
|
||||
<component :is="`${value}Transition`">
|
||||
<div class="box" v-show="show"></div>
|
||||
</component>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { Select } from 'ant-design-vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import {
|
||||
FadeTransition,
|
||||
ScaleTransition,
|
||||
SlideYTransition,
|
||||
ScrollYTransition,
|
||||
SlideYReverseTransition,
|
||||
ScrollYReverseTransition,
|
||||
SlideXTransition,
|
||||
ScrollXTransition,
|
||||
SlideXReverseTransition,
|
||||
ScrollXReverseTransition,
|
||||
ScaleRotateTransition,
|
||||
ExpandXTransition,
|
||||
ExpandTransition,
|
||||
} from '/@/components/Transition';
|
||||
|
||||
const transitionList = [
|
||||
'Fade',
|
||||
'Scale',
|
||||
'SlideY',
|
||||
'ScrollY',
|
||||
'SlideYReverse',
|
||||
'ScrollYReverse',
|
||||
'SlideX',
|
||||
'ScrollX',
|
||||
'SlideXReverse',
|
||||
'ScrollXReverse',
|
||||
'ScaleRotate',
|
||||
'ExpandX',
|
||||
'Expand',
|
||||
];
|
||||
const options = transitionList.map((item) => ({
|
||||
label: item,
|
||||
value: item,
|
||||
key: item,
|
||||
}));
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Select,
|
||||
PageWrapper,
|
||||
FadeTransition,
|
||||
ScaleTransition,
|
||||
SlideYTransition,
|
||||
ScrollYTransition,
|
||||
SlideYReverseTransition,
|
||||
ScrollYReverseTransition,
|
||||
SlideXTransition,
|
||||
ScrollXTransition,
|
||||
SlideXReverseTransition,
|
||||
ScrollXReverseTransition,
|
||||
ScaleRotateTransition,
|
||||
ExpandXTransition,
|
||||
ExpandTransition,
|
||||
},
|
||||
setup() {
|
||||
const value = ref('Fade');
|
||||
const show = ref(true);
|
||||
function start() {
|
||||
show.value = false;
|
||||
setTimeout(() => {
|
||||
show.value = true;
|
||||
}, 300);
|
||||
}
|
||||
return { options, value, start, show };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.box {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin-top: 20px;
|
||||
background-color: rgb(126, 170, 236);
|
||||
}
|
||||
</style>
|
||||
@ -1,54 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="上传组件示例">
|
||||
<a-alert message="基础示例" />
|
||||
<BasicUpload :maxSize="20" :maxNumber="10" @change="handleChange" :api="uploadApi" class="my-5" :accept="['image/*']" />
|
||||
|
||||
<a-alert message="嵌入表单,加入表单校验" />
|
||||
|
||||
<BasicForm @register="register" class="my-5" />
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicUpload } from '/@/components/Upload';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { Alert } from 'ant-design-vue';
|
||||
import { uploadApi } from '/@/api/sys/upload';
|
||||
|
||||
const schemas: FormSchema[] = [
|
||||
{
|
||||
field: 'field1',
|
||||
component: 'Upload',
|
||||
label: '字段1',
|
||||
colProps: {
|
||||
span: 8,
|
||||
},
|
||||
rules: [{ required: true, message: '请选择上传文件' }],
|
||||
componentProps: {
|
||||
api: uploadApi,
|
||||
},
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicUpload, BasicForm, PageWrapper, [Alert.name]: Alert },
|
||||
setup() {
|
||||
const { createMessage } = useMessage();
|
||||
const [register] = useForm({
|
||||
labelWidth: 120,
|
||||
schemas,
|
||||
actionColOptions: {
|
||||
span: 16,
|
||||
},
|
||||
});
|
||||
return {
|
||||
handleChange: (list: string[]) => {
|
||||
createMessage.info(`已上传文件${JSON.stringify(list)}`);
|
||||
},
|
||||
uploadApi,
|
||||
register,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,33 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="旋转校验示例">
|
||||
<div class="flex justify-center p-4 items-center bg-gray-700">
|
||||
<RotateDragVerify :src="img" ref="el" @success="handleSuccess" />
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { RotateDragVerify } from '/@/components/Verify/index';
|
||||
|
||||
import img from '/@/assets/images/header.jpg';
|
||||
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
export default defineComponent({
|
||||
components: { RotateDragVerify, PageWrapper },
|
||||
setup() {
|
||||
const handleSuccess = () => {
|
||||
console.log('success!');
|
||||
};
|
||||
return {
|
||||
handleSuccess,
|
||||
img,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.bg-gray-700 {
|
||||
background-color: #4a5568;
|
||||
}
|
||||
</style>
|
||||
@ -1,97 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="拖动校验示例">
|
||||
<div class="flex justify-center p-4 items-center bg-gray-700">
|
||||
<BasicDragVerify ref="el1" @success="handleSuccess" />
|
||||
<a-button type="primary" class="ml-2" @click="handleBtnClick(el1)"> 还原 </a-button>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center p-4 items-center bg-gray-700">
|
||||
<BasicDragVerify ref="el2" @success="handleSuccess" circle />
|
||||
<a-button type="primary" class="ml-2" @click="handleBtnClick(el2)"> 还原 </a-button>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center p-4 items-center bg-gray-700">
|
||||
<BasicDragVerify
|
||||
ref="el3"
|
||||
@success="handleSuccess"
|
||||
text="拖动以进行校验"
|
||||
successText="校验成功"
|
||||
:barStyle="{
|
||||
backgroundColor: '#018ffb',
|
||||
}"
|
||||
/>
|
||||
<a-button type="primary" class="ml-2" @click="handleBtnClick(el3)"> 还原 </a-button>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center p-4 items-center bg-gray-700">
|
||||
<BasicDragVerify ref="el4" @success="handleSuccess">
|
||||
<template #actionIcon="isPassing">
|
||||
<BugOutlined v-if="isPassing" />
|
||||
<RightOutlined v-else />
|
||||
</template>
|
||||
</BasicDragVerify>
|
||||
<a-button type="primary" class="ml-2" @click="handleBtnClick(el4)"> 还原 </a-button>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center p-4 items-center bg-gray-700">
|
||||
<BasicDragVerify ref="el5" @success="handleSuccess">
|
||||
<template #text="isPassing">
|
||||
<div v-if="isPassing">
|
||||
<BugOutlined />
|
||||
成功
|
||||
</div>
|
||||
<div v-else>
|
||||
拖动
|
||||
<RightOutlined />
|
||||
</div>
|
||||
</template>
|
||||
</BasicDragVerify>
|
||||
<a-button type="primary" class="ml-2" @click="handleBtnClick(el5)"> 还原 </a-button>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { BasicDragVerify, DragVerifyActionType, PassingData } from '/@/components/Verify/index';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { BugOutlined, RightOutlined } from '@ant-design/icons-vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicDragVerify, BugOutlined, RightOutlined, PageWrapper },
|
||||
setup() {
|
||||
const { createMessage } = useMessage();
|
||||
const el1 = ref<Nullable<DragVerifyActionType>>(null);
|
||||
const el2 = ref<Nullable<DragVerifyActionType>>(null);
|
||||
const el3 = ref<Nullable<DragVerifyActionType>>(null);
|
||||
const el4 = ref<Nullable<DragVerifyActionType>>(null);
|
||||
const el5 = ref<Nullable<DragVerifyActionType>>(null);
|
||||
|
||||
function handleSuccess(data: PassingData) {
|
||||
const { time } = data;
|
||||
createMessage.success(`校验成功,耗时${time}秒`);
|
||||
}
|
||||
|
||||
function handleBtnClick(elRef: Nullable<DragVerifyActionType>) {
|
||||
if (!elRef) {
|
||||
return;
|
||||
}
|
||||
elRef.resume();
|
||||
}
|
||||
return {
|
||||
handleSuccess,
|
||||
el1,
|
||||
el2,
|
||||
el3,
|
||||
el4,
|
||||
el5,
|
||||
handleBtnClick,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.bg-gray-700 {
|
||||
background-color: #4a5568;
|
||||
}
|
||||
</style>
|
||||
@ -1,81 +0,0 @@
|
||||
<!-- 标题与字段布局 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" @submit="handleSubmit" style="margin: 20px auto"/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
label: '姓名',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '年龄',
|
||||
field: 'password',
|
||||
component: 'InputNumber',
|
||||
},
|
||||
{
|
||||
label: '生日',
|
||||
field: 'birthday',
|
||||
component: 'DatePicker',
|
||||
},
|
||||
{
|
||||
label: '头像',
|
||||
field: 'avatar',
|
||||
component: 'JImageUpload',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
showActionButtonGroup: false,
|
||||
actionColOptions: { span: 12 },
|
||||
//控制标题宽度占比
|
||||
labelCol: {
|
||||
xs: 2,
|
||||
sm: 2,
|
||||
md: 2,
|
||||
lg: 9,
|
||||
xl: 3,
|
||||
xxl: 2,
|
||||
},
|
||||
//控制组件宽度占比
|
||||
wrapperCol: {
|
||||
xs: 15,
|
||||
sm: 14,
|
||||
md: 16,
|
||||
lg: 17,
|
||||
xl: 19,
|
||||
xxl: 20,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* 点击提交按钮的value值
|
||||
* @param values
|
||||
*/
|
||||
function handleSubmit(values: any) {
|
||||
console.log('提交按钮数据::::', values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,70 +0,0 @@
|
||||
<!-- 固定label标题的宽度 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" @submit="handleSubmit" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
label: '姓名',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '年龄',
|
||||
field: 'password',
|
||||
component: 'InputNumber',
|
||||
},
|
||||
{
|
||||
label: '生日',
|
||||
field: 'birthday',
|
||||
component: 'DatePicker',
|
||||
},
|
||||
{
|
||||
label: '头像',
|
||||
field: 'avatar',
|
||||
component: 'JImageUpload',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
showResetButton: false,
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
actionColOptions: { span: 17 },
|
||||
//使用labelWidth控制标题宽度
|
||||
labelWidth: '150px',
|
||||
//使用labelCol的样式属性来控制标题宽度
|
||||
labelCol: { style: { width: '150px' } },
|
||||
//标题对齐方式(left:左对齐,right:右对齐),默认右对齐
|
||||
labelAlign: 'right',
|
||||
});
|
||||
|
||||
/**
|
||||
* 点击提交按钮的value值
|
||||
* @param values
|
||||
*/
|
||||
function handleSubmit(values: any) {
|
||||
console.log('提交按钮数据::::', values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,143 +0,0 @@
|
||||
<!-- 动态增减表单 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px;" @submit="handleSubmit">
|
||||
<!-- 添加input的插槽 -->
|
||||
<template #addForm="{ field }">
|
||||
<a-button v-if="Number(field) === 0" @click="addField" style="width: 50px">+</a-button>
|
||||
<a-button v-if="Number(field) > 0" @click="delField(field)" style="width: 50px">-</a-button>
|
||||
</template>
|
||||
</BasicForm>
|
||||
<!-- <div style="margin: 20px auto; text-align: center">
|
||||
<a-button @click="addField">添加表单项</a-button>
|
||||
</div>-->
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
import { CollapseContainer } from '/@/components/Container';
|
||||
import { ref } from 'vue';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'name1',
|
||||
label: '姓名1',
|
||||
component: 'Input',
|
||||
// ifShow:false,
|
||||
colProps: {
|
||||
span: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'age1',
|
||||
label: '年龄1',
|
||||
component: 'InputNumber',
|
||||
// ifShow:false,
|
||||
colProps: {
|
||||
span: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: '0',
|
||||
component: 'Input',
|
||||
// ifShow:false,
|
||||
label: ' ',
|
||||
colProps: {
|
||||
span: 8,
|
||||
},
|
||||
slot: 'addForm',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
* appendSchemaByField:增加表单项(字段)
|
||||
*
|
||||
* removeSchemaByFiled:减少表单项(字段)
|
||||
*/
|
||||
const [registerForm, { appendSchemaByField, removeSchemaByFiled }] = useForm({
|
||||
schemas: formSchemas,
|
||||
showResetButton: false,
|
||||
labelWidth: '150px',
|
||||
// showSubmitButton:false
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
actionColOptions: { span: 17 },
|
||||
});
|
||||
|
||||
//组件个数
|
||||
let n = ref<number>(2);
|
||||
|
||||
/**
|
||||
* 添加字段
|
||||
* appendSchemaByField类型: ( schema: FormSchema, prefixField: string | undefined, first?: boolean | undefined ) => Promise<void>
|
||||
* 说明: 插入到指定 filed 后面,如果没传指定 field,则插入到最后,当 first = true 时插入到第一个位置
|
||||
*/
|
||||
async function addField() {
|
||||
//添加表单字段,里面为schemas对应的属性,可自行配置
|
||||
await appendSchemaByField(
|
||||
{
|
||||
field: `name${n.value}`,
|
||||
component: 'Input',
|
||||
label: '字段' + n.value,
|
||||
colProps: {
|
||||
span: 8,
|
||||
},
|
||||
},
|
||||
''
|
||||
);
|
||||
await appendSchemaByField(
|
||||
{
|
||||
field: `sex${n.value}`,
|
||||
component: 'InputNumber',
|
||||
label: '字段' + n.value,
|
||||
colProps: {
|
||||
span: 8,
|
||||
},
|
||||
},
|
||||
''
|
||||
);
|
||||
|
||||
await appendSchemaByField(
|
||||
{
|
||||
field: `${n.value}`,
|
||||
component: 'Input',
|
||||
label: ' ',
|
||||
colProps: {
|
||||
span: 8,
|
||||
},
|
||||
slot: 'addForm',
|
||||
},
|
||||
''
|
||||
);
|
||||
n.value++;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除字段
|
||||
* 类型: (field: string | string[]) => Promise<void>
|
||||
* 说明: 根据 field 删除 Schema
|
||||
* @param field 当前字段名称
|
||||
*/
|
||||
function delField(field) {
|
||||
//移除指定字段
|
||||
removeSchemaByFiled([`name${field}`, `sex${field}`, `${field}`]);
|
||||
n.value--;
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击提交按钮的value值
|
||||
* @param values
|
||||
*/
|
||||
function handleSubmit(values: any) {
|
||||
console.log('提交按钮数据::::', values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,66 +0,0 @@
|
||||
<!-- 操作按钮 -->
|
||||
<template>
|
||||
<div style="margin: 20px auto; text-align: center">
|
||||
<!-- 通过setProps 可以设置 userForm 中的属性 -->
|
||||
<!-- showActionButtonGroup 显示或者隐藏查询、重置按钮 -->
|
||||
<a-button @click="setProps({ showActionButtonGroup: false })" class="mr-2"> 隐藏操作按钮 </a-button>
|
||||
<a-button @click="setProps({ showActionButtonGroup: true })" class="mr-2"> 显示操作按钮 </a-button>
|
||||
<!-- showActionButtonGroup 显示或者隐藏重置按钮 -->
|
||||
<a-button @click="setProps({ showResetButton: false })" class="mr-2"> 隐藏重置按钮 </a-button>
|
||||
<a-button @click="setProps({ showResetButton: true })" class="mr-2"> 显示重置按钮 </a-button>
|
||||
<!-- showActionButtonGroup 显示或者隐藏查询按钮 -->
|
||||
<a-button @click="setProps({ showSubmitButton: false })" class="mr-2"> 隐藏查询按钮 </a-button>
|
||||
<a-button @click="setProps({ showSubmitButton: true })" class="mr-2"> 显示查询按钮 </a-button>
|
||||
</div>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" @submit="handleSubmit" style="margin-top: 50px; margin-left: 50px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
import { CollapseContainer } from '/@/components/Container';
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
* setProps方法可以动态设置useForm中的属性
|
||||
*/
|
||||
const [registerForm, { setProps }] = useForm({
|
||||
//自定义查询按钮的文本和图标
|
||||
submitButtonOptions: { text: '查询', preIcon: '' },
|
||||
//自定义重置按钮的文本和图标
|
||||
resetButtonOptions: { text: '重置', preIcon: '' },
|
||||
//操作按钮的位置
|
||||
actionColOptions: { span: 17 },
|
||||
//提交按钮的自定义事件
|
||||
submitFunc: customSubmitFunc,
|
||||
//重置按钮的自定义时间
|
||||
resetFunc: customSubmitFunc,
|
||||
//显示操作按钮
|
||||
showActionButtonGroup: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* 查询按钮点击事件
|
||||
*/
|
||||
async function customSubmitFunc() {
|
||||
console.log('查询按钮点击事件,此处处理查询按钮的逻辑');
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置按钮点击事件
|
||||
*/
|
||||
async function customResetFunc() {
|
||||
console.log('重置按钮点击事件,此处处理重置按钮的逻辑');
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击提交按钮的value值
|
||||
* @param values
|
||||
*/
|
||||
function handleSubmit(values: any) {
|
||||
console.log('提交按钮数据::::', values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,95 +0,0 @@
|
||||
<!-- 操作禁用表单 -->
|
||||
<template>
|
||||
<div style="margin: 20px auto; text-align: center">
|
||||
<!-- all 触发或清空所有验证,visitor 只触发或者清空来访人员验证 -->
|
||||
<a-button @click="triggerFormRule('all')" class="mr-2"> 触发表单验证 </a-button>
|
||||
<a-button @click="cancelFormRule('all')" class="mr-2"> 清空表单验证 </a-button>
|
||||
<a-button @click="triggerFormRule('visitor')" class="mr-2"> 只验证来访人员 </a-button>
|
||||
<a-button @click="cancelFormRule('visitor')" class="mr-2"> 只清空来访人员验证 </a-button>
|
||||
</div>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px;" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'visitor',
|
||||
label: '来访人员',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'accessed',
|
||||
label: '来访日期',
|
||||
component: 'DatePicker',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'phone',
|
||||
label: '来访人手机号',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
* clearValidate 清除所有验证,支持取消验证其中几个字段 如 clearValidate(['visitor',...])
|
||||
* validate 验证所有,支持验证其中几个字段,validate(['visitor',...])
|
||||
* validateFields 只支持验证其中几个字段,如validateFields(['visitor',...])
|
||||
*/
|
||||
const [registerForm, { clearValidate, validateFields, validate }] = useForm({
|
||||
schemas: formSchemas,
|
||||
labelWidth: '150px',
|
||||
//隐藏操作按钮
|
||||
showActionButtonGroup: false,
|
||||
//默认聚焦第一个,只支持input
|
||||
autoFocusFirstItem: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* 触发表单验证
|
||||
* @param type all 所有验证 visitor 只验证来访人员
|
||||
*/
|
||||
async function triggerFormRule(type) {
|
||||
if (type == 'all') {
|
||||
//触发所有验证
|
||||
await validate();
|
||||
} else {
|
||||
//触发来访人员验证
|
||||
//visitor 来访人员的对应formSchemas field字段
|
||||
await validateFields(['visitor']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发表单验证
|
||||
* @param type all 所有验证 visitor 只验证来访人员
|
||||
*/
|
||||
async function cancelFormRule(type) {
|
||||
if (type == 'all') {
|
||||
//取消全部验证
|
||||
await clearValidate();
|
||||
} else {
|
||||
//只取消来访人员的验证
|
||||
//visitor 来访人员的对应formSchemas field字段
|
||||
await clearValidate(['visitor']);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,58 +0,0 @@
|
||||
<!-- 操作禁用表单 -->
|
||||
<template>
|
||||
<div style="margin: 20px auto; text-align: center">
|
||||
<!-- 通过setProps 可以设置 userForm 中的属性 -->
|
||||
<!-- 表单大小,默认为 default -->
|
||||
<a-button @click="setProps({ size: 'large' })" class="mr-2"> 更改大小为最大 </a-button>
|
||||
<a-button @click="setProps({ size: 'default' })" class="mr-2"> 还原大小 </a-button>
|
||||
<a-button @click="setProps({ size: 'small' })" class="mr-2"> 更改大小为最小 </a-button>
|
||||
<!-- disabled表单禁用 -->
|
||||
<a-button @click="setProps({ disabled: true })" class="mr-2"> 禁用表单 </a-button>
|
||||
<a-button @click="setProps({ disabled: false })" class="mr-2"> 解除禁用 </a-button>
|
||||
<!-- compact 是否为紧凑表单 -->
|
||||
<a-button @click="setProps({ compact: true })" class="mr-2"> 紧凑表单 </a-button>
|
||||
<a-button @click="setProps({ compact: false })" class="mr-2"> 还原正常间距 </a-button>
|
||||
</div>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px;" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
import { CollapseContainer } from '/@/components/Container';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'visitor',
|
||||
label: '来访人员',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
field: 'accessed',
|
||||
label: '来访日期',
|
||||
component: 'DatePicker',
|
||||
},
|
||||
{
|
||||
field: 'phone',
|
||||
label: '来访人手机号',
|
||||
component: 'Input',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
* setProps方法可以动态设置useForm中的属性
|
||||
*/
|
||||
const [registerForm, { setProps }] = useForm({
|
||||
schemas: formSchemas,
|
||||
labelWidth: '150px',
|
||||
//隐藏操作按钮
|
||||
showActionButtonGroup: false,
|
||||
//默认聚焦第一个,只支持input
|
||||
autoFocusFirstItem: true,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,34 +0,0 @@
|
||||
<!-- 操作表单值 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px;" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
import { schemas } from './example.data';
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm, { getFieldsValue, setFieldsValue, resetFields, validate }] = useForm({
|
||||
schemas: schemas,
|
||||
labelWidth: '150px',
|
||||
//隐藏操作按钮
|
||||
showActionButtonGroup: false,
|
||||
//默认聚焦第一个,只支持input
|
||||
autoFocusFirstItem: true,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,63 +0,0 @@
|
||||
<!-- 控件属性 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
label: '员工姓名',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
disabled: true,
|
||||
},
|
||||
defaultValue: '张三',
|
||||
},
|
||||
{
|
||||
label: '性别',
|
||||
field: 'sex',
|
||||
component: 'Select',
|
||||
//填写组件的属性
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '男', value: 1 },
|
||||
{ label: '女', value: 2 },
|
||||
{ label: '未知', value: 3 },
|
||||
],
|
||||
},
|
||||
//默认值
|
||||
defaultValue: 3,
|
||||
},
|
||||
{
|
||||
label: '年龄',
|
||||
field: 'age',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '入职时间',
|
||||
subLabel: '( 选填 )',
|
||||
field: 'entryTime',
|
||||
component: 'TimePicker',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
labelWidth: '150px',
|
||||
showResetButton: false,
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
actionColOptions: { span: 17 },
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,32 +0,0 @@
|
||||
<!-- 自定义组件 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'custom',
|
||||
label: '自定义组件',
|
||||
//引入自定义组件
|
||||
component: 'JInput',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
labelWidth: '150px',
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,32 +0,0 @@
|
||||
<!-- 操作表单值 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
import { schemas } from './exampleCustom.data';
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm, { getFieldsValue, setFieldsValue, resetFields, validate }] = useForm({
|
||||
schemas: schemas,
|
||||
labelWidth: '150px',
|
||||
//隐藏操作按钮
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,64 +0,0 @@
|
||||
<!-- 插槽 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" @submit="handleSubmit">
|
||||
<!-- #name对应的是formSchemas对应slot(name)插槽 -->
|
||||
<template #name="{ model, field }">
|
||||
<JInput v-model:value="model[field]" />
|
||||
</template>
|
||||
</BasicForm>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
//引入CustomDemo自定义组件
|
||||
import JInput from "/@/components/Form/src/jeecg/components/JInput.vue";
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'name',
|
||||
label: '姓名',
|
||||
component: 'Input',
|
||||
slot:'name'
|
||||
},
|
||||
{
|
||||
field: 'phone',
|
||||
label: '联系方式',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
field: 'feedback',
|
||||
label: '问题反馈',
|
||||
component: 'InputTextArea',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
showResetButton: false,
|
||||
labelWidth: '150px',
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
actionColOptions: { span: 17 },
|
||||
});
|
||||
|
||||
/**
|
||||
* 提交信息
|
||||
*/
|
||||
function handleSubmit(values) {
|
||||
console.log("values::",values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.font-color {
|
||||
font-size: 13px;
|
||||
color: #a1a1a1;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
</style>
|
||||
@ -1,80 +0,0 @@
|
||||
<!-- 动态表单验证 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" @submit="handleSubmit" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
import { duplicateCheck } from '/@/views/system/user/user.api';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'visitor',
|
||||
label: '来访人员',
|
||||
component: 'Input',
|
||||
//自动触发检验,布尔类型
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'accessed',
|
||||
label: '来访日期',
|
||||
component: 'DatePicker',
|
||||
//支持获取当前值判断触发 values代表当前表单的值
|
||||
required: ({ values }) => {
|
||||
return !values.accessed;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'phone',
|
||||
label: '来访人手机号',
|
||||
component: 'Input',
|
||||
//动态自定义正则,values: 当前表单的所有值
|
||||
dynamicRules: ({ values }) => {
|
||||
//需要return
|
||||
return [
|
||||
{
|
||||
//默认开启表单检验
|
||||
required: true,
|
||||
// value 当前手机号输入的值
|
||||
validator: (_, value) => {
|
||||
//需要return 一个Promise对象
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!value) {
|
||||
reject('请输入手机号!');
|
||||
}
|
||||
//验证手机号是否正确
|
||||
let reg = /^1[3456789]\d{9}$/;
|
||||
if (!reg.test(value)) {
|
||||
reject('请输入正确手机号!');
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
showResetButton: false,
|
||||
labelWidth: '150px',
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
actionColOptions: { span: 17 },
|
||||
});
|
||||
|
||||
/**
|
||||
* 提交事件
|
||||
*/
|
||||
function handleSubmit(values: any) {}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,70 +0,0 @@
|
||||
<!-- 字段显示与隐藏 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'id',
|
||||
label: '编号',
|
||||
component: 'Input',
|
||||
//隐藏id,css 控制,不会删除 dom(支持布尔类型 true和false。支持动态值判断,详情请见ifShow)
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
field: 'evaluate',
|
||||
label: '对公司整体评价',
|
||||
component: 'RadioGroup',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '满意', value: '0' },
|
||||
{ label: '不满意', value: '1' },
|
||||
],
|
||||
},
|
||||
defaultValue: '0',
|
||||
},
|
||||
{
|
||||
field: 'describe',
|
||||
label: '不满意原因说明',
|
||||
component: 'InputTextArea',
|
||||
//ifShow和show属性一致,使用其中一个即可,values代表当前表单的值,js 控制,会删除 dom
|
||||
ifShow: ({ values }) => {
|
||||
return values.evaluate == '1';
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'satisfiedLevel',
|
||||
label: '满意度',
|
||||
component: 'Slider',
|
||||
componentProps: {
|
||||
tipFormatter: (value) => {
|
||||
return value + '%';
|
||||
},
|
||||
},
|
||||
//动态禁用,values代表当前表单的值,返回 true或false
|
||||
dynamicDisabled: ({ values }) => {
|
||||
return values.evaluate == '1';
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
showResetButton: false,
|
||||
labelWidth: '150px',
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
actionColOptions: { span: 17 },
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,55 +0,0 @@
|
||||
<!-- 字段标题提示及前缀 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'month',
|
||||
label: '当前月份',
|
||||
component: 'Input',
|
||||
suffix: '月',
|
||||
},
|
||||
{
|
||||
field: 'lateNumber',
|
||||
label: '迟到次数',
|
||||
component: 'InputNumber',
|
||||
//帮助信息:可以直接返回String(helpMessage:"迟到次数"),也可以获取表单值,动态填写
|
||||
helpMessage: ({ values }) => {
|
||||
return '当前迟到次数' + values.lateNumber + ', 扣款' + values.lateNumber * 50 + '元';
|
||||
},
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
field: 'lateReason',
|
||||
label: '迟到原因',
|
||||
component: 'Input',
|
||||
helpMessage: '什么原因耽误上班迟到',
|
||||
//自定义提示属性,需要结合helpMessage一起使用
|
||||
helpComponentProps: {
|
||||
maxWidth: '200px',
|
||||
color: '#66CCFF',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
showResetButton: false,
|
||||
labelWidth: '150px',
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
actionColOptions: { span: 17 },
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,105 +0,0 @@
|
||||
<!-- 自定义页脚 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px">
|
||||
<template #formHeader>
|
||||
<div style="margin: 0 auto 20px">
|
||||
<span>我是自定义按钮</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #formFooter>
|
||||
<div style="margin: 0 auto">
|
||||
<a-button type="primary" @click="save" class="mr-2"> 保存 </a-button>
|
||||
<a-button type="primary" @click="saveDraft" class="mr-2"> 保存草稿 </a-button>
|
||||
<a-button type="error" @click="reset" class="mr-2"> 重置 </a-button>
|
||||
</div>
|
||||
</template>
|
||||
</BasicForm>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
label: '员工姓名',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '性别',
|
||||
field: 'sex',
|
||||
component: 'Select',
|
||||
//填写组件的属性
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '男', value: 1 },
|
||||
{ label: '女', value: 2 },
|
||||
{ label: '未知', value: 3 },
|
||||
],
|
||||
},
|
||||
//默认值
|
||||
defaultValue: 3,
|
||||
},
|
||||
{
|
||||
label: '年龄',
|
||||
field: 'age',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '入职时间',
|
||||
subLabel: '( 选填 )',
|
||||
field: 'entryTime',
|
||||
component: 'TimePicker',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm, { validate, resetFields }] = useForm({
|
||||
schemas: formSchemas,
|
||||
labelWidth: '150px',
|
||||
//隐藏操作按钮
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
|
||||
/**
|
||||
* 保存
|
||||
*/
|
||||
async function save() {
|
||||
//使用useForm方法获取表单值
|
||||
let values = await validate();
|
||||
console.log(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存草稿
|
||||
*/
|
||||
async function saveDraft() {
|
||||
//使用useForm方法validate获取表单值
|
||||
let values = await validate();
|
||||
console.log(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
async function reset() {
|
||||
//使用useForm方法resetFields清空值
|
||||
await resetFields();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,63 +0,0 @@
|
||||
<!-- 表单布局 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
label: '会议名称',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '参会地点',
|
||||
field: 'meetingLocation',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '参与人数',
|
||||
field: 'numberOfPart',
|
||||
component: 'InputNumber',
|
||||
},
|
||||
{
|
||||
label: '会议纪要',
|
||||
field: 'meetingMinutes',
|
||||
component: 'JUpload',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//表单布局属性,支持(vertical,inline),默认为inline
|
||||
layout: 'inline',
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
//不显示查询和重置按钮
|
||||
showActionButtonGroup: false,
|
||||
//默认row行配置,当 layout 为 inline 生效
|
||||
rowProps: { gutter: 24, justify: 'center', align: 'middle' },
|
||||
//全局col列占比(每列显示多少位),和schemas中的colProps属性一致
|
||||
baseColProps: { span: 12 },
|
||||
//row行的样式
|
||||
baseRowStyle: { width: '100%' },
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,84 +0,0 @@
|
||||
<!-- 弹出层表单 -->
|
||||
<template>
|
||||
<div style="margin: 20px auto">
|
||||
<a-button type="primary" @click="openPopup" class="mr-2"> 打开弹窗 </a-button>
|
||||
</div>
|
||||
<!-- 自定义弹窗组件 -->
|
||||
<BasicModal @register="registerModal" title="弹出层表单">
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
import { BasicModal } from '/@/components/Modal';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
label: '员工姓名',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '性别',
|
||||
field: 'sex',
|
||||
component: 'Select',
|
||||
//填写组件的属性
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '男', value: 1 },
|
||||
{ label: '女', value: 2 },
|
||||
{ label: '未知', value: 3 },
|
||||
],
|
||||
},
|
||||
//默认值
|
||||
defaultValue: 3,
|
||||
},
|
||||
{
|
||||
label: '年龄',
|
||||
field: 'age',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '入职时间',
|
||||
subLabel: '( 选填 )',
|
||||
field: 'entryTime',
|
||||
component: 'TimePicker',
|
||||
},
|
||||
];
|
||||
|
||||
//BasicModal绑定注册;
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm, { validate, resetFields }] = useForm({
|
||||
schemas: formSchemas,
|
||||
//隐藏操作按钮
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
|
||||
/**
|
||||
* 打开弹窗
|
||||
*/
|
||||
async function openPopup() {
|
||||
//详见 BasicModal模块
|
||||
openModal(true, {});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,90 +0,0 @@
|
||||
<!-- 自定义渲染 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px">
|
||||
<!-- #phone对应的是formSchemas对应slot(phone)插槽 -->
|
||||
<template #phone="{ model, field }">
|
||||
<!-- 如果是组件需要进行双向绑定,model当前表单对象,field当前字段名称 -->
|
||||
<a-input v-model:value="model[field]" placeholder="请输入手机号" />
|
||||
<span class="font-color">请输入您的手机号,方便我们联系您</span>
|
||||
</template>
|
||||
<template #feedback="{ model, field }">
|
||||
<JEditor v-model:value="model[field]" placeholder="请输入问题反馈" />
|
||||
<span class="font-color">请您图文并茂,方便我们了解问题并及时反馈</span>
|
||||
</template>
|
||||
</BasicForm>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
import JEditor from '/@/components/Form/src/jeecg/components/JEditor.vue';
|
||||
import { h } from 'vue';
|
||||
import { Input } from 'ant-design-vue';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'productName',
|
||||
label: '商品名称',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
field: 'price',
|
||||
label: '价格',
|
||||
component: 'InputNumber',
|
||||
},
|
||||
{
|
||||
field: 'buyNums',
|
||||
label: '购买个数',
|
||||
component: 'InputNumber',
|
||||
//model 单签表单对象,field 当前字段
|
||||
render: ({ model, field }) => {
|
||||
//渲染自定义组件,以Input为例
|
||||
return h(Input, {
|
||||
placeholder: '请输入购买个数',
|
||||
value: model[field],
|
||||
style: { width: '100%' },
|
||||
type: 'number',
|
||||
onChange: (e: ChangeEvent) => {
|
||||
model[field] = e.target.value;
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'describe',
|
||||
label: '描述',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
disabled: true,
|
||||
},
|
||||
//渲染 values当前表单所有值
|
||||
render: ({ values }) => {
|
||||
let productName = values.productName?values.productName:'';
|
||||
let price = values.price ? values.price : 0;
|
||||
let buyNums = values.buyNums ? values.buyNums : 0;
|
||||
return '购买商品名称:' + productName + ', 总价格: ' + price * buyNums + '元';
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
showResetButton: false,
|
||||
labelWidth: '150px',
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
actionColOptions: { span: 17 },
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,58 +0,0 @@
|
||||
<!-- 表单验证 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" @submit="handleSubmit" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'visitor',
|
||||
label: '来访人员',
|
||||
component: 'Input',
|
||||
//自动触发检验,布尔类型
|
||||
required: true,
|
||||
//检验的时候不加上标题
|
||||
rulesMessageJoinLabel: false,
|
||||
},
|
||||
{
|
||||
field: 'accessed',
|
||||
label: '来访日期',
|
||||
component: 'DatePicker',
|
||||
//支持获取当前值判断触发 values代表当前表单的值
|
||||
required: ({ values }) => {
|
||||
return !values.accessed;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'phone',
|
||||
label: '来访人手机号',
|
||||
component: 'Input',
|
||||
//支持正则表达式pattern 和 自定义提示信息 message
|
||||
rules: [{ required: false, message: '请输入正确的手机号', pattern: /^1[3456789]\d{9}$/ }],
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
showResetButton: false,
|
||||
labelWidth: '150px',
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
actionColOptions: { span: 17 },
|
||||
});
|
||||
|
||||
/**
|
||||
* 提交事件
|
||||
*/
|
||||
function handleSubmit(values: any) {}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,99 +0,0 @@
|
||||
<!-- 操作表单schemas配置 -->
|
||||
<template>
|
||||
<div style="margin: 20px auto; text-align: center">
|
||||
<a-button @click="updateFormSchemas" class="mr-2"> 更新字段属性 </a-button>
|
||||
<a-button @click="resetFormSchemas" class="mr-2"> 重置字段属性 </a-button>
|
||||
</div>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'visitor',
|
||||
label: '来访人员',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'accessed',
|
||||
label: '来访日期',
|
||||
component: 'DatePicker',
|
||||
ifShow: false,
|
||||
},
|
||||
{
|
||||
field: 'phone',
|
||||
label: '来访人手机号',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
* updateSchema 更新字段属性,支持schemas里面所有的配置
|
||||
* updateSchema([{ field: 'visitor', componentProps: { disabled: false },}, ... ]);
|
||||
* resetSchema 重置字段属性,支持schemas里面所有的配置
|
||||
* resetSchema([{ field: 'visitor',label: '来访人员',component: 'Input',},... ]);
|
||||
*/
|
||||
const [registerForm, { updateSchema, resetSchema }] = useForm({
|
||||
schemas: formSchemas,
|
||||
//隐藏操作按钮
|
||||
showActionButtonGroup: false,
|
||||
labelWidth: '150px',
|
||||
//默认聚焦第一个,只支持input
|
||||
autoFocusFirstItem: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* 清除表单配置
|
||||
*/
|
||||
async function resetFormSchemas() {
|
||||
await resetSchema([
|
||||
{
|
||||
//字段必填
|
||||
field: 'visitor',
|
||||
label: '来访人员',
|
||||
component: 'Input',
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新表单配置
|
||||
*/
|
||||
async function updateFormSchemas() {
|
||||
//支持更新schemas里面所有的配置
|
||||
await updateSchema([
|
||||
{
|
||||
//字段必填
|
||||
field: 'visitor',
|
||||
componentProps: {
|
||||
disabled: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'accessed',
|
||||
ifShow: true,
|
||||
},
|
||||
]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,116 +0,0 @@
|
||||
<!-- 查询区域 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" @submit="handleSubmit" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'name',
|
||||
label: '姓名',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
field: 'hobby',
|
||||
label: '爱好',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
field: 'birthday',
|
||||
label: '生日',
|
||||
component: 'DatePicker',
|
||||
},
|
||||
{
|
||||
field: 'joinTime',
|
||||
label: '入职时间',
|
||||
component: 'RangePicker',
|
||||
componentProps: {
|
||||
valueType: 'Date',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'workYears',
|
||||
label: '工作年份',
|
||||
component: 'JRangeNumber',
|
||||
},
|
||||
{
|
||||
field: 'sex',
|
||||
label: '性别',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: [
|
||||
{
|
||||
label: '男',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '女',
|
||||
value: '2',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'marital',
|
||||
label: '婚姻状况',
|
||||
component: 'RadioGroup',
|
||||
componentProps: {
|
||||
options: [
|
||||
{
|
||||
label: '未婚',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '已婚',
|
||||
value: '2',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//将表单内时间区域的值映射成 2个字段, 'YYYY-MM-DD'日期格式化
|
||||
fieldMapToTime: [['joinTime', ['joinTime_begin', 'joinTime_end'], 'YYYY-MM-DD']],
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
//是否显示展开收起按钮,默认false
|
||||
showAdvancedButton: true,
|
||||
//超过指定行数折叠,默认3行
|
||||
autoAdvancedCol: 3,
|
||||
//折叠时默认显示行数,默认1行
|
||||
alwaysShowLines: 2,
|
||||
|
||||
//将表单内数值类型区域的值映射成 2个字段
|
||||
fieldMapToNumber: [['workYears', ['workYears_begin', 'workYears_end']]],
|
||||
//每列占比,默认一行为24
|
||||
baseColProps: { span: 12 },
|
||||
});
|
||||
|
||||
/**
|
||||
* 点击提交按钮的value值
|
||||
* @param values
|
||||
*/
|
||||
function handleSubmit(values: any) {
|
||||
console.log('提交按钮数据::::', values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,63 +0,0 @@
|
||||
<!-- 插槽 -->
|
||||
<template>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px">
|
||||
<!-- #phone对应的是formSchemas对应slot(phone)插槽 -->
|
||||
<template #phone="{ model, field }">
|
||||
<!-- 如果是组件需要进行双向绑定,model当前表单对象,field当前字段名称 -->
|
||||
<a-input v-model:value="model[field]" placeholder="请输入手机号" />
|
||||
<span class="font-color">请输入您的手机号,方便我们联系您</span>
|
||||
</template>
|
||||
<template #feedback="{ model, field }">
|
||||
<JEditor v-model:value="model[field]" placeholder="请输入问题反馈" />
|
||||
<span class="font-color">请您图文并茂,方便我们了解问题并及时反馈</span>
|
||||
</template>
|
||||
</BasicForm>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
import JEditor from '/@/components/Form/src/jeecg/components/JEditor.vue';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'name',
|
||||
label: '姓名',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
field: 'phone',
|
||||
label: '联系方式',
|
||||
component: 'Input',
|
||||
slot: 'phone',
|
||||
},
|
||||
{
|
||||
field: 'feedback',
|
||||
label: '问题反馈',
|
||||
component: 'InputTextArea',
|
||||
slot: 'feedback',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
showResetButton: false,
|
||||
labelWidth: '150px',
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
actionColOptions: { span: 17 },
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.font-color {
|
||||
font-size: 13px;
|
||||
color: #a1a1a1;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
</style>
|
||||
@ -1,94 +0,0 @@
|
||||
<!-- 操作表单值 -->
|
||||
<template>
|
||||
<div style="margin: 20px auto; text-align: center">
|
||||
<a-button @click="getFormValue" class="mr-2"> 获取表单值 </a-button>
|
||||
<a-button @click="clearFormValue" class="mr-2"> 清空表单值 </a-button>
|
||||
<a-button @click="updateFormValue" class="mr-2"> 更新表单值 </a-button>
|
||||
</div>
|
||||
<!-- 自定义表单 -->
|
||||
<BasicForm @register="registerForm" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
field: 'visitor',
|
||||
label: '来访人员',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'accessed',
|
||||
label: '来访日期',
|
||||
component: 'DatePicker',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'phone',
|
||||
label: '来访人手机号',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
* getFieldsValue 获取所有表单值
|
||||
* validate 验证通过之后的表单值,支持验证其中几个字段,validate(['visitor',...])
|
||||
* setFieldsValue 更新表单值,如 setFieldsValue({'visitor':'李四',...})
|
||||
* resetFields 清除所有表单值
|
||||
*/
|
||||
const [registerForm, { getFieldsValue, setFieldsValue, resetFields, validate }] = useForm({
|
||||
schemas: formSchemas,
|
||||
//隐藏操作按钮
|
||||
showActionButtonGroup: false,
|
||||
labelWidth: '150px',
|
||||
//默认聚焦第一个,只支持input
|
||||
autoFocusFirstItem: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取表单值
|
||||
*/
|
||||
async function getFormValue() {
|
||||
//获取所有值
|
||||
let fieldsValue = await getFieldsValue();
|
||||
console.log('fieldsValue:::', fieldsValue);
|
||||
//表单验证通过后获取所有字段值
|
||||
fieldsValue = await validate();
|
||||
console.log('fieldsValue:::', fieldsValue);
|
||||
//表单验`visitor来访人员`通过后获取的值
|
||||
fieldsValue = await validate(['visitor']);
|
||||
console.log('fieldsValue:::', fieldsValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空表单值
|
||||
*/
|
||||
async function clearFormValue() {
|
||||
await resetFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新表单值
|
||||
*/
|
||||
async function updateFormValue() {
|
||||
console.log('我进来了');
|
||||
await setFieldsValue({ visitor: '李四' });
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/** 时间和数字输入框样式 */
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-picker) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,63 +0,0 @@
|
||||
<!-- 基本用法 -->
|
||||
<template>
|
||||
<!-- 自定表单 -->
|
||||
<BasicForm @register="registerForm" @submit="handleSubmit" style="margin-top: 20px" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//引入依赖
|
||||
import { useForm, BasicForm, FormSchema } from '/@/components/Form';
|
||||
|
||||
//自定义表单字段
|
||||
const formSchemas: FormSchema[] = [
|
||||
{
|
||||
//标题名称
|
||||
label: '用户名(后面根据labelLength定义的长度隐藏)',
|
||||
//字段
|
||||
field: 'username',
|
||||
//组件
|
||||
component: 'Input',
|
||||
//标题宽度,支持数字和字符串
|
||||
labelWidth: 150,
|
||||
//标题长度,超过位数隐藏
|
||||
labelLength: 3,
|
||||
},
|
||||
{
|
||||
label: '密码',
|
||||
field: 'password',
|
||||
//子标题名称(在主标题后面)
|
||||
subLabel: '(数字和字母组成)',
|
||||
component: 'InputPassword',
|
||||
labelWidth: '150px',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* BasicForm绑定注册;
|
||||
* useForm 是整个框架的核心用于表单渲染,里边封装了很多公共方法;
|
||||
* 支持(schemas: 渲染表单列,autoSubmitOnEnter:回车提交,submitButtonOptions:自定义按钮文本和图标等方法);
|
||||
* 平台通过此封装,简化了代码,支持自定义扩展;
|
||||
*/
|
||||
const [registerForm] = useForm({
|
||||
//注册表单列
|
||||
schemas: formSchemas,
|
||||
//回车提交
|
||||
autoSubmitOnEnter: true,
|
||||
//不显示重置按钮
|
||||
showResetButton: false,
|
||||
//自定义提交按钮文本和图标
|
||||
submitButtonOptions: { text: '提交', preIcon: '' },
|
||||
//查询列占比 24代表一行 取值范围 0-24
|
||||
actionColOptions: { span: 17 },
|
||||
});
|
||||
|
||||
/**
|
||||
* 点击提交按钮的value值
|
||||
* @param values
|
||||
*/
|
||||
function handleSubmit(values: any) {
|
||||
console.log('提交按钮数据::::', values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,393 +0,0 @@
|
||||
import { FormSchema } from '/@/components/Form';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export const schemas: FormSchema[] = [
|
||||
{
|
||||
label: '文本框',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
prefix: '中文',
|
||||
showCount: true,
|
||||
},
|
||||
defaultValue: '张三',
|
||||
},
|
||||
{
|
||||
label: '密码',
|
||||
field: 'password',
|
||||
component: 'InputPassword',
|
||||
componentProps: {
|
||||
//是否显示切换按钮或者控制密码显隐
|
||||
visibilityToggle: true,
|
||||
prefix: '密码',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '搜索框',
|
||||
field: 'searchBox',
|
||||
component: 'InputSearch',
|
||||
componentProps: {
|
||||
onSearch: (value) => {
|
||||
console.log(value);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '文本域',
|
||||
field: 'textArea',
|
||||
component: 'InputTextArea',
|
||||
componentProps: {
|
||||
//可以点击清除图标删除内容
|
||||
allowClear: true,
|
||||
//是否展示字数
|
||||
showCount: true,
|
||||
//自适应内容高度,可设置为 true | false 或对象:{ minRows: 2, maxRows: 6 }
|
||||
autoSize: {
|
||||
//最小显示行数
|
||||
minRows: 2,
|
||||
//最大显示行数
|
||||
maxRows: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数值输入框',
|
||||
field: 'number',
|
||||
component: 'InputNumber',
|
||||
componentProps: {
|
||||
//带标签的 input,设置后置标签
|
||||
addonAfter: '保留两位小数',
|
||||
//最大值
|
||||
max: 100,
|
||||
//数值经度
|
||||
precision: 2,
|
||||
//步数
|
||||
step: 0.1,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
label: '下拉框',
|
||||
field: 'jinputtype',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ value: 'like', label: '模糊(like)' },
|
||||
{ value: 'ne', label: '不等于(ne)' },
|
||||
{ value: 'ge', label: '大于等于(ge)' },
|
||||
{ value: 'le', label: '小于等于(le)' },
|
||||
],
|
||||
//下拉多选
|
||||
mode: 'multiple',
|
||||
//配置是否可搜索
|
||||
showSearch: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'TreeSelect',
|
||||
label: '下拉树',
|
||||
component: 'TreeSelect',
|
||||
componentProps: {
|
||||
//是否显示下拉框,默认false
|
||||
treeCheckable: true,
|
||||
//标题
|
||||
title: '下拉树',
|
||||
//下拉树
|
||||
treeData: [
|
||||
{
|
||||
label: '洗衣机',
|
||||
value: '0',
|
||||
children: [
|
||||
{
|
||||
label: '滚筒洗衣机',
|
||||
value: '0-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '电视机',
|
||||
value: '1',
|
||||
children: [
|
||||
{
|
||||
label: '平板电视',
|
||||
value: '1-1',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
label: 'CRT电视机',
|
||||
value: '1-2',
|
||||
},
|
||||
{
|
||||
label: '投影电视',
|
||||
value: '1-3',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'RadioButtonGroup组件',
|
||||
field: 'status',
|
||||
component: 'RadioButtonGroup',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '有效', value: 1 },
|
||||
{ label: '无效', value: 0 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '单选框',
|
||||
field: 'radioSex',
|
||||
component: 'RadioGroup',
|
||||
componentProps: {
|
||||
//options里面由一个一个的radio组成,支持disabled禁用
|
||||
options: [
|
||||
{ label: '男', value: 1, disabled: false },
|
||||
{ label: '女', value: 0 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '多选框',
|
||||
field: 'checkbox',
|
||||
component: 'Checkbox',
|
||||
componentProps: {
|
||||
//是否禁用,默认false
|
||||
disabled: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '多选框组',
|
||||
field: 'checkSex',
|
||||
component: 'CheckboxGroup',
|
||||
componentProps: {
|
||||
//RadioGroup 下所有 input[type="radio"] 的 name 属性
|
||||
name: '爱好',
|
||||
//options支持disabled禁用
|
||||
options: [
|
||||
{ label: '运动', value: 0, disabled: true },
|
||||
{ label: '听音乐', value: 1 },
|
||||
{ label: '看书', value: 2 },
|
||||
],
|
||||
},
|
||||
defaultValue: [2],
|
||||
},
|
||||
{
|
||||
label: '自动完成组件',
|
||||
field: 'AutoComplete',
|
||||
component: 'AutoComplete',
|
||||
componentProps: {
|
||||
options: [{ value: 'Burns Bay Road' }, { value: 'Downing Street' }, { value: 'Wall Street' }],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '级联选择',
|
||||
field: 'cascade',
|
||||
component: 'Cascader',
|
||||
componentProps: {
|
||||
//最多显示多少个tag
|
||||
maxTagCount: 2,
|
||||
//浮层预设位置
|
||||
placement: 'bottomRight',
|
||||
//在选择框中显示搜索框,默认false
|
||||
showSearch: true,
|
||||
options: [
|
||||
{
|
||||
label: '北京',
|
||||
value: 'BeiJin',
|
||||
children: [
|
||||
{
|
||||
label: '海淀区',
|
||||
value: 'HaiDian',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '江苏省',
|
||||
value: 'JiangSu',
|
||||
children: [
|
||||
{
|
||||
label: '南京',
|
||||
value: 'Nanjing',
|
||||
children: [
|
||||
{
|
||||
label: '中华门',
|
||||
value: 'ZhongHuaMen',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '日期选择',
|
||||
field: 'dateSelect',
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
//日期格式化,页面上显示的值
|
||||
format: 'YYYY-MM-DD',
|
||||
//返回值格式化(绑定值的格式)
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
//是否显示今天按钮
|
||||
showToday: true,
|
||||
//不可选择日期
|
||||
disabledDate: (currentDate) => {
|
||||
let date = dayjs(currentDate).format('YYYY-MM-DD');
|
||||
let nowDate = dayjs(new Date()).format('YYYY-MM-DD');
|
||||
//当天不可选择
|
||||
if (date == nowDate) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '月份选择',
|
||||
field: 'monthSelect',
|
||||
component: 'MonthPicker',
|
||||
componentProps: {
|
||||
//不可选择日期
|
||||
disabledDate: (currentDate) => {
|
||||
let date = dayjs(currentDate).format('YYYY-MM');
|
||||
let nowDate = dayjs(new Date()).format('YYYY-MM');
|
||||
//当天不可选择
|
||||
if (date == nowDate) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '周选择',
|
||||
field: 'weekSelect',
|
||||
component: 'WeekPicker',
|
||||
componentProps: {
|
||||
size: 'small',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '时间选择',
|
||||
field: 'timeSelect',
|
||||
component: 'TimePicker',
|
||||
componentProps: {
|
||||
size: 'default',
|
||||
//日期时间或者时间模式下是否显示此刻,不支持日期时间范围和时间范围
|
||||
showNow: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '日期时间范围',
|
||||
field: 'dateTimeRangeSelect',
|
||||
component: 'RangePicker',
|
||||
componentProps: {
|
||||
//是否显示时间
|
||||
showTime: true,
|
||||
//日期格式化
|
||||
format: 'YYYY/MM/DD HH:mm:ss',
|
||||
//范围文本描述用集合
|
||||
placeholder: ['请选择开始日期时间', '请选择结束日期时间'],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '日期范围',
|
||||
field: 'dateRangeSelect',
|
||||
component: 'RangeDate',
|
||||
componentProps: {
|
||||
//日期格式化
|
||||
format: 'YYYY/MM/DD',
|
||||
//范围文本描述用集合
|
||||
placeholder: ['请选择开始日期', '请选择结束日期'],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '时间范围',
|
||||
field: 'timeRangeSelect',
|
||||
component: 'RangeTime',
|
||||
componentProps: {
|
||||
//日期格式化
|
||||
format: 'HH/mm/ss',
|
||||
//范围文本描述用集合
|
||||
placeholder: ['请选择开始时间', '请选择结束时间'],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '开关',
|
||||
field: 'switch',
|
||||
component: 'Switch',
|
||||
componentProps: {
|
||||
//开关大小,可选值:default small
|
||||
size: 'default',
|
||||
//非选中时的内容
|
||||
unCheckedChildren: '开启',
|
||||
//非选中时的值
|
||||
unCheckedValue: '0',
|
||||
//选中时的内容
|
||||
checkedChildren: '关闭',
|
||||
//选中时的值
|
||||
checkedValue: '1',
|
||||
//是否禁用
|
||||
disabled: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '滑动输入条',
|
||||
field: 'slider',
|
||||
component: 'Slider',
|
||||
componentProps: {
|
||||
//最小值
|
||||
min: -20,
|
||||
//最大值
|
||||
max: 100,
|
||||
//是否为双滑块模式
|
||||
range: true,
|
||||
//刻度标记
|
||||
marks: {
|
||||
'-20': '-20°C',
|
||||
0: '0°C',
|
||||
26: '26°C',
|
||||
37: '37°C',
|
||||
100: {
|
||||
style: {
|
||||
color: '#f50',
|
||||
},
|
||||
label: '100°C',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '评分',
|
||||
field: 'rate',
|
||||
component: 'Rate',
|
||||
componentProps: {
|
||||
//是否允许半选
|
||||
allowHalf: true,
|
||||
//star 总数
|
||||
count: 5,
|
||||
//tooltip提示,有几颗星写几个
|
||||
tooltips: ['非常差', '较差', '正常', '很好', '非很好'],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '分割线',
|
||||
field: 'divisionLine',
|
||||
component: 'Divider',
|
||||
componentProps: {
|
||||
//是否虚线
|
||||
dashed: false,
|
||||
//分割线标题的位置(left | right | center)
|
||||
orientation: 'center',
|
||||
//文字是否显示为普通正文样式
|
||||
plain: true,
|
||||
//水平还是垂直类型(horizontal | vertical)
|
||||
type: 'horizontal',
|
||||
},
|
||||
},
|
||||
];
|
||||
@ -1,452 +0,0 @@
|
||||
import { FormSchema } from '/@/components/Form';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
export const schemas: FormSchema[] = [
|
||||
{
|
||||
label: '验证码',
|
||||
field: 'code',
|
||||
component: 'InputCountDown',
|
||||
componentProps: {
|
||||
//'default': 默认, 'large': 最大, 'small': 最小
|
||||
size:'default',
|
||||
//倒计时
|
||||
count: 120,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Api下拉选择',
|
||||
field: 'apiSelect',
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
//multiple: 多选;不填写为单选
|
||||
mode: 'multiple',
|
||||
//请求api,返回结果{ result: { records:[{'id':'1',name:'scott'},{'id':'2',name:'小张'}] }}
|
||||
api: () => defHttp.get({ url: '/test/jeecgDemo/list' }),
|
||||
//数值转成String
|
||||
numberToString: false,
|
||||
//标题字段
|
||||
labelField: 'name',
|
||||
//值字段
|
||||
valueField: 'id',
|
||||
//请求参数
|
||||
params: {},
|
||||
//返回结果字段
|
||||
resultField: 'records',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Api树选择',
|
||||
field: 'apiSelect',
|
||||
component: 'ApiTreeSelect',
|
||||
componentProps: {
|
||||
/* 请求api,返回结果
|
||||
{ result: { list: [{ title:'选项0',value:'0',key:'0',
|
||||
children: [ {"title": "选项0-0","value": "0-0","key": "0-0"},...]
|
||||
}, ...]
|
||||
}} */
|
||||
api: () => defHttp.get({ url: '/mock/tree/getDemoOptions' }),
|
||||
//请求参数
|
||||
params: {},
|
||||
//返回结果字段
|
||||
resultField: 'list',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '校验密码强度',
|
||||
field: 'pwd',
|
||||
component: 'StrengthMeter',
|
||||
componentProps: {
|
||||
//是否显示密码文本框
|
||||
showInput: true,
|
||||
//是否禁用
|
||||
disabled: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '省市县联动',
|
||||
field: 'province',
|
||||
component: 'JAreaLinkage',
|
||||
componentProps: {
|
||||
//是否显示区县,默认true,否则只显示省
|
||||
showArea: true,
|
||||
//是否是全部文本,默认false
|
||||
showAll: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '岗位选择',
|
||||
field: 'post',
|
||||
component: 'JSelectPosition',
|
||||
componentProps: {
|
||||
//是否右侧显示选中列表
|
||||
showSelected: true,
|
||||
//最大选择数量
|
||||
maxSelectCount: 1,
|
||||
//岗位标题
|
||||
modalTitle: '岗位',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '角色选择',
|
||||
field: 'role',
|
||||
component: 'JSelectRole',
|
||||
componentProps: {
|
||||
//请求参数 如params:{"code":"001"}
|
||||
params: {},
|
||||
//是否单选,默认false
|
||||
isRadioSelection: true,
|
||||
//角色标题
|
||||
modalTitle: '角色',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '用户选择',
|
||||
field: 'user',
|
||||
component: 'JSelectUser',
|
||||
componentProps: {
|
||||
//取值字段配置,一般为主键字段
|
||||
rowKey: 'username',
|
||||
//显示字段配置
|
||||
labelKey: 'realname',
|
||||
//是否显示选择按钮
|
||||
showButton: false,
|
||||
//用户标题
|
||||
modalTitle: '用户',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '图片上传',
|
||||
field: 'uploadImage',
|
||||
component: 'JImageUpload',
|
||||
componentProps: {
|
||||
//按钮显示文字
|
||||
text:'图片上传',
|
||||
//支持两种基本样式picture和picture-card
|
||||
listType:'picture-card',
|
||||
//用于控制文件上传的业务路径,默认temp
|
||||
bizPath:'temp',
|
||||
//是否禁用
|
||||
disabled:false,
|
||||
//最大上传数量
|
||||
fileMax:1,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '字典标签',
|
||||
field: 'dictTags',
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: {
|
||||
//字典code配置,比如通过性别字典编码:sex,也可以使用demo,name,id 表名,名称,值的方式
|
||||
dictCode:'sex',
|
||||
//支持radio(单选按钮)、radioButton(单选按钮 btn风格)、select(下拉框)
|
||||
type:'radioButton'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '部门选择',
|
||||
field: 'dept',
|
||||
component: 'JSelectDept',
|
||||
componentProps: {
|
||||
//是否开启异步加载
|
||||
sync: false,
|
||||
//是否显示复选框
|
||||
checkable: true,
|
||||
//是否显示选择按钮
|
||||
showButton: false,
|
||||
//父子节点选中状态不再关联
|
||||
checkStrictly: true,
|
||||
//选择框标题
|
||||
modalTitle: '部门选择',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '省市县级联动',
|
||||
field: 'provinceArea',
|
||||
component: 'JAreaSelect',
|
||||
componentProps: {
|
||||
//级别 1 只显示省 2 省市 3 省市区
|
||||
level:3
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '富文本',
|
||||
field: 'editor',
|
||||
component: 'JEditor',
|
||||
componentProps: {
|
||||
//是否禁用
|
||||
disabled: false
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'markdown',
|
||||
field: 'markdown',
|
||||
component: 'JMarkdownEditor',
|
||||
componentProps: {
|
||||
//是否禁用
|
||||
disabled: false
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '可输入下拉框',
|
||||
field: 'inputSelect',
|
||||
component: 'JSelectInput',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: 'Default', value: 'default' },
|
||||
{ label: 'IFrame', value: 'iframe' },
|
||||
],
|
||||
//是否为搜索模式
|
||||
showSearch: true,
|
||||
//是否禁用
|
||||
disabled: false
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '代码编辑器组件',
|
||||
field: 'jCode',
|
||||
component: 'JCodeEditor',
|
||||
componentProps: {
|
||||
//高度,默认auto
|
||||
height:'150px',
|
||||
//是否禁用
|
||||
disabled:false,
|
||||
//是否全屏
|
||||
fullScreen:false,
|
||||
//全屏之后的坐标
|
||||
zIndex: 999,
|
||||
//代码主题,目前只支持idea,可在组件自行扩展
|
||||
theme:'idea',
|
||||
//代码提示
|
||||
keywords:['console'],
|
||||
//语言如(javascript,vue,markdown)可在组件自行扩展
|
||||
language:'javascript'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '分类字典树',
|
||||
field: 'dictTree',
|
||||
component: 'JCategorySelect',
|
||||
componentProps: {
|
||||
//占位内容
|
||||
placeholder:'请选择分类字典树',
|
||||
//查询条件,如“{'name':'笔记本'}”
|
||||
condition:"",
|
||||
//是否多选
|
||||
multiple: false,
|
||||
//起始选择code,见配置的分类字典的类型编码
|
||||
pcode: 'A04',
|
||||
//父级id
|
||||
pid:'',
|
||||
//返回key
|
||||
back:'id',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '下拉多选',
|
||||
field: 'selectMultiple',
|
||||
component: 'JSelectMultiple',
|
||||
componentProps: {
|
||||
//字典code配置,比如通过性别字典编码:sex,也可以使用demo,name,id 表名,名称,值的方式
|
||||
dictCode:'company_rank',
|
||||
//是否只读
|
||||
readOnly:false,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'popup',
|
||||
field: 'popup',
|
||||
component: 'JPopup',
|
||||
componentProps: ({ formActionType }) => {
|
||||
const {setFieldsValue} = formActionType;
|
||||
return{
|
||||
setFieldsValue:setFieldsValue,
|
||||
//online报表编码
|
||||
code:"demo",
|
||||
//是否为多选
|
||||
multi:false,
|
||||
//字段配置
|
||||
fieldConfig: [
|
||||
{ source: 'name', target: 'popup' },
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '开关自定义',
|
||||
field: 'switch',
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
//取值 options
|
||||
options:['Y','N'],
|
||||
//文本option
|
||||
labelOptions:['是', '否'],
|
||||
//是否启用下拉
|
||||
query: false,
|
||||
//是否禁用
|
||||
disabled: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '定时表达式选择',
|
||||
field: 'timing',
|
||||
component: 'JEasyCron',
|
||||
componentProps:{
|
||||
//是否隐藏参数秒和年设置,如果隐藏,那么参数秒和年将会全部忽略掉。
|
||||
hideSecond: false,
|
||||
//是否隐藏参数年设置,如果隐藏,那么参数年将会全部忽略掉
|
||||
hideYear: false,
|
||||
//是否禁用
|
||||
disabled: false,
|
||||
//获取预览执行时间列表的函数,格式为:remote (cron值, time时间戳, cb回调函数)
|
||||
remote:(cron,time,cb)=>{}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '分类字典树',
|
||||
field: 'treeDict',
|
||||
component: 'JTreeDict',
|
||||
componentProps:{
|
||||
//指定当前组件需要存储的字段 可选: id(主键)和code(编码)
|
||||
field:'id',
|
||||
//是否为异步
|
||||
async: true,
|
||||
//是否禁用
|
||||
disabled: false,
|
||||
//指定一个节点的编码,加载该节点下的所有字典数据,若不指定,默认加载所有数据
|
||||
parentCode:'A04'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '多行输入窗口',
|
||||
field: 'inputPop',
|
||||
component: 'JInputPop',
|
||||
componentProps:{
|
||||
//标题
|
||||
title:'多行输入窗口',
|
||||
//弹窗显示位置
|
||||
position:'bottom',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '多选',
|
||||
field: 'multipleChoice',
|
||||
component: 'JCheckbox',
|
||||
componentProps:{
|
||||
//字典code配置,比如通过职位字典编码:company_rank,也可以使用demo,name,id 表名,名称,值的方式
|
||||
dictCode:'company_rank',
|
||||
//是否禁用
|
||||
disabled: false,
|
||||
//没有字典code可以使用option来定义
|
||||
// options:[
|
||||
// {label:'CE0',value:'1'}
|
||||
// ]
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '下拉树选择',
|
||||
field: 'treeCusSelect',
|
||||
component: 'JTreeSelect',
|
||||
componentProps: {
|
||||
//字典code配置,比如通过性别字典编码:sex,也可以使用sys_permission,name,id 表名,名称,值的方式
|
||||
dict: 'sys_permission,name,id',
|
||||
//父级id字段
|
||||
pidField: 'parent_id',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '根据部门选择用户组件',
|
||||
field: 'userByDept',
|
||||
component: 'JSelectUserByDept',
|
||||
componentProps: {
|
||||
//是否显示选择按钮
|
||||
showButton: true,
|
||||
//选择框标题
|
||||
modalTitle: '部门用户选择'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '文件上传',
|
||||
field: 'uploadFile',
|
||||
component: 'JUpload',
|
||||
componentProps: {
|
||||
//是否显示选择按钮
|
||||
text: '文件上传',
|
||||
//最大上传数
|
||||
maxCount: 2,
|
||||
//是否显示下载按钮
|
||||
download: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '字典表搜索',
|
||||
field: 'dictSearchSelect',
|
||||
component: 'JSearchSelect',
|
||||
componentProps: {
|
||||
//字典code配置,通过 demo,name,id 表名,名称,值的方式
|
||||
dict: 'demo,name,id',
|
||||
//是否异步加载
|
||||
async: true,
|
||||
//当async设置为true时有效,表示异步查询时,每次获取数据的数量,默认10
|
||||
pageSize:3
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '动态创建input框',
|
||||
field: 'jAddInput',
|
||||
component: 'JAddInput',
|
||||
componentProps: {
|
||||
//自定义超过多少行才会显示删除按钮,默认为1
|
||||
min:1
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '用户选择组件',
|
||||
field: 'userCusSelect',
|
||||
component: 'UserSelect',
|
||||
componentProps: {
|
||||
//是否多选
|
||||
multi: true,
|
||||
//从用户表中选择一列,其值作为该控件的存储值,默认id列
|
||||
store: 'id',
|
||||
//是否排除我自己(当前登录用户)
|
||||
izExcludeMy: false,
|
||||
//是否禁用
|
||||
disabled: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '选择角色组件',
|
||||
field: 'roleSelect',
|
||||
component: 'RoleSelect',
|
||||
componentProps: {
|
||||
//最大选择数量
|
||||
maxSelectCount: 4,
|
||||
//是否单选
|
||||
multi: true
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数值范围输入框',
|
||||
field: 'rangeNumber',
|
||||
component: 'JRangeNumber',
|
||||
},
|
||||
{
|
||||
label: '远程Api单选框组',
|
||||
field: 'apiRadioGroup',
|
||||
component: 'ApiRadioGroup',
|
||||
componentProps:{
|
||||
//请求接口返回结果{ result:{ list: [ name: '选项0',id: '1' ] }}
|
||||
api:()=> defHttp.get({ url: '/mock/select/getDemoOptions' }),
|
||||
//请求参数
|
||||
params:{},
|
||||
//是否为按钮风格类型,默认false
|
||||
isBtn: false,
|
||||
//返回集合名称
|
||||
resultField: 'list',
|
||||
//标题字段名称
|
||||
labelField: 'name',
|
||||
//值字段名称
|
||||
valueField: 'id',
|
||||
}
|
||||
},
|
||||
];
|
||||
@ -1,24 +0,0 @@
|
||||
export { default as BasicFiledsLayotForm } from './BasicFiledsLayotForm.vue';
|
||||
export { default as BasicFixedWidthForm } from './BasicFixedWidthForm.vue';
|
||||
export { default as BasicFormAdd } from './BasicFormAdd.vue';
|
||||
export { default as BasicFormBtn } from './BasicFormBtn.vue';
|
||||
export { default as BasicFormCleanRule } from './BasicFormCleanRule.vue';
|
||||
export { default as BasicFormCompact } from './BasicFormCompact.vue';
|
||||
export { default as BasicFormComponent } from './BasicFormComponent.vue';
|
||||
export { default as BasicFormConAttribute } from './BasicFormConAttribute.vue';
|
||||
export { default as BasicFormCustom } from './BasicFormCustom.vue';
|
||||
export { default as BasicFormCustomComponent } from './BasicFormCustomComponent.vue';
|
||||
export { default as BasicFormCustomSlots } from './BasicFormCustomSlots.vue';
|
||||
export { default as BasicFormDynamicsRules } from './BasicFormDynamicsRules.vue';
|
||||
export { default as BasicFormFieldShow } from './BasicFormFieldShow.vue';
|
||||
export { default as BasicFormFieldTip } from './BasicFormFieldTip.vue';
|
||||
export { default as BasicFormFooter } from './BasicFormFooter.vue';
|
||||
export { default as BasicFormLayout } from './BasicFormLayout.vue';
|
||||
export { default as BasicFormModal } from './BasicFormModal.vue';
|
||||
export { default as BasicFormRander } from './BasicFormRander.vue';
|
||||
export { default as BasicFormRules } from './BasicFormRules.vue';
|
||||
export { default as BasicFormSchemas } from './BasicFormSchemas.vue';
|
||||
export { default as BasicFormSearch } from './BasicFormSearch.vue';
|
||||
export { default as BasicFormSlots } from './BasicFormSlots.vue';
|
||||
export { default as BasicFormValue } from './BasicFormValue.vue';
|
||||
export { default as BasicFunctionForm } from './BasicFunctionForm.vue';
|
||||
@ -1,114 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<a-card :bordered="false" style="height: 100%">
|
||||
<a-tabs v-model:activeKey="activeKey" @change="tabChange">
|
||||
<a-tab-pane :key="item.key" :tab="item.label" v-for="item in compList" />
|
||||
</a-tabs>
|
||||
<component :is="currentComponent" />
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, computed } from 'vue';
|
||||
import {
|
||||
BasicFunctionForm,
|
||||
BasicFormConAttribute,
|
||||
BasicFormFieldShow,
|
||||
BasicFormFieldTip,
|
||||
BasicFormRules,
|
||||
BasicFormDynamicsRules,
|
||||
BasicFormSlots,
|
||||
BasicFormCustomSlots,
|
||||
BasicFormRander,
|
||||
BasicFixedWidthForm,
|
||||
BasicFiledsLayotForm,
|
||||
BasicFormLayout,
|
||||
BasicFormBtn,
|
||||
BasicFormCompact,
|
||||
BasicFormCleanRule,
|
||||
BasicFormValue,
|
||||
BasicFormSchemas,
|
||||
BasicFormAdd,
|
||||
BasicFormFooter,
|
||||
BasicFormModal,
|
||||
BasicFormCustom,
|
||||
BasicFormSearch,
|
||||
BasicFormComponent,
|
||||
BasicFormCustomComponent,
|
||||
} from './index';
|
||||
export default defineComponent({
|
||||
name: 'document-table-demo',
|
||||
components: {
|
||||
BasicFunctionForm,
|
||||
BasicFormConAttribute,
|
||||
BasicFormFieldShow,
|
||||
BasicFormFieldTip,
|
||||
BasicFormRules,
|
||||
BasicFormDynamicsRules,
|
||||
BasicFormSlots,
|
||||
BasicFormCustomSlots,
|
||||
BasicFormRander,
|
||||
BasicFixedWidthForm,
|
||||
BasicFiledsLayotForm,
|
||||
BasicFormLayout,
|
||||
BasicFormBtn,
|
||||
BasicFormCompact,
|
||||
BasicFormCleanRule,
|
||||
BasicFormValue,
|
||||
BasicFormSchemas,
|
||||
BasicFormAdd,
|
||||
BasicFormFooter,
|
||||
BasicFormModal,
|
||||
BasicFormCustom,
|
||||
BasicFormSearch,
|
||||
BasicFormComponent,
|
||||
BasicFormCustomComponent,
|
||||
},
|
||||
setup() {
|
||||
//当前选中key
|
||||
const activeKey = ref('BasicFunctionForm');
|
||||
//组件集合
|
||||
const compList = ref([
|
||||
{ key: 'BasicFunctionForm', label: '基础表单' },
|
||||
{ key: 'BasicFormConAttribute', label: '字段控件属性' },
|
||||
{ key: 'BasicFormComponent', label: 'Ant Design Vue自带控件' },
|
||||
{ key: 'BasicFormCustomComponent', label: 'JEECG封装的控件' },
|
||||
{ key: 'BasicFormFieldShow', label: '字段显示和隐藏' },
|
||||
{ key: 'BasicFormFieldTip', label: '字段标题提示' },
|
||||
{ key: 'BasicFormRules', label: '表单检验' },
|
||||
{ key: 'BasicFormDynamicsRules', label: '自定义动态检验' },
|
||||
{ key: 'BasicFormSlots', label: '字段插槽' },
|
||||
{ key: 'BasicFormCustomSlots', label: '自定义组件(插槽)' },
|
||||
{ key: 'BasicFormCustom', label: '自定义组件(component)' },
|
||||
{ key: 'BasicFormRander', label: '自定义渲染' },
|
||||
{ key: 'BasicFixedWidthForm', label: '固定label宽度' },
|
||||
{ key: 'BasicFiledsLayotForm', label: '标题与字段布局' },
|
||||
{ key: 'BasicFormLayout', label: '表单布局' },
|
||||
{ key: 'BasicFormBtn', label: '操作按钮示例' },
|
||||
{ key: 'BasicFormCompact', label: '表单紧凑' },
|
||||
{ key: 'BasicFormCleanRule', label: '表单检验配置' },
|
||||
{ key: 'BasicFormValue', label: '获取value值' },
|
||||
{ key: 'BasicFormSchemas', label: '更新schemas表单配置' },
|
||||
{ key: 'BasicFormAdd', label: '动态增减表单' },
|
||||
{ key: 'BasicFormFooter', label: '自定义页脚' },
|
||||
{ key: 'BasicFormModal', label: '弹出层表单' },
|
||||
{ key: 'BasicFormSearch', label: '查询区域' },
|
||||
]);
|
||||
//当前选中组件
|
||||
const currentComponent = computed(() => {
|
||||
return activeKey.value;
|
||||
});
|
||||
|
||||
//使用component动态切换tab
|
||||
function tabChange(key) {
|
||||
activeKey.value = key;
|
||||
}
|
||||
return {
|
||||
activeKey,
|
||||
currentComponent,
|
||||
tabChange,
|
||||
compList,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,135 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #action="{ record }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: 'demo:btn:show', // 根据权限控制是否显示: 无权限,不显示
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
icon: 'ic:outline-delete-outline',
|
||||
onClick: handleDelete.bind(null, record),
|
||||
auth: 'super', // 根据权限控制是否显示: 有权限,会显示
|
||||
},
|
||||
]"
|
||||
:dropDownActions="[
|
||||
{
|
||||
label: '启用',
|
||||
popConfirm: {
|
||||
title: '是否启用?',
|
||||
confirm: handleOpen.bind(null, record),
|
||||
},
|
||||
ifShow: (_action) => {
|
||||
return record.status !== 'enable'; // 根据业务控制是否显示: 非enable状态的不显示启用按钮
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '禁用',
|
||||
popConfirm: {
|
||||
title: '是否禁用?',
|
||||
confirm: handleOpen.bind(null, record),
|
||||
},
|
||||
ifShow: () => {
|
||||
return record.status === 'enable'; // 根据业务控制是否显示: enable状态的显示禁用按钮
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '同时控制',
|
||||
popConfirm: {
|
||||
title: '是否动态显示?',
|
||||
confirm: handleOpen.bind(null, record),
|
||||
},
|
||||
auth: 'super', // 同时根据权限和业务控制是否显示
|
||||
ifShow: () => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
auth: 'demo:field:show', // 根据权限控制是否显示: 无权限,不显示
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
auth: 'super', // 同时根据权限和业务控制是否显示
|
||||
ifShow: (_column) => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable, TableAction },
|
||||
setup() {
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '权限列',
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
bordered: true,
|
||||
useSearchForm: false,
|
||||
actionColumn: {
|
||||
width: 250,
|
||||
title: 'Action',
|
||||
dataIndex: 'action',
|
||||
slots: { customRender: 'action' },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
//注册table数据
|
||||
const [registerTable] = tableContext;
|
||||
|
||||
function handleEdit(record: Recordable) {
|
||||
console.log('点击了编辑', record);
|
||||
}
|
||||
function handleDelete(record: Recordable) {
|
||||
console.log('点击了删除', record);
|
||||
}
|
||||
function handleOpen(record: Recordable) {
|
||||
console.log('点击了启用', record);
|
||||
}
|
||||
return {
|
||||
registerTable,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
handleOpen,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,94 +0,0 @@
|
||||
<template>
|
||||
<!--引用表格-->
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #bodyCell="{ column, text }">
|
||||
<template v-if="column.dataIndex === 'name'">
|
||||
<a>{{ text }}</a>
|
||||
</template>
|
||||
</template>
|
||||
<template #footer>页脚</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="basic-table-demo" setup>
|
||||
import { ActionItem, BasicColumn, BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
//定义表格列
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '住址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '长内容列',
|
||||
dataIndex: 'address',
|
||||
key: 'address 2',
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '长内容列',
|
||||
dataIndex: 'address',
|
||||
key: 'address 3',
|
||||
ellipsis: true,
|
||||
},
|
||||
];
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext } = useListPage({
|
||||
designScope: 'basic-table-demo',
|
||||
tableProps: {
|
||||
title: '边框表格',
|
||||
dataSource: [
|
||||
{
|
||||
key: '1',
|
||||
name: '张三',
|
||||
age: 32,
|
||||
address: '中国北京北京市朝阳区大屯路科学院南里1号楼3单元401',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: '刘思',
|
||||
age: 32,
|
||||
address: '中国北京北京市昌平区顺沙路尚湖世家2号楼7单元503',
|
||||
},
|
||||
],
|
||||
columns: columns,
|
||||
showActionColumn: false,
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [registerTable] = tableContext;
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record): ActionItem[] {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function handleEdit(record) {
|
||||
console.log(record);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,81 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable">
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="basic-table-demo" setup>
|
||||
import { ActionItem, BasicColumn, BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
//定义表格列
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
resizable: false,
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
},
|
||||
{
|
||||
title: '住址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
},
|
||||
];
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext } = useListPage({
|
||||
designScope: 'basic-table-demo',
|
||||
tableProps: {
|
||||
title: '用户列表',
|
||||
dataSource: [
|
||||
{
|
||||
key: '1',
|
||||
name: '胡歌',
|
||||
age: 32,
|
||||
address: '朝阳区林萃路1号',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: '刘诗诗',
|
||||
age: 32,
|
||||
address: '昌平区白沙路1号',
|
||||
},
|
||||
],
|
||||
columns: columns,
|
||||
size: 'large', //紧凑型表格 large
|
||||
striped: false, //斑马纹设置 false
|
||||
showActionColumn: true,
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [registerTable, methods] = tableContext;
|
||||
console.log('methods', methods);
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record): ActionItem[] {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function handleEdit(record) {
|
||||
console.log(record);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,157 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<!--定义表格-->
|
||||
<BasicTable @register="registerTable">
|
||||
<!-- 搜索区域插槽自定义查询 -->
|
||||
<template #form-email="{ model, field }">
|
||||
<a-input placeholder="请输入邮箱" v-model:value="model[field]" addon-before="邮箱:" addon-after=".com"></a-input>
|
||||
</template>
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="basic-table-demo" setup>
|
||||
import { ActionItem, BasicColumn, BasicTable, FormSchema, TableAction } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
//定义表格列
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 170,
|
||||
align: 'left',
|
||||
resizable: true,
|
||||
sorter: {
|
||||
multiple: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '关键词',
|
||||
dataIndex: 'keyWord',
|
||||
width: 130,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '打卡时间',
|
||||
dataIndex: 'punchTime',
|
||||
width: 140,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '工资',
|
||||
dataIndex: 'salaryMoney',
|
||||
width: 140,
|
||||
resizable: true,
|
||||
sorter: {
|
||||
multiple: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '奖金',
|
||||
dataIndex: 'bonusMoney',
|
||||
width: 140,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
sorter: {
|
||||
multiple: 3,
|
||||
},
|
||||
filters: [
|
||||
{ text: '男', value: '1' },
|
||||
{ text: '女', value: '2' },
|
||||
],
|
||||
customRender: ({ record }) => {
|
||||
return record.sex ? (record.sex == '1' ? '男' : '女') : '';
|
||||
},
|
||||
width: 120,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '生日',
|
||||
dataIndex: 'birthday',
|
||||
width: 120,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
width: 120,
|
||||
resizable: true,
|
||||
},
|
||||
];
|
||||
//表单搜索字段
|
||||
const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
label: '姓名', //显示label
|
||||
field: 'name', //查询字段
|
||||
component: 'JInput', //渲染的组件
|
||||
defaultValue: '苏榕润', //设置默认值
|
||||
},
|
||||
{
|
||||
label: '性别',
|
||||
field: 'sex',
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: {
|
||||
//渲染的组件的props
|
||||
dictCode: 'sex',
|
||||
placeholder: '请选择性别',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '邮箱',
|
||||
field: 'email',
|
||||
component: 'JInput',
|
||||
slot: 'email',
|
||||
},
|
||||
{
|
||||
label: '生日',
|
||||
field: 'birthday',
|
||||
component: 'DatePicker',
|
||||
},
|
||||
];
|
||||
//ajax请求api接口
|
||||
const demoListApi = (params) => {
|
||||
return defHttp.get({ url: '/test/jeecgDemo/list', params });
|
||||
};
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext } = useListPage({
|
||||
designScope: 'basic-table-demo-filter',
|
||||
tableProps: {
|
||||
title: '用户列表',
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
formConfig: {
|
||||
schemas: searchFormSchema,
|
||||
},
|
||||
useSearchForm: true,
|
||||
},
|
||||
});
|
||||
//BasicTable绑定注册
|
||||
const [registerTable, { getForm }] = tableContext;
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record): ActionItem[] {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function handleEdit(record) {
|
||||
let { getFieldsValue } = getForm();
|
||||
console.log('查询form的数据', getFieldsValue());
|
||||
console.log(record);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,106 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #id="{ record }"> ID: {{ record.id }} </template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<Avatar v-if="column.key === 'avatar'" :size="60" :src="record.avatar" />
|
||||
<Tag v-if="column.key === 'no'" color="green">
|
||||
{{ record.no }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #img="{ text }">
|
||||
<TableImg :size="60" :simpleShow="true" :imgList="text" />
|
||||
</template>
|
||||
<template #imgs="{ text }"> <TableImg :size="60" :imgList="text" /> </template>
|
||||
|
||||
<template #category="{ record }">
|
||||
<Tag color="green">
|
||||
{{ record.no }}
|
||||
</Tag>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable, BasicColumn, TableImg } from '/@/components/Table';
|
||||
import { Tag, Avatar } from 'ant-design-vue';
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
slots: { customRender: 'id' },
|
||||
},
|
||||
{
|
||||
title: '头像',
|
||||
dataIndex: 'avatar',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '分类',
|
||||
dataIndex: 'category',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
defaultHidden: true,
|
||||
slots: { customRender: 'category' },
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '图片列表1',
|
||||
dataIndex: 'imgArr',
|
||||
helpMessage: ['这是简单模式的图片列表', '只会显示一张在表格中', '但点击可预览多张图片'],
|
||||
width: 140,
|
||||
slots: { customRender: 'img' },
|
||||
},
|
||||
{
|
||||
title: '照片列表2',
|
||||
dataIndex: 'imgs',
|
||||
width: 160,
|
||||
slots: { customRender: 'imgs' },
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable, TableImg, Tag, Avatar },
|
||||
setup() {
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '自定义列内容',
|
||||
titleHelpMessage: '表格中所有头像、图片均为mock生成,仅用于演示图片占位',
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
bordered: true,
|
||||
showTableSetting: false,
|
||||
showActionColumn: false,
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [registerTable] = tableContext;
|
||||
return {
|
||||
registerTable,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,217 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable" @edit-end="handleEditEnd" @edit-cancel="handleEditCancel" :beforeEditSubmit="beforeEditSubmit" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
|
||||
import { optionsListApi } from '/@/api/demo/select';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { treeOptionsListApi } from '/@/api/demo/tree';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '输入框',
|
||||
dataIndex: 'name',
|
||||
edit: true,
|
||||
editComponentProps: {
|
||||
prefix: '$',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '默认输入状态',
|
||||
dataIndex: 'name7',
|
||||
edit: true,
|
||||
editable: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '输入框校验',
|
||||
dataIndex: 'name1',
|
||||
edit: true,
|
||||
// 默认必填校验
|
||||
editRule: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '输入框函数校验',
|
||||
dataIndex: 'name2',
|
||||
edit: true,
|
||||
editRule: async (text) => {
|
||||
if (text === '2') {
|
||||
return '不能输入该值';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '数字输入框',
|
||||
dataIndex: 'id',
|
||||
edit: true,
|
||||
editRule: true,
|
||||
editComponent: 'InputNumber',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '下拉框',
|
||||
dataIndex: 'name3',
|
||||
edit: true,
|
||||
editComponent: 'Select',
|
||||
editComponentProps: {
|
||||
options: [
|
||||
{
|
||||
label: 'Option1',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: 'Option2',
|
||||
value: '2',
|
||||
},
|
||||
],
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '远程下拉',
|
||||
dataIndex: 'name4',
|
||||
edit: true,
|
||||
editComponent: 'ApiSelect',
|
||||
editComponentProps: {
|
||||
api: optionsListApi,
|
||||
resultField: 'list',
|
||||
labelField: 'name',
|
||||
valueField: 'id',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '远程下拉树',
|
||||
dataIndex: 'name71',
|
||||
edit: true,
|
||||
editComponent: 'ApiTreeSelect',
|
||||
editRule: false,
|
||||
editComponentProps: {
|
||||
api: treeOptionsListApi,
|
||||
resultField: 'list',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '日期选择',
|
||||
dataIndex: 'date',
|
||||
edit: true,
|
||||
editComponent: 'DatePicker',
|
||||
editComponentProps: {
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
format: 'YYYY-MM-DD',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '时间选择',
|
||||
dataIndex: 'time',
|
||||
edit: true,
|
||||
editComponent: 'TimePicker',
|
||||
editComponentProps: {
|
||||
valueFormat: 'HH:mm',
|
||||
format: 'HH:mm',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '勾选框',
|
||||
dataIndex: 'name5',
|
||||
edit: true,
|
||||
editComponent: 'Checkbox',
|
||||
editValueMap: (value) => {
|
||||
return value ? '是' : '否';
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '开关',
|
||||
dataIndex: 'name6',
|
||||
edit: true,
|
||||
editComponent: 'Switch',
|
||||
editValueMap: (value) => {
|
||||
return value ? '开' : '关';
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext } = useListPage({
|
||||
designScope: 'basic-table-demo',
|
||||
tableProps: {
|
||||
title: '可编辑单元格示例',
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
showIndexColumn: false,
|
||||
bordered: true,
|
||||
showActionColumn: false,
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [registerTable] = tableContext;
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
function handleEditEnd({ record, index, key, value }: Recordable) {
|
||||
console.log(record, index, key, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 模拟将指定数据保存
|
||||
function feakSave({ value, key, id }) {
|
||||
createMessage.loading({
|
||||
content: `正在模拟保存${key}`,
|
||||
key: '_save_fake_data',
|
||||
duration: 0,
|
||||
});
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
if (value === '') {
|
||||
createMessage.error({
|
||||
content: '保存失败:不能为空',
|
||||
key: '_save_fake_data',
|
||||
duration: 2,
|
||||
});
|
||||
resolve(false);
|
||||
} else {
|
||||
createMessage.success({
|
||||
content: `记录${id}的${key}已保存`,
|
||||
key: '_save_fake_data',
|
||||
duration: 2,
|
||||
});
|
||||
resolve(true);
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
async function beforeEditSubmit({ record, index, key, value }) {
|
||||
console.log('单元格数据正在准备提交', { record, index, key, value });
|
||||
return await feakSave({ id: record.id, key, value });
|
||||
}
|
||||
|
||||
function handleEditCancel() {
|
||||
console.log('cancel');
|
||||
}
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
handleEditEnd,
|
||||
handleEditCancel,
|
||||
beforeEditSubmit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,261 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable" @edit-change="onEditChange">
|
||||
<template #action="{ record, column }">
|
||||
<TableAction :actions="createActions(record, column)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { BasicTable, useTable, TableAction, BasicColumn, ActionItem, EditRecordRow } from '/@/components/Table';
|
||||
import { optionsListApi } from '/@/api/demo/select';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { treeOptionsListApi } from '/@/api/demo/tree';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '输入框',
|
||||
dataIndex: 'name',
|
||||
editRow: true,
|
||||
editComponentProps: {
|
||||
prefix: '$',
|
||||
},
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '默认输入状态',
|
||||
dataIndex: 'name7',
|
||||
editRow: true,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '输入框校验',
|
||||
dataIndex: 'name1',
|
||||
editRow: true,
|
||||
align: 'left',
|
||||
// 默认必填校验
|
||||
editRule: true,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '输入框函数校验',
|
||||
dataIndex: 'name2',
|
||||
editRow: true,
|
||||
align: 'right',
|
||||
editRule: async (text) => {
|
||||
if (text === '2') {
|
||||
return '不能输入该值';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '数字输入框',
|
||||
dataIndex: 'id',
|
||||
editRow: true,
|
||||
editRule: true,
|
||||
editComponent: 'InputNumber',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '下拉框',
|
||||
dataIndex: 'name3',
|
||||
editRow: true,
|
||||
editComponent: 'Select',
|
||||
editComponentProps: {
|
||||
options: [
|
||||
{
|
||||
label: 'Option1',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: 'Option2',
|
||||
value: '2',
|
||||
},
|
||||
{
|
||||
label: 'Option3',
|
||||
value: '3',
|
||||
},
|
||||
],
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '远程下拉',
|
||||
dataIndex: 'name4',
|
||||
editRow: true,
|
||||
editComponent: 'ApiSelect',
|
||||
editComponentProps: {
|
||||
api: optionsListApi,
|
||||
resultField: 'list',
|
||||
labelField: 'name',
|
||||
valueField: 'id',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '远程下拉树',
|
||||
dataIndex: 'name8',
|
||||
editRow: true,
|
||||
editComponent: 'ApiTreeSelect',
|
||||
editRule: false,
|
||||
editComponentProps: {
|
||||
api: treeOptionsListApi,
|
||||
resultField: 'list',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '日期选择',
|
||||
dataIndex: 'date',
|
||||
editRow: true,
|
||||
editComponent: 'DatePicker',
|
||||
editComponentProps: {
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
format: 'YYYY-MM-DD',
|
||||
},
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '时间选择',
|
||||
dataIndex: 'time',
|
||||
editRow: true,
|
||||
editComponent: 'TimePicker',
|
||||
editComponentProps: {
|
||||
valueFormat: 'HH:mm',
|
||||
format: 'HH:mm',
|
||||
},
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '勾选框',
|
||||
dataIndex: 'name5',
|
||||
editRow: true,
|
||||
|
||||
editComponent: 'Checkbox',
|
||||
editValueMap: (value) => {
|
||||
return value ? '是' : '否';
|
||||
},
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '开关',
|
||||
dataIndex: 'name6',
|
||||
editRow: true,
|
||||
editComponent: 'Switch',
|
||||
editValueMap: (value) => {
|
||||
return value ? '开' : '关';
|
||||
},
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable, TableAction },
|
||||
setup() {
|
||||
const { createMessage: msg } = useMessage();
|
||||
const currentEditKeyRef = ref('');
|
||||
|
||||
const { tableContext } = useListPage({
|
||||
designScope: 'basic-table-demo',
|
||||
tableProps: {
|
||||
title: '可编辑行示例',
|
||||
titleHelpMessage: ['本例中修改[数字输入框]这一列时,同一行的[远程下拉]列的当前编辑数据也会同步发生改变'],
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
showIndexColumn: false,
|
||||
showTableSetting: true,
|
||||
tableSetting: { fullScreen: true },
|
||||
actionColumn: {
|
||||
width: 160,
|
||||
title: 'Action',
|
||||
dataIndex: 'action',
|
||||
slots: { customRender: 'action' },
|
||||
},
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [registerTable] = tableContext;
|
||||
|
||||
function handleEdit(record: EditRecordRow) {
|
||||
currentEditKeyRef.value = record.key;
|
||||
record.onEdit?.(true);
|
||||
}
|
||||
|
||||
function handleCancel(record: EditRecordRow) {
|
||||
currentEditKeyRef.value = '';
|
||||
record.onEdit?.(false, false);
|
||||
}
|
||||
|
||||
async function handleSave(record: EditRecordRow) {
|
||||
// 校验
|
||||
msg.loading({ content: '正在保存...', duration: 0, key: 'saving' });
|
||||
const valid = await record.onValid?.();
|
||||
if (valid) {
|
||||
try {
|
||||
const data = cloneDeep(record.editValueRefs);
|
||||
console.log(data);
|
||||
//TODO 此处将数据提交给服务器保存
|
||||
// ...
|
||||
// 保存之后提交编辑状态
|
||||
const pass = await record.onEdit?.(false, true);
|
||||
if (pass) {
|
||||
currentEditKeyRef.value = '';
|
||||
}
|
||||
msg.success({ content: '数据已保存', key: 'saving' });
|
||||
} catch (error) {
|
||||
msg.error({ content: '保存失败', key: 'saving' });
|
||||
}
|
||||
} else {
|
||||
msg.error({ content: '请填写正确的数据', key: 'saving' });
|
||||
}
|
||||
}
|
||||
|
||||
function createActions(record: EditRecordRow, column: BasicColumn): ActionItem[] {
|
||||
if (!record.editable) {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
disabled: currentEditKeyRef.value ? currentEditKeyRef.value !== record.key : false,
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
return [
|
||||
{
|
||||
label: '保存',
|
||||
onClick: handleSave.bind(null, record, column),
|
||||
},
|
||||
{
|
||||
label: '取消',
|
||||
popConfirm: {
|
||||
title: '是否取消编辑',
|
||||
confirm: handleCancel.bind(null, record, column),
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function onEditChange({ column, value, record }) {
|
||||
// 本例
|
||||
if (column.dataIndex === 'id') {
|
||||
record.editValueRefs.name4.value = `${value}`;
|
||||
}
|
||||
console.log(column, value, record);
|
||||
}
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
handleEdit,
|
||||
createActions,
|
||||
onEditChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,119 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper
|
||||
title="可展开表格"
|
||||
content="不可与scroll共用。TableAction组件可配置stopButtonPropagation来阻止操作按钮的点击事件冒泡,以便配合Table组件的expandRowByClick"
|
||||
>
|
||||
<BasicTable @register="registerTable">
|
||||
<template #expandedRowRender="{ record }">
|
||||
<span>No: {{ record.no }} </span>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<TableAction
|
||||
stopButtonPropagation
|
||||
:actions="[
|
||||
{
|
||||
label: '删除',
|
||||
icon: 'ic:outline-delete-outline',
|
||||
onClick: handleDelete.bind(null, record),
|
||||
},
|
||||
]"
|
||||
:dropDownActions="[
|
||||
{
|
||||
label: '启用',
|
||||
popConfirm: {
|
||||
title: '是否启用?',
|
||||
confirm: handleOpen.bind(null, record),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable, TableAction, BasicColumn } from '/@/components/Table';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
fixed: 'left',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 150,
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male' },
|
||||
{ text: 'Female', value: 'female' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
defaultHidden: true,
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
dataIndex: 'endTime',
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable, TableAction, PageWrapper },
|
||||
setup() {
|
||||
const { tableContext } = useListPage({
|
||||
designScope: 'basic-table-demo',
|
||||
tableProps: {
|
||||
api: demoListApi,
|
||||
title: '可展开表格演示',
|
||||
titleHelpMessage: ['已启用expandRowByClick', '已启用stopButtonPropagation'],
|
||||
columns: columns,
|
||||
rowKey: 'id',
|
||||
canResize: false,
|
||||
expandRowByClick: true,
|
||||
actionColumn: {
|
||||
width: 160,
|
||||
title: 'Action',
|
||||
dataIndex: 'action',
|
||||
},
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [registerTable] = tableContext;
|
||||
|
||||
function handleDelete(record: Recordable) {
|
||||
console.log('点击了删除', record);
|
||||
}
|
||||
function handleOpen(record: Recordable) {
|
||||
console.log('点击了启用', record);
|
||||
}
|
||||
|
||||
return {
|
||||
registerTable,
|
||||
handleDelete,
|
||||
handleOpen,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,131 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
</template>
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="basic-table-demo" setup>
|
||||
import { ActionItem, BasicColumn, BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
//定义表格列
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 170,
|
||||
align: 'left',
|
||||
resizable: true,
|
||||
sorter: {
|
||||
multiple: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '关键词',
|
||||
dataIndex: 'keyWord',
|
||||
width: 130,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '打卡时间',
|
||||
dataIndex: 'punchTime',
|
||||
width: 140,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '工资',
|
||||
dataIndex: 'salaryMoney',
|
||||
width: 140,
|
||||
resizable: true,
|
||||
sorter: {
|
||||
multiple: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '奖金',
|
||||
dataIndex: 'bonusMoney',
|
||||
width: 140,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
sorter: {
|
||||
multiple: 3,
|
||||
},
|
||||
filters: [
|
||||
{ text: '男', value: '1' },
|
||||
{ text: '女', value: '2' },
|
||||
],
|
||||
customRender: ({ record }) => {
|
||||
return record.sex ? (record.sex == '1' ? '男' : '女') : '';
|
||||
},
|
||||
width: 120,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '生日',
|
||||
dataIndex: 'birthday',
|
||||
width: 120,
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
width: 120,
|
||||
resizable: true,
|
||||
},
|
||||
];
|
||||
|
||||
//ajax请求api接口
|
||||
const demoListApi = (params) => {
|
||||
return defHttp.get({ url: '/test/jeecgDemo/list', params });
|
||||
};
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext, onExportXls, onImportXls } = useListPage({
|
||||
designScope: 'basic-table-demo-filter',
|
||||
tableProps: {
|
||||
title: '表单搜索',
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
showActionColumn: false,
|
||||
useSearchForm: false,
|
||||
},
|
||||
exportConfig: {
|
||||
name: '示例列表',
|
||||
url: '/test/jeecgDemo/exportXls',
|
||||
},
|
||||
importConfig: {
|
||||
url: '/test/jeecgDemo/importExcel',
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [registerTable, { reload }, { rowSelection, selectedRows, selectedRowKeys }] = tableContext;
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record): ActionItem[] {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function handleEdit(record) {
|
||||
console.log(record);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,98 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #action="{ record }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: '删除',
|
||||
icon: 'ic:outline-delete-outline',
|
||||
onClick: handleDelete.bind(null, record),
|
||||
},
|
||||
]"
|
||||
:dropDownActions="[
|
||||
{
|
||||
label: '启用',
|
||||
popConfirm: {
|
||||
title: '是否启用?',
|
||||
confirm: handleOpen.bind(null, record),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
fixed: 'left',
|
||||
width: 280,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 260,
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
width: 200,
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable, TableAction },
|
||||
setup() {
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '固定头和列示例',
|
||||
api: demoListApi,
|
||||
columns: columns,
|
||||
canResize: false,
|
||||
scroll: { y: 200 },
|
||||
actionColumn: {
|
||||
width: 160,
|
||||
title: 'Action',
|
||||
dataIndex: 'action',
|
||||
},
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
|
||||
const [registerTable] = tableContext;
|
||||
function handleDelete(record: Recordable) {
|
||||
console.log('点击了删除', record);
|
||||
}
|
||||
function handleOpen(record: Recordable) {
|
||||
console.log('点击了启用', record);
|
||||
}
|
||||
return {
|
||||
registerTable,
|
||||
handleDelete,
|
||||
handleOpen,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,131 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable" class="components-table-demo-nested">
|
||||
<template #bodyCell="{ column }">
|
||||
<template v-if="column.key === 'operation'">
|
||||
<a>Publish</a>
|
||||
</template>
|
||||
</template>
|
||||
<template #expandedRowRender>
|
||||
<a-table :columns="innerColumns" :data-source="innerData" :pagination="false">
|
||||
<template #bodyCell="{ column }">
|
||||
<template v-if="column.dataIndex === 'state'">
|
||||
<span>
|
||||
<a-badge status="success" />
|
||||
Finished
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'operation'">
|
||||
<span class="table-operation">
|
||||
<a>Pause</a>
|
||||
<a>Stop</a>
|
||||
<a-dropdown>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>Action 1</a-menu-item>
|
||||
<a-menu-item>Action 2</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a> More </a>
|
||||
</a-dropdown>
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicTable } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
|
||||
const columns = [
|
||||
{ title: 'Name', dataIndex: 'name', key: 'name' },
|
||||
{ title: 'Platform', dataIndex: 'platform', key: 'platform' },
|
||||
{ title: 'Version', dataIndex: 'version', key: 'version' },
|
||||
{ title: 'Upgraded', dataIndex: 'upgradeNum', key: 'upgradeNum' },
|
||||
{ title: 'Creator', dataIndex: 'creator', key: 'creator' },
|
||||
{ title: 'Date', dataIndex: 'createdAt', key: 'createdAt' },
|
||||
{ title: 'Action', key: 'operation' },
|
||||
];
|
||||
|
||||
interface DataItem {
|
||||
key: number;
|
||||
name: string;
|
||||
platform: string;
|
||||
version: string;
|
||||
upgradeNum: number;
|
||||
creator: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
const data: DataItem[] = [];
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
data.push({
|
||||
key: i,
|
||||
name: 'Screem',
|
||||
platform: 'iOS',
|
||||
version: '10.3.4.5654',
|
||||
upgradeNum: 500,
|
||||
creator: 'Jack',
|
||||
createdAt: '2014-12-24 23:12:00',
|
||||
});
|
||||
}
|
||||
|
||||
const innerColumns = [
|
||||
{ title: 'Date', dataIndex: 'date', key: 'date' },
|
||||
{ title: 'Name', dataIndex: 'name', key: 'name' },
|
||||
{ title: 'Status', dataIndex: 'state', key: 'state' },
|
||||
{ title: 'Upgrade Status', dataIndex: 'upgradeNum', key: 'upgradeNum' },
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: 'operation',
|
||||
key: 'operation',
|
||||
},
|
||||
];
|
||||
|
||||
interface innerDataItem {
|
||||
key: number;
|
||||
date: string;
|
||||
name: string;
|
||||
upgradeNum: string;
|
||||
}
|
||||
|
||||
const innerData: innerDataItem[] = [];
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
innerData.push({
|
||||
key: i,
|
||||
date: '2014-12-24 23:12:00',
|
||||
name: 'This is production name',
|
||||
upgradeNum: 'Upgraded: 56',
|
||||
});
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '内嵌表格',
|
||||
dataSource: data,
|
||||
columns: columns,
|
||||
showActionColumn: false,
|
||||
rowKey: 'key',
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [registerTable] = tableContext;
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
innerColumns,
|
||||
innerData,
|
||||
registerTable,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,70 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="registerTable" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicColumn, BasicTable, useTable } from '/@/components/Table';
|
||||
|
||||
import { demoListApi } from '/@/api/demo/table';
|
||||
//计算合并表头
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
const [registerTable] = useTable({
|
||||
title: '分组表头示例',
|
||||
api: demoListApi,
|
||||
columns: getMergeHeaderColumns(),
|
||||
bordered: true,
|
||||
useSearchForm: false,
|
||||
});
|
||||
|
||||
function getMergeHeaderColumns(): BasicColumn[] {
|
||||
return [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
width: 120,
|
||||
children: [
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
key: 'no',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'beginTime',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
}
|
||||
return {
|
||||
registerTable,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,144 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable">
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="basic-table-demo" setup>
|
||||
import { ActionItem, BasicColumn, BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
//定义表格列
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
customCell: (record, index, column) => ({
|
||||
colSpan: index < 4 ? 1 : 5,
|
||||
}),
|
||||
customRender: ({ text, record, index, column }) => {
|
||||
return index < 4 ? text : `${record.name}/${record.age}/${record.address}/${record.phone}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
customCell: (record, index, column) => {
|
||||
if (index == 4) {
|
||||
return { colSpan: 0 };
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '家庭住址',
|
||||
dataIndex: 'address',
|
||||
customCell: (record, index, column) => {
|
||||
if (index == 4) {
|
||||
return { colSpan: 0 };
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '联系电话',
|
||||
colSpan: 2,
|
||||
dataIndex: 'tel',
|
||||
customCell: (record, index, column) => {
|
||||
if (index === 2) {
|
||||
return { rowSpan: 2 };
|
||||
}
|
||||
if (index === 3) {
|
||||
return { rowSpan: 0 };
|
||||
}
|
||||
if (index === 4) {
|
||||
return { colSpan: 0 };
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Phone',
|
||||
colSpan: 0,
|
||||
dataIndex: 'phone',
|
||||
customCell: (record, index, column) => {
|
||||
if (index === 4) {
|
||||
return { colSpan: 0 };
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext } = useListPage({
|
||||
designScope: 'basic-table-demo',
|
||||
tableProps: {
|
||||
title: '合并行列',
|
||||
dataSource: [
|
||||
{
|
||||
key: '1',
|
||||
name: '尹嘉乐',
|
||||
age: 32,
|
||||
tel: '0319-5972018',
|
||||
phone: 17600080009,
|
||||
address: '北京市昌平区',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: '龙佳钰',
|
||||
tel: '0319-5972018',
|
||||
phone: 17600060007,
|
||||
age: 42,
|
||||
address: '北京市海淀区',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: '贺泽惠',
|
||||
age: 32,
|
||||
tel: '0319-5972018',
|
||||
phone: 17600040005,
|
||||
address: '北京市门头沟区',
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
name: '沈勇',
|
||||
age: 18,
|
||||
tel: '0319-5972018',
|
||||
phone: 17600010003,
|
||||
address: '北京市朝阳区',
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
name: '白佳毅',
|
||||
age: 18,
|
||||
tel: '0319-5972018',
|
||||
phone: 17600010002,
|
||||
address: '北京市丰台区',
|
||||
},
|
||||
],
|
||||
columns: columns,
|
||||
showActionColumn: false,
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [registerTable] = tableContext;
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record): ActionItem[] {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function handleEdit(record) {
|
||||
console.log(record);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,139 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-alert
|
||||
message="多表格实例测试 (Issue #8792 修复)"
|
||||
description="此示例演示父子组件同时使用 BasicTable 时,列配置、列宽调整等功能正常工作,两个表格实例互不干扰"
|
||||
type="info"
|
||||
show-icon
|
||||
class="mb-4"
|
||||
/>
|
||||
|
||||
<a-card title="父组件的表格" class="mb-4">
|
||||
<BasicTable
|
||||
@register="registerParentTable"
|
||||
:columns="parentColumns"
|
||||
:dataSource="parentData"
|
||||
:pagination="false"
|
||||
showTableSetting
|
||||
:canResize="false"
|
||||
>
|
||||
<template #toolbar>
|
||||
<a-button type="primary" @click="testParentTable">测试父表格</a-button>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</a-card>
|
||||
|
||||
<a-card title="子组件的表格">
|
||||
<BasicTable
|
||||
@register="registerChildTable"
|
||||
:columns="childColumns"
|
||||
:dataSource="childData"
|
||||
:pagination="false"
|
||||
showTableSetting
|
||||
:canResize="false"
|
||||
>
|
||||
<template #toolbar>
|
||||
<a-button type="primary" @click="testChildTable">测试子表格</a-button>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
// 父表格配置
|
||||
const parentColumns: BasicColumn[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '父表格-姓名',
|
||||
dataIndex: 'name',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '父表格-年龄',
|
||||
dataIndex: 'age',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '父表格-地址',
|
||||
dataIndex: 'address',
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
|
||||
const parentData = ref([
|
||||
{ id: 1, name: '父表格-张三', age: 25, address: '北京市朝阳区' },
|
||||
{ id: 2, name: '父表格-李四', age: 30, address: '上海市浦东新区' },
|
||||
{ id: 3, name: '父表格-王五', age: 28, address: '广州市天河区' },
|
||||
]);
|
||||
|
||||
const [registerParentTable, { getColumns: getParentColumns }] = useTable({
|
||||
columns: parentColumns,
|
||||
dataSource: parentData.value,
|
||||
});
|
||||
|
||||
// 子表格配置
|
||||
const childColumns: BasicColumn[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '子表格-产品名称',
|
||||
dataIndex: 'product',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '子表格-价格',
|
||||
dataIndex: 'price',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '子表格-库存',
|
||||
dataIndex: 'stock',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '子表格-分类',
|
||||
dataIndex: 'category',
|
||||
width: 150,
|
||||
},
|
||||
];
|
||||
|
||||
const childData = ref([
|
||||
{ id: 1, product: '子表格-商品A', price: 99, stock: 100, category: '电子产品' },
|
||||
{ id: 2, product: '子表格-商品B', price: 199, stock: 50, category: '家居用品' },
|
||||
{ id: 3, product: '子表格-商品C', price: 299, stock: 30, category: '服装鞋包' },
|
||||
]);
|
||||
|
||||
const [registerChildTable, { getColumns: getChildColumns }] = useTable({
|
||||
columns: childColumns,
|
||||
dataSource: childData.value,
|
||||
});
|
||||
|
||||
function testParentTable() {
|
||||
const cols = getParentColumns();
|
||||
createMessage.success(`父表格列数: ${cols.length},请查看控制台`);
|
||||
console.log('父表格列配置:', cols);
|
||||
}
|
||||
|
||||
function testChildTable() {
|
||||
const cols = getChildColumns();
|
||||
createMessage.success(`子表格列数: ${cols.length},请查看控制台`);
|
||||
console.log('子表格列配置:', cols);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
@ -1,80 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="basic-table-demo" setup>
|
||||
import { BasicColumn, BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
//定义表格列
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
resizable: true,
|
||||
},
|
||||
{
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
},
|
||||
{
|
||||
title: '住址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
},
|
||||
];
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext } = useListPage({
|
||||
designScope: 'basic-table-demo',
|
||||
tableProps: {
|
||||
title: '可选择表格',
|
||||
dataSource: [
|
||||
{
|
||||
id: '1',
|
||||
name: '胡歌',
|
||||
age: 32,
|
||||
address: '朝阳区林萃路1号',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '刘诗诗',
|
||||
age: 32,
|
||||
address: '昌平区白沙路1号',
|
||||
},
|
||||
],
|
||||
columns: columns,
|
||||
rowSelection: { type: 'checkbox' }, //默认是 checkbox 多选,可以设置成 radio 单选
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [registerTable, { reload }, { rowSelection, selectedRows, selectedRowKeys }] = tableContext;
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record): ActionItem[] {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function handleEdit(record) {
|
||||
console.log(record);
|
||||
console.log(selectedRows.value);
|
||||
console.log(selectedRowKeys.value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -1,124 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<BasicTable @register="register">
|
||||
<template #toolbar>
|
||||
<a-button type="primary" @click="expandAll">展开全部</a-button>
|
||||
<a-button type="primary" @click="collapseAll">折叠全部</a-button>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicColumn, BasicTable } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
fixed: 'left',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
width: 150,
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male' },
|
||||
{ text: 'Female', value: 'female' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'no',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
defaultHidden: true,
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
dataIndex: 'beginTime',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
width: 150,
|
||||
sorter: true,
|
||||
dataIndex: 'endTime',
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '树形表格',
|
||||
isTreeTable: true,
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
getCheckboxProps(record: Recordable) {
|
||||
// Demo: 第一行(id为0)的选择框禁用
|
||||
if (record.id === '0') {
|
||||
return { disabled: true };
|
||||
} else {
|
||||
return { disabled: false };
|
||||
}
|
||||
},
|
||||
},
|
||||
columns: columns,
|
||||
dataSource: getTreeTableData(),
|
||||
rowKey: 'id',
|
||||
useSearchForm: false,
|
||||
},
|
||||
});
|
||||
//注册table数据
|
||||
const [register, { expandAll, collapseAll }] = tableContext;
|
||||
function getTreeTableData() {
|
||||
const data: any = (() => {
|
||||
const arr: any = [];
|
||||
for (let index = 0; index < 40; index++) {
|
||||
arr.push({
|
||||
id: `${index}`,
|
||||
name: 'John Brown',
|
||||
age: `1${index}`,
|
||||
no: `${index + 10}`,
|
||||
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||
beginTime: new Date().toLocaleString(),
|
||||
endTime: new Date().toLocaleString(),
|
||||
children: [
|
||||
{
|
||||
id: `l2-${index}`,
|
||||
name: 'John Brown',
|
||||
age: `1${index}`,
|
||||
no: `${index + 10}`,
|
||||
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||
beginTime: new Date().toLocaleString(),
|
||||
endTime: new Date().toLocaleString(),
|
||||
},
|
||||
{
|
||||
id: `l3-${index}`,
|
||||
name: 'John Mary',
|
||||
age: `1${index}`,
|
||||
no: `${index + 10}`,
|
||||
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||
beginTime: new Date().toLocaleString(),
|
||||
endTime: new Date().toLocaleString(),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
})();
|
||||
|
||||
return data;
|
||||
}
|
||||
return { register, expandAll, collapseAll };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,16 +0,0 @@
|
||||
export { default as AuthColumnDemo } from './AuthColumnDemo.vue';
|
||||
export { default as BasicTableBorder } from './BasicTableBorder.vue';
|
||||
export { default as BasicTableDemo } from './BasicTableDemo.vue';
|
||||
export { default as BasicTableDemoAjax } from './BasicTableDemoAjax.vue';
|
||||
export { default as CustomerCellDemo } from './CustomerCellDemo.vue';
|
||||
export { default as EditCellTableDemo } from './EditCellTableDemo.vue';
|
||||
export { default as EditRowTableDemo } from './EditRowTableDemo.vue';
|
||||
export { default as ExpandTableDemo } from './ExpandTableDemo.vue';
|
||||
export { default as ExportTableDemo } from './ExportTableDemo.vue';
|
||||
export { default as FixedHeaderColumn } from './FixedHeaderColumn.vue';
|
||||
export { default as InnerTableDemo } from './InnerTableDemo.vue';
|
||||
export { default as MergeHeaderDemo } from './MergeHeaderDemo.vue';
|
||||
export { default as MergeTableDemo } from './MergeTableDemo.vue';
|
||||
export { default as SelectTableDemo } from './SelectTableDemo.vue';
|
||||
export { default as TreeTableDemo } from './TreeTableDemo.vue';
|
||||
export { default as MultipleTableDemo } from './MultipleTableDemo.vue';
|
||||
@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<div class="p-4">
|
||||
<a-card :bordered="false" style="height: 100%">
|
||||
<a-tabs v-model:activeKey="activeKey" @change="tabChange">
|
||||
<a-tab-pane :key="item.key" :tab="item.label" v-for="item in compList" />
|
||||
</a-tabs>
|
||||
<component :is="currentComponent" />
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, computed } from 'vue';
|
||||
import {
|
||||
AuthColumnDemo,
|
||||
BasicTableBorder,
|
||||
BasicTableDemo,
|
||||
BasicTableDemoAjax,
|
||||
CustomerCellDemo,
|
||||
EditCellTableDemo,
|
||||
EditRowTableDemo,
|
||||
ExpandTableDemo,
|
||||
ExportTableDemo,
|
||||
FixedHeaderColumn,
|
||||
InnerTableDemo,
|
||||
MergeHeaderDemo,
|
||||
MergeTableDemo,
|
||||
SelectTableDemo,
|
||||
TreeTableDemo,
|
||||
MultipleTableDemo,
|
||||
} from './index';
|
||||
export default defineComponent({
|
||||
name: 'document-table-demo',
|
||||
components: {
|
||||
AuthColumnDemo,
|
||||
BasicTableBorder,
|
||||
BasicTableDemo,
|
||||
BasicTableDemoAjax,
|
||||
CustomerCellDemo,
|
||||
EditCellTableDemo,
|
||||
EditRowTableDemo,
|
||||
ExpandTableDemo,
|
||||
ExportTableDemo,
|
||||
FixedHeaderColumn,
|
||||
InnerTableDemo,
|
||||
MergeHeaderDemo,
|
||||
MergeTableDemo,
|
||||
SelectTableDemo,
|
||||
TreeTableDemo,
|
||||
MultipleTableDemo,
|
||||
},
|
||||
setup() {
|
||||
//当前选中key
|
||||
const activeKey = ref('BasicTableDemo');
|
||||
//组件集合
|
||||
const compList = ref([
|
||||
{ key: 'BasicTableDemo', label: '基础静态表格' },
|
||||
{ key: 'BasicTableDemoAjax', label: '常规AJAX表格' },
|
||||
{ key: 'BasicTableBorder', label: '边框表格' },
|
||||
{ key: 'CustomerCellDemo', label: '自定义列内容' },
|
||||
{ key: 'EditCellTableDemo', label: '可编辑单元格' },
|
||||
{ key: 'EditRowTableDemo', label: '可编辑行' },
|
||||
{ key: 'ExpandTableDemo', label: '可展开表格' },
|
||||
{ key: 'ExportTableDemo', label: '导入导出' },
|
||||
{ key: 'FixedHeaderColumn', label: '固定头和列示例' },
|
||||
{ key: 'InnerTableDemo', label: '内嵌表格' },
|
||||
{ key: 'MergeHeaderDemo', label: '分组表头示例' },
|
||||
{ key: 'MergeTableDemo', label: '合并行列' },
|
||||
{ key: 'SelectTableDemo', label: '可选择表格' },
|
||||
{ key: 'TreeTableDemo', label: '树形表格' },
|
||||
{ key: 'AuthColumnDemo', label: '权限列设置' },
|
||||
{ key: 'MultipleTableDemo', label: '多表格实例' },
|
||||
]);
|
||||
//当前选中组件
|
||||
const currentComponent = computed(() => {
|
||||
return activeKey.value;
|
||||
});
|
||||
|
||||
//使用component动态切换tab
|
||||
function tabChange(key) {
|
||||
activeKey.value = key;
|
||||
}
|
||||
return {
|
||||
activeKey,
|
||||
currentComponent,
|
||||
tabChange,
|
||||
compList,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,91 +0,0 @@
|
||||
<template>
|
||||
<PageWrapper title="代码编辑器组件示例" contentFullHeight fixedHeight contentBackground>
|
||||
<template #extra>
|
||||
<a-space size="middle">
|
||||
<a-button @click="showData" type="primary">获取数据</a-button>
|
||||
<RadioGroup button-style="solid" v-model:value="modeValue" @change="handleModeChange">
|
||||
<RadioButton value="application/json"> json数据 </RadioButton>
|
||||
<RadioButton value="htmlmixed"> html代码 </RadioButton>
|
||||
<RadioButton value="javascript"> javascript代码 </RadioButton>
|
||||
</RadioGroup>
|
||||
</a-space>
|
||||
</template>
|
||||
<CodeEditor v-model:value="value" :mode="modeValue" />
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { CodeEditor } from '/@/components/CodeEditor';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { Radio, Space, Modal } from 'ant-design-vue';
|
||||
|
||||
const jsonData =
|
||||
'{"name":"BeJson","url":"http://www.xxx.com","page":88,"isNonProfit":true,"address":{"street":"科技园路.","city":"江苏苏州","country":"中国"},"links":[{"name":"Google","url":"http://www.xxx.com"},{"name":"Baidu","url":"http://www.xxx.com"},{"name":"SoSo","url":"http://www.xxx.com"}]}';
|
||||
|
||||
const jsData = `
|
||||
(() => {
|
||||
var htmlRoot = document.getElementById('htmlRoot');
|
||||
var theme = window.localStorage.getItem('__APP__DARK__MODE__');
|
||||
if (htmlRoot && theme) {
|
||||
htmlRoot.setAttribute('data-theme', theme);
|
||||
theme = htmlRoot = null;
|
||||
}
|
||||
})();
|
||||
`;
|
||||
|
||||
const htmlData = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" id="htmlRoot">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||
/>
|
||||
<title><%= title %></title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
export default defineComponent({
|
||||
components: {
|
||||
CodeEditor,
|
||||
PageWrapper,
|
||||
RadioButton: Radio.Button,
|
||||
RadioGroup: Radio.Group,
|
||||
ASpace: Space,
|
||||
},
|
||||
setup() {
|
||||
const modeValue = ref('application/json');
|
||||
const value = ref(jsonData);
|
||||
|
||||
function handleModeChange(e: ChangeEvent) {
|
||||
const mode = e.target.value;
|
||||
if (mode === 'application/json') {
|
||||
value.value = jsonData;
|
||||
return;
|
||||
}
|
||||
if (mode === 'htmlmixed') {
|
||||
value.value = htmlData;
|
||||
return;
|
||||
}
|
||||
if (mode === 'javascript') {
|
||||
value.value = jsData;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function showData() {
|
||||
Modal.info({ title: '编辑器当前值', content: value.value });
|
||||
}
|
||||
|
||||
return { value, modeValue, handleModeChange, showData };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user