项目初始化
This commit is contained in:
parent
012025080d
commit
575c278572
@ -37,7 +37,7 @@ module.exports = {
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-redeclare': 'error',
|
||||
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [2],
|
||||
'@typescript-eslint/no-unused-vars': 'warning',
|
||||
'vue/custom-event-name-casing': 'off',
|
||||
'vue/attributes-order': 'off',
|
||||
'vue/one-component-per-file': 'off',
|
||||
|
@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
// 一行最多多少个字符
|
||||
printWidth: 150,
|
||||
printWidth: 100,
|
||||
// 指定每个缩进级别的空格数
|
||||
tabWidth: 2,
|
||||
// 使用制表符而不是空格缩进行
|
||||
|
367
CHANGELOG.md
367
CHANGELOG.md
@ -1,367 +0,0 @@
|
||||
# <a href="https://gitee.com/lyt-top/vue-next-admin" target="_blank">vue-next-admin 更新日志</a>
|
||||
|
||||
🎉🎉🔥 `vue-next-admin` 基于 vue3.x 、Typescript、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支)
|
||||
|
||||
## 2.2.0
|
||||
|
||||
`2022.07.10`
|
||||
|
||||
⚡⚡⚡ [/sec/stores/userInfo.ts](https://gitee.com/lyt-top/vue-next-admin/blob/master/src/stores/userInfo.ts) 下添加了 `getApiUserInfo` 接口模拟数据 `setTimeout` 为 3 秒
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🐞 修复 [主界面重新授权按钮点击卡死不跳转登录界面#I5C3JS](https://gitee.com/lyt-top/vue-next-admin/issues/I5C3JS),感谢[@Hero-Typ](https://gitee.com/tian_yu_peng)
|
||||
- 🐞 修复 编译警告[#I5CVSB](https://gitee.com/lyt-top/vue-next-admin/issues/I5CVSB),全局替换成 `:deep(attr)`,感谢[@Linvas](https://gitee.com/linvas)。参考文档:[vue3 sfc-style](https://v3.cn.vuejs.org/api/sfc-style.html#style-scoped)。`node_modules\print-js\dist\print.js` 需 `print-js` 作者适配或去除 `package.json` 中的 `"print-js": "^1.6.0"`
|
||||
- 🐞 修复 [vue-next-admin-template-js 版本前端控制路由:userInfo.js 请求用户信息接口报错,加载不到路由 可以写个定时器模拟一下接口 一样的报错#I5F1HP](https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP),感谢[@白开水](https://gitee.com/libin951223)
|
||||
|
||||
## 2.1.1
|
||||
|
||||
`2022.05.27`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 深色模式下,`<el-button text></el-button>` 时,`:active` 样式
|
||||
- 🎯 优化 [页面缓存在刷新之后失效 #I58U75](https://gitee.com/lyt-top/vue-next-admin/issues/I58U75)),感谢[@ls0428](https://gitee.com/ls0428)
|
||||
- 🎯 优化 [SvgIcon 对下载的 Svg 图像设置颜色无效 #I59ND0](https://gitee.com/lyt-top/vue-next-admin/issues/I59ND0)),感谢[@elus_z](https://gitee.com/elus_z)
|
||||
- 🎯 优化 `/src/utils/toolsValidate.ts` 工具类
|
||||
- 🐞 修复 [布局切换,TagsView 显示的 tab 会多一个出来 #I58WGM](https://gitee.com/lyt-top/vue-next-admin/issues/I58WGM),感谢[@lg_boy](https://gitee.com/lg_boy)
|
||||
- 🐞 修复 [如果设置顶部面包屑导航开启图标 isBreadcrumbIcon=true 后,样式有点问题 如果不开启就是正常的 #I58VB8](https://gitee.com/lyt-top/vue-next-admin/issues/I58VB8)
|
||||
- 🐞 修复 地址栏路由地址输入错误时,返回首页后,再次输入路由地址错误时,不跳转 404 问题
|
||||
- 🐞 修复 [2.1.0 版本的图标选择组件多次点击后功能失效 #I590TH](https://gitee.com/lyt-top/vue-next-admin/issues/I590TH),感谢[@quber](https://gitee.com/quber)
|
||||
|
||||
## 2.1.0
|
||||
|
||||
`2022.04.18`
|
||||
|
||||
⚡⚡⚡ 此版本为破环性更新,优化内容如下:(谨慎更新!谨慎更新!!谨慎更新!!!)。因为 `vuex` 替换成 `pinia`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 部分界面图片不显示问题(更换 gitee 在线图片地址源)
|
||||
- 🎯 优化 各界面方法引入与逻辑之间添加一行空行,方便区分内容
|
||||
- 🎯 优化 图标选择器 [#I4YAHB](https://gitee.com/lyt-top/vue-next-admin/issues/I4YAHB),感谢[@真有你的](https://gitee.com/sunliusen)
|
||||
- 🎯 优化 图标选择器 icon type 类型为 all 时,类型 ali、ele、awe 回显问题
|
||||
- 🎯 优化 去掉开发环境 i18n 控制台警告,页面代码:[i18n/index.ts](https://gitee.com/lyt-top/vue-next-admin/blob/master/src/i18n/index.ts)
|
||||
- 🎯 优化 `NextLoading.start()` 方法,防止第一次进入界面时出现短暂空白
|
||||
- 🎯 优化 地址栏有参数退出登录,再次登录不跳之前界面问题 `src/layout/navBars/breadcrumb/user.vue`
|
||||
- 🎯 优化 `SvgIcon` 组件,防止 `开启 Tagsview 图标` 时,`tagsView 右键菜单关闭` 报错问题,工作流不可连线、全屏时关闭按钮消失问题
|
||||
- 🎯 优化 [如果 url 中有中文等特殊字符,第一次切换该 tab 时 keep-alive 失效#I55JS7](https://gitee.com/lyt-top/vue-next-admin/issues/I55JS7),感谢[yuyong1566](https://gitee.com/yuyong1566)
|
||||
- 🎯 优化 [wangEditor](https://www.wangeditor.com/) 更新到 v5,[vue3 版本线上示例中 wangeditor 富文本编辑器 demo 实例,无法换行#I5565B](https://gitee.com/lyt-top/vue-next-admin/issues/I5565B),感谢@[jenchih](https://gitee.com/jenchih)
|
||||
- 🎯 优化 [在关闭 tagview 时,高度刷新时会会变化,出现滚动条](https://gitee.com/lyt-top/vue-next-admin/issues/I55FHM),感谢[张松](https://gitee.com/zs310071113)
|
||||
- 🎯 优化 [路由参数](https://lyt-top.gitee.io/vue-next-admin-preview/#/params/common)演示
|
||||
- 🎉 新增 [vuex](https://vuex.vuejs.org/) 替换成 [pinia](https://pinia.vuejs.org/getting-started.html)
|
||||
- 🎉 新增 tagsView 支持自定义 tagsView 名称(文章详情时有用),前往体验:[路由参数/普通路由](https://lyt-top.gitee.io/vue-next-admin-preview/#/params/common)。新增 tagsView 支持自定义名称国际化,感谢[@q7but](https://gitee.com/q7but)、[!22 add 添加自定义 tagVIewName 拓展,支持国际化](https://gitee.com/lyt-top/vue-next-admin/pulls/22/files)、感谢[@tony_tong_xin](https://gitee.com/tony_tong_xin)
|
||||
- 🐞 修复 适配 `"element-plus": "^2.1.9",2.2.0` 版本
|
||||
- 🐞 修复 [导航栏横向布局后,一级菜单显示问题#I4Z3M3](https://gitee.com/lyt-top/vue-next-admin/issues/I4Z3M3)
|
||||
- 🐞 修复 横向布局三级及以上导航菜单高亮、导航高度不统一问题
|
||||
- 🐞 修复 分栏模式下,选中的菜单是 primary 样式,鼠标移入字也变成 primary 色了,感谢群友@孤夜-流殇
|
||||
- 🐞 修复 [vuex 里面改了颜色 但是不生效 #I4WFMA](https://gitee.com/lyt-top/vue-next-admin/issues/I4WFMA)
|
||||
- 🐞 修复 全局主题 primary 清空颜色后报错,[#I4X0LG](https://gitee.com/lyt-top/vue-next-admin/issues/I4X0LG),感谢[面向 BUG 编程](https://gitee.com/fhtfy)
|
||||
- 🐞 修复 [.eslintrc.js 文件 rules 标签名错误 #I53IPK](https://gitee.com/lyt-top/vue-next-admin/issues/I53IPK),感谢[yuyong1566](https://gitee.com/yuyong1566)
|
||||
- 🐞 修复 `开启 Tagsview 图标` 时,`tagsView 右键菜单关闭` 报错问题
|
||||
- 🐞 修复 `router.push` 路径找不到时报错问题,`404、401 界面` 已移入到 `main` 主布局里(之前全屏)
|
||||
- 🐞 修复 [全局修改组件大小失效了](https://gitee.com/lyt-top/vue-next-admin/issues/I551RP),感谢[lg_boy](https://gitee.com/lg_boy)
|
||||
- 🐞 修复 [修改一下配置时,需要每次都清理 `window.localStorage` 浏览器永久缓存,配置才会生效,问题解决#I567R1](https://gitee.com/lyt-top/vue-next-admin/issues/I567R1),感谢[@lanbao123](https://gitee.com/lanbao123)
|
||||
- 🐞 修复 [标记为需要缓存的 tab 页后,再次从左侧菜单打开,还是显示被缓存的页面内容#I4UY3G](https://gitee.com/lyt-top/vue-next-admin/issues/I4UY3G),感谢@axcc1234、特别感谢群友@华仔
|
||||
- 🌈 重构 路由(`/src/router/index.ts`)解决 No match found for location with path "xxx"(前端控制,后端控制未解决) 问题
|
||||
|
||||
## 2.0.2
|
||||
|
||||
`2022.03.04`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 Alert 提示添加边框
|
||||
- 🎯 优化 功能 / 数字滚动 演示界面
|
||||
- 🐞 修复 全局主题按钮颜色 :active 问题
|
||||
- 🐞 修复 Dropdown 下拉菜单样式问题
|
||||
- 🐞 修复 SvgIcon 图标组件动态切换时报警告问题,[SvgIcon 改变 name 时可能导致图像不显示](https://gitee.com/lyt-top/vue-next-admin/issues/I4VGE0),感谢@axcc1234
|
||||
|
||||
## 2.0.1
|
||||
|
||||
`2022.02.25`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 svgIcon 图标组件
|
||||
- 🎯 优化 vite.config.ts 打包,感谢群友@YourObjec
|
||||
- 🐞 修复 tagViews 开启图标不显示问题(风格 5),感谢群友@坏人
|
||||
- 🐞 修复 [Element Plus 1.2.0-beta.6 以后的版本 el-table 在移动端无法左右滑动](https://gitee.com/lyt-top/vue-next-admin/issues/I4UPTP),感谢@YGDada
|
||||
|
||||
## 2.0.0
|
||||
|
||||
`2022.02.21`
|
||||
|
||||
⚡⚡⚡ 此版本为破环性更新,优化内容如下:(谨慎更新!谨慎更新!!谨慎更新!!!)。演示界面建议直接覆盖文件。如需使用之前版本,请前往[gitee 发行版](https://gitee.com/lyt-top/vue-next-admin/releases) 进行对应版本下载。基础版会基于 `master` 分支进行修改
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🌟 更新 登录页、首页
|
||||
- 💔 移除 vue-web-screen-shot
|
||||
- 💔 移除 城市多级联动,完整 json 数据请去 [vue-next-admin-images/menu](https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu) 仓库查看
|
||||
- 💔 移除 功能/echartsTree 树图
|
||||
- 💔 移除 其它设置/Tagsview 风格 2、Tagsview 风格 3
|
||||
- 💔 移除 功能/验证器
|
||||
- 🚧 调整 src/api 编写方式
|
||||
- 🚧 调整 自定义封装公用组件演示,更好的维护
|
||||
- 🎉 新增 Volar 支持,vs code 配置参考 [Vue Language Features (Volar)](https://lyt-top.gitee.io/vue-next-admin-doc-preview/home/vscode/)
|
||||
- 🎉 新增 `SvgIcon` 支持本地 svg 图标使用
|
||||
- 🎉 新增 表单表格验证演示
|
||||
- 🎯 优化 全局主题(移除 success、info、warning、danger)
|
||||
- 🎯 优化 工作流(开源)
|
||||
- 🎯 优化 element plus svg 图标,`elementXXX` 改成 `ele-XXX`
|
||||
- 🌈 重构 深色模式
|
||||
- 🌹 合并 [处理 parent 的 h100 由于外层有 min-height 导致失效的问题](https://gitee.com/lyt-top/vue-next-admin/pulls/20),感谢@MaxNull、@21030442-mao
|
||||
- 🐞 修复 element plus 升级 `^1.3.0-beta.5` 后 组件 size 大小问题(大改:涉及布局、演示界面)
|
||||
- 🐞 修复 vs code 使用 Vue Language Features (Volar) 插件 代码报红问题(可以把公用的 ts 类型定义封装起来公用)
|
||||
|
||||
## 1.2.2
|
||||
|
||||
`2021.12.21`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 iframes 滚动条问题
|
||||
- 🎯 优化 部署后每次都要强制刷新清浏览器缓存问题
|
||||
- 🎉 新增 工具类百分比验证演示
|
||||
- 🐞 修复 [tag-view 标签右键会超出浏览器 #I4KN78](https://gitee.com/lyt-top/vue-next-admin/issues/I4KN78)
|
||||
|
||||
## 1.2.1
|
||||
|
||||
`2021.12.12`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 cropper 裁剪时卡顿问题 [#I4M2VQ](https://gitee.com/lyt-top/vue-next-admin/issues/I4M2VQ)
|
||||
- 🎯 优化 Wangeditor 富文本编辑器的问题 [#I4LPC1](https://gitee.com/lyt-top/vue-next-admin/issues/I4LPC1)、[#I4LM7I](https://gitee.com/lyt-top/vue-next-admin/issues/I4LM7I)
|
||||
- 🐞 修复 浏览器标题问题
|
||||
- 🐞 修复 element plus svg 图标引入
|
||||
- 🐞 修复 工作流不可以拖线连接问题
|
||||
|
||||
## 1.2.0
|
||||
|
||||
`2021.11.28`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 深色模式
|
||||
- 🎯 优化 `/@/utils` 文件夹,合并删除单一内容
|
||||
- 🎯 优化 系统设置:菜单管理(新增、修改)、角色管理(新增菜单权限)、用户管理、部门管理、字典管理
|
||||
- 🎯 优化 登录界面逻辑、权限管理逻辑
|
||||
- 🎯 优化 同步 [vue-next-admin-images](https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu) 后端控制菜单模拟数据
|
||||
- 🎉 新增 适配 Font Icon 向 SVG Icon 迁移(改动大,"element-plus": "^1.2.0-beta.4" 谨慎更新)
|
||||
- 🐞 修复 热更新问题,感谢@甜蜜蜜
|
||||
- 🐞 修复 页面/element 字体图标演示
|
||||
- 🐞 修复 功能/图标选择器演示,新增高级功能 [issues #I4GJXQ](https://gitee.com/lyt-top/vue-next-admin/issues/I4GJXQ)
|
||||
|
||||
## 1.1.2
|
||||
|
||||
`2021.10.17`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🐞 修复 开启全屏时,刷新界面被还原成未全屏的状态
|
||||
- 🎯 优化 tagsView 右键菜单关闭逻辑
|
||||
- 🎯 优化 wangeditor 富文本编辑器(增加双向绑定)
|
||||
- 🎉 新增 工作流(暂不开源)
|
||||
- 🎉 新增 基础版 ts(不带国际化),切换 `vue-next-admin-template` 分支
|
||||
|
||||
## 1.1.1
|
||||
|
||||
`2021.09.25`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本(`"element-plus": "^1.1.0-beta.13"` 版本运行错误,`^1.1.0-beta.16`修复横向菜单卡死问题)
|
||||
- 🐞 修复 Dialog 弹窗位置错误、Drawer 抽屉内边距、el-menu 菜单收起时背景色问题
|
||||
- 🎯 优化 锁屏界面自动锁屏(s/秒)必须设置至少 1 秒
|
||||
- 🎉 新增 分栏布局,鼠标移入当前项时,显示当前项菜单内容
|
||||
- 🎉 新增 工作流(未完成)
|
||||
|
||||
## 1.1.0
|
||||
|
||||
`2021.09.10`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 小屏模式下登录页二维码遮挡标题问题
|
||||
- 🎉 新增 图片验证器
|
||||
- 🎉 新增 动态复杂表单
|
||||
- 🎉 新增 工作流(未完成)
|
||||
- 🎉 新增 深色主题(伪深色,样式变动大,谨慎更新)
|
||||
|
||||
## 1.0.18
|
||||
|
||||
`2021.08.29`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 权限组件去掉顶级 div(`/src/components/auth`)
|
||||
- 🎉 新增 布局配置添加恢复默认按钮
|
||||
- 🐞 修复 升级 <a href="https://element-plus.gitee.io/#/zh-CN/component/changelog" target="_blank">element plus 1.1.0-beta.7</a>后项目无法启动、el-menu 菜单
|
||||
- 🐞 修复 表格固定列时的层级、设置了相对定位时,遮挡左侧导航菜单问题
|
||||
|
||||
## 1.0.17
|
||||
|
||||
`2021.08.22`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 去除设置布局切换,重置主题样式(initSetLayoutChange),切换布局需手动设置样式,设置的样式自动同步各布局
|
||||
- 🎯 优化 Dropdown 下拉菜单用户账号靠边时换行问题
|
||||
- 🎯 优化 左侧导航菜单,共用菜单树,防止 `布局配置` 设置 `菜单 / 顶栏` 时,样式丢失等问题
|
||||
- 🐞 修复 固定 header 后没有回到顶部的 bug,拉取项目后运行不起来的 bug。<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/14" target="_blank">!14</a>,感谢<a href="https://gitee.com/wjs0509" target="_blank">@wjs0509</a>
|
||||
- 🐞 修复 tagView 右键全屏后,浏览器窗口大小发生任何变化都会导致左边菜单显示出来,并且可点击打开对应页面。<a href="https://gitee.com/lyt-top/vue-next-admin/issues/I46E6T" target="_blank">I46E6T</a>
|
||||
- 🐞 修复 默认设置 `菜单 / 顶栏` 样式不生效问题(/@/src/store/modules/themeConfig.ts)
|
||||
|
||||
## 1.0.16
|
||||
|
||||
`2021.08.14`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 菜单高亮(详情且详情设置了 meta.isHide 时,顶级菜单高亮),感谢群友@YourObject
|
||||
- 🎯 优化 详情路径写法:如父级(/pages/filtering),那么详情为(/pages/filtering/details?id=1)。这样写可实现(详情时,父级菜单高亮),否则写成(/pages/filteringDetails?id=1)顶级菜单将不会高亮。可参考:`页面/过滤筛选组件`,点击当前图片进行测试
|
||||
- 🎯 优化 tagsView 右键菜单全屏时,打开的界面高度问题
|
||||
- 🎯 优化 图表批量 resize 问题
|
||||
- 🐞 修复 菜单收起时(设置全局主题:primary 且有二级菜单时),文字高亮颜色不对
|
||||
- 🐞 修复 国际化 <a href="https://gitee.com/lyt-top/vue-next-admin/issues/I43NPE" target="_blank">#I43NPE</a>。可参考:`页面/过滤筛选组件`,点击顶部语言切换,进行底部分页国际化查看
|
||||
|
||||
## 1.0.15
|
||||
|
||||
`2021.08.06`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 tagsView 右键菜单点击时的字段名(id 已修改成 contextMenuClickId)与路由中返回的 id 名冲突问题,感谢群友@伯牙已遇钟子期
|
||||
- 🎉 新增 多个 form 表单验证界面演示
|
||||
|
||||
## 1.0.14
|
||||
|
||||
`2021.07.29`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本(vue、vuex、vue-router),出现问题,请手动降级。版本查看:<a href="https://www.npmjs.com/" target="_blank">vnpm</a>
|
||||
- 🎯 优化 数据可视化图表演示加载卡顿问题、优化有图表的演示界面
|
||||
- 🎯 优化 路由参数演示界面
|
||||
- 🎯 优化 tagsView 操作演示界面,由于存在相同路由多标签,必须要传全部参数值(query 或者 params)
|
||||
- 🎉 新增 开启 TagsView 共用,开启时:(多个路由菜单共用一个详情组件(参数为后点击的覆盖前面点击的),tagsView 中只会出现一个(不支持同时出现多个 tagsView 标签))。关闭时:(多个路由菜单共用一个详情组件,参数不同,会同时出现多个 tagsView 标签)
|
||||
- 🐞 修复 tagsView 共用(单标签)时,右键菜单功能点击,参数不对的问题(第 2n+个参数未覆盖第一个参数值)
|
||||
- 🐞 修复 多 tagsView 标签(参数不同)、单个 tagsView 标签公用(参数不同)所带来的刷新功能、横向自动滚动等问题
|
||||
- 🐞 修复 处理全屏若干问题,<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/12" target="_blank">pr!12</a>,感谢群友@另一个前端
|
||||
|
||||
## 1.0.13
|
||||
|
||||
`2021.07.25`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎉 新增 数据可视化演示界面(/visualizingDemo1、/visualizingDemo2)
|
||||
- 🎉 新增 登录页扫码登录
|
||||
|
||||
## 1.0.12
|
||||
|
||||
`2021.07.16`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎉 新增 数据可视化演示空界面(待完善)
|
||||
- 🎯 优化 tagsView 动态路由(xxx/:id/:name)时的右键菜单刷新、关闭其它时参数丢失问题(2021.07.15 优化)
|
||||
- 🐞 修复 路由带参数时,复制路径到登录页,跳转后参数消失的问题
|
||||
- 🐞 修复 设置多个外链,点击后,页面内容停留在上一个内容(内容未改变)、国际化处理、打开新窗口 sessionStorage 共享等
|
||||
|
||||
## 1.0.11
|
||||
|
||||
`2021.07.14`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎉 新增 路由参数、图片懒加载界面演示
|
||||
- ⚠️ 警告 Form 表单 `binding value must be a string or number`,解决:加上 `label-position="top"` 不报警告(等待官方修复)
|
||||
- 🎯 优化 锁屏界面动画效果、首页图表显示
|
||||
- 🎯 优化 tagsView 右键菜单 `关闭` 功能逻辑
|
||||
- 🐞 修复 开启 TagsView 拖拽报错及小于 `1000px` 时自动设置禁止拖拽(<a href="https://gitee.com/lyt-top/vue-next-admin/issues/I3ZRRI" target="_blank">#I3ZRRI</a>)
|
||||
- 🐞 修复 `iframe 内嵌、外链` 高度问题,使用 computed 进行计算
|
||||
- 🐞 修复 默认布局开启 `侧边栏 Logo` 与关闭 `菜单水平折叠`,切换到横向布局时,菜单看不见的问题
|
||||
- 🐞 修复 切换不同布局时,再去开启 `经典布局分割菜单` 功能不生效问题
|
||||
- 🐞 修复 浏览器窗口标题中/英文切换不实时生效的问题
|
||||
- 🐞 修复 切换布局时,某些功能不可以使用。部分界面不需要取消事件监听(proxy.mittBus.off('xxx'))
|
||||
- 🐞 修复 动态路由带参数,router-link 跳转问题(<a href="hhttps://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G" target="_blank">#I3YX6G</a>)
|
||||
- 🐞 修复 横向菜单有二级菜单时,点击子级菜单不高亮问题
|
||||
- 🐞 修复 功能 tagsView 操作演示不生效
|
||||
|
||||
## 1.0.10
|
||||
|
||||
`2021.07.07`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本(字体图标无问题)
|
||||
- 🎯 优化 内嵌 iframe、外链,解决 tagsView 刷新问题
|
||||
|
||||
## 1.0.9
|
||||
|
||||
`2021.07.02`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎯 优化 图标选择器设置宽度、v-model 等问题
|
||||
- 🎯 优化 滚动通知栏在手机上的体验
|
||||
- 🎯 优化 系统管理/新增菜单(编辑菜单),使用 `图标选择器` 进行模拟
|
||||
- 🎯 优化 字体图标(自动载入) 逻辑
|
||||
- 🐞 修复 screenfull 全屏时,按键盘 esc 键图标不改变问题,感谢群友@伯牙已遇钟子期
|
||||
|
||||
## 1.0.8
|
||||
|
||||
`2021.06.29`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎉 新增 表单中英文切换演示
|
||||
- 🎯 优化 登录页查看密码 icon 图标
|
||||
- 🎯 优化 图标选择器
|
||||
- 🎯 优化 拖动指令
|
||||
- 🐞 修复 form 表单在页面小于 576px 时的排版问题
|
||||
|
||||
## 1.0.7
|
||||
|
||||
`2021.06.24`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🎉 新增 拖动指令及其演示界面
|
||||
- 🎯 优化 锁屏界面,解锁提示
|
||||
- 🎯 优化 登录页在手机上显示的效果
|
||||
|
||||
## 1.0.6
|
||||
|
||||
`2021.06.23`
|
||||
|
||||
- 🎯 优化 去掉内嵌 iframe 内边距(padding)
|
||||
- 🎯 优化 城市多级联动组件
|
||||
- 🎯 优化 Tree 树形控件改成表格组件
|
||||
- 🐞 修复 Cascader 级联选择器高度问题
|
||||
|
||||
## 1.0.5
|
||||
|
||||
`2021.06.22`
|
||||
|
||||
- 🌟 更新 vite 降级为@vite2.3.7,降级方法 `cnpm install vite@2.3.7`,防止 element plus 字体图标消失
|
||||
- 🐞 修复 开启后端控制路由(isRequestRoutes = true)时,内嵌 iframe、外链不可使用的问题
|
||||
|
||||
## 1.0.4
|
||||
|
||||
`2021.06.19`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本("vite": "^2.3.7")热更新无问题
|
||||
- 🎉 新增 深克隆工具,方便开发,感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/6" target="_blank">#6</a>)
|
||||
- 🎯 优化 vuex 模块自动导入。感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/4" target="_blank">#4</a>),感谢群友@web 小学生-第五君
|
||||
- 🎯 优化 类型定义提高编码体验,修复不能将类型“string | undefined”分配给类型“string”的问题。感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/5" target="_blank">#5</a>)
|
||||
- 🎯 优化 `layout` 文件夹移动到与 `views` 文件夹同级(改动较大,`/@/views/layout` 变成 `/@/layout`)
|
||||
- 🎯 优化 页面有 `console.log` 时 `eslint` 不生效问题
|
||||
- 🎯 优化 页面、ts 中 `any` 类型问题(改动较大)
|
||||
- 🎯 优化 登录页在手机上显示的效果
|
||||
- 🎯 优化 多行注释信息,鼠标放到方法名即可查看,更加直观的知道方法参数等。引入方法时需去掉以 `.ts` 结尾的后缀(改动较大)
|
||||
- 🎯 优化 移除 `utils/storage.ts` 下的旧写法(改动较大)
|
||||
- 🎯 优化 拆分 `router` 下内容,路由、前端、后端控制分开写,方便理解
|
||||
- 🐞 修复 鼠标移入顶部用户信息栏 `开/关全屏` 文字反向问题
|
||||
- 🐞 修复 热更新时,NextLoading(界面 loading) 不消失问题 `window.nextLoading === undefined`
|
||||
- 🐞 修复 vuex 中不可以使用 `/@/api/xxx` 下的接口调用问题
|
||||
|
||||
## 1.0.3
|
||||
|
||||
`2021.06.02`
|
||||
|
||||
- ❄️ 删除 G6 思维导图界面
|
||||
- 🌟 更新 手动更新 vue、vue-router、vuex 到最近最多人使用的版本,出现不可预测的问题请降低版本。版本查看:<a href="https://www.npmjs.com/package/vue" target="_blank">vue 版本查看</a>
|
||||
- 🐞 修复 开启后端控制路由 `isRequestRoutes` 在非首页刷新页面后,回到首页的问题,感谢群友@伯牙已遇钟子期
|
||||
|
||||
## 1.0.2
|
||||
|
||||
`2021.06.01`
|
||||
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🐞 修复 菜单搜索中文不可以搜索的问题,感谢群友@逍遥天意
|
||||
|
||||
## 1.0.1
|
||||
|
||||
`2021.05.31`
|
||||
|
||||
- 🎉 新增 更新日志文件 `CHANGELOG.md`,以后每次更新都会在这里显示对应内容
|
||||
- 🌟 更新 依赖更新最新版本
|
||||
- 🐞 修复 分栏、经典布局路由设置 `meta.isHide` 为 `true` 时报错问题,感谢群友@29、@芭芭拉
|
||||
- 🐞 修复 经典布局点击 `tagsView` 左侧菜单数据不变问题
|
21
LICENSE
21
LICENSE
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 lyt-Top
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
57
README.md
57
README.md
@ -1,57 +0,0 @@
|
||||
<div align="center">
|
||||
<img src="https://yxh-1301841944.cos.ap-chongqing.myqcloud.com/gfast/2022-04-19/gfastlogo.png">
|
||||
<p align="center">
|
||||
<a href="https://v3.vuejs.org/" target="_blank">
|
||||
<img src="https://img.shields.io/badge/vue.js-vue3.x-green" alt="vue">
|
||||
</a>
|
||||
<a href="https://element-plus.gitee.io/#/zh-CN/component/changelog" target="_blank">
|
||||
<img src="https://img.shields.io/badge/element--plus-%3E1.0.0-blue" alt="element plus">
|
||||
</a>
|
||||
<a href="https://www.tslang.cn/" target="_blank">
|
||||
<img src="https://img.shields.io/badge/typescript-%3E4.0.0-blue" alt="typescript">
|
||||
</a>
|
||||
<a href="https://vitejs.dev/" target="_blank">
|
||||
<img src="https://img.shields.io/badge/vite-%3E2.0.0-yellow" alt="vite">
|
||||
</a>
|
||||
<a href="https://gitee.com/lyt-top/vue-next-admin/blob/master/LICENSE" target="_blank">
|
||||
<img src="https://img.shields.io/badge/license-MIT-success" alt="license">
|
||||
</a>
|
||||
</p>
|
||||
<p> </p>
|
||||
</div>
|
||||
|
||||
#### 🌈 介绍
|
||||
|
||||
基于 vue3.x + CompositionAPI + typescript + vite + element plus + vue-router-next + next.vuex,适配手机、平板、pc 的后台开源免费模板,希望减少工作量,帮助大家实现快速开发。
|
||||
|
||||
#### 🚧 安装 cnpm、yarn
|
||||
|
||||
- 复制代码(桌面 cmd 运行) `npm install -g cnpm --registry=https://registry.npm.taobao.org`
|
||||
- 复制代码(桌面 cmd 运行) `npm install -g yarn`
|
||||
|
||||
#### 🏭 环境支持
|
||||
|
||||
| Edge | last 2 versions | last 2 versions | last 2 versions |
|
||||
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
|
||||
|  |  |  |  |
|
||||
|
||||
> 由于 Vue3 不再支持 IE11,故而 ElementPlus 也不支持 IE11 及之前版本。
|
||||
#### ⚡ 使用说明
|
||||
|
||||
建议使用 cnpm,因为 yarn 有时会报错。<a href="http://nodejs.cn/" target="_blank">node 版本[v16.x ~ v20.x)</a>
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
git clone -b v3.2 https://gitee.com/tiger1103/gfast-ui.git
|
||||
# 进入项目
|
||||
cd gfast-ui
|
||||
# 安装依赖
|
||||
npm install --registry=https://registry.npmmirror.com
|
||||
# 运行项目
|
||||
npm run dev
|
||||
# 打包发布
|
||||
npm run build
|
||||
```
|
||||
## ❤特别鸣谢
|
||||
|
||||
* 感谢[VUE-NEXT-ADMIN](https://github.com/lyt-Top/vue-next-admin)
|
1500
package-lock.json
generated
1500
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@
|
||||
"@codemirror/lang-javascript": "^6.1.1",
|
||||
"@codemirror/theme-one-dark": "^6.1.0",
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@vue/reactivity": "^3.5.18",
|
||||
"axios": "1.8.2",
|
||||
"codemirror": "^6.0.1",
|
||||
"countup.js": "^2.8.0",
|
||||
@ -46,6 +47,7 @@
|
||||
"vue-ueditor-wrap": "^3.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^20.11.28",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
@ -61,7 +63,7 @@
|
||||
"sass-loader": "^16.0.3",
|
||||
"typescript": "^5.4.2",
|
||||
"vite": "6.3.4",
|
||||
"vite-plugin-cdn-import": "^0.3.5",
|
||||
"vite-plugin-cdn-import": "^1.0.1",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-vue-setup-extend-plus": "^0.1.0",
|
||||
"vue-eslint-parser": "^9.4.1"
|
||||
|
3516
pnpm-lock.yaml
generated
Normal file
3516
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
4
pnpm-workspace.yaml
Normal file
4
pnpm-workspace.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
onlyBuiltDependencies:
|
||||
- '@parcel/watcher'
|
||||
- esbuild
|
||||
- vue-demi
|
163
src/components/dynamicpage/ProTable/index.vue
Normal file
163
src/components/dynamicpage/ProTable/index.vue
Normal file
@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="data"
|
||||
:row-key="rowKey"
|
||||
:border="border"
|
||||
:stripe="stripe"
|
||||
:loading="loading"
|
||||
:height="tableHeight"
|
||||
:size="size"
|
||||
:highlight-current-row="highlightCurrentRow"
|
||||
@row-dblclick="onRowDblClick"
|
||||
@selection-change="onSelectionChange"
|
||||
@sort-change="onSortChange"
|
||||
v-bind="tableProps"
|
||||
>
|
||||
<!-- 选择框 -->
|
||||
<el-table-column v-if="showSelection" type="selection" width="55" align="center" />
|
||||
|
||||
<!-- 序号 -->
|
||||
<el-table-column v-if="showIndex" type="index" width="55" align="center" label="#" />
|
||||
|
||||
<template v-for="col in columns" :key="col.prop">
|
||||
<!-- <el-table-column
|
||||
v-if="col.isFormater"
|
||||
:prop="col.prop"
|
||||
:label="col.label"
|
||||
:width="col.width"
|
||||
:min-width="col.minWidth"
|
||||
:align="col.align || 'center'"
|
||||
:sortable="col.sortable || false"
|
||||
:fixed="col.fixed || false"
|
||||
:show-overflow-tooltip="col.showOverflowTooltip || true"
|
||||
:formatter="(row:any,col:any)=>col.formater(row,col)"
|
||||
/> -->
|
||||
<div >{{col}}</div>
|
||||
|
||||
<!-- <el-table-column
|
||||
v-else
|
||||
:prop="col.prop"
|
||||
:label="col.label"
|
||||
:width="col.width"
|
||||
:min-width="col.minWidth"
|
||||
:align="col.align || 'center'"
|
||||
:sortable="col.sortable || false"
|
||||
:fixed="col.fixed || false"
|
||||
:show-overflow-tooltip="col.showOverflowTooltip || true"
|
||||
>
|
||||
<template #default="scope">
|
||||
<slot v-if="$slots[col.prop]" :name="col.prop" v-bind="scope" />
|
||||
<component
|
||||
v-else-if="col.render"
|
||||
:is="col.render"
|
||||
v-bind="{ row: scope.row, col, index: scope.$index }"
|
||||
/>
|
||||
<span v-else>{{ scope.row[col.prop] }}</span>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<el-table-column
|
||||
v-if="$slots.actions"
|
||||
label="操作"
|
||||
:fixed="actionFixed"
|
||||
:width="actionWidth"
|
||||
align="center"
|
||||
>
|
||||
<template #default="scope">
|
||||
<slot name="actions" v-bind="scope" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
||||
import { formatter, type TableColumnCtx } from 'element-plus';
|
||||
import { TableColumn } from '../type';
|
||||
|
||||
interface Props {
|
||||
columns: TableColumn[];
|
||||
data: Record<string, any>[];
|
||||
loading?: boolean;
|
||||
rowKey?: string;
|
||||
border?: boolean;
|
||||
stripe?: boolean;
|
||||
size?: 'small' | 'default' | 'large';
|
||||
showIndex?: boolean;
|
||||
showSelection?: boolean;
|
||||
highlightCurrentRow?: boolean;
|
||||
actionWidth?: string | number;
|
||||
actionFixed?: 'left' | 'right' | boolean;
|
||||
tableProps?: Record<string, any>; // 透传 Element Plus Table 所有 props
|
||||
autoHeight?: boolean;
|
||||
heightOffset?: number; // 距离底部的偏移量
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
columns: () => [],
|
||||
data: () => [],
|
||||
loading: false,
|
||||
rowKey: 'id',
|
||||
border: false,
|
||||
stripe: true,
|
||||
size: 'default',
|
||||
showIndex: false,
|
||||
showSelection: false,
|
||||
highlightCurrentRow: false,
|
||||
actionWidth: 180,
|
||||
actionFixed: 'right',
|
||||
tableProps: () => ({}),
|
||||
autoHeight: true,
|
||||
heightOffset: 360,
|
||||
});
|
||||
|
||||
defineOptions({ name: 'ProTable' });
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'row-dblclick', row: any): void;
|
||||
(e: 'selection-change', selection: any[]): void;
|
||||
(e: 'sort-change', col: TableColumnCtx<any>): void;
|
||||
}>();
|
||||
|
||||
// 表格高度
|
||||
const tableHeight = ref<string | number>('auto');
|
||||
|
||||
const calcHeight = () => {
|
||||
if (props.autoHeight) {
|
||||
tableHeight.value = window.innerHeight - props.heightOffset;
|
||||
}
|
||||
};
|
||||
|
||||
// 监听窗口变化
|
||||
onMounted(() => {
|
||||
calcHeight();
|
||||
window.addEventListener('resize', calcHeight);
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', calcHeight);
|
||||
});
|
||||
|
||||
// 事件处理
|
||||
const onRowDblClick = (row: any) => emit('row-dblclick', row);
|
||||
const onSelectionChange = (selection: any[]) => emit('selection-change', selection);
|
||||
const onSortChange = (col: TableColumnCtx<any>) => emit('sort-change', col);
|
||||
|
||||
// 暴露 Element Plus Table API
|
||||
const tableRef = ref();
|
||||
const clearSelection = () => tableRef.value?.clearSelection();
|
||||
const toggleRowSelection = (row: any, selected?: boolean) =>
|
||||
tableRef.value?.toggleRowSelection(row, selected);
|
||||
const getSelectionRows = () => tableRef.value?.getSelectionRows();
|
||||
|
||||
defineExpose({
|
||||
clearSelection,
|
||||
toggleRowSelection,
|
||||
getSelectionRows,
|
||||
tableRef,
|
||||
});
|
||||
</script>
|
199
src/components/dynamicpage/queryForm/index.vue
Normal file
199
src/components/dynamicpage/queryForm/index.vue
Normal file
@ -0,0 +1,199 @@
|
||||
<template>
|
||||
<div class="query-form">
|
||||
<el-form ref="formRef" :model="modelValue" :label-width="labelWidth" :inline="inline">
|
||||
<el-row :gutter="gutter">
|
||||
<template v-for="(item, index) in fields" :key="item.prop">
|
||||
<div class="form-item-wrapper" v-show="showAll || index < defaultFieldCount">
|
||||
<el-form-item :label="item.label" :prop="item.prop" :rules="item.rules">
|
||||
<!-- 插槽优先 -->
|
||||
<slot :name="item.prop" :item="item" :form="modelValue">
|
||||
<!-- 动态组件渲染 -->
|
||||
<component
|
||||
:is="getComponent(item.type)"
|
||||
v-model="modelValue[item.prop]"
|
||||
v-bind="getProps(item)"
|
||||
@keyup.enter="item.type === 'input' && handleSearch()"
|
||||
>
|
||||
<!-- 下拉选项 -->
|
||||
<template v-if="item.type === 'select'" #default>
|
||||
<el-option
|
||||
v-for="opt in item.options || []"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</template>
|
||||
</component>
|
||||
</slot>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="form-item-wrapper actions">
|
||||
<el-form-item>
|
||||
<slot name="actions">
|
||||
<el-button type="primary" :icon="Search" size="default" @click="handleSearch">
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button :icon="Refresh" size="default" @click="handleReset">重置</el-button>
|
||||
<el-button link v-if="fields.length > defaultFieldCount" @click="toggleSearch">
|
||||
{{ word }}
|
||||
<el-icon>
|
||||
<ele-ArrowUp v-if="showAll" />
|
||||
<ele-ArrowDown v-else />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</slot>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import { Search, Refresh } from '@element-plus/icons-vue';
|
||||
import type { FormInstance } from 'element-plus';
|
||||
import { QueryFormField } from '../type';
|
||||
interface Props {
|
||||
fields: QueryFormField[];
|
||||
modelValue: Record<string, any>; // 双向绑定
|
||||
defaultFieldCount?: number;
|
||||
labelWidth?: string;
|
||||
inline?: boolean;
|
||||
gutter?: number;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
fields: () => [] as QueryFormField[],
|
||||
modelValue: () => ({}),
|
||||
defaultFieldCount: 3,
|
||||
labelWidth: '100px',
|
||||
inline: true,
|
||||
gutter: 20,
|
||||
});
|
||||
defineOptions({ name: 'QueryForm' });
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', val: Record<string, any>): void;
|
||||
(e: 'search', val: Record<string, any>): void;
|
||||
(e: 'reset'): void;
|
||||
}>();
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const showAll = ref(false);
|
||||
const toggleSearch = () => (showAll.value = !showAll.value);
|
||||
|
||||
const word = computed(() => (showAll.value ? '收起搜索' : '展开搜索'));
|
||||
|
||||
const dates = ['daterange', 'datetimerange'];
|
||||
|
||||
/**
|
||||
* 初始化表单
|
||||
*/
|
||||
const initForm = () => {
|
||||
const form: Record<string, any> = {};
|
||||
props.fields.forEach((item) => {
|
||||
form[item.prop] = item.defaultValue ?? '';
|
||||
});
|
||||
return form;
|
||||
};
|
||||
|
||||
/**
|
||||
* 更新父组件的值
|
||||
*/
|
||||
const updateModel = (val: Record<string, any>) => {
|
||||
emit('update:modelValue', val);
|
||||
};
|
||||
|
||||
/**
|
||||
* 动态组件映射
|
||||
*/
|
||||
const componentMap: Record<string, any> = {
|
||||
input: 'el-input',
|
||||
select: 'el-select',
|
||||
daterange: 'el-date-picker',
|
||||
datetimerange: 'el-date-picker',
|
||||
};
|
||||
|
||||
const getComponent = (type: string) => componentMap[type] || 'el-input';
|
||||
|
||||
/**
|
||||
* 获取组件属性
|
||||
*/
|
||||
const getProps = (item: QueryFormField) => {
|
||||
const commonProps = {
|
||||
size: item.size || 'default',
|
||||
placeholder: item.placeholder || '请输入',
|
||||
};
|
||||
if (item.type === 'select') {
|
||||
return { ...commonProps, filterable: true };
|
||||
}
|
||||
if (dates.includes(item.type)) {
|
||||
return {
|
||||
...commonProps,
|
||||
type: item.type,
|
||||
'value-format': item.valueFormat || 'YYYY-MM-DD',
|
||||
'range-separator': '至',
|
||||
'start-placeholder': item.staerPlaceholder || '开始日期',
|
||||
'end-placeholder': item.endPlaceholder || '结束日期',
|
||||
style: { width: '220px' },
|
||||
};
|
||||
}
|
||||
return commonProps;
|
||||
};
|
||||
|
||||
const loadOptions = async () => {
|
||||
let oldFetchOptions:any = [];
|
||||
for (const field of props.fields) {
|
||||
if (field.fetchOptions) {
|
||||
if (!oldFetchOptions.includes(field.fetchOptions)) {
|
||||
field.options = await field.fetchOptions();
|
||||
oldFetchOptions.push(field.fetchOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadOptions();
|
||||
});
|
||||
|
||||
/**
|
||||
* 搜索事件(防抖)
|
||||
*/
|
||||
const handleSearch = () => emit('search', props.modelValue);
|
||||
|
||||
/**
|
||||
* 重置事件
|
||||
*/
|
||||
const handleReset = () => {
|
||||
const newForm = initForm();
|
||||
updateModel(newForm);
|
||||
emit('reset');
|
||||
};
|
||||
|
||||
/**
|
||||
* 监听字段变化,保持双向绑定
|
||||
*/
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => updateModel(val),
|
||||
{ deep: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.form-item-wrapper {
|
||||
display: block;
|
||||
}
|
||||
.query-form {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
34
src/components/dynamicpage/type.ts
Normal file
34
src/components/dynamicpage/type.ts
Normal file
@ -0,0 +1,34 @@
|
||||
export interface OptionItem {
|
||||
label: string;
|
||||
value: string | number;
|
||||
|
||||
}
|
||||
|
||||
export interface QueryFormField {
|
||||
label: string; // 显示的 label
|
||||
prop: string; // 绑定的字段
|
||||
type: 'input' | 'select' | 'date' | 'daterange' | 'datetimerange' | 'monthrange';
|
||||
placeholder?: string;
|
||||
size?: 'small' | 'default' | 'large';
|
||||
defaultValue?: any;
|
||||
options?: OptionItem[];
|
||||
fetchOptions?: () => Promise<OptionItem[]>; // 异步加载 options
|
||||
valueFormat?:string;
|
||||
rules?: any[]; // 校验规则
|
||||
staerPlaceholder?: string;
|
||||
endPlaceholder?: string;
|
||||
|
||||
}
|
||||
export interface TableColumn {
|
||||
label: string;
|
||||
prop: string;
|
||||
width?: string | number;
|
||||
minWidth?: string | number;
|
||||
align?: 'left' | 'center' | 'right';
|
||||
sortable?: boolean;
|
||||
fixed?: 'left' | 'right' | boolean;
|
||||
render?: any;
|
||||
showOverflowTooltip?: boolean;
|
||||
formater?: (row: any, column: any) => any;
|
||||
isFormater?: boolean;
|
||||
}
|
@ -24,18 +24,18 @@
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
|
||||
<!-- <div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
|
||||
<el-icon :title="$t('message.user.title2')">
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
|
||||
</div> -->
|
||||
<!-- <div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
|
||||
<i class="icon-skin iconfont" :title="$t('message.user.title3')"></i>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="layout-navbars-breadcrumb-user-icon" @click="removeCacheClick">
|
||||
<i class="fa-trash fa" title="清除缓存"></i>
|
||||
</div>
|
||||
<div class="layout-navbars-breadcrumb-user-icon">
|
||||
<!-- <div class="layout-navbars-breadcrumb-user-icon">
|
||||
<el-popover ref="newPopoverRef" placement="bottom" trigger="click" transition="el-zoom-in-top" :width="500" :persistent="false">
|
||||
<template #reference>
|
||||
<el-badge :is-dot="true">
|
||||
@ -48,7 +48,7 @@
|
||||
<UserNews @hideNews="hideNews" />
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick">
|
||||
<i
|
||||
class="iconfont"
|
||||
@ -67,10 +67,10 @@
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="/home">{{ $t('message.user.dropdown1') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="wareHouse">{{ $t('message.user.dropdown6') }}</el-dropdown-item>
|
||||
<!-- <el-dropdown-item command="wareHouse">{{ $t('message.user.dropdown6') }}</el-dropdown-item> -->
|
||||
<el-dropdown-item command="/personal">{{ $t('message.user.dropdown2') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="/404">{{ $t('message.user.dropdown3') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="/401">{{ $t('message.user.dropdown4') }}</el-dropdown-item>
|
||||
<!-- <el-dropdown-item command="/404">{{ $t('message.user.dropdown3') }}</el-dropdown-item> -->
|
||||
<!-- <el-dropdown-item command="/401">{{ $t('message.user.dropdown4') }}</el-dropdown-item> -->
|
||||
<el-dropdown-item divided command="logOut">{{ $t('message.user.dropdown5') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
@ -80,7 +80,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, getCurrentInstance, computed, reactive, toRefs, onMounted, defineComponent, watch} from 'vue';
|
||||
import {ref, getCurrentInstance, computed, reactive, toRefs, onMounted, watch} from 'vue';
|
||||
import { useRoute,useRouter } from 'vue-router';
|
||||
import {ElMessageBox, ElMessage, ElNotification} from 'element-plus';
|
||||
import screenfull from 'screenfull';
|
||||
@ -90,7 +90,6 @@ import { useUserInfo } from '/@/stores/userInfo';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import other from '/@/utils/other';
|
||||
import { Session, Local } from '/@/utils/storage';
|
||||
import UserNews from '/@/layout/navBars/breadcrumb/userNews.vue';
|
||||
import Search from '/@/layout/navBars/breadcrumb/search.vue';
|
||||
import {logout} from "/@/api/login";
|
||||
import {removeCache} from "/@/api/system/cache";
|
||||
@ -197,7 +196,6 @@ const onSearchClick = () => {
|
||||
searchRef.value.openSearch();
|
||||
};
|
||||
const hideNews=()=>{
|
||||
debugger
|
||||
newPopoverRef.value.hide()
|
||||
}
|
||||
// 组件大小改变
|
||||
@ -263,7 +261,7 @@ const noticeStoreAct = noticeStore()
|
||||
const getMessages = computed(() => {
|
||||
return noticeStoreAct.message;
|
||||
});
|
||||
watch(getMessages,(nv,ov)=>{
|
||||
watch(getMessages,(nv)=>{
|
||||
if (!nv || !nv.id) {
|
||||
return;
|
||||
}
|
||||
|
14
src/main.ts
14
src/main.ts
@ -11,9 +11,7 @@ import ElementPlus from 'element-plus';
|
||||
import 'element-plus/dist/index.css';
|
||||
import '/@/theme/index.scss';
|
||||
import mitt from 'mitt';
|
||||
import VueGridLayout from 'vue-grid-layout';
|
||||
import {findChildrenByPid, flattenTree, getUpFileUrl, handleTree, parseTime, selectDictLabel} from '/@/utils/gfast';
|
||||
import Websocket from '/@/utils/websocket';
|
||||
import {useDict} from '/@/api/system/dict/data';
|
||||
import {getItems, setItems, getOptionValue, isEmpty} from '/@/api/items'
|
||||
// 分页组件
|
||||
@ -27,17 +25,6 @@ import VueUeditorWrap from 'vue-ueditor-wrap';
|
||||
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
// 全局websocket
|
||||
const onMessageList: Array<Function> = [];
|
||||
app.provide('onMessageList', onMessageList);
|
||||
const onMessage = (event: any) => {
|
||||
onMessageList.forEach((f) => {
|
||||
f.call(null, event);
|
||||
});
|
||||
};
|
||||
Websocket(onMessage);
|
||||
|
||||
directive(app);
|
||||
other.elSvg(app);
|
||||
|
||||
@ -47,7 +34,6 @@ app.use(pinia)
|
||||
.use(router)
|
||||
.use(ElementPlus)
|
||||
.use(i18n)
|
||||
.use(VueGridLayout)
|
||||
.use(VueUeditorWrap)
|
||||
.mount('#app');
|
||||
|
||||
|
@ -1,10 +1,17 @@
|
||||
import { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
// Extend the Window interface to include nextLoading
|
||||
declare global {
|
||||
interface Window {
|
||||
nextLoading?: any;
|
||||
}
|
||||
}
|
||||
import pinia from '/@/stores/index';
|
||||
import { useUserInfo } from '/@/stores/userInfo';
|
||||
import { useRequestOldRoutes } from '/@/stores/requestOldRoutes';
|
||||
import { Session } from '/@/utils/storage';
|
||||
import { NextLoading } from '/@/utils/loading';
|
||||
import { demoRoutes,dynamicRoutes, notFoundAndNoPower } from '/@/router/route';
|
||||
import { dynamicRoutes, notFoundAndNoPower } from '/@/router/route';
|
||||
import { formatTwoStageRoutes, formatFlatteningRoutes, router } from '/@/router/index';
|
||||
import { useRoutesList } from '/@/stores/routesList';
|
||||
import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
|
||||
@ -47,7 +54,7 @@ export async function initBackEndControlRoutes() {
|
||||
// 存储接口原始路由(未处理component),根据需求选择使用
|
||||
useRequestOldRoutes().setRequestOldRoutes(JSON.parse(JSON.stringify(menuRoute)));
|
||||
// 处理路由(component),替换 dynamicRoutes(/@/router/route)第一个顶级 children 的路由
|
||||
dynamicRoutes[0].children?.push(...await backEndComponent(menuRoute),...demoRoutes);
|
||||
dynamicRoutes[0].children?.push(...await backEndComponent(menuRoute));
|
||||
// 添加动态路由
|
||||
await setAddRoute();
|
||||
// 设置路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
|
1023
src/router/route.ts
1023
src/router/route.ts
File diff suppressed because it is too large
Load Diff
43
src/types/index.ts
Normal file
43
src/types/index.ts
Normal file
@ -0,0 +1,43 @@
|
||||
export interface DeptItem {
|
||||
deptId: number;
|
||||
parentId: number;
|
||||
ancestors: string;
|
||||
deptName: string;
|
||||
orderNum: number;
|
||||
leader: null;
|
||||
phone: string;
|
||||
email: string;
|
||||
status: number;
|
||||
createdBy: number;
|
||||
updatedBy: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt: null;
|
||||
};
|
||||
export interface UserItem {
|
||||
id: number;
|
||||
userName: string;
|
||||
mobile: string;
|
||||
userNickname: string;
|
||||
birthday: number;
|
||||
userPassword: string;
|
||||
userSalt: string;
|
||||
userStatus: number;
|
||||
userEmail: string;
|
||||
sex: number;
|
||||
avatar: string;
|
||||
deptId: number;
|
||||
remark: string;
|
||||
isAdmin: number;
|
||||
address: string;
|
||||
describe: string;
|
||||
lastLoginIp: string;
|
||||
lastLoginTime: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt: null;
|
||||
openId : string;
|
||||
dept: DeptItem;
|
||||
roleInfo: null;
|
||||
post: null;
|
||||
};
|
@ -0,0 +1,200 @@
|
||||
<template>
|
||||
<!-- 详情抽屉 -->
|
||||
<div class="demo-speciesName-detail">
|
||||
<el-drawer v-model="isShowDialog" size="80%" direction="ltr">
|
||||
<template #header>
|
||||
<h4>详情</h4>
|
||||
</template>
|
||||
<el-descriptions
|
||||
class="margin-top"
|
||||
:column="3"
|
||||
border
|
||||
style="margin: 8px;"
|
||||
>
|
||||
<el-descriptions-item :span="1">
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
主键
|
||||
</div>
|
||||
</template>
|
||||
{{ formData.id }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="1">
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
物种编号
|
||||
</div>
|
||||
</template>
|
||||
{{ formData.speciesCode }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="1">
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
物种名称
|
||||
</div>
|
||||
</template>
|
||||
{{ formData.name }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="1">
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
物种名称内容
|
||||
</div>
|
||||
</template>
|
||||
{{ formData.content }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="1">
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
数据来源
|
||||
</div>
|
||||
</template>
|
||||
{{ formData.sourcesData }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="1">
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
数据采集人
|
||||
</div>
|
||||
</template>
|
||||
{{ formData.createUser }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="1">
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
数据采集信息
|
||||
</div>
|
||||
</template>
|
||||
{{ proxy.parseTime(formData.createDate, '{y}-{m}-{d} {h}:{i}:{s}') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="1">
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
数据核查人
|
||||
</div>
|
||||
</template>
|
||||
{{ formData.auditUser }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="1">
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
数据核查日期
|
||||
</div>
|
||||
</template>
|
||||
{{ proxy.parseTime(formData.auditDate, '{y}-{m}-{d} {h}:{i}:{s}') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="1">
|
||||
<template #label>
|
||||
<div class="cell-item">
|
||||
备注
|
||||
</div>
|
||||
</template>
|
||||
{{ formData.remark }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, toRefs, defineComponent,ref,unref,getCurrentInstance,computed } from 'vue';
|
||||
import {ElMessageBox, ElMessage, FormInstance,UploadProps} from 'element-plus';
|
||||
import {
|
||||
listSpeciesName,
|
||||
getSpeciesName,
|
||||
delSpeciesName,
|
||||
addSpeciesName,
|
||||
updateSpeciesName,
|
||||
} from "./api";
|
||||
import {
|
||||
SpeciesNameTableColumns,
|
||||
SpeciesNameInfoData,
|
||||
SpeciesNameTableDataState,
|
||||
SpeciesNameEditState
|
||||
} from "./type"
|
||||
defineOptions({ name: "ApiV1BusinessesSpeciesNameDetail"})
|
||||
const {proxy} = <any>getCurrentInstance()
|
||||
const formRef = ref<HTMLElement | null>(null);
|
||||
const menuRef = ref();
|
||||
const state = reactive<SpeciesNameEditState>({
|
||||
loading:false,
|
||||
isShowDialog: false,
|
||||
formData: {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
name: undefined,
|
||||
content: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
remark: undefined,
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
id : [
|
||||
{ required: true, message: "主键不能为空", trigger: "blur" }
|
||||
],
|
||||
name : [
|
||||
{ required: true, message: "物种名称不能为空", trigger: "blur" }
|
||||
],
|
||||
}
|
||||
});
|
||||
const { isShowDialog,formData } = toRefs(state);
|
||||
// 打开弹窗
|
||||
const openDialog = (row?: SpeciesNameInfoData) => {
|
||||
resetForm();
|
||||
if(row) {
|
||||
getSpeciesName(row.id!).then((res:any)=>{
|
||||
const data = res.data;
|
||||
state.formData = data;
|
||||
})
|
||||
}
|
||||
state.isShowDialog = true;
|
||||
};
|
||||
// 关闭弹窗
|
||||
const closeDialog = () => {
|
||||
state.isShowDialog = false;
|
||||
};
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
closeDialog();
|
||||
};
|
||||
const resetForm = ()=>{
|
||||
state.formData = {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
name: undefined,
|
||||
content: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
remark: undefined,
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.demo-speciesName-detail :deep(.el-form-item--large .el-form-item__label){
|
||||
font-weight: bolder;
|
||||
}
|
||||
.pic-block{
|
||||
margin-right: 8px;
|
||||
}
|
||||
.file-block{
|
||||
width: 100%;
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
margin-bottom: 5px;
|
||||
padding: 3px 6px;
|
||||
}
|
||||
.ml-2{margin-right: 5px;}
|
||||
</style>
|
@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<div class="demo-speciesName-edit">
|
||||
<!-- 添加或修改对话框 -->
|
||||
<el-dialog v-model="isShowDialog" width="800px" :close-on-click-modal="false" :destroy-on-close="true">
|
||||
<template #header>
|
||||
<div v-drag="['.demo-speciesName-edit .el-dialog', '.demo-speciesName-edit .el-dialog__header']">{{(!formData.id || formData.id==0?'添加':'修改')+''}}</div>
|
||||
</template>
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
|
||||
<el-form-item label="物种编号" prop="speciesCode">
|
||||
<el-input v-model="formData.speciesCode" placeholder="请输入物种编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="物种名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入物种名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="物种名称内容" prop="content">
|
||||
<el-input v-model="formData.content" placeholder="请输入物种名称内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据来源" prop="sourcesData">
|
||||
<el-input v-model="formData.sourcesData" placeholder="请输入数据来源" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据采集人" prop="createUser">
|
||||
<el-input v-model="formData.createUser" placeholder="请输入数据采集人" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据采集信息" prop="createDate">
|
||||
<el-date-picker clearable style="width: 200px"
|
||||
v-model="formData.createDate"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="选择数据采集信息">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据核查人" prop="auditUser">
|
||||
<el-input v-model="formData.auditUser" placeholder="请输入数据核查人" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据核查日期" prop="auditDate">
|
||||
<el-date-picker clearable style="width: 200px"
|
||||
v-model="formData.auditDate"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="选择数据核查日期">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="onSubmit" :disabled="loading">确 定</el-button>
|
||||
<el-button @click="onCancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, toRefs, ref,unref,getCurrentInstance,computed } from 'vue';
|
||||
import {ElMessageBox, ElMessage, FormInstance,UploadProps} from 'element-plus';
|
||||
import {
|
||||
listSpeciesName,
|
||||
getSpeciesName,
|
||||
delSpeciesName,
|
||||
addSpeciesName,
|
||||
updateSpeciesName,
|
||||
} from "./api";
|
||||
import {
|
||||
SpeciesNameTableColumns,
|
||||
SpeciesNameInfoData,
|
||||
SpeciesNameTableDataState,
|
||||
SpeciesNameEditState
|
||||
} from "./type"
|
||||
defineOptions({ name: "ApiV1BusinessesSpeciesNameEdit"})
|
||||
const emit = defineEmits(['speciesNameList'])
|
||||
const {proxy} = <any>getCurrentInstance()
|
||||
const formRef = ref<HTMLElement | null>(null);
|
||||
const menuRef = ref();
|
||||
const state = reactive<SpeciesNameEditState>({
|
||||
loading:false,
|
||||
isShowDialog: false,
|
||||
formData: {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
name: undefined,
|
||||
content: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
remark: undefined,
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
id : [
|
||||
{ required: true, message: "主键不能为空", trigger: "blur" }
|
||||
],
|
||||
name : [
|
||||
{ required: true, message: "物种名称不能为空", trigger: "blur" }
|
||||
],
|
||||
}
|
||||
});
|
||||
const { loading,isShowDialog,formData,rules } = toRefs(state);
|
||||
// 打开弹窗
|
||||
const openDialog = (row?: SpeciesNameInfoData) => {
|
||||
resetForm();
|
||||
if(row) {
|
||||
getSpeciesName(row.id!).then((res:any)=>{
|
||||
const data = res.data;
|
||||
state.formData = data;
|
||||
})
|
||||
}
|
||||
state.isShowDialog = true;
|
||||
};
|
||||
// 关闭弹窗
|
||||
const closeDialog = () => {
|
||||
state.isShowDialog = false;
|
||||
};
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
closeDialog();
|
||||
};
|
||||
// 提交
|
||||
const onSubmit = () => {
|
||||
const formWrap = unref(formRef) as any;
|
||||
if (!formWrap) return;
|
||||
formWrap.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
state.loading = true;
|
||||
if(!state.formData.id || state.formData.id===0){
|
||||
//添加
|
||||
addSpeciesName(state.formData).then(()=>{
|
||||
ElMessage.success('添加成功');
|
||||
closeDialog(); // 关闭弹窗
|
||||
emit('speciesNameList')
|
||||
}).finally(()=>{
|
||||
state.loading = false;
|
||||
})
|
||||
}else{
|
||||
//修改
|
||||
updateSpeciesName(state.formData).then(()=>{
|
||||
ElMessage.success('修改成功');
|
||||
closeDialog(); // 关闭弹窗
|
||||
emit('speciesNameList')
|
||||
}).finally(()=>{
|
||||
state.loading = false;
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
const resetForm = ()=>{
|
||||
state.formData = {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
name: undefined,
|
||||
content: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
remark: undefined,
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.kv-label{margin-bottom: 15px;font-size: 14px;}
|
||||
.mini-btn i.el-icon{margin: unset;}
|
||||
.kv-row{margin-bottom: 12px;}
|
||||
</style>
|
45
src/views/businesses/speciesName/api/index.ts
Normal file
45
src/views/businesses/speciesName/api/index.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import request from '/@/utils/request'
|
||||
// 查询列表
|
||||
export function listSpeciesName(query:object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesName/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询详细
|
||||
export function getSpeciesName(id:number) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesName/get',
|
||||
method: 'get',
|
||||
params: {
|
||||
id: id.toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 新增
|
||||
export function addSpeciesName(data:object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesName/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 修改
|
||||
export function updateSpeciesName(data:object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesName/edit',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 删除
|
||||
export function delSpeciesName(ids:number[]) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesName/delete',
|
||||
method: 'delete',
|
||||
data:{
|
||||
ids:ids
|
||||
}
|
||||
})
|
||||
}
|
273
src/views/businesses/speciesName/index.vue
Normal file
273
src/views/businesses/speciesName/index.vue
Normal file
@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card shadow="hover">
|
||||
<QueryForm
|
||||
v-model="searchForm"
|
||||
:fields="searchFields"
|
||||
@search="onSearch"
|
||||
@reset="onReset"
|
||||
ref="queryFormRef"
|
||||
/>
|
||||
|
||||
<el-row :gutter="10" style="padding-bottom: 10px">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" @click="handleAdd" v-auth="'api/v1/businesses/speciesName/add'"
|
||||
><el-icon><ele-Plus /></el-icon>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete(null)"
|
||||
v-auth="'api/v1/businesses/speciesName/delete'"
|
||||
><el-icon><ele-Delete /></el-icon>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<ProTable
|
||||
ref="proTableRef"
|
||||
:columns="columns"
|
||||
:data="tableData.data"
|
||||
:loading="loading"
|
||||
:show-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
</ProTable>
|
||||
<!-- <el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
class-name="small-padding"
|
||||
min-width="160px"
|
||||
fixed="right"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-auth="'api/v1/businesses/speciesName/edit'"
|
||||
><el-icon><ele-EditPen /></el-icon>修改</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="handleDelete(scope.row)"
|
||||
v-auth="'api/v1/businesses/speciesName/delete'"
|
||||
><el-icon><ele-DeleteFilled /></el-icon>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="speciesNameList"
|
||||
/>
|
||||
</el-card>
|
||||
<ApiV1BusinessesSpeciesNameEdit
|
||||
ref="editRef"
|
||||
@speciesNameList="speciesNameList"
|
||||
></ApiV1BusinessesSpeciesNameEdit>
|
||||
<ApiV1BusinessesSpeciesNameDetail
|
||||
ref="detailRef"
|
||||
@speciesNameList="speciesNameList"
|
||||
></ApiV1BusinessesSpeciesNameDetail>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, getCurrentInstance, toRaw, computed } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { listSpeciesName, delSpeciesName } from './api/index';
|
||||
import { SpeciesNameTableColumns, SpeciesNameInfoData, SpeciesNameTableDataState } from './type';
|
||||
import ApiV1BusinessesSpeciesNameDetail from './ApiV1BusinessesSpeciesNameDetail.vue';
|
||||
import ApiV1BusinessesSpeciesNameEdit from './ApiV1BusinessesSpeciesNameEdit.vue';
|
||||
import QueryForm from '/@/components/dynamicpage/queryForm/index.vue';
|
||||
import ProTable from '/@/components/dynamicpage/ProTable/index.vue';
|
||||
import { QueryFormField, TableColumn } from '/@/components/dynamicpage/type';
|
||||
import { getUserList } from '/@/api/system/user/index';
|
||||
import { UserItem } from '/@/types';
|
||||
import { parseTime } from '/@/utils/gfast';
|
||||
defineOptions({ name: 'apiV1DemoSpeciesNameList' });
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const loading = ref(false);
|
||||
const editRef = ref();
|
||||
const detailRef = ref();
|
||||
|
||||
// 非单个禁用
|
||||
const single = ref(true);
|
||||
// 非多个禁用
|
||||
const multiple = ref(true);
|
||||
const userOptions = ref<UserItem[]>([]);
|
||||
|
||||
const onSearch = async (val: Record<string, any>) => {
|
||||
console.log('搜索参数', val);
|
||||
state.tableData.param = { ...state.tableData.param, ...val };
|
||||
speciesNameList();
|
||||
};
|
||||
const onReset = () => {
|
||||
state.tableData.param = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
name: undefined,
|
||||
content: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
dateRange: [],
|
||||
};
|
||||
speciesNameList();
|
||||
};
|
||||
const searchForm = ref<Omit<SpeciesNameInfoData, 'id' | 'remark' | 'content'>>({
|
||||
speciesCode: undefined,
|
||||
name: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
});
|
||||
const searchFields = computed<QueryFormField[]>(() => [
|
||||
{ label: '物种编码', prop: 'speciesCode', type: 'input', placeholder: '请输入物种编码' },
|
||||
{ label: '物种名称', prop: 'name', type: 'input', placeholder: '请输入物种名称' },
|
||||
{ label: '数据来源', prop: 'sourcesData', type: 'input', placeholder: '请输入数据来源' },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
{ label: '数据采集日期', prop: 'createDate', type: 'daterange', valueFormat: 'YYYY-MM-DD' },
|
||||
|
||||
{
|
||||
label: '数据核查人',
|
||||
prop: 'auditUser',
|
||||
type: 'select',
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
placeholder: '请选择数据核查人',
|
||||
},
|
||||
{ label: '数据核查日期', prop: 'auditDate', type: 'daterange', valueFormat: 'YYYY-MM-DD' },
|
||||
]);
|
||||
|
||||
const state = reactive<SpeciesNameTableDataState>({
|
||||
ids: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
name: undefined,
|
||||
content: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
dateRange: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
const { tableData } = toRefs(state);
|
||||
const columns: TableColumn[] = [
|
||||
{ label: '物种编码', prop: 'speciesCode' },
|
||||
{ label: '物种名称', prop: 'name' },
|
||||
{ label: '物种名称内容', prop: 'content' },
|
||||
{ label: '数据来源', prop: 'sourcesData' },
|
||||
{ label: '数据采集人', prop: 'createUser' },
|
||||
{ label: '数据采集日期', prop: 'createDate',isFormater:true,formater(row,col){
|
||||
console.log(row,col);
|
||||
|
||||
return parseTime(row.createDate,'{y}-{m}-{d}')
|
||||
} },
|
||||
{ label: '数据核查人', prop: 'auditUser' },
|
||||
{ label: '数据核查日期', prop: 'auditDate' },
|
||||
{ label: '备注', prop: 'remark' },
|
||||
];
|
||||
const proTableRef = ref();
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
speciesNameList();
|
||||
reqGetUserList();
|
||||
};
|
||||
// 获取列表数据
|
||||
const speciesNameList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listSpeciesName(state.tableData.param);
|
||||
let list = res.data.list ?? [];
|
||||
state.tableData.data = list;
|
||||
state.tableData.total = res.data.total;
|
||||
loading.value = false;
|
||||
};
|
||||
const reqGetUserList = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await getUserList({ pageSize: 9999, pageNum: 1 });
|
||||
userOptions.value = res.data.userList;
|
||||
};
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection: Array<SpeciesNameInfoData>) => {
|
||||
state.ids = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
const handleAdd = () => {
|
||||
editRef.value.openDialog();
|
||||
};
|
||||
const handleUpdate = (row: SpeciesNameTableColumns | null) => {
|
||||
if (!row) {
|
||||
row = state.tableData.data.find((item: SpeciesNameTableColumns) => {
|
||||
return item.id === state.ids[0];
|
||||
}) as SpeciesNameTableColumns;
|
||||
}
|
||||
editRef.value.openDialog(toRaw(row));
|
||||
};
|
||||
const handleDelete = (row: SpeciesNameTableColumns | null) => {
|
||||
let msg = '你确定要删除所选数据?';
|
||||
let id: number[] = [];
|
||||
if (row) {
|
||||
msg = `此操作将永久删除数据,是否继续?`;
|
||||
id = [row.id];
|
||||
} else {
|
||||
id = state.ids;
|
||||
}
|
||||
if (id.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据。');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
delSpeciesName(id).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
speciesNameList();
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
</script>
|
55
src/views/businesses/speciesName/type/index.ts
Normal file
55
src/views/businesses/speciesName/type/index.ts
Normal file
@ -0,0 +1,55 @@
|
||||
export interface SpeciesNameTableColumns {
|
||||
id: number; // 主键
|
||||
speciesCode: string; // 物种编号
|
||||
name: string; // 物种名称
|
||||
content: string; // 物种名称内容
|
||||
sourcesData: string; // 数据来源
|
||||
createUser: number; // 数据采集人
|
||||
createDate: string; // 数据采集信息
|
||||
auditUser: number; // 数据核查人
|
||||
auditDate: string; // 数据核查日期
|
||||
remark: string; // 备注
|
||||
}
|
||||
|
||||
export interface SpeciesNameInfoData {
|
||||
id: number | undefined; // 主键
|
||||
speciesCode: string | undefined; // 物种编号
|
||||
name: string | undefined; // 物种名称
|
||||
content: string | undefined; // 物种名称内容
|
||||
sourcesData: string | undefined; // 数据来源
|
||||
createUser: number | undefined; // 数据采集人
|
||||
createDate: string | undefined; // 数据采集信息
|
||||
auditUser: number | undefined; // 数据核查人
|
||||
auditDate: string | undefined; // 数据核查日期
|
||||
remark: string | undefined; // 备注
|
||||
}
|
||||
|
||||
export interface SpeciesNameTableDataState {
|
||||
ids: any[];
|
||||
tableData: {
|
||||
data: Array<SpeciesNameTableColumns>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
id: number | undefined;
|
||||
speciesCode: string | undefined;
|
||||
name: string | undefined;
|
||||
content: string | undefined;
|
||||
sourcesData: string | undefined;
|
||||
createUser: number | undefined;
|
||||
createDate: string | undefined;
|
||||
auditUser: number | undefined;
|
||||
auditDate: string | undefined;
|
||||
dateRange: string[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface SpeciesNameEditState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: SpeciesNameInfoData;
|
||||
rules: object;
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import {defineComponent,h} from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name:"baiduMap",
|
||||
props:{
|
||||
src:{
|
||||
type:String,
|
||||
default:'',
|
||||
}
|
||||
},
|
||||
setup(prop){
|
||||
return ()=>{
|
||||
return h('script',{src:prop.src,type:'text/javascript'})
|
||||
}
|
||||
},
|
||||
})
|
@ -117,7 +117,7 @@ const state = reactive({
|
||||
isShowPassword: false,
|
||||
ruleForm: {
|
||||
username: 'demo',
|
||||
password: '123456',
|
||||
password: 'Demo123',
|
||||
verifyCode: '',
|
||||
verifyKey:''
|
||||
},
|
||||
|
@ -6,7 +6,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, defineComponent, onMounted } from 'vue';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import QRCode from 'qrcodejs2-fixes';
|
||||
defineOptions({ name: "loginScan"})
|
||||
const qrcodeRef = ref<HTMLElement | null>(null);
|
||||
|
@ -14,24 +14,11 @@
|
||||
<el-tab-pane :label="$t('message.label.one1')" name="account">
|
||||
<Account />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('message.label.two2')" name="mobile">
|
||||
<!-- <el-tab-pane :label="$t('message.label.two2')" name="mobile">
|
||||
<Mobile />
|
||||
</el-tab-pane>
|
||||
</el-tab-pane> -->
|
||||
</el-tabs>
|
||||
</div>
|
||||
<Scan v-if="isScan" />
|
||||
<div class="login-content-main-sacn" @click="isScan = !isScan">
|
||||
<i class="iconfont" :class="isScan ? 'icon-diannao1' : 'icon-barcode-qr'"></i>
|
||||
<div class="login-content-main-sacn-delta"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-footer">
|
||||
<div class="login-footer-content mt15">
|
||||
<div class="login-footer-content-warp">
|
||||
<div>Copyright © 2021-2023 g-fast.cn All Rights Reserved.</div>
|
||||
<div class="mt5">云南奇讯科技有限公司版权所有</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -39,15 +26,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRefs, reactive, computed, defineComponent, onMounted } from 'vue';
|
||||
import { toRefs, reactive, computed, onMounted } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import logoMini from '/@/assets/logo-mini.svg';
|
||||
import loginIconTwo from '/@/assets/login-icon-two.svg';
|
||||
import { NextLoading } from '/@/utils/loading';
|
||||
import Account from '/@/views/login/component/account.vue';
|
||||
import Mobile from '/@/views/login/component/mobile.vue';
|
||||
import Scan from '/@/views/login/component/scan.vue';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface LoginState {
|
||||
|
@ -1,164 +0,0 @@
|
||||
<template>
|
||||
<div class="notice-bar-container">
|
||||
<el-card shadow="hover" header="滚动通知栏:默认">
|
||||
<NoticeBar
|
||||
text="🎉🎉🔥基于vue3.x 、Typescript、vite、Element plus等,适配手机、平板、pc
|
||||
的后台开源免费模板库(vue2.x请切换vue-prev-admin分支),仓库地址:https://gitee.com/lyt-top/vue-next-admin"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" header="滚动通知栏:设置样式" class="mt15">
|
||||
<NoticeBar
|
||||
text="🎉🎉🔥基于vue3.x 、Typescript、vite、Element plus等,适配手机、平板、pc
|
||||
的后台开源免费模板库(vue2.x请切换vue-prev-admin分支),仓库地址:https://gitee.com/lyt-top/vue-next-admin"
|
||||
leftIcon="iconfont icon-tongzhi2"
|
||||
rightIcon="ele-ArrowRight"
|
||||
background="#ecf5ff"
|
||||
color="#409eff"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" header="滚动通知栏:搭配 NoticeBar 和 Carousel 走马灯 组件可以实现垂直滚动的效果" class="mt15">
|
||||
<NoticeBar :scrollable="true">
|
||||
<el-carousel height="40px" direction="vertical" :autoplay="true" indicator-position="none" :interval="3000">
|
||||
<el-carousel-item v-for="v in noticeList" :key="v">{{ v }} </el-carousel-item>
|
||||
</el-carousel>
|
||||
</NoticeBar>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" header="滚动通知栏:参数" class="mt15">
|
||||
<el-table :data="tableData" style="width: 100%">
|
||||
<el-table-column prop="a1" label="参数"> </el-table-column>
|
||||
<el-table-column prop="a2" label="说明"> </el-table-column>
|
||||
<el-table-column prop="a3" label="类型"> </el-table-column>
|
||||
<el-table-column prop="a4" label="可选值"> </el-table-column>
|
||||
<el-table-column prop="a5" label="默认值"> </el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" header="图标选择器(宽度自动):事件" class="mt15">
|
||||
<el-table :data="tableData1" style="width: 100%">
|
||||
<el-table-column prop="a1" label="事件名称"> </el-table-column>
|
||||
<el-table-column prop="a2" label="说明"> </el-table-column>
|
||||
<el-table-column prop="a3" label="类型"> </el-table-column>
|
||||
<el-table-column prop="a4" label="回调参数"> </el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, defineComponent } from 'vue';
|
||||
import NoticeBar from '/@/components/noticeBar/index.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'makeNoticeBar',
|
||||
components: { NoticeBar },
|
||||
setup() {
|
||||
const state = reactive({
|
||||
noticeList: [
|
||||
'🎉🎉🔥基于vue3.x 、Typescript、vite、Element plus等',
|
||||
'适配手机、平板、pc的后台开源免费模板库(vue2.x请切换vue-prev-admin分支)',
|
||||
'仓库地址:https://gitee.com/lyt-top/vue-next-admin',
|
||||
'演示地址:https://lyt-top.gitee.io/vue-next-admin-preview/#/login',
|
||||
],
|
||||
tableData: [
|
||||
{
|
||||
a1: 'mode',
|
||||
a2: '通知栏模式,用于右侧 icon 图标点击',
|
||||
a3: 'string',
|
||||
a4: 'closeable / link',
|
||||
a5: '',
|
||||
},
|
||||
{
|
||||
a1: 'text',
|
||||
a2: '通知文本内容,scrollable 为 false 时生效',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '',
|
||||
},
|
||||
{
|
||||
a1: 'color',
|
||||
a2: '通知文本颜色',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '#e6a23c',
|
||||
},
|
||||
{
|
||||
a1: 'background',
|
||||
a2: '通知背景色',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '#fdf6ec',
|
||||
},
|
||||
{
|
||||
a1: 'size',
|
||||
a2: '字体大小,单位px',
|
||||
a3: 'number / string',
|
||||
a4: '',
|
||||
a5: '14',
|
||||
},
|
||||
{
|
||||
a1: 'height',
|
||||
a2: '通知栏高度,单位px',
|
||||
a3: 'number / string',
|
||||
a4: '',
|
||||
a5: '40',
|
||||
},
|
||||
{
|
||||
a1: 'delay',
|
||||
a2: '动画延迟时间 (s)',
|
||||
a3: 'number / string',
|
||||
a4: '',
|
||||
a5: '1',
|
||||
},
|
||||
{
|
||||
a1: 'speed',
|
||||
a2: '滚动速率 (px/s)',
|
||||
a3: 'number / string',
|
||||
a4: '',
|
||||
a5: '100',
|
||||
},
|
||||
{
|
||||
a1: 'scrollable',
|
||||
a2: '是否开启垂直滚动',
|
||||
a3: 'boolean',
|
||||
a4: 'true',
|
||||
a5: 'false',
|
||||
},
|
||||
{
|
||||
a1: 'leftIcon',
|
||||
a2: '自定义左侧图标',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '',
|
||||
},
|
||||
{
|
||||
a1: 'rightIcon',
|
||||
a2: '自定义右侧图标',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '',
|
||||
},
|
||||
],
|
||||
tableData1: [
|
||||
{
|
||||
a1: 'close',
|
||||
a2: '通知栏模式(mode)closeable 时回调事件',
|
||||
a3: 'function',
|
||||
a4: '',
|
||||
},
|
||||
{
|
||||
a1: 'link',
|
||||
a2: '通知栏模式(mode)link 时回调事件',
|
||||
a3: 'function',
|
||||
a4: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -1,126 +0,0 @@
|
||||
<template>
|
||||
<div class="selector-container">
|
||||
<el-card shadow="hover" header="图标选择器(宽度自动):">
|
||||
<IconSelector @get="onGetIcon" @clear="onClearIcon" v-model="modelIcon" />
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" header="图标选择器(宽度自动):参数" class="mt15">
|
||||
<el-table :data="tableData" style="width: 100%">
|
||||
<el-table-column prop="a1" label="参数"> </el-table-column>
|
||||
<el-table-column prop="a2" label="说明"> </el-table-column>
|
||||
<el-table-column prop="a3" label="类型"> </el-table-column>
|
||||
<el-table-column prop="a4" label="可选值"> </el-table-column>
|
||||
<el-table-column prop="a5" label="默认值"> </el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" header="图标选择器(宽度自动):事件" class="mt15">
|
||||
<el-table :data="tableData1" style="width: 100%">
|
||||
<el-table-column prop="a1" label="事件名称"> </el-table-column>
|
||||
<el-table-column prop="a2" label="说明"> </el-table-column>
|
||||
<el-table-column prop="a3" label="类型"> </el-table-column>
|
||||
<el-table-column prop="a4" label="回调参数"> </el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, defineComponent } from 'vue';
|
||||
import IconSelector from '/@/components/iconSelector/index.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'makeSelector',
|
||||
components: { IconSelector },
|
||||
setup() {
|
||||
const state = reactive({
|
||||
modelIcon: '',
|
||||
tableData: [
|
||||
{
|
||||
a1: 'prepend',
|
||||
a2: '输入框前置内容,只能字体图标',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: 'ele-Pointer',
|
||||
},
|
||||
{
|
||||
a1: 'placeholder',
|
||||
a2: '输入框占位文本',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '请输入内容搜索图标或者选择图标',
|
||||
},
|
||||
{
|
||||
a1: 'size',
|
||||
a2: '尺寸',
|
||||
a3: 'string',
|
||||
a4: 'large / default / small',
|
||||
a5: 'default',
|
||||
},
|
||||
{
|
||||
a1: 'title',
|
||||
a2: '弹窗标题',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '请选择图标',
|
||||
},
|
||||
{
|
||||
a1: 'type',
|
||||
a2: 'icon 图标类型',
|
||||
a3: 'string',
|
||||
a4: 'ali / ele / awe / all',
|
||||
a5: 'ele',
|
||||
},
|
||||
{
|
||||
a1: 'disabled',
|
||||
a2: '禁用',
|
||||
a3: 'boolean',
|
||||
a4: 'true',
|
||||
a5: 'false',
|
||||
},
|
||||
{
|
||||
a1: 'clearable',
|
||||
a2: '是否可清空',
|
||||
a3: 'boolean',
|
||||
a4: 'false',
|
||||
a5: 'true',
|
||||
},
|
||||
{
|
||||
a1: 'emptyDescription',
|
||||
a2: '自定义空状态描述文字',
|
||||
a3: 'String',
|
||||
a4: '',
|
||||
a5: '无相关图标',
|
||||
},
|
||||
],
|
||||
tableData1: [
|
||||
{
|
||||
a1: 'get',
|
||||
a2: '获取当前点击的 icon 图标',
|
||||
a3: 'function',
|
||||
a4: '(icon: string)',
|
||||
},
|
||||
{
|
||||
a1: 'clear',
|
||||
a2: '清空当前点击的 icon 图标',
|
||||
a3: 'function',
|
||||
a4: '(icon: string)',
|
||||
},
|
||||
],
|
||||
});
|
||||
// 获取当前点击的 icon 图标
|
||||
const onGetIcon = (icon: string) => {
|
||||
console.log(icon);
|
||||
};
|
||||
// 清空当前点击的 icon 图标
|
||||
const onClearIcon = (icon: string) => {
|
||||
console.log(icon);
|
||||
};
|
||||
return {
|
||||
onGetIcon,
|
||||
onClearIcon,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -1,59 +0,0 @@
|
||||
<template>
|
||||
<div class="svg-demo-container">
|
||||
<el-card shadow="hover" header="svgIcon:演示(支持本地svg)">
|
||||
<SvgIcon name="iconfont icon-shuju1" color="red" :size="30" />
|
||||
<SvgIcon name="ele-Trophy" color="var(--el-color-primary)" :size="30" />
|
||||
<SvgIcon name="fa fa-flag-checkered" color="#09f" :size="30" />
|
||||
<SvgIcon :name="logoMini" color="#09f" :size="30" />
|
||||
</el-card>
|
||||
<el-card shadow="hover" header="svgIcon:参数" class="mt15">
|
||||
<el-table :data="tableData" style="width: 100%">
|
||||
<el-table-column prop="a1" label="参数"> </el-table-column>
|
||||
<el-table-column prop="a2" label="说明"> </el-table-column>
|
||||
<el-table-column prop="a3" label="类型"> </el-table-column>
|
||||
<el-table-column prop="a4" label="可选值"> </el-table-column>
|
||||
<el-table-column prop="a5" label="默认值"> </el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, defineComponent } from 'vue';
|
||||
import logoMini from '/@/assets/logo-mini.svg';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'makeSvgDemo',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
tableData: [
|
||||
{
|
||||
a1: 'name',
|
||||
a2: 'svg 图标组件名字 / svg 路径 url',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '',
|
||||
},
|
||||
{
|
||||
a1: 'size',
|
||||
a2: 'svg 大小',
|
||||
a3: 'number',
|
||||
a4: '',
|
||||
a5: 14,
|
||||
},
|
||||
{
|
||||
a1: 'color',
|
||||
a2: 'svg 颜色',
|
||||
a3: 'string',
|
||||
a4: '',
|
||||
a5: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
return {
|
||||
logoMini,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -1,127 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card>
|
||||
<el-alert type="error" title="消息队列测试,先生产一条消息再订阅,先订阅不存在的topic会失败" :closable="false"></el-alert>
|
||||
<el-row :gutter="20" style="margin-top: 20px;">
|
||||
<el-col :span="10">
|
||||
<div class="my-title">生产者</div>
|
||||
<el-form :label-width="80">
|
||||
<el-form-item label="topic">
|
||||
<el-input v-model="demoForm.topic" />
|
||||
</el-form-item>
|
||||
<el-form-item label="topic">
|
||||
<el-input v-model="demoForm.body" type="textarea" :rows="6" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="default" @click="handleProduce">生产消息</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
<el-col :span="14">
|
||||
<div class="my-title">消费者</div>
|
||||
<el-form :label-width="80">
|
||||
<el-form-item label="topic">
|
||||
<el-input v-model="demoForm.topic" :disabled="wsReady" />
|
||||
</el-form-item>
|
||||
<el-form-item label="channel">
|
||||
<el-input v-model="demoForm.channel" :disabled="wsReady" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="default" type="primary" @click="handleStartSubscribe" :disabled="wsReady">订阅消费</el-button>
|
||||
<el-button size="default" type="primary" @click="handleUnSubscribe" :disabled="!wsReady">取消订阅</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="消费结果">
|
||||
<el-input :model-value="messageResult" type="textarea" :rows="12"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import {reactive, ref} from "vue";
|
||||
import {ElMessageBox} from "element-plus";
|
||||
import request from "/@/utils/request";
|
||||
|
||||
const demoForm = reactive({
|
||||
topic: "producer_topic_test",
|
||||
body: "测试消息队列内容",
|
||||
channel: "channel1"
|
||||
})
|
||||
const consumerForm = reactive({
|
||||
topic:"producer_topic_test",
|
||||
channel:"channel1"
|
||||
})
|
||||
|
||||
function handleProduce(){
|
||||
request({
|
||||
url: '/api/v1/mqueue/demo/produce',
|
||||
method: 'post',
|
||||
data: {topic:demoForm.topic,body:demoForm.body}
|
||||
}).then((res:any)=>{
|
||||
window.console.log(res)
|
||||
})
|
||||
}
|
||||
const webSocketURL = import.meta.env.VITE_WEBSOCKET_URL
|
||||
const messageResult = ref("")
|
||||
let ws:WebSocket|null = null
|
||||
const wsReady = ref(false)
|
||||
function handleStartSubscribe(){
|
||||
if(ws) return
|
||||
const url = webSocketURL+"api/v1/mqueue/demo/subscribe?topic="+demoForm.topic+"&channel="+demoForm.channel;
|
||||
ws = new WebSocket(url);
|
||||
try {
|
||||
// ws连接成功
|
||||
ws.onopen = function () {
|
||||
messageResult.value += "WebSocket Server [" + url +"] 连接成功!\r\n";
|
||||
wsReady.value = true
|
||||
};
|
||||
// ws连接关闭
|
||||
ws.onclose = function () {
|
||||
if (ws) {
|
||||
ws.close();
|
||||
ws = null;
|
||||
wsReady.value = false
|
||||
}
|
||||
messageResult.value += "WebSocket Server [" + url +"] 连接被服务器关闭!\r\n";
|
||||
};
|
||||
// ws连接错误
|
||||
ws.onerror = function () {
|
||||
if (ws) {
|
||||
ws.close();
|
||||
ws = null;
|
||||
wsReady.value = false
|
||||
}
|
||||
messageResult.value += "WebSocket Server [" + url +"] 连接错误!\r\n";
|
||||
};
|
||||
// ws数据返回处理
|
||||
ws.onmessage = function (result) {
|
||||
window.console.log(result)
|
||||
messageResult.value += " > " + result.data+"\r\n";
|
||||
};
|
||||
} catch (e:any) {
|
||||
ElMessageBox.alert(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
function handleUnSubscribe(){
|
||||
if(ws) {
|
||||
ws.close()
|
||||
ws = null;
|
||||
wsReady.value = false
|
||||
messageResult.value += "已手动取消订阅!\r\n";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-title{
|
||||
font-size: 16px; font-weight: bold;line-height: 2;
|
||||
color: #1890ff;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
</style>
|
@ -1,387 +0,0 @@
|
||||
<template>
|
||||
<div class="personal">
|
||||
<el-row>
|
||||
<!-- 个人信息 -->
|
||||
<el-col :xs="24" :sm="16">
|
||||
<el-card shadow="hover" header="个人信息">
|
||||
<div class="personal-user">
|
||||
<div class="personal-user-left">
|
||||
<el-upload class="h100 personal-user-left-upload" action="https://jsonplaceholder.typicode.com/posts/" multiple :limit="1">
|
||||
<img src="https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500" />
|
||||
</el-upload>
|
||||
</div>
|
||||
<div class="personal-user-right">
|
||||
<el-row>
|
||||
<el-col :span="24" class="personal-title mb18">{{ currentTime }},admin,生活变的再糟糕,也不妨碍我变得更好! </el-col>
|
||||
<el-col :span="24">
|
||||
<el-row>
|
||||
<el-col :xs="24" :sm="8" class="personal-item mb6">
|
||||
<div class="personal-item-label">昵称:</div>
|
||||
<div class="personal-item-value">小柒</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="16" class="personal-item mb6">
|
||||
<div class="personal-item-label">身份:</div>
|
||||
<div class="personal-item-value">超级管理</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-row>
|
||||
<el-col :xs="24" :sm="8" class="personal-item mb6">
|
||||
<div class="personal-item-label">登录IP:</div>
|
||||
<div class="personal-item-value">192.168.1.1</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="16" class="personal-item mb6">
|
||||
<div class="personal-item-label">登录时间:</div>
|
||||
<div class="personal-item-value">2021-02-05 18:47:26</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- 消息通知 -->
|
||||
<el-col :xs="24" :sm="8" class="pl15 personal-info">
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<span>消息通知</span>
|
||||
<span class="personal-info-more">更多</span>
|
||||
</template>
|
||||
<div class="personal-info-box">
|
||||
<ul class="personal-info-ul">
|
||||
<li v-for="(v, k) in newsInfoList" :key="k" class="personal-info-li">
|
||||
<a :href="v.link" target="_block" class="personal-info-li-title">{{ v.title }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- 营销推荐 -->
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover" class="mt15" header="营销推荐">
|
||||
<el-row :gutter="15" class="personal-recommend-row">
|
||||
<el-col :sm="6" v-for="(v, k) in recommendList" :key="k" class="personal-recommend-col">
|
||||
<div class="personal-recommend" :style="{ 'background-color': v.bg }">
|
||||
<SvgIcon :name="v.icon" :size="70" :style="{ color: v.iconColor }" />
|
||||
<div class="personal-recommend-auto">
|
||||
<div>{{ v.title }}</div>
|
||||
<div class="personal-recommend-msg">{{ v.msg }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- 更新信息 -->
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover" class="mt15 personal-edit" header="更新信息">
|
||||
<div class="personal-edit-title">基本信息</div>
|
||||
<el-form :model="personalForm" size="default" label-width="40px" class="mt35 mb35">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
||||
<el-form-item label="昵称">
|
||||
<el-input v-model="personalForm.name" placeholder="请输入昵称" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
||||
<el-form-item label="邮箱">
|
||||
<el-input v-model="personalForm.email" placeholder="请输入邮箱" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
||||
<el-form-item label="签名">
|
||||
<el-input v-model="personalForm.autograph" placeholder="请输入签名" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
||||
<el-form-item label="职业">
|
||||
<el-select v-model="personalForm.occupation" placeholder="请选择职业" clearable class="w100">
|
||||
<el-option label="计算机 / 互联网 / 通信" value="1"></el-option>
|
||||
<el-option label="生产 / 工艺 / 制造" value="2"></el-option>
|
||||
<el-option label="医疗 / 护理 / 制药" value="3"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
||||
<el-form-item label="手机">
|
||||
<el-input v-model="personalForm.phone" placeholder="请输入手机" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
||||
<el-form-item label="性别">
|
||||
<el-select v-model="personalForm.sex" placeholder="请选择性别" clearable class="w100">
|
||||
<el-option label="男" value="1"></el-option>
|
||||
<el-option label="女" value="2"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item>
|
||||
<el-button type="primary">
|
||||
<el-icon>
|
||||
<ele-Position />
|
||||
</el-icon>
|
||||
更新个人信息
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="personal-edit-title mb15">账号安全</div>
|
||||
<div class="personal-edit-safe-box">
|
||||
<div class="personal-edit-safe-item">
|
||||
<div class="personal-edit-safe-item-left">
|
||||
<div class="personal-edit-safe-item-left-label">账户密码</div>
|
||||
<div class="personal-edit-safe-item-left-value">当前密码强度:强</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-item-right">
|
||||
<el-button text type="primary">立即修改</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-box">
|
||||
<div class="personal-edit-safe-item">
|
||||
<div class="personal-edit-safe-item-left">
|
||||
<div class="personal-edit-safe-item-left-label">密保手机</div>
|
||||
<div class="personal-edit-safe-item-left-value">已绑定手机:132****4108</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-item-right">
|
||||
<el-button text type="primary">立即修改</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-box">
|
||||
<div class="personal-edit-safe-item">
|
||||
<div class="personal-edit-safe-item-left">
|
||||
<div class="personal-edit-safe-item-left-label">密保问题</div>
|
||||
<div class="personal-edit-safe-item-left-value">已设置密保问题,账号安全大幅度提升</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-item-right">
|
||||
<el-button text type="primary">立即设置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-box">
|
||||
<div class="personal-edit-safe-item">
|
||||
<div class="personal-edit-safe-item-left">
|
||||
<div class="personal-edit-safe-item-left-label">绑定QQ</div>
|
||||
<div class="personal-edit-safe-item-left-value">已绑定QQ:110****566</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-item-right">
|
||||
<el-button text type="primary">立即设置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive, computed, defineComponent } from 'vue';
|
||||
import { formatAxis } from '/@/utils/formatTime';
|
||||
import { newsInfoList, recommendList } from './mock';
|
||||
|
||||
// 定义接口来定义对象的类型
|
||||
interface PersonalState {
|
||||
newsInfoList: any;
|
||||
recommendList: any;
|
||||
personalForm: any;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'personal',
|
||||
setup() {
|
||||
const state = reactive<PersonalState>({
|
||||
newsInfoList,
|
||||
recommendList,
|
||||
personalForm: {
|
||||
name: '',
|
||||
email: '',
|
||||
autograph: '',
|
||||
occupation: '',
|
||||
phone: '',
|
||||
sex: '',
|
||||
},
|
||||
});
|
||||
// 当前时间提示语
|
||||
const currentTime = computed(() => {
|
||||
return formatAxis(new Date());
|
||||
});
|
||||
return {
|
||||
currentTime,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use '../../theme/mixins/index.scss' as *;
|
||||
.personal {
|
||||
.personal-user {
|
||||
height: 130px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.personal-user-left {
|
||||
width: 100px;
|
||||
height: 130px;
|
||||
border-radius: 3px;
|
||||
:deep(.el-upload) {
|
||||
height: 100%;
|
||||
}
|
||||
.personal-user-left-upload {
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 3px;
|
||||
}
|
||||
&:hover {
|
||||
img {
|
||||
animation: logoAnimation 0.3s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.personal-user-right {
|
||||
flex: 1;
|
||||
padding: 0 15px;
|
||||
.personal-title {
|
||||
font-size: 18px;
|
||||
@include text-ellipsis(1);
|
||||
}
|
||||
.personal-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
.personal-item-label {
|
||||
color: var(--el-text-color-secondary);
|
||||
@include text-ellipsis(1);
|
||||
}
|
||||
.personal-item-value {
|
||||
@include text-ellipsis(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.personal-info {
|
||||
.personal-info-more {
|
||||
float: right;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 13px;
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.personal-info-box {
|
||||
height: 130px;
|
||||
overflow: hidden;
|
||||
.personal-info-ul {
|
||||
list-style: none;
|
||||
.personal-info-li {
|
||||
font-size: 13px;
|
||||
padding-bottom: 10px;
|
||||
.personal-info-li-title {
|
||||
display: inline-block;
|
||||
@include text-ellipsis(1);
|
||||
color: var(--el-text-color-secondary);
|
||||
text-decoration: none;
|
||||
}
|
||||
& a:hover {
|
||||
color: var(--el-color-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.personal-recommend-row {
|
||||
.personal-recommend-col {
|
||||
.personal-recommend {
|
||||
position: relative;
|
||||
height: 100px;
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
i {
|
||||
right: 0px !important;
|
||||
bottom: 0px !important;
|
||||
transition: all ease 0.3s;
|
||||
}
|
||||
}
|
||||
i {
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
bottom: -10px;
|
||||
font-size: 70px;
|
||||
transform: rotate(-30deg);
|
||||
transition: all ease 0.3s;
|
||||
}
|
||||
.personal-recommend-auto {
|
||||
padding: 15px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 5%;
|
||||
color: var(--next-color-white);
|
||||
.personal-recommend-msg {
|
||||
font-size: 12px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.personal-edit {
|
||||
.personal-edit-title {
|
||||
position: relative;
|
||||
padding-left: 10px;
|
||||
color: var(--el-text-color-regular);
|
||||
&::after {
|
||||
content: '';
|
||||
width: 2px;
|
||||
height: 10px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
.personal-edit-safe-box {
|
||||
border-bottom: 1px solid var(--el-border-color-light, #ebeef5);
|
||||
padding: 15px 0;
|
||||
.personal-edit-safe-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.personal-edit-safe-item-left {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
.personal-edit-safe-item-left-label {
|
||||
color: var(--el-text-color-regular);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.personal-edit-safe-item-left-value {
|
||||
color: var(--el-text-color-secondary);
|
||||
@include text-ellipsis(1);
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:last-of-type {
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,66 +0,0 @@
|
||||
/**
|
||||
* 消息通知
|
||||
* @returns 返回模拟数据
|
||||
*/
|
||||
export const newsInfoList: Array<object> = [
|
||||
{
|
||||
title: '[发布] 2021年02月28日发布基于 vue3.x + vite v1.0.0 版本',
|
||||
date: '02/28',
|
||||
link: 'https://gitee.com/lyt-top/vue-next-admin',
|
||||
},
|
||||
{
|
||||
title: '[发布] 2021年04月15日发布 vue2.x + webpack 重构版本',
|
||||
date: '04/15',
|
||||
link: 'https://gitee.com/lyt-top/vue-next-admin/tree/vue-prev-admin/',
|
||||
},
|
||||
{
|
||||
title: '[重构] 2021年04月10日 重构 vue2.x + webpack v1.0.0 版本',
|
||||
date: '04/10',
|
||||
link: 'https://gitee.com/lyt-top/vue-next-admin/tree/vue-prev-admin/',
|
||||
},
|
||||
{
|
||||
title: '[预览] 2020年12月08日,基于 vue3.x 版本后台模板的预览',
|
||||
date: '12/08',
|
||||
link: 'http://lyt-top.gitee.io/vue-next-admin-preview/#/login',
|
||||
},
|
||||
{
|
||||
title: '[预览] 2020年11月15日,基于 vue2.x 版本后台模板的预览',
|
||||
date: '11/15',
|
||||
link: 'https://lyt-top.gitee.io/vue-prev-admin-preview/#/login',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 营销推荐
|
||||
* @returns 返回模拟数据
|
||||
*/
|
||||
export const recommendList: Array<object> = [
|
||||
{
|
||||
title: '优惠券',
|
||||
msg: '现金券、折扣券、营销必备',
|
||||
icon: 'ele-Food',
|
||||
bg: '#48D18D',
|
||||
iconColor: '#64d89d',
|
||||
},
|
||||
{
|
||||
title: '多人拼团',
|
||||
msg: '社交电商、开辟流量',
|
||||
icon: 'ele-ShoppingCart',
|
||||
bg: '#F95959',
|
||||
iconColor: '#F86C6B',
|
||||
},
|
||||
{
|
||||
title: '分销中心',
|
||||
msg: '轻松招募分销员,成功推广奖励',
|
||||
icon: 'ele-School',
|
||||
bg: '#8595F4',
|
||||
iconColor: '#92A1F4',
|
||||
},
|
||||
{
|
||||
title: '秒杀',
|
||||
msg: '超低价抢购引导更多销量',
|
||||
icon: 'ele-AlarmClock',
|
||||
bg: '#FEBB50',
|
||||
iconColor: '#FDC566',
|
||||
},
|
||||
];
|
@ -2,7 +2,7 @@
|
||||
<div class="personal">
|
||||
<el-row>
|
||||
<!-- 个人信息 -->
|
||||
<el-col :xs="24" :sm="16">
|
||||
<el-col :xs="24" :sm="24">
|
||||
<el-card shadow="hover" header="个人信息">
|
||||
<div class="personal-user">
|
||||
<div class="personal-user-left">
|
||||
@ -64,7 +64,7 @@
|
||||
</el-col>
|
||||
|
||||
<!-- 消息通知 -->
|
||||
<el-col :xs="24" :sm="8" class="pl15 personal-info">
|
||||
<!-- <el-col :xs="24" :sm="8" class="pl15 personal-info">
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<span>消息通知</span>
|
||||
@ -78,10 +78,10 @@
|
||||
</ul>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
|
||||
<!-- 营销推荐 -->
|
||||
<el-col :span="24">
|
||||
<!-- <el-col :span="24">
|
||||
<el-card shadow="hover" class="mt15" header="营销推荐">
|
||||
<el-row :gutter="15" class="personal-recommend-row">
|
||||
<el-col :sm="6" v-for="(v, k) in recommendList" :key="k" class="personal-recommend-col">
|
||||
@ -95,7 +95,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
|
||||
<!-- 更新信息 -->
|
||||
<el-col :span="24">
|
||||
@ -164,39 +164,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-box">
|
||||
<div class="personal-edit-safe-item">
|
||||
<div class="personal-edit-safe-item-left">
|
||||
<div class="personal-edit-safe-item-left-label">密保手机</div>
|
||||
<div class="personal-edit-safe-item-left-value">已绑定手机:132****4108</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-item-right">
|
||||
<el-button text type="primary">立即修改</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-box">
|
||||
<div class="personal-edit-safe-item">
|
||||
<div class="personal-edit-safe-item-left">
|
||||
<div class="personal-edit-safe-item-left-label">密保问题</div>
|
||||
<div class="personal-edit-safe-item-left-value">已设置密保问题,账号安全大幅度提升</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-item-right">
|
||||
<el-button text type="primary">立即设置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-box">
|
||||
<div class="personal-edit-safe-item">
|
||||
<div class="personal-edit-safe-item-left">
|
||||
<div class="personal-edit-safe-item-left-label">绑定QQ</div>
|
||||
<div class="personal-edit-safe-item-left-value">已绑定QQ:110****566</div>
|
||||
</div>
|
||||
<div class="personal-edit-safe-item-right">
|
||||
<el-button text type="primary">立即设置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 607 KiB |
Binary file not shown.
Before Width: | Height: | Size: 783 KiB |
@ -1,51 +0,0 @@
|
||||
// 地图模拟数据
|
||||
export const echartsMapList: Array<object> = [
|
||||
{ name: '深圳市人民政府', value: '100' },
|
||||
{ name: '莲花山公园', value: '100' },
|
||||
{ name: '世界之窗', value: '100' },
|
||||
{ name: '华侨城欢乐谷', value: '100' },
|
||||
{ name: '宝安区西乡', value: '100' },
|
||||
];
|
||||
|
||||
// 地图经纬度数据
|
||||
export const echartsMapData: object = {
|
||||
深圳市人民政府: [114.064524, 22.549225],
|
||||
莲花山公园: [114.0658, 22.560072],
|
||||
世界之窗: [113.979419, 22.540579],
|
||||
华侨城欢乐谷: [113.986066, 22.548056],
|
||||
宝安区西乡: [113.869053, 22.581714],
|
||||
};
|
||||
|
||||
// 地图图片显示
|
||||
export const echartsMapImgs: Array<object> = [
|
||||
{
|
||||
url: 'https://img1.baidu.com/it/u=4244861097,3561366422&fm=11&fmt=auto&gp=0.jpg',
|
||||
name: '深圳市人民政府',
|
||||
add: '深圳市福田区福中三路市民中心C区',
|
||||
dec: '深圳市人民政府是根据《中华人民共和国地方各级人民代表大会和地方各级人民政府组织法》设立的,是深圳市人民代表大会的执行机关,是深圳市的国家行政机关。',
|
||||
},
|
||||
{
|
||||
url: 'https://img1.baidu.com/it/u=3793608028,4006842751&fm=26&fmt=auto&gp=0.jpg',
|
||||
name: '莲花山公园',
|
||||
add: '广东省深圳市福田区莲花街道莲花北社区红荔路6030号',
|
||||
dec: '莲花山公园筹建于1992年10月10日 ,1997年6月23日正式对外局部开放。',
|
||||
},
|
||||
{
|
||||
url: 'https://img0.baidu.com/it/u=1406340112,1927292660&fm=26&fmt=auto&gp=0.jpg',
|
||||
name: '世界之窗',
|
||||
add: '深圳市南山区深南大道9037号',
|
||||
dec: '这里,世界首座实景拍摄悬空式球幕影院“飞跃美利坚””,为游客提供集休闲放松于一体的都市时尚生活空间。',
|
||||
},
|
||||
{
|
||||
url: 'https://img0.baidu.com/it/u=3042342330,902556630&fm=26&fmt=auto&gp=0.jpg',
|
||||
name: '华侨城欢乐谷',
|
||||
add: '广东省深圳市南山区沙河街道星河街社区侨城西街1号',
|
||||
dec: '深圳欢乐谷注重满足人们参与、体验的新型诱游需求,营造出自然、清新、活泼、惊奇、热烈、刺激的休闲旅游氛围。',
|
||||
},
|
||||
{
|
||||
url: 'https://img2.baidu.com/it/u=1075072079,1229283519&fm=11&fmt=auto&gp=0.jpg',
|
||||
name: '宝安区西乡',
|
||||
add: '西乡街道下辖25个社区',
|
||||
dec: '西乡街道,隶属于广东省深圳市宝安区,位于宝安区西南部,东接石岩街道,南接新安街道,西至珠江口岸边,北接航城街道。',
|
||||
},
|
||||
];
|
@ -1,131 +0,0 @@
|
||||
// 顶部下来菜单
|
||||
export const dropdownList: Array<object> = [
|
||||
{
|
||||
label: '广东省农业农村厅',
|
||||
},
|
||||
{
|
||||
label: '广西省农业农村厅',
|
||||
},
|
||||
{
|
||||
label: '四川省农业农村厅',
|
||||
},
|
||||
{
|
||||
label: '湖北省农业农村厅',
|
||||
},
|
||||
{
|
||||
label: '福建省农业农村厅',
|
||||
},
|
||||
{
|
||||
label: '山东省农业农村厅',
|
||||
},
|
||||
{
|
||||
label: '江西省农业农村厅',
|
||||
},
|
||||
];
|
||||
|
||||
// sky 天气
|
||||
export const skyList: Array<object> = [
|
||||
{
|
||||
v1: '时间',
|
||||
v2: '天气',
|
||||
v3: '温度',
|
||||
v4: '湿度',
|
||||
v5: '降水概率',
|
||||
v6: '风向',
|
||||
v7: '风力',
|
||||
type: 'title',
|
||||
},
|
||||
{
|
||||
v1: '今天',
|
||||
v2: 'ele-Sunny',
|
||||
v3: '20°/26°',
|
||||
v4: '80%',
|
||||
v5: '50%',
|
||||
v6: '东南风',
|
||||
v7: '13m/s',
|
||||
},
|
||||
{
|
||||
v1: '明天',
|
||||
v2: 'ele-Lightning',
|
||||
v3: '20°/26°',
|
||||
v4: '80%',
|
||||
v5: '50%',
|
||||
v6: '东南风',
|
||||
v7: '13m/s',
|
||||
},
|
||||
{
|
||||
v1: '后天',
|
||||
v2: 'ele-Sunny',
|
||||
v3: '20°/26°',
|
||||
v4: '80%',
|
||||
v5: '50%',
|
||||
v6: '东南风',
|
||||
v7: '13m/s',
|
||||
},
|
||||
];
|
||||
|
||||
// 当前设置状态
|
||||
export const dBtnList: Array<object> = [
|
||||
{
|
||||
v1: '地块A-灌溉',
|
||||
v2: '阳光玫瑰种植',
|
||||
v3: '126天',
|
||||
v4: '设备在线',
|
||||
},
|
||||
{
|
||||
v1: '地块B-收割',
|
||||
v2: '阳光玫瑰种植',
|
||||
v3: '360天',
|
||||
v4: '设备预警',
|
||||
},
|
||||
];
|
||||
|
||||
// 当前设备监测
|
||||
export const chartData4List: Array<object> = [
|
||||
{
|
||||
label: '温度',
|
||||
},
|
||||
{
|
||||
label: '光照',
|
||||
},
|
||||
{
|
||||
label: '湿度',
|
||||
},
|
||||
{
|
||||
label: '风力',
|
||||
},
|
||||
{
|
||||
label: '张力',
|
||||
},
|
||||
{
|
||||
label: '气压',
|
||||
},
|
||||
];
|
||||
|
||||
// 3DEarth 地图周围按钮组
|
||||
export const earth3DBtnList: Array<object> = [
|
||||
{
|
||||
topLevelClass: 'fixed-top',
|
||||
icon: 'ele-MagicStick',
|
||||
label: '环境监测',
|
||||
type: 0,
|
||||
},
|
||||
{
|
||||
topLevelClass: 'fixed-right',
|
||||
icon: 'ele-MoonNight',
|
||||
label: '精准管理',
|
||||
type: 1,
|
||||
},
|
||||
{
|
||||
topLevelClass: 'fixed-bottom',
|
||||
icon: 'ele-TrendCharts',
|
||||
label: '数据报表',
|
||||
type: 2,
|
||||
},
|
||||
{
|
||||
topLevelClass: 'fixed-left',
|
||||
icon: 'ele-Van',
|
||||
label: '产品追溯',
|
||||
type: 3,
|
||||
},
|
||||
];
|
@ -69,6 +69,6 @@
|
||||
"skipLibCheck": true /* Skip type checking of declaration files. */,
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.vue", "src/**/*.tsx", "src/**/*.d.ts"], // **Represents any directory, and * represents any file. Indicates that all files in the src directory will be compiled
|
||||
"include": ["src/**/*.ts", "src/**/*.vue", "src/**/*.tsx", "src/**/*.d.ts", "shim.d.ts"], // **Represents any directory, and * represents any file. Indicates that all files in the src directory will be compiled
|
||||
"exclude": ["node_modules", "dist"] // Indicates the file directory that does not need to be compiled
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user