移除废弃文件

This commit is contained in:
zjl 2024-12-14 13:35:34 +08:00
parent 37c6502440
commit 69d66b0a17
48 changed files with 14 additions and 5764 deletions

View File

@ -1,705 +1 @@
# CHANGELOG
## Pending
- 💎 优化 `搜索页面` 跳转以及显示问题
## 2.5.0
- 🌟 新增 `BasicTable` 组件 可通过 `immediate` 参数,手动控制加载数据
- 💎 升级 `axios``1.7.2` 采用 `AbortController` 取消请求的方案
- 💎 优化 调整 `vite/client` 的加载方式
- 💎 优化 `BasicColumn` 类型,支持泛型传入
- 🐞 修复 `BasicTable` 切换页数量,未重置勾选数据
- `依赖升级`
## 2.4.4
- 🌟 新增 `深色主题` 切换组件,并在顶部右侧展示
- 🌟 新增 `深色主题` 切换过度样式
- 💎 优化 `多页签` 过度样式
- 💎 优化 `code` 类型定义
- 💎 升级 `vite``5.x` 版本
- `依赖升级`
## 2.4.3
- 💎 优化 `BasicSelect` 组件逻辑,支持响应式 `options`
- 💎 优化 `BasicColumn` 类型定义
- `依赖升级`
## 2.4.2
- 💎 优化 `defineComponent` 语法 为 `setup`
- `依赖升级`
## 2.4.1
- 🌟 新增 `v-debounce` 全局指令
- 🌟 新增 `v-throttle` 全局指令
- 💎 优化 `横向菜单` 显示内容,支持收起溢出的菜单
- `依赖升级`
## 2.4.0
- 🌟 新增 `BasicForm` 支持 `validate` 方法单独验证
- 💎 优化 `BasicForm` 提交按钮加载效果
- 💎 优化 `setLoadingSub` 改名为 `setLoading`
- 🐞 修复 `菜单折叠后` 层级问题
- 🐞 修复 `BasicTable` 使用插槽报错问题
- 🌟 新增 `BasicTable` 导出 `setLoading`
- 🌟 新增 `TableSelect` 结合 `Form` 组件使用示例
- 🌟 新增 `TableSelect` 导出 `getTableRef``updateTableSelectedKeys` 方法
- 🐞 修复 `多页签` 异常初始化
- 🐞 修复 `面包屑` 跳转警告
- `依赖升级`
## 2.3.9 (2023-07-21)
- 🐞 修复 `getTreeValues` 方法
- 🐞 修复 `搜索页面` 跳转异常
- 🌟 新增 `TableSelect` 支持 `formValues` 配置查询表单参数
- 🌟 新增 `BasicForm` 支持 `isEnterSubmit` 配置,监听回车事件提交
- `依赖升级`
## 2.3.8 (2023-06-03)
- 🌟 新增 `BasicForm` 支持 `valueFormat` 特性
- 💎 优化 `useECharts` 监听菜单收缩变化
- `依赖升级`
## 2.3.7 (2023-04-26)
- 🌟 新增 `BasicForm` 支持 `ImageUpload` 组件
- 🌟 新增 `BasicTable` 支持 `helpMessage` 配置
- 🐞 修复 `PageWrapper` 横向菜单宽度异常
- 💎 优化 `Code And TypeScript`
- `依赖升级`
## 2.3.6 (2023-03-23)
- 🌟 新增 `sendFormData` `get` `put` `delete` 请求方法
- 🌟 新增 `权限判断` 示例页面,功能示例>权限判断
- 🌟 新增 `Authority` 全局注册权限判断组件
- 💎 优化 `hasPermission` 权限判断方法,兼容两种格式
- 🐞 修复 `BasicTable` 分页异常判断逻辑
- 🐞 修复 `顶部拆分菜单` 当只有顶级菜单时 `ui` 显示异常
- `依赖升级`
## 2.3.5 (2023-02-02)
- 🌟 新增 `项目配置` 开关
- 🌟 新增 `添加角色` 页面模板
- 🌟 新增 `BasicForm` 支持 `setSchema` 方法
- `依赖升级`
## 2.3.4 (2022-12-23)
- 🌟 新增 `菜单管理2` 页面,用表格展示
- 🐞 修复 `pinia 失去响应式`
- 🐞 修复 `getTreeAll` 方法错误
- `依赖升级`
## 2.3.3 (2022-12-12)
- 🌟 新增 `env.test` 环境打包配置
- 🌟 新增 `rollup-plugin-visualizer` 打包分析插件支持
- 🌟 增强 `menuSetting` 配置灵活性
- 💎 移除 `BasicForm` 创建 `placeholder` 中文提示
- `依赖升级`
## 2.3.2 (2022-10-12)
## Breaking Changes
- 🌟 `BasicForm` 变更 `submit` 方法返回 `values` 整个表单值对象
## Feats
- 🌟 `BasicForm` 增强 `field` 参数支持 `a.b.c` 语法
- 🌟 `BasicModal` 优化 嵌套弹窗,支持拖拽
- `依赖升级`
## 2.3.1 (2022-09-13)
- 🌟 升级 `vite` 支持 `3.x`
- 💎 重构 `TableSelect` 组件,优化单选,分页多选
- 🐞 修复 `BasicUpload` 组件,图片回显问题
- `依赖升级`
## 2.3.0 (2022-08-28)
- 💎 升级 `naiveui v2.32.2`
- 💎 优化 `类型导入` 错误
- `依赖升级`
## 2.2.9 (2022-08-02)
- 💎 优化 `BasicColumn` 类型定义
- 🐞 修复 `修复ts类型` 错误
- `依赖升级`
## 2.2.8 (2022-07-18)
- 🌟 新增 `BasicForm` 支持 `setSchema` 方法
- 🌟 新增 `BasicSelect` 取消 `request` 必传,支持直接传入 `options`
- 🌟 新增 `TableSetting` 支持 `宽度配置` 且支持最大高度滚动
- 🐞 修复 `网络请求异常` 弹窗按钮背景色异常
- `依赖升级`
## 2.2.7 (2022-07-09)
- 🌟 新增 `meta.documentTitle` 网页标题 优先 title 字段
- 🌟 新增 `meta.title` 支持定制 `Render` `多页签` `面包屑` 同步渲染
- 🌟 新增 `meta.authEvery` 是否验证每一个权限都包含
- 🌟 新增 `basicModal` 支持 `prefixFooter` `centerFooter` `suffixFooter` 插槽,用于定制其他元素
- 🌟 新增 `basicModal` 导出 `handleSubmit` 方法
- `依赖升级`
## 2.2.6 (2022-07-01)
- 🌟 新增 `meta.tagView` 配置,是否显示在多页签中
- 🌟 新增 `meta.breadcrumbView` 配置,是否显示在面包屑中
- 🌟 新增 `TableImg` 组件,可在外部使用
- 🌟 新增 `Authority` 权限控制组件
- 🐞 修复 `useDialog` 方法参数定义
- `依赖升级`
## 2.2.5 (2022-06-20)
- 🌟 新增 `tableSelect` 组件支持 `v-model`
- 🌟 新增 `Region` 支持配置 `labelField``valueField` 属性
- 🐞 修复 `activeMenu` 路由配置,刷新浏览器之后失效
- `依赖升级`
## 2.2.4 (2022-06-10)
### ✨ 新增功能
- 新增 `BasicTable` 支持 `autoScrollX` 属性,用于自动计算 `columns` 总和
- 新增 `BasicTable` 表格列支持 `draggable` 配置是可拖拽
- 新增 `useDialog` `useLoadingBar` `useMessage` 可在 `setup` 外使用
- `依赖升级`
### 🐛 Bug Fixes
- 修复 `URL` 正则表达式错误
- 修复 `useECharts` 报错和暗色模式问题
### 💎 优化
- 移除 `挂载` window 写法
- 移除 `额外挂载` appProvider
## 2.2.3 (2022-05-25)
### ✨ 新增功能
- 新增 `BasicTable` 导出 `getTableRef` 方法,用于调用组件原生事件
- 新增 `basicModal` 操作按钮 `showAction` 可控制是否显示底部按钮
- `依赖升级`
### ✨ 新增示例
- 新增 `BasicForm` 结合 `表格选择器` 示例
- 更新 `README.md` 说明
### 💎 优化
- 优化 `组件参数` ts 类型定义
- 优化 `上传组件` 样式错位
## 2.2.2 (2022-04-29)
### ✨ 新增功能
- 新增 `BasicTable` 拖拽列 `columns-change` 方法
- 新增 `BasicForm` 支持 `BasicSelect` 组件,示例在:组件-表单-基础使用
- 新增 `BasicTable` 日期编辑,新增格式化示例,示例在:组件-表格-单元格编辑
- `依赖升级`
## 2.2.1 (2022-04-19)
### ✨ 新增功能
- 新增 `表格选择器` 组件
- 新增 `BasicTable` 设置选中行 `setCheckedRowKeys` 方法
### 🐛 Bug Fixes
- 修复 `开发环境` 运行控制台错误提示
### 💻 新增页面
- 新增 `表格选择器` 示例
- `依赖升级`
## 2.2.0 (2022-03-23)
### ✨ 新增功能
- 新增 `多级菜单缓存`
- `依赖升级`
### 💻 新增页面
- 新增 `多级菜单缓存`
- `依赖升级`
### 🐛 Bug Fixes
- 修复 `BasicForm` 隐藏表单,存在占位问题
## 2.1.9 (2022-02-18)
### 🐛 Bug Fixes
- 修复 `BasicUpload` 组件,回显问题
- 修复 `BasicForm` 组件 `collapsed` 无效
- 修复 `表格编辑` 时间格式化异常 [#92](https://github.com/jekip/naive-ui-admin/issues/92)
## 2.1.8 (2022-01-26)
### 💎 功能优化
- 优化 `BasicForm` 导出操作方法
### ✨ 新增功能
- 新增 `basicModal` 动态创建 `id` 支持嵌套弹窗拖动
- 新增 `BasicTable` 表格查询展开收起,配合 `form` 表单
- 新增 `BasicTable` 选中行 `alert` 提示,可配置开关
- 新增 `BasicTable` `tableSetting` 配置新增 `query` 字段
- 新增 `多页签` 状态设置,特定场景,可实现二次确认提示是否关闭(参考:功能示例->多页签操作)
- `依赖升级`
## 2.1.7 (2022-01-11)
### 💎 功能优化
- 优化 `::v-deep` 修改为 `:deep`
- 优化 `页面ts类型`
- 优化 `表格单元格编辑`
### 🐛 问题修复
- 移除 `引导页示例`
- 修复 `css变量前缀` 和UI组件库不一致
### ✨ 新增功能
- 新增 `Tailwindcss 3.x` 移除 `windicss`
- 新增 `项目配置` 悬浮入口
- `依赖升级`
## 2.1.6 (2021-12-30)
### 🐛 Bug Fixes
- 修复 `路由history跳转锚点` 多标签重复创建问题
- 变更 `多标签操作` `setTitle` 方法,传 `fullPath` 路径(依然存在缺陷)
### ✨ Features
- 新增 `菜单权限-FIXED模式` 随机(普通管理员/超级管理员)角色权限演示
- 新增 `菜单权限-BACK模式` 随机(普通管理员/超级管理员)角色权限演示
- 说明 `超级管理员` 拥有 `主控台、列表页面` 权限,`普通管理员` 拥有 `主控台` 权限,可退出登录,或者刷新页面测试
- 测试 `退出登录>重新登录` 或者 `刷新页面` 查看效果
- `依赖升级`
## 2.1.5 (2021-12-13)
### 🐛 Bug Fixes
- 修复 `BasicTable` 选择行与列配置拖拽异常
- 修复 `BasicTable` 分页总数,无法响应式
- 修复 `Axios` api地址拼接异常
### ✨ Features
- 破坏 `Axios` 取消默认导出 `http` 可支持多个请求导出
- 搜索 `import http from '@/utils/http/axios'` 替换为 `import { http } from '@/utils/http/axios`
- `依赖升级`
## 2.1.4 (2021-11-25)
### 🐛 Bug Fixes
- 修复 `BasicTable` 自适应高度问题
- 破坏 `meta.alwaysShow` 取消路由自动计算根路由特性
### ✨ Features
- 新增 `BasicTable` 斑马纹开关配置
- 新增 `BasicTable` 分页配置,默认显示总条数,不需要的地方可单独重置
- 新增 `useTabs` 暴露 `closeCurrent``setTitle` 方法,用于外部页面操作多页签
- 新增 `功能示例->多页签操作示例`
## 2.1.3 (2021-11-23)
### 🐛 Bug Fixes
- 修复 `ActionItem` 类型定义问题
- 修复 `BasicForm` 自定义提交逻辑,按钮一直处于 loading
### ✨ Features
- 新增 `BasicForm.setLoadingSub` 方法
- `依赖升级`
## 2.1.2 (2021-11-18)
### 🐛 Bug Fixes
- 修复 `锁屏界面` 黑暗主题适配问题
- 修复 `登录页面` 异常情况,按钮一直处于 loading
- 修复 `顶部混合菜单` 一级菜单,内容区域布局问题
- 修复 `BasicSelect` 存储 `localStorage` 空白key
- 修复 `多标签``router.push` 带上 `query` 参数报错
### ✨ Features
- 新增 `按需引入NaiveUi并自动创建.d.ts声明` 可获得代码提示和类型检查
## 2.1.1 (2021-11-15)
### ✨ Features
- 优化 `骨架结构布局` 破坏性调整,按需更新(建议是升级)
- 新增 `侧栏是否固定配置项`
- 新增 `BasicTable` 选中行内部维护,新增 `restCheckedRowKeys``checked-row-change` 方法
- `依赖升级`
## 2.1.0 (2021-11-11)
### ✨ Features
- 优化 `加载图标`
- 优化 `顶部分割菜单`
- 新增 `表格全屏`
- 新增 `内容页全屏`
## 2.0.9 (2021-11-05)
### 🐛 Bug Fixes
- 优化 `页面卡片间距``mt-3` 统一
### ✨ Features
- 引入 `windicss` 代替 `tailwindcss` 提高开发效率
- 引入 `pnpm` 代替 `yarn` 升级方法,删除 `node_modules` 运行 pnpm install
- `依赖升级`
## 2.0.8 (2021-11-03)
### 🐛 Bug Fixes
- 修复 `表格编辑` 事件穿透问题
- 修复 `切换全屏` 菜单展开问题,取消自动展开特性
- 修复 `切换全屏` 图标和提示语问题
- 还原 `tailwindcss2.x` 默认样式存在问题
### ✨ Features
- 新增 `BasicTable` 表格设置工具栏可配置
## 2.0.7 (2021-11-02)
### 🐛 Bug Fixes
- 修复 `多标签` 样式优化
- 修复 `多标签缓存设置` 关闭标签,清除缓存
- 修复 `BasicTable` 操作刷新参数异常
- 修复 `深色模式` 菜单选中色无法切换问题
### ✨ Features
- 新增 `多标签关闭` 清除关闭页面缓存特性
- 破坏 `tailwindcss升级3.x` 移除导入的默认样式
- `依赖升级`
## 2.0.6 (2021-10-25)
### ✨ Features
- `深色主题`优化滚动条样式
- `BasicTable.actionColumn` 操作组件配置增强,支持`图标,大小`
- `BasicTable.actionColumn` 新增`dropDownProps`更多按钮组件,支持配置,和 `actionColumn一致`
- `BasicTable` 组件新增`updateTableDataRecord``deleteTableDataRecord``getColumns``setColumns`方法
- `BasicForm.schemas` 新增`hidden`,配置隐藏域表单,可配合`defaultValue`设置默认值,常用于编辑
## 2.0.5 (2021-10-14)
- 移除`rxjs`依赖和相关文件
- 修复`面包屑`显示隐藏路由
- 修复`多标签`关闭当前页判断不准确
- 修复`多标签`跳转路由参数丢失
- 修复`路由带参`路由相同,参数不同缓存无效
- 修复`BasicTable`组件编辑行`switch`组件默认值不生效
### ✨ Features
- 新增`useGo`和`useRedo`路由跳转方法
- `BasicForm`组件提交按钮loading 动画状态优化
- `BasicTable`组件重构为`script setup`语法
- `BasicTable`组件导出`updateTableData``setTableData``getDataSource`方法
- `依赖升级`
## 2.0.4 (2021-10-09)
### 🐛 Bug Fixes
- 修复`富文本`默认值不生效问题
- 修复`多标签`无法及时更新文字问题
- 修复`BasicTable`组件配置默认分页数量不生效问题
- 优化`刷新功能`面包屑闪现`Redirect`路由地址问题
- 优化`axios拦截器`中无法使用DialogMessage等提示性质组件
### ✨ Features
- `独立精简版分支`
## 2.0.3 (2021-09-28)
### 🐛 Bug Fixes
- 修复`深色主题`顶部右侧搜索组件和部分页面布局不适配问题
- 修复`ts类型定义`完善
### ✨ Features
- `多标签`组件交互重写更加人性化配置和交互
- `BasicTable`组件支持dataSource纯表格数据 非 request 加载情况
- `BasicTable`组件新增`redoHeight`重新计算表格高度方法
- `BasicForm`组件新增`advanced`展开收起回调方法
- `依赖升级`
## 2.0.2 (2021-09-24)
### 🐛 Bug Fixes
- 修复`多标签`关闭左右侧,关闭全部不准确问题
- 修复`多标签切换开关`内容区域间距问题
- 修复`权限判断`hooks 中方法判断问题
- 修复`顶部混合菜单`会受左侧菜单收缩效果影响问题
### ✨ Features
- `BasicTable`组件新增,`restReload`方法(重置页码刷新)
- `依赖升级`
## 2.0.1 (2021-09-20)
### 🐛 Bug Fixes
- 修复`BasicTable`配置选择项异常
### ✨ Features
- 新增`PageWrapper`布局组件
- 新增`PageFooter`布局组件
- 新增`BasicTable->actionColumn`配置增强,可设置`popconfirm`二次确认
- 优化`BasicTable`全选反选部分选择效果
- 移除`BasicTable`配置里面勾选列功能,用处不大,增加不必要代码量
- 新增`高级表单`布局页面
- 依赖升级
## 2.0.0 (2021-09-15)
## 💄 破坏性更新
### ✨ Features
🔥🔥🔥 代码重构 `script setup` 语法源码更加易读性能更优ts 类型更加全面
#### 💻 页面
- 🌟 `全新登录/注册页面`
- 🌟 `全新主控台页面`
- 🌟 `用户管理`
- 🌟 `字典管理`
#### ✨ 优化
- 🌟 `主结构布局优化`
- 🌟 `表格主从结构`
- 🌟 `多标签页可关闭左右侧标签`
- 🌟 `多标签页可自动滚动到当前页面`
- 🌟 `弹窗组件拖拽可配置`
#### 🏷️ 功能
- 🌟 `右键菜单`
- 🌟 `文件下载`
- 🌟 `Excel导出`
- 🌟 `剪贴板`
- 🌟 `打印`
- 🌟 `滚动条`
- 🌟 `消息通知`
- 🌟 `主控台图表示例`
- 🌟 `引导`
- 🌟 `修改密码`
- 🌟 `固定主体区域可配置`
- 🌟 `pinia 持久化存储`
#### 📦 组件
- 🌟 `省市区`
- 🌟 `顶部搜索`
- 🌟 `二维码`
- 🌟 `密码强度`
- 🌟 `图片裁剪,支持圆形矩形`
- 🌟 `选择器增强,支持缓存`
# CHANGELOG
## 1.5.5 (2021-08-14)
### 🐛 Bug Fixes
- 修复路由只存在一个子路由,图标不显示问题
- UI样式美化
- ### ✨ Features
- 支持 Vue 3.2.x
- 代码全部按 `script setup` 语法重写完成80%
- 新增 `回到顶部` 功能
- 新增 `拖拽` 示例页面
- 新增 `富文本` 组件
- 新增 `路由切换动画` 可在项目设置切换
- 依赖升级
# CHANGELOG
## 1.5.4 (2021-08-10)
### 🐛 Bug Fixes
- `暗色模式下多页签背景问题 ` 合并 [#23](https://github.com/jekip/naive-ui-admin/pull/23)
感谢 [@Dishone](https://github.com/Dishone)
- `表格设置列重复添加action列样式错乱问题` 合并 [#24](https://github.com/jekip/naive-ui-admin/pull/24)
感谢 [@CasbaL](https://github.com/CasbaL)
- ### ✨ Features
- 新增 `路由支持(内联外部地址)`配置
- 新增 `顶部菜单` logo展示 -(破坏性更新)
- 优化 `动态路由配置` 取消`constantRouterComponents.ts`,中组件映射配置,更名为 `router-icons.ts`
- 优化 `admin_info接口结构`roles 更名为permissionsroles.roleName更名为label
- 优化 多级路由,当没有配置`redirect`时,默认为第一个子路由,配置则优先按配置
- 依赖升级
# 1.5.3 (2021-08-09)
### 🐛 Bug Fixes
- 修复顶部菜单,选中联动
- 修复混合菜单模式,切换其他模式菜单未重置
- 实例基础列表,和表格组件实例,开启横向滚动特性
- `naiveui` 升级成最新版
- ### ✨ Features
- table组件默认开启 `ellipsis` 特性
# 1.5.2 (2021-08-06)
### 🐛 Bug Fixes
- 修复已知bug
- ### ✨ Features
- 新增 `混合菜单模式`
- 新增 `根路由`
- 新增 `关于` 根路由示例页面
- 文档同步更新,组件和示例
# 1.5.1 (2021-08-05)
### 🐛 Bug Fixes
- 修复windows系统获取项目换行符问题
- 修复表格分页计算问题 [@Chika99](https://github.com/Chika99)
- 修复锁屏样式自适应问题 [@Chika99](https://github.com/Chika99)
- 依赖 dayjs 移除用date-fns和UI框架底层保持一致
- 修复已知bug
- ### ✨ Features
- 新增 `baseForm` 组件,和`基础``useForm`使用方式
- 新增 `baseModal`,组件,和 `useForm`使用方式
- 新增`子菜单` new Tag标签
- 菜单支持 `根路由`配置
# 1.5.0 (2021-07-30)
### 🐛 Bug Fixes
- 修复表格列配置,拖拽时最后的操作列重复增加
- 多标签页交互优化
- ### ✨ Features
- `项目文档`已上线
- `Application`组件加载机制优化解决路由守卫Axios中可使用DialogMessage 等之类组件
- `BasicTable` 组件新增`高度自适应``单元格编辑``整行编辑` 特性
- `nprogress` 移除,用 `Loading Bar`代替
- 打包支持`gzip``brotli` 压缩
- 新增代理`VITE_PROXY`配置
- 路由菜单,支持多级菜单
- 依赖升级
- 本次更新,有破坏性更新,涉及文件重命名,增删调整
# 1.4.0 (2021-07-21)
### 🐛 Bug Fixes
- vite降至2.3.6
- 多标签页交互优化
- ### ✨ Features
- 新增 `TableAction` 组件
- 新增 `菜单权限管理` 示例
- 新增 `角色权限管理` 示例
- 持续更新更多实用组件及示例感谢Star
# 1.3.0 (2021-07-19)
### 🐛 Bug Fixes
- 修复多标签页左右切换按钮自适应展示
- 修复登录页面出现多标签页
- ### ✨ Features
- 新增 `Upload` 组件及配置
- 新增 `VITE_GLOB_IMG_URL` 图片前缀地址配合Upload
- 新增 `滑块验证码` 组件
- 新增 `登录页面-滑块验证码` 示例
- 持续更新更多实用组件及示例感谢Star
# 1.2.0 (2021-07-16)
### 🐛 Bug Fixes
- 修复面包屑显示登录页面
- 菜单支持只展开当前父级菜单
- ### ✨ Features
- 新增 `列表页面-基础列表` 示例页面
- 新增 `异常页面-404-403-500` 示例页面
- 新增 `结果页面-成功-失败-信息` 示例页面
- 新增 `设置页面-个人设置-系统设置` 示例页面
- tips `示例页面,可能在深色主题显示不佳`
- 持续更新更多实用示例,同时也演示`Naive UI`使用方法
# 1.1.0 (2021-07-15)
- ### ✨ Features
- 新增 `基础表单` 示例页面
- 新增 `分步表单` 示例页面
- 新增 `表单详情` 示例页面
- 持续更新更多实用示例,同时也演示`Naive UI`使用方法
# 1.0.0 (2021-07-12)
### 🐛 Bug Fixes
- 修复页面切换面包屑未及时更新
- ### ✨ Features
- 1.0骨架发布
- Naive UI 升级至2.15.4
- 菜单新增排序字段
- 新增 `ProTable` 组件,封装了常用的分页列配置等逻辑
- 新增 `ProTable` 组件示例页面
- 持续更新中...
# 0.1.1-beta (2021-07-07)
### 🐛 Bug Fixes
- 修正黑色主题,页面背景色和导航风格问题
- ### ✨ Features
- 主控台,工作台,自适应支持
- 左侧菜单屏幕可视宽度<=950 自动收起
- 页脚是否显示,可配置
- 新增页面缓存,演示页面在>工作台>动态卡片>输入框
# 0.1.0-beta (2021-07-04)
- Naive Ui Admin 骨架
- ### ✨ Features
- 菜单模式(左侧/顶部)
- 权限(固定角色/动态路由菜单)
- 主题(深色/浅色)引用 naiveui 特性,黑暗主题/自定义组件,暗黑主题信手捏来
- 系统主题(十种安全色,可切换预览,可自定义)
- 导航风格(三种,可自由搭配,暗色侧边/白色侧边和通栏/暗色侧边和顶部通栏)
- 多页签,持久化,拖拽,关闭,固定
- 面包屑,图标,子菜单下拉联动展示
- 漂亮的锁屏界面
- 在线配置抽屉(布局预览功能)
- 主控台,简单写了一下,能看了
- 工作台随意撸了一下不想写style用 tailwindcss大开杀戒了
- echarts官网例子很全了没啥好撸的偷懒再次引用vben作者的代码再感谢一次哈哈
- 挑个合适的时间,发布一下源码到 github
## 更新日志

View File

@ -1,79 +1 @@
## 简介
[NaiveAdminPro](https://github.com/jekip/naive-ui-admin) 是一个基于 [Vue3.0](https://github.com/vuejs/vue-next)、[Vite](https://github.com/vitejs/vite)、 [Naive UI](https://www.naiveui.com/)、[TypeScript](https://www.typescriptlang.org/) 的中后台解决方案,它使用了最新的前端技术栈,并提炼了典型的业务模型,页面,包括二次封装组件、动态菜单、权限校验、粒子化权限控制等功能,它可以帮助你快速搭建企业级中后台项目,相信不管是从新技术使用还是其他方面,都能帮助到你。
## 特性
- **最新技术栈**:使用 Vue3/vite2 等前端前沿技术开发
- **TypeScript**: 应用程序级 JavaScript 的语言
- **主题**:可配置的主题
- **Mock 数据** 内置 Mock 数据方案
- **权限** 内置完善的动态路由权限生成方案
- **组件** 二次封装了多个常用的组件
## 在线预览
- [naive-admin-pro](https://pro.naiveadmin.com)
账号admin密码123456随意
## 文档
[文档地址](https://www.naiveadmin.com/guide/introduction)
## 准备
- [node](http://nodejs.org/) 和 [git](https://git-scm.com/) -项目开发环境
- [pnpm](https://www.pnpm.cn/) pnpm - 速度快、节省磁盘空间的软件包管理器
- [Vite](https://vitejs.dev/) - 熟悉 vite 特性
- [Vue3](https://v3.vuejs.org/) - 熟悉 Vue 基础语法
- [TypeScript](https://www.typescriptlang.org/) - 熟悉`TypeScript`基本语法
- [Es6+](http://es6.ruanyifeng.com/) - 熟悉 es6 基本语法
- [Vue-Router-Next](https://next.router.vuejs.org/) - 熟悉 vue-router 基本使用
- [Naive-ui-admin](https://www.naiveui.com/) - ui 基本使用
- [Mock.js](https://github.com/nuysoft/Mock) - mockjs 基本语法
## 安装使用
- 获取项目代码
```bash
git clone git@codeup.aliyun.com:naiveadmin/naive-admin-pro.git
```
- 安装依赖
```bash
cd naive-admin-pro
pnpm install如果电脑没有安装 pnpm 的,可以执行 npm install -g pnpm@next-7node版本推荐16.x以上
```
- 运行
```bash
pnpm run dev
```
- 打包
```bash
pnpm run build
```
## 更新日志
[CHANGELOG](./CHANGELOG.md)
## 浏览器支持
本地开发推荐使用`Chrome 80+` 浏览器
支持现代浏览器, 不支持 IE
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| :-: | :-: | :-: | :-: | :-: |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 维护者
[@Ah jung](https://github.com/jekip)
### 云恒WMS

View File

@ -1,10 +1,12 @@
{
"name": "naive-admin-pro",
"version": "2.5.0",
"name": "yunheng",
"version": "2.0.0",
"description": "云恒WMS",
"license": "Apache-2.0",
"author": {
"name": "Ahjung",
"email": "735878602@qq.com",
"url": "https://github.com/jekip"
"name": "云恒WMS",
"email": "yunhengcloud@163.com",
"url": "https://www.baidu.com"
},
"private": true,
"scripts": {

View File

@ -22,24 +22,22 @@
</n-descriptions-item>
<n-descriptions-item label="文档地址">
<div class="flex items-center">
<a href="https://www.naiveadmin.com" class="py-2" target="_blank">查看文档地址</a>
<a href="https://www.baidu.com" class="py-2" target="_blank">查看文档地址</a>
</div>
</n-descriptions-item>
<n-descriptions-item label="预览地址">
<div class="flex items-center">
<a href="https://pro.naiveadmin.com" class="py-2" target="_blank">查看预览地址</a>
<a href="https://www.baidu.com" class="py-2" target="_blank">查看预览地址</a>
</div>
</n-descriptions-item>
<n-descriptions-item label="Github">
<div class="flex items-center">
<a href="https://github.com/jekip/naive-ui-admin" class="py-2" target="_blank"
>查看Github地址</a
>
<a href="https://github.com/" class="py-2" target="_blank">查看Github地址</a>
</div>
</n-descriptions-item>
<n-descriptions-item label="QQ交流群">
<div class="flex items-center">
<a href="https://jq.qq.com/?_wv=1027&k=xib9dU4C" class="py-2" target="_blank"
<a href="https://www.baidu.com" class="py-2" target="_blank"
>点击链接加入群聊Naive Admin</a
>
</div>

View File

@ -1,65 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="图片裁剪示例">
适用于头像上传图片上传之前需要进行裁剪简单说就是需要图片上传并且需要裁剪就可以用这个组件快速实现需要真实接口才能进行上传测试
</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard" title="圆形裁剪">
<!--圆形裁剪-->
<Cropper
ref="cropperCircled"
:circled="true"
:src="src"
:uploadApi="upload"
title="圆形头像上传"
/>
<n-space>
<n-button class="mt-3 ml-12" @click="cropperCircledImg">选择图片</n-button>
</n-space>
</n-card>
<n-card :bordered="false" class="mt-3 proCard" title="矩形裁剪">
<!--矩形裁剪-->
<Cropper ref="cropperRectangle" :src="src" title="矩形头像上传" />
<n-space>
<n-button class="mt-3 ml-12" @click="cropperRectangleImg">选择图片</n-button>
</n-space>
</n-card>
<n-card :bordered="false" class="mt-3 proCard" title="自定义内容,选择权交给您">
<!--圆形裁剪-->
<Cropper
ref="cropperCircled"
:circled="true"
:src="src"
:uploadApi="upload"
title="圆形头像上传"
>
<n-button class="mt-3 ml-12" @click="cropperCircledImg">自定义裁剪图片</n-button>
</Cropper>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { Cropper } from '@/components/Cropper';
import { upload } from '@/api/common/';
const src = ref('https://img.naiveadmin.com/assets/avatar/avatar-2.jpg');
const cropperCircled = ref();
const cropperRectangle = ref();
function cropperCircledImg() {
cropperCircled.value.openCropper();
}
function cropperRectangleImg() {
cropperRectangle.value.openCropper();
}
</script>
<style lang="less"></style>

View File

@ -1,161 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="拖拽"> 常用于卡片事项预约流程计划等 </n-card>
</div>
<n-alert title="花式拖拽演示" type="info" class="mt-3">
每个卡片都可以上下拖拽顺序另外不同卡片也可以拖拽过去拖拽过来都不在话下呢快试试O(_)O哈哈~
</n-alert>
<n-grid
cols="1 s:2 m:3 l:4 xl:4 2xl:4"
class="mt-3 proCard"
responsive="screen"
:x-gap="12"
:y-gap="8"
>
<n-grid-item>
<n-card
title="需求池"
:segmented="{ content: true, footer: true }"
size="small"
:bordered="false"
>
<template #header-extra>
<n-tag type="info"></n-tag>
</template>
<Draggable
class="draggable-ul"
animation="300"
:list="demandList"
group="people"
itemKey="name"
>
<template #item="{ element }">
<div class="cursor-move draggable-li">
<n-tag type="info">需求</n-tag><span class="ml-2">{{ element.name }}</span>
</div>
</template>
</Draggable>
</n-card>
</n-grid-item>
<n-grid-item>
<n-card
title="开发中"
:segmented="{ content: true, footer: true }"
size="small"
:bordered="false"
>
<template #header-extra>
<n-tag type="info"></n-tag>
</template>
<Draggable
class="draggable-ul"
animation="300"
:list="exploitList"
group="people"
itemKey="name"
>
<template #item="{ element }">
<div class="cursor-move draggable-li">
<n-tag type="warning">开发中</n-tag><span class="ml-2">{{ element.name }}</span>
</div>
</template>
</Draggable>
</n-card>
</n-grid-item>
<n-grid-item>
<n-card
title="已完成"
:segmented="{ content: true, footer: true }"
size="small"
:bordered="false"
>
<template #header-extra>
<n-tag type="info"></n-tag>
</template>
<Draggable
class="draggable-ul"
animation="300"
:list="completeList"
group="people"
itemKey="name"
>
<template #item="{ element }">
<div class="cursor-move draggable-li">
<n-tag type="error">已完成</n-tag><span class="ml-2">{{ element.name }}</span>
</div>
</template>
</Draggable>
</n-card>
</n-grid-item>
<n-grid-item>
<n-card
title="已验收"
:segmented="{ content: true, footer: true }"
size="small"
:bordered="false"
>
<template #header-extra>
<n-tag type="info"></n-tag>
</template>
<Draggable
class="draggable-ul"
animation="300"
:list="approvedList"
group="people"
itemKey="name"
>
<template #item="{ element }">
<div class="cursor-move draggable-li">
<n-tag type="success">已验收</n-tag><span class="ml-2">{{ element.name }}</span>
</div>
</template>
</Draggable>
</n-card>
</n-grid-item>
</n-grid>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue';
import Draggable from 'vuedraggable';
const demandList = reactive([
{ name: '预约表单页面,能填写预约相关信息', id: 1 },
{ name: '促销活动页面,包含促销广告展示', id: 2 },
{ name: '商品列表,需要一个到货提醒功能', id: 3 },
{ name: '商品需要一个评价功能', id: 4 },
{ name: '商品图片需要提供放大镜', id: 5 },
{ name: '订单需要提供删除到回收站', id: 6 },
{ name: '用户头像上传,需要支持裁剪', id: 7 },
{ name: '据说Vue3.2发布了setup啥时候支持', id: 8 },
]);
const exploitList = reactive([{ name: '商品图片需要提供放大镜', id: 5 }]);
const completeList = reactive([{ name: '商品图片需要提供放大镜', id: 5 }]);
const approvedList = reactive([{ name: '商品图片需要提供放大镜', id: 5 }]);
</script>
<style lang="less" scoped>
.draggable-ul {
width: 100%;
overflow: hidden;
margin-top: -16px;
.draggable-li {
width: 100%;
padding: 16px 10px;
border-bottom: 1px solid var(--n-border-color);
}
}
</style>

View File

@ -1,225 +0,0 @@
<template>
<PageWrapper
title="基础表单"
content="基础表单,用于向用户收集表单信息,并展示业务逻辑交互使用示例"
showFooter
>
<n-card :bordered="false" class="mt-3 proCard">
<div class="BasicForm">
<BasicForm
ref="basicFormRef"
submitButtonText="提交预约"
layout="horizontal"
:gridProps="{ cols: 1 }"
:schemas="schemas"
@submit="handleSubmit"
@reset="handleReset"
/>
</div>
</n-card>
<template #leftFooter>
<n-space>
<n-button @click="verifyMobile">只验证手机号码</n-button>
<n-button @click="setName">设置姓名</n-button>
</n-space>
</template>
</PageWrapper>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, unref } from 'vue';
import { BasicForm, FormSchema } from '@/components/Form/index';
import { useMessage } from 'naive-ui';
import { useVerificate } from '@/hooks/web/useVerificate';
const basicFormRef = ref();
const isMakeSource = ref(true);
const { isMobile } = useVerificate();
const getIsMakeSource = computed(() => {
return isMakeSource.value;
});
const schemas: FormSchema[] = reactive([
{
field: 'id',
defaultValue: 128,
hidden: true,
},
{
field: 'identity',
defaultValue: '我是一个隐藏字段内容',
hidden: true,
},
{
field: 'info.name',
component: 'NInput',
label: '姓名',
labelMessage: '这是一个提示',
// defaultValue: '',
componentProps: {
placeholder: '请输入姓名',
onInput: (e: any) => {
console.log(e);
},
},
rules: [{ required: true, message: '请输入姓名', trigger: ['blur'] }],
},
{
field: 'mobile',
component: 'NInputNumber',
label: '手机',
componentProps: {
placeholder: '请输入手机号码',
showButton: false,
onInput: (e: any) => {
console.log(e);
},
},
rules: [
{
key: 'mobile',
required: true,
validator: isMobile,
trigger: ['input', 'blur'],
},
],
},
{
field: 'type',
component: 'NSelect',
label: '类型',
componentProps: {
placeholder: '请选择类型',
options: [
{
label: '舒适性',
value: 1,
},
{
label: '经济性',
value: 2,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeDate',
component: 'NDatePicker',
label: '预约时间',
defaultValue: 1183135260000,
componentProps: {
type: 'date',
onUpdateValue: (e: any) => {
console.log(e);
},
},
//
// schema, values, model, field
hidden: ({ model }) => {
return !model.type;
},
rules: [{ required: true, type: 'number', message: '请选择预约时间', trigger: ['change'] }],
},
{
field: 'makeTime',
component: 'NTimePicker',
label: '停留时间',
componentProps: {
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeProject',
component: 'NCheckbox',
label: '预约项目',
componentProps: {
placeholder: '请选择预约项目',
options: [
{
label: '种牙',
value: 1,
},
{
label: '补牙',
value: 2,
},
{
label: '根管',
value: 3,
},
],
onUpdateValue: (e: any) => {
//
isMakeSource.value = e.includes(3);
basicFormRef.value.setSchema(getNewSchemas());
},
},
},
{
field: 'makeSource',
component: 'NRadioGroup',
label: '来源',
hidden: getIsMakeSource.value,
componentProps: {
options: [
{
label: '网上',
value: 1,
},
{
label: '门店',
value: 2,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
]);
function setName() {
basicFormRef.value.setFieldsValue({
'info.name': '我是啊俊',
});
}
function verifyMobile() {
basicFormRef.value.validate(['mobile']);
}
function getNewSchemas() {
const newSchemas = unref(schemas);
newSchemas.forEach((item) => {
if (item.field === 'makeSource') {
item.hidden = !isMakeSource.value;
}
});
return newSchemas;
}
const message = useMessage();
function handleSubmit(values: Recordable) {
message.success(JSON.stringify(values));
}
function handleReset(values: Recordable) {
message.success(JSON.stringify(values));
}
</script>
<style lang="less" scoped>
.BasicForm {
width: 550px;
margin: 0 auto;
overflow: hidden;
padding-top: 20px;
}
</style>

View File

@ -1,223 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="基础表单"> useForm 表单用于向用户收集表单信息 </n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<div class="BasicForm">
<BasicForm @register="register" @submit="handleSubmit" @reset="handleReset">
<template #statusSlot="{ model, field }">
<n-input v-model:value="model[field]" />
</template>
</BasicForm>
<n-divider />
<n-button strong secondary type="tertiary" @click="eidtSchemas" block
>改变 Schemas</n-button
>
</div>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
import { useMessage } from 'naive-ui';
const schemas: FormSchema[] = [
{
field: 'name',
component: 'NInput',
label: '姓名',
labelMessage: '这是一个提示',
giProps: {
span: 1,
},
componentProps: {
placeholder: '请输入姓名',
onInput: (e: any) => {
console.log(e);
},
},
rules: [{ required: true, message: '请输入姓名', trigger: ['blur'] }],
},
{
field: 'mobile',
component: 'NInputNumber',
label: '手机',
componentProps: {
placeholder: '请输入手机号码',
showButton: false,
onInput: (e: any) => {
console.log(e);
},
},
},
{
field: 'type',
component: 'NSelect',
label: '类型',
giProps: {
//span: 24,
},
componentProps: {
placeholder: '请选择类型',
options: [
{
label: '舒适性',
value: 1,
},
{
label: '经济性',
value: 2,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeDate',
component: 'NDatePicker',
label: '预约时间',
giProps: {
//span: 24,
},
defaultValue: 1183135260000,
componentProps: {
type: 'date',
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeTime',
component: 'NTimePicker',
label: '停留时间',
giProps: {
//span: 24,
},
componentProps: {
clearable: true,
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeProject',
component: 'NCheckbox',
label: '预约项目',
giProps: {
//span: 24,
},
componentProps: {
placeholder: '请选择预约项目',
options: [
{
label: '种牙',
value: 1,
},
{
label: '补牙',
value: 2,
},
{
label: '根管',
value: 3,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeSource',
component: 'NRadioGroup',
label: '来源',
giProps: {
//span: 24,
},
componentProps: {
options: [
{
label: '网上',
value: 1,
},
{
label: '门店',
value: 2,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'status',
label: '状态',
giProps: {
//span: 24,
},
//
slot: 'statusSlot',
},
];
const message = useMessage();
const [register, { setSchema }] = useForm({
gridProps: { cols: 1 },
collapsedRows: 3,
labelWidth: 120,
layout: 'horizontal',
submitButtonText: '提交预约',
schemas,
});
function eidtSchemas() {
setSchema([
{
field: 'name',
component: 'NInput',
label: '姓名',
labelMessage: '这是一个提示',
giProps: {
span: 1,
},
componentProps: {
// placeholder: '',
onInput: (e: any) => {
console.log(e);
},
},
rules: [{ required: true, message: '请输入姓名', trigger: ['blur'] }],
},
]);
}
function handleSubmit(values: Recordable) {
if (values) {
console.log(values);
message.success(JSON.stringify(values));
} else {
message.error('验证失败,请填写完整信息');
}
}
function handleReset(values: Recordable) {
console.log(values);
}
</script>
<style lang="less" scoped>
.BasicForm {
width: 550px;
margin: 0 auto;
overflow: hidden;
padding-top: 20px;
}
</style>

View File

@ -1,332 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="模态框">
模态框用于向用户收集或展示信息Modal 采用 Dialog 预设扩展拖拽效果
<br />
以下是 useModal
方式ref方式也支持使用方式和其他组件一致modalRef.value.closeModal()
</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="提示" type="warning" class="mb-3">
组件暴露了setProps 方法用于修改组件内部
Props比如标题具体参考UI框架文档DialogReactive Properties
</n-alert>
<n-alert title="Modal嵌套Form" type="info">
使用 useModal 进行弹窗展示和操作并演示了在Modal内和Form组件组合使用方法
<br />
<br />
<n-button type="primary" @click="showModal">打开Modal嵌套Form例子</n-button>
</n-alert>
</n-card>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="个性化轻量级" type="info">
使用 useModal 进行弹窗展示和操作自定义配置实现轻量级效果更多配置请参考文档
<br />
<br />
<n-button type="primary" @click="showLightModal">轻量级确认</n-button>
</n-alert>
</n-card>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="多个Modal嵌套" type="info">
使用 useModal 进行弹窗展示并且嵌套 Modal 使用方法
<br />
<br />
<n-button type="primary" @click="showNestedModal">打开多个Modal嵌套</n-button>
</n-alert>
</n-card>
<basicModal
@register="modalRegister"
ref="modalRef"
class="basicModal basicFormModal"
@on-ok="okModal"
>
<template #default>
<BasicForm @register="register" @reset="handleReset" class="basicForm">
<template #statusSlot="{ model, field }">
<n-input v-model:value="model[field]" />
</template>
</BasicForm>
</template>
</basicModal>
<basicModal
@register="lightModalRegister"
class="basicModalLight"
ref="modalRef"
@on-ok="lightOkModal"
>
<template #default>
<p class="text-gray-500" style="padding-left: 35px">一些对话框内容</p>
</template>
</basicModal>
<basicModal @register="nestedModalRegister" ref="modalRefOne" :showAction="false">
<template #default>
<div class="my-6">
<n-h3>我是第一个弹窗支持拖动哦~</n-h3>
<n-button type="primary" @click="showNestedModalTow">在打开一个Modal</n-button>
</div>
</template>
</basicModal>
<basicModal @register="nestedTowModalRegister" ref="modalRefTow" :showAction="false">
<template #default>
<div class="my-12">
<n-h3>我是第二个弹窗也是可以拖动的哦~</n-h3>
</div>
</template>
</basicModal>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useMessage } from 'naive-ui';
import { basicModal, useModal } from '@/components/Modal';
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
const schemas: FormSchema[] = [
{
field: 'name',
component: 'NInput',
label: '姓名',
labelMessage: '这是一个提示',
giProps: {
span: 1,
},
componentProps: {
placeholder: '请输入姓名',
onInput: (e: any) => {
console.log(e);
},
},
rules: [{ required: true, message: '请输入姓名', trigger: ['blur'] }],
},
{
field: 'mobile',
component: 'NInputNumber',
label: '手机',
componentProps: {
placeholder: '请输入手机号码',
showButton: false,
onInput: (e: any) => {
console.log(e);
},
},
},
{
field: 'type',
component: 'NSelect',
label: '类型',
giProps: {
//span: 24,
},
componentProps: {
placeholder: '请选择类型',
options: [
{
label: '舒适性',
value: 1,
},
{
label: '经济性',
value: 2,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeDate',
component: 'NDatePicker',
label: '预约时间',
giProps: {
//span: 24,
},
defaultValue: 1183135260000,
componentProps: {
type: 'date',
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeTime',
component: 'NTimePicker',
label: '停留时间',
giProps: {
//span: 24,
},
componentProps: {
clearable: true,
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeProject',
component: 'NCheckbox',
label: '预约项目',
giProps: {
//span: 24,
},
componentProps: {
placeholder: '请选择预约项目',
options: [
{
label: '种牙',
value: 1,
},
{
label: '补牙',
value: 2,
},
{
label: '根管',
value: 3,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeSource',
component: 'NRadioGroup',
label: '来源',
giProps: {
//span: 24,
},
componentProps: {
options: [
{
label: '网上',
value: 1,
},
{
label: '门店',
value: 2,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'status',
label: '状态',
giProps: {
//span: 24,
},
//
slot: 'statusSlot',
},
];
const modalRef: any = ref(null);
const message = useMessage();
const [modalRegister, { openModal, closeModal, setSubLoading }] = useModal({
title: '新增预约',
width: 600,
});
const [
lightModalRegister,
{ openModal: lightOpenModal, closeModal: lightCloseModal, setSubLoading: lightSetSubLoading },
] = useModal({
title: '确认对话框',
showIcon: true,
type: 'warning',
closable: false,
maskClosable: true,
});
const [register, { submit }] = useForm({
gridProps: { cols: 1 },
collapsedRows: 3,
labelWidth: 120,
layout: 'horizontal',
submitButtonText: '提交预约',
showActionButtonGroup: false,
schemas,
});
const [nestedModalRegister, { openModal: nestedOpenModal }] = useModal({
title: '嵌套弹窗',
width: 350,
});
const [nestedTowModalRegister, { openModal: nestedOpenTowModal }] = useModal({
title: '第二个弹窗',
width: 550,
});
function showNestedModal() {
nestedOpenModal();
}
function showNestedModalTow() {
nestedOpenTowModal();
}
async function okModal() {
const formRes = await submit();
if (formRes) {
closeModal();
message.success('提交成功');
} else {
message.error('验证失败,请填写完整信息');
setSubLoading(false);
}
}
function lightOkModal() {
lightCloseModal();
lightSetSubLoading();
}
function showLightModal() {
lightOpenModal();
}
function showModal() {
openModal();
}
function handleReset(values: Recordable) {
console.log(values);
}
</script>
<style lang="less">
.n-dialog.basicFormModal {
width: 640px;
}
.n-dialog.basicModalLight {
width: 410px;
}
</style>
<style lang="less" scoped>
.basicForm {
padding-top: 20px;
}
.n-dialog.basicModalLight {
width: 416px;
padding-top: 26px;
}
</style>

View File

@ -1,37 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="密码强度校验组件">
用于常用密码强度设置通常要求比较严格一点密码适用验证灵活配置脱离 Form
单独使用也可以哦~
</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="基础效果" type="info"> 密码长度6-32复杂密码</n-alert>
<Password class="mt-3" />
<n-alert title="设定密码长度" type="info">比如来个( 12 - 16 个字符 )</n-alert>
<Password :min-length="12" :max-length="16" class="mt-3" />
<n-alert title="简单密码" type="info"
>不需要满足字母数字及特殊字符两种或以上组合条件
</n-alert>
<Password class="mt-3" :complexity="false" />
<n-alert title="自定义密码强度等级提示语" type="info">
支持4个等级配置1 - 4 默认4个等级名称分别为 1. 弱不禁风 2. 平淡无奇 3. 出神入化 4.
登峰造极
</n-alert>
<Password class="mt-3" :level="{ 1: '很Low', 2: '一般Low', 3: '没那么Low', 4: '不Low了' }" />
<n-alert title="再次确认密码" type="info" />
<Password :repeat="true" class="mt-3" />
</n-card>
</div>
</template>
<script lang="ts" setup>
import { Password } from '@/components/Password';
</script>
<style lang="less"></style>

View File

@ -1,162 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="二维码组件">
二维码组件使用示例通常用于一些商品促销活动或者分享推广二维码展示
</n-card>
</div>
<n-grid class="mt-3" cols="1 s:2 m:2 l:3 xl:3 2xl:3" responsive="screen" :x-gap="12" :y-gap="9">
<n-gi>
<n-card :segmented="{ content: true }" :bordered="false" size="small" title="基础实例">
<n-space justify="center" class="qrcode-space">
<QrCode :value="qrCodeUrl" />
</n-space>
</n-card>
</n-gi>
<n-gi>
<n-card
:segmented="{ content: true }"
:bordered="false"
size="small"
title="渲染成img标签示例"
>
<n-space justify="center" class="qrcode-space">
<QrCode :value="qrCodeUrl" tag="img" />
</n-space>
</n-card>
</n-gi>
<n-gi>
<n-card :segmented="{ content: true }" :bordered="false" size="small" title="配置样式示例">
<n-space justify="center" class="qrcode-space">
<QrCode
:value="qrCodeUrl"
:options="{
color: { dark: '#55D187' },
}"
/>
</n-space>
</n-card>
</n-gi>
<n-gi>
<n-card :segmented="{ content: true }" :bordered="false" size="small" title="本地logo示例">
<n-space justify="center" class="qrcode-space">
<QrCode :value="qrCodeUrl" :logo="LogoImg" />
</n-space>
</n-card>
</n-gi>
<n-gi>
<n-card :segmented="{ content: true }" :bordered="false" size="small" title="在线logo示例">
<n-space justify="center" class="qrcode-space">
<QrCode
:value="qrCodeUrl"
logo="https://assets.naiveadmin.com/images/logo.png"
:options="{
color: { dark: '#55D187' },
}"
/>
</n-space>
</n-card>
</n-gi>
<n-gi>
<n-card :segmented="{ content: true }" :bordered="false" size="small" title="LOGO配置示例">
<n-space justify="center" class="qrcode-space">
<QrCode
:value="qrCodeUrl"
:logo="{
src: 'https://assets.naiveadmin.com/images/logo.png',
logoSize: 0.2,
borderSize: 0.05,
borderRadius: 50,
bgColor: 'blue',
}"
/>
</n-space>
</n-card>
</n-gi>
<n-gi>
<n-card :segmented="{ content: true }" :bordered="false" size="small" title="下载示例">
<n-space justify="center" class="qrcode-space">
<QrCode :value="qrCodeUrl" ref="qrRef" :logo="LogoImg" />
</n-space>
<n-space justify="center" class="qrcode-space">
<n-button class="mt-3" type="primary" @click="download"> 下载 </n-button>
</n-space>
<n-space justify="center" class="qrcode-space">
<div class="msg">(在线logo会导致图片跨域需要下载图片需要自行解决跨域问题)</div>
</n-space>
</n-card>
</n-gi>
<n-gi>
<n-card :segmented="{ content: true }" :bordered="false" size="small" title="扩展绘制示例">
<n-space justify="center" class="qrcode-space">
<QrCode
:value="qrCodeUrl"
:width="200"
:options="{ margin: 5 }"
ref="qrDiyRef"
:logo="LogoImg"
@done="onQrcodeDone"
/>
</n-space>
<n-space justify="center" class="qrcode-space">
<n-button class="mt-3" type="primary" @click="downloadDiy"> 下载 </n-button>
</n-space>
<n-space justify="center" class="qrcode-space">
<div class="msg">要进行扩展绘制则不能将tag设为img</div>
</n-space>
</n-card>
</n-gi>
<n-gi>
<n-card :segmented="{ content: true }" :bordered="false" size="small" title="配置大小示例">
<n-space justify="center" class="qrcode-space">
<QrCode :value="qrCodeUrl" :width="280" />
</n-space>
</n-card>
</n-gi>
</n-grid>
</div>
</template>
<script lang="ts" setup>
import { ref, unref } from 'vue';
import { QrCode, QrCodeActionType } from '@/components/Qrcode/index';
import LogoImg from '@/assets/images/logo.png';
const qrCodeUrl = 'https://www.naiveadmin.com';
const qrRef = ref<Nullable<QrCodeActionType>>(null);
const qrDiyRef = ref<Nullable<QrCodeActionType>>(null);
function download() {
const qrEl = unref(qrRef);
if (!qrEl) return;
qrEl.download('img');
}
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('扫描关注Star点一点', 100, 195, 200);
}
}
</script>
<style lang="less" scoped>
.qrcode-space {
position: relative;
bottom: 0;
transition: bottom 0.4s;
&:hover {
bottom: 6px;
}
}
</style>

View File

@ -1,48 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="地区">
地区组件用于选择省市区比如填写地址配送地址...
</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="添加场景" type="info"> 自动加载数据显示省市区</n-alert>
<Region class="Region mt-3" @change="regionChange" />
<n-divider />
<n-alert title="回显场景" type="info"> 设置默认值自动加载数据并且选中</n-alert>
<Region v-model:value="regionIds" class="Region mt-3" @change="regionChange" />
<n-divider />
<n-alert title="只显示省市" type="info" />
<Region
v-model:value="regionIds"
:hideArea="true"
class="Region mt-3"
@change="regionChange"
/>
<n-divider />
<n-alert title="只显示省" type="info" />
<Region :onlyProvince="true" class="Region mt-3" @change="regionChange" />
</n-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { Region } from '@/components/Region';
const regionIds = ref([1, 11, 111]);
//
function regionChange(result) {
console.log(result);
}
</script>
<style lang="less">
.Region {
width: 320px;
}
</style>

View File

@ -1,118 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="富文本">
富文本用于展示图文信息比如商品详情文章详情等...
</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<QuillEditor
ref="quillEditor"
:options="options"
v-model:content="myContent"
style="height: 350px"
@ready="readyQuill"
class="quillEditor"
/>
<template #footer>
<n-space>
<n-button @click="addText">增加文本</n-button>
<n-button @click="addImg">增加图片</n-button>
<n-button @click="getHtml">获取HTML</n-button>
</n-space>
</template>
</n-card>
<n-card :bordered="false" class="mt-3 proCard" title="HTML 内容">
<n-input
v-model:value="myContentHtml"
type="textarea"
placeholder="html"
:autosize="{
minRows: 3,
maxRows: 6,
}"
/>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue';
import { QuillEditor } from '@vueup/vue-quill';
import '@vueup/vue-quill/dist/vue-quill.snow.css';
const quillEditor = ref();
const myContent = ref(
'<h4>Naive Ui Admin 是一个基于 vue3,vite2,TypeScript 的中后台解决方案</h4>',
);
const myContentHtml = ref(
'<h4>Naive Ui Admin 是一个基于 vue3,vite2,TypeScript 的中后台解决方案</h4>',
);
const options = reactive({
modules: {
toolbar: [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{ header: 1 }, { header: 2 }], // custom button values
[{ list: 'ordered' }, { list: 'bullet' }],
[{ script: 'sub' }, { script: 'super' }], // superscript/subscript
[{ indent: '-1' }, { indent: '+1' }], // outdent/indent
[{ direction: 'rtl' }], // text direction
[{ size: ['small', false, 'large', 'huge'] }], // custom dropdown
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ color: [] }, { background: [] }], // dropdown with defaults from theme
[{ font: [] }],
[{ align: [] }],
['clean'],
['image'],
],
},
theme: 'snow',
placeholder: '输入您喜欢的内容吧!',
});
function readyQuill() {
console.log('Quill准备好了');
}
function getHtml() {
myContentHtml.value = getHtmlVal();
}
function addText() {
const html = getHtmlVal() + '新增加的内容';
quillEditor.value.setHTML(html);
}
function addImg() {
const html =
getHtmlVal() +
'<img style="width:100px" src="https://www.baidu.com/img/flexible/logo/pc/result.png"/>';
quillEditor.value.setHTML(html);
}
function getHtmlVal() {
return quillEditor.value.getHTML();
}
onMounted(() => {
quillEditor.value.setHTML(myContent.value);
});
</script>
<style lang="less">
.ql-toolbar.ql-snow {
border-top: none;
border-left: none;
border-right: none;
border-bottom: 1px solid #eee;
margin-top: -10px;
}
.ql-container.ql-snow {
border: none;
}
</style>

View File

@ -1,119 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="选择器">
扩展选择器组件用于各种表单选择器简化使用内置缓存可对相同的数据减少http请求也可手动刷新数据源
</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="基础使用" type="info">
自动加载数据首次加载缓存之后同一个KEY不在获取新数据</n-alert
>
<div class="mt-3">
<n-space align="center">
<BasicSelect
ref="basicSelectRef"
v-model:value="selectValue"
:request="loadSelectData"
@update:value="handleUpdateValue"
cache
cacheKey="SELECT_CLASSIFY"
style="width: 150px"
><template #action>如果你点开了这个例子你可能需要它</template></BasicSelect
>
<n-button @click="setSelectData">设置选中值</n-button>
<n-button @click="getSelectValue">获取选中值</n-button>
<n-button @click="getSelectData">获取数据源</n-button>
<n-button @click="refreshSelectData">刷新数据</n-button>
</n-space>
</div>
</n-card>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="自定义数据" type="info">
自定义一个响应式数据源在特定的场景可能也有用</n-alert
>
<div class="mt-3">
<n-space align="center">
<BasicSelect
ref="customBasicSelectRef"
:options="customOptions"
@update:value="handleUpdateValue"
style="width: 150px"
/>
<n-button @click="setCustomOptions">更新自定义值</n-button>
</n-space>
</div>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { getClassifyList } from '@/api/select/select';
import { BasicSelect } from '@/components/Select';
import { useMessage } from 'naive-ui';
const message = useMessage();
const selectValue = ref('hot');
const basicSelectRef = ref();
const customBasicSelectRef = ref();
const customOptions = ref([
{
label: '热门',
value: 'hot',
},
{
label: '推荐',
value: 'rec',
},
]);
const params = {
type: 1,
};
async function loadSelectData(res) {
//
return (await getClassifyList({ ...res, ...params })).map((item, index) => {
return {
...item,
index,
};
});
}
function handleUpdateValue(value, option) {
message.info('value: ' + JSON.stringify(value));
message.info('option: ' + JSON.stringify(option));
}
function refreshSelectData() {
basicSelectRef?.value.fetch();
}
function setSelectData() {
selectValue.value = 'new';
}
function getSelectValue() {
message.info('value: ' + JSON.stringify(selectValue.value));
}
function getSelectData() {
message.info('Data: ' + JSON.stringify(basicSelectRef?.value.getData()));
}
function setCustomOptions() {
customOptions.value = [
{
label: '新品',
value: 'new',
},
{
label: '限购',
value: 'pur',
},
];
}
</script>
<style lang="less"></style>

View File

@ -1,104 +0,0 @@
import { h } from 'vue';
import { NAvatar, NTag } from 'naive-ui';
import { BasicColumn } from '@/components/Table';
export const columns: BasicColumn[] = [
{
title: 'id',
key: 'id',
width: 100,
},
{
title: '编码',
key: 'no',
width: 100,
},
{
title: '名称',
key: 'name',
editComponent: 'NInput',
// 默认必填校验
editRule: (currentValue) => {
return new Promise((resolve) => {
if (!currentValue) {
resolve('请输入名称');
}
resolve('');
});
},
edit: true,
width: 80,
editCellRender: (value) => {
return h(
NTag,
{
style: {
marginRight: '6px',
},
type: 'info',
},
{
default: () => value,
},
);
},
},
{
title: '头像',
key: 'avatar',
width: 100,
render(row) {
return h(NAvatar, {
size: 48,
src: row.avatar,
});
},
},
{
title: '地址',
key: 'address',
editComponent: 'NSelect',
editComponentProps: {
options: [
{
label: '广东省',
value: 1,
},
{
label: '浙江省',
value: 2,
},
],
},
edit: true,
width: 200,
ellipsis: false,
},
{
title: '开始日期',
key: 'beginTime',
edit: true,
width: 160,
editComponent: 'NDatePicker',
editComponentProps: {
type: 'datetime',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
},
ellipsis: false,
},
{
title: '结束日期',
key: 'endTime',
width: 160,
},
{
title: '创建时间',
key: 'date',
width: 160,
},
{
title: '停留时间',
key: 'time',
width: 80,
},
];

View File

@ -1,107 +0,0 @@
<template>
<n-card :bordered="false" class="proCard">
<BasicTable
title="表格列表"
titleTooltip="这是一个提示"
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
ref="actionRef"
:actionColumn="actionColumn"
:scroll-x="1360"
:table-setting="{ width: 252 }"
@update:checked-row-keys="onCheckedRow"
>
<template #toolbar>
<n-button type="primary" @click="reloadTable">刷新数据</n-button>
</template>
</BasicTable>
</n-card>
</template>
<script lang="ts" setup>
import { reactive, ref, h } from 'vue';
import { BasicTable, TableAction, BasicColumn } from '@/components/Table';
import { getTableList } from '@/api/table/list';
import { columns } from './basicColumns';
import { useDialog, useMessage } from 'naive-ui';
const message = useMessage();
const dialog = useDialog();
const actionRef = ref();
const params = reactive({
pageSize: 5,
name: 'xiaoMa',
});
const actionColumn: BasicColumn = reactive({
width: 150,
title: '操作',
key: 'action',
fixed: 'right',
align: 'center',
render(record) {
return h(TableAction, {
style: 'button',
actions: createActions(record),
});
},
});
function createActions(record) {
return [
{
label: '删除',
onClick: handleDelete.bind(null, record),
// isShow auth
ifShow: () => {
return true;
},
// :
auth: ['basic_list'],
},
{
label: '编辑',
onClick: handleEdit.bind(null, record),
ifShow: () => {
return true;
},
auth: ['basic_list'],
},
];
}
const loadDataTable = async (res) => {
return await getTableList({ ...params, ...res });
};
function onCheckedRow(rowKeys) {
console.log(rowKeys);
}
function reloadTable() {
actionRef.value.reload();
}
function handleDelete(record) {
console.log(record);
dialog.info({
title: '提示',
content: `您想删除${record.name}`,
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
message.success('删除成功');
},
onNegativeClick: () => {},
});
}
function handleEdit(record) {
console.log(record);
message.success('您点击了编辑按钮');
}
</script>
<style lang="less" scoped></style>

View File

@ -1,80 +0,0 @@
import { h } from 'vue';
import { NAvatar, NTag } from 'naive-ui';
import { BasicColumn } from '@/components/Table';
export const columns: BasicColumn[] = [
{
type: 'expand',
expandable: (rowData) => rowData.name !== 'Jim Green',
renderExpand: (rowData) => {
return `${rowData.name} is a good guy.`;
},
},
{
title: 'id',
key: 'id',
width: 100,
},
{
title: '编码',
key: 'no',
width: 100,
},
{
title: '名称',
key: 'name',
width: 100,
},
{
title: '头像',
key: 'avatar',
width: 100,
render(row) {
return h(NAvatar, {
size: 48,
src: row.avatar,
});
},
},
{
title: '地址',
key: 'address',
width: 150,
},
{
title: '开始日期',
key: 'beginTime',
width: 160,
},
{
title: '结束日期',
key: 'endTime',
width: 160,
},
{
title: '状态',
key: 'status',
width: 100,
render(row) {
return h(
NTag,
{
type: row.status ? 'success' : 'error',
},
{
default: () => (row.status ? '启用' : '禁用'),
},
);
},
},
{
title: '创建时间',
key: 'date',
width: 160,
},
{
title: '停留时间',
key: 'time',
width: 80,
},
];

View File

@ -1,73 +0,0 @@
<template>
<n-card :bordered="false" class="proCard">
<BasicTable
title="表格列表"
titleTooltip="这是一个提示"
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
ref="actionRef"
@edit-end="editEnd"
@edit-change="onEditChange"
@update:checked-row-keys="onCheckedRow"
:scroll-x="1360"
:row-props="rowProps"
>
<template #toolbar>
<n-button type="primary" @click="reloadTable">刷新数据</n-button>
</template>
</BasicTable>
</n-card>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { BasicTable } from '@/components/Table';
import { getTableList } from '@/api/table/list';
import { columns } from './CellColumns';
const actionRef = ref();
const params = reactive({
pageSize: 5,
name: 'xiaoMa',
});
function rowProps(rows) {
return {
style: 'cursor: pointer;',
onclick: function () {
console.log('row点击事件触发');
console.log(rows);
},
};
}
function onEditChange({ column, value, record }) {
if (column.key === 'id') {
record.editValueRefs.name4.value = `${value}`;
}
console.log(column, value, record);
}
const loadDataTable = async (res) => {
return await getTableList({ ...params, ...res });
};
function onCheckedRow(rowKeys) {
console.log(rowKeys);
}
function reloadTable() {
console.log(actionRef.value);
actionRef.value.reload();
}
function editEnd({ record, index, key, value }) {
console.log('record', record);
console.log('index', index);
console.log('key', key);
console.log('value', value);
}
</script>
<style lang="less" scoped></style>

View File

@ -1,118 +0,0 @@
<template>
<n-card :bordered="false" class="proCard">
<BasicTable
title="表格列表"
titleTooltip="这是一个提示"
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
ref="actionRef"
:actionColumn="actionColumn"
@edit-end="editEnd"
@edit-change="onEditChange"
@update:checked-row-keys="onCheckedRow"
:scroll-x="1590"
>
<template #toolbar>
<n-button type="primary" @click="reloadTable">刷新数据</n-button>
</template>
</BasicTable>
</n-card>
</template>
<script lang="ts" setup>
import { reactive, ref, h } from 'vue';
import { BasicTable, TableAction, BasicColumn } from '@/components/Table';
import { getTableList } from '@/api/table/list';
import { columns } from './rowColumns';
const actionRef = ref();
const currentEditKeyRef = ref('');
const params = reactive({
pageSize: 5,
name: 'xiaoMa',
});
const actionColumn: BasicColumn = reactive({
width: 150,
title: '操作',
key: 'action',
fixed: 'right',
align: 'center',
render(record) {
return h(TableAction, {
style: 'button',
actions: createActions(record),
});
},
});
function handleEdit(record) {
console.log(record);
currentEditKeyRef.value = record.key;
record.onEdit?.(true);
}
function handleCancel(record) {
currentEditKeyRef.value = '';
record.onEdit?.(false, false);
}
function onEditChange({ column, value, record }) {
if (column.key === 'id') {
record.editValueRefs.name4.value = `${value}`;
}
console.log(column, value, record);
}
async function handleSave(record) {
const pass = await record.onEdit?.(false, true);
if (pass) {
currentEditKeyRef.value = '';
}
}
function createActions(record) {
if (!record.editable) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
];
} else {
return [
{
label: '保存',
onClick: handleSave.bind(null, record),
},
{
label: '取消',
onClick: handleCancel.bind(null, record),
},
];
}
}
const loadDataTable = async (res) => {
return await getTableList({ ...params, ...res });
};
function onCheckedRow(rowKeys) {
console.log(rowKeys);
}
function reloadTable() {
console.log(actionRef.value);
actionRef.value.reload();
}
function editEnd({ record, index, key, value }) {
console.log('record', record);
console.log('index', index);
console.log('key', key);
console.log('value', value);
}
</script>
<style lang="less" scoped></style>

View File

@ -1,97 +0,0 @@
import { h } from 'vue';
import { NAvatar } from 'naive-ui';
import { BasicColumn } from '@/components/Table';
export const columns: BasicColumn[] = [
{
title: 'id',
key: 'id',
width: 100,
},
{
title: '编码',
key: 'no',
width: 100,
},
{
title: '名称',
key: 'name',
editComponent: 'NInput',
editRow: true,
// 默认必填校验
editRule: true,
edit: true,
width: 200,
},
{
title: '头像',
key: 'avatar',
width: 100,
render(row) {
return h(NAvatar, {
size: 48,
src: row.avatar,
});
},
},
{
title: '地址',
key: 'address',
editRow: true,
editComponent: 'NSelect',
editComponentProps: {
options: [
{
label: '广东省',
value: 1,
},
{
label: '浙江省',
value: 2,
},
],
},
edit: true,
width: 200,
ellipsis: false,
},
{
title: '开始日期',
key: 'beginTime',
editRow: true,
edit: true,
width: 240,
editComponent: 'NDatePicker',
editComponentProps: {
type: 'datetime',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
},
ellipsis: false,
},
{
title: '结束日期',
key: 'endTime',
width: 160,
},
{
title: '状态',
key: 'status',
editRow: true,
edit: true,
width: 100,
editComponent: 'NSwitch',
editValueMap: (value) => {
return value ? '启用' : '禁用';
},
},
{
title: '创建时间',
key: 'date',
width: 160,
},
{
title: '停留时间',
key: 'time',
width: 80,
},
];

View File

@ -1,32 +0,0 @@
import { h } from 'vue';
import { NAvatar } from 'naive-ui';
import { BasicColumn } from '@/components/Table';
export const columns: BasicColumn[] = [
{
title: 'id',
key: 'id',
width: 100,
},
{
title: '名称',
key: 'name',
width: 100,
},
{
title: '头像',
key: 'avatar',
width: 100,
render(row) {
return h(NAvatar, {
size: 48,
src: row.avatar,
});
},
},
{
title: '地址',
key: 'address',
width: 150,
},
];

View File

@ -1,188 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="表格选择器">
选择器增强用于展示多列数据表格选择器可实现单选/多选还能配置表单查询项目实测还是挺实用的
</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="单选" type="info"> 始终只能选择一个切换分页也是如此 </n-alert>
<div class="mt-3">
<n-space align="center">
<TableSelect
ref="TableSelectRef"
labelField="name"
valueField="id"
placeholder="请选择内容(单选)"
v-model:value="tableSelectData"
:tableProps="{
rowKey: (row) => row.id,
request: loadDataTable,
columns: columns,
pagination: {
simple: true,
},
}"
@change="tableSelectChange"
/>
</n-space>
</div>
</n-card>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="多选" type="info" class="mt-3">
支持选择多个切换分页也不影响试试吧
</n-alert>
<div class="mt-3">
<n-space align="center">
<TableSelect
ref="TableSelectRef"
labelField="name"
valueField="id"
placeholder="请选择内容(多选)"
:multiple="true"
:tableProps="{
rowKey: (row) => row.id,
request: loadDataTable,
columns: columns,
pagination: {
simple: true,
},
}"
@change="tableSelectChange"
v-model:value="tableSelectData"
/>
</n-space>
</div>
</n-card>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="多选" type="info">
支持配置表单搜索查询适用于查询数据较多支持分页多选
</n-alert>
<div class="mt-3">
<n-space align="center">
<TableSelect
ref="TableSelectRef"
labelField="name"
valueField="id"
placeholder="请选择内容(多选)"
v-model:formValues="formValues"
:multiple="true"
:formProps="formPropsOption"
:tableProps="{
rowKey: (row) => row.id,
request: loadDataTable,
columns: columns,
pagination: {
simple: true,
},
}"
@change="tableSelectChange"
/>
</n-space>
</div>
</n-card>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="配合Form" type="info"> 外面配合 Form 组件结合搜索查询 </n-alert>
<div class="mt-3">
<BasicForm
ref="basicFormRef"
submitButtonText="提交预约"
layout="horizontal"
:gridProps="{ cols: 1 }"
:schemas="FormSchemas"
@submit="handleSubmit"
@reset="handleReset"
>
<template #tableSelect="{ model, field }">
<TableSelect
ref="TableSelectRef"
labelField="name"
valueField="id"
placeholder="请选择内容"
v-model:value="model[field]"
:multiple="true"
:formProps="formPropsOption"
:tableProps="{
rowKey: (row) => row.id,
request: loadDataTable,
columns: columns,
pagination: {
simple: true,
},
}"
@change="tableSelectChange"
/>
</template>
</BasicForm>
</div>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { TableSelect } from '@/components/TableSelect';
import { getTableSelectList } from '@/api/table/list';
import { columns } from './basicColumns';
import { BasicForm, FormSchema } from '@/components/Form/index';
import { useMessage } from 'naive-ui';
const tableSelectData = ref(['啊俊']);
const formValues = ref();
const TableSelectRef = ref();
const message = useMessage();
const schemas: FormSchema[] = [
{
field: 'name',
labelMessage: '可以通过名称搜索查询哦',
component: 'NInput',
label: '名称',
componentProps: {
placeholder: '请输入名称',
onInput: (e: any) => {
console.log(e);
},
},
// rules: [{ required: true, message: '', trigger: ['blur'] }],
},
];
const FormSchemas: FormSchema[] = [
{
field: 'name',
label: '名称',
slot: 'tableSelect',
},
];
const formPropsOption = {
gridProps: { cols: '2' },
labelWidth: 80,
submitButtonText: '查询',
showAdvancedButton: false,
schemas,
};
const loadDataTable = async (res) => {
return await getTableSelectList({ ...formValues.value, ...res });
};
function handleSubmit(values: Recordable) {
message.success(JSON.stringify(values));
}
function handleReset(values: Recordable) {
message.success(JSON.stringify(values));
TableSelectRef.value.updateSelectedRowKeys();
}
function tableSelectChange(list) {
console.log('list', list);
}
</script>
<style lang="less" scoped></style>

View File

@ -1,111 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="上传图片"> 上传图片用于向用户收集图片信息 </n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-grid cols="2 s:1 m:3 l:3 xl:3 2xl:3" responsive="screen">
<n-grid-item offset="0 s:0 m:1 l:1 xl:1 2xl:1">
<n-form
:label-width="80"
:model="formValue"
:rules="rules"
label-placement="left"
ref="formRef"
class="py-8"
>
<n-form-item label="预约姓名" path="name">
<n-input v-model:value="formValue.name" placeholder="输入姓名" />
</n-form-item>
<n-form-item label="预约号码" path="mobile">
<n-input placeholder="电话号码" v-model:value="formValue.mobile" />
</n-form-item>
<n-form-item label="病例图片" path="images">
<BasicUpload
:action="`${uploadUrl}/v1.0/files`"
:headers="uploadHeaders"
:data="{ type: '0' }"
name="files"
:width="100"
:height="100"
@uploadChange="uploadChange"
v-model:value="formValue.images"
helpText="单个文件不超过2MB最多只能上传10个文件"
/>
</n-form-item>
<div style="margin-left: 80px">
<n-space>
<n-button type="primary" @click="formSubmit">提交预约</n-button>
<n-button @click="resetForm">重置</n-button>
</n-space>
</div>
</n-form>
</n-grid-item>
</n-grid>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { ref, unref, reactive } from 'vue';
import { useMessage, FormRules } from 'naive-ui';
import { BasicUpload } from '@/components/Upload';
import { useGlobSetting } from '@/hooks/setting';
const globSetting = useGlobSetting();
const rules: FormRules = {
name: {
required: true,
message: '请输入预约姓名',
trigger: 'blur',
},
remark: {
required: true,
message: '请输入预约备注',
trigger: 'blur',
},
images: {
required: true,
type: 'array',
message: '请上传病例图片',
trigger: 'change',
},
};
const formRef: any = ref(null);
const message = useMessage();
const { uploadUrl } = globSetting;
const formValue = reactive({
name: '',
mobile: '',
// 使 |
images: ['https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'],
});
const uploadHeaders: any = reactive({
platform: 'miniPrograms',
timestamp: new Date().getTime(),
token: 'Q6fFCuhc1vkKn5JNFWaCLf6gRAc5n0LQHd08dSnG4qo=',
});
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
message.success('验证成功');
} else {
message.error('验证失败,请填写完整信息');
}
});
}
function resetForm() {
formRef.value.restoreValidation();
}
function uploadChange(list: string[]) {
formValue.images = unref(list);
}
</script>

View File

@ -1,75 +0,0 @@
<template>
<PageWrapper>
<div class="n-layout-page-header">
<n-card :bordered="false" title="权限判断">
中后台系统权限事关重要可能在任意页面都会存在前端可以通过多种方式来实现权限控制
</n-card>
</div>
<n-card
:bordered="false"
title="方法判断"
class="mt-3 proCard"
size="small"
:segmented="{ content: true }"
>
<n-space>
<n-button type="success" v-if="hasPermission(['delete_user'])" @click="handleDeleteSueeess"
>有删除用户权限可见</n-button
>
<n-button type="error" @click="handleDeleteError">没有删除列表权限</n-button>
</n-space>
</n-card>
<n-card
:bordered="false"
title="指令判断"
class="mt-3 proCard"
size="small"
:segmented="{ content: true }"
>
<n-space>
<n-button type="error" v-permission="{ action: ['delete_list'], effect: 'disabled' }"
>没有删除列表权限禁用</n-button
>
<n-button type="error" v-permission="{ action: ['delete_list'] }"
>没有删除列表权限隐藏</n-button
>
</n-space>
</n-card>
<n-card
:bordered="false"
title="组件判断"
class="mt-3 proCard"
size="small"
:segmented="{ content: true }"
>
<n-space>
<Authority :value="['delete_user']">
<n-button type="success" @click="handleDeleteSueeess">有删除用户权限可见</n-button>
</Authority>
<Authority :value="['delete_list']">
<n-button type="error" @click="handleDeleteSueeess">没有删除列表权限隐藏</n-button>
</Authority>
</n-space>
</n-card>
</PageWrapper>
</template>
<script lang="ts" setup>
import { usePermission } from '@/hooks/web/usePermission';
import { useMessage } from 'naive-ui';
const message = useMessage();
const { hasPermission } = usePermission();
function handleDeleteSueeess() {
if (hasPermission(['delete_user'])) {
message.success('恭喜,您拥有该操作权限');
}
}
function handleDeleteError() {
if (!hasPermission(['delete_list'])) {
message.warning('抱歉,您没有操作权限');
}
}
</script>

View File

@ -1,97 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="右键菜单"> 右键菜单示例指定元素右键显示操作菜单 </n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert :show-icon="false" title="右键展示菜单" type="info">
<n-button class="mt-2" type="primary" @contextmenu="handleContextMenu">右键试试</n-button>
</n-alert>
<n-alert :show-icon="false" title="头像组件右键展示菜单" type="info" class="mt-3">
<n-avatar
:size="80"
src="https://naive-ui-admin-docs.vercel.app/logo.png"
@contextmenu="handleContextMenu"
/>
</n-alert>
<n-dropdown
placement="bottom-start"
@select="handleSelect"
trigger="manual"
:x="xRef"
:y="yRef"
:options="options"
:show="showDropdownRef"
:on-clickoutside="onClickoutside"
/>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { ref, nextTick } from 'vue';
import { useMessage } from 'naive-ui';
import {
MailOutlined,
AndroidOutlined,
EllipsisOutlined,
QqOutlined,
WechatOutlined,
} from '@vicons/antd';
import { renderIcon } from '@/utils';
const options = [
{
label: '发送到邮箱',
key: 'email',
icon: renderIcon(MailOutlined),
},
{
label: '发送到手机',
key: 'mobile',
icon: renderIcon(AndroidOutlined),
},
{
label: '其他',
key: 'others',
icon: renderIcon(EllipsisOutlined),
children: [
{
label: 'QQ',
key: 'qq',
icon: renderIcon(QqOutlined),
},
{
label: '微信',
key: 'weixin',
icon: renderIcon(WechatOutlined),
},
],
},
];
const showDropdownRef = ref(false);
const message = useMessage();
const xRef = ref(0);
const yRef = ref(0);
function handleSelect(key) {
showDropdownRef.value = false;
message.info(`${key}-这个是你点击的菜单吧?`);
}
function handleContextMenu(e) {
e.preventDefault();
showDropdownRef.value = false;
nextTick().then(() => {
showDropdownRef.value = true;
xRef.value = e.clientX;
yRef.value = e.clientY;
});
}
function onClickoutside() {
message.info('您点击了外部区域,菜单不见了哈!');
showDropdownRef.value = false;
}
</script>

View File

@ -1,70 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="文本复制">
文本复制示例用于常规订单号编号快速复制等场景
</n-card>
</div>
<n-card
:bordered="false"
title="基本信息"
class="mt-3 proCard"
size="small"
:segmented="{ content: true }"
>
<n-descriptions label-placement="left" class="py-2">
<n-descriptions-item>
<template #label>收款人姓名</template>
啊俊
</n-descriptions-item>
<n-descriptions-item label="收款账户">NaiveUiAdmin@qq.com</n-descriptions-item>
<n-descriptions-item label="付款类型">支付宝</n-descriptions-item>
<n-descriptions-item label="付款账户">
{{ account }}
<n-button size="small" type="info" @click="handleAccountCopy">复制</n-button>
</n-descriptions-item>
<n-descriptions-item label="转账金额">
<n-space>
<n-input v-model:value="money" />
<n-button type="info" @click="handleMoneyCopy">复制</n-button>
</n-space>
</n-descriptions-item>
<n-descriptions-item label="状态">
<n-tag type="success"> 已到账</n-tag>
</n-descriptions-item>
</n-descriptions>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { ref, unref } from 'vue';
import { useCopyToClipboard } from '@/hooks/web/useCopyToClipboard';
import { useMessage } from 'naive-ui';
const { clipboardRef, copiedRef } = useCopyToClipboard();
const account = ref('NaiveUiAdmin@163.com');
const money = ref(null);
const message = useMessage();
function handleAccountCopy() {
const value = unref(account.value);
clipboardRef.value = value;
if (unref(copiedRef)) {
message.success(`拷贝成功:${value}`);
}
}
function handleMoneyCopy() {
const value = unref(money.value);
if (!value) {
message.warning('请输入要复制的内容!');
return;
}
clipboardRef.value = value;
if (unref(copiedRef)) {
message.success(`拷贝成功:${value}`);
}
}
</script>

View File

@ -1,61 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="文件下载">
文件下载示例用于各种场景下载文件或者图片
</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert :show-icon="false" title="后台接口文件流下载" type="info">
<n-button class="mt-2" type="primary" @click="downloadFile">文件流下载</n-button>
</n-alert>
<n-divider />
<n-alert :show-icon="false" title="文件地址下载" type="info">
<n-button class="mt-2" type="primary" @click="downloadFileUrl">文件地址下载</n-button>
</n-alert>
<n-divider />
<n-alert :show-icon="false" title="base64流下载" type="info">
<n-button class="mt-2" type="primary" @click="downloadFileBase64">base64流下载</n-button>
</n-alert>
<n-divider />
<n-alert
:show-icon="false"
title="图片Url下载如果有跨域问题需要先处理图片跨域才能下载"
type="info"
>
<n-button class="mt-2" type="primary" @click="downloadFileImgUrl">图片Url下载</n-button>
</n-alert>
</n-card>
</div>
</template>
<script lang="ts" setup>
import {
downloadByUrl,
downloadByData,
downloadByBase64,
downloadByOnlineUrl,
} from '@/utils/file/download';
import imgBase64 from './imgBase64';
const getName = new Date().valueOf();
function downloadFile() {
downloadByData('测试下载文件流', `${getName}-file.txt`);
}
function downloadFileUrl() {
downloadByUrl({
url: 'https://naive-ui-admin-docs.vercel.app/logo.png',
target: '_self',
});
}
function downloadFileBase64() {
downloadByBase64(imgBase64, `${getName}.png`);
}
function downloadFileImgUrl() {
downloadByOnlineUrl('https://naive-ui-admin-docs.vercel.app/logo.png', `${getName}.png`);
}
</script>

File diff suppressed because one or more lines are too long

View File

@ -1,220 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="导出示例"> 可以选择导出格式 </n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<BasicTable
title="表格列表"
titleTooltip="这是一个提示"
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
ref="actionRef"
:actionColumn="actionColumn"
:scroll-x="1360"
@update:checked-row-keys="onCheckedRow"
>
<template #toolbar>
<n-button type="primary" @click="openModal">导出数据</n-button>
</template>
</BasicTable>
</n-card>
<basicModal @register="modalRegister" ref="modalRef" class="basicModal" @on-ok="okModal">
<template #default>
<BasicForm
@register="register"
@submit="handleSubmit"
@reset="handleReset"
class="basicForm"
>
<template #statusSlot="{ model, field }">
<n-input v-model:value="model[field]" />
</template>
</BasicForm>
</template>
</basicModal>
</div>
</template>
<script lang="ts" setup>
import { reactive, unref, ref, h } from 'vue';
import { BasicTable, TableAction } from '@/components/Table';
import { basicModal, useModal } from '@/components/Modal';
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
import { getTableList } from '@/api/table/list';
import { columns } from '../../comp/table/basicColumns';
import { jsonToSheetXlsx } from '@/components/Excel';
import { useDialog, useMessage } from 'naive-ui';
const schemas: FormSchema[] = [
{
field: 'filename',
component: 'NInput',
label: '文件名',
labelMessage: '导出的文件以该名称命名',
giProps: {
span: 1,
},
componentProps: {
placeholder: '请输入文件名称',
onInput: (e: any) => {
console.log(e);
},
},
rules: [{ required: true, message: '请输入导出的文件名称', trigger: ['blur'] }],
},
{
field: 'bookType',
component: 'NSelect',
label: '文件类型',
componentProps: {
placeholder: '请选择文件类型',
options: [
{
label: 'xlsx',
value: 'xlsx',
},
{
label: 'html',
value: 'html',
},
{
label: 'csv',
value: 'csv',
},
{
label: 'txt',
value: 'txt',
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
rules: [{ required: true, message: '请选择文件类型', trigger: ['change'] }],
},
];
const message = useMessage();
const dialog = useDialog();
const actionRef = ref();
const modalRef = ref();
const tableData = ref();
const params = reactive({
pageSize: 5,
name: 'xiaoMa',
});
const [modalRegister, { openModal }] = useModal({
title: '导出数据',
});
const [register, { submit }] = useForm({
gridProps: { cols: 1 },
collapsedRows: 3,
labelWidth: 120,
layout: 'horizontal',
showActionButtonGroup: false,
schemas,
});
const actionColumn = reactive({
width: 150,
title: '操作',
key: 'action',
fixed: 'right',
align: 'center',
render(record) {
return h(TableAction, {
style: 'button',
actions: createActions(record),
});
},
});
async function okModal() {
const formRes = await submit();
if (formRes) {
modalRef.value.closeModal();
message.success('提交成功');
} else {
message.error('验证失败,请填写完整信息');
modalRef.value.setSubLoading(false);
}
}
function handleReset(values: Recordable) {
console.log(values);
}
function createActions(record) {
return [
{
label: '删除',
onClick: handleDelete.bind(null, record),
// isShow auth
ifShow: () => {
return true;
},
// :
auth: ['basic_list'],
},
{
label: '编辑',
onClick: handleEdit.bind(null, record),
ifShow: () => {
return true;
},
auth: ['basic_list'],
},
];
}
const loadDataTable = async (res) => {
const result = await getTableList({ ...params, ...res });
tableData.value = result.list;
return result;
};
function onCheckedRow(rowKeys) {
console.log(rowKeys);
}
function handleDelete(record) {
console.log(record);
dialog.info({
title: '提示',
content: `您想删除${record.name}`,
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
message.success('删除成功');
},
onNegativeClick: () => {},
});
}
function handleEdit(record) {
console.log(record);
message.success('您点击了编辑按钮');
}
function handleSubmit(values: Recordable) {
console.log(values);
// Object.keys(data[0])header
const { filename, bookType } = values;
jsonToSheetXlsx({
data: unref(tableData),
filename: `${filename.split('.').shift()}.${bookType}`,
write2excelOpts: {
bookType,
},
});
message.success(JSON.stringify(values));
}
</script>
<style lang="less" scoped></style>

View File

@ -1,145 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="导出示例"> 根据JSON格式的数据进行导出 </n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<BasicTable
title="表格列表"
titleTooltip="这是一个提示"
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
ref="actionRef"
:actionColumn="actionColumn"
:scroll-x="1360"
@update:checked-row-keys="onCheckedRow"
>
<template #toolbar>
<n-space>
<n-button type="primary" @click="customHeader">导出自定义表头</n-button>
<n-button type="primary" @click="defaultHeader">导出默认表头</n-button>
</n-space>
</template>
</BasicTable>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, h, unref } from 'vue';
import { BasicTable, TableAction, BasicColumn } from '@/components/Table';
import { getTableList } from '@/api/table/list';
import { columns } from '../../comp/table/basicColumns';
import { jsonToSheetXlsx } from '@/components/Excel';
import { useDialog, useMessage } from 'naive-ui';
const message = useMessage();
const dialog = useDialog();
const actionRef = ref();
const tableData = ref();
const params = reactive({
pageSize: 5,
name: 'xiaoMa',
});
const actionColumn: BasicColumn = reactive({
width: 150,
title: '操作',
key: 'action',
fixed: 'right',
align: 'center',
render(record) {
return h(TableAction, {
style: 'button',
actions: createActions(record),
});
},
});
function createActions(record) {
return [
{
label: '删除',
onClick: handleDelete.bind(null, record),
// isShow auth
ifShow: () => {
return true;
},
// :
auth: ['basic_list'],
},
{
label: '编辑',
onClick: handleEdit.bind(null, record),
ifShow: () => {
return true;
},
auth: ['basic_list'],
},
];
}
const loadDataTable = async (res) => {
const result = await getTableList({ ...params, ...res });
tableData.value = result.list;
return result;
};
function onCheckedRow(rowKeys) {
console.log(rowKeys);
}
function handleDelete(record) {
console.log(record);
dialog.info({
title: '提示',
content: `您想删除${record.name}`,
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
message.success('删除成功');
},
onNegativeClick: () => {},
});
}
function handleEdit(record) {
console.log(record);
message.success('您点击了编辑按钮');
}
function defaultHeader() {
// Object.keys(data[0])header
jsonToSheetXlsx({
data: unref(tableData),
filename: '使用key作为默认表头.xlsx',
});
}
function customHeader() {
jsonToSheetXlsx({
data: unref(tableData),
header: {
id: 'ID',
no: '编码',
name: '名称',
avatar: '头像',
address: '地址',
beginTime: '开始日期',
endTime: '结束时间',
status: '状态',
date: '创建时间',
time: '停留时间',
},
filename: '自定义表头.xlsx',
json2sheetOpts: {
//
//header: ['id', 'no','name','avatar','address','beginTime','endTime','status','date','time'],
},
});
}
</script>
<style lang="less" scoped></style>

View File

@ -1,41 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="打印场景"> json打印表格图片打印 </n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-space>
<n-button type="primary" @click="jsonPrint">打印表格</n-button>
<n-button type="primary" @click="imagePrint">打印图片</n-button>
</n-space>
</n-card>
</div>
</template>
<script lang="ts" setup>
import printJS from 'print-js';
function jsonPrint() {
printJS({
printable: [
{ name: '汪伟', email: '735869@gmail.com', phone: '186****5653' },
{ name: '雷秀英', email: '235656452@gmail.com', phone: '135****6536' },
{ name: '邹芳', email: '24586526@gmail.com', phone: '159****5869' },
],
properties: ['name', 'email', 'phone'],
type: 'json',
});
}
function imagePrint() {
printJS({
printable: [
'https://naive-ui-admin-docs.vercel.app/logo.png',
'https://naive-ui-admin-docs.vercel.app/logo.png',
],
type: 'image',
header: 'Multiple Images',
imageStyle: 'width:100%;',
});
}
</script>

View File

@ -1,96 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="滚动场景"> 比如卡片列表文章列表滚动</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-alert title="UI框架内置滚动条" type="info"
>如果你只是想简单的实现一个滚动可以这么写
</n-alert>
<div class="mt-3 scrollbar-box">
<n-scrollbar>
<p v-for="item in list" :key="item.id">{{ item.name }}</p>
</n-scrollbar>
</div>
<n-alert class="mt-3" title="指令方式" type="info"
>基于perfect-scrollbar 使用方式可参考该插件
</n-alert>
<div class="mt-3 scrollbar-main">
<div v-scrollBar class="scrollbar-box">
<p v-for="item in list" :key="item.id">{{ item.name }}</p>
</div>
</div>
<n-alert class="mt-3" title="UI框架内置滚动条" type="info">演示函数触发滚动条位置</n-alert>
<div class="mt-3 scrollbar-box">
<n-scrollbar ref="scrollbar">
<p v-for="item in list" :key="item.id">{{ item.name }}</p>
</n-scrollbar>
</div>
<div class="mt-3">
<n-space>
<n-button @click="goScrollbar(120)">滚动到120位置</n-button>
<n-button @click="goScrollbar(900)">滚动到900位置</n-button>
<n-button @click="goScrollbar(0)">滚动到顶部</n-button>
<n-button @click="goScrollbar(99999)">滚动到底部</n-button>
</n-space>
</div>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import 'perfect-scrollbar/css/perfect-scrollbar.css';
interface IList {
id: string | number;
name: string;
}
function getList() {
const arr: IList[] = [];
for (let index = 0; index < 40; index++) {
arr.push({
id: `${index}`,
name: '这内容下面可能还有很多个,鼠标放进来使劲的滚动吧',
});
}
return arr;
}
const list = getList();
const scrollbar = ref();
function goScrollbar(y) {
scrollbar.value.scrollTo(0, y);
}
</script>
<style lang="less" scoped>
// 使 perfect-scrollbarDOM
// 使border/margin/padding
// bug;
.scrollbar-main {
width: 360px;
border: 1px solid #eee;
overflow: hidden;
}
.scrollbar-box {
width: 360px;
height: 350px;
overflow: hidden;
position: relative;
border-radius: 4px;
border: 1px solid #eee;
padding: 10px;
p {
padding: 5px 0;
color: #666;
}
}
</style>

View File

@ -1,69 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="多页签">
有些时候可能要操作多页签标题比如页面特定交互详情页面区分该操作仅限于当前打开过并且显示的标签
</n-card>
</div>
<n-card
:bordered="false"
title="多页签操作"
class="mt-3 proCard"
size="small"
:segmented="{ content: true }"
>
<n-space>
<n-button type="primary" @click="setTabsTitle">更新当前页面标题</n-button>
<n-button type="primary" @click="setTabsTitleSpecific">更新指定页面标题</n-button>
<n-button type="primary" @click="closeCurrent">关闭当前页</n-button>
</n-space>
<n-h2>设置多页签状态</n-h2>
<n-space>
<n-button type="warning" @click="setTabState('undone')">设置当前页面状态未完成</n-button>
<n-button type="success" @click="setTabState('done')">设置当前页面状态已完成</n-button>
</n-space>
</n-card>
</div>
</template>
<script lang="ts" setup>
import { onMounted } from 'vue';
import { useTabs } from '@/hooks/web/useTags';
import { useMessage } from 'naive-ui';
const useTagsHooks = useTabs();
const message = useMessage();
function setTabsTitle() {
useTagsHooks.setTitle('货品详情:编码-3695');
message.success('设置成功');
}
function setTabsTitleSpecific() {
useTagsHooks.setTitle('指定页面标题', { name: '/list/basic-list' });
message.success('设置成功');
}
function closeCurrent() {
useTagsHooks.closeCurrent();
}
function setTabState(state: string) {
useTagsHooks.setTabState({
state,
dialogOptions: {
content: '页面尚未提交,是否关闭?',
},
});
const msg =
state === 'undone'
? '设置成功,点击当前页标签关闭按钮,试试效果'
: '取消成功,当前页标签,可以正常关闭';
message.success(msg);
}
// onMounted
onMounted(() => {
//setTabsTitle();
});
</script>

View File

@ -1,374 +0,0 @@
<template>
<PageWrapper>
<div class="n-layout-page-header">
<n-card :bordered="false" title="高级表单">
当一次性提交大量数据时可使用高级表单根据自身情况选择是否使用 BasicForm
组件以下布局支持自适应
</n-card>
</div>
<n-form
ref="formRef"
:label-width="100"
:model="formValue"
:rules="rules"
label-placement="left"
>
<n-card
:bordered="false"
class="mt-3 proCard"
title="预约信息"
size="small"
:segmented="{
content: true,
}"
content-style="padding: 20px 20px 0 0;"
>
<n-grid cols="1 s:1 m:2 l:3 xl:4 2xl:4" responsive="screen">
<n-grid-item>
<n-form-item label="预约姓名" path="name">
<n-input v-model:value="formValue.name" placeholder="输入姓名" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="预约号码" path="mobile">
<n-input v-model:value="formValue.mobile" placeholder="电话号码" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="预约时间" path="datetime">
<n-date-picker class="w-full" v-model:value="formValue.datetime" type="datetime" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="预约医生" path="doctor">
<n-select
v-model:value="formValue.doctor"
:options="doctorList"
placeholder="请选择预约医生"
/>
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="预约事项" path="matter">
<n-select
v-model:value="formValue.matter"
:options="matterList"
multiple
placeholder="请选择预约事项"
/>
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="预约备注" path="remark">
<n-input v-model:value="formValue.remark" placeholder="请输入预约备注" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="预约备注" path="remark">
<n-input v-model:value="formValue.remark" placeholder="请输入预约备注" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="出生日期" path="dateBirth">
<n-date-picker class="w-full" v-model:value="formValue.dateBirth" type="datetime" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="性别" path="sex">
<n-radio-group v-model:value="formValue.sex" name="sex">
<n-space>
<n-radio :value="1"></n-radio>
<n-radio :value="2"></n-radio>
</n-space>
</n-radio-group>
</n-form-item>
</n-grid-item>
<!-- <div style="margin-left: 80px">-->
<!-- <n-space>-->
<!-- <n-button type="primary" @click="formSubmit">提交预约</n-button>-->
<!-- <n-button @click="resetForm">重置</n-button>-->
<!-- </n-space>-->
<!-- </div>-->
</n-grid>
</n-card>
<n-card
:bordered="false"
class="mt-3 proCard"
title="就诊信息"
size="small"
:segmented="{
content: true,
}"
content-style="padding: 20px 20px 0 0;"
>
<n-grid cols="1 s:1 m:2 l:3 xl:4 2xl:4" responsive="screen">
<n-grid-item>
<n-form-item label="过敏史" path="allergiChistory">
<n-input v-model:value="formValue.allergiChistory" placeholder="请输入过敏史" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="既往史" path="pastHistory">
<n-input v-model:value="formValue.pastHistory" placeholder="请输入既往史" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="传染史" path="contagion">
<n-input v-model:value="formValue.contagion" placeholder="请输入传染史" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="身份证号" path="idNo">
<n-input v-model:value="formValue.idNo" placeholder="请输入身份证号" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="介绍人" path="introducer">
<n-input v-model:value="formValue.introducer" placeholder="请输入介绍人" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="就诊医生" path="seeDoctor">
<n-select
v-model:value="formValue.seeDoctor"
:options="doctorList"
placeholder="请选择就诊医生"
/>
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="初诊日期" path="firstDatetime">
<n-date-picker
class="w-full"
v-model:value="formValue.firstDatetime"
type="datetime"
/>
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="近次复诊" path="subsequent">
<n-date-picker class="w-full" v-model:value="formValue.subsequent" type="datetime" />
</n-form-item>
</n-grid-item>
<!-- <n-grid-item>-->
<!-- <n-form-item label="图片" path="img">-->
<!-- <BasicUpload-->
<!-- v-model:value="uploadList"-->
<!-- :action="`${uploadUrl}/v1.0/files`"-->
<!-- :data="{ type: 0 }"-->
<!-- :headers="uploadHeaders"-->
<!-- :height="100"-->
<!-- :width="100"-->
<!-- helpText="单个文件不超过20MB最多只能上传10个文件"-->
<!-- name="files"-->
<!-- @uploadChange="uploadChange"-->
<!-- />-->
<!-- </n-form-item>-->
<!-- </n-grid-item>-->
</n-grid>
</n-card>
<n-card
:bordered="false"
class="mt-3 proCard"
title="就诊信息"
size="small"
:segmented="{
content: true,
}"
content-style="padding: 20px 20px 0 0;"
>
<n-grid cols="1 s:1 m:2 l:3 xl:4 2xl:4" responsive="screen">
<n-grid-item>
<n-form-item label="过敏史" path="allergiChistory">
<n-input v-model:value="formValue.allergiChistory" placeholder="请输入过敏史" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="既往史" path="pastHistory">
<n-input v-model:value="formValue.pastHistory" placeholder="请输入既往史" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="传染史" path="contagion">
<n-input v-model:value="formValue.contagion" placeholder="请输入传染史" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="身份证号" path="idNo">
<n-input v-model:value="formValue.idNo" placeholder="请输入身份证号" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="介绍人" path="introducer">
<n-input v-model:value="formValue.introducer" placeholder="请输入介绍人" />
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="就诊医生" path="seeDoctor">
<n-select
v-model:value="formValue.seeDoctor"
:options="doctorList"
placeholder="请选择就诊医生"
/>
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="初诊日期" path="firstDatetime">
<n-date-picker
class="w-full"
v-model:value="formValue.firstDatetime"
type="datetime"
/>
</n-form-item>
</n-grid-item>
<n-grid-item>
<n-form-item label="近次复诊" path="subsequent">
<n-date-picker class="w-full" v-model:value="formValue.subsequent" type="datetime" />
</n-form-item>
</n-grid-item>
<!-- <n-grid-item>-->
<!-- <n-form-item label="图片" path="img">-->
<!-- <BasicUpload-->
<!-- v-model:value="uploadList"-->
<!-- :action="`${uploadUrl}/v1.0/files`"-->
<!-- :data="{ type: 0 }"-->
<!-- :headers="uploadHeaders"-->
<!-- :height="100"-->
<!-- :width="100"-->
<!-- helpText="单个文件不超过20MB最多只能上传10个文件"-->
<!-- name="files"-->
<!-- @uploadChange="uploadChange"-->
<!-- />-->
<!-- </n-form-item>-->
<!-- </n-grid-item>-->
</n-grid>
</n-card>
</n-form>
<template #rightFooter>
<n-space>
<n-button @click="resetForm">重置</n-button>
<n-button type="primary" @click="formSubmit">提交</n-button>
</n-space>
</template>
</PageWrapper>
</template>
<script lang="ts" setup>
import { ref, unref, reactive } from 'vue';
import { PageWrapper } from '@/components/Page';
import { useMessage } from 'naive-ui';
import { FormRules } from 'naive-ui';
const matterList = [
{
label: '种牙',
value: 1,
},
{
label: '补牙',
value: 2,
},
{
label: '根管',
value: 3,
},
];
const doctorList = [
{
label: '李医生',
value: 1,
},
{
label: '黄医生',
value: 2,
},
{
label: '张医生',
value: 3,
},
];
const rules: FormRules = {
name: {
required: true,
message: '请输入预约姓名',
trigger: 'blur',
},
remark: {
required: true,
message: '请输入预约备注',
trigger: 'blur',
},
mobile: {
required: true,
message: '请输入预约电话号码',
trigger: ['input'],
},
datetime: {
required: true,
type: 'number',
message: '请选择预约时间',
trigger: ['blur', 'change'],
},
seeDoctor: {
required: true,
type: 'number',
message: '请选择就诊时间',
trigger: ['blur', 'change'],
},
firstDatetime: {
required: true,
type: 'number',
message: '请选择初诊时间',
trigger: ['blur', 'change'],
},
doctor: {
required: true,
type: 'number',
message: '请选择预约医生',
trigger: 'change',
},
};
const formRef: any = ref(null);
const message = useMessage();
const defaultValueRef = () => ({
name: '',
mobile: '',
remark: '',
sex: 1,
matter: null,
doctor: null,
datetime: [],
});
let formValue: any = reactive(defaultValueRef());
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
message.success('验证成功');
} else {
message.error('验证失败,请填写完整信息');
}
});
}
function resetForm() {
formRef.value.resetFields();
formValue = Object.assign(unref(formValue), defaultValueRef());
}
</script>

View File

@ -1,199 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="基础表单">
表单页用于向用户收集或验证信息基础表单常见于数据项较少的表单场景表单域标签也可支持响应式
</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-grid cols="1 s:1 m:3 l:3 xl:3 2xl:3" responsive="screen">
<n-grid-item offset="0 s:0 m:1 l:1 xl:1 2xl:1">
<n-form
ref="formRef"
:label-width="80"
:model="formValue"
:rules="rules"
class="py-8"
label-placement="left"
>
<n-form-item label="预约姓名" path="name">
<n-input v-model:value="formValue.name" placeholder="输入姓名" />
</n-form-item>
<n-form-item label="预约号码" path="mobile">
<n-input v-model:value="formValue.mobile" placeholder="电话号码" />
</n-form-item>
<n-form-item label="预约时间" path="datetime">
<n-date-picker v-model:value="formValue.datetime" type="datetime" />
</n-form-item>
<n-form-item label="预约医生" path="doctor">
<n-select
v-model:value="formValue.doctor"
:options="doctorList"
placeholder="请选择预约医生"
/>
</n-form-item>
<n-form-item label="预约事项" path="matter">
<n-select
v-model:value="formValue.matter"
:options="matterList"
multiple
placeholder="请选择预约事项"
/>
</n-form-item>
<n-form-item label="性别" path="sex">
<n-radio-group v-model:value="formValue.sex" name="sex">
<n-space>
<n-radio :value="1"></n-radio>
<n-radio :value="2"></n-radio>
</n-space>
</n-radio-group>
</n-form-item>
<n-form-item label="预约备注" path="remark">
<n-input
v-model:value="formValue.remark"
placeholder="请输入预约备注"
type="textarea"
/>
</n-form-item>
<n-form-item label="图片" path="img">
<BasicUpload
v-model:value="uploadList"
:action="`${uploadUrl}/v1.0/files`"
:data="{ type: '0' }"
:headers="uploadHeaders"
:height="100"
:width="100"
helpText="单个文件不超过20MB最多只能上传10个文件"
name="files"
@uploadChange="uploadChange"
/>
</n-form-item>
<div style="margin-left: 80px">
<n-space>
<n-button type="primary" @click="formSubmit">提交预约</n-button>
<n-button @click="resetForm">重置</n-button>
</n-space>
</div>
</n-form>
</n-grid-item>
</n-grid>
</n-card>
</div>
</template>
<script lang="ts">
export default {
name: 'BasicForm',
};
</script>
<script lang="ts" setup>
import { ref, unref, reactive } from 'vue';
import { useMessage, FormRules } from 'naive-ui';
import { BasicUpload } from '@/components/Upload';
import { useGlobSetting } from '@/hooks/setting';
const globSetting = useGlobSetting();
const matterList = [
{
label: '种牙',
value: 1,
},
{
label: '补牙',
value: 2,
},
{
label: '根管',
value: 3,
},
];
const doctorList = [
{
label: '李医生',
value: 1,
},
{
label: '黄医生',
value: 2,
},
{
label: '张医生',
value: 3,
},
];
const rules: FormRules = {
name: {
required: true,
message: '请输入预约姓名',
trigger: 'blur',
},
remark: {
required: true,
message: '请输入预约备注',
trigger: 'blur',
},
mobile: {
required: true,
message: '请输入预约电话号码',
trigger: ['input'],
},
datetime: {
required: true,
type: 'number',
message: '请选择预约时间',
trigger: ['blur', 'change'],
},
doctor: {
required: true,
type: 'number',
message: '请选择预约医生',
trigger: 'change',
},
};
const formRef: any = ref(null);
const message = useMessage();
const { uploadUrl } = globSetting;
const defaultValueRef = () => ({
name: '',
mobile: '',
remark: '',
sex: 1,
matter: null,
doctor: null,
datetime: [],
});
let formValue = reactive(defaultValueRef());
const uploadList = ref([
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
]);
const uploadHeaders: any = reactive({
platform: 'miniPrograms',
timestamp: new Date().getTime(),
token: 'Q6fFCuhc1vkKn5JNFWaCLf6gRAc5n0LQHd08dSnG4qo=',
});
function formSubmit() {
formRef.value.validate((errors) => {
if (!errors) {
message.success('验证成功');
} else {
message.error('验证失败,请填写完整信息');
}
});
}
function resetForm() {
formRef.value.restoreValidation();
formValue = Object.assign(unref(formValue), defaultValueRef());
}
function uploadChange(list: string[]) {
console.log(list);
}
</script>

View File

@ -1,124 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="表单详情">
表单除了提交数据有时也用于显示只读信息
</n-card>
</div>
<n-card
:bordered="false"
title="基本信息"
class="mt-3 proCard"
size="small"
:segmented="{ content: true }"
>
<n-descriptions label-placement="left" class="py-2">
<n-descriptions-item>
<template #label>收款人姓名</template>
啊俊
</n-descriptions-item>
<n-descriptions-item label="收款账户">NaiveUiAdmin@qq.com</n-descriptions-item>
<n-descriptions-item label="付款类型">支付宝</n-descriptions-item>
<n-descriptions-item label="付款账户">NaiveUiAdmin@163.com</n-descriptions-item>
<n-descriptions-item label="转账金额">1980.00</n-descriptions-item>
<n-descriptions-item label="状态">
<n-tag type="success"> 已到账</n-tag>
</n-descriptions-item>
</n-descriptions>
</n-card>
<n-card
:bordered="false"
title="其它信息"
class="mt-3 proCard"
size="small"
:segmented="{ content: true }"
>
<n-descriptions label-placement="left" class="py-2">
<n-descriptions-item>
<template #label>城市</template>
深圳
</n-descriptions-item>
<n-descriptions-item label="性别"></n-descriptions-item>
<n-descriptions-item label="邮箱">NaiveUiAdmin@qq.com</n-descriptions-item>
<n-descriptions-item label="地址">广东省深圳市南山区</n-descriptions-item>
<n-descriptions-item label="生日">1991-06-04</n-descriptions-item>
<n-descriptions-item label="认证">
<n-tag type="success"> 已认证</n-tag>
</n-descriptions-item>
</n-descriptions>
</n-card>
<n-card
:bordered="false"
title="表格信息"
class="mt-3 proCard"
size="small"
:segmented="{ content: true }"
>
<n-table :bordered="false" :single-line="false">
<thead>
<tr>
<th>姓名</th>
<th>性别</th>
<th>城市</th>
<th>生日</th>
<th width="150">操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ah jung</td>
<td></td>
<td>深圳</td>
<td>1993-11-09</td>
<td>
<n-space>
<n-button size="small" type="error">删除</n-button>
<n-button size="small" type="info">查看</n-button>
</n-space>
</td>
</tr>
<tr>
<td>西门飞雪</td>
<td></td>
<td>广州</td>
<td>1991-09-11</td>
<td>
<n-space>
<n-button size="small" type="error">删除</n-button>
<n-button size="small" type="info">查看</n-button>
</n-space>
</td>
</tr>
<tr>
<td>泰坦巨人</td>
<td></td>
<td>北京</td>
<td>1990-11-03</td>
<td>
<n-space>
<n-button size="small" type="error">删除</n-button>
<n-button size="small" type="info">查看</n-button>
</n-space>
</td>
</tr>
<tr>
<td>猎魔人</td>
<td></td>
<td>上海</td>
<td>1992-03-11</td>
<td>
<n-space>
<n-button size="small" type="error">删除</n-button>
<n-button size="small" type="info">查看</n-button>
</n-space>
</td>
</tr>
</tbody>
</n-table>
</n-card>
</div>
</template>
<script setup></script>
<style lang="less" scoped></style>

View File

@ -1,122 +0,0 @@
<template>
<n-form
ref="form1Ref"
:label-width="90"
:model="formValue"
:rules="rules"
label-placement="left"
style="max-width: 500px; margin: 40px auto 0 80px"
>
<n-form-item label="付款账户" path="myAccount">
<n-select
v-model:value="formValue.myAccount"
:options="myAccountList"
placeholder="请选择付款账户"
/>
</n-form-item>
<n-form-item label="收款账户" path="account">
<n-input-group>
<n-select
v-model:value="formValue.accountType"
:options="accountTypeList"
:style="{ width: '20%' }"
placeholder="请选择"
/>
<n-input
v-model:value="formValue.account"
:style="{ width: '80%' }"
placeholder="请输入收款账户"
/>
</n-input-group>
</n-form-item>
<n-form-item label="收款人姓名" path="name">
<n-input v-model:value="formValue.name" placeholder="请输入收款人姓名" />
</n-form-item>
<n-form-item label="转账金额" path="money">
<n-input v-model:value="formValue.money" placeholder="请输入转账金额">
<template #prefix>
<span class="text-gray-400"></span>
</template>
</n-input>
</n-form-item>
<div style="margin-left: 80px">
<n-space>
<n-button type="primary" @click="formSubmit">下一步</n-button>
</n-space>
</div>
</n-form>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { FormRules, useMessage } from 'naive-ui';
const myAccountList = [
{
label: 'NaiveUiAdmin@163.com',
value: 1,
},
{
label: 'NaiveUiAdmin@qq.com',
value: 2,
},
];
const accountTypeList = [
{
label: '微信',
value: 1,
},
{
label: '支付宝',
value: 2,
},
];
const emit = defineEmits(['nextStep']);
const form1Ref: any = ref(null);
const message = useMessage();
const formValue = ref({
accountType: 1,
myAccount: null,
account: 'xioama@qq.com',
money: '1980',
name: 'Ah jung',
});
const rules: FormRules = {
name: {
required: true,
message: '请输入收款人姓名',
trigger: 'blur',
},
account: {
required: true,
message: '请输入收款账户',
trigger: 'blur',
},
money: {
required: true,
message: '请输入转账金额',
trigger: 'blur',
},
myAccount: {
required: true,
type: 'number',
message: '请选择付款账户',
trigger: 'change',
},
};
function formSubmit() {
form1Ref.value.validate((errors) => {
if (!errors) {
emit('nextStep');
} else {
message.error('验证失败,请填写完整信息');
}
});
}
</script>

View File

@ -1,73 +0,0 @@
<template>
<n-form
ref="form2Ref"
:label-width="90"
:model="formValue"
:rules="rules"
label-placement="left"
style="max-width: 500px; margin: 40px auto 0 80px"
>
<n-form-item label="付款账户" path="myAccount">
<span>NaiveUiAdmin@163.com</span>
</n-form-item>
<n-form-item label="收款账户" path="account">
<span>NaiveUiAdmin@qq.com</span>
</n-form-item>
<n-form-item label="收款人姓名" path="name">
<span>Ah jung</span>
</n-form-item>
<n-form-item label="转账金额" path="money">
<span>1980</span>
</n-form-item>
<n-divider />
<n-form-item label="支付密码" path="password">
<n-input v-model:value="formValue.password" type="password" />
</n-form-item>
<div style="margin-left: 80px">
<n-space>
<n-button :loading="loading" type="primary" @click="formSubmit">提交</n-button>
<n-button @click="prevStep">上一步</n-button>
</n-space>
</div>
</n-form>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useMessage } from 'naive-ui';
const form2Ref: any = ref(null);
const message = useMessage();
const loading = ref(false);
const formValue = ref({
password: '086611',
});
const rules = {
password: {
required: true,
message: '请输入支付密码',
trigger: 'blur',
},
};
const emit = defineEmits(['prevStep', 'nextStep']);
function prevStep() {
emit('prevStep');
}
function formSubmit() {
loading.value = true;
form2Ref.value.validate((errors) => {
if (!errors) {
setTimeout(() => {
emit('nextStep');
}, 1500);
} else {
message.error('验证失败,请填写完整信息');
}
});
}
</script>

View File

@ -1,71 +0,0 @@
<template>
<div>
<n-result class="step-result" description="预计两小时内到账" status="success" title="操作成功">
<template #default>
<div class="information">
<n-grid class="my-1" cols="2 s:2 m:3 l:3 xl:3 2xl:3" responsive="screen">
<n-gi>付款账户</n-gi>
<n-gi>NaiveUiAdmin@163.com</n-gi>
</n-grid>
<n-grid class="my-1" cols="2 s:2 m:3 l:3 xl:3 2xl:3" responsive="screen">
<n-gi>收款账户</n-gi>
<n-gi>xiaoma@qq.com</n-gi>
</n-grid>
<n-grid class="my-1" cols="2 s:2 m:3 l:3 xl:3 2xl:3" responsive="screen">
<n-gi>收款人姓名</n-gi>
<n-gi>啊俊</n-gi>
</n-grid>
<n-grid class="my-1" cols="2 s:2 m:3 l:3 xl:3 2xl:3" responsive="screen">
<n-gi>转账金额</n-gi>
<n-gi><span class="money">1980</span> </n-gi>
</n-grid>
</div>
</template>
<template #footer>
<div class="flex justify-center">
<n-button class="mr-4" type="primary" @click="finish">再转一笔</n-button>
<n-button @click="prevStep">查看账单</n-button>
</div>
</template>
</n-result>
</div>
</template>
<script lang="ts" setup>
const emit = defineEmits(['finish', 'prevStep']);
function prevStep() {
emit('prevStep');
}
function finish() {
emit('finish');
}
</script>
<style lang="less" scoped>
.step-result {
max-width: 560px;
margin: 40px auto 0;
:deep(.n-result-content) {
background-color: #fafafa;
padding: 24px 40px;
}
.information {
line-height: 22px;
.ant-row:not(:last-child) {
margin-bottom: 24px;
}
}
.money {
font-family: 'Helvetica Neue', sans-serif;
font-weight: 500;
font-size: 20px;
line-height: 14px;
}
}
</style>

View File

@ -1,54 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="分步表单">
将一个冗长或用户不熟悉的表单任务分成多个步骤指导用户完成
</n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard">
<n-space vertical class="steps" justify="center">
<n-steps :current="currentTab" :status="currentStatus">
<n-step title="填写转账信息" description="确保填写正确" />
<n-step title="确认转账信息" description="确认转账信息" />
<n-step title="完成转账" description="恭喜您,转账成功" />
</n-steps>
<step1 v-if="currentTab === 1" @nextStep="nextStep" />
<step2 v-if="currentTab === 2" @nextStep="nextStep" @prevStep="prevStep" />
<step3 v-if="currentTab === 3" @prevStep="prevStep" @finish="finish" />
</n-space>
</n-card>
</div>
</template>
<script setup>
import { ref } from 'vue';
import step1 from './Step1.vue';
import step2 from './Step2.vue';
import step3 from './Step3.vue';
const currentTab = ref(1);
const currentStatus = ref('process');
function nextStep() {
if (currentTab.value < 3) {
currentTab.value += 1;
}
}
function prevStep() {
if (currentTab.value > 1) {
currentTab.value -= 1;
}
}
function finish() {
currentTab.value = 1;
}
</script>
<style lang="less" scoped>
.steps {
max-width: 750px;
margin: 16px auto;
}
</style>

View File

@ -1 +0,0 @@
<template> 项目文档 </template>

View File

@ -1,62 +0,0 @@
import { h } from 'vue';
import { TableImg } from '@/components/TableImg';
import { BasicColumn } from '@/components/Table';
export const columns: BasicColumn[] = [
{
type: 'selection',
width: 60,
},
{
title: 'id',
key: 'id',
width: 100,
sorter: (row1, row2) => row1.id - row2.id,
},
{
title: '名称',
key: 'name',
helpMessage: '这是一个提示,参数可以自定义',
helpMessageProps: {
showArrow: false,
},
width: 100,
},
{
title: '头像',
key: 'avatar',
width: 200,
render(row) {
return h(TableImg, {
imgList: [row.avatar, row.avatar],
spaceProps: {
justify: 'space-between',
},
});
},
},
{
title: '地址',
key: 'address',
auth: ['basic_list'], // 同时根据权限控制是否显示
ifShow: (_column) => {
return true; // 根据业务控制是否显示
},
width: 150,
},
{
title: '开始日期',
key: 'beginTime',
width: 160,
},
{
title: '结束日期',
key: 'endTime',
width: 160,
},
{
title: '创建时间',
key: 'date',
width: 100,
},
];

View File

@ -1,381 +0,0 @@
<template>
<div>
<n-card :bordered="false" class="pt-3 mb-3 proCard">
<BasicForm
@register="register"
@submit="handleSubmit"
@reset="handleReset"
@advanced="formAdvanced"
>
<template #statusSlot="{ model, field }">
<n-input v-model:value="model[field]" />
</template>
</BasicForm>
</n-card>
<n-card :bordered="false" class="proCard">
<BasicTable
:columns="columns"
:request="loadDataTable"
:row-key="(row) => row.id"
ref="tableRef"
:actionColumn="actionColumn"
@checked-row-change="onCheckedRow"
@columns-change="onColumnsChange"
:autoScrollX="true"
>
<template #tableTitle>
<n-button type="primary" @click="addTable">
<template #icon>
<n-icon>
<PlusOutlined />
</n-icon>
</template>
新建
</n-button>
</template>
<template #toolbar>
<n-button type="primary" @click="reloadTable">刷新数据</n-button>
</template>
</BasicTable>
</n-card>
<n-modal v-model:show="showModal" :show-icon="false" preset="dialog" title="新建">
<n-form
:model="formParams"
:rules="rules"
ref="formRef"
label-placement="left"
:label-width="80"
class="py-4"
>
<n-form-item label="名称" path="name">
<n-input placeholder="请输入名称" v-model:value="formParams.name" />
</n-form-item>
<n-form-item label="地址" path="address">
<n-input type="textarea" placeholder="请输入地址" v-model:value="formParams.address" />
</n-form-item>
<n-form-item label="日期" path="date">
<n-date-picker type="datetime" placeholder="请选择日期" v-model:value="formParams.date" />
</n-form-item>
</n-form>
<template #action>
<n-space>
<n-button @click="() => (showModal = false)">取消</n-button>
<n-button type="info" :loading="formBtnLoading" @click="confirmForm">确定</n-button>
</n-space>
</template>
</n-modal>
</div>
</template>
<script lang="ts" setup>
import { h, reactive, ref } from 'vue';
import { useMessage, FormRules } from 'naive-ui';
import { BasicTable, TableAction, BasicColumn } from '@/components/Table';
import { BasicForm, useForm, FormSchema } from '@/components/Form/index';
import { getTableList } from '@/api/table/list';
import { columns } from './columns';
import { PlusOutlined, DeleteOutlined, FormOutlined } from '@vicons/antd';
import { useRouter, useRoute } from 'vue-router';
import { renderIcon } from '@/utils';
const rules: FormRules = {
name: {
required: true,
trigger: ['blur', 'input'],
message: '请输入名称',
},
address: {
required: true,
trigger: ['blur', 'input'],
message: '请输入地址',
},
date: {
type: 'number',
required: true,
trigger: ['blur', 'change'],
message: '请选择日期',
},
};
const schemas: FormSchema[] = [
{
field: 'name',
labelMessage: '这是一个提示',
component: 'NInput',
label: '姓名',
componentProps: {
placeholder: '请输入姓名',
onInput: (e: any) => {
console.log(e);
},
},
// rules: [{ required: true, message: '', trigger: ['blur'] }],
},
{
field: 'mobile',
component: 'NInputNumber',
label: '手机',
componentProps: {
placeholder: '请输入手机号码',
showButton: false,
onInput: (e: any) => {
console.log(e);
},
},
},
{
field: 'type',
component: 'NSelect',
label: '类型',
componentProps: {
placeholder: '请选择类型',
options: [
{
label: '舒适性',
value: 1,
},
{
label: '经济性',
value: 2,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeDate',
component: 'NDatePicker',
label: '预约时间',
defaultValue: 1183135260000,
componentProps: {
type: 'date',
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeTime',
component: 'NTimePicker',
label: '停留时间',
componentProps: {
clearable: true,
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'status',
label: '状态',
//
slot: 'statusSlot',
},
{
field: 'makeProject',
component: 'NCheckbox',
label: '预约项目',
componentProps: {
placeholder: '请选择预约项目',
options: [
{
label: '种牙',
value: 1,
},
{
label: '补牙',
value: 2,
},
{
label: '根管',
value: 3,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
{
field: 'makeSource',
component: 'NRadioGroup',
label: '来源',
componentProps: {
options: [
{
label: '网上',
value: 1,
},
{
label: '门店',
value: 2,
},
],
onUpdateValue: (e: any) => {
console.log(e);
},
},
},
];
const router = useRouter();
const route = useRoute();
const formRef: any = ref(null);
const message = useMessage();
const tableRef = ref();
const showModal = ref(false);
const formBtnLoading = ref(false);
const formParams = reactive({
name: '',
address: '',
date: null,
});
const params = ref({
name: '',
id: route.params.id,
});
const actionColumn: BasicColumn = reactive({
width: 220,
title: '操作',
key: 'action',
fixed: 'right',
render(record) {
return h(TableAction as any, {
style: 'button',
actions: [
{
label: '删除',
type: 'error',
size: 'medium',
icon: renderIcon(DeleteOutlined),
onPositiveClick: handleDelete.bind(null, record),
onNegativeClick: handleNegative.bind(null, record),
isConfirm: true,
confirmContent: '您真的,确定要删除吗?',
positiveText: '确定删除',
},
{
label: '编辑',
type: 'warning',
size: 'medium',
icon: renderIcon(FormOutlined),
onPositiveClick: handleEdit.bind(null, record),
onNegativeClick: handleNegative.bind(null, record),
isConfirm: true,
confirmContent: '您真的,确定要编辑吗?',
},
],
dropDownProps: {
label: '更多',
type: 'info',
size: 'medium',
icon: renderIcon(DeleteOutlined),
// iconPlacement: 'left',
},
dropDownActions: [
{
label: '启用',
size: 'medium',
key: 'enabled',
// : enable
ifShow: () => {
return true;
},
},
{
label: '禁用',
key: 'disabled',
ifShow: () => {
return true;
},
},
],
select: (key) => {
message.info(`您点击了,${key} 按钮`);
},
});
},
});
const [register, {}] = useForm({
gridProps: { cols: '1 s:1 m:2 l:3 xl:4 2xl:4' },
labelWidth: 80,
schemas,
});
function onColumnsChange(columns) {
console.log('columns', columns);
}
function formAdvanced(status) {
console.log(status);
tableRef.value.redoHeight();
}
function addTable() {
showModal.value = true;
}
const loadDataTable = async (res) => {
return await getTableList({ ...formParams, ...params.value, ...res });
};
function onCheckedRow(rowKeys) {
console.log(rowKeys.value);
}
function reloadTable() {
tableRef.value.reload();
}
function confirmForm(e) {
e.preventDefault();
formBtnLoading.value = true;
formRef.value.validate((errors) => {
if (!errors) {
message.success('新建成功');
setTimeout(() => {
showModal.value = false;
reloadTable();
});
} else {
message.error('请填写完整信息');
}
formBtnLoading.value = false;
});
}
function handleEdit(record: Recordable) {
console.log('点击了编辑', record);
router.push({ name: 'BasicInfo', params: { id: record.id } });
}
function handleDelete(record: Recordable) {
console.log('点击了删除', record);
window['$message'].info('点击了删除');
}
function handleNegative(record: Recordable) {
console.log('点击了取消', record);
message.info('点击了取消');
}
function handleSubmit(values: Recordable) {
console.log(values);
params.value = Object.assign(formParams, values) as any;
reloadTable();
}
function handleReset(values: Recordable) {
console.log(values);
}
</script>
<style lang="less" scoped></style>

View File

@ -1,54 +0,0 @@
<template>
<div>
<div class="n-layout-page-header">
<n-card :bordered="false" title="基础详情"> 基础详情有时也用于显示只读信息 </n-card>
</div>
<n-card :bordered="false" class="mt-3 proCard" size="small" :segmented="{ content: true }">
<n-descriptions label-placement="left" class="py-2">
<n-descriptions-item>
<template #label>收款人姓名</template>
啊俊
</n-descriptions-item>
<n-descriptions-item label="收款账户">NaiveUiAdmin@qq.com</n-descriptions-item>
<n-descriptions-item label="付款类型">支付宝</n-descriptions-item>
<n-descriptions-item label="付款账户">NaiveUiAdmin@163.com</n-descriptions-item>
<n-descriptions-item label="转账金额">1980.00</n-descriptions-item>
<n-descriptions-item label="状态">
<n-tag type="success"> 已到账</n-tag>
</n-descriptions-item>
</n-descriptions>
<div class="w-full">
<n-space>
<label>测试页面缓存</label>
<n-input placeholder="输入点内容试试" />
<n-button type="primary" @click="setTabsTitle">更新当前页面标题</n-button>
</n-space>
</div>
</n-card>
</div>
</template>
<script lang="ts">
export default {
name: 'BasicInfo',
};
</script>
<script lang="ts" setup>
import { useMessage } from 'naive-ui';
import { useTabs } from '@/hooks/web/useTags';
import { useRoute } from 'vue-router';
const route = useRoute(); //
const useTagsHooks = useTabs();
const message = useMessage();
function setTabsTitle() {
const id = route.params && route.params.id;
useTagsHooks.setTitle(`基础详情id-${id}`, {
fullPath: `/list/basic-info/${id}`,
});
message.success('设置成功');
}
</script>
<style lang="less" scoped></style>

View File

@ -1,63 +0,0 @@
<template>
<n-card :bordered="false" class="proCard">
<div class="result-box">
<n-result status="error" title="操作失败" description="请核对并修改以下信息后,再重新提交。">
<div class="result-box-extra">
<p>您提交的内容有如下错误</p>
<p class="mt-3">
<n-space align="center">
<n-icon size="20" color="#f0a020">
<InfoCircleOutlined />
</n-icon>
<span>认证照片不够清晰</span>
<n-button type="info" text>立即修改</n-button>
</n-space>
</p>
<p class="mt-3">
<n-space>
<n-icon size="20" color="#f0a020">
<InfoCircleOutlined />
</n-icon>
<span>备注包含敏感字符并且不能包含政治相关</span>
<n-button type="info" text>立即修改</n-button>
</n-space>
</p>
</div>
<template #footer>
<div class="flex justify-center mb-4">
<n-space align="center">
<n-button type="info" @click="goHome">回到首页</n-button>
<n-button>查看详情</n-button>
<n-button>打印</n-button>
</n-space>
</div>
</template>
</n-result>
</div>
</n-card>
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router';
import { InfoCircleOutlined } from '@vicons/antd';
const router = useRouter();
function goHome() {
router.push('/');
}
</script>
<style lang="less" scoped>
.result-box {
width: 72%;
margin: 0 auto;
text-align: center;
padding-top: 5px;
&-extra {
padding: 24px 40px;
text-align: left;
background: var(--n-border-color);
border-radius: 4px;
}
}
</style>

View File

@ -1,67 +0,0 @@
<template>
<n-card :bordered="false" class="proCard">
<div class="result-box">
<n-result
status="info"
title="提示"
description="本次提交将在24小时候内自动转入对方账户如操作失误请及时撤回"
>
<div class="result-box-extra">
<p>您提交的内容如下</p>
<p class="mt-3">
<n-space align="center">
<n-icon size="20" color="#18a058">
<CheckCircleOutlined />
</n-icon>
<span>转入支付宝账户189****54261980</span>
<n-button type="info" text>立即撤回</n-button>
</n-space>
</p>
<p class="mt-3">
<n-space>
<n-icon size="20" color="#18a058">
<CheckCircleOutlined />
</n-icon>
<span>转入支付宝账户187****54262980</span>
<n-button type="info" text>立即撤回</n-button>
</n-space>
</p>
</div>
<template #footer>
<div class="flex justify-center mb-4">
<n-space align="center">
<n-button type="info" @click="goHome">回到首页</n-button>
<n-button>查看详情</n-button>
<n-button>全部撤回</n-button>
</n-space>
</div>
</template>
</n-result>
</div>
</n-card>
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router';
import { CheckCircleOutlined } from '@vicons/antd';
const router = useRouter();
function goHome() {
router.push('/');
}
</script>
<style lang="less" scoped>
.result-box {
width: 72%;
margin: 0 auto;
text-align: center;
padding-top: 5px;
&-extra {
padding: 24px 40px;
text-align: left;
background: var(--n-border-color);
border-radius: 4px;
}
}
</style>

View File

@ -1,48 +0,0 @@
<template>
<n-card :bordered="false" class="proCard">
<div class="result-box">
<n-result
status="success"
title="操作成功"
description="提交结果页用于反馈一系列操作任务的处理结果,如果仅是简单操作,灰色区域可以显示一些补充的信息。"
>
<div class="result-box-extra">
<p>已提交申请等待财务部门审核</p>
</div>
<template #footer>
<div class="flex justify-center mb-4">
<n-space align="center">
<n-button type="info" @click="goHome">回到首页</n-button>
<n-button>查看详情</n-button>
<n-button>打印</n-button>
</n-space>
</div>
</template>
</n-result>
</div>
</n-card>
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router';
const router = useRouter();
function goHome() {
router.push('/');
}
</script>
<style lang="less" scoped>
.result-box {
width: 72%;
margin: 0 auto;
text-align: center;
padding-top: 5px;
&-extra {
padding: 24px 40px;
text-align: left;
background: var(--n-border-color);
border-radius: 4px;
}
}
</style>

View File

@ -80,7 +80,7 @@
const [modalRegister, { openModal, setSubLoading }] = useModal({
title: '分配权限',
subBtuText: '确定',
width: 400,
width: 450,
});
/**