Compare commits

...

148 Commits

Author SHA1 Message Date
GitHub Actions Bot
2fd75fe097 🔱: [client] sync upgrade with 6 commits [trident-sync]
build: publish success
perf: antdv示例背景设置为白色
fix: card布局情况下,header-top header-bottom同时跟search显隐的bug
fix: 修复table-select 示例右上角自定义插槽无法设置的bug
feat: 将代码编辑器单独打包到@fast-crud/editor-code,加快不需要code的项目的打包速度,如果您使用了editor-code,请按照文档重新进行editor-code的集成

BREAKING CHANGE: 将代码编辑器单独打包到@fast-crud/editor-code,,如果您使用了editor-code,请按照文档重新进行editor-code的集成
2025-07-28 19:27:48 +00:00
GitHub Actions Bot
76b963f426 🔱: [client] sync upgrade with 2 commits [trident-sync]
fix: 独立使用form表单缺失mode的问题
2025-07-25 19:27:15 +00:00
GitHub Actions Bot
85cbc16c53 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
fix: 修复fs-values-format组件某些值无法获取自动颜色的bug
2025-06-10 19:25:46 +00:00
GitHub Actions Bot
f802b4c2dd 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore: 增加打开对话框示例
2025-05-28 19:25:49 +00:00
GitHub Actions Bot
957d9d8307 🔱: [client] sync upgrade with 4 commits [trident-sync]
build: publish success
fix: 修复cloneable模式下的dict 无法动态修改data的bug
chore:
2025-05-26 19:25:13 +00:00
GitHub Actions Bot
407b11fdf9 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
chore:
2025-05-14 19:25:07 +00:00
GitHub Actions Bot
f0b5489e3e 🔱: [client] sync upgrade with 4 commits [trident-sync]
perf: 单元格支持tooltip
Merge remote-tracking branch 'origin/main'

# Conflicts:
#	src/plugin/antdv-async/index.ts
fix: 修复naive-ui下 form-item 的label设置为render会报警告的问题
2025-04-28 19:25:14 +00:00
GitHub Actions Bot
7bb8e9bdc4 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
perf: 优化antdv单元格合并示例,使用customCell方法,以及增加操作列合并演示
2025-04-25 19:25:06 +00:00
GitHub Actions Bot
c7a3bc9eac 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 新增editable-select组件
2025-04-23 19:25:19 +00:00
GitHub Actions Bot
ec01f47b98 🔱: [client] sync upgrade with 4 commits [trident-sync]
build: publish success
fix: 修复yaml workers引入问题
fix: 修复预览大图previewurl错误的bug
2025-04-16 19:25:11 +00:00
GitHub Actions Bot
dde43bbe4d 🔱: [client] sync upgrade with 8 commits [trident-sync]
build: publish success
chore:
chore:
chore:
fix: 修复commonOptions无法覆盖某些参数的bug
chore: yaml-worker挪到外面
fix: fs-editor-code 支持配置schema校验
2025-04-10 19:24:40 +00:00
GitHub Actions Bot
34aea1d398 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 添加代码编辑器示例
2025-03-31 19:25:06 +00:00
GitHub Actions Bot
88a4e5051b 🔱: [client] sync upgrade with 6 commits [trident-sync]
chore:
build: publish success
fix: 修复新页面编辑无法正确获取数据的bug

Closes https://github.com/fast-crud/fast-crud/issues/460
fix: 修复antdv4示例没有源码跳转按钮的bug
pref: 添加代码编辑器功能

- 新增 fs-editor-code组件实现代码编辑功能
- 支持 javascript、json、yaml三种语言
- 集成 monaco-editor 并配置相关 worker
- 添加代码格式校验功能
- 在 fast-extends 中引入新功能模块
2025-03-30 19:24:09 +00:00
GitHub Actions Bot
6f30d82394 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore: trace
2025-03-27 19:24:52 +00:00
GitHub Actions Bot
d2652baf22 🔱: [client] sync upgrade with 4 commits [trident-sync]
build: publish success
build: publish success
perf: antdv示例增加保存列宽功能
2025-03-19 19:25:03 +00:00
GitHub Actions Bot
2b4b15f558 🔱: [client] sync upgrade with 6 commits [trident-sync]
chore:
chore: help menu
chore: help menu
fix: 修复 antdv 弹出菜单边框过大的问题
fix: 修复 antdv懒加载后dropdown按钮无法点击的bug
2025-03-05 19:24:47 +00:00
GitHub Actions Bot
140606744b 🔱: [client] sync upgrade with 5 commits [trident-sync]
build: publish success
perf: antdv 异步加载,加快首页打开速度
perf: 精简lodash
chore: 兼容手机版
2025-03-04 19:24:24 +00:00
GitHub Actions Bot
335d175d57 🔱: [client] sync upgrade with 7 commits [trident-sync]
chore:
Merge branch 'vben'

# Conflicts:
#	package.json
perf: antdv示例改成使用vben框架
chore: vben
chore: vben
chore: vben
2025-03-03 19:24:51 +00:00
GitHub Actions Bot
de26ee9383 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2025-02-23 19:23:42 +00:00
GitHub Actions Bot
d442462952 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2025-02-22 19:23:46 +00:00
GitHub Actions Bot
558fc9f306 🔱: [client] sync upgrade with 2 commits [trident-sync]
fix: 修复4.2.x版本antdv导致modal全屏无效的bug
2025-02-20 19:24:20 +00:00
GitHub Actions Bot
2eebb3388a 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore:
2025-02-12 19:24:12 +00:00
GitHub Actions Bot
fe4367c580 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore:
2025-01-24 19:24:01 +00:00
GitHub Actions Bot
e70732c9ac 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2025-01-12 19:23:54 +00:00
GitHub Actions Bot
42ad04cabd 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 支持图标选择器
2025-01-09 19:24:07 +00:00
GitHub Actions Bot
7f5e89d489 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
chore:
2024-12-31 19:23:58 +00:00
GitHub Actions Bot
c504f33b1f 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
chore:
2024-12-28 19:23:55 +00:00
GitHub Actions Bot
ed6a18dae7 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore: 提示优化
2024-12-24 19:23:49 +00:00
GitHub Actions Bot
844c4bf983 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
fix: 修复表单全屏的bug
2024-12-03 19:26:18 +00:00
GitHub Actions Bot
43961c1c18 🔱: [client] sync upgrade with 3 commits [trident-sync]
perf: rowHandle按钮支持render,删除按钮提供popcomfirm风格示例
perf: table-select open支持context参数
2024-12-02 19:26:32 +00:00
GitHub Actions Bot
7b42d7252e 🔱: [client] sync upgrade with 5 commits [trident-sync]
build: publish success
perf: 增加card列表示例
fix: 修复antdv4新页面打开示例不显示表单的bug
chore:
2024-11-26 19:26:27 +00:00
GitHub Actions Bot
4aa136189a 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2024-11-18 19:25:37 +00:00
GitHub Actions Bot
c66802af2d 🔱: [client] sync upgrade with 2 commits [trident-sync]
fix: 修复dict-select多选情况下selected-change返回为空的bug
2024-11-15 19:25:37 +00:00
GitHub Actions Bot
49e65c611f 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
fix: 修复1.23.0 antdv下不显示pagination的bug
2024-11-13 19:24:23 +00:00
GitHub Actions Bot
abf29bc164 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
chore:
2024-11-11 19:23:56 +00:00
GitHub Actions Bot
08854e0ab9 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore:
2024-11-07 19:24:59 +00:00
GitHub Actions Bot
575416a16d 🔱: [client] sync upgrade with 4 commits [trident-sync]
feat: 示例全面改成useFsAsync
chore:
perf: 示例改成useFsAsync
2024-11-06 19:26:07 +00:00
GitHub Actions Bot
3dd0783510 🔱: [client] sync upgrade with 5 commits [trident-sync]
build: publish success
chore:
fix: 修复tab change后清空查询表单的bug
build: publish success
2024-11-04 19:26:56 +00:00
GitHub Actions Bot
fadb1d35b3 🔱: [client] sync upgrade with 3 commits [trident-sync]
Merge remote-tracking branch 'origin/main'
fix: 修复search.formItem配置无效的bug
2024-10-30 19:26:28 +00:00
GitHub Actions Bot
27a9fc32a6 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: editable row 优化添加
2024-10-26 19:23:53 +00:00
GitHub Actions Bot
7008a408ca 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2024-10-24 19:26:31 +00:00
GitHub Actions Bot
b928bb46c7 🔱: [client] sync upgrade with 7 commits [trident-sync]
build: publish success
chore:
perf: editable支持单元格插槽

https://github.com/fast-crud/fast-crud/issues/431
perf: 独立使用表单支持插槽

https://github.com/fast-crud/fast-crud/issues/435
perf: 表单支持左右插槽
chore:
2024-10-23 19:24:45 +00:00
GitHub Actions Bot
18c9c4a166 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
build: publish success
2024-10-21 19:25:06 +00:00
GitHub Actions Bot
49fa01f209 🔱: [client] sync upgrade with 4 commits [trident-sync]
build: publish success
perf: 优化列设置多级表头支持级联勾选
perf: table-select支持destroyOnClose参数,以修复点击取消后,扔保留上一次选中值的bug
2024-10-13 19:27:22 +00:00
GitHub Actions Bot
fe9d443100 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 优化示例的自动调整列宽
2024-09-25 19:23:59 +00:00
GitHub Actions Bot
3dec43d8d4 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2024-09-20 19:24:53 +00:00
GitHub Actions Bot
5ab2943c3a 🔱: [client] sync upgrade with 2 commits [trident-sync]
fix: 修复search-slot错位的问题
2024-09-11 19:24:00 +00:00
GitHub Actions Bot
6e8b0eeca9 🔱: [client] sync upgrade with 2 commits [trident-sync]
fix: 修复antdv 文件上传 success事件无效的bug
2024-09-10 19:24:33 +00:00
GitHub Actions Bot
d0c4dfca97 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 全部支持拖动调整列宽
2024-08-04 19:24:18 +00:00
GitHub Actions Bot
f4a11ed328 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore:
2024-07-29 19:24:00 +00:00
GitHub Actions Bot
b2971cf5fb 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore:
2024-07-28 19:23:50 +00:00
GitHub Actions Bot
f97827ec76 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
Merge remote-tracking branch 'origin/main'
2024-07-15 19:23:57 +00:00
GitHub Actions Bot
f230a2a94d 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore: 1
2024-07-14 19:24:39 +00:00
GitHub Actions Bot
54d9050483 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 优化editorwang示例
2024-07-12 19:23:47 +00:00
GitHub Actions Bot
80019d4dc1 🔱: [client] sync upgrade with 3 commits [trident-sync]
docs: 1
docs: 1
2024-07-11 19:23:48 +00:00
GitHub Actions Bot
692e2b5b96 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 增加示例,FsInDrawer
2024-06-26 19:24:03 +00:00
GitHub Actions Bot
586d23fc55 🔱: [client] sync upgrade with 6 commits [trident-sync]
build: publish success
fix: 修复多级表头时列设置的问题

https://github.com/fast-crud/fast-crud/issues/175
chore: 1
fix: 修复element示例中远程搜索下拉框label不显示的bug

https://github.com/fast-crud/fast-crud/issues/422
fix: 修复独立使用对话框 openDialog方法await无返回值的bug
2024-06-23 19:23:47 +00:00
GitHub Actions Bot
ad360e81cb 🔱: [client] sync upgrade with 21 commits [trident-sync]
perf: 优化antdv4 示例授权页面tree的样式
build: publish success
chore: 1
chore: 1
chore: 1
fix: getFileName支持item参数

https://github.com/fast-crud/fast-crud/issues/385
fix: fs-form独立使用支持插槽

https://github.com/fast-crud/fast-crud/issues/389
fix: 修复三级以上路由页面无法缓存的问题

https://github.com/fast-crud/fast-crud/issues/394
perf: form.wrapper.buttons支持compute动态计算
feat: 表单支持变更关闭前提醒保存,form.wrapper支持beforeClose事件
fix: 修复图片裁剪按钮上下和左右相反的bug

https://github.com/fast-crud/fast-crud/issues/402
perf: alioss getAuthorization接口支持后台返回key

https://github.com/fast-crud/fast-crud/issues/405
perf: alioss getAuthorization接口支持后台返回key

https://github.com/fast-crud/fast-crud/issues/405
perf: fs-dict-tree支持插槽

https://github.com/fast-crud/fast-crud/issues/407
perf: 单选、多选、select、tree-select、table-select 都提供selected-change事件,可以获取选中的dict选项
feat: table-select 支持查看模式

https://github.com/fast-crud/fast-crud/issues/413
perf: 优化fs-admin可以在手机上操作
chore: pnpm workspace问题优化
docs: 1
chore: antdv4 支持主题色选择
...
2024-06-15 18:32:36 +00:00
GitHub Actions Bot
9caa4cd1d4 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
fix: 修复三级以上路由页面无法缓存的问题

https://github.com/fast-crud/fast-crud/issues/394
2024-06-09 19:23:54 +00:00
GitHub Actions Bot
91fd80d44f 🔱: [client] sync upgrade with 3 commits [trident-sync]
perf: alioss getAuthorization接口支持后台返回key

https://github.com/fast-crud/fast-crud/issues/405
fix: edit-wang 改成edit-wang5

https://github.com/fast-crud/fast-crud/issues/409
2024-06-08 19:24:01 +00:00
GitHub Actions Bot
f932e553b0 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore: pnpm workspace问题优化
2024-05-30 19:23:48 +00:00
GitHub Actions Bot
33fb1a6bf3 🔱: [client] sync upgrade with 2 commits [trident-sync]
docs: 修改依赖增加workspace:
2024-05-10 19:23:53 +00:00
GitHub Actions Bot
56a1f8158a 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
chore:
2024-03-21 19:24:00 +00:00
GitHub Actions Bot
92f9371156 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
fix: 修复1.20.0版本子表行編輯情況下,删除无效的bug

Closes https://github.com/fast-crud/fast-crud/issues/362
2024-02-27 19:24:07 +00:00
GitHub Actions Bot
3e3373b8c7 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2024-01-28 19:24:14 +00:00
GitHub Actions Bot
7d45db89bf 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 行编辑也支持排他式激活

Closes https://github.com/fast-crud/fast-crud/issues/332
2024-01-25 19:23:52 +00:00
GitHub Actions Bot
b2abf1490b 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2023-12-15 19:24:10 +00:00
GitHub Actions Bot
02bfbd5019 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 增加formWatch示例
2023-12-06 19:24:02 +00:00
GitHub Actions Bot
282f8b4e02 🔱: [client] sync upgrade with 5 commits [trident-sync]
chore:
chore:
chore: editRequest 判断form.id不为空
chore:
2023-11-23 19:24:19 +00:00
GitHub Actions Bot
3393bde820 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2023-11-22 19:24:09 +00:00
GitHub Actions Bot
2277c87908 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore:
2023-11-21 19:24:11 +00:00
GitHub Actions Bot
2ea0c48853 🔱: [client] sync upgrade with 8 commits [trident-sync]
build: publish success
chore:
chore:
chore:
chore:
build: publish success
chore:
2023-11-20 19:24:12 +00:00
GitHub Actions Bot
28cbefde04 🔱: [client] sync upgrade with 2 commits [trident-sync]
feat(editable): editable优化重构,分三种模式:free、row、cell
2023-11-19 19:24:08 +00:00
GitHub Actions Bot
4e13843c78 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2023-11-08 19:24:13 +00:00
GitHub Actions Bot
a929f8429d 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2023-11-07 19:24:00 +00:00
GitHub Actions Bot
1df036a811 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore:
2023-10-31 19:24:08 +00:00
GitHub Actions Bot
461a12e909 🔱: [client] sync upgrade with 5 commits [trident-sync]
build: publish success
perf: component.name局部引用无需shallowRef包裹
build: publish success
build: publish success
2023-10-26 19:24:28 +00:00
GitHub Actions Bot
afb682e3eb 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
feat: 新特性,CrudOptionsPlugin
2023-10-25 19:24:07 +00:00
GitHub Actions Bot
31384fbce5 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 优化文档搜索
2023-10-24 19:24:06 +00:00
GitHub Actions Bot
2ffc7d19f1 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
chore:
2023-09-26 19:24:11 +00:00
GitHub Actions Bot
d857021df5 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2023-09-23 19:24:21 +00:00
GitHub Actions Bot
2ee864ccaf 🔱: [client] sync upgrade with 3 commits [trident-sync]
chore:
build: publish success
2023-09-16 19:24:09 +00:00
GitHub Actions Bot
018dfed128 🔱: [client] sync upgrade with 4 commits [trident-sync]
build: publish success
chore:  keepName: true,
perf: table select 支持返回object对象

https://github.com/fast-crud/fast-crud/issues/241
2023-09-13 19:24:15 +00:00
GitHub Actions Bot
90e4545210 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2023-09-12 19:23:50 +00:00
GitHub Actions Bot
4a4b16b010 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: table-select支持跨页选择
2023-09-11 19:24:00 +00:00
GitHub Actions Bot
8701303012 🔱: [client] sync upgrade with 3 commits [trident-sync]
perf: dict.getNodesByValues 修改为单例模式也可以运行,无需配置prototype,优化性能
chore: 各ui支持table-select
2023-09-09 19:24:09 +00:00
GitHub Actions Bot
9788aefcc1 🔱: [client] sync upgrade with 12 commits [trident-sync]
chore: 1.16.11
chore: 1.16.10
chore:
chore:
chore:
build: publish success
perf: 组件独立使用示例

https://github.com/fast-crud/fast-crud/issues/226
perf: 导出增加 onlyShow 和 columnFilter配置

https://github.com/fast-crud/fast-crud/issues/229
Merge remote-tracking branch 'origin/main'
perf: 表单labelWidth演示

https://github.com/fast-crud/fast-crud/issues/230
perf: 翻页后自动滚动到顶部

https://github.com/fast-crud/fast-crud/issues/232
2023-09-03 19:24:05 +00:00
GitHub Actions Bot
ed08ef1604 🔱: [client] sync upgrade with 6 commits [trident-sync]
chore:
chore:
fix: 修复无法嵌套路由的bug
build: publish success
build: publish success
2023-08-21 19:24:03 +00:00
GitHub Actions Bot
adce70a5e5 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2023-08-20 19:24:13 +00:00
GitHub Actions Bot
d5978f64e1 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore:
2023-08-19 19:23:55 +00:00
GitHub Actions Bot
45215debcc 🔱: [client] sync upgrade with 4 commits [trident-sync]
build: publish success
chore:
perf: 增加查看表单使用单元格组件示例

https://github.com/fast-crud/fast-crud/issues/219
2023-08-18 19:24:07 +00:00
GitHub Actions Bot
919eef55a1 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2023-08-10 19:24:03 +00:00
GitHub Actions Bot
8c529eed46 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore:
2023-08-09 19:24:03 +00:00
GitHub Actions Bot
7909c2cd46 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2023-08-07 19:24:11 +00:00
GitHub Actions Bot
b1ac396bf1 🔱: [client] sync upgrade with 4 commits [trident-sync]
build: publish success
chore:
chore:
2023-08-05 19:24:03 +00:00
GitHub Actions Bot
d5eb4a1900 🔱: [client] sync upgrade with 6 commits [trident-sync]
chore:
feat: antdv4 支持
perf: 升级依赖版本
Merge remote-tracking branch 'origin/main'
chore: antdv4 start
2023-08-04 19:23:57 +00:00
GitHub Actions Bot
b8eb27441c 🔱: [client] sync upgrade with 3 commits [trident-sync]
Merge remote-tracking branch 'origin/main'
feat: 重构search,支持search.validatedForm直接修改查询表单数据,修复tab变化后清空查询表单的bug

https://github.com/fast-crud/fast-crud/issues/215
2023-08-03 19:24:08 +00:00
GitHub Actions Bot
de1494710a 🔱: [client] sync upgrade with 2 commits [trident-sync]
build: publish success
2023-07-24 19:24:03 +00:00
GitHub Actions Bot
e3b05ac77f 🔱: [client] sync upgrade with 3 commits [trident-sync]
build: publish success
refactor: fs-images-format images prop define
2023-07-23 19:24:04 +00:00
GitHub Actions Bot
32c8e9482c 🔱: [client] sync upgrade with 2 commits [trident-sync]
fix: 修复hello world 返回数据格式错误
2023-07-10 19:24:06 +00:00
GitHub Actions Bot
b4c4dc2c2e 🔱: [client] sync upgrade with 5 commits [trident-sync]
build: publish success
chore:
chore:
perf: 优化export,支持查询导出
2023-07-04 19:24:06 +00:00
GitHub Actions Bot
474fd77970 🔱: [client] sync upgrade with 3 commits [trident-sync]
fix: 修复search.value第一次查询无效的bug

https://github.com/fast-crud/fast-crud/issues/208
build: publish success
2023-07-03 19:24:01 +00:00
GitHub Actions Bot
6fda0d6896 🔱: [client] sync upgrade with 8 commits [trident-sync]
chore: 1.14.4
chore: 1.14.3
fix: export lib
chore: 1.14.2
refactor: import
refactor: import
perf: 导入支持
2023-07-02 19:23:56 +00:00
GitHub Actions Bot
a8edaf4dfa 🔱: [client] sync upgrade with 2 commits [trident-sync]
perf: 导出重构
2023-07-01 19:23:57 +00:00
GitHub Actions Bot
e11b7802c2 🔱: [client] sync upgrade with 8 commits [trident-sync]
perf: export 功能
perf: export 功能
chore: 自定义组件onChange
perf: naiveui 自定义组件支持change validation
chore:
perf: 自定义组件支持触发validation
chore:
2023-06-30 19:24:21 +00:00
GitHub Actions Bot
aa0c5972fb 🔱: [client] sync upgrade with 6 commits [trident-sync]
chore:
perf: v-model editable-row示例
chore: mock tip
fix: 修复行编辑模式下,render、conditionalRender无效的bug
fix: 修复行编辑初始化无效的bug
2023-06-29 19:24:00 +00:00
GitHub Actions Bot
47cb00857c 🔱: [client] sync upgrade with 2 commits [trident-sync]
chore: 1.14.1
2023-06-16 19:24:07 +00:00
GitHub Actions Bot
7904e05b4a 🔱: [client] sync upgrade with 5 commits [trident-sync]
chore: 1.14.0
chore: 1
feat: crudBinding.value.table.columns由array改成map
chore: 1
2023-06-09 19:24:11 +00:00
GitHub Actions Bot
c4fe19f2e6 🔱: [client] sync upgrade with 3 commits [trident-sync]
chore: 1.13.12
chore: 1.13.11
2023-06-08 19:24:03 +00:00
GitHub Actions Bot
9db57f0517 🔱: [client] sync upgrade with 6 commits [trident-sync]
perf: search校验失败后,refresh保持原来的formData
perf(search): validation支持

https://github.com/fast-crud/fast-crud/issues/200
chore: 增加search render示例
chore: 增加search render示例
chore: jsx文档
2023-06-07 19:24:02 +00:00
GitHub Actions Bot
164b90a22f 🔱: [client] sync upgrade with 3 commits [trident-sync]
chore: jsx文档
chore: jsx文档
2023-06-06 19:24:01 +00:00
GitHub Actions Bot
dc735a8aa2 🔱: [client] sync upgrade with 4 commits [trident-sync]
chore: 1.13.10
chore: 1.13.9
fix: 恢复search插槽
2023-05-31 19:24:04 +00:00
GitHub Actions Bot
02466ea0bd 🔱: [client] sync upgrade with 3 commits [trident-sync]
chore: 一些小优化
chore: doc
2023-05-23 19:24:05 +00:00
GitHub Actions Bot
59f22ab17e 🔱: [client] sync upgrade with 3 commits [trident-sync]
chore: 1.13.8
perf(form): 支持conditionalRender
2023-05-22 19:23:55 +00:00
GitHub Actions Bot
2db9343e0f 🔱: [client] sync upgrade with 2 commits [trident-sync]
refactor: 1.13.7
2023-05-19 19:23:53 +00:00
GitHub Actions Bot
36b3a53ab2 🔱: [client] sync upgrade with 2 commits [trident-sync]
fix: 修复rowhandle 排列不整齐的问题
2023-05-17 19:24:06 +00:00
GitHub Actions Bot
dc8c42a820 🔱: [client] sync upgrade with 4 commits [trident-sync]
refactor:  修复login页面logo错位问题
refactor:  移除fs-bpmn
refactor:  publishConfig 恢复
2023-05-15 19:24:01 +00:00
GitHub Actions Bot
2bd5d0bd8e 🔱: [client] sync upgrade with 5 commits [trident-sync]
refactor: 1.13.6
refactor: proxy
refactor: 1.13.5
refactor: tabs remove 样式
2023-05-13 19:24:08 +00:00
GitHub Actions Bot
c9ac5ae963 🔱: [client] sync upgrade with 3 commits [trident-sync]
refactor: 1.13.4
perf: 服务端过滤示例
2023-05-06 19:24:02 +00:00
GitHub Actions Bot
49487419d2 🔱: [client] sync upgrade with 3 commits [trident-sync]
fix: 修复helloworld,添加记录无效的bug
fix: 1.13.3
2023-05-04 19:24:12 +00:00
GitHub Actions Bot
508fe69cf8 🔱: [client] sync upgrade with 3 commits [trident-sync]
docs: vModel支持trim、number doc
perf: vModel支持trim、number

https://github.com/fast-crud/fast-crud/issues/182
2023-04-28 19:24:08 +00:00
GitHub Actions Bot
3e4a8f230f 🔱: [client] sync upgrade with 4 commits [trident-sync]
refactor: 1.13.2
refactor: fs-bpmn 1.0.14
refactor: fs-bpmn 1.0.14
2023-04-20 19:24:50 +00:00
GitHub Actions Bot
a62230c195 🔱: [client] sync upgrade with 3 commits [trident-sync]
fix: _index列 被conditionalRender影响的bug
refactor:
2023-04-19 19:24:05 +00:00
GitHub Actions Bot
1173fb1e90 🔱: [client] sync upgrade with 3 commits [trident-sync]
Merge remote-tracking branch 'origin/main'
perf: 优化fs-images-format 加载失败时的显示
2023-04-18 19:24:09 +00:00
GitHub Actions Bot
529648a30c 🔱: [client] sync upgrade with 3 commits [trident-sync]
refactor: bpmn 1.0.10
refactor: bpmn 1.0.9
2023-04-17 19:26:40 +00:00
GitHub Actions Bot
82b6b9ccb2 🔱: [client] sync upgrade with 2 commits [trident-sync]
refactor: fs-bpmn 1.0.8
2023-04-15 19:23:59 +00:00
GitHub Actions Bot
71244a4eb8 🔱: [client] sync upgrade with 2 commits [trident-sync]
fix: 修复 文件上传accept问题
2023-04-12 19:24:06 +00:00
GitHub Actions Bot
32fd424295 🔱: [client] sync upgrade with 3 commits [trident-sync]
refactor: 1.13.1
refactor:
2023-04-10 19:23:56 +00:00
GitHub Actions Bot
5746042d68 🔱: [client] sync upgrade with 9 commits [trident-sync]
refactor: bpmn 1.0.6
Merge remote-tracking branch 'origin/main'
refactor: bpmn 1.0.6
Merge branch 'main' of https://github.com/fast-crud/fs-admin-antdv
perf: toolbar按钮显隐配置,保存按钮,对话框样式优化
refactor: 1.13.0
refactor: 1.13.0
feat: FsComponentRender组件重构

修复选择联动示例报错的bug
2023-04-07 19:23:58 +00:00
GitHub Actions Bot
e76fb235aa 🔱: [client] sync upgrade with 4 commits [trident-sync]
refactor: 1.12.2
refactor: card layout style
perf: 新增table.conditionalRender配置,条件渲染
2023-04-06 19:24:11 +00:00
GitHub Actions Bot
47e13312b1 🔱: [client] sync upgrade with 2 commits [trident-sync]
refactor: 1.12.1
2023-04-04 19:24:00 +00:00
GitHub Actions Bot
55e05afe0e 🔱: [client] sync upgrade with 8 commits [trident-sync]
perf: 增加自定义组件示例
Merge remote-tracking branch 'origin/main'
refactor: fs-bpmn
refactor: integration fs-bpmn
refactor: 集成fs-bpmn
refactor:
refactor: 优化i18n
2023-04-03 19:24:05 +00:00
GitHub Actions Bot
aebce2f241 🔱: [client] sync upgrade with 21 commits [trident-sync]
refactor: 1.12.0
refactor: 多行查询优化
perf: 优化多行查询示例
feat(search): search支持自定义布局

search支持自定义布局,search.layout、search.collapse转移到 search.container之下。如果想使用原来的search组件,请配置search.is=fs-search-v1
refactor: 1.11.10
fix: 修复列设置显隐和禁用无效的bug
refactor: 1.11.9
refactor: 1.11.9
perf: 增加表单字段render示例
refactor: 删除无用的index
Merge remote-tracking branch 'origin/main'
refactor: circle check
refactor: circle check
refactor: 1.11.8
refactor: upload demo test
perf: 优化dict性能
refactor: debug
fix: 修复当limit=1时,上传文件删光后,再选择文件上传第一次无效的bug

https://github.com/fast-crud/fast-crud/issues/166
refactor: 1.11.7
refactor: 1.11.6
...
2023-03-31 19:24:21 +00:00
GitHub Actions Bot
aa3207fca5 🔱: [client] sync upgrade with 2 commits [trident-sync]
feat(search): search支持自定义布局

BREAKING CHANGE: search支持自定义布局,search.layout、search.collapse转移到 search.container之下。如果想使用原来的search组件,请配置search.is=fs-search-v1
2023-03-30 19:23:57 +00:00
GitHub Actions Bot
ce8df34b49 🔱: [client] sync upgrade with 3 commits [trident-sync]
refactor: 1.11.10
fix: 修复列设置显隐和禁用无效的bug
2023-03-29 19:23:55 +00:00
GitHub Actions Bot
8aa8c5d8ae 🔱: [client] sync upgrade with 5 commits [trident-sync]
refactor: 1.11.9
refactor: 1.11.9
perf: 增加表单字段render示例
refactor: 删除无用的index
2023-03-28 19:24:02 +00:00
GitHub Actions Bot
e7628bdbdd 🔱: [client] sync upgrade with 8 commits [trident-sync]
Merge remote-tracking branch 'origin/main'
refactor: circle check
refactor: circle check
refactor: 1.11.8
refactor: upload demo test
perf: 优化dict性能
refactor: debug
2023-03-24 19:24:06 +00:00
GitHub Actions Bot
b9dd4a35db 🔱: [client] sync upgrade with 2 commits [trident-sync]
fix: 修复当limit=1时,上传文件删光后,再选择文件上传第一次无效的bug

https://github.com/fast-crud/fast-crud/issues/166
2023-03-23 19:24:01 +00:00
GitHub Actions Bot
040b2e8a53 🔱: [client] sync upgrade with 11 commits [trident-sync]
refactor: 1.11.7
refactor: 1.11.6
refactor: 1.11.5
refactor: ui interface
refactor: ui interface
refactor: ui interface
refactor: 1.11.4
fix: 多级表头列设置不显示bug
fix: tabs,修复连续触发两次查询的bug

https://github.com/fast-crud/fast-crud/issues/161
perf: 文本复制组件优化
2023-03-22 19:23:53 +00:00
GitHub Actions Bot
af25254628 🔱: [client] sync upgrade with 3 commits [trident-sync]
refactor: 1.11.3
refactor: 1.11.2
2023-03-21 19:24:02 +00:00
GitHub Actions Bot
0c673a54cd 🔱: [client] sync upgrade with 2 commits [trident-sync]
refactor: docs
2023-03-19 19:23:51 +00:00
GitHub Actions Bot
9f1f36774d 🔱: [client] sync upgrade with 5 commits [trident-sync]
refactor: 1
refactor: 1.11.1
refactor: 1.11.1
perf: useFs优化,增加context:UseFsContext
2023-03-17 19:23:57 +00:00
GitHub Actions Bot
6ec697b010 🔱: [client] sync upgrade with 12 commits [trident-sync]
refactor: 1.11.0
refactor: 1.11.0
refactor: 1.11.0
refactor: 1.11.0
refactor: ts化
refactor: ts化
feat: 全面TS化
perf: 全面ts化
refactor: 继续优化ts
perf: ts定义优化
fix: 修复wangeditor无法上传视频的bug
2023-03-16 19:24:01 +00:00
GitHub Actions Bot
f344c58f26 🔱: [client] sync upgrade with 4 commits [trident-sync]
perf: DynamicallyCrudOptions 动态CrudOptions
refactor: doc cover
refactor: doc cover
2023-03-13 19:24:02 +00:00
GitHub Actions Bot
263b0fa455 🔱: [client] sync upgrade with 6 commits [trident-sync]
Merge remote-tracking branch 'origin/main'
refactor: fsRefValue初步
refactor: deploy
Merge remote-tracking branch 'origin/main'
refactor: 1.10.0
2023-03-12 19:23:59 +00:00
GitHub Actions Bot
a634c8f2d1 🔱: [client] sync upgrade with 6 commits [trident-sync]
refactor: deploy
refactor: deploy
refactor: 1.10.0
refactor: 1
perf: 增加s3示例
2023-03-11 19:23:57 +00:00
GitHub Actions Bot
336faa46b2 🔱: [client] sync upgrade with 4 commits [trident-sync]
perf: upload sdk换成aws-s3
feat: upload 支持s3 minio

https://github.com/fast-crud/fast-crud/issues/149
feat: fs-form-wrapper支持多实例

https://github.com/fast-crud/fast-crud/issues/150
2023-03-10 19:24:05 +00:00
GitHub Actions Bot
52a167c647 🔱: [client] sync upgrade with 9 commits [trident-sync]
perf: 完善文档,完善部分types
perf: 优化d.ts类型
perf: 日期增加week、month、year、quarter类型
feat: resetCrudOptions 示例
feat: tabs快捷查询组件
fix: 行编辑支持多级表头

https://github.com/fast-crud/fast-crud/issues/143
perf: antdv 增加自定义表头示例

https://github.com/fast-crud/fast-crud/issues/141
perf: 表单下方按钮支持context

https://github.com/fast-crud/fast-crud/issues/142
2023-03-09 19:24:01 +00:00
1232 changed files with 54373 additions and 7794 deletions

View File

@@ -0,0 +1,463 @@
/** @type {import('dependency-cruiser').IConfiguration} */
module.exports = {
forbidden: [
/* rules from the 'recommended' preset: */
{
name: 'no-circular',
severity: 'warn',
comment:
'This dependency is part of a circular relationship. You might want to revise ' +
'your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ',
from: {},
to: {
circular: true
}
},
{
name: 'no-orphans',
comment:
"This is an orphan module - it's likely not used (anymore?). Either use it or " +
"remove it. If it's logical this module is an orphan (i.e. it's a config file), " +
"add an exception for it in your dependency-cruiser configuration. By default " +
"this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration " +
"files (.d.ts), tsconfig.json and some of the babel and webpack configs.",
severity: 'warn',
from: {
orphan: true,
pathNot: [
'(^|/)\\.[^/]+\\.(js|cjs|mjs|ts|json)$', // dot files
'\\.d\\.ts$', // TypeScript declaration files
'(^|/)tsconfig\\.json$', // TypeScript config
'(^|/)(babel|webpack)\\.config\\.(js|cjs|mjs|ts|json)$' // other configs
]
},
to: {},
},
{
name: 'no-deprecated-core',
comment:
'A module depends on a node core module that has been deprecated. Find an alternative - these are ' +
"bound to exist - node doesn't deprecate lightly.",
severity: 'warn',
from: {},
to: {
dependencyTypes: [
'core'
],
path: [
'^(v8\/tools\/codemap)$',
'^(v8\/tools\/consarray)$',
'^(v8\/tools\/csvparser)$',
'^(v8\/tools\/logreader)$',
'^(v8\/tools\/profile_view)$',
'^(v8\/tools\/profile)$',
'^(v8\/tools\/SourceMap)$',
'^(v8\/tools\/splaytree)$',
'^(v8\/tools\/tickprocessor-driver)$',
'^(v8\/tools\/tickprocessor)$',
'^(node-inspect\/lib\/_inspect)$',
'^(node-inspect\/lib\/internal\/inspect_client)$',
'^(node-inspect\/lib\/internal\/inspect_repl)$',
'^(async_hooks)$',
'^(punycode)$',
'^(domain)$',
'^(constants)$',
'^(sys)$',
'^(_linklist)$',
'^(_stream_wrap)$'
],
}
},
{
name: 'not-to-deprecated',
comment:
'This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later ' +
'version of that module, or find an alternative. Deprecated modules are a security risk.',
severity: 'warn',
from: {},
to: {
dependencyTypes: [
'deprecated'
]
}
},
{
name: 'no-non-package-json',
severity: 'error',
comment:
"This module depends on an npm package that isn't in the 'dependencies' section of your package.json. " +
"That's problematic as the package either (1) won't be available on live (2 - worse) will be " +
"available on live with an non-guaranteed version. Fix it by adding the package to the dependencies " +
"in your package.json.",
from: {},
to: {
dependencyTypes: [
'npm-no-pkg',
'npm-unknown'
]
}
},
{
name: 'not-to-unresolvable',
comment:
"This module depends on a module that cannot be found ('resolved to disk'). If it's an npm " +
'module: add it to your package.json. In all other cases you likely already know what to do.',
severity: 'error',
from: {},
to: {
couldNotResolve: true
}
},
{
name: 'no-duplicate-dep-types',
comment:
"Likely this module depends on an external ('npm') package that occurs more than once " +
"in your package.json i.e. bot as a devDependencies and in dependencies. This will cause " +
"maintenance problems later on.",
severity: 'warn',
from: {},
to: {
moreThanOneDependencyType: true,
// as it's pretty common to have a type import be a type only import
// _and_ (e.g.) a devDependency - don't consider type-only dependency
// types for this rule
dependencyTypesNot: ["type-only"]
}
},
/* rules you might want to tweak for your specific situation: */
{
name: 'not-to-test',
comment:
"This module depends on code within a folder that should only contain tests. As tests don't " +
"implement functionality this is odd. Either you're writing a test outside the test folder " +
"or there's something in the test folder that isn't a test.",
severity: 'error',
from: {
pathNot: '^(tests)'
},
to: {
path: '^(tests)'
}
},
{
name: 'not-to-spec',
comment:
'This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. ' +
"If there's something in a spec that's of use to other modules, it doesn't have that single " +
'responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.',
severity: 'error',
from: {},
to: {
path: '\\.(spec|test)\\.(js|mjs|cjs|ts|ls|coffee|litcoffee|coffee\\.md)$'
}
},
{
name: 'not-to-dev-dep',
severity: 'error',
comment:
"This module depends on an npm package from the 'devDependencies' section of your " +
'package.json. It looks like something that ships to production, though. To prevent problems ' +
"with npm packages that aren't there on production declare it (only!) in the 'dependencies'" +
'section of your package.json. If this module is development only - add it to the ' +
'from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration',
from: {
path: '^(src)',
pathNot: '\\.(spec|test)\\.(js|mjs|cjs|ts|ls|coffee|litcoffee|coffee\\.md)$'
},
to: {
dependencyTypes: [
'npm-dev'
]
}
},
{
name: 'optional-deps-used',
severity: 'info',
comment:
"This module depends on an npm package that is declared as an optional dependency " +
"in your package.json. As this makes sense in limited situations only, it's flagged here. " +
"If you're using an optional dependency here by design - add an exception to your" +
"dependency-cruiser configuration.",
from: {},
to: {
dependencyTypes: [
'npm-optional'
]
}
},
{
name: 'peer-deps-used',
comment:
"This module depends on an npm package that is declared as a peer dependency " +
"in your package.json. This makes sense if your package is e.g. a plugin, but in " +
"other cases - maybe not so much. If the use of a peer dependency is intentional " +
"add an exception to your dependency-cruiser configuration.",
severity: 'warn',
from: {},
to: {
dependencyTypes: [
'npm-peer'
]
}
}
],
options: {
/* conditions specifying which files not to follow further when encountered:
- path: a regular expression to match
- dependencyTypes: see https://github.com/sverweij/dependency-cruiser/blob/master/doc/rules-reference.md#dependencytypes-and-dependencytypesnot
for a complete list
*/
doNotFollow: {
path: 'node_modules'
},
/* conditions specifying which dependencies to exclude
- path: a regular expression to match
- dynamic: a boolean indicating whether to ignore dynamic (true) or static (false) dependencies.
leave out if you want to exclude neither (recommended!)
*/
// exclude : {
// path: '',
// dynamic: true
// },
/* pattern specifying which files to include (regular expression)
dependency-cruiser will skip everything not matching this pattern
*/
// includeOnly : '',
/* dependency-cruiser will include modules matching against the focus
regular expression in its output, as well as their neighbours (direct
dependencies and dependents)
*/
// focus : '',
/* list of module systems to cruise */
// moduleSystems: ['amd', 'cjs', 'es6', 'tsd'],
/* prefix for links in html and svg output (e.g. 'https://github.com/you/yourrepo/blob/develop/'
to open it on your online repo or `vscode://file/${process.cwd()}/` to
open it in visual studio code),
*/
// prefix: '',
/* false (the default): ignore dependencies that only exist before typescript-to-javascript compilation
true: also detect dependencies that only exist before typescript-to-javascript compilation
"specify": for each dependency identify whether it only exists before compilation or also after
*/
tsPreCompilationDeps: true,
/*
list of extensions to scan that aren't javascript or compile-to-javascript.
Empty by default. Only put extensions in here that you want to take into
account that are _not_ parsable.
*/
// extraExtensionsToScan: [".json", ".jpg", ".png", ".svg", ".webp"],
/* if true combines the package.jsons found from the module up to the base
folder the cruise is initiated from. Useful for how (some) mono-repos
manage dependencies & dependency definitions.
*/
// combinedDependencies: false,
/* if true leave symlinks untouched, otherwise use the realpath */
// preserveSymlinks: false,
/* TypeScript project file ('tsconfig.json') to use for
(1) compilation and
(2) resolution (e.g. with the paths property)
The (optional) fileName attribute specifies which file to take (relative to
dependency-cruiser's current working directory). When not provided
defaults to './tsconfig.json'.
*/
tsConfig: {
fileName: 'tsconfig.json'
},
/* Webpack configuration to use to get resolve options from.
The (optional) fileName attribute specifies which file to take (relative
to dependency-cruiser's current working directory. When not provided defaults
to './webpack.conf.js'.
The (optional) `env` and `args` attributes contain the parameters to be passed if
your webpack config is a function and takes them (see webpack documentation
for details)
*/
// webpackConfig: {
// fileName: './webpack.config.js',
// env: {},
// args: {},
// },
/* Babel config ('.babelrc', '.babelrc.json', '.babelrc.json5', ...) to use
for compilation (and whatever other naughty things babel plugins do to
source code). This feature is well tested and usable, but might change
behavior a bit over time (e.g. more precise results for used module
systems) without dependency-cruiser getting a major version bump.
*/
// babelConfig: {
// fileName: './.babelrc'
// },
/* List of strings you have in use in addition to cjs/ es6 requires
& imports to declare module dependencies. Use this e.g. if you've
re-declared require, use a require-wrapper or use window.require as
a hack.
*/
// exoticRequireStrings: [],
/* options to pass on to enhanced-resolve, the package dependency-cruiser
uses to resolve module references to disk. You can set most of these
options in a webpack.conf.js - this section is here for those
projects that don't have a separate webpack config file.
Note: settings in webpack.conf.js override the ones specified here.
*/
enhancedResolveOptions: {
/* List of strings to consider as 'exports' fields in package.json. Use
['exports'] when you use packages that use such a field and your environment
supports it (e.g. node ^12.19 || >=14.7 or recent versions of webpack).
If you have an `exportsFields` attribute in your webpack config, that one
will have precedence over the one specified here.
*/
exportsFields: ["exports"],
/* List of conditions to check for in the exports field. e.g. use ['imports']
if you're only interested in exposed es6 modules, ['require'] for commonjs,
or all conditions at once `(['import', 'require', 'node', 'default']`)
if anything goes for you. Only works when the 'exportsFields' array is
non-empty.
If you have a 'conditionNames' attribute in your webpack config, that one will
have precedence over the one specified here.
*/
conditionNames: ["import", "require", "node", "default"],
/*
The extensions, by default are the same as the ones dependency-cruiser
can access (run `npx depcruise --info` to see which ones that are in
_your_ environment. If that list is larger than what you need (e.g.
it contains .js, .jsx, .ts, .tsx, .cts, .mts - but you don't use
TypeScript you can pass just the extensions you actually use (e.g.
[".js", ".jsx"]). This can speed up the most expensive step in
dependency cruising (module resolution) quite a bit.
*/
// extensions: [".js", ".jsx", ".ts", ".tsx", ".d.ts"],
/*
If your TypeScript project makes use of types specified in 'types'
fields in package.jsons of external dependencies, specify "types"
in addition to "main" in here, so enhanced-resolve (the resolver
dependency-cruiser uses) knows to also look there. You can also do
this if you're not sure, but still use TypeScript. In a future version
of dependency-cruiser this will likely become the default.
*/
mainFields: ["main", "types"],
},
reporterOptions: {
dot: {
/* pattern of modules that can be consolidated in the detailed
graphical dependency graph. The default pattern in this configuration
collapses everything in node_modules to one folder deep so you see
the external modules, but not the innards your app depends upon.
*/
collapsePattern: 'node_modules/(@[^/]+/[^/]+|[^/]+)',
/* Options to tweak the appearance of your graph.See
https://github.com/sverweij/dependency-cruiser/blob/master/doc/options-reference.md#reporteroptions
for details and some examples. If you don't specify a theme
don't worry - dependency-cruiser will fall back to the default one.
*/
// theme: {
// graph: {
// /* use splines: "ortho" for straight lines. Be aware though
// graphviz might take a long time calculating ortho(gonal)
// routings.
// */
// splines: "true"
// },
// modules: [
// {
// criteria: { matchesFocus: true },
// attributes: {
// fillcolor: "lime",
// penwidth: 2,
// },
// },
// {
// criteria: { matchesFocus: false },
// attributes: {
// fillcolor: "lightgrey",
// },
// },
// {
// criteria: { matchesReaches: true },
// attributes: {
// fillcolor: "lime",
// penwidth: 2,
// },
// },
// {
// criteria: { matchesReaches: false },
// attributes: {
// fillcolor: "lightgrey",
// },
// },
// {
// criteria: { source: "^src/model" },
// attributes: { fillcolor: "#ccccff" }
// },
// {
// criteria: { source: "^src/view" },
// attributes: { fillcolor: "#ccffcc" }
// },
// ],
// dependencies: [
// {
// criteria: { "rules[0].severity": "error" },
// attributes: { fontcolor: "red", color: "red" }
// },
// {
// criteria: { "rules[0].severity": "warn" },
// attributes: { fontcolor: "orange", color: "orange" }
// },
// {
// criteria: { "rules[0].severity": "info" },
// attributes: { fontcolor: "blue", color: "blue" }
// },
// {
// criteria: { resolved: "^src/model" },
// attributes: { color: "#0000ff77" }
// },
// {
// criteria: { resolved: "^src/view" },
// attributes: { color: "#00770077" }
// }
// ]
// }
},
archi: {
/* pattern of modules that can be consolidated in the high level
graphical dependency graph. If you use the high level graphical
dependency graph reporter (`archi`) you probably want to tweak
this collapsePattern to your situation.
*/
collapsePattern: '^(packages|src|lib|app|bin|test(s?)|spec(s?))/[^/]+|node_modules/(@[^/]+/[^/]+|[^/]+)',
/* Options to tweak the appearance of your graph.See
https://github.com/sverweij/dependency-cruiser/blob/master/doc/options-reference.md#reporteroptions
for details and some examples. If you don't specify a theme
for 'archi' dependency-cruiser will use the one specified in the
dot section (see above), if any, and otherwise use the default one.
*/
// theme: {
// },
},
"text": {
"highlightFocused": true
},
}
}
};
// generated: dependency-cruiser@12.11.0 on 2023-03-24T14:11:38.647Z

View File

@@ -1,3 +1,9 @@
VITE_APP_API=/api
#登录与权限关闭
VITE_APP_PM_ENABLED=true
VITE_APP_PM_ENABLED=false
VITE_APP_TITLE=fs-admin-antdv4
VITE_APP_SLOGAN=面向配置的CRUD开发快如闪电
VITE_APP_COPYRIGHT=Copyright © 2021 Greper
VITE_APP_LOGO_PATH=./images/logo/logo.svg
VITE_APP_PROJECT_PATH=https://github.com/fast-crud/fast-crud
VITE_APP_NAMESPACE=fs

View File

@@ -16,14 +16,11 @@ module.exports = {
tsx: true
}
},
extends: [
"plugin:vue/vue3-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
"prettier"
],
extends: ["plugin:vue/vue3-recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended", "prettier"],
rules: {
//"max-len": [0, 200, 2, { ignoreUrls: true }],
"@typescript-eslint/no-unused-vars": "off",
"no-unused-vars": "off",
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "off",

View File

@@ -30,6 +30,8 @@ jobs:
- name: push to gitee # 4. 执行同步
run: |
git remote add upstream https://gitee.com/fast-crud/fs-admin-antdv
git remote add upstream https://gitee.com/fast-crud/fs-admin-antdv4
git push --set-upstream upstream main

View File

@@ -0,0 +1,2 @@
link-workspace-packages=deep
prefer-workspace-packages=true

View File

@@ -3,27 +3,687 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.9.2](https://github.com/fast-crud/fast-crud/compare/v1.9.1...v1.9.2) (2023-03-01)
# [1.26.0](https://github.com/fast-crud/fast-crud/compare/v1.25.13...v1.26.0) (2025-07-28)
### Bug Fixes
* 独立使用form表单缺失mode的问题 ([9ed791a](https://github.com/fast-crud/fast-crud/commit/9ed791ad4bb9294f4b9380d858df89fbc32ca2a0))
* 修复table-select 示例右上角自定义插槽无法设置的bug ([54a5d90](https://github.com/fast-crud/fast-crud/commit/54a5d90b86338036474657267de3bd7a74caf1eb))
* card布局情况下header-top header-bottom同时跟search显隐的bug ([3484232](https://github.com/fast-crud/fast-crud/commit/348423280f06f052fb16214e863ba03735ff9042))
### Performance Improvements
* antdv示例背景设置为白色 ([3d74bf4](https://github.com/fast-crud/fast-crud/commit/3d74bf4e7ca76ecad286ec8f1b8fd2cbcb6428eb))
## [1.25.13](https://github.com/fast-crud/fast-crud/compare/v1.25.12...v1.25.13) (2025-06-10)
### Bug Fixes
* 修复fs-values-format组件某些值无法获取自动颜色的bug ([18169fc](https://github.com/fast-crud/fast-crud/commit/18169fc11f37595b8fba96467f0c741fe898ad21))
## [1.25.12](https://github.com/fast-crud/fast-crud/compare/v1.25.11...v1.25.12) (2025-05-26)
### Bug Fixes
* 修复cloneable模式下的dict 无法动态修改data的bug ([1dd5cd1](https://github.com/fast-crud/fast-crud/commit/1dd5cd1e1445b126451c6e1b68f453a70bf920de))
## [1.25.11](https://github.com/fast-crud/fast-crud/compare/v1.25.10...v1.25.11) (2025-05-14)
### Bug Fixes
* 修复naive-ui下 form-item 的label设置为render会报警告的问题 ([45e1bc6](https://github.com/fast-crud/fast-crud/commit/45e1bc6d9cfc408a98dfe628bf3b9bd14af4b2cf))
### Performance Improvements
* 单元格支持tooltip ([44d83ad](https://github.com/fast-crud/fast-crud/commit/44d83ad890589b2b64ff5e9f869fc04863576a3b))
## [1.25.10](https://github.com/fast-crud/fast-crud/compare/v1.25.9...v1.25.10) (2025-04-25)
### Performance Improvements
* 新增editable-select组件 ([8681285](https://github.com/fast-crud/fast-crud/commit/86812851de435cb2406d06898396c368d5eda414))
* 优化antdv单元格合并示例使用customCell方法以及增加操作列合并演示 ([1068f9a](https://github.com/fast-crud/fast-crud/commit/1068f9aaa9b7732acb7082cc2ce3b1fadf1f8521))
## [1.25.9](https://github.com/fast-crud/fast-crud/compare/v1.25.8...v1.25.9) (2025-04-16)
### Bug Fixes
* 修复预览大图previewurl错误的bug ([cfb6554](https://github.com/fast-crud/fast-crud/commit/cfb6554c7c93297ddfcaa206168aceaf4ba2c2ef))
* 修复yaml workers引入问题 ([1c90198](https://github.com/fast-crud/fast-crud/commit/1c90198f6f7df0ac0c9845d1c6af0592b1c34ae3))
## [1.25.8](https://github.com/fast-crud/fast-crud/compare/v1.25.7...v1.25.8) (2025-04-10)
### Bug Fixes
* 修复commonOptions无法覆盖某些参数的bug ([f2ecc03](https://github.com/fast-crud/fast-crud/commit/f2ecc034bf5b38d668ee8366c903a824af34302c))
* fs-editor-code 支持配置schema校验 ([7d342cb](https://github.com/fast-crud/fast-crud/commit/7d342cbe8ebbaebb6ff5b3b80ce977d87aaa9ba5))
### Performance Improvements
* 添加代码编辑器示例 ([7217460](https://github.com/fast-crud/fast-crud/commit/72174604735b90fc57e0fb1ce40cc380b6c0c351))
## [1.25.7](https://github.com/fast-crud/fast-crud/compare/v1.25.6...v1.25.7) (2025-03-30)
### Bug Fixes
* 修复新页面编辑无法正确获取数据的bug ([e0df772](https://github.com/fast-crud/fast-crud/commit/e0df7729d0d8fff7a0bcd81477ec9379f6f23369))
* 修复antdv4示例没有源码跳转按钮的bug ([a8f6486](https://github.com/fast-crud/fast-crud/commit/a8f6486bccc441bb394ae5fb8bbe515de78f83d3))
## [1.25.6](https://github.com/fast-crud/fast-crud/compare/v1.25.5...v1.25.6) (2025-03-19)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.25.5](https://github.com/fast-crud/fast-crud/compare/v1.25.4...v1.25.5) (2025-03-19)
### Bug Fixes
* 修复 antdv 弹出菜单边框过大的问题 ([fe4a044](https://github.com/fast-crud/fast-crud/commit/fe4a0442bf8fcdc3120b6de788ff318933b6bfab))
* 修复 antdv懒加载后dropdown按钮无法点击的bug ([30ee067](https://github.com/fast-crud/fast-crud/commit/30ee067580fb663bbe550d50abf63c1fd89504a1))
### Performance Improvements
* antdv示例增加保存列宽功能 ([a1218b0](https://github.com/fast-crud/fast-crud/commit/a1218b0451eb73fae8e337128e79b6e1fd4184eb))
## [1.25.4](https://github.com/fast-crud/fast-crud/compare/v1.25.3...v1.25.4) (2025-03-04)
### Performance Improvements
* 精简lodash ([21f59e8](https://github.com/fast-crud/fast-crud/commit/21f59e80db56cf0968b2739b9bc7ff1e8b7be4e4))
* antdv 异步加载,加快首页打开速度 ([4eb4283](https://github.com/fast-crud/fast-crud/commit/4eb4283ad66e856814962ca2bde416dddbac0868))
## [1.25.3](https://github.com/fast-crud/fast-crud/compare/v1.25.2...v1.25.3) (2025-02-23)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.25.2](https://github.com/fast-crud/fast-crud/compare/v1.25.1...v1.25.2) (2025-02-22)
### Bug Fixes
* 修复4.2.x版本antdv导致modal全屏无效的bug ([9a26363](https://github.com/fast-crud/fast-crud/commit/9a26363d44faf6b0eb0809be4a8dd0fd14f2c309))
## [1.25.1](https://github.com/fast-crud/fast-crud/compare/v1.25.0...v1.25.1) (2025-02-12)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
# [1.25.0](https://github.com/fast-crud/fast-crud/compare/v1.24.2...v1.25.0) (2025-01-12)
### Performance Improvements
* 支持图标选择器 ([7dd8745](https://github.com/fast-crud/fast-crud/commit/7dd874534caa926ba63d6b8100116c032d794d51))
## [1.24.2](https://github.com/fast-crud/fast-crud/compare/v1.24.1...v1.24.2) (2024-12-31)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.24.1](https://github.com/fast-crud/fast-crud/compare/v1.24.0...v1.24.1) (2024-12-28)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
# [1.24.0](https://github.com/fast-crud/fast-crud/compare/v1.23.4...v1.24.0) (2024-12-28)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.23.4](https://github.com/fast-crud/fast-crud/compare/v1.23.3...v1.23.4) (2024-12-03)
### Bug Fixes
* 修复表单全屏的bug ([a25cff7](https://github.com/fast-crud/fast-crud/commit/a25cff725bef9d0dac063f7bd653844231c57b8d))
### Performance Improvements
* rowHandle按钮支持render删除按钮提供popcomfirm风格示例 ([b834db9](https://github.com/fast-crud/fast-crud/commit/b834db96e46e6b281d5c3a178a57c71aadf9bfd0))
* table-select open支持context参数 ([492ee98](https://github.com/fast-crud/fast-crud/commit/492ee9862eee80ffcef81f42178a33484102213a))
## [1.23.3](https://github.com/fast-crud/fast-crud/compare/v1.23.2...v1.23.3) (2024-11-26)
### Bug Fixes
* 修复antdv4新页面打开示例不显示表单的bug ([34ab106](https://github.com/fast-crud/fast-crud/commit/34ab106d5e1cce918ce9745df141fda03f69331d))
### Performance Improvements
* 增加card列表示例 ([cfad8c8](https://github.com/fast-crud/fast-crud/commit/cfad8c87cb6f9588bb016c0595d03b34b0147c2a))
## [1.23.2](https://github.com/fast-crud/fast-crud/compare/v1.23.1...v1.23.2) (2024-11-18)
### Bug Fixes
* 修复dict-select多选情况下selected-change返回为空的bug ([181b167](https://github.com/fast-crud/fast-crud/commit/181b167d29536ffd8cd476e4744e322c5542b991))
## [1.23.1](https://github.com/fast-crud/fast-crud/compare/v1.23.0...v1.23.1) (2024-11-13)
### Bug Fixes
* 修复1.23.0 antdv下不显示pagination的bug ([9424dc1](https://github.com/fast-crud/fast-crud/commit/9424dc130505a5557042534acb976400b42ff483))
# [1.23.0](https://github.com/fast-crud/fast-crud/compare/v1.22.5...v1.23.0) (2024-11-11)
### Features
* 示例全面改成useFsAsync ([aa848a9](https://github.com/fast-crud/fast-crud/commit/aa848a9530af831247077620fa3ee0f605c19009))
### Performance Improvements
* 示例改成useFsAsync ([f7fac52](https://github.com/fast-crud/fast-crud/commit/f7fac52fcfaa4703bfebd8259007b235401b8357))
## [1.22.5](https://github.com/fast-crud/fast-crud/compare/v1.22.4...v1.22.5) (2024-11-04)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.22.4](https://github.com/fast-crud/fast-crud/compare/v1.22.3...v1.22.4) (2024-11-04)
### Bug Fixes
* 修复tab change后清空查询表单的bug ([8d7525a](https://github.com/fast-crud/fast-crud/commit/8d7525a747c41fe3fb1f14b92d0e353440ebc8ad))
## [1.22.3](https://github.com/fast-crud/fast-crud/compare/v1.22.2...v1.22.3) (2024-11-01)
### Bug Fixes
* 修复search.formItem配置无效的bug ([e112f03](https://github.com/fast-crud/fast-crud/commit/e112f033a60e142eced129e03b7c3cb96605b3fb))
### Performance Improvements
* editable row 优化添加 ([9e0beb0](https://github.com/fast-crud/fast-crud/commit/9e0beb06470b564d490ec9393afe978f8a66c2fd))
## [1.22.2](https://github.com/fast-crud/fast-crud/compare/v1.22.1...v1.22.2) (2024-10-24)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.22.1](https://github.com/fast-crud/fast-crud/compare/v1.22.0...v1.22.1) (2024-10-23)
### Performance Improvements
* 表单支持左右插槽 ([e3a9e8b](https://github.com/fast-crud/fast-crud/commit/e3a9e8b985558f7cbff0acd580af242df56da8c4))
* 独立使用表单支持插槽 ([095da7a](https://github.com/fast-crud/fast-crud/commit/095da7ac92996779f3b3c3885a8abd4de6c2fc0c))
* editable支持单元格插槽 ([ae029de](https://github.com/fast-crud/fast-crud/commit/ae029de0f554f4cc4c4750e0af3b6f7bd1edaee5))
* values-format option支持iconSpin ([cdaa4f5](https://github.com/fast-crud/fast-crud/commit/cdaa4f55a9384b95764443b4a7f4223ec787cce3))
# [1.22.0](https://github.com/fast-crud/fast-crud/compare/v1.21.5...v1.22.0) (2024-10-21)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.21.5](https://github.com/fast-crud/fast-crud/compare/v1.21.4...v1.21.5) (2024-10-21)
### Performance Improvements
* 列设置支持自定义storage ([298fb2f](https://github.com/fast-crud/fast-crud/commit/298fb2f9f2fff559567bedf6e977e7cb04024cdd))
## [1.21.4](https://github.com/fast-crud/fast-crud/compare/v1.21.3...v1.21.4) (2024-10-13)
### Performance Improvements
* 优化列设置多级表头支持级联勾选 ([a196922](https://github.com/fast-crud/fast-crud/commit/a196922630e9ef627dd548bb8d1c13acbe2eee28))
* table-select支持destroyOnClose参数以修复点击取消后扔保留上一次选中值的bug ([5a70cec](https://github.com/fast-crud/fast-crud/commit/5a70cec7e5f45439a518fc2aadc40b29fad5c6f1))
## [1.21.3](https://github.com/fast-crud/fast-crud/compare/v1.21.2...v1.21.3) (2024-09-20)
### Performance Improvements
* 优化antdv search按钮组错位问题 ([0948650](https://github.com/fast-crud/fast-crud/commit/0948650747d725ffe84e4f357d81a3a9a331109e))
## [1.21.2](https://github.com/fast-crud/fast-crud/compare/v1.21.1...v1.21.2) (2024-07-15)
### Performance Improvements
* 增加示例FsInDrawer ([777830f](https://github.com/fast-crud/fast-crud/commit/777830f860b6a9752ba24df5a99af5e7c62bdfb2))
## [1.21.1](https://github.com/fast-crud/fast-crud/compare/v1.21.0...v1.21.1) (2024-06-23)
### Bug Fixes
* 修复独立使用对话框 openDialog方法await无返回值的bug ([0cc22fd](https://github.com/fast-crud/fast-crud/commit/0cc22fd2ad57b8e3e85174ced1546bb6a90ed838))
# [1.21.0](https://github.com/fast-crud/fast-crud/compare/v1.20.2...v1.21.0) (2024-06-08)
### Bug Fixes
* 修复三级以上路由页面无法缓存的问题 ([9ce8c7a](https://github.com/fast-crud/fast-crud/commit/9ce8c7a6a5fc12f347351ca74213ff9c542820d3))
* 修复提交表单只有一个输入框时点回车会刷新浏览器的问题 ([3d756ea](https://github.com/fast-crud/fast-crud/commit/3d756eaab6894355053e078424835d3edbd80025))
* 修复fs-table.less中的颜色污染 ([a0b1de4](https://github.com/fast-crud/fast-crud/commit/a0b1de45668f882e13669c5aee484d3d2532ce25))
* edit-wang 改成edit-wang5 ([7b994c1](https://github.com/fast-crud/fast-crud/commit/7b994c19637aa4b6399acbf362d4dc6a73c07ca4))
### Performance Improvements
* 富文本编辑器增加为空校验示例 ([3e51ac1](https://github.com/fast-crud/fast-crud/commit/3e51ac1c2c22f2dc5200134732fc0146a4a0fd2d))
* 图片裁剪组件中英文支持 ([8b5b3f6](https://github.com/fast-crud/fast-crud/commit/8b5b3f61bc67e17ed13ded4a5519434249d5c4df))
* alioss getAuthorization接口支持后台返回key ([75e5b14](https://github.com/fast-crud/fast-crud/commit/75e5b1449238fbae86f002c290771a6b9fd1f824))
## [1.20.2](https://github.com/fast-crud/fast-crud/compare/v1.20.1...v1.20.2) (2024-03-21)
### Bug Fixes
* 修复单元格valueChange 的value 改变滞后的问题 ([768c233](https://github.com/fast-crud/fast-crud/commit/768c233c915dc4277f3fb49106bf99f0bd1fb31c))
### Performance Improvements
* 升级依赖版本 ([42ae562](https://github.com/fast-crud/fast-crud/commit/42ae56289cc9d80ee1b3c1f9b7b2dd4656e9ba84))
* table-select element增加radio列 ([b56b5df](https://github.com/fast-crud/fast-crud/commit/b56b5df79c6ce634bdac0545e83629f6f5587d42))
## [1.20.1](https://github.com/fast-crud/fast-crud/compare/v1.20.0...v1.20.1) (2024-02-27)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
# [1.20.0](https://github.com/fast-crud/fast-crud/compare/v1.19.3...v1.20.0) (2024-01-28)
### Bug Fixes
* 修复查询valueChange 修改form无效的bug ([054f8b4](https://github.com/fast-crud/fast-crud/commit/054f8b4b808a52f6d8daf2d19ee3adf43f693c0a))
### Performance Improvements
* 优化element 日期示例格式化问题输入数据格式告警问题range样式问题 ([66fd07b](https://github.com/fast-crud/fast-crud/commit/66fd07b96143b77ed73b5e3b88182070ebdb4c80))
* 优化form.wrapper.buttons的默认配置 ([61f2ae5](https://github.com/fast-crud/fast-crud/commit/61f2ae5600814a59e2eaad8933892c1ec9f57c69))
* 优化free模式支持默认不激活 ([aeaf0a6](https://github.com/fast-crud/fast-crud/commit/aeaf0a683ecc24dcb86036daea363f3019347299))
* dict-tree组件无需手动配置labelName keyName ([c8b0ee1](https://github.com/fast-crud/fast-crud/commit/c8b0ee1ee5fa22e73b3a8ef77e1ad3335351dc70))
## [1.19.3](https://github.com/fast-crud/fast-crud/compare/v1.19.2...v1.19.3) (2023-12-15)
### Bug Fixes
* antdv4 日期组件bug修复 ([a55b3e2](https://github.com/fast-crud/fast-crud/commit/a55b3e293a94396bbdfbd7d6dabb19d886cb8e16))
### Performance Improvements
* 增加表单label=0px示例 ([500d793](https://github.com/fast-crud/fast-crud/commit/500d793d72d727e8945cf7bca47aee684856bd80))
## [1.19.2](https://github.com/fast-crud/fast-crud/compare/v1.19.1...v1.19.2) (2023-11-22)
### Bug Fixes
* **editable:** 行编辑只能删除第一条数据的bug ([daf041f](https://github.com/fast-crud/fast-crud/commit/daf041f21cf531b4e32655248e522c96dd06f460))
## [1.19.1](https://github.com/fast-crud/fast-crud/compare/v1.19.0...v1.19.1) (2023-11-20)
### Bug Fixes
* 修复一些错误的类型定义 ([e098f51](https://github.com/fast-crud/fast-crud/commit/e098f511160148a824a1950bf4e85325c2ac50f0))
# [1.19.0](https://github.com/fast-crud/fast-crud/compare/v1.18.5...v1.19.0) (2023-11-20)
### Bug Fixes
* **editable:** 支持多级数据 ([89db59e](https://github.com/fast-crud/fast-crud/commit/89db59ea2b3dbe8227399086513e27aa7c2ab7aa))
## [1.18.5](https://github.com/fast-crud/fast-crud/compare/v1.18.4...v1.18.5) (2023-11-08)
### Bug Fixes
* 修复form.value会覆盖初始值的bug ([050f889](https://github.com/fast-crud/fast-crud/commit/050f889dfbdfb38debcd7c8e4a455acf07198530))
## [1.18.4](https://github.com/fast-crud/fast-crud/compare/v1.18.3...v1.18.4) (2023-11-07)
### Bug Fixes
* 修复afterSubmit返回false仍然关闭对话框的bug ([80337ff](https://github.com/fast-crud/fast-crud/commit/80337ffc46eda74d526562d9f27c43a2b6eb0534))
### Performance Improvements
* 新增国际手机号输入框 ([ebabee2](https://github.com/fast-crud/fast-crud/commit/ebabee2f61caed3678f0681330ed3cb044803a2f))
* antdv 支持按钮组 ([cfdefdf](https://github.com/fast-crud/fast-crud/commit/cfdefdf89bfe7e037d1a8d3c6416cf38678074c9))
## [1.18.3](https://github.com/fast-crud/fast-crud/compare/v1.18.2...v1.18.3) (2023-10-26)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.18.2](https://github.com/fast-crud/fast-crud/compare/v1.18.1...v1.18.2) (2023-10-26)
### Bug Fixes
* 导出配置columns报错的bug ([d12f881](https://github.com/fast-crud/fast-crud/commit/d12f881f83e8c521673dc49d656e457a4fc67102))
* 修复动态切换component.name报 resolveComponent 只能在setup和render中使用的问题 ([8792962](https://github.com/fast-crud/fast-crud/commit/8792962156346dbf05445d8f143b23296d60c781))
## [1.18.1](https://github.com/fast-crud/fast-crud/compare/v1.18.0...v1.18.1) (2023-10-26)
### Bug Fixes
* 取消 searchCopyFormProps valueResolve配置 ([ae55fda](https://github.com/fast-crud/fast-crud/commit/ae55fda1f9aa206d644f2e3da654201f0831f0be))
# [1.18.0](https://github.com/fast-crud/fast-crud/compare/v1.17.5...v1.18.0) (2023-10-25)
### Bug Fixes
* 修复antdv4drawer弹窗过时的api ([9514db6](https://github.com/fast-crud/fast-crud/commit/9514db6768b5a5e1bef283b961438a6671f7df79))
* 修复element下按钮图标异常问题 ([4959c2e](https://github.com/fast-crud/fast-crud/commit/4959c2e15b89f6d2fec50864f1453f2965a85159))
* 增加文档链接 ([2b9f525](https://github.com/fast-crud/fast-crud/commit/2b9f525988c34ea322695b1a40de0628a627e50a))
### Features
* 新特性CrudOptionsPlugin ([9e1ac6d](https://github.com/fast-crud/fast-crud/commit/9e1ac6df56622b3b75cd5a23ea565f5c722085de))
* ui-demoui-interface独立 ([d78f040](https://github.com/fast-crud/fast-crud/commit/d78f040cd666d072937b0350edb2da11871206e6))
### Performance Improvements
* 导出增加loading ([6530c29](https://github.com/fast-crud/fast-crud/commit/6530c29615be9e1ff04029a962d521bed2df30a6))
* 优化文档搜索 ([19fff41](https://github.com/fast-crud/fast-crud/commit/19fff41b3f431e2bd1c84274a7d17ad96a547b03))
## [1.17.5](https://github.com/fast-crud/fast-crud/compare/v1.17.4...v1.17.5) (2023-09-26)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.17.4](https://github.com/fast-crud/fast-crud/compare/v1.17.3...v1.17.4) (2023-09-26)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.17.3](https://github.com/fast-crud/fast-crud/compare/v1.17.2...v1.17.3) (2023-09-23)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.17.2](https://github.com/fast-crud/fast-crud/compare/v1.17.1...v1.17.2) (2023-09-16)
### Bug Fixes
* 修复naive 时间示例无法修改的bug ([6ab9218](https://github.com/fast-crud/fast-crud/commit/6ab92188fc19d792de8bed0190853c444784b009))
* antdv 查询框label上置错位的bug ([00a35ad](https://github.com/fast-crud/fast-crud/commit/00a35ade86de3f2b9c3c336f3c8dda6f224e1abf))
## [1.17.1](https://github.com/fast-crud/fast-crud/compare/v1.17.0...v1.17.1) (2023-09-13)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
# [1.17.0](https://github.com/fast-crud/fast-crud/compare/v1.16.11...v1.17.0) (2023-09-12)
### Bug Fixes
* 修复element 图片裁剪组件无法横向排列的bug ([25fa258](https://github.com/fast-crud/fast-crud/commit/25fa25855e9750813d5a959a8b09ff6e90b04c1c))
### Features
* table-select支持 ([1c5b749](https://github.com/fast-crud/fast-crud/commit/1c5b7493a7782581a5f2a5bff843b135eb531f92))
### Performance Improvements
* 增加重置后清空排序设置演示 ([6a563ad](https://github.com/fast-crud/fast-crud/commit/6a563ad67b87f66e2765e47f72c5d4831cf06801))
## [1.16.11](https://github.com/fast-crud/fast-crud/compare/v1.16.10...v1.16.11) (2023-09-03)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.16.10](https://github.com/fast-crud/fast-crud/compare/v1.16.9...v1.16.10) (2023-09-03)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.16.9](https://github.com/fast-crud/fast-crud/compare/v1.16.8...v1.16.9) (2023-09-03)
### Performance Improvements
* 表单下所有组件优化为宽度100% ([da38460](https://github.com/fast-crud/fast-crud/commit/da384605f9c6bfc26359a369613dce4f48a3ba64))
## [1.16.8](https://github.com/fast-crud/fast-crud/compare/v1.16.7...v1.16.8) (2023-09-03)
### Performance Improvements
* 表单labelWidth演示 ([72f5372](https://github.com/fast-crud/fast-crud/commit/72f5372948f9aefebb0aba8671c277e8d80566bd))
* 翻页后自动滚动到顶部 ([a6e5f67](https://github.com/fast-crud/fast-crud/commit/a6e5f6740a59780995283c7d787864fdd65f0d4b))
## [1.16.7](https://github.com/fast-crud/fast-crud/compare/v1.16.6...v1.16.7) (2023-08-21)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.16.6](https://github.com/fast-crud/fast-crud/compare/v1.16.5...v1.16.6) (2023-08-21)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.16.5](https://github.com/fast-crud/fast-crud/compare/v1.16.4...v1.16.5) (2023-08-20)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.16.4](https://github.com/fast-crud/fast-crud/compare/v1.16.3...v1.16.4) (2023-08-18)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.16.3](https://github.com/fast-crud/fast-crud/compare/v1.16.2...v1.16.3) (2023-08-18)
### Performance Improvements
* fs-button增加buttonProps参数当fs-button的属性与x-button属性名重复时使用 ([5ca5333](https://github.com/fast-crud/fast-crud/commit/5ca53330f8bcf8d7acf4eb921aa92b83c41de52a))
## [1.16.2](https://github.com/fast-crud/fast-crud/compare/v1.16.1...v1.16.2) (2023-08-10)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.16.1](https://github.com/fast-crud/fast-crud/compare/v1.16.0...v1.16.1) (2023-08-09)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
# [1.16.0](https://github.com/fast-crud/fast-crud/compare/v1.15.1...v1.16.0) (2023-08-07)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
## [1.15.1](https://github.com/fast-crud/fast-crud/compare/v1.15.0...v1.15.1) (2023-08-05)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv4
# [1.15.0](https://github.com/fast-crud/fast-crud/compare/v1.14.7...v1.15.0) (2023-08-05)
### Features
* antdv4 支持 ([1935614](https://github.com/fast-crud/fast-crud/commit/19356142cda925d1248fe7c84c18cb8324ce5f70))
### Performance Improvements
* 适配antdv4样式 ([1108f58](https://github.com/fast-crud/fast-crud/commit/1108f5874a5369cbdb6f015264327ea8a879da61))
## [1.14.7](https://github.com/fast-crud/fast-crud/compare/v1.14.6...v1.14.7) (2023-07-24)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.14.6](https://github.com/fast-crud/fast-crud/compare/v1.14.5...v1.14.6) (2023-07-23)
### Bug Fixes
* 修复element 版 search select组件右边超出显示的问题 ([ff11cf4](https://github.com/fast-crud/fast-crud/commit/ff11cf4f9c6ac63d997b5cad2067123c01cd299b))
## [1.14.5](https://github.com/fast-crud/fast-crud/compare/v1.14.4...v1.14.5) (2023-07-04)
### Bug Fixes
* 修复search.value第一次查询无效的bug ([d9a907a](https://github.com/fast-crud/fast-crud/commit/d9a907a477bae66662a8a8720a24ab3506772d30))
## [1.14.4](https://github.com/fast-crud/fast-crud/compare/v1.14.3...v1.14.4) (2023-07-02)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.14.3](https://github.com/fast-crud/fast-crud/compare/v1.14.2...v1.14.3) (2023-07-02)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.14.2](https://github.com/fast-crud/fast-crud/compare/v1.14.1...v1.14.2) (2023-07-02)
### Bug Fixes
* 修复多选导出csv导致表格错位的bug ([4e0bf5b](https://github.com/fast-crud/fast-crud/commit/4e0bf5bae3bd39fd1654c5cf10991039eacf1acc))
* 修复某些情况下fs-icon spin失效的bug ([2499a33](https://github.com/fast-crud/fast-crud/commit/2499a338def7436356c91a9b547e570c4204286d))
* 修复行编辑模式下render、conditionalRender无效的bug ([403fedc](https://github.com/fast-crud/fast-crud/commit/403fedc6e22817e33a1f4ac316a016e570127aa8))
### Performance Improvements
* 导出重构 ([e99dc7b](https://github.com/fast-crud/fast-crud/commit/e99dc7bb6b24d4456fc524a04e8787e16b07511e))
* export 功能 ([2accdba](https://github.com/fast-crud/fast-crud/commit/2accdba5d087c01a87c6fd20b98c6510d0038f9d))
## [1.14.1](https://github.com/fast-crud/fast-crud/compare/v1.14.0...v1.14.1) (2023-06-16)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
# [1.14.0](https://github.com/fast-crud/fast-crud/compare/v1.13.12...v1.14.0) (2023-06-09)
### Features
* crudBinding.value.table.columns由array改成map ([8f89d2b](https://github.com/fast-crud/fast-crud/commit/8f89d2b26e12be0b3bcec2da8b4d7a2942395e8e))
## [1.13.12](https://github.com/fast-crud/fast-crud/compare/v1.13.11...v1.13.12) (2023-06-08)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.13.11](https://github.com/fast-crud/fast-crud/compare/v1.13.10...v1.13.11) (2023-06-08)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.13.10](https://github.com/fast-crud/fast-crud/compare/v1.13.9...v1.13.10) (2023-05-31)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.13.9](https://github.com/fast-crud/fast-crud/compare/v1.13.8...v1.13.9) (2023-05-31)
### Bug Fixes
* 修复antdv文件上传限制数量的bug ([8b14ba3](https://github.com/fast-crud/fast-crud/commit/8b14ba3a45f90a11222cc751b2ca173e212bc666))
## [1.13.8](https://github.com/fast-crud/fast-crud/compare/v1.13.7...v1.13.8) (2023-05-22)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.13.7](https://github.com/fast-crud/fast-crud/compare/v1.13.6...v1.13.7) (2023-05-19)
### Bug Fixes
* 修复rowhandle 排列不整齐的问题 ([ff644b1](https://github.com/fast-crud/fast-crud/commit/ff644b11b91c58295692fc0874dc4a3d743eb6df))
## [1.13.6](https://github.com/fast-crud/fast-crud/compare/v1.13.5...v1.13.6) (2023-05-13)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.13.5](https://github.com/fast-crud/fast-crud/compare/v1.13.4...v1.13.5) (2023-05-13)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.13.4](https://github.com/fast-crud/fast-crud/compare/v1.13.3...v1.13.4) (2023-05-06)
### Bug Fixes
* 1.13.3 ([451bd53](https://github.com/fast-crud/fast-crud/commit/451bd5390ce88fcbb875d39a39c88b3226f46b4e))
### Performance Improvements
* naiveui sortable示例完善 ([dcd9e5b](https://github.com/fast-crud/fast-crud/commit/dcd9e5b04df7bda352878f4f1e30874ab9a6f452))
## [1.13.3](https://github.com/fast-crud/fast-crud/compare/v1.13.2...v1.13.3) (2023-05-04)
### Bug Fixes
* 升级cos sdk修复windows报毒问题 ([352f8df](https://github.com/fast-crud/fast-crud/commit/352f8df76dfe093dd29c8778f3b33e3e3775b902))
## [1.13.2](https://github.com/fast-crud/fast-crud/compare/v1.13.1...v1.13.2) (2023-04-20)
### Bug Fixes
* dict ts缺少cloneable参数 ([ab9528d](https://github.com/fast-crud/fast-crud/commit/ab9528d7ae2ab782cccc89d7530a22faa981ee74))
### Performance Improvements
* 优化fs-images-format 加载失败时的显示 ([7df6eab](https://github.com/fast-crud/fast-crud/commit/7df6eab4d653409de442eeef933177906a2ffc70))
## [1.13.1](https://github.com/fast-crud/fast-crud/compare/v1.13.0...v1.13.1) (2023-04-10)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
# [1.13.0](https://github.com/fast-crud/fast-crud/compare/v1.12.2...v1.13.0) (2023-04-07)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.12.2](https://github.com/fast-crud/fast-crud/compare/v1.12.1...v1.12.2) (2023-04-06)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.12.1](https://github.com/fast-crud/fast-crud/compare/v1.12.0...v1.12.1) (2023-04-04)
### Performance Improvements
* 增加自定义组件示例 ([c1f5b40](https://github.com/fast-crud/fast-crud/commit/c1f5b407d6137a0f5cbedb1ec2a56a18140e77a1))
# [1.12.0](https://github.com/fast-crud/fast-crud/compare/v1.11.10...v1.12.0) (2023-03-31)
### Performance Improvements
* 优化多行查询示例 ([95fa427](https://github.com/fast-crud/fast-crud/commit/95fa427043b29ef9590ce75fe91df9d5d686b196))
## [1.11.10](https://github.com/fast-crud/fast-crud/compare/v1.11.9...v1.11.10) (2023-03-29)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.11.9](https://github.com/fast-crud/fast-crud/compare/v1.11.8...v1.11.9) (2023-03-28)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.11.8](https://github.com/fast-crud/fast-crud/compare/v1.11.7...v1.11.8) (2023-03-24)
### Bug Fixes
* 修复当limit=1时上传文件删光后再选择文件上传第一次无效的bug ([d0a1ed9](https://github.com/fast-crud/fast-crud/commit/d0a1ed9c8a730d5eea19dc61f0dd6cf4031db1c3))
### Performance Improvements
* 优化翻页性能 ([d0a1db7](https://github.com/fast-crud/fast-crud/commit/d0a1db7bda08b49226739bba38e28b38c60c2b65))
## [1.11.7](https://github.com/fast-crud/fast-crud/compare/v1.11.6...v1.11.7) (2023-03-22)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.11.6](https://github.com/fast-crud/fast-crud/compare/v1.11.5...v1.11.6) (2023-03-22)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.11.5](https://github.com/fast-crud/fast-crud/compare/v1.11.4...v1.11.5) (2023-03-22)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.11.4](https://github.com/fast-crud/fast-crud/compare/v1.11.3...v1.11.4) (2023-03-22)
### Performance Improvements
* doRefresh增加参数 ([a585604](https://github.com/fast-crud/fast-crud/commit/a5856045380f4a3fe2e657fd2ace1aea3473c6d7))
## [1.11.3](https://github.com/fast-crud/fast-crud/compare/v1.11.2...v1.11.3) (2023-03-21)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.11.2](https://github.com/fast-crud/fast-crud/compare/v1.11.1...v1.11.2) (2023-03-21)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.11.1](https://github.com/fast-crud/fast-crud/compare/v1.11.0...v1.11.1) (2023-03-17)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
# [1.11.0](https://github.com/fast-crud/fast-crud/compare/v1.10.0...v1.11.0) (2023-03-16)
### Bug Fixes
* 修复wangeditor无法上传视频的bug ([53ee51e](https://github.com/fast-crud/fast-crud/commit/53ee51e901956da9596600235632545bcf98746e))
### Performance Improvements
* 全面ts化 ([168d3a2](https://github.com/fast-crud/fast-crud/commit/168d3a240eb67548195c31a5fa4cb5aedb8a410c))
# [1.10.0](https://github.com/fast-crud/fast-crud/compare/v1.9.2...v1.10.0) (2023-03-11)
### Bug Fixes
* 行编辑支持多级表头 ([a547c99](https://github.com/fast-crud/fast-crud/commit/a547c99250f2d00b9d91c326364ccb81415c2772))
### Features
* fs-form-wrapper支持多实例 ([023cc1d](https://github.com/fast-crud/fast-crud/commit/023cc1d425d5b1fa618a3d13fe5c88c81671524d))
### Performance Improvements
* 完善文档完善部分types ([8fff02d](https://github.com/fast-crud/fast-crud/commit/8fff02d758530bbb1212d7475dc94bc8b562ef97))
* 优化d.ts类型 ([7a51aac](https://github.com/fast-crud/fast-crud/commit/7a51aace532ed6692f28a53332a2103a74f5827a))
* 增加s3示例 ([9060b03](https://github.com/fast-crud/fast-crud/commit/9060b036ce9e36ef8f2ddc50b1362682c7d3aa7f))
## [1.9.2](https://github.com/fast-crud/fast-crud/compare/v1.9.1...v1.9.2) (2023-03-01)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [1.9.1](https://github.com/fast-crud/fast-crud/compare/v1.9.0...v1.9.1) (2023-03-01)
**Note:** Version bump only for package @fast-crud/fs-admin-antdv
## [0.10.5](https://github.com/fast-crud/fast-crud/compare/v0.10.4...v0.10.5) (2021-07-01)
### Performance Improvements
* fs-admin 与crud demo ([4e6b20f](https://github.com/fast-crud/fast-crud/commit/4e6b20fe19434460853841f371b9fd5f16e5e2d3))
* fs-admin纳入子模块 ([2940d30](https://github.com/fast-crud/fast-crud/commit/2940d30f419bf4bde1e8e791f1fbdb9184818285))

View File

@@ -13,6 +13,11 @@ https://github.com/fast-crud/fs-server-js
* [fs-admin-naive](https://github.com/fast-crud/fs-admin-naive-ui) naive版示例
* [fs-in-vben-starter](https://github.com/fast-crud/fs-in-vben-starter) vben示例
# build
```sh
set NODE_OPTIONS=--max-old-space-size=32768 && npm run build
```
# 感谢
### 依赖
@@ -34,3 +39,4 @@ https://github.com/fast-crud/fs-server-js

View File

@@ -0,0 +1,254 @@
import path from "node:path";
import { addDynamicIconSelectors } from "@iconify/tailwind";
import { getPackagesSync } from "@manypkg/get-packages";
import typographyPlugin from "@tailwindcss/typography";
import animate from "tailwindcss-animate";
import { enterAnimationPlugin } from "./plugins/entry.mjs";
// import defaultTheme from 'tailwindcss/defaultTheme';
const { packages } = getPackagesSync(process.cwd());
const tailwindPackages = [];
packages.forEach((pkg) => {
// apps目录下和 @vben-core/tailwind-ui 包需要使用到 tailwindcss ui
// if (fs.existsSync(path.join(pkg.dir, 'tailwind.config.mjs'))) {
tailwindPackages.push(pkg.dir);
// }
});
const shadcnUiColors = {
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
hover: "hsl(var(--accent-hover))",
lighter: "has(val(--accent-lighter))"
},
background: {
deep: "hsl(var(--background-deep))",
DEFAULT: "hsl(var(--background))"
},
border: {
DEFAULT: "hsl(var(--border))"
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))"
},
destructive: {
...createColorsPalette("destructive"),
DEFAULT: "hsl(var(--destructive))"
},
foreground: {
DEFAULT: "hsl(var(--foreground))"
},
input: {
background: "hsl(var(--input-background))",
DEFAULT: "hsl(var(--input))"
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))"
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))"
},
primary: {
...createColorsPalette("primary"),
DEFAULT: "hsl(var(--primary))"
},
ring: "hsl(var(--ring))",
secondary: {
DEFAULT: "hsl(var(--secondary))",
desc: "hsl(var(--secondary-desc))",
foreground: "hsl(var(--secondary-foreground))"
}
};
const customColors = {
green: {
...createColorsPalette("green"),
foreground: "hsl(var(--success-foreground))"
},
header: {
DEFAULT: "hsl(var(--header))"
},
heavy: {
DEFAULT: "hsl(var(--heavy))",
foreground: "hsl(var(--heavy-foreground))"
},
main: {
DEFAULT: "hsl(var(--main))"
},
overlay: {
content: "hsl(var(--overlay-content))",
DEFAULT: "hsl(var(--overlay))"
},
red: {
...createColorsPalette("red"),
foreground: "hsl(var(--destructive-foreground))"
},
sidebar: {
deep: "hsl(var(--sidebar-deep))",
DEFAULT: "hsl(var(--sidebar))"
},
success: {
...createColorsPalette("success"),
DEFAULT: "hsl(var(--success))"
},
warning: {
...createColorsPalette("warning"),
DEFAULT: "hsl(var(--warning))"
},
yellow: {
...createColorsPalette("yellow"),
foreground: "hsl(var(--warning-foreground))"
}
};
export default {
content: ["./index.html", ...tailwindPackages.map((item) => path.join(item, "src/**/*.{vue,js,ts,jsx,tsx,svelte,astro,html}"))],
darkMode: "selector",
plugins: [animate, typographyPlugin, addDynamicIconSelectors(), enterAnimationPlugin],
prefix: "",
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px"
}
},
extend: {
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
"collapsible-down": "collapsible-down 0.2s ease-in-out",
"collapsible-up": "collapsible-up 0.2s ease-in-out",
float: "float 5s linear 0ms infinite"
},
animationDuration: {
2000: "2000ms",
3000: "3000ms"
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
xl: "calc(var(--radius) + 4px)"
},
boxShadow: {
float: `0 6px 16px 0 rgb(0 0 0 / 8%),
0 3px 6px -4px rgb(0 0 0 / 12%),
0 9px 28px 8px rgb(0 0 0 / 5%)`
},
colors: {
...customColors,
...shadcnUiColors
},
fontFamily: {
sans: [
"var(--font-family)"
// ...defaultTheme.fontFamily.sans
]
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" }
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" }
},
"collapsible-down": {
from: { height: "0" },
to: { height: "var(--radix-collapsible-content-height)" }
},
"collapsible-up": {
from: { height: "var(--radix-collapsible-content-height)" },
to: { height: "0" }
},
float: {
"0%": { transform: "translateY(0)" },
"50%": { transform: "translateY(-20px)" },
"100%": { transform: "translateY(0)" }
}
},
zIndex: {
100: "100",
1000: "1000"
}
}
},
safelist: ["dark"]
};
function createColorsPalette(name) {
// backgroundLightest: '#EFF6FF', // Tailwind CSS 默认的 `blue-50`
// backgroundLighter: '#DBEAFE', // Tailwind CSS 默认的 `blue-100`
// backgroundLight: '#BFDBFE', // Tailwind CSS 默认的 `blue-200`
// borderLight: '#93C5FD', // Tailwind CSS 默认的 `blue-300`
// border: '#60A5FA', // Tailwind CSS 默认的 `blue-400`
// main: '#3B82F6', // Tailwind CSS 默认的 `blue-500`
// hover: '#2563EB', // Tailwind CSS 默认的 `blue-600`
// active: '#1D4ED8', // Tailwind CSS 默认的 `blue-700`
// backgroundDark: '#1E40AF', // Tailwind CSS 默认的 `blue-800`
// backgroundDarker: '#1E3A8A', // Tailwind CSS 默认的 `blue-900`
// backgroundDarkest: '#172554', // Tailwind CSS 默认的 `blue-950`
// • backgroundLightest (#EFF6FF): 适用于最浅的背景色,可能用于非常轻微的阴影或卡片的背景。
// • backgroundLighter (#DBEAFE): 适用于略浅的背景色,通常用于次要背景或略浅的区域。
// • backgroundLight (#BFDBFE): 适用于浅色背景,可能用于输入框或表单区域的背景。
// • borderLight (#93C5FD): 适用于浅色边框,可能用于输入框或卡片的边框。
// • border (#60A5FA): 适用于普通边框,可能用于按钮或卡片的边框。
// • main (#3B82F6): 适用于主要的主题色,通常用于按钮、链接或主要的强调色。
// • hover (#2563EB): 适用于鼠标悬停状态下的颜色,例如按钮悬停时的背景色或边框色。
// • active (#1D4ED8): 适用于激活状态下的颜色,例如按钮按下时的背景色或边框色。
// • backgroundDark (#1E40AF): 适用于深色背景,可能用于主要按钮或深色卡片背景。
// • backgroundDarker (#1E3A8A): 适用于更深的背景,通常用于头部导航栏或页脚。
// • backgroundDarkest (#172554): 适用于最深的背景,可能用于非常深色的区域或极端对比色。
return {
50: `hsl(var(--${name}-50))`,
100: `hsl(var(--${name}-100))`,
200: `hsl(var(--${name}-200))`,
300: `hsl(var(--${name}-300))`,
400: `hsl(var(--${name}-400))`,
500: `hsl(var(--${name}-500))`,
600: `hsl(var(--${name}-600))`,
700: `hsl(var(--${name}-700))`,
// 800: `hsl(var(--${name}-800))`,
// 900: `hsl(var(--${name}-900))`,
// 950: `hsl(var(--${name}-950))`,
// 激活状态下的颜色,适用于按钮按下时的背景色或边框色。
active: `hsl(var(--${name}-700))`,
// 浅色背景,适用于输入框或表单区域的背景。
"background-light": `hsl(var(--${name}-200))`,
// 适用于略浅的背景色,通常用于次要背景或略浅的区域。
"background-lighter": `hsl(var(--${name}-100))`,
// 最浅的背景色,适用于非常轻微的阴影或卡片的背景。
"background-lightest": `hsl(var(--${name}-50))`,
// 适用于普通边框,可能用于按钮或卡片的边框。
border: `hsl(var(--${name}-400))`,
// 浅色边框,适用于输入框或卡片的边框。
"border-light": `hsl(var(--${name}-300))`,
foreground: `hsl(var(--${name}-foreground))`,
// 鼠标悬停状态下的颜色,适用于按钮悬停时的背景色或边框色。
hover: `hsl(var(--${name}-600))`,
// 主色文本
text: `hsl(var(--${name}-500))`,
// 主色文本激活态
"text-active": `hsl(var(--${name}-700))`,
// 主色文本悬浮态
"text-hover": `hsl(var(--${name}-600))`
};
}

View File

@@ -0,0 +1,53 @@
import plugin from "tailwindcss/plugin.js";
const enterAnimationPlugin = plugin(({ addUtilities }) => {
const maxChild = 5;
const utilities = {};
for (let i = 1; i <= maxChild; i++) {
const baseDelay = 0.1;
const delay = `${baseDelay * i}s`;
utilities[`.enter-x:nth-child(${i})`] = {
animation: `enter-x-animation 0.3s ease-in-out ${delay} forwards`,
opacity: "0",
transform: `translateX(50px)`
};
utilities[`.enter-y:nth-child(${i})`] = {
animation: `enter-y-animation 0.3s ease-in-out ${delay} forwards`,
opacity: "0",
transform: `translateY(50px)`
};
utilities[`.-enter-x:nth-child(${i})`] = {
animation: `enter-x-animation 0.3s ease-in-out ${delay} forwards`,
opacity: "0",
transform: `translateX(-50px)`
};
utilities[`.-enter-y:nth-child(${i})`] = {
animation: `enter-y-animation 0.3s ease-in-out ${delay} forwards`,
opacity: "0",
transform: `translateY(-50px)`
};
}
// 添加动画关键帧
addUtilities(utilities);
addUtilities({
"@keyframes enter-x-animation": {
to: {
opacity: "1",
transform: "translateX(0)"
}
},
"@keyframes enter-y-animation": {
to: {
opacity: "1",
transform: "translateY(0)"
}
}
});
});
export { enterAnimationPlugin };

View File

@@ -0,0 +1,15 @@
import config from ".";
export default {
plugins: {
...(process.env.NODE_ENV === "production" ? { cssnano: {} } : {}),
// Specifying the config is not necessary in most cases, but it is included
autoprefixer: {},
// 修复 element-plus 和 ant-design-vue 的样式和tailwindcss冲突问题
"postcss-antd-fixes": { prefixes: ["ant", "el"] },
"postcss-import": {},
"postcss-preset-env": {},
tailwindcss: { config },
"tailwindcss/nesting": {}
}
};

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>antdv-fast-crud</title>
<title><%= title %></title>
<link rel="stylesheet" type="text/css" href="/index.css" />
</head>
<body>
@@ -14,8 +14,8 @@
<div class="fs-bootstrap__loading"></div>
</div>
<div class="fs-bootstrap__footer">
<a href="https://github.com/fast-crud/fast-crud" target="_blank">
https://github.com/fast-crud/fast-crud
<a href="<%= projectPath %>" target="_blank">
<%= projectPath %>
</a>
</div>
</div>

View File

@@ -1,12 +1,12 @@
{
"name": "@fast-crud/fs-admin-antdv",
"version": "1.9.2",
"name": "@fast-crud/fs-admin-antdv4",
"version": "1.26.0",
"private": true,
"scripts": {
"dev": "vite",
"dev:pm": "vite --mode pm",
"dev:force": "vite --force",
"debug": "vite --mode debug",
"debug": "vite --mode debug --open",
"debug:pm": "vite --mode debugpm",
"debug:force": "vite --force --mode debug",
"build": "vite build ",
@@ -15,96 +15,134 @@
"pretty-quick": "pretty-quick",
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/",
"upgrade": "yarn upgrade-interactive --latest",
"tsc": "vue-tsc --noEmit --skipLibCheck"
"tsc": "vue-tsc --noEmit --skipLibCheck",
"circle:check": "pnpm dependency-cruise --validate --output-type err-html -f dependency-report.html src",
"afterPubPush": "git add . && git commit -m \"build: publish success\" && git push"
},
"author": "Greper",
"author": "greper",
"license": "MIT",
"dependencies": {
"@ant-design/colors": "^6.0.0",
"@ant-design/icons-vue": "^6.0.1",
"@fast-crud/fast-crud": "^1.9.2",
"@fast-crud/fast-extends": "^1.9.2",
"@fast-crud/ui-antdv": "^1.9.2",
"@iconify/iconify": "^3.0.1",
"@iconify/json": "^2.1.151",
"@purge-icons/generated": "^0.9.0",
"@ant-design/colors": "^7.0.2",
"@ant-design/icons-vue": "^7.0.1",
"@aws-sdk/client-s3": "^3.535.0",
"@aws-sdk/s3-request-presigner": "^3.535.0",
"@ctrl/tinycolor": "^4.1.0",
"@fast-crud/editor-code": "^1.26.0",
"@fast-crud/fast-crud": "^1.26.0",
"@fast-crud/fast-extends": "^1.26.0",
"@fast-crud/ui-antdv4": "^1.26.0",
"@fast-crud/ui-interface": "^1.26.0",
"@iconify/tailwind": "^1.2.0",
"@iconify/vue": "^4.1.1",
"@manypkg/get-packages": "^2.2.2",
"@soerenmartius/vue3-clipboard": "^0.1.2",
"ant-design-vue": "^3.2.15",
"axios": "^1.2.1",
"axios-mock-adapter": "^1.21.2",
"@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
"@tailwindcss/typography": "^0.5.16",
"@tanstack/vue-store": "^0.7.0",
"@vee-validate/zod": "^4.15.0",
"@vue/shared": "^3.5.13",
"@vueuse/core": "^10.11.0",
"ant-design-vue": "^4.2.6",
"axios": "^1.6.8",
"axios-mock-adapter": "^1.22.0",
"base64-js": "^1.5.1",
"better-scroll": "^2.5.0",
"china-division": "^2.4.0",
"core-js": "^3.26.1",
"cos-js-sdk-v5": "^1.4.15-beta.0",
"cropperjs": "^1.5.13",
"dayjs": "^1.11.7",
"deepdash-es": "5.3.5",
"highlight.js": "^11.7.0",
"lodash-es": "^4.17.15",
"mitt": "^3.0.0",
"better-scroll": "^2.5.1",
"china-division": "^2.7.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"core-js": "^3.36.0",
"cos-js-sdk-v5": "^1.7.0",
"cropperjs": "^1.6.1",
"cssnano": "^7.0.6",
"dayjs": "^1.11.10",
"defu": "^6.1.4",
"highlight.js": "^11.9.0",
"js-yaml": "^4.1.0",
"lodash-es": "^4.17.21",
"lucide-vue-next": "^0.477.0",
"mitt": "^3.0.1",
"monaco-editor": "^0.52.2",
"monaco-yaml": "^5.3.1",
"nprogress": "^0.2.0",
"object-assign": "^4.1.1",
"pinia": "2.0.28",
"qiniu-js": "^3.4.1",
"sortablejs": "^1.14.0",
"vue": "^3.2.45",
"pinia": "2.1.7",
"pinia-plugin-persistedstate": "^4.2.0",
"postcss-antd-fixes": "^0.2.0",
"postcss-import": "^16.1.0",
"postcss-preset-env": "^10.1.5",
"qiniu-js": "^3.4.2",
"radix-vue": "^1.9.16",
"sortablejs": "^1.15.3",
"tailwind-merge": "^3.0.2",
"tailwindcss-animate": "^1.0.7",
"theme-colors": "^0.1.0",
"vee-validate": "^4.15.0",
"vitest": "^0.34.6",
"vue": "^3.4.21",
"vue-cropperjs": "^5.0.0",
"vue-i18n": "^9.2.2",
"vue-router": "^4.1.5",
"vuedraggable": "^4.0.1"
"vue-i18n": "^9.10.2",
"vue-router": "^4.3.0",
"vuedraggable": "^2.24.3",
"watermark-js-plus": "^1.5.8",
"yaml-language-server": "^1.17.0",
"zod": "^3.24.2",
"zod-defaults": "^0.1.3"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^23.0.4",
"@rollup/plugin-node-resolve": "^15.0.1",
"@types/chai": "^4.3.4",
"@types/lodash-es": "^4.17.6",
"@types/mocha": "^10.0.1",
"@types/node": "^18.11.15",
"@typescript-eslint/eslint-plugin": "^5.46.1",
"@typescript-eslint/parser": "^5.46.1",
"@vitejs/plugin-legacy": "^3.0.1",
"@vitejs/plugin-vue": "^4.0.0",
"@vitejs/plugin-vue-jsx": "^3.0.0",
"@vue/compiler-sfc": "^3.2.45",
"@vue/eslint-config-typescript": "^11.0.2",
"@vue/test-utils": "^2.2.6",
"autoprefixer": "^10.4.12",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@types/chai": "^4.3.12",
"@types/lodash-es": "^4.17.12",
"@types/mocha": "^10.0.6",
"@types/node": "^20.11.28",
"@types/nprogress": "^0.2.3",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-legacy": "^5.3.2",
"@vitejs/plugin-vue": "^5.0.4",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/compiler-sfc": "^3.4.21",
"@vue/eslint-config-typescript": "^13.0.0",
"@vue/test-utils": "^2.4.5",
"autoprefixer": "^10.4.20",
"caller-path": "^4.0.0",
"chai": "^4.3.7",
"eslint": "8.29.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-import": "^2.26.0",
"chai": "^5.1.0",
"dependency-cruiser": "^16.2.3",
"dot": "^1.1.3",
"eslint": "8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.0.1",
"eslint-plugin-vue": "^9.8.0",
"esno": "^0.16.3",
"husky": "^8.0.2",
"less": "^4.1.3",
"less-loader": "^11.0.0",
"lint-staged": "^13.1.0",
"postcss": "^8.4.20",
"prettier": "2.8.1",
"pretty-quick": "^3.1.3",
"rimraf": "^3.0.2",
"rollup": "^3.7.4",
"rollup-plugin-visualizer": "^5.8.2",
"stylelint": "^14.16.0",
"stylelint-config-prettier": "^9.0.4",
"stylelint-order": "^5.0.0",
"tailwindcss": "^3.2.4",
"ts-node": "^10.9.1",
"typescript": "4.9.4",
"vite": "^4.0.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-vue": "^9.23.0",
"esno": "^4.7.0",
"husky": "^9.0.11",
"less": "^4.2.0",
"less-loader": "^12.2.0",
"lint-staged": "^15.2.2",
"postcss": "^8.4.35",
"prettier": "3.2.5",
"pretty-quick": "^4.0.0",
"rimraf": "^5.0.5",
"rollup": "^4.13.0",
"rollup-plugin-visualizer": "^5.12.0",
"stylelint": "^16.2.1",
"stylelint-config-prettier": "^9.0.5",
"stylelint-order": "^6.0.4",
"tailwindcss": "^3.4.14",
"terser": "^5.29.2",
"ts-node": "^10.9.2",
"tslint": "^6.1.3",
"typescript": "5.4.2",
"unplugin-vue-define-options": "^1.4.2",
"vite": "^5.1.6",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-optimize-persist": "^0.1.2",
"vite-plugin-package-config": "^0.1.1",
"vite-plugin-purge-icons": "^0.9.2",
"vite-plugin-theme": "^0.8.1",
"vite-plugin-windicss": "^1.8.10",
"vue-eslint-parser": "^9.1.0",
"vue-tsc": "^0.40.13",
"vite-plugin-html": "^3.2.2",
"vite-plugin-theme": "^0.8.6",
"vite-plugin-windicss": "^1.9.3",
"vue-eslint-parser": "^9.4.2",
"vue-tsc": "^1.8.8",
"windicss": "^3.5.6"
},
"husky": {

View File

@@ -0,0 +1,15 @@
import config from "./build/tailwind-config/index.mjs";
export default {
plugins: {
...(process.env.NODE_ENV === "production" ? { cssnano: {} } : {}),
// Specifying the config is not necessary in most cases, but it is included
autoprefixer: {},
// 修复 element-plus 和 ant-design-vue 的样式和tailwindcss冲突问题
"postcss-antd-fixes": { prefixes: ["ant", "el"] },
"postcss-import": {},
"postcss-preset-env": {},
tailwindcss: { config },
"tailwindcss/nesting": {}
}
};

View File

@@ -1,7 +0,0 @@
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="500" height="500" viewBox="0 0 500.000000 500.000000"
>
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
transform="translate(70, 76) scale(6,6)"
></path>
</svg>

Before

Width:  |  Height:  |  Size: 402 B

View File

@@ -1,44 +0,0 @@
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="800" height="300" viewBox="0 0 800.000000 300.000000"
>
<g fill="#333">
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
transform="translate(40, 40) scale(4,4)"
></path>
<g transform="translate(280, 260) scale(2,2)">
<path d="M28.95-58.70L49.98-58.70L49.98-48.22L33.70-48.22Q27.37-48.22 24.46-47.34Q21.56-46.46 19.62-43.91L19.62-43.91Q18.30-42.15 17.82-40.39Q17.34-38.63 16.98-34.41L16.98-34.41L49.98-34.41L49.98-23.94L16.98-23.94Q17.69-16.37 21.47-13.42Q25.26-10.47 34.32-10.47L34.32-10.47L49.98-10.47L49.98 0L33.70 0Q27.10 0 22.09-0.79L22.09-0.79Q14.17-2.11 9.50-7.74L9.50-7.74Q2.82-15.84 2.82-29.66L2.82-29.66Q2.82-44.97 12.23-53.50L12.23-53.50Q15.49-56.41 19.14-57.55Q22.79-58.70 28.95-58.70L28.95-58.70Z"
transform="translate(0 0) "
></path>
<path d="M28.51-22.26L18.48-22.26L18.48 0L5.98 0L5.98-58.70L34.67-58.70Q46.99-58.70 51.83-55.53L51.83-55.53Q55.18-53.42 56.98-49.94Q58.78-46.46 58.78-42.33L58.78-42.33Q58.78-33.97 54.56-29.39L54.56-29.39Q51.92-26.66 47.61-25.26L47.61-25.26Q51.04-24.02 52.80-22.66Q54.56-21.30 55.97-18.66L55.97-18.66Q57.02-16.54 57.51-14.61Q57.99-12.67 58.26-8.89L58.26-8.89Q58.78-2.55 59.66 0L59.66 0L45.67 0Q45.06-2.02 44.35-8.36L44.35-8.36Q43.91-13.46 42.55-16.19Q41.18-18.92 38.46-20.50L38.46-20.50Q35.02-22.35 28.51-22.26L28.51-22.26ZM18.48-48.22L18.48-32.74L35.99-32.74Q40.39-32.74 42.24-34.06L42.24-34.06Q45.06-35.99 45.06-40.83L45.06-40.83Q45.06-46.20 40.83-47.70L40.83-47.70Q39.34-48.22 35.99-48.22L35.99-48.22L18.48-48.22Z"
transform="translate(58.855999999999995 0) "
></path>
<path d="M19.01 0L19.01-48.22L0.35-48.22L0.35-58.70L50.95-58.70L50.95-48.22L31.50-48.22L31.50 0L19.01 0Z"
transform="translate(126.68799999999999 0) "
></path>
<path d="M5.98 0L5.98-58.70L30.89-58.70Q40.22-58.70 45.32-56.85L45.32-56.85Q54.74-53.42 57.90-44.26L57.90-44.26Q60.28-37.22 60.28-29.22L60.28-29.22Q60.28-21.30 57.99-14.26L57.99-14.26Q55.70-7.04 50.42-3.61L50.42-3.61Q47.08-1.50 43.08-0.75Q39.07 0 30.89 0L30.89 0L5.98 0ZM30.89-48.22L18.48-48.22L18.48-10.47L30.89-10.47Q39.07-10.47 42.24-14.08L42.24-14.08Q44.18-16.37 45.36-20.50Q46.55-24.64 46.55-29.30L46.55-29.30Q46.55-34.50 45.14-38.81Q43.74-43.12 41.45-45.23L41.45-45.23Q38.10-48.22 30.89-48.22L30.89-48.22Z"
transform="translate(183.07999999999998 0) "
></path>
</g>
<!-- <path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23-->
<!-- 9-15.62L9-15.62Q7.65-14.08-->
<!-- 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17-->
<!-- 11.81-4.93Q12.87-4.68-->
<!-- 14.76-4.68L14.76-4.68L21.24-4.68L21.24-->
<!-- 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35-->
<!-- 4.32-3.01L4.32-3.01Q1.48-6.17-->
<!-- 1.48-11.03L1.48-11.03Q1.48-16.88-->
<!-- 4.86-19.75L4.86-19.75Q6.21-20.93-->
<!-- 8.10-21.42Q9.99-21.91-->
<!-- 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48-->
<!-- 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"-->
<!-- fill="#2c3e50"-->
<!-- transform="translate(300, 270) scale(4,4)"-->
<!-- ></path>-->
<text x="300" y="100" font-size="50" font-weight="bold">让你的证书永不过期</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -1,44 +0,0 @@
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="800" height="300" viewBox="0 0 800.000000 300.000000"
>
<g fill="#fff">
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
transform="translate(40, 40) scale(4,4)"
></path>
<g transform="translate(280, 260) scale(2,2)">
<path d="M28.95-58.70L49.98-58.70L49.98-48.22L33.70-48.22Q27.37-48.22 24.46-47.34Q21.56-46.46 19.62-43.91L19.62-43.91Q18.30-42.15 17.82-40.39Q17.34-38.63 16.98-34.41L16.98-34.41L49.98-34.41L49.98-23.94L16.98-23.94Q17.69-16.37 21.47-13.42Q25.26-10.47 34.32-10.47L34.32-10.47L49.98-10.47L49.98 0L33.70 0Q27.10 0 22.09-0.79L22.09-0.79Q14.17-2.11 9.50-7.74L9.50-7.74Q2.82-15.84 2.82-29.66L2.82-29.66Q2.82-44.97 12.23-53.50L12.23-53.50Q15.49-56.41 19.14-57.55Q22.79-58.70 28.95-58.70L28.95-58.70Z"
transform="translate(0 0) "
></path>
<path d="M28.51-22.26L18.48-22.26L18.48 0L5.98 0L5.98-58.70L34.67-58.70Q46.99-58.70 51.83-55.53L51.83-55.53Q55.18-53.42 56.98-49.94Q58.78-46.46 58.78-42.33L58.78-42.33Q58.78-33.97 54.56-29.39L54.56-29.39Q51.92-26.66 47.61-25.26L47.61-25.26Q51.04-24.02 52.80-22.66Q54.56-21.30 55.97-18.66L55.97-18.66Q57.02-16.54 57.51-14.61Q57.99-12.67 58.26-8.89L58.26-8.89Q58.78-2.55 59.66 0L59.66 0L45.67 0Q45.06-2.02 44.35-8.36L44.35-8.36Q43.91-13.46 42.55-16.19Q41.18-18.92 38.46-20.50L38.46-20.50Q35.02-22.35 28.51-22.26L28.51-22.26ZM18.48-48.22L18.48-32.74L35.99-32.74Q40.39-32.74 42.24-34.06L42.24-34.06Q45.06-35.99 45.06-40.83L45.06-40.83Q45.06-46.20 40.83-47.70L40.83-47.70Q39.34-48.22 35.99-48.22L35.99-48.22L18.48-48.22Z"
transform="translate(58.855999999999995 0) "
></path>
<path d="M19.01 0L19.01-48.22L0.35-48.22L0.35-58.70L50.95-58.70L50.95-48.22L31.50-48.22L31.50 0L19.01 0Z"
transform="translate(126.68799999999999 0) "
></path>
<path d="M5.98 0L5.98-58.70L30.89-58.70Q40.22-58.70 45.32-56.85L45.32-56.85Q54.74-53.42 57.90-44.26L57.90-44.26Q60.28-37.22 60.28-29.22L60.28-29.22Q60.28-21.30 57.99-14.26L57.99-14.26Q55.70-7.04 50.42-3.61L50.42-3.61Q47.08-1.50 43.08-0.75Q39.07 0 30.89 0L30.89 0L5.98 0ZM30.89-48.22L18.48-48.22L18.48-10.47L30.89-10.47Q39.07-10.47 42.24-14.08L42.24-14.08Q44.18-16.37 45.36-20.50Q46.55-24.64 46.55-29.30L46.55-29.30Q46.55-34.50 45.14-38.81Q43.74-43.12 41.45-45.23L41.45-45.23Q38.10-48.22 30.89-48.22L30.89-48.22Z"
transform="translate(183.07999999999998 0) "
></path>
</g>
<!-- <path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23-->
<!-- 9-15.62L9-15.62Q7.65-14.08-->
<!-- 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17-->
<!-- 11.81-4.93Q12.87-4.68-->
<!-- 14.76-4.68L14.76-4.68L21.24-4.68L21.24-->
<!-- 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35-->
<!-- 4.32-3.01L4.32-3.01Q1.48-6.17-->
<!-- 1.48-11.03L1.48-11.03Q1.48-16.88-->
<!-- 4.86-19.75L4.86-19.75Q6.21-20.93-->
<!-- 8.10-21.42Q9.99-21.91-->
<!-- 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48-->
<!-- 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"-->
<!-- fill="#2c3e50"-->
<!-- transform="translate(300, 270) scale(4,4)"-->
<!-- ></path>-->
<text x="300" y="100" font-size="50" font-weight="bold">让你的证书永不过期</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -1,17 +0,0 @@
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="500" height="500" viewBox="0 0 500.000000 500.000000"
>
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
fill="#2c3e50"
transform="translate(124, 60) scale(4,4)"
></path>
<path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23 9-15.62L9-15.62Q7.65-14.08 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17 11.81-4.93Q12.87-4.68 14.76-4.68L14.76-4.68L21.24-4.68L21.24 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35 4.32-3.01L4.32-3.01Q1.48-6.17 1.48-11.03L1.48-11.03Q1.48-16.88 4.86-19.75L4.86-19.75Q6.21-20.93 8.10-21.42Q9.99-21.91 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"
fill="#2c3e50"
transform="translate(28, 430) scale(4,4)"
></path>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1,7 +1,106 @@
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="500" height="500" viewBox="0 0 500.000000 500.000000"
>
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
transform="translate(70, 76) scale(6,6)"
></path>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg"
width="210mm"
height="210mm"
viewBox="0 0 210 210"
version="1.1"
id="svg8"
>
<g id="layer1" style="display:inline">
<path
style="fill:#002255;stroke:none;stroke-width:0.625348"
d="M 35.587501,69.766667 V 59.766664 h 70.000109 69.99991 v 10.000003 9.999997 H 105.58761 35.587501 Z"
id="path12" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2"
width="32.244232"
height="20"
x="71.506088"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-8"
width="32.244232"
height="20"
x="107.42467"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-5-8"
width="32.244232"
height="20"
x="143.34325"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-4"
width="32.244232"
height="20"
x="71.506088"
y="129.82079" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-8-3"
width="32.244232"
height="20"
x="107.42467"
y="129.82079" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-5-8-2"
width="32.244232"
height="20"
x="143.34325"
y="129.82079" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-7"
width="32.244232"
height="20"
x="35.587502"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-4-0"
width="32.244232"
height="20"
x="35.587502"
y="129.82079" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-9"
width="32.244232"
height="20"
x="71.506088"
y="82.941666" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-8-37"
width="32.244232"
height="20"
x="107.42467"
y="82.941666" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-5-8-4"
width="32.244232"
height="20"
x="143.34325"
y="82.941666" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-7-1"
width="32.244232"
height="20"
x="35.587502"
y="82.941666" />
</g>
<polygon
points="75.3,174.4 103.1,103.6 79.8,103.6 112.6,41.3 156.4,41.3 129.9,90.5 148.1,90.5 "
fill="#f6cc00"
id="polygon276"
transform="matrix(1.0930933,0,0,0.99853202,-17.517362,-0.52287941)" />
</svg>

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -1,108 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg"
width="210mm"
height="210mm"
viewBox="0 0 210 210"
version="1.1"
id="svg8">
<defs
id="defs2" />
<g
id="layer1"
style="display:inline">
<path
style="fill:#002255;stroke:none;stroke-width:0.625348"
d="M 35.587501,69.766667 V 59.766664 h 70.000109 69.99991 v 10.000003 9.999997 H 105.58761 35.587501 Z"
id="path12" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2"
width="32.244232"
height="20"
x="71.506088"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-8"
width="32.244232"
height="20"
x="107.42467"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-5-8"
width="32.244232"
height="20"
x="143.34325"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-4"
width="32.244232"
height="20"
x="71.506088"
y="129.82079" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-8-3"
width="32.244232"
height="20"
x="107.42467"
y="129.82079" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-5-8-2"
width="32.244232"
height="20"
x="143.34325"
y="129.82079" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-7"
width="32.244232"
height="20"
x="35.587502"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-4-0"
width="32.244232"
height="20"
x="35.587502"
y="129.82079" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-9"
width="32.244232"
height="20"
x="71.506088"
y="82.941666" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-8-37"
width="32.244232"
height="20"
x="107.42467"
y="82.941666" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-5-8-4"
width="32.244232"
height="20"
x="143.34325"
y="82.941666" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-7-1"
width="32.244232"
height="20"
x="35.587502"
y="82.941666" />
</g>
<polygon
points="75.3,174.4 103.1,103.6 79.8,103.6 112.6,41.3 156.4,41.3 129.9,90.5 148.1,90.5 "
fill="#f6cc00"
id="polygon276"
transform="matrix(1.0930933,0,0,0.99853202,-17.517362,-0.52287941)" />
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -1,44 +0,0 @@
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="800" height="300" viewBox="0 0 800.000000 300.000000"
>
<g fill="#fff">
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
transform="translate(40, 40) scale(4,4)"
></path>
<g transform="translate(280, 260) scale(2,2)">
<path d="M28.95-58.70L49.98-58.70L49.98-48.22L33.70-48.22Q27.37-48.22 24.46-47.34Q21.56-46.46 19.62-43.91L19.62-43.91Q18.30-42.15 17.82-40.39Q17.34-38.63 16.98-34.41L16.98-34.41L49.98-34.41L49.98-23.94L16.98-23.94Q17.69-16.37 21.47-13.42Q25.26-10.47 34.32-10.47L34.32-10.47L49.98-10.47L49.98 0L33.70 0Q27.10 0 22.09-0.79L22.09-0.79Q14.17-2.11 9.50-7.74L9.50-7.74Q2.82-15.84 2.82-29.66L2.82-29.66Q2.82-44.97 12.23-53.50L12.23-53.50Q15.49-56.41 19.14-57.55Q22.79-58.70 28.95-58.70L28.95-58.70Z"
transform="translate(0 0) "
></path>
<path d="M28.51-22.26L18.48-22.26L18.48 0L5.98 0L5.98-58.70L34.67-58.70Q46.99-58.70 51.83-55.53L51.83-55.53Q55.18-53.42 56.98-49.94Q58.78-46.46 58.78-42.33L58.78-42.33Q58.78-33.97 54.56-29.39L54.56-29.39Q51.92-26.66 47.61-25.26L47.61-25.26Q51.04-24.02 52.80-22.66Q54.56-21.30 55.97-18.66L55.97-18.66Q57.02-16.54 57.51-14.61Q57.99-12.67 58.26-8.89L58.26-8.89Q58.78-2.55 59.66 0L59.66 0L45.67 0Q45.06-2.02 44.35-8.36L44.35-8.36Q43.91-13.46 42.55-16.19Q41.18-18.92 38.46-20.50L38.46-20.50Q35.02-22.35 28.51-22.26L28.51-22.26ZM18.48-48.22L18.48-32.74L35.99-32.74Q40.39-32.74 42.24-34.06L42.24-34.06Q45.06-35.99 45.06-40.83L45.06-40.83Q45.06-46.20 40.83-47.70L40.83-47.70Q39.34-48.22 35.99-48.22L35.99-48.22L18.48-48.22Z"
transform="translate(58.855999999999995 0) "
></path>
<path d="M19.01 0L19.01-48.22L0.35-48.22L0.35-58.70L50.95-58.70L50.95-48.22L31.50-48.22L31.50 0L19.01 0Z"
transform="translate(126.68799999999999 0) "
></path>
<path d="M5.98 0L5.98-58.70L30.89-58.70Q40.22-58.70 45.32-56.85L45.32-56.85Q54.74-53.42 57.90-44.26L57.90-44.26Q60.28-37.22 60.28-29.22L60.28-29.22Q60.28-21.30 57.99-14.26L57.99-14.26Q55.70-7.04 50.42-3.61L50.42-3.61Q47.08-1.50 43.08-0.75Q39.07 0 30.89 0L30.89 0L5.98 0ZM30.89-48.22L18.48-48.22L18.48-10.47L30.89-10.47Q39.07-10.47 42.24-14.08L42.24-14.08Q44.18-16.37 45.36-20.50Q46.55-24.64 46.55-29.30L46.55-29.30Q46.55-34.50 45.14-38.81Q43.74-43.12 41.45-45.23L41.45-45.23Q38.10-48.22 30.89-48.22L30.89-48.22Z"
transform="translate(183.07999999999998 0) "
></path>
</g>
<!-- <path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23-->
<!-- 9-15.62L9-15.62Q7.65-14.08-->
<!-- 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17-->
<!-- 11.81-4.93Q12.87-4.68-->
<!-- 14.76-4.68L14.76-4.68L21.24-4.68L21.24-->
<!-- 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35-->
<!-- 4.32-3.01L4.32-3.01Q1.48-6.17-->
<!-- 1.48-11.03L1.48-11.03Q1.48-16.88-->
<!-- 4.86-19.75L4.86-19.75Q6.21-20.93-->
<!-- 8.10-21.42Q9.99-21.91-->
<!-- 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48-->
<!-- 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"-->
<!-- fill="#2c3e50"-->
<!-- transform="translate(300, 270) scale(4,4)"-->
<!-- ></path>-->
<text x="300" y="100" font-size="50" font-weight="bold">让你的证书永不过期</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -1,106 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg"
width="210mm"
height="210mm"
viewBox="0 0 210 210"
version="1.1"
id="svg8"
>
<g id="layer1" style="display:inline">
<path
style="fill:#002255;stroke:none;stroke-width:0.625348"
d="M 35.587501,69.766667 V 59.766664 h 70.000109 69.99991 v 10.000003 9.999997 H 105.58761 35.587501 Z"
id="path12" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2"
width="32.244232"
height="20"
x="71.506088"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-8"
width="32.244232"
height="20"
x="107.42467"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-5-8"
width="32.244232"
height="20"
x="143.34325"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-4"
width="32.244232"
height="20"
x="71.506088"
y="129.82079" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-8-3"
width="32.244232"
height="20"
x="107.42467"
y="129.82079" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-5-8-2"
width="32.244232"
height="20"
x="143.34325"
y="129.82079" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-7"
width="32.244232"
height="20"
x="35.587502"
y="106.64581" />
<rect
style="fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-4-0"
width="32.244232"
height="20"
x="35.587502"
y="129.82079" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-9"
width="32.244232"
height="20"
x="71.506088"
y="82.941666" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-8-37"
width="32.244232"
height="20"
x="107.42467"
y="82.941666" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-8-5-8-4"
width="32.244232"
height="20"
x="143.34325"
y="82.941666" />
<rect
style="display:inline;fill:#2a7fff;fill-rule:evenodd;stroke-width:0.214311"
id="rect22-2-7-1"
width="32.244232"
height="20"
x="35.587502"
y="82.941666" />
</g>
<polygon
points="75.3,174.4 103.1,103.6 79.8,103.6 112.6,41.3 156.4,41.3 129.9,90.5 148.1,90.5 "
fill="#f6cc00"
id="polygon276"
transform="matrix(1.0930933,0,0,0.99853202,-17.517362,-0.52287941)" />
</svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -1,17 +0,0 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,6 @@
name,mobile
张三,18603040102
李四,18603040103
王五,18603040104
赵六,18603040105
田七,18603040106
1 name mobile
2 张三 18603040102
3 李四 18603040103
4 王五 18603040104
5 赵六 18603040105
6 田七 18603040106

View File

@@ -1,56 +1,69 @@
<template>
<a-config-provider :locale="locale">
<router-view v-if="routerEnabled" />
</a-config-provider>
<AConfigProvider :locale="locale" :theme="tokenTheme">
<fs-form-provider>
<router-view v-if="routerEnabled" />
</fs-form-provider>
</AConfigProvider>
</template>
<script>
<script lang="ts" setup>
import zhCN from "ant-design-vue/es/locale/zh_CN";
import enUS from "ant-design-vue/es/locale/en_US";
import { provide, ref, nextTick } from "vue";
import { usePageStore } from "/src/store/modules/page";
import { useResourceStore } from "/src/store/modules/resource";
import { useSettingStore } from "/@/store/modules/settings";
import 'dayjs/locale/zh-cn';
import 'dayjs/locale/en';
import dayjs from 'dayjs'
export default {
name: "App",
setup() {
//刷新页面方法
const routerEnabled = ref(true);
const locale = ref(zhCN);
async function reload() {
routerEnabled.value = false;
await nextTick();
routerEnabled.value = true;
}
function localeChanged(value) {
console.log("locale changed:", value);
if (value === "zh-cn") {
locale.value = zhCN;
dayjs.locale('zh-cn');
} else if (value === "en") {
locale.value = enUS;
dayjs.locale('en');
}
}
localeChanged('zh-cn')
provide("fn:router.reload", reload);
provide("fn:locale.changed", localeChanged);
import { computed, provide, ref } from "vue";
import "dayjs/locale/zh-cn";
import "dayjs/locale/en";
import dayjs from "dayjs";
import { usePreferences, preferences } from "/@/vben/preferences";
import { useAntdDesignTokens } from "/@/vben/hooks";
import { theme } from "ant-design-vue";
import AConfigProvider from "ant-design-vue/es/config-provider";
defineOptions({
name: "App"
});
//其他初始化
const resourceStore = useResourceStore();
resourceStore.init();
const pageStore = usePageStore();
pageStore.init();
const settingStore = useSettingStore();
settingStore.init();
return {
routerEnabled,
locale
};
//刷新页面方法
const routerEnabled = ref(true);
const locale = ref(zhCN);
async function reload() {
// routerEnabled.value = false;
// await nextTick();
// routerEnabled.value = true;
}
function localeChanged(value: any) {
console.log("locale changed:", value);
if (value === "zh-cn") {
locale.value = zhCN;
dayjs.locale("zh-cn");
} else if (value === "en") {
locale.value = enUS;
dayjs.locale("en");
}
};
}
localeChanged("zh-cn");
provide("fn:router.reload", reload);
provide("fn:locale.changed", localeChanged);
const { isDark } = usePreferences();
const { tokens } = useAntdDesignTokens();
const tokenTheme = computed(() => {
const algorithm = isDark.value ? [theme.darkAlgorithm] : [theme.defaultAlgorithm];
// antd 紧凑模式算法
if (preferences.app.compact) {
algorithm.push(theme.compactAlgorithm);
}
return {
algorithm,
token: tokens
};
});
//其他初始化
// const resourceStore = useResourceStore();
// resourceStore.init();
// const pageStore = usePageStore();
// pageStore.init();
// const settingStore = useSettingStore();
// settingStore.init();
</script>

View File

@@ -12,6 +12,7 @@ export interface UserInfoRes {
id: string | number;
username: string;
nickName: string;
avatar?: string;
}
export interface LoginRes {

View File

@@ -106,8 +106,8 @@ function createService() {
* @description 创建请求方法
* @param {Object} service axios 实例
*/
function createRequestFunction(service) {
return function (config) {
function createRequestFunction(service: any) {
return function (config: any) {
const configDefault = {
headers: {
"Content-Type": get(config, "headers.Content-Type", "application/json")

View File

@@ -48,18 +48,22 @@ export function responseError(data = {}, msg = "请求失败", code = 500) {
* @description 记录和显示错误
* @param {Error} error 错误对象
*/
export function errorLog(error) {
export function errorLog(error: any) {
// 打印到控制台
console.error(error);
let message = error.message;
if (error.response?.data?.message) {
message = error.response.data.message;
}
// 显示提示
uiContext.get().notification.error({ message: error.message });
uiContext.get().notification.error({ message });
}
/**
* @description 创建一个错误
* @param {String} msg 错误信息
*/
export function errorCreate(msg) {
export function errorCreate(msg: any) {
const error = new Error(msg);
errorLog(error);
throw error;

View File

@@ -1,15 +1,18 @@
<template>
<pre class="fs-highlight hljs" v-html="highlightHTML"></pre>
<pre class="fs-highlight hljs" v-html="highlightHTMLRef"></pre>
</template>
<script>
<script lang="ts">
// 相关文档
// https://highlightjs.org/usage/
// http://highlightjs.readthedocs.io/en/latest/api.html#configure-options
import highlight from "highlight.js";
import { ref, watch } from "vue";
import { defineComponent, Ref } from "vue";
import "../highlight-styles/github-gist.css";
import htmlFormat from "./libs/htmlFormat";
export default {
//@ts-ignore
import htmlFormat from "./libs/htmlFormat.js";
export default defineComponent({
name: "FsHighlight",
props: {
code: {
@@ -28,39 +31,37 @@ export default {
default: ""
}
},
data() {
setup(props: any, ctx: any) {
const highlightHTMLRef: Ref = ref("");
watch(
() => {
return props.code;
},
() => {
doHighlight();
},
{
immediate: true
}
);
function doHighlight() {
const code = props.formatHtml ? htmlFormat(props.code) : props.code;
highlightHTMLRef.value = (highlight as any).highlightAuto(code, [props.lang, "html", "javascript", "json", "css", "scss", "less"]).value;
}
return {
highlightHTML: ""
highlightHTMLRef,
doHighlight
};
},
watch: {
code() {
this.highlight();
}
},
mounted() {
this.highlight();
},
methods: {
highlight() {
const code = this.formatHtml ? htmlFormat(this.code) : this.code;
this.highlightHTML = highlight.highlightAuto(code, [
this.lang,
"html",
"javascript",
"json",
"css",
"scss",
"less"
]).value;
}
}
};
});
</script>
<style lang="less">
.fs-highlight {
margin: 0px;
border-radius: 4px;
font-size: 12px;
}
</style>

View File

@@ -1,7 +1,7 @@
import { defineAsyncComponent } from "vue";
const AsyncHighLight = defineAsyncComponent(() => import("./highlight/index.vue"));
export default {
install(app) {
install(app: any) {
app.component("FsHighlight", AsyncHighLight);
}
};

View File

@@ -1,20 +1,13 @@
import { createI18n } from "vue-i18n";
//
import enFsLocale from "@fast-crud/fast-crud/dist/locale/lang/en.js";
import zhFsLocale from "@fast-crud/fast-crud/dist/locale/lang/zh-cn.js";
import en from "./locale/en";
import zh from "./locale/zh_CN";
const messages = {
en: {
label: "English",
// 定义您自己的字典,但是请不要和 `fs` 重复,这样会导致 fast-crud 内部组件的翻译失效.
fs: enFsLocale.fs,
...en
},
"zh-cn": {
label: "简体中文",
// 定义您自己的字典,但是请不要和 `fs` 重复,这样会导致 fast-crud 内部组件的翻译失效.
fs: zhFsLocale.fs,
...zh
}
};

View File

@@ -1,3 +1,8 @@
export default {
app: { crud: { i18n: { name: "name", city: "city", status: "status" } } }
app: { crud: { i18n: { name: "name", city: "city", status: "status" } } },
fs: {
rowHandle: {
title: "Operation"
}
}
};

View File

@@ -5,5 +5,10 @@ export default {
logoutTip: "确认",
logoutMessage: "确定要注销登录吗?"
}
},
fs: {
rowHandle: {
title: "操作列"
}
}
};

View File

@@ -1,56 +0,0 @@
<template>
<div class="fs-contentmenu-list" @click="rowClick">
<div
v-for="item in menulist"
:key="item.value"
:data-value="item.value"
class="fs-contentmenu-item"
flex="cross:center main:center"
>
<d2-icon v-if="item.icon" :name="item.icon" />
<div class="fs-contentmenu-item-title" flex-box="1">
{{ item.title }}
</div>
</div>
</div>
</template>
<script>
export default {
name: "FsContextmenuList",
props: {
menulist: {
type: Array,
default: () => []
}
},
methods: {
rowClick(event) {
let target = event.target;
while (!target.dataset.value) {
target = target.parentNode;
}
this.$emit("rowClick", target.dataset.value);
}
}
};
</script>
<style lang="less">
.fs-contentmenu-list {
.fs-contentmenu-item {
padding: 8px 20px 8px 15px;
margin: 0;
font-size: 14px;
color: #606266;
cursor: pointer;
&:hover {
background: #ecf5ff;
color: #66b1ff;
}
.fs-contentmenu-item-title {
margin-left: 10px;
}
}
}
</style>

View File

@@ -1,68 +0,0 @@
<template>
<div v-show="flag" class="fs-contextmenu" :style="style">
<slot />
</div>
</template>
<script>
export default {
name: "FsContextmenu",
props: {
visible: {
type: Boolean,
default: false
},
x: {
type: Number,
default: 0
},
y: {
type: Number,
default: 0
}
},
computed: {
flag: {
get() {
if (this.visible) {
// 注册全局监听事件 [ 目前只考虑鼠标解除触发 ]
window.addEventListener("mousedown", this.watchContextmenu);
}
return this.visible;
},
set(newVal) {
this.$emit("update:visible", newVal);
}
},
style() {
return {
left: this.x + "px",
top: this.y + "px",
display: this.visible ? "block" : "none "
};
}
},
mounted() {
// 将菜单放置到body下
document.querySelector("body").appendChild(this.$el);
},
methods: {
watchContextmenu(event) {
if (!this.$el.contains(event.target) || event.button !== 0) this.flag = false;
window.removeEventListener("mousedown", this.watchContextmenu);
}
}
};
</script>
<style>
.fs-contextmenu {
position: absolute;
padding: 5px 0;
z-index: 2018;
background: #fff;
border: 1px solid #cfd7e5;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style>

View File

@@ -19,17 +19,17 @@
</a-dropdown>
</template>
<script>
<script lang="ts">
import i18n from "../../../i18n";
import { computed, inject } from "vue";
import _ from "lodash-es";
import { forEach } from "lodash-es";
export default {
name: "FsLocale",
setup() {
const languages = computed(() => {
const map = i18n.global.messages?.value || {};
const list = [];
_.forEach(map, (item, key) => {
const map: any = i18n.global.messages?.value || {};
const list: any = [];
forEach(map, (item, key) => {
list.push({
key,
label: item.label
@@ -41,12 +41,12 @@ export default {
return i18n.global.locale.value;
});
const routerReload = inject("fn:router.reload");
const localeChanged = inject("fn:locale.changed");
const changeLocale = (change) => {
const routerReload: any = inject("fn:router.reload");
const localeChanged: any = inject("fn:locale.changed");
const changeLocale = (change: any) => {
i18n.global.locale.value = change.key;
routerReload();
localeChanged(change.key)
localeChanged(change.key);
};
return {
languages,

View File

@@ -1,14 +1,13 @@
import { useRoute, useRouter } from "vue-router";
import { ref, watch, onMounted, onUnmounted, resolveComponent, nextTick, defineComponent } from "vue";
import getEachDeep from "deepdash-es/getEachDeep";
import _ from "lodash-es";
import { forEach } from "lodash-es";
import BScroll from "better-scroll";
import "./index.less";
const eachDeep = getEachDeep(_);
import { utils } from "@fast-crud/fast-crud";
function useBetterScroll(enabled = true) {
let bsRef = ref(null);
let asideMenuRef = ref();
const bsRef = ref(null);
const asideMenuRef = ref();
let onOpenChange = () => {};
if (enabled) {
@@ -71,7 +70,7 @@ export default defineComponent({
scroll: {}
},
setup(props, ctx) {
async function open(path) {
async function open(path: any) {
if (path == null) {
return;
}
@@ -90,23 +89,24 @@ export default defineComponent({
console.error("导航失败", e);
}
}
function onSelect(item) {
function onSelect(item: any) {
open(item.key);
}
const FsIcon = resolveComponent("FsIcon");
const fsIcon = resolveComponent("FsIcon");
const buildMenus = (children) => {
const slots = [];
const buildMenus = (children: any) => {
const slots: any = [];
if (children == null) {
return slots;
}
for (let sub of children) {
const title = () => {
for (const sub of children) {
const title: any = () => {
if (sub?.meta?.icon) {
// @ts-ignore
return (
<div class={"menu-item-title"}>
<FsIcon class={"anticon"} icon={sub.meta.icon} />
<fsIcon class={"anticon"} icon={sub.meta.icon} />
<span>{sub.title}</span>
</div>
);
@@ -147,21 +147,21 @@ export default defineComponent({
const route = useRoute();
const router = useRouter();
function openSelectedParents(fullPath) {
function openSelectedParents(fullPath: any) {
if (!props.expandSelected) {
return;
}
if (props.menus == null) {
return;
}
const keys = [];
const keys: any = [];
let changed = false;
eachDeep(props.menus, (value, key, parent, context) => {
utils.deepdash.forEachDeep(props.menus, (value: any, key: any, parent: any, context: any) => {
if (value == null) {
return;
}
if (value.path === fullPath) {
_.forEach(context.parents, (item) => {
forEach(context.parents, (item) => {
if (item.value instanceof Array) {
return;
}
@@ -170,7 +170,7 @@ export default defineComponent({
}
});
if (keys.length > 0) {
for (let key of keys) {
for (const key of keys) {
if (openKeys.value.indexOf(key) === -1) {
openKeys.value.push(key);
changed = true;
@@ -180,7 +180,7 @@ export default defineComponent({
return changed;
}
const { asideMenuRef, onOpenChange } = useBetterScroll(props.scroll);
const { asideMenuRef, onOpenChange } = useBetterScroll(props.scroll as any);
watch(
() => {

View File

@@ -5,7 +5,7 @@
</div>
</template>
<script>
<script lang="ts">
import { defineComponent, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
export default defineComponent({
@@ -22,8 +22,8 @@ export default defineComponent({
},
{ immediate: true }
);
const middle = "/fast-crud/fs-admin-antdv/tree/main/src/views";
function goSource(prefix) {
const middle = "/fast-crud/fs-admin-antdv4/blob/main/src/views";
function goSource(prefix: any) {
const path = router.currentRoute.value.fullPath;
window.open(prefix + middle + path + "/index.vue");
}
@@ -40,6 +40,7 @@ export default defineComponent({
position: fixed;
right: 3px;
bottom: 20px;
z-index: 1000;
.fs-source-link {
text-align: left;
cursor: pointer;

View File

@@ -2,22 +2,8 @@
<div class="fs-multiple-page-control-group">
<div class="fs-multiple-page-control-content">
<div class="fs-multiple-page-control-content-inner">
<a-tabs
class="fs-multiple-page-control fs-multiple-page-sort"
:active-key="page.getCurrent"
type="editable-card"
hide-add
@tabClick="handleClick"
@edit="handleTabEdit"
@contextmenu="handleContextmenu"
>
<a-tab-pane
v-for="item in page.getOpened"
:key="item.fullPath"
:tab="item.meta?.title || '未命名'"
:name="item.fullPath"
:closable="isTabClosable(item)"
/>
<a-tabs class="fs-multiple-page-control fs-multiple-page-sort" :active-key="page.getCurrent" type="editable-card" hide-add @tab-click="handleClick" @edit="handleTabEdit">
<a-tab-pane v-for="item in page.getOpened" :key="item.fullPath" :tab="item.meta?.title || '未命名'" :name="item.fullPath" :closable="isTabClosable(item)" />
</a-tabs>
<!-- <fs-contextmenu v-model:visible="contextmenuFlag" :x="contentmenuX" :y="contentmenuY">-->
<!-- <fs-contextmenu-list-->
@@ -30,10 +16,10 @@
<div class="fs-multiple-page-control-btn">
<a-dropdown-button class="control-btn-dropdown" split-button @click="closeAll">
<span class="iconify" data-icon="ion:close-circle" data-inline="false"></span>
<fs-icon icon="ion:close-circle"></fs-icon>
<template #icon><DownOutlined /></template>
<template #overlay>
<a-menu @click="(command) => handleControlItemClick(command)">
<a-menu @click="(command: any) => handleControlItemClick(command)">
<a-menu-item key="left">
<fs-icon name="arrow-left" class="fs-mr-10" />
关闭左侧
@@ -57,8 +43,7 @@
</div>
</template>
<script>
import Sortable from "sortablejs";
<script lang="ts">
import { usePageStore } from "../../../store/modules/page";
import { computed } from "vue";
export default {
@@ -119,14 +104,14 @@ export default {
* @description 计算某个标签页是否可关闭
* @param {Object} page 其中一个标签页
*/
isTabClosable(page) {
isTabClosable(page: any) {
return page.name !== "index";
},
/**
* @description 右键菜单功能点击
* @param {Object} event 事件
*/
handleContextmenu(event) {
handleContextmenu(event: any) {
let target = event.target;
// fix https://github.com/fs-projects/fs-admin/issues/54
let flag = false;
@@ -148,7 +133,7 @@ export default {
* @description 右键菜单的 row-click 事件
* @param {String} command 事件类型
*/
contextmenuClick(command) {
contextmenuClick(command: any) {
this.handleControlItemClick(command, this.tagName);
},
/**
@@ -156,7 +141,7 @@ export default {
* @param {String} command 事件类型
* @param {String} tagName tab 名称
*/
handleControlItemClick(command, tagName = null) {
handleControlItemClick(command: any, tagName: any = null) {
//if (tagName) this.contextmenuFlag = false;
const params = { pageSelect: tagName };
switch (command.key) {
@@ -182,9 +167,9 @@ export default {
* @param {object} tab 标签
* @param {object} event 事件
*/
handleClick(tab) {
handleClick(tab: any) {
// 找到点击的页面在 tag 列表里是哪个
const page = this.page.getOpened.find((page) => page.fullPath === tab);
const page = this.page.getOpened.find((page: any) => page.fullPath === tab);
if (page) {
const { name, params, query } = page;
this.$router.push({ name, params, query });
@@ -194,12 +179,12 @@ export default {
* @description 点击 tab 上的删除按钮触发这里
* @param {String} tagName tab 名称
*/
handleTabEdit(tagName, action) {
handleTabEdit(tagName: any, action: any) {
if (action === "remove") {
this.close({ tagName });
}
}
}
} as any
};
</script>
<style lang="less">
@@ -217,6 +202,11 @@ export default {
}
//antdv
.fs-multiple-page-control-group {
.ant-tabs-tab-remove {
display: flex;
justify-content: center;
align-items: center;
}
.ant-tabs-bar {
margin: 0;
border-bottom: 1px solid #f0f0f0;

View File

@@ -14,7 +14,7 @@
</div>
</template>
<script>
<script lang="ts">
import { defineComponent, ref } from "vue";
const colorListDefine = [
{
@@ -54,13 +54,14 @@ export default defineComponent({
name: "FsThemeColorPicker",
props: {
primaryColor: {
type: String,
default: "#1890ff"
}
},
emits: ["change"],
setup(props, ctx) {
const colorList = ref(colorListDefine);
function changeColor(color) {
function changeColor(color: any) {
ctx.emit("change", color);
}
return {

View File

@@ -1,23 +1,13 @@
<template>
<div class="fs-theme" @click="show()">
<fs-iconify icon="ion:sparkles-outline" />
<a-drawer
v-model:visible="visible"
title="主题设置"
placement="right"
width="350px"
:closable="false"
@after-visible-change="afterVisibleChange"
>
<fs-theme-color-picker
:primary-color="setting.getTheme.primaryColor"
@change="setting.setPrimaryColor"
></fs-theme-color-picker>
<a-drawer v-model:open="visible" title="主题设置" placement="right" width="350px" :closable="false" @after-open-change="afterVisibleChange">
<fs-theme-color-picker :primary-color="setting.themeConfig?.colorPrimary" @change="setting.setPrimaryColor"></fs-theme-color-picker>
</a-drawer>
</div>
</template>
<script>
<script lang="ts">
import { ref, defineComponent } from "vue";
import FsThemeColorPicker from "./color-picker.vue";
import { useSettingStore } from "/@/store/modules/settings";

View File

@@ -0,0 +1,44 @@
<template>
<div class="fs-theme-mode">
<a-switch :checked="setting.themeConfig.mode === 'dark'" @update:checked="onChange">
<template #checkedChildren>
<fs-iconify icon="ion:moon" />
</template>
<template #unCheckedChildren>
<fs-iconify icon="ion:sunny" />
</template>
</a-switch>
</div>
</template>
<script lang="ts">
import { ref, defineComponent } from "vue";
import { useSettingStore } from "/@/store/modules/settings";
export default defineComponent({
name: "FsThemeModeSet",
components: {},
setup() {
const setting = useSettingStore();
const onChange = (checked: boolean) => {
if (checked) {
setting.setDarkMode("dark");
} else {
setting.setDarkMode("light");
}
};
return {
setting,
onChange
};
}
});
</script>
<style lang="less">
.fs-theme-mode {
display: inline-flex;
justify-content: center;
align-items: center;
}
</style>

View File

@@ -10,7 +10,7 @@
</template>
</a-dropdown>
</template>
<script>
<script lang="ts">
import { defineComponent } from "vue";
import { useUserStore } from "/src/store/modules/user";
import { Modal } from "ant-design-vue";

View File

@@ -0,0 +1,50 @@
<script lang="ts" setup>
import { BasicLayout, LockScreen, UserDropdown } from "/@/vben/layouts";
import FsSourceLink from "./components/source-link/index.vue";
import { computed } from "vue";
import { VBEN_DOC_URL } from "/@/vben/constants";
import { BookOpenText } from "/@/vben/icons";
import { preferences } from "/@/vben/preferences";
import { useAccessStore } from "/@/vben/stores";
import { openWindow } from "/@/vben/utils";
import { $t } from "/@/vben/locales";
import { useUserStore } from "/@/store/modules/user";
const userStore = useUserStore();
const accessStore = useAccessStore();
const menus = computed(() => [
// {
// handler: () => {
// openWindow(VBEN_DOC_URL, {
// target: "_blank"
// });
// },
// icon: BookOpenText,
// text: $t("ui.widgets.document")
// }
]);
const avatar = computed(() => {
return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
});
async function handleLogout() {
await userStore.logout(true);
}
</script>
<template>
<BasicLayout @clear-preferences-and-logout="handleLogout">
<template #user-dropdown>
<UserDropdown :avatar :menus :text="userStore.userInfo?.nickName" description="development@handsfree.work" tag-text="Pro" @logout="handleLogout" />
</template>
<template #lock-screen>
<LockScreen :avatar @to-login="handleLogout" />
</template>
<template #extra>
<FsSourceLink />
</template>
</BasicLayout>
</template>

View File

@@ -1,9 +1,9 @@
<template xmlns:w="http://www.w3.org/1999/xhtml">
<template>
<a-layout class="fs-framework">
<a-layout-sider v-model:collapsed="asideCollapsed" :trigger="null" collapsible>
<div class="header-logo">
<img src="/images/logo/rect-black.svg" />
<span v-if="!asideCollapsed" class="title">FsAdmin</span>
<img :src="envRef.LOGO_PATH" />
<span v-if="!asideCollapsed" class="title">{{ envRef.TITLE }}</span>
</div>
<div class="aside-menu">
<fs-menu :scroll="true" :menus="asideMenus" :expand-selected="!asideCollapsed" />
@@ -31,9 +31,18 @@
<!-- Button-->
<!-- </button>-->
<fs-menu class="header-menu" mode="horizontal" :expand-selected="false" :selectable="false" :menus="headerMenus" />
<fs-locale class="btn" />
<!-- <fs-theme-set class="btn" />-->
<fs-user-info class="btn" />
<div class="header-btn">
<fs-locale />
</div>
<!-- <div class="header-btn">-->
<!-- <fs-theme-mode-set />-->
<!-- </div>-->
<div class="header-btn">
<fs-theme-set />
</div>
<div class="header-btn">
<fs-user-info />
</div>
</div>
</a-layout-header>
<fs-tabs></fs-tabs>
@@ -58,7 +67,7 @@
</a-layout>
</template>
<script>
<script lang="ts">
import { computed, onErrorCaptured, ref } from "vue";
import FsMenu from "./components/menu/index.jsx";
import FsLocale from "./components/locale/index.vue";
@@ -69,11 +78,12 @@ import { useResourceStore } from "../store/modules/resource";
import { usePageStore } from "/@/store/modules/page";
import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons-vue";
import FsThemeSet from "/@/layout/components/theme/index.vue";
import { notification } from "ant-design-vue";
import { env } from "../utils/util.env";
import FsThemeModeSet from "./components/theme/mode-set.vue";
export default {
name: "LayoutFramework",
// eslint-disable-next-line vue/no-unused-components
components: { FsThemeSet, MenuFoldOutlined, MenuUnfoldOutlined, FsMenu, FsLocale, FsSourceLink, FsUserInfo, FsTabs },
components: { FsThemeSet, MenuFoldOutlined, MenuUnfoldOutlined, FsMenu, FsLocale, FsSourceLink, FsUserInfo, FsTabs, FsThemeModeSet },
setup() {
const resourceStore = useResourceStore();
const frameworkMenus = computed(() => {
@@ -95,11 +105,13 @@ export default {
}
onErrorCaptured((e) => {
console.error("ErrorCaptured:", e);
notification.error({ message: e.message });
// notification.error({ message: e.message });
//阻止错误向上传递
return false;
});
const version = ref(import.meta.env.VITE_APP_VERSION);
const envRef = ref(env);
return {
version,
frameworkMenus,
@@ -107,7 +119,8 @@ export default {
asideMenus,
keepAlive,
asideCollapsed,
asideCollapsedToggle
asideCollapsedToggle,
envRef
};
}
};
@@ -152,6 +165,11 @@ export default {
background: #f6f6f6;
display: flex;
justify-content: space-between;
> div {
height: auto;
padding: 5px;
}
}
.header-buttons {
display: flex;
@@ -160,11 +178,16 @@ export default {
cursor: pointer;
padding: 0 10px;
}
height: 100%;
& > .btn {
& > .header-btn {
display: inline-flex;
justify-content: center;
align-items: center;
height: 100%;
//border-bottom: 1px solid rgba(255, 255, 255, 0);
&:hover {
background-color: #fff;
color: @primary-color;
}
}
}

View File

@@ -5,10 +5,10 @@
<div class="user-layout-content">
<div class="top flex flex-col items-center justify-center">
<div class="header flex flex-row items-center">
<img src="/images/logo/rect-black.svg" class="logo" alt="logo" />
<span class="title">FsAdmin</span>
<img :src="envRef.LOGO_PATH" class="logo" alt="logo" />
<span class="title">{{ envRef.TITLE }}</span>
</div>
<div class="desc">fast-crud开发crud快如闪电</div>
<div class="desc">{{ envRef.SLOGAN }}</div>
</div>
<router-view />
@@ -19,15 +19,24 @@
<a href="_self">隐私</a>
<a href="_self">条款</a>
</div>
<div class="copyright">Copyright &copy; 2021 Greper</div>
<div class="copyright">{{ envRef.COPYRIGHT }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
<script lang="ts">
import { env } from "/@/utils/util.env";
import { ref } from "vue";
export default {
name: "LayoutOutside"
name: "LayoutOutside",
setup() {
const envRef = ref(env);
return {
envRef
};
}
};
</script>
@@ -51,6 +60,8 @@ export default {
background-size: 100%;
//padding: 50px 0 84px;
position: relative;
display: flex;
flex-direction: column;
.user-layout-lang {
width: 100%;
@@ -75,7 +86,10 @@ export default {
.top {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.header {
height: 44px;
line-height: 44px;

View File

@@ -1,3 +1,10 @@
<template>
<router-view />
<router-view> </router-view>
</template>
<!--<script lang="ts" setup>-->
<!--import { usePageStore } from "/@/store/modules/page";-->
<!--const pageStore = usePageStore();-->
<!--const keepAlive = pageStore.keepAlive;-->
<!--</script>-->

View File

@@ -1,23 +1,43 @@
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import Antd from "ant-design-vue";
import "ant-design-vue/dist/antd.less";
// import "virtual:windi.css";
// import Antd from "ant-design-vue";
import Antd from "./plugin/antdv-async/index";
import "./style/common.less";
import "./mock";
import i18n from "./i18n";
import store from "./store";
import components from "./components";
import router from "./router";
import plugin from "./plugin/";
// 正式项目请删除mock避免影响性能
import "./mock";
import { setupVben } from "./vben";
import { util } from "/@/utils";
import { initPreferences } from "/@/vben/preferences";
// @ts-ignore
const app = createApp(App);
// 尽量
app.use(Antd);
app.use(router);
app.use(i18n);
app.use(store);
app.use(components);
app.use(plugin, { i18n });
app.mount("#app");
async function bootstrap() {
const app = createApp(App);
// app.use(Antd);
app.use(Antd);
await setupVben(app);
app.use(router);
app.use(i18n);
// app.use(store);
app.use(components);
app.use(plugin, { i18n });
const envMode = util.env.MODE;
const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${envMode}`;
// app偏好设置初始化
await initPreferences({
namespace,
overrides: {
app: {
name: import.meta.env.VITE_APP_TITLE
}
}
});
app.mount("#app");
}
bootstrap();

View File

@@ -1,7 +1,11 @@
import _ from "lodash-es";
function copyList(originList, newList, options, parentId) {
import { cloneDeep, mergeWith, isArray } from "lodash-es";
function copyList(originList: any, newList: any, options: any, parentId?: any) {
for (const item of originList) {
const newItem = { ...item, parentId };
const newItem: any = cloneDeep(item);
if (parentId != null && newItem.parentId == null) {
newItem.parentId = parentId;
}
newItem.id = ++options.idGenerator;
newList.push(newItem);
if (item.children != null) {
@@ -11,7 +15,7 @@ function copyList(originList, newList, options, parentId) {
}
}
function delById(req, list) {
function delById(req: any, list: any) {
for (let i = 0; i < list.length; i++) {
const item = list[i];
console.log("remove i", i, req, req.params.id, item.id);
@@ -26,27 +30,38 @@ function delById(req, list) {
}
}
function findById(id, list) {
function findById(id: any, list: any) {
for (const item of list) {
if (item.id === id) {
return item;
}
if (item.children != null && item.children.length > 0) {
const sub = findById(id, item.children);
const sub: any = findById(id, item.children);
if (sub != null) {
return sub;
}
}
}
}
export default {
function findByIds(ids: any[], list: any) {
const res = [];
for (const id of ids) {
const item = findById(id, list);
if (item != null) {
res.push(item);
}
}
console.log("findbyids", res, ids);
return res;
}
const mockUtil: any = {
findById,
buildMock(options) {
buildMock(options: any) {
const name = options.name;
if (options.copyTimes == null) {
options.copyTimes = 29;
}
const list = [];
const list: any = [];
for (let i = 0; i < options.copyTimes; i++) {
copyList(options.list, list, options);
}
@@ -55,7 +70,7 @@ export default {
{
path: "/mock/" + name + "/page",
method: "get",
handle(req) {
handle(req: any) {
let data = [...list];
let limit = 20;
let offset = 0;
@@ -65,9 +80,10 @@ export default {
item.lazy = false;
}
}
let orderProp, orderAsc;
let orderProp: any, orderAsc: any;
if (req && req.body) {
const { page, query, sort } = req.body;
const { page, sort } = req.body;
let query = req.body.query;
if (page.limit != null) {
limit = parseInt(page.limit);
}
@@ -76,9 +92,9 @@ export default {
}
orderProp = sort.prop;
orderAsc = sort.asc;
query = query || {};
if (Object.keys(query).length > 0) {
data = list.filter((item) => {
data = list.filter((item: any) => {
let allFound = true; // 是否所有条件都符合
for (const key in query) {
// 判定某一个条件
@@ -169,16 +185,10 @@ export default {
{
path: "/mock/" + name + "/get",
method: "get",
handle(req) {
handle(req: any) {
let id = req.params.id;
id = parseInt(id);
let current = null;
for (const item of list) {
if (item.id === id) {
current = item;
break;
}
}
const current = findById(id, list);
return {
code: 0,
msg: "success",
@@ -186,31 +196,44 @@ export default {
};
}
},
{
path: "/mock/" + name + "/byIds",
method: "post",
handle(req: any) {
const ids = req.body.ids;
const res = findByIds(ids, list);
return {
code: 0,
msg: "success",
data: res
};
}
},
{
path: "/mock/" + name + "/add",
method: "post",
handle(req) {
handle(req: any) {
req.body.id = ++options.idGenerator;
list.unshift(req.body);
return {
code: 0,
msg: "success",
data: req.body.id
data: cloneDeep(req.body)
};
}
},
{
path: "/mock/" + name + "/update",
method: "post",
handle(req) {
handle(req: any): any {
const item = findById(req.body.id, list);
if (item) {
_.mergeWith(item, req.body, (objValue, srcValue) => {
mergeWith(item, req.body, (objValue, srcValue) => {
if (srcValue == null) {
return;
}
// 如果被合并对象为数组,则直接被覆盖对象覆盖,只要覆盖对象不为空
if (_.isArray(objValue)) {
if (isArray(objValue)) {
return srcValue;
}
});
@@ -225,7 +248,7 @@ export default {
{
path: "/mock/" + name + "/delete",
method: "post",
handle(req) {
handle(req: any): any {
delById(req, list);
return {
code: 0,
@@ -237,7 +260,7 @@ export default {
{
path: "/mock/" + name + "/batchDelete",
method: "post",
handle(req) {
handle(req: any): any {
const ids = req.body.ids;
for (let i = list.length - 1; i >= 0; i--) {
const item = list[i];
@@ -255,7 +278,7 @@ export default {
{
path: "/mock/" + name + "/delete",
method: "post",
handle(req) {
handle(req: any): any {
delById(req, list);
return {
code: 0,
@@ -267,14 +290,72 @@ export default {
{
path: "/mock/" + name + "/all",
method: "post",
handle(req) {
handle(req: any): any {
return {
code: 0,
msg: "success",
data: list
};
}
},
{
path: "/mock/" + name + "/cellUpdate",
method: "post",
handle(req: any): any {
console.log("req", req);
let item = findById(req.body.id, list);
if (item) {
mergeWith(item, { [req.body.key]: req.body.value }, (objValue, srcValue) => {
if (srcValue == null) {
return;
}
// 如果被合并对象为数组,则直接被覆盖对象覆盖,只要覆盖对象不为空
if (isArray(objValue)) {
return srcValue;
}
});
} else {
item = {
id: ++options.idGenerator,
[req.body.key]: req.body.value
};
list.unshift(item);
}
return {
code: 0,
msg: "success",
data: item
};
}
},
{
path: "/mock/" + name + "/columnUpdate",
method: "post",
handle(req: any): any {
for (const item of req.body) {
const item2 = findById(item.id, list);
if (item2) {
mergeWith(item2, item, (objValue, srcValue) => {
if (srcValue == null) {
return;
}
// 如果被合并对象为数组,则直接被覆盖对象覆盖,只要覆盖对象不为空
if (isArray(objValue)) {
return srcValue;
}
});
}
}
return {
code: 0,
msg: "success",
data: null
};
}
}
];
}
};
export default mockUtil;

View File

@@ -1,11 +1,13 @@
import cascaderData from "./cascader-data";
// @ts-ignore
import pcaDataLittle from "./pca-data-little";
// @ts-ignore
import { TreeNodesLazyLoader, getPcaData } from "./pcas-data";
import { cloneDeep } from "lodash-es";
const openStatus = [
{ value: "1", label: "打开", color: "success",icon:"ion:radio-button-on" },
{ value: "1", label: "打开", color: "success", icon: "ion:radio-button-on" },
{ value: "2", label: "停止", color: "cyan" },
{ value: "0", label: "关闭", color: "red",icon:"ion:radio-button-off" }
{ value: "0", label: "关闭", color: "red", icon: "ion:radio-button-off" }
];
const moreOpenStatus = [
@@ -20,11 +22,27 @@ const textStatus = [
{ id: "0", text: "关闭", color: "red" }
];
export function GetTreeChildrenByParentId(parentId) {
let manyStatus = [
{ value: "1", label: "打开", color: "success", icon: "ion:radio-button-on" },
{ value: "2", label: "停止", color: "cyan" },
{ value: "0", label: "关闭", color: "red", icon: "ion:radio-button-off" }
];
let tempManyStatus: any[] = [];
for (let i = 0; i < 100; i++) {
tempManyStatus = tempManyStatus.concat(cloneDeep(manyStatus));
}
manyStatus = tempManyStatus;
let idIndex = 0;
for (const item of manyStatus) {
idIndex++;
item.value = idIndex + "";
}
export function GetTreeChildrenByParentId(parentId: any) {
return TreeNodesLazyLoader.getChildren(parentId);
}
export function GetNodesByValues(values) {
export function GetNodesByValues(values: any) {
return TreeNodesLazyLoader.getNodesByValues(values);
}
@@ -51,6 +69,17 @@ export default [
};
}
},
{
path: "/mock/dicts/ManyOpenStatusEnum",
method: "get",
handle() {
return {
code: 0,
msg: "success",
data: manyStatus
};
}
},
{
path: "/mock/dicts/moreOpenStatusEnum",
method: "get",
@@ -99,7 +128,7 @@ export default [
{
path: "/mock/tree/GetTreeChildrenByParentId",
method: "get",
async handle({ params }) {
async handle({ params }: any) {
const list = await GetTreeChildrenByParentId(params.parentId);
return {
code: 0,
@@ -111,7 +140,7 @@ export default [
{
path: "/mock/tree/GetNodesByValues",
method: "get",
async handle({ params }) {
async handle({ params }: any) {
const list = await GetNodesByValues(params.values);
return {
code: 0,

View File

@@ -1,16 +1,18 @@
import _ from "lodash-es";
import {cloneDeep} from "lodash-es";
export async function getPcasData() {
// @ts-ignore
const pcasData = () => import("china-division/dist/pcas-code.json");
const ret = await pcasData();
return ret.default;
}
export async function getPcaData() {
// @ts-ignore
const pcaData = () => import("china-division/dist/pca-code.json");
const ret = await pcaData();
return ret.default;
}
export const TreeNodesLazyLoader = {
getNodesByValues(values) {
getNodesByValues(values: any) {
console.log("getNodesByValues", values);
if (!(values instanceof Array)) {
values = [values];
@@ -20,7 +22,7 @@ export const TreeNodesLazyLoader = {
for (const value of values) {
const found = this.getNode(data, value);
if (found) {
const target = _.cloneDeep(found);
const target = cloneDeep(found);
delete target.children;
nodes.push(target);
}
@@ -28,20 +30,20 @@ export const TreeNodesLazyLoader = {
return nodes;
});
},
getNode(list, value) {
getNode(list: any, value: any) {
for (const item of list) {
if (item.code === value) {
return item;
}
if (item.children && item.children.length > 0) {
const found = this.getNode(item.children, value);
const found: any = this.getNode(item.children, value);
if (found) {
return found;
}
}
}
},
getChildren(parent) {
getChildren(parent: any) {
return getPcasData().then((data) => {
const list = this.getChildrenByParent(parent, data);
if (list == null) {
@@ -50,7 +52,7 @@ export const TreeNodesLazyLoader = {
return this.cloneAndDeleteChildren(list);
});
},
getChildrenByParent(parentId, tree) {
getChildrenByParent(parentId: any, tree: any) {
if (!parentId) {
// 取第一级
return tree;
@@ -61,7 +63,7 @@ export const TreeNodesLazyLoader = {
}
if (node.children && node.children.length > 0) {
// 递归查找
const list = this.getChildrenByParent(parentId, node.children);
const list: any = this.getChildrenByParent(parentId, node.children);
if (list) {
return list;
}
@@ -69,10 +71,10 @@ export const TreeNodesLazyLoader = {
}
}
},
cloneAndDeleteChildren(list) {
cloneAndDeleteChildren(list: any) {
const newList = [];
for (const node of list) {
const newNode = {};
const newNode: any = {};
Object.assign(newNode, node);
if (newNode.children == null || newNode.children.length === 0) {
newNode.isLeaf = true;

View File

@@ -1,26 +1,30 @@
import { mock } from "../api/service";
import * as tools from "../api/tools";
import _ from "lodash-es";
const commonMocks = import.meta.globEager("./common/mock.*.js");
const apiMocks = import.meta.globEager("../api/modules/*.mock.ts");
const viewMocks = import.meta.globEager("../views/**/mock.js");
import { forEach } from "lodash-es";
import { utils } from "@fast-crud/fast-crud";
// @ts-ignore
const commonMocks: any = import.meta.glob("./common/mock.*.[j|t]s", { eager: true });
// @ts-ignore
const apiMocks: any = import.meta.glob("../api/modules/*.mock.ts", { eager: true });
// @ts-ignore
const viewMocks: any = import.meta.glob("../views/**/mock.[j|t]s", { eager: true });
const list = [];
_.forEach(commonMocks, (value) => {
const list: any = [];
forEach(commonMocks, (value: any) => {
list.push(value.default);
});
_.forEach(apiMocks, (value) => {
forEach(apiMocks, (value) => {
list.push(value.default);
});
_.forEach(viewMocks, (value) => {
forEach(viewMocks, (value) => {
list.push(value.default);
});
list.forEach((apiFile) => {
list.forEach((apiFile: any) => {
for (const item of apiFile) {
mock.onAny(new RegExp(item.path)).reply(async (config) => {
console.log("------------fake request start -------------");
console.log("request:", config);
mock.onAny(new RegExp(item.path)).reply(async (config: any) => {
utils.logger.debug("------------fake request start -------------");
utils.logger.debug("request:", config);
const data = config.data ? JSON.parse(config.data) : {};
const query = config.url.indexOf("?") >= 0 ? config.url.substring(config.url.indexOf("?") + 1) : undefined;
const params = config.params || {};
@@ -37,8 +41,8 @@ list.forEach((apiFile) => {
params: params
};
const ret = await item.handle(req);
console.log("response:", ret);
console.log("------------fake request end-------------");
utils.logger.debug("response:", ret);
utils.logger.debug("------------fake request end-------------");
if (ret.code === 0) {
return tools.responseSuccess(ret.data, ret.msg);
} else {

View File

@@ -0,0 +1,243 @@
import { defineAsyncComponent } from "vue";
import Input from "ant-design-vue/es/input";
import Button from "ant-design-vue/es/button";
import Divider from "ant-design-vue/es/divider";
import Badge from "ant-design-vue/es/badge";
import Empty from "ant-design-vue/es/empty";
import Avatar from "ant-design-vue/es/avatar";
import Steps from "ant-design-vue/es/steps";
import Select from "ant-design-vue/es/select";
import PageHeader from "ant-design-vue/es/page-header";
import Card from "ant-design-vue/es/card";
export default {
install(app: any) {
app.use(Input);
app.use(Button);
app.use(Divider);
app.use(Badge);
app.use(Empty);
app.use(Avatar);
app.use(PageHeader);
app.use(Steps);
app.use(Select);
app.use(Card);
app.component(
"AAutoComplete",
defineAsyncComponent(() => import("ant-design-vue/es/auto-complete/index"))
);
app.component(
"ARadio",
defineAsyncComponent(() => import("ant-design-vue/es/radio/Radio"))
);
app.component(
"ARadioGroup",
defineAsyncComponent(() => import("ant-design-vue/es/radio/Group"))
);
app.component(
"ATable",
defineAsyncComponent(() => import("ant-design-vue/es/table/Table"))
);
app.component(
"AModal",
defineAsyncComponent(() => import("ant-design-vue/es/modal/Modal"))
);
app.component(
"AForm",
defineAsyncComponent(() => import("ant-design-vue/es/form/Form"))
);
app.component(
"AFormItem",
defineAsyncComponent(() => import("ant-design-vue/es/form/FormItem"))
);
app.component(
"AFormItemRest",
defineAsyncComponent(() => import("ant-design-vue/es/form/FormItemContext"))
);
app.component(
"ATabs",
defineAsyncComponent(() => import("ant-design-vue/es/tabs/src/Tabs"))
);
app.component(
"ATabPane",
defineAsyncComponent(() => import("ant-design-vue/es/tabs/src/TabPanelList/TabPane"))
);
app.component(
"ATextarea",
defineAsyncComponent(() => import("ant-design-vue/es/input/TextArea"))
);
app.component(
"AInputNumber",
defineAsyncComponent(() => import("ant-design-vue/es/input-number/index"))
);
app.component(
"ADrawer",
defineAsyncComponent(() => import("ant-design-vue/es/drawer/index"))
);
app.component(
"ASwitch",
defineAsyncComponent(() => import("ant-design-vue/es/switch/index"))
);
app.component(
"AUpload",
defineAsyncComponent(() => import("ant-design-vue/es/upload/index"))
);
app.component(
"ADatePicker",
defineAsyncComponent(() => import("ant-design-vue/es/date-picker/index"))
);
app.component(
"ARangePicker",
defineAsyncComponent(async () => {
const { RangePicker } = await import("ant-design-vue/es/date-picker/index");
return RangePicker;
})
);
app.component(
"ATimePicker",
defineAsyncComponent(() => import("ant-design-vue/es/time-picker/index"))
);
app.component(
"ATag",
defineAsyncComponent(() => import("ant-design-vue/es/tag/index"))
);
app.component(
"AAlert",
defineAsyncComponent(() => import("ant-design-vue/es/alert/index"))
);
app.component(
"AInputAutoComplete",
defineAsyncComponent(() => import("ant-design-vue/es/auto-complete/index"))
);
app.component(
"ACascader",
defineAsyncComponent(() => import("ant-design-vue/es/cascader/index"))
);
app.component(
"ACheckbox",
defineAsyncComponent(() => import("ant-design-vue/es/checkbox"))
);
app.component(
"ACheckboxGroup",
defineAsyncComponent(() => import("ant-design-vue/es/checkbox/Group"))
);
app.component(
"ACol",
defineAsyncComponent(() => import("ant-design-vue/es/col"))
);
app.component(
"ARow",
defineAsyncComponent(() => import("ant-design-vue/es/row"))
);
app.component(
"ADropdown",
defineAsyncComponent(() => import("ant-design-vue/es/dropdown"))
);
app.component(
"AGrid",
defineAsyncComponent(() => import("ant-design-vue/es/grid"))
);
app.component(
"AImage",
defineAsyncComponent(() => import("ant-design-vue/es/image"))
);
app.component(
"APagination",
defineAsyncComponent(() => import("ant-design-vue/es/pagination"))
);
app.component(
"ATooltip",
defineAsyncComponent(() => import("ant-design-vue/es/tooltip"))
);
app.component(
"ATree",
defineAsyncComponent(() => import("ant-design-vue/es/tree"))
);
app.component(
"ATreeSelect",
defineAsyncComponent(() => import("ant-design-vue/es/tree-select"))
);
app.component(
"ATour",
defineAsyncComponent(() => import("ant-design-vue/es/tour"))
);
app.component(
"AMenu",
defineAsyncComponent(() => import("ant-design-vue/es/menu/index"))
);
app.component(
"ASubMenu",
defineAsyncComponent(() => import("ant-design-vue/es/menu/src/SubMenu"))
);
app.component(
"AMenuItem",
defineAsyncComponent(() => import("ant-design-vue/es/menu/src/MenuItem"))
);
app.component(
"AProgress",
defineAsyncComponent(() => import("ant-design-vue/es/progress"))
);
app.component(
"ATimelineItem",
defineAsyncComponent(() => import("ant-design-vue/es/timeline/TimelineItem"))
);
app.component(
"ATimeline",
defineAsyncComponent(() => import("ant-design-vue/es/timeline/Timeline"))
);
app.component(
"APageHeader",
defineAsyncComponent(() => import("ant-design-vue/es/page-header/index"))
);
app.component(
"APopover",
defineAsyncComponent(() => import("ant-design-vue/es/popover"))
);
app.component(
"APopconfirm",
defineAsyncComponent(() => import("ant-design-vue/es/popconfirm"))
);
app.component(
"ACollapse",
defineAsyncComponent(() => import("ant-design-vue/es/collapse"))
);
app.component(
"ADescriptions",
defineAsyncComponent(() => import("ant-design-vue/es/descriptions"))
);
app.component(
"ADescriptionsItem",
defineAsyncComponent(async () => {
const m = await import("ant-design-vue/es/descriptions/");
return m.DescriptionsItem;
})
);
app.component(
"AResult",
defineAsyncComponent(() => import("ant-design-vue/es/result"))
);
app.component(
"ATableSummaryCell",
defineAsyncComponent(() => import("ant-design-vue/es/vc-table/Cell/index"))
);
app.component(
"ATableSummaryRow",
defineAsyncComponent(() => import("ant-design-vue/es/vc-table/Footer/Row"))
);
app.component(
"ATableSummary",
defineAsyncComponent(() => import("ant-design-vue/es/vc-table/Footer/Summary"))
);
app.component(
"ASlider",
defineAsyncComponent(() => import("ant-design-vue/es/slider/index"))
);
}
};

View File

@@ -0,0 +1,33 @@
import { debounce } from "lodash-es";
import { LocalStorage } from "/@/utils/util.storage";
export class ColumnSizeSaver {
save: (key: string, size: number) => void;
constructor() {
this.save = debounce((key: string, size: number) => {
const saveKey = this.getKey();
let data = LocalStorage.get(saveKey);
if (!data) {
data = {};
}
data[key] = size;
LocalStorage.set(saveKey, data);
});
}
getKey() {
const loc = window.location;
const currentUrl = `${loc.pathname}${loc.search}${loc.hash}`;
return `columnSize-${currentUrl}`;
}
get(key: string) {
const saveKey = this.getKey();
const row = LocalStorage.get(saveKey);
return row?.[key];
}
clear() {
const saveKey = this.getKey();
LocalStorage.remove(saveKey);
}
}
export const columnSizeSaver = new ColumnSizeSaver();

View File

@@ -1,20 +1,26 @@
import { request, requestForMock } from "/src/api/service";
import "/src/mock";
import { FastCrud, UseCrudProps, useTypes, setLogger, useColumns, ColumnCompositionProps, MergeColumnPlugin, CrudOptions } from "@fast-crud/fast-crud";
// import "/src/mock";
import { ColumnCompositionProps, CrudOptions, FastCrud, PageQuery, PageRes, setLogger, TransformResProps, useColumns, UseCrudProps, UserPageQuery, useTypes, utils } from "@fast-crud/fast-crud";
import "@fast-crud/fast-crud/dist/style.css";
import { FsExtendsUploader, FsExtendsEditor, FsExtendsJson, FsExtendsCopyable, FsExtendsTime } from "@fast-crud/fast-extends";
import { FsExtendsCopyable, FsExtendsEditor, FsExtendsJson, FsExtendsTime, FsExtendsUploader, FsExtendsInput, FsUploaderS3SignedUrlType, FsUploaderGetAuthContext, FsUploaderAliossSTS } from "@fast-crud/fast-extends";
import "@fast-crud/fast-extends/dist/style.css";
import UiAntdv from "@fast-crud/ui-antdv";
import _ from "lodash-es";
import UiAntdv from "@fast-crud/ui-antdv4";
import "@fast-crud/ui-antdv4/dist/style.css";
import { merge } from "lodash-es";
import { useCrudPermission } from "../permission";
function install(app, options: any = {}) {
import { GetSignedUrl } from "/@/views/crud/component/uploader/s3/api";
import { notification } from "ant-design-vue";
import { usePreferences } from "/@/vben/preferences";
import { columnSizeSaver } from "/@/plugin/fast-crud/column-size-saver";
import { FsEditorCode } from "@fast-crud/editor-code";
function install(app: any, options: any = {}) {
app.use(UiAntdv);
//设置日志级别
setLogger({ level: "debug" });
app.use(FastCrud, {
i18n: options.i18n,
async dictRequest({ url }) {
async dictRequest({ url }: any) {
if (url && url.startsWith("/mock")) {
//如果是crud开头的dict请求视为mock
return await requestForMock({ url, method: "post" });
@@ -23,21 +29,64 @@ function install(app, options: any = {}) {
},
/**
* useCrud时会被执行
* @param contextuseCrud的参数
* @param propsuseCrud的参数
*/
commonOptions(context: UseCrudProps) {
const crudBinding = context.expose?.crudBinding;
commonOptions(props: UseCrudProps): CrudOptions {
utils.logger.debug("commonOptions:", props);
const crudBinding = props.crudExpose?.crudBinding;
const { isMobile } = usePreferences();
const opts: CrudOptions = {
settings: {
plugins: {
mobile: {
enabled: true,
props: {
isMobile: isMobile
}
}
}
},
table: {
scroll: {
x: 960
},
size: "small",
pagination: false,
onResizeColumn: (w, col) => {
crudBinding.value.table.columnsMap[col.key].width = w;
onResizeColumn: (w: number, col: any) => {
if (crudBinding.value?.table?.columnsMap && crudBinding.value?.table?.columnsMap[col.key]) {
crudBinding.value.table.columnsMap[col.key].width = w;
columnSizeSaver.save(col.key, w);
}
},
conditionalRender: {
match(scope) {
if (scope.key === "__blank__") {
return false;
}
//不能用 !scope.value 否则switch组件设置为关之后就消失了
const { value, key, props } = scope;
return !value && key != "_index" && value != false;
},
render() {
return "-";
}
}
},
toolbar: {
export: {
fileType: "excel"
},
columnsFilter: {
async onReset() {
columnSizeSaver.clear();
}
}
},
rowHandle: {
fixed: "right",
buttons: {
view: { type: "link", text: null, icon: "ion:eye-outline" },
copy: { show: true, type: "link", text: null, icon: "ion:copy-outline" },
edit: { type: "link", text: null, icon: "ion:create-outline" },
remove: { type: "link", style: { color: "red" }, text: null, icon: "ion:trash-outline" }
},
@@ -48,7 +97,7 @@ function install(app, options: any = {}) {
}
},
request: {
transformQuery: ({ page, form, sort }) => {
transformQuery: ({ page, form, sort }: PageQuery): UserPageQuery => {
const limit = page.pageSize;
const currentPage = page.currentPage ?? 1;
const offset = limit * (currentPage - 1);
@@ -64,13 +113,13 @@ function install(app, options: any = {}) {
sort
};
},
transformRes: ({ res }) => {
transformRes: ({ res }: TransformResProps): PageRes => {
const pageSize = res.limit;
let currentPage = res.offset / pageSize;
if (res.offset % pageSize === 0) {
currentPage++;
}
return { currentPage, pageSize, ...res };
return { currentPage, pageSize, records: res.records, total: res.total, ...res };
}
},
form: {
@@ -82,14 +131,53 @@ function install(app, options: any = {}) {
width: "120px"
}
},
async afterSubmit({ mode }) {
if (mode === "add") {
notification.success({ message: "添加成功" });
} else if (mode === "edit") {
notification.success({ message: "保存成功" });
}
},
wrapperCol: {
span: null
},
wrapper: {
saveRemind: true
// inner: true,
// innerContainerSelector: "main.fs-framework-content"
}
},
columns: {
createdAt: {
title: "创建时间",
type: "datetime",
form: {
show: false
},
column: {
order: 1000
}
},
//最后一列空白,用于自动伸缩列宽
__blank__: {
title: "",
type: "text",
form: {
show: false
},
column: {
order: 99999,
width: -1,
columnSetShow: false,
resizable: false
}
}
}
};
// 从 useCrud({permission}) 里获取permission参数去设置各个按钮的权限
const crudPermission = useCrudPermission({ permission: context.permission });
const permission = props.context?.permission || null;
const crudPermission = useCrudPermission({ permission });
return crudPermission.merge(opts);
}
});
@@ -99,79 +187,121 @@ function install(app, options: any = {}) {
app.use(FsExtendsUploader, {
defaultType: "cos",
cos: {
keepName: true,
domain: "https://d2p-demo-1251260344.cos.ap-guangzhou.myqcloud.com",
bucket: "d2p-demo-1251260344",
region: "ap-guangzhou",
secretId: "", //
secretKey: "", // 传了secretKey 和secretId 代表使用本地签名模式(不安全,生产环境不推荐)
getAuthorization(custom) {
async getAuthorization(custom: any) {
// 不传secretKey代表使用临时签名模式,此时此参数必传(安全,生产环境推荐)
return request({
const ret = request({
url: "http://www.docmirror.cn:7070/api/upload/cos/getAuthorization",
method: "get"
}).then((ret) => {
// 返回结构如下
// ret.data:{
// TmpSecretId,
// TmpSecretKey,
// XCosSecurityToken,
// ExpiredTime, // SDK 在 ExpiredTime 时间前,不会再次调用 getAuthorization
// }
return ret;
});
// 返回结构要求如下
// ret.data:{
// TmpSecretId,
// TmpSecretKey,
// XCosSecurityToken,
// ExpiredTime, // SDK 在 ExpiredTime 时间前,不会再次调用 getAuthorization
// }
return ret;
},
successHandle(ret) {
successHandle(ret: any) {
// 上传完成后可以在此处处理结果修改url什么的
console.log("success handle:", ret);
return ret;
}
},
alioss: {
keepName: true,
domain: "https://d2p-demo.oss-cn-shenzhen.aliyuncs.com",
bucket: "d2p-demo",
region: "oss-cn-shenzhen",
accessKeyId: "",
accessKeyId: "", //不建议客户端使用AccessKey生产部署请使用getAuthorization来获取授权
accessKeySecret: "",
async getAuthorization(custom, context) {
async getAuthorization(context: FsUploaderGetAuthContext): Promise<FsUploaderAliossSTS> {
// 不传accessKeySecret代表使用临时签名模式,此时此参数必传(安全,生产环境推荐)
const ret = await request({
url: "http://www.docmirror.cn:7070/api/upload/alioss/getAuthorization",
method: "get"
});
console.log("ret", ret);
// 返回结构要求如下
// ret.data:{
// TmpSecretId,
// TmpSecretKey,
// XCosSecurityToken,
// ExpiredTime, // SDK 在 ExpiredTime 时间前,不会再次调用 getAuthorization
// key //【可选】后台生成的文件key如果不传则用前端自己生成的key
// }
return ret;
},
sdkOpts: {
// sdk配置
secure: true // 默认为非https上传,为了安全设置为true
},
successHandle(ret) {
successHandle(ret: any) {
// 上传完成后可以在此处处理结果修改url什么的
console.log("success handle:", ret);
return ret;
}
},
qiniu: {
keepName: true,
bucket: "d2p-demo",
async getToken(options) {
async getToken(options: any) {
const ret = await request({
url: "http://www.docmirror.cn:7070/api/upload/qiniu/getToken",
method: "get"
});
return ret; // {token:xxx,expires:xxx}
},
successHandle(ret) {
successHandle(ret: any) {
// 上传完成后可以在此处处理结果修改url什么的
console.log("success handle:", ret);
return ret;
},
domain: "http://d2p.file.handsfree.work/"
},
s3: {
keepName: true,
//同时也支持minio
bucket: "fast-crud",
sdkOpts: {
s3ForcePathStyle: true,
signatureVersion: "v4",
region: "us-east-1",
forcePathStyle: true,
//minio与s3完全适配
endpoint: "https://play.min.io",
credentials: {
//不建议在客户端使用secretAccessKey来上传 生产部署请使用getSignedUrl来获取授权
accessKeyId: "Q3AM3UQ867SPQQA43P2F", //访问登录名
secretAccessKey: "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" //访问密码
}
},
//预签名配置,向后端获取上传的预签名连接(生产部署推荐)
async getSignedUrl(bucket: string, key: string, options: any, type: FsUploaderS3SignedUrlType = "put") {
return await GetSignedUrl(bucket, key, type);
},
successHandle(ret: any) {
// 上传完成后可以在此处处理结果修改url什么的
console.log("success handle:", ret);
return ret;
}
},
form: {
keepName: true,
action: "http://www.docmirror.cn:7070/api/upload/form/upload",
name: "file",
withCredentials: false,
uploadRequest: async ({ action, file, onProgress }) => {
test: 22,
custom: { aaa: 22 },
uploadRequest: async (opts: any) => {
console.log("uploadRequest:", opts);
const { action, file, onProgress } = opts;
// @ts-ignore
const data = new FormData();
data.append("file", file);
@@ -183,12 +313,12 @@ function install(app, options: any = {}) {
},
timeout: 60000,
data,
onUploadProgress: (p) => {
onUploadProgress: (p: any) => {
onProgress({ percent: Math.round((p.loaded / p.total) * 100) });
}
});
},
successHandle(ret) {
successHandle(ret: any) {
// 上传完成后的结果处理, 此处应返回格式为{url:xxx}
return {
url: "http://www.docmirror.cn:7070" + ret,
@@ -201,20 +331,32 @@ function install(app, options: any = {}) {
//安装editor
app.use(FsExtendsEditor, {
//编辑器的公共配置
wangEditor: {}
wangEditor: {
editorConfig: {
MENU_CONF: {}
},
toolbarConfig: {}
}
});
app.use(FsExtendsJson);
app.use(FsExtendsTime);
app.use(FsExtendsCopyable);
app.use(FsExtendsInput);
app.use(FsEditorCode);
const { addTypes, getType } = useTypes();
//此处演示修改官方字段类型
const textType = getType("text");
textType.search.autoSearchTrigger = "change"; //修改官方的字段类型,变化就触发 "enter"=回车键触发
// 此处演示自定义字段类型
const { addTypes } = useTypes();
addTypes({
time2: {
//如果与官方字段类型同名,将会覆盖官方的字段类型
form: { component: { name: "a-date-picker" } },
column: { component: { name: "fs-date-format", format: "YYYY-MM-DD" } },
valueBuilder(context) {
valueBuilder(context: any) {
console.log("time2,valueBuilder", context);
}
}
@@ -230,7 +372,7 @@ function install(app, options: any = {}) {
// 比如你可以定义一个readonly的公共属性处理该字段只读不能编辑
if (columnProps.readonly) {
// 合并column配置
_.merge(columnProps, {
merge(columnProps, {
form: { show: false },
viewForm: { show: true }
});
@@ -238,6 +380,28 @@ function install(app, options: any = {}) {
return columnProps;
}
});
//默认宽度,支持自动拖动调整列宽
registerMergeColumnPlugin({
name: "resize-column-plugin",
order: 2,
handle: (columnProps: ColumnCompositionProps) => {
if (!columnProps.column) {
columnProps.column = {};
}
if (columnProps.column.resizable == null) {
columnProps.column.resizable = true;
const savedColumnWidth = columnSizeSaver.get(columnProps.key as string);
if (savedColumnWidth) {
columnProps.column.width = savedColumnWidth;
} else if (!columnProps.column.width) {
columnProps.column.width = 200;
}
}
return columnProps;
}
});
}
export default {

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import "./iconfont.js"
import "./iconfont.js";

View File

@@ -1,2 +1,2 @@
// import "@iconify/iconify";
import "@purge-icons/generated";
// import "@purge-icons/generated";

View File

@@ -2,9 +2,11 @@ import "./iconify";
import "./iconfont";
import FastCrud from "./fast-crud";
import permission from "./permission";
function install(app, options: any = {}) {
import { setupMonaco } from "./monaco";
function install(app: any, options: any = {}) {
app.use(FastCrud, options);
app.use(permission);
setupMonaco();
}
export default {

View File

@@ -0,0 +1,15 @@
import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
import yamlWorker from "./yaml.worker?worker";
import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
import { registerWorker } from "@fast-crud/editor-code";
export function setupMonaco() {
registerWorker("json", jsonWorker);
registerWorker(["css", "less", "scss"], cssWorker);
registerWorker(["html", "handlebars", "razor"], htmlWorker);
registerWorker(["yaml", "yml"], yamlWorker);
registerWorker(["typescript", "javascript"], tsWorker);
registerWorker("*", editorWorker);
}

View File

@@ -0,0 +1 @@
export * from "monaco-yaml/yaml.worker.js";

View File

@@ -1,9 +1,11 @@
import permission from "./permission";
import permission from "./permission.js";
import permissionUtil from "../util.permission";
const install = function (app) {
const install = function (app: any) {
app.directive("permission", permission);
app.config.globalProperties.$hasPermissions = permissionUtil.hasPermissions;
};
permission.install = install;
export default permission;
export default {
install,
...permission
};

View File

@@ -1,6 +1,6 @@
import permissionUtil from "../util.permission";
export default {
mounted(el, binding, vnode) {
mounted(el: any, binding: any, vnode: any) {
const { value } = binding;
const hasPermission = permissionUtil.hasPermissions(value);

View File

@@ -6,7 +6,7 @@ import { message } from "ant-design-vue";
import NProgress from "nprogress";
export function registerRouterHook() {
// 注册路由beforeEach钩子在第一次加载路由页面时加载权限
router.beforeEach(async (to, from, next) => {
router.beforeEach(async (to, from) => {
const permissionStore = usePermissionStore();
if (permissionStore.isInited) {
if (to.meta.permission) {
@@ -20,15 +20,13 @@ export function registerRouterHook() {
return false;
}
}
next();
return;
return true;
}
const userStore = useUserStore();
const token = userStore.getToken;
if (!token || token === "undefined") {
next();
return;
return true;
}
// 初始化权限列表
@@ -36,10 +34,10 @@ export function registerRouterHook() {
console.log("permission is enabled");
await permissionStore.loadFromRemote();
console.log("PM load success");
next({ ...to, replace: true });
return { ...to, replace: true };
} catch (e) {
console.error("加载动态路由失败", e);
next();
return false;
}
});
}

View File

@@ -1,4 +1,4 @@
import permissionDirective from "./directive/index";
import permissionDirective from "./directive/index.js";
import { registerRouterHook } from "./hook";
import util from "./util.permission";
export * from "./use-crud-permission";
@@ -11,7 +11,7 @@ export function usePermission() {
}
export default {
install(app) {
install(app: any) {
// 开启权限模块
// 注册v-permission指令, 用于控制按钮权限
app.use(permissionDirective);

View File

@@ -1,8 +1,9 @@
import { defineStore } from "pinia";
import { useResourceStore } from "/src/store/modules/resource";
// import { useResourceStore } from "/src/store/modules/resource";
import { getPermissions } from "./api";
import { mitter } from "/@/utils/util.mitt";
import { env } from "/@/utils/util.env";
import { useAccessStore } from "/@/vben/stores";
//监听注销事件
mitter.on("app.logout", () => {
@@ -21,7 +22,7 @@ interface PermissionState {
* @param permissionList
* @returns {*}
*/
function formatPermissions(menuTree: Array<any>, permissionList = []) {
function formatPermissions(menuTree: Array<any>, permissionList: any[] = []) {
if (menuTree == null) {
menuTree = [];
}
@@ -44,17 +45,19 @@ export const usePermissionStore = defineStore({
inited: false
}),
getters: {
// @ts-ignore
getPermissions() {
// @ts-ignore
return this.permissions;
},
// @ts-ignore
isInited() {
// @ts-ignore
return this.inited;
}
},
actions: {
init({ permissions }) {
init({ permissions }: any) {
this.permissions = permissions;
this.inited = true;
},
@@ -62,13 +65,13 @@ export const usePermissionStore = defineStore({
this.permissions = [];
this.inited = false;
},
resolve(resourceTree) {
resolve(resourceTree: any) {
const permissions = formatPermissions(resourceTree);
this.init({ permissions });
//过滤没有权限的菜单
const resourceStore = useResourceStore();
resourceStore.filterByPermission(permissions);
const accessStore = useAccessStore();
accessStore.setAccessCodes(permissions);
},
async loadFromRemote() {
let permissionTree = [];

View File

@@ -1,24 +1,36 @@
import { usePermission } from "/@/plugin/permission";
import _ from "lodash-es";
import { merge as LodashMerge } from "lodash-es";
export type UseCrudPermissionExtraProps = {
hasActionPermission: (action: string) => boolean;
};
export type UseCrudPermissionExtra = (props: UseCrudPermissionExtraProps) => any;
export type UseCrudPermissionCompProps = {
prefix: string;
extra?: UseCrudPermissionExtra;
[key: string]: any;
};
export type UseCrudPermissionProps = {
permission: string | UseCrudPermissionCompProps;
};
/**
* 设置按钮动作权限
* @param permission {prefix,extra}
*/
export function useCrudPermission({ permission }) {
export function useCrudPermission({ permission }: UseCrudPermissionProps) {
const { hasPermissions } = usePermission();
const prefix = permission instanceof Object ? permission.prefix : permission;
//根据权限显示按钮
function hasActionPermission(action) {
function hasActionPermission(action: string) {
if (!prefix) {
return true;
}
return hasPermissions(prefix + ":" + action);
}
function buildCrudPermission() {
function buildCrudPermission(): any {
if (permission == null) {
return {};
}
@@ -31,7 +43,7 @@ export function useCrudPermission({ permission }) {
}
}
return _.merge(
return LodashMerge(
{
actionbar: {
buttons: {
@@ -50,9 +62,9 @@ export function useCrudPermission({ permission }) {
);
}
function merge(userOptions) {
function merge(userOptions: any) {
const permissionOptions = buildCrudPermission();
_.merge(permissionOptions, userOptions);
LodashMerge(permissionOptions, userOptions);
return permissionOptions;
}

View File

@@ -14,11 +14,14 @@ const util = {
}
const permissionStore = usePermissionStore();
const userPermissionList = permissionStore.getPermissions;
return userPermissionList.some((permission) => {
return userPermissionList.some((permission: any) => {
if (permission === "*") {
return true;
}
return need.includes(permission);
});
},
requirePermissions: (value) => {
requirePermissions: (value: any) => {
if (!util.hasPermissions(value)) {
message.error("对不起,您没有权限执行此操作");
throw new NoPermissionError();

View File

@@ -0,0 +1,35 @@
import type { ComponentRecordType, GenerateMenuAndRoutesOptions } from "/@/vben/types";
import { generateAccessible } from "/@/vben/access";
import { preferences } from "/@/vben/preferences";
import { BasicLayout, IFrameView } from "/@/vben/layouts";
const forbiddenComponent = () => import("#/views/_core/fallback/forbidden.vue");
async function generateAccess(options: GenerateMenuAndRoutesOptions) {
const pageMap: ComponentRecordType = import.meta.glob("../views/**/*.vue");
const layoutMap: ComponentRecordType = {
BasicLayout,
IFrameView
} as any;
return await generateAccessible(preferences.app.accessMode, {
...options,
// fetchMenuListAsync: async () => {
// message.loading({
// content: `${$t("common.loadingMenu")}...`,
// duration: 1.5
// });
// return await getAllMenusApi();
// },
// 可以指定没有权限跳转403页面
forbiddenComponent,
// 如果 route.meta.menuVisibleWithForbidden = true
layoutMap,
pageMap
});
}
export { generateAccess };

View File

@@ -0,0 +1,113 @@
import type { Router } from "vue-router";
import { DEFAULT_HOME_PATH, LOGIN_PATH } from "/@/vben/constants";
import { preferences } from "/@/vben/preferences";
import { useAccessStore } from "/@/vben/stores";
import { generateMenus, startProgress, stopProgress } from "/@/vben/utils";
import { useUserStore } from "/@/store/modules/user";
import { frameworkRoutes } from "/@/router/resolve";
/**
* 通用守卫配置
* @param router
*/
export function setupCommonGuard(router: Router) {
// 记录已经加载的页面
const loadedPaths = new Set<string>();
router.beforeEach(async (to) => {
to.meta.loaded = loadedPaths.has(to.path);
// 页面加载进度条
if (!to.meta.loaded && preferences.transition.progress) {
startProgress();
}
return true;
});
router.afterEach((to) => {
// 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行
loadedPaths.add(to.path);
// 关闭页面加载进度条
if (preferences.transition.progress) {
stopProgress();
}
});
}
/**
* 权限访问守卫配置
* @param router
*/
function setupAccessGuard(router: Router) {
router.beforeEach(async (to, from) => {
if (to.matched && to.matched.length > 2) {
to.matched.splice(1, to.matched.length - 2);
}
// 基本路由,这些路由不需要进入权限拦截
const needAuth = to.matched.some((r) => {
return r.meta?.auth || r.meta?.permission;
});
const accessStore = useAccessStore();
if (needAuth) {
if (!accessStore.accessToken) {
// 没有访问权限,跳转登录页面
if (to.fullPath !== LOGIN_PATH) {
return {
path: LOGIN_PATH,
// 如不需要,直接删除 query
query: to.fullPath === DEFAULT_HOME_PATH ? {} : { redirect: encodeURIComponent(to.fullPath) },
// 携带当前跳转的页面,登录后重新跳转该页面
replace: true
};
}
return true;
}
}
// 是否已经生成过动态路由
if (!accessStore.isAccessChecked) {
const accessibleMenus = await generateMenus(frameworkRoutes[0].children, router);
accessStore.setAccessRoutes(frameworkRoutes);
accessStore.setAccessMenus(accessibleMenus);
accessStore.setIsAccessChecked(true);
}
// 生成菜单和路由
// const { accessibleMenus, accessibleRoutes } = await generateAccess({
// roles: [],
// router,
// // 则会在菜单中显示但是访问会被重定向到403
// routes: accessRoutes
// });
//
// // 保存菜单信息和路由信息
// accessStore.setAccessMenus(accessibleMenus);
// accessStore.setAccessRoutes(accessibleRoutes);
// const redirectPath = (from.query.redirect ?? (to.path === DEFAULT_HOME_PATH ? DEFAULT_HOME_PATH : to.fullPath)) as string;
//
// return {
// ...router.resolve(decodeURIComponent(redirectPath)),
// replace: true
// };
return true;
});
}
/**
* 项目守卫配置
* @param router
*/
function createRouterGuard(router: Router) {
/** 通用 */
setupCommonGuard(router);
/** 权限访问 */
setupAccessGuard(router);
}
export { createRouterGuard };

View File

@@ -1,68 +1,73 @@
import { createRouter, createWebHashHistory } from "vue-router";
// 进度条
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import { usePageStore } from "../store/modules/page";
import { site } from "../utils/util.site";
import { routes } from "./resolve";
import { useResourceStore } from "../store/modules/resource";
import { useUserStore } from "../store/modules/user";
import { createRouterGuard } from "/@/router/guard";
const router = createRouter({
history: createWebHashHistory(),
routes
});
//
// /**
// * 路由拦截
// */
// router.beforeEach(async (to, from, next) => {
// // 进度条
// NProgress.start();
// // 修复三级以上路由页面无法缓存的问题
// if (to.matched && to.matched.length > 2) {
// to.matched.splice(1, to.matched.length - 2);
// }
// // 验证当前路由所有的匹配中是否需要有登录验证的
// if (
// to.matched.some((r) => {
// return r.meta?.auth || r.meta?.permission;
// })
// ) {
// const userStore = useUserStore();
// // 这里暂时将cookie里是否存有token作为验证是否登录的条件
// // 请根据自身业务需要修改
// const token = userStore.getToken;
// if (token) {
// next();
// } else {
// // 没有登录的时候跳转到登录界面
// // 携带上登陆成功之后需要跳转的页面完整路径
// next({
// name: "login",
// query: {
// redirect: to.fullPath
// }
// });
// // https://github.com/d2-projects/d2-admin/issues/138
// NProgress.done();
// }
// } else {
// // 不需要身份校验 直接通过
// next();
// }
// });
//
// router.afterEach((to: any) => {
// // 进度条
// NProgress.done();
// // 多页控制 打开新的页面
// const pageStore = usePageStore();
// // for (const item of to.matched) {
// // pageStore.keepAlivePush(item.name);
// // }
// pageStore.open(to);
// // 更改标题
// site.title(to.meta.title);
//
// //修改左侧边栏
// const matched = to.matched;
// if (matched.length > 0) {
// const resourceStore = useResourceStore();
// resourceStore.setAsideMenuByCurrentRoute(matched);
// }
// });
/**
* 路由拦截
*/
router.beforeEach(async (to, from, next) => {
// 进度条
NProgress.start();
// 验证当前路由所有的匹配中是否需要有登录验证的
if (
to.matched.some((r) => {
return r.meta?.auth || r.meta?.permission;
})
) {
const userStore = useUserStore();
// 这里暂时将cookie里是否存有token作为验证是否登录的条件
// 请根据自身业务需要修改
const token = userStore.getToken;
if (token) {
next();
} else {
// 没有登录的时候跳转到登录界面
// 携带上登陆成功之后需要跳转的页面完整路径
next({
name: "login",
query: {
redirect: to.fullPath
}
});
// https://github.com/d2-projects/d2-admin/issues/138
NProgress.done();
}
} else {
// 不需要身份校验 直接通过
next();
}
});
router.afterEach((to) => {
// 进度条
NProgress.done();
// 多页控制 打开新的页面
const pageStore = usePageStore();
pageStore.open(to);
// 更改标题
site.title(to.meta.title);
//修改左侧边栏
const matched = to.matched;
if (matched.length > 0) {
const resourceStore = useResourceStore();
resourceStore.setAsideMenuByCurrentRoute(matched);
}
});
createRouterGuard(router);
export default router;

View File

@@ -1,13 +1,12 @@
import LayoutPass from "/src/layout/layout-pass.vue";
import _ from "lodash-es";
import { cloneDeep } from "lodash-es";
import { outsideResource } from "./source/outside";
import { headerResource } from "./source/header";
import { frameworkResource } from "./source/framework";
// @ts-ignore
const modules = import.meta.glob("/src/views/**/*.vue");
let index = 0;
function transformOneResource(resource) {
function transformOneResource(resource: any, parent: any) {
let menu: any = null;
if (resource.meta == null) {
resource.meta = {};
@@ -20,60 +19,60 @@ function transformOneResource(resource) {
if (meta.isMenu === false) {
menu = null;
} else {
menu = _.cloneDeep(resource);
menu = cloneDeep(resource);
delete menu.component;
}
let route;
if (resource.type !== "menu") {
if (resource.path == null || resource.path.startsWith("https://") || resource.path.startsWith("http://")) {
//没有route
route = null;
if (menu.path?.startsWith("/")) {
menu.fullPath = menu.path;
} else {
route = _.cloneDeep(resource);
if (route.component && typeof route.component === "string") {
const path = "/src/views" + route.component;
route.component = modules[path];
}
if (route.component == null) {
route.component = LayoutPass;
}
menu.fullPath = (parent?.fullPath || "") + "/" + menu.path;
}
}
let route;
if (meta.isRoute === false || resource.path == null || resource.path.startsWith("https://") || resource.path.startsWith("http://")) {
//没有route
route = null;
} else {
route = cloneDeep(resource);
if (route.component && typeof route.component === "string") {
const path = "/src/views" + route.component;
route.component = modules[path];
}
if (route.component == null) {
route.component = LayoutPass;
}
if (route?.meta?.cache !== false) {
if (route.meta == null) {
route.meta = {};
}
route.meta.cache = true;
}
}
if (resource.children) {
const { menus, routes } = buildMenusAndRouters(resource.children, resource);
if (menu) {
menu.children = menus;
}
if (route) {
route.children = routes;
}
}
return {
menu,
route
};
}
export const buildMenusAndRouters = (resources) => {
export const buildMenusAndRouters = (resources: any, parent: any = null) => {
const routes: Array<any> = [];
const menus: Array<any> = [];
for (const item of resources) {
const { menu, route } = transformOneResource(item);
let menuChildren;
let routeChildren;
if (item.children) {
if (item.children.length > 0) {
const ret = buildMenusAndRouters(item.children);
menuChildren = ret.menus;
routeChildren = ret.routes;
}
}
const { menu, route } = transformOneResource(item, parent);
if (menu) {
menus.push(menu);
menu.children = menuChildren;
}
if (route) {
if (route?.meta?.cache !== false) {
if (route.meta == null) {
route.meta = {};
}
route.meta.cache = true;
}
routes.push(route);
route.children = routeChildren;
}
}
@@ -84,7 +83,7 @@ export const buildMenusAndRouters = (resources) => {
};
};
function setIndex(menus) {
function setIndex(menus: any) {
for (const menu of menus) {
menu.index = "index_" + index;
index++;
@@ -94,7 +93,7 @@ function setIndex(menus) {
}
}
function findMenus(menus, condition) {
function findMenus(menus: any, condition: any) {
const list: any = [];
for (const menu of menus) {
if (condition(menu)) {
@@ -110,8 +109,8 @@ function findMenus(menus, condition) {
return list;
}
function filterMenus(menus, condition) {
const list = menus.filter((item) => {
function filterMenus(menus: any, condition: any) {
const list = menus.filter((item: any) => {
return condition(item);
});
@@ -123,7 +122,7 @@ function filterMenus(menus, condition) {
return list;
}
function flatChildren(list, children) {
function flatChildren(list: any, children: any) {
for (const child of children) {
list.push(child);
if (child.children && child.children.length > 0) {
@@ -132,7 +131,7 @@ function flatChildren(list, children) {
child.children = null;
}
}
function flatSubRouters(routers) {
function flatSubRouters(routers: any) {
for (const router of routers) {
const children: Array<any> = [];
if (router.children && router.children.length > 0) {
@@ -148,7 +147,7 @@ const outsideRet = buildMenusAndRouters(outsideResource);
const headerRet = buildMenusAndRouters(headerResource);
const outsideRoutes = outsideRet.routes;
const frameworkRoutes = flatSubRouters(frameworkRet.routes);
const frameworkRoutes = frameworkRet.routes;
const routes = [...outsideRoutes, ...frameworkRoutes];
const frameworkMenus = frameworkRet.menus;
const headerMenus = headerRet.menus;

View File

@@ -1,15 +1,26 @@
import LayoutFramework from "/src/layout/layout-framework.vue";
import { crudResources } from "/@/router/source/modules/crud";
import { sysResources } from "/@/router/source/modules/sys";
import LayoutBasic from "/@/layout/layout-basic.vue";
import type { RouteRecordRaw } from "vue-router";
import { mergeRouteModules } from "/@/vben/utils";
const dynamicRouteFiles = import.meta.glob("./modules/**/*.ts", {
eager: true
});
/** 动态路由 */
const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
export const frameworkResource = [
{
title: "框架",
name: "framework",
name: "root",
path: "/",
redirect: "/index",
component: LayoutFramework,
component: LayoutBasic,
meta: {
icon: "ion:accessibility"
icon: "ion:accessibility",
hideInBreadcrumb: true
},
children: [
{
@@ -20,11 +31,12 @@ export const frameworkResource = [
meta: {
fixedAside: true,
showOnHeader: false,
icon: "ion:home-outline"
icon: "ion:home-outline",
auth: true
}
},
...crudResources,
...sysResources
// @ts-ignore
...dynamicRoutes.sort((a, b) => (a.meta?.order || 0) - (b.meta?.order || 0))
]
}
];

View File

@@ -54,14 +54,14 @@ export const headerResource = [
children: [
{
title: "github",
path: "http://github.com/fast-crud/fs-admin-antdv",
path: "http://github.com/fast-crud/fs-admin-antdv4",
meta: {
icon: "ion:logo-github"
}
},
{
title: "gitee",
path: "http://gitee.com/fast-crud/fs-admin-antdv",
path: "http://gitee.com/fast-crud/fs-admin-antdv4",
meta: {
icon: "ion:logo-octocat"
}

View File

@@ -0,0 +1,85 @@
import { IFrameView } from "/@/vben/layouts";
export const aboutResource = [
{
title: "关于",
name: "about",
path: "/about",
redirect: "/about/doc",
meta: {
icon: "lucide:copyright",
order: 9999
},
children: [
{
title: "文档",
name: "document",
path: "/about/doc",
component: IFrameView,
meta: {
icon: "lucide:book-open-text",
link: "http://fast-crud.docmirror.cn/",
title: "文档"
}
},
{
name: "Github",
path: "/about/github",
component: IFrameView,
meta: {
icon: "mdi:github",
link: "https://github.com/fast-crud/fast-crud",
title: "Github"
}
},
{
name: "Gitee",
path: "/about/gitee",
component: IFrameView,
meta: {
icon: "ion:logo-octocat",
link: "https://gitee.com/fast-crud/fast-crud",
title: "Gite"
}
},
{
title: "其他Demo",
name: "demo",
path: "/about/demo",
meta: {
icon: "ion:git-branch-outline"
},
children: [
{
title: "Element版",
path: "/about/demo/element",
component: IFrameView,
meta: {
link: "http://fast-crud.docmirror.cn/element/",
title: "Element版"
}
},
{
title: "Naive版",
path: "/about/demo/naive",
component: IFrameView,
meta: {
link: "http://fast-crud.docmirror.cn/naive/",
title: "Naive版"
}
},
{
title: "VbenAdmin",
path: "/about/demo/vben",
meta: {
link: "http://fast-crud.docmirror.cn/vben/",
title: "VbenAdmin"
}
}
]
}
]
}
];
export default aboutResource;

View File

@@ -8,6 +8,16 @@ export const crudResources = [
icon: "ion:apps-sharp"
},
children: [
{
title: "debug",
name: "debug",
path: "/crud/debug",
component: "/crud/debug/index.vue",
meta: {
isMenu: false
// hideInMenu: true
}
},
{
title: "基本特性",
name: "basis",
@@ -18,11 +28,17 @@ export const crudResources = [
},
children: [
{
title: "HelloWorld",
title: "FirstDemo",
name: "FsCrudFirst",
path: "/crud/basis/first",
component: "/crud/basis/first/index.vue"
},
{
title: "HelloWorld",
name: "FsCrudHelloWorld",
path: "/crud/basis/helloworld",
component: "/crud/basis/helloworld/index.vue"
},
{
title: "动态计算",
name: "BasisCompute",
@@ -59,6 +75,12 @@ export const crudResources = [
path: "/crud/basis/layout-custom",
component: "/crud/basis/layout-custom/index.vue"
},
{
title: "自定义组件",
name: "BasisCustom",
path: "/crud/basis/custom",
component: "/crud/basis/custom/index.vue"
},
{
title: "列设置",
name: "BasisColumnsSet",
@@ -70,6 +92,27 @@ export const crudResources = [
name: "BasisColumnMergePlugin",
path: "/crud/basis/column-merge-plugin",
component: "/crud/basis/column-merge-plugin/index.vue"
},
{
title: "ResetCrudOptions",
name: "BasisReset",
path: "/crud/basis/reset",
component: "/crud/basis/reset/index.vue",
meta: {
cache: true
}
},
{
title: "CrudOptions插件",
name: "BasisPlugin",
path: "/crud/basis/plugin",
component: "/crud/basis/plugin/index.vue"
},
{
title: "Ts定义测试",
name: "BasisTsTest",
path: "/crud/basis/ts",
component: "/crud/basis/ts/index.vue"
}
]
},
@@ -165,6 +208,12 @@ export const crudResources = [
path: "/crud/component/select",
component: "/crud/component/select/index.vue"
},
{
title: " 表格选择(table-select)",
name: "ComponentTableSelect",
path: "/crud/component/table-select",
component: "/crud/component/table-select/index.vue"
},
{
title: "级联(cascader)",
name: "ComponentCascader",
@@ -243,12 +292,24 @@ export const crudResources = [
path: "/crud/component/uploader/qiniu",
component: "/crud/component/uploader/qiniu/index.vue"
},
{
title: "s3上传",
name: "ComponentUploaderS3",
path: "/crud/component/uploader/s3",
component: "/crud/component/uploader/s3/index.vue"
},
{
title: "富文本编辑器",
name: "ComponentEditor",
path: "/crud/component/editor",
component: "/crud/component/editor/index.vue"
},
{
title: "代码编辑器",
name: "ComponentCode",
path: "/crud/component/code",
component: "/crud/component/code/index.vue"
},
{
title: "图标",
name: "ComponentIcon",
@@ -260,6 +321,18 @@ export const crudResources = [
name: "ComponentJson",
path: "/crud/component/json",
component: "/crud/component/json/index.vue"
},
{
title: "手机号输入框",
name: "ComponentPhone",
path: "/crud/component/phone",
component: "/crud/component/phone/index.vue"
},
{
title: "组件独立使用",
name: "ComponentIndependent",
path: "/crud/component/independent",
component: "/crud/component/independent/index.vue"
}
]
},
@@ -391,6 +464,30 @@ export const crudResources = [
name: "FormNest",
path: "/crud/form/nest",
component: "/crud/form/nest/index.vue"
},
{
title: "字段组件render",
name: "FormRender",
path: "/crud/form/render",
component: "/crud/form/render/index.vue"
},
{
title: "查看表单使用单元格组件",
name: "FormView",
path: "/crud/form/view",
component: "/crud/form/view/index.vue"
},
{
title: "initialForm",
name: "FormInitial",
path: "/crud/form/initial",
component: "/crud/form/initial/index.vue"
},
{
title: "表单Watch",
name: "FormWatch",
path: "/crud/form/watch",
component: "/crud/form/watch/index.vue"
}
]
},
@@ -444,6 +541,12 @@ export const crudResources = [
path: "/crud/feature/header-group",
component: "/crud/feature/header-group/index.vue"
},
{
title: "自定义表头",
name: "FeatureHeader",
path: "/crud/feature/header",
component: "/crud/feature/header/index.vue"
},
{
title: "合并单元格",
name: "FeatureMerge",
@@ -474,18 +577,6 @@ export const crudResources = [
path: "/crud/feature/height",
component: "/crud/feature/height/index.vue"
},
{
title: "可编辑",
name: "FeatureEditable",
path: "/crud/feature/editable",
component: "/crud/feature/editable/index.vue"
},
{
title: "行编辑",
name: "FeatureEditableRow",
path: "/crud/feature/editable-row",
component: "/crud/feature/editable-row/index.vue"
},
{
title: "查询框",
name: "FeatureSearch",
@@ -498,6 +589,12 @@ export const crudResources = [
path: "/crud/feature/search-multi",
component: "/crud/feature/search-multi/index.vue"
},
{
title: "Tabs快捷查询",
name: "FeatureTabs",
path: "/crud/feature/tabs",
component: "/crud/feature/tabs/index.vue"
},
{
title: "字段排序",
name: "FeatureColumnSort",
@@ -525,9 +622,21 @@ export const crudResources = [
{
title: "v-model",
name: "FeatureVModel",
path: "/crud/feature/v-model",
path: "/crud/feature/local-v-model",
component: "/crud/feature/local-v-model/index.vue"
},
{
title: "导入",
name: "FeatureImport",
path: "/crud/feature/local-import",
component: "/crud/feature/local-import/index.vue"
},
{
title: "导出",
name: "FeatureExport",
path: "/crud/feature/export",
component: "/crud/feature/export/index.vue"
},
{
title: "自定义删除",
name: "FeatureRemove",
@@ -542,6 +651,53 @@ export const crudResources = [
}
]
},
{
title: "可编辑",
name: "Editable",
path: "/crud/editable",
redirect: "/crud/editable/free",
meta: {
icon: "ion:create-outline"
},
children: [
{
title: "自由编辑",
name: "EditableFree",
path: "/crud/editable/free",
component: "/crud/editable/free/index.vue"
},
{
title: "行编辑",
name: "EditableRow",
path: "/crud/editable/row",
component: "/crud/editable/row/index.vue"
},
{
title: "单元格编辑",
name: "EditableCell",
path: "/crud/editable/cell",
component: "/crud/editable/cell/index.vue"
},
{
title: "子表格编辑",
name: "EditableVModel",
path: "/crud/editable/vmodel",
component: "/crud/editable/vmodel/index.vue"
},
{
title: "子CRUD",
name: "EditableSubCrud",
path: "/crud/editable/sub-crud",
component: "/crud/editable/sub-crud/index.vue"
},
{
title: "行编辑VModel",
name: "EditableRowVModel",
path: "/crud/editable/menus",
component: "/crud/editable/menus/index.vue"
}
]
},
{
title: "插槽",
name: "Slots",
@@ -622,14 +778,28 @@ export const crudResources = [
path: "/crud/advanced/in-dialog",
component: "/crud/advanced/in-dialog/index.vue"
},
{
title: "抽屉中显示crud",
name: "AdvancedInDrawer",
path: "/crud/advanced/in-drawer",
component: "/crud/advanced/in-drawer/index.vue"
},
{
title: "大量数据",
name: "AdvancedBigData",
path: "/crud/advanced/big-data",
component: "/crud/advanced/big-data/index.vue"
},
{
title: "列表以card方式显示",
name: "AdvancedCard",
path: "/crud/advanced/card",
component: "/crud/advanced/card/index.vue"
}
]
}
]
}
];
export default crudResources;

View File

@@ -0,0 +1,27 @@
import type { RouteRecordRaw } from "vue-router";
import BasicLayout from "/@/vben/layouts/basic/layout.vue";
export const integrationResources = [
{
title: "集成",
name: "integration",
path: "/integration",
redirect: "/integration/bpmn",
meta: {
icon: "ion:apps-sharp"
},
children: [
{
title: "FsBpmn",
name: "FsBpmn",
path: "/integration/bpmn",
component: "/integration/bpmn/index.vue",
meta: {
icon: "ion:disc-outline"
}
}
]
}
];
// export default integrationResources;

View File

@@ -1,4 +1,5 @@
import LayoutPass from "/@/layout/layout-pass.vue";
import BasicLayout from "/@/vben/layouts/basic/layout.vue";
export const sysResources = [
{
@@ -6,7 +7,6 @@ export const sysResources = [
name: "sys",
path: "/sys",
redirect: "/sys/authority",
component: LayoutPass,
meta: {
icon: "ion:settings-outline",
permission: "sys"
@@ -59,3 +59,5 @@ export const sysResources = [
]
}
];
export default sysResources;

View File

@@ -0,0 +1,34 @@
import BasicLayout from "/@/vben/layouts/basic/layout.vue";
export const uiResources = [
{
title: "UI示例",
name: "ui",
path: "/ui",
redirect: "/ui/form",
meta: {
icon: "ion:apps-sharp"
},
children: [
{
title: "表单组件",
name: "UIForm",
path: "/ui/form",
redirect: "/ui/form/input",
meta: {
icon: "ion:disc-outline"
},
children: [
{
title: "input",
name: "UIFormInput",
path: "/ui/form/input",
component: "/ui/form/input/index.vue"
}
]
}
]
}
];
// export default uiResources;

View File

@@ -1,7 +1,7 @@
import { createPinia } from "pinia";
const store = createPinia();
export default {
install(app) {
install(app: any) {
app.use(store);
}
};

View File

@@ -1,436 +0,0 @@
import { defineStore } from "pinia";
import { cloneDeep, get, uniq } from "lodash-es";
import router from "/src/router";
import { frameworkRoutes } from "/src/router/resolve";
// @ts-ignore
import { LocalStorage } from "/src/utils/util.storage";
import { useUserStore } from "/src/store/modules/user";
const OPENED_CACHE_KEY = "TABS_OPENED";
interface PageState {
// 可以在多页 tab 模式下显示的页面
pool: Array<any>;
// 当前显示的多页面列表
opened: Array<any>;
// 已经加载多标签页数据 https://github.com/d2-projects/d2-admin/issues/201
openedLoaded: boolean;
// 当前页面
current: "";
// 需要缓存的页面 name
keepAlive: Array<any>;
inited: boolean;
}
// 判定是否需要缓存
const isKeepAlive = (data) => get(data, "meta.cache", false);
export const usePageStore = defineStore({
id: "app.page",
state: (): PageState => ({
// 可以在多页 tab 模式下显示的页面
pool: [],
// 当前显示的多页面列表
opened: [
{
name: "index",
fullPath: "/index",
meta: {
title: "首页",
auth: false
}
}
],
// 已经加载多标签页数据 https://github.com/d2-projects/d2-admin/issues/201
openedLoaded: false,
// 当前页面
current: "",
// 需要缓存的页面 name
keepAlive: [],
inited: false
}),
getters: {
getOpened() {
// @ts-ignore
return this.opened;
},
getCurrent(): string {
return this.current;
}
},
actions: {
/**
* @description 确认已经加载多标签页数据 https://github.com/d2-projects/d2-admin/issues/201
* @param {Object} context
*/
async isLoaded() {
if (this.openedLoaded) {
return true;
}
return new Promise((resolve) => {
const timer = setInterval(() => {
if (this.openedLoaded) {
resolve(clearInterval(timer));
}
}, 10);
});
},
/**
* @class opened
* @description 从持久化数据载入标签页列表
* @param {Object} context
*/
async openedLoad() {
// store 赋值
const value = LocalStorage.get(this.getStorageKey());
if (value == null) {
return;
}
// 在处理函数中进行数据优化 过滤掉现在已经失效的页签或者已经改变了信息的页签
// 以 fullPath 字段为准
// 如果页面过多的话可能需要优化算法
// valid 有效列表 1, 1, 0, 1 => 有效, 有效, 失效, 有效
const valid: Array<number> = [];
// 处理数据
this.opened = value
.map((opened) => {
// 忽略首页
if (opened.fullPath === "/index") {
valid.push(1);
return opened;
}
// 尝试在所有的支持多标签页的页面里找到 name 匹配的页面
const find = this.pool.find((item) => item.name === opened.name);
// 记录有效或无效信息
valid.push(find ? 1 : 0);
// 返回合并后的数据 新的覆盖旧的
// 新的数据中一般不会携带 params 和 query, 所以旧的参数会留存
return Object.assign({}, opened, find);
})
.filter((opened, index) => valid[index] === 1);
// 标记已经加载多标签页数据 https://github.com/d2-projects/d2-admin/issues/201
this.openedLoaded = true;
// 根据 opened 数据生成缓存设置
this.keepAliveRefresh();
},
getStorageKey() {
const userStore = useUserStore();
const userId = userStore.getUserInfo?.id ?? "anonymous";
return OPENED_CACHE_KEY + ":" + userId;
},
/**
* 将 opened 属性赋值并持久化 在这之前请先确保已经更新了 state.opened
* @param {Object} context
*/
async opened2db() {
// 设置数据
LocalStorage.set(this.getStorageKey(), this.opened);
},
/**
* @class opened
* @description 更新页面列表上的某一项
* @param {Object} context
* @param {Object} payload { index, params, query, fullPath } 路由信息
*/
async openedUpdate({ index, params, query, fullPath }) {
// 更新页面列表某一项
const page = this.opened[index];
page.params = params || page.params;
page.query = query || page.query;
page.fullPath = fullPath || page.fullPath;
this.opened.splice(index, 1, page);
// 持久化
await this.opened2db();
},
/**
* @class opened
* @description 重排页面列表上的某一项
* @param {Object} context
* @param {Object} payload { oldIndex, newIndex } 位置信息
*/
async openedSort({ oldIndex, newIndex }) {
// 重排页面列表某一项
const page = this.opened[oldIndex];
this.opened.splice(oldIndex, 1);
this.opened.splice(newIndex, 0, page);
// 持久化
await this.opened2db();
},
/**
* @class opened
* @description 新增一个 tag (打开一个页面)
* @param {Object} context
* @param {Object} payload new tag info
*/
async add({ tag, params, query, fullPath }) {
// 设置新的 tag 在新打开一个以前没打开过的页面时使用
const newTag = tag;
newTag.params = params || newTag.params;
newTag.query = query || newTag.query;
newTag.fullPath = fullPath || newTag.fullPath;
// 添加进当前显示的页面数组
this.opened.push(newTag);
// 如果这个页面需要缓存 将其添加到缓存设置
if (isKeepAlive(newTag)) {
this.keepAlivePush(tag.name);
}
// 持久化
await this.opened2db();
},
/**
* @class current
* @description 打开一个新的页面
* @param {Object} context
* @param {Object} payload 从路由钩子的 to 对象上获取 { name, params, query, fullPath, meta } 路由信息
*/
async open({ name, params, query, fullPath, meta }) {
// 已经打开的页面
const opened = this.opened;
// 判断此页面是否已经打开 并且记录位置
let pageOpendIndex = 0;
const pageOpend = opened.find((page, index) => {
const same = page.fullPath === fullPath;
pageOpendIndex = same ? index : pageOpendIndex;
return same;
});
if (pageOpend) {
// 页面以前打开过
await this.openedUpdate({
index: pageOpendIndex,
params,
query,
fullPath
});
} else {
// 页面以前没有打开过
const page = this.pool.find((t) => t.name === name);
// 如果这里没有找到 page 代表这个路由虽然在框架内 但是不参与标签页显示
if (page) {
this.add({
tag: Object.assign({}, page),
params,
query,
fullPath
});
}
}
// 如果这个页面需要缓存 将其添加到缓存设置
if (isKeepAlive({ meta })) {
this.keepAlivePush(name);
}
// 设置当前的页面
this.currentSet(fullPath);
},
/**
* @class opened
* @description 关闭一个 tag (关闭一个页面)
* @param {Object} context
* @param {Object} payload { tagName: 要关闭的标签名字 }
*/
async close({ tagName }) {
// 预定下个新页面
let newPage = {};
const isCurrent = this.current === tagName;
// 如果关闭的页面就是当前显示的页面
if (isCurrent) {
// 去找一个新的页面
const len = this.opened.length;
for (let i = 0; i < len; i++) {
if (this.opened[i].fullPath === tagName) {
newPage = i < len - 1 ? this.opened[i + 1] : this.opened[i - 1];
break;
}
}
}
// 找到这个页面在已经打开的数据里是第几个
const index = this.opened.findIndex((page) => page.fullPath === tagName);
if (index >= 0) {
// 如果这个页面是缓存的页面 将其在缓存设置中删除
this.keepAliveRemove(this.opened[index].name);
// 更新数据 删除关闭的页面
this.opened.splice(index, 1);
}
// 持久化
await this.opened2db();
// 决定最后停留的页面
if (isCurrent) {
// @ts-ignore
const { name = "index", params = {}, query = {} } = newPage;
const routerObj = { name, params, query };
await router.push(routerObj);
}
},
/**
* @class opened
* @description 关闭当前标签左边的标签
* @param opts
*/
async closeLeft(opts = {}) {
await this.closeByCondition({
condition({ i, currentIndex }) {
return i >= currentIndex;
},
...opts
});
},
/**
* @class opened
* @description 关闭当前标签右边的标签
* @param opts
*/
async closeRight(opts = {}) {
await this.closeByCondition({
condition({ i, currentIndex }) {
return currentIndex >= i;
},
...opts
});
},
/**
* @class opened
* @description 关闭当前标签右边的标签
* @param opts
*/
async closeByCondition(opts = {}) {
// @ts-ignore
const { pageSelect, condition } = opts;
const pageAim = pageSelect || this.current;
let currentIndex = 0;
this.opened.forEach((page, index) => {
if (page.fullPath === pageAim) currentIndex = index;
});
// 删除打开的页面 并在缓存设置中删除
for (let i = this.opened.length - 1; i >= 0; i--) {
if (this.opened[i].name === "index" || condition({ i, currentIndex })) {
continue;
}
this.keepAliveRemove(this.opened[i].name);
this.opened.splice(i, 1);
}
// 持久化
await this.opened2db();
// 设置当前的页面
this.current = pageAim;
// @ts-ignore
if (router.currentRoute.fullPath !== pageAim) await router.push(pageAim);
},
/**
* @class opened
* @description 关闭当前激活之外的 tag
* @param opts
*/
async closeOther(opts = {}) {
await this.closeByCondition({
condition({ i, currentIndex }) {
return currentIndex === i;
},
...opts
});
},
/**
* @class opened
* @description 关闭所有 tag
* @param {Object} context
*/
async closeAll() {
// 删除打开的页面 并在缓存设置中删除
for (let i = this.opened.length - 1; i >= 0; i--) {
if (this.opened[i].name === "index") {
continue;
}
this.keepAliveRemove(this.opened[i].name);
this.opened.splice(i, 1);
}
// 持久化
await this.opened2db();
// 关闭所有的标签页后需要判断一次现在是不是在首页
// @ts-ignore
if (router.currentRoute.name !== "index") {
await router.push({ name: "index" });
}
},
/**
* @class keepAlive
* @description 从已经打开的页面记录中更新需要缓存的页面记录
* @param {Object} state state
*/
keepAliveRefresh() {
this.keepAlive = this.opened.filter((item) => isKeepAlive(item)).map((e) => e.name);
console.log("keep alive:", this.keepAlive);
},
/**
* @description 删除一个页面的缓存设置
* @param {Object} state state
* @param {String} name name
*/
keepAliveRemove(name) {
const list = cloneDeep(this.keepAlive);
const index = list.findIndex((item) => item === name);
if (index !== -1) {
list.splice(index, 1);
this.keepAlive = list;
}
},
/**
* @description 增加一个页面的缓存设置
* @param {Object} state state
* @param {String} name name
*/
keepAlivePush(name) {
const keep = cloneDeep(this.keepAlive);
keep.push(name);
this.keepAlive = uniq(keep);
},
/**
* @description 清空页面缓存设置
* @param {Object} state state
*/
keepAliveClean() {
this.keepAlive = [];
},
/**
* @class current
* @description 设置当前激活的页面 fullPath
* @param {Object} state state
* @param {String} fullPath new fullPath
*/
currentSet(fullPath) {
this.current = fullPath;
},
/**
* @class pool
* @description 保存 pool (候选池)
* @param {Object} state state
* @param {Array} routes routes
*/
async init(routes) {
if (this.inited) {
return;
}
this.inited = true;
if (routes == null) {
//不能用全部的routes只能是framework内的
routes = frameworkRoutes;
}
const pool = [];
const push = function (routes) {
routes.forEach((route) => {
if (route.children && route.children.length > 0) {
push(route.children);
} else {
if (!route.hidden) {
const { meta, name, path } = route;
// @ts-ignore
pool.push({ meta, name, path });
}
}
});
};
push(routes);
this.pool = pool;
await this.openedLoad();
}
}
});

View File

@@ -1,127 +0,0 @@
import { defineStore } from "pinia";
// @ts-ignore
import { frameworkMenus, headerMenus, filterMenus, findMenus } from "/src/router/resolve";
import _ from "lodash-es";
import { mitter } from "/src/utils/util.mitt";
//监听注销事件
mitter.on("app.logout", () => {
const resourceStore = useResourceStore();
resourceStore.clear();
});
interface ResourceState {
frameworkMenus: Array<any>;
headerMenus: Array<any>;
asideMenus: Array<any>;
fixedAsideMenus: Array<any>;
inited: boolean;
currentAsidePath: string;
}
export const useResourceStore = defineStore({
id: "app.resource",
state: (): ResourceState => ({
// user info
frameworkMenus: [],
headerMenus: [],
asideMenus: [],
fixedAsideMenus: [],
inited: false,
currentAsidePath: ""
}),
getters: {
getAsideMenus() {
return this.asideMenus;
},
getHeaderMenus() {
return this.headerMenus;
},
getFrameworkMenus() {
return this.frameworkMenus;
}
},
actions: {
clear() {
this.inited = false;
},
/**
* 初始化资源
*/
init() {
if (this.inited) {
return;
}
this.inited = true;
const showMenus = _.cloneDeep(frameworkMenus[0].children);
this.frameworkMenus = filterMenus(showMenus, (item) => {
return item?.meta?.showOnHeader !== false;
});
this.fixedAsideMenus = findMenus(showMenus, (item) => {
return item?.meta?.fixedAside === true;
});
this.headerMenus = headerMenus;
this.setAsideMenu();
},
setAsideMenu(topMenu?) {
if (this.frameworkMenus.length === 0) {
return;
}
if (topMenu == null) {
topMenu = this.frameworkMenus[0];
}
const asideMenus = topMenu?.children || [];
this.asideMenus = [...this.fixedAsideMenus, ...asideMenus];
},
setAsideMenuByCurrentRoute(matched) {
const menuHeader = this.frameworkMenus;
if (matched?.length <= 1) {
return;
}
function findFromTree(tree, find) {
const results: Array<any> = [];
for (const item of tree) {
if (find(item)) {
results.push(item);
return results;
}
if (item.children && item.children.length > 0) {
const found = findFromTree(item.children, find);
if (found) {
results.push(item);
return results.concat(found);
}
}
}
}
const matchedPath = matched[1].path;
const _side = findFromTree(menuHeader, (menu) => menu.path === matchedPath);
if (_side?.length > 0) {
if (this.currentAsidePath === _side[0]) {
return;
}
this.currentAsidePath = _side[0];
this.setAsideMenu(_side[0]);
}
},
filterByPermission(permissions) {
this.frameworkMenus = this.filterChildrenByPermission(this.frameworkMenus, permissions);
},
filterChildrenByPermission(list, permissions) {
const menus = list.filter((item) => {
if (item?.meta?.permission) {
return permissions.includes(item.meta.permission);
}
return true;
});
for (const menu of menus) {
if (menu.children && menu.children.length > 0) {
menu.children = this.filterChildrenByPermission(menu.children, permissions);
}
}
return menus;
}
}
});

View File

@@ -1,63 +0,0 @@
import { defineStore } from "pinia";
// @ts-ignore
import { LocalStorage } from "/src/utils/util.storage";
// import { replaceStyleVariables } from "vite-plugin-theme/es/client";
// import { getThemeColors, generateColors } from "/src/../build/theme-colors";
//
// import { mixLighten, mixDarken, tinycolor } from "vite-plugin-theme/es/colorUtils";
// export async function changeTheme(color?: string) {
// if (color == null) {
// return;
// }
// const colors = generateColors({
// mixDarken,
// mixLighten,
// tinycolor,
// color
// });
//
// return await replaceStyleVariables({
// colorVariables: [...getThemeColors(color), ...colors]
// });
// }
interface SettingState {
theme: any;
}
const SETTING_THEME_KEY = "SETTING_THEME";
export const useSettingStore = defineStore({
id: "app.setting",
state: (): SettingState => ({
// user info
theme: null
}),
getters: {
getTheme(): any {
return this.theme || LocalStorage.get(SETTING_THEME_KEY) || {};
}
},
actions: {
persistTheme() {
LocalStorage.set(SETTING_THEME_KEY, this.getTheme);
},
async setTheme(theme?: Object) {
if (theme == null) {
theme = this.getTheme;
}
this.theme = theme;
this.persistTheme();
// await changeTheme(this.theme.primaryColor);
},
async setPrimaryColor(color) {
const theme = this.theme;
theme.primaryColor = color;
await this.setTheme();
},
async init() {
await this.setTheme(this.getTheme);
}
}
});

View File

@@ -11,6 +11,7 @@ import { Modal } from "ant-design-vue";
import { useI18n } from "vue-i18n";
import { mitter } from "/src/utils/util.mitt";
import { resetAllStores, useAccessStore } from "/@/vben/stores";
interface UserState {
userInfo: Nullable<UserInfoRes>;
@@ -36,8 +37,10 @@ export const useUserStore = defineStore({
}
},
actions: {
setToken(info: string, expire: number) {
this.token = info;
setToken(token: string, expire: number) {
this.token = token;
const accessStore = useAccessStore();
accessStore.setAccessToken(token);
LocalStorage.set(TOKEN_KEY, this.token, expire);
},
setUserInfo(info: UserInfoRes) {
@@ -79,6 +82,7 @@ export const useUserStore = defineStore({
*/
logout(goLogin = true) {
this.resetState();
resetAllStores();
goLogin && router.push("/login");
mitter.emit("app.logout");
},
@@ -99,8 +103,3 @@ export const useUserStore = defineStore({
}
}
});
// Need to be used outside the setup
export function useUserStoreWidthOut() {
return useUserStore(store);
}

View File

@@ -0,0 +1,47 @@
.ant-layout .ant-layout-sider{
background-color: #ebf1f6;
}
.ant-layout .ant-layout-header{
background-color: #ebf1f6;
}
.fs-multiple-page-control-group .fs-multiple-page-control-content{
overflow-y: hidden;
}
.fs-multiple-page-control-group .fs-multiple-page-control-btn .ant-btn{
border-bottom-left-radius:0;
border-bottom-right-radius:0;
}
.ant-menu-horizontal{
border-bottom: 0;
}
.fs-framework .header-menu{
overflow-y: hidden;
}
.ant-btn.ant-btn-icon-only{
padding-inline:revert;
}
//适配手机端
.ant-tour{
max-width: 90vw
}
.fs-page{
.fs-page-header{
background-color: hsl(var(--card));
}
.fs-crud-table{
background-color: hsl(var(--card));
}
}
footer{
background-color: hsl(var(--card)) !important;
}

View File

@@ -3,7 +3,7 @@
@import './scroll.less';
@import './transition.less';
@import './fix-windicss.less';
@import './antdv4.less';
html, body {
margin: 0;
padding: 0;
@@ -12,6 +12,9 @@ html, body {
box-sizing: border-box;
}
body{
//min-width: 1000px;
}
div#app {
height: 100%
}
@@ -42,3 +45,21 @@ h1, h2, h3, h4, h5, h6 {
.anticon {
vertical-align: 0 !important;
}
.ml-5{
margin-left:5px;
}
.mt-10{
margin-top:10px;
}
.m-10{
margin:10px;
}
.p-5{
padding:5px;
}

View File

@@ -1,21 +1,21 @@
.ant-layout{
background-color: @bg-color;
background-color: @colorPrimaryBg;
}
.ant-layout-header {
background-color: @bg-color
background-color: @colorPrimaryBg
}
.ant-layout-sider {
background-color:@bg-color
background-color:@colorPrimaryBg
}
.ant-menu{
background-color: @bg-color;
background-color: @colorPrimaryBg;
&.ant-menu-submenu-popup{
background-color: transparent;
}
}
.aside-menu{
.ant-menu-submenu > .ant-menu{
background-color:@bg-color
background-color:@colorPrimaryBg
}
.ant-menu-item-active{

View File

@@ -1,4 +1,3 @@
@primary-color: #1890ff;
// theme
@bg-color: #ebf1f6;
@bg-menu-item-color:hsla(0,0%,100%,.5);
@colorPrimaryBg:#ebf1f6;
@primary-color: #1890ff;

View File

@@ -1,10 +1,4 @@
import type {
ComponentRenderProxy,
VNode,
ComponentPublicInstance,
FunctionalComponent,
PropType as VuePropType,
} from 'vue';
import type { ComponentRenderProxy, VNode, ComponentPublicInstance, FunctionalComponent, PropType as VuePropType } from "vue";
declare global {
const __APP_INFO__: {
@@ -64,7 +58,7 @@ declare global {
VITE_GLOB_APP_SHORT_NAME: string;
VITE_USE_CDN: boolean;
VITE_DROP_CONSOLE: boolean;
VITE_BUILD_COMPRESS: 'gzip' | 'brotli' | 'none';
VITE_BUILD_COMPRESS: "gzip" | "brotli" | "none";
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean;
VITE_LEGACY: boolean;
VITE_USE_IMAGEMIN: boolean;
@@ -92,8 +86,6 @@ declare global {
}
}
declare module 'vue' {
export type JSXComponent<Props = any> =
| { new (): ComponentPublicInstance<Props> }
| FunctionalComponent<Props>;
declare module "vue" {
export type JSXComponent<Props = any> = { new (): ComponentPublicInstance<Props> } | FunctionalComponent<Props>;
}

View File

@@ -1,13 +1,13 @@
import _ from "lodash-es";
import { isArray } from "lodash-es";
export default {
arrayToMap(array) {
arrayToMap(array: any) {
if (!array) {
return {};
}
if (!_.isArray(array)) {
if (!isArray(array)) {
return array;
}
const map = {};
const map: any = {};
for (const item of array) {
if (item.key) {
map[item.key] = item;
@@ -15,11 +15,11 @@ export default {
}
return map;
},
mapToArray(map) {
mapToArray(map: any) {
if (!map) {
return [];
}
if (_.isArray(map)) {
if (isArray(map)) {
return map;
}
const array: any = [];

View File

@@ -1,24 +1,28 @@
import _ from "lodash-es";
export function getEnvValue(key) {
import {forEach} from "lodash-es";
export function getEnvValue(key: string) {
// @ts-ignore
return import.meta.env["VITE_APP_" + key];
}
export class EnvConfig {
API;
MODE;
STORAGE;
TITLE;
PM_ENABLED;
API: string;
MODE: string;
STORAGE: string;
TITLE: string;
SLOGAN: string;
COPYRIGHT: string;
LOGO_PATH: string;
PM_ENABLED: string;
constructor() {
this.init();
}
init() {
// @ts-ignore
_.forEach(import.meta.env, (value, key) => {
forEach(import.meta.env, (value, key) => {
if (key.startsWith("VITE_APP")) {
key = key.replace("VITE_APP_", "");
// @ts-ignore
this[key] = value;
}
});
@@ -26,7 +30,8 @@ export class EnvConfig {
this.MODE = import.meta.env.MODE;
}
get(key, defaultValue) {
get(key: string, defaultValue: string) {
// @ts-ignore
return this[key] ?? defaultValue;
}
isDev() {

View File

@@ -4,7 +4,7 @@ export const site = {
* @description 更新标题
* @param {String} title 标题
*/
title: function (titleText) {
title: function (titleText: string) {
const processTitle = env.TITLE || "FsAdmin";
window.document.title = `${processTitle}${titleText ? ` | ${titleText}` : ""}`;
}

View File

@@ -1,5 +1,5 @@
import { env } from "./util.env";
function isNullOrUnDef(value) {
function isNullOrUnDef(value: any) {
return value == null;
}
const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 7;

View File

@@ -0,0 +1,47 @@
<!--
Access control component for fine-grained access control.
TODO: 可以扩展更完善的功能
1. 支持多个权限码只要有一个权限码满足即可 或者 多个权限码全部满足
2. 支持多个角色只要有一个角色满足即可 或者 多个角色全部满足
3. 支持自定义权限码和角色的判断逻辑
-->
<script lang="ts" setup>
import { computed } from "vue";
import { useAccess } from "./use-access";
interface Props {
/**
* Specified codes is visible
* @default []
*/
codes?: string[];
/**
* 通过什么方式来控制组件,如果是 role则传入角色如果是 code则传入权限码
* @default 'role'
*/
type?: "code" | "role";
}
defineOptions({
name: "AccessControl"
});
const props = withDefaults(defineProps<Props>(), {
codes: () => [],
type: "role"
});
const { hasAccessByCodes, hasAccessByRoles } = useAccess();
const hasAuth = computed(() => {
const { codes, type } = props;
return type === "role" ? hasAccessByRoles(codes) : hasAccessByCodes(codes);
});
</script>
<template>
<slot v-if="!codes"></slot>
<slot v-else-if="hasAuth"></slot>
</template>

View File

@@ -0,0 +1,84 @@
import type { AccessModeType, GenerateMenuAndRoutesOptions, RouteRecordRaw } from "/@/vben/types";
import { cloneDeep, generateMenus, generateRoutesByBackend, generateRoutesByFrontend, mapTree } from "/@/vben/utils";
async function generateAccessible(mode: AccessModeType, options: GenerateMenuAndRoutesOptions) {
const { router } = options;
options.routes = cloneDeep(options.routes);
// 生成路由
const accessibleRoutes = await generateRoutes(mode, options);
const root = router.getRoutes().find((item: any) => item.path === "/");
// 动态添加到router实例内
accessibleRoutes.forEach((route) => {
if (root && !route.meta?.noBasicLayout) {
// 为了兼容之前的版本用法如果包含子路由则将component移除以免出现多层BasicLayout
// 如果你的项目已经跟进了本次修改移除了所有自定义菜单首级的BasicLayout可以将这段if代码删除
if (route.children && route.children.length > 0) {
delete route.component;
}
root.children?.push(route);
} else {
router.addRoute(route);
}
});
if (root) {
if (root.name) {
router.removeRoute(root.name);
}
router.addRoute(root);
}
// 生成菜单
const accessibleMenus = await generateMenus(accessibleRoutes, options.router);
return { accessibleMenus, accessibleRoutes };
}
/**
* Generate routes
* @param mode
* @param options
*/
async function generateRoutes(mode: AccessModeType, options: GenerateMenuAndRoutesOptions) {
const { forbiddenComponent, roles, routes } = options;
let resultRoutes: RouteRecordRaw[] = routes;
switch (mode) {
case "backend": {
resultRoutes = await generateRoutesByBackend(options);
break;
}
case "frontend": {
resultRoutes = await generateRoutesByFrontend(routes, roles || [], forbiddenComponent);
break;
}
}
/**
* 调整路由树,做以下处理:
* 1. 对未添加redirect的路由添加redirect
*/
resultRoutes = mapTree(resultRoutes, (route) => {
// 如果有redirect或者没有子路由则直接返回
if (route.redirect || !route.children || route.children.length === 0) {
return route;
}
const firstChild = route.children[0];
// 如果子路由不是以/开头,则直接返回,这种情况需要计算全部父级的path才能得出正确的path这里不做处理
if (!firstChild?.path || !firstChild.path.startsWith("/")) {
return route;
}
route.redirect = firstChild.path;
return route;
});
return resultRoutes;
}
export { generateAccessible };

View File

@@ -0,0 +1,42 @@
/**
* Global authority directive
* Used for fine-grained control of component permissions
* @Example v-access:role="[ROLE_NAME]" or v-access:role="ROLE_NAME"
* @Example v-access:code="[ROLE_CODE]" or v-access:code="ROLE_CODE"
*/
import type { App, Directive, DirectiveBinding } from 'vue';
import { useAccess } from './use-access';
function isAccessible(
el: Element,
binding: DirectiveBinding<string | string[]>,
) {
const { accessMode, hasAccessByCodes, hasAccessByRoles } = useAccess();
const value = binding.value;
if (!value) return;
const authMethod =
accessMode.value === 'frontend' && binding.arg === 'role'
? hasAccessByRoles
: hasAccessByCodes;
const values = Array.isArray(value) ? value : [value];
if (!authMethod(values)) {
el?.remove();
}
}
const mounted = (el: Element, binding: DirectiveBinding<string | string[]>) => {
isAccessible(el, binding);
};
const authDirective: Directive = {
mounted,
};
export function registerAccessDirective(app: App) {
app.directive('access', authDirective);
}

View File

@@ -0,0 +1,4 @@
export { default as AccessControl } from './access-control.vue';
export * from './accessible';
export * from './directive';
export * from './use-access';

View File

@@ -0,0 +1,52 @@
import { computed } from "vue";
import { preferences, updatePreferences } from "@vben/preferences";
import { useAccessStore, useUserStore } from "@vben/stores";
function useAccess() {
const accessStore = useAccessStore();
const userStore = useUserStore();
const accessMode = computed(() => {
return preferences.app.accessMode;
});
/**
* 基于角色判断是否有权限
* @description: Determine whether there is permissionThe role is judged by the user's role
* @param roles
*/
function hasAccessByRoles(roles: string[]) {
const userRoleSet = new Set(userStore.userRoles);
const intersection = roles.filter((item) => userRoleSet.has(item));
return intersection.length > 0;
}
/**
* 基于权限码判断是否有权限
* @description: Determine whether there is permissionThe permission code is judged by the user's permission code
* @param codes
*/
function hasAccessByCodes(codes: string[]) {
const userCodesSet = new Set(accessStore.accessCodes);
const intersection = codes.filter((item) => userCodesSet.has(item));
return intersection.length > 0;
}
async function toggleAccessMode() {
updatePreferences({
app: {
accessMode: preferences.app.accessMode === "frontend" ? "backend" : "frontend"
}
});
}
return {
accessMode,
hasAccessByCodes,
hasAccessByRoles,
toggleAccessMode
};
}
export { useAccess };

Some files were not shown because too many files have changed in this diff Show More