Compare commits

..

129 Commits

Author SHA1 Message Date
橙子
de0c040cb3 !17 update Yi.Furion.Net6/Yi.Framework.Infrastructure/Helper/MimeHelper.cs. 后缀名拼写错误。
Merge pull request !17 from zsmygitee/N/A
2024-06-18 08:23:29 +00:00
zsmygitee
23276bb0fd update Yi.Furion.Net6/Yi.Framework.Infrastructure/Helper/MimeHelper.cs. 后缀名拼写错误。
后缀名拼写错误。

Signed-off-by: zsmygitee <274725822@qq.com>
2024-06-11 06:57:53 +00:00
陈淳
46c53e09a3 fix: 修复task注入问题 2024-01-10 15:06:15 +08:00
陈淳
209eb019d3 feat:去除多余job 2023-12-14 15:53:42 +08:00
陈淳
10a608c0af fix: 修复登录过期token的发放 2023-12-11 10:51:38 +08:00
陈淳
098d4bc85f feat: 添加配置多环境文件 2023-11-30 16:45:34 +08:00
陈淳
26f7d67c50 fix: 修复审计日志更新问题 2023-11-27 10:11:44 +08:00
陈淳
42d2525b46 fix: 修复审计日志赋值问题 2023-11-27 10:00:53 +08:00
陈淳
d9305c7620 feat:构建还原 2023-11-22 11:10:12 +08:00
陈淳
185d87c24e feat: 优化excel操作 2023-11-16 12:43:52 +08:00
陈淳
a4080490bd feat: 添加excel模块搭建 2023-11-15 19:12:24 +08:00
陈淳
714bcbdbb1 doc: 添加文档 2023-11-09 17:36:49 +08:00
陈淳
9158a38496 fix: 修复登录无权限问题 2023-11-09 08:49:59 +08:00
陈淳
1f1f7f167f style: 修改配置文件 2023-11-08 17:20:26 +08:00
陈淳
9453cc1c3b Merge branch 'furion' of https://gitee.com/ccnetcore/Yi into furion 2023-11-07 10:51:09 +08:00
陈淳
33a03d8119 feat: 完善缓存监控模块 2023-11-07 10:31:53 +08:00
橙子
2292fd1df6 update README.md.
Signed-off-by: 橙子 <454313500@qq.com>
2023-10-30 00:48:27 +00:00
橙子
18ac428a95 fix: 修复角色分配菜单404问题 2023-10-25 15:52:28 +08:00
橙子
f0d0c304d6 fix: 删除多余的种子数据 2023-10-19 21:47:10 +08:00
陈淳
7f041c96fb fix: 修复静态资源问题 2023-10-18 12:35:28 +08:00
陈淳
53ca11f85b fix: 修复图片打包问题 2023-10-18 12:33:12 +08:00
陈淳
a9f2a0c2ac feat: app添加默认头像 2023-10-18 12:20:43 +08:00
陈淳
181e2b21bb test: 添加bbs cicd 2023-10-18 11:49:31 +08:00
陈淳
04bc6b4cb8 fix: 修复app时间显示问题 2023-10-18 11:36:04 +08:00
陈淳
6058a1741b Merge branch 'furion' of https://gitee.com/ccnetcore/Yi into furion 2023-10-16 15:55:38 +08:00
陈淳
455f11af34 test: 测试vue3 cicd 2023-10-16 15:55:28 +08:00
橙子
0b8848d63f feat: 完善app首页应用 2023-10-08 23:50:53 +08:00
橙子
1b7d6d09a8 Merge branch 'furion' of https://gitee.com/ccnetcore/Yi into furion 2023-10-08 22:59:29 +08:00
橙子
c9592446c8 feat: 完善前端 2023-10-08 22:59:22 +08:00
橙子
f2d2055f72 style: 完善readme
Signed-off-by: 橙子 <454313500@qq.com>
2023-10-08 10:33:46 +00:00
橙子
21ce0789ef style: 完善readme
Signed-off-by: 橙子 <454313500@qq.com>
2023-10-08 10:32:45 +00:00
橙子
794a8fc6aa update README.md.
Signed-off-by: 橙子 <454313500@qq.com>
2023-10-08 10:31:48 +00:00
橙子
408ef4a7df update README.md.
Signed-off-by: 橙子 <454313500@qq.com>
2023-10-08 10:28:00 +00:00
橙子
ab9b357c9b style: 修改readme
Signed-off-by: 橙子 <454313500@qq.com>
2023-10-08 10:18:59 +00:00
橙子
68d072cd60 style: 优化分组 2023-10-07 19:28:42 +08:00
橙子
aae1d37505 stlye: 构建前端 2023-10-07 17:54:27 +08:00
橙子
e927f2ff78 style: 完善配置文件 2023-10-07 17:52:29 +08:00
橙子
c271f3005a feat: 数据库迁移 2023-10-07 17:51:05 +08:00
橙子
ca5697fb9c feat: 搭建移动端前端框架 2023-10-07 01:31:56 +08:00
橙子
9150101498 test: 测试cicd 2023-10-05 16:23:43 +08:00
橙子
6d0e6d0d16 chore: 构建cicd 2023-10-05 15:54:42 +08:00
橙子
c4236937b7 chore: 添加jenkins构建脚本 2023-10-05 15:26:33 +08:00
橙子
c1c0774572 style: 修改报错信息中文样式 2023-10-04 23:16:07 +08:00
橙子
fcb0ea9574 feat: 完成web to code及code to web功能 2023-09-28 12:59:25 +08:00
陈淳
f095fde5a7 feat: webfrist基本流程已完成 2023-09-27 18:01:10 +08:00
橙子
8bc2db1e6e feat: 完成数据表及数据字段管理 2023-09-26 22:56:21 +08:00
陈淳
7cbc15ea85 feat: 完成webfirst 数据表管理前端模块 2023-09-26 18:01:41 +08:00
陈淳
c2a9c670c4 feat: 完成界面基础搭建 2023-09-26 09:21:27 +08:00
橙子
4e5bdf6847 style: 添加webfirst种子数据 2023-09-26 00:38:10 +08:00
陈淳
0aa6443a20 fix:修复菜单排序问题 2023-09-25 18:16:20 +08:00
橙子
04278f553e feat: 添加webfirst前端路由 2023-09-24 23:41:26 +08:00
橙子
349a041d71 feat: 完成code to web模块 2023-09-24 00:42:09 +08:00
陈淳
58bf5062bf style: 修改配置样式 2023-09-22 10:49:15 +08:00
陈淳
878f24ecae style: 更改注册问题 2023-09-22 10:47:54 +08:00
陈淳
a15a374fb0 feat: 添加webfirst字段生成器 2023-09-22 10:25:05 +08:00
陈淳
8a90f9d089 style: 简化结构 2023-09-21 19:59:38 +08:00
陈淳
3007267951 feat: 准备构建数据库领域服务 2023-09-21 19:57:02 +08:00
陈淳
710bb97cd3 feat: 完善webfirst模板及表模块 2023-09-21 19:55:55 +08:00
橙子
18eb3a7fbf feat: 完善搭建生成器 2023-09-21 00:04:55 +08:00
橙子
1d499b7052 feat: 添加webfirst 字段模块 2023-09-19 23:48:37 +08:00
橙子
36b28d83ed Merge branch 'furion' of https://gitee.com/ccnetcore/Yi into furion 2023-09-18 23:31:44 +08:00
橙子
04fc03ccf5 feat:扩展webfirst 2023-09-18 23:31:36 +08:00
陈淳
ffb5898ea1 fix: 修复时间问题 2023-09-18 10:36:22 +08:00
chenchun
2c2eb0cb8d fix: 修复linux时间周问题 2023-09-17 10:50:02 +08:00
chenchun
15dd8a60d7 fix: 修复访问日志问题,添加easy.tools 2023-09-17 09:52:20 +08:00
橙子
65a0a6fb92 feat: 添加模块控制器分组功能 2023-09-15 23:56:59 +08:00
陈淳
a0b35f4233 feat: 同步 2023-09-15 18:05:59 +08:00
陈淳
a271bc25c6 style: 完善日期显示 2023-09-15 15:21:05 +08:00
陈淳
c988ed7988 feat: 添加访问统计模块 2023-09-15 15:05:14 +08:00
橙子
c2ca0b1f29 feat: 添加微信应用模块,支持微信支付及微信小程序对接(功能产品已上线验证) 2023-09-03 11:22:19 +08:00
橙子
efee87e4c5 Merge branch 'furion' of https://gitee.com/ccnetcore/Yi into furion 2023-08-13 21:27:55 +08:00
橙子
98a990d9ea feat: 添加api访问日志 2023-08-13 21:27:50 +08:00
陈淳
3a61df42ea feat: 完善aop插入审计日志 2023-08-08 10:35:09 +08:00
陈淳
d62baa0e51 fix:修复重置密码为空的问题 2023-07-19 01:24:27 +08:00
陈淳
dfe8806344 feat:完善时间格式转换 2023-07-13 16:04:15 +08:00
陈淳
f1e95b960a feat:添加模板 2023-07-05 15:51:16 +08:00
陈淳
7d0fa7f5d1 Update Login.vue 2023-06-28 16:27:13 +08:00
陈淳
174f247a8e style:添加config种子数据 2023-06-28 16:01:26 +08:00
橙子
9cc41e8558 update README.md.
Signed-off-by: 橙子 <454313500@qq.com>
2023-06-12 08:48:29 +00:00
陈淳
1fe8b9c5c9 feat:搭建webfirst模块 2023-06-10 13:53:00 +08:00
橙子
496861587d refactor:优化角色授权查询 2023-05-24 20:54:26 +08:00
陈淳
93764fc5b5 feat:完善角色授权用户功能 2023-05-24 12:29:20 +08:00
陈淳
22fab8dee0 feat:添加角色授权用户 2023-05-23 19:29:56 +08:00
陈淳
dcbd729944 feat:完成数据权限功能 2023-05-22 13:03:09 +08:00
陈淳
327a7b2a48 feat:完成后端数据权限过滤 2023-05-22 12:57:27 +08:00
橙子
ad6bd8f39b feat:添加数据权限搭建,准备完成数据权限过滤 2023-05-21 21:43:11 +08:00
橙子
95a91a10b3 feat:完善用户查询部门过滤 2023-05-21 13:16:04 +08:00
橙子
b50f2b4c7e update README.md.
Signed-off-by: 橙子 <454313500@qq.com>
2023-05-20 09:44:34 +00:00
陈淳
a1e0dac85c feat:完善前端友好提示功能 2023-05-20 17:20:52 +08:00
橙子
027f6dd538 Update README.md 2023-04-30 19:14:19 +08:00
陈淳
94f902f788 feat:完成job页面+接口功能,还差job状态更新 2023-04-25 13:30:54 +08:00
陈淳
bc5aaff9c9 feat:合并 2023-04-25 10:39:41 +08:00
陈淳
770e8d7310 feat;完成接口对接 2023-04-25 10:38:51 +08:00
陈淳
6a881e4613 feat:完善job dto 2023-04-25 09:19:17 +08:00
橙子
0f36672783 feat:添加执行一次接口 2023-04-24 21:08:12 +08:00
橙子
7d5a7e0fe8 feat:完成job后端接口 2023-04-23 23:46:20 +08:00
橙子
6977e233bb fix:修复时间映射问题 2023-04-23 23:23:31 +08:00
橙子
dbcb27e41a feat:完成job定时任务功能模块 2023-04-23 21:42:03 +08:00
橙子
4b5b4464f4 1 2023-04-23 20:47:26 +08:00
橙子
4b6241e0b0 feat:添加任务调度基础功能 2023-04-22 19:13:29 +08:00
橙子
17fb60c481 feat:添加日志记录+完善定时任务 2023-04-22 18:03:13 +08:00
橙子
51575b9f2d feat:添加任务调度,系统每天12点、0点重置一次 2023-04-21 23:44:14 +08:00
橙子
c943c1fc74 fix:完成非空问题修复 2023-04-20 23:08:21 +08:00
橙子
b55a45baa2 feat:完成codefirst与种子数据,发现非空类型问题,等待紧急修复 2023-04-20 22:36:32 +08:00
橙子
ae5db16d67 fix:修复菜单排序问题 2023-04-19 22:54:33 +08:00
橙子
8f143be4b0 feat:上线服务监控功能 2023-04-19 22:38:46 +08:00
陈淳
9ebafff392 feat:准备服务监控 2023-04-19 19:40:47 +08:00
陈淳
e904c3df69 Revert "1"
This reverts commit 8ed1c958af.
2023-04-19 18:08:38 +08:00
陈淳
8ed1c958af 1 2023-04-19 18:07:57 +08:00
陈淳
a93e65df0a feat:添加登录事件 2023-04-19 18:06:40 +08:00
陈淳
2fd861025a feat:添加种子数据 2023-04-19 16:35:47 +08:00
陈淳
654c7d650a feat:完善缓存相关 2023-04-19 13:39:55 +08:00
陈淳
cb75196455 feat:添加缓存监控页面 2023-04-19 11:19:36 +08:00
橙子
dd2b584c3d feat:添加长连接,强制下线功能 2023-04-18 21:29:44 +08:00
橙子
85d1cbff34 feat:添加令牌效验 2023-04-18 20:29:53 +08:00
陈淳
92d9c532c2 chore:优化构建结构 2023-04-18 14:46:59 +08:00
橙子
24bc61396e feat:完成furion改造 2023-04-16 14:30:56 +08:00
橙子
1655870d4d feat:全基础流程跑通 2023-04-15 22:44:33 +08:00
陈淳
9b1a978cb5 chore:完成目录改造 2023-04-15 18:03:11 +08:00
陈淳
fb27fb8aa4 chore:目录重构 2023-04-15 17:35:22 +08:00
陈淳
a612af4f68 chore:去除对于 2023-04-15 17:34:28 +08:00
陈淳
eb8e076732 chore:修改目录 2023-04-15 17:33:42 +08:00
陈淳
0401e97ed3 feat:完成异常处理 2023-04-15 14:36:48 +08:00
陈淳
c4f25b7a41 style: 修改大小写问题 2023-04-15 14:01:50 +08:00
橙子
ef5b628b31 feat:完成内部核心模块替换改造成furion 2023-04-15 12:25:47 +08:00
橙子
543c13d94b feat:让程序能够跑起来 2023-04-15 12:19:02 +08:00
橙子
b9dad93c9d feat:furion rbac搭建 2023-04-13 21:12:06 +08:00
橙子
18696ec542 feat:框架基础设施搭建 2023-04-12 22:52:09 +08:00
橙子
5efdffcda8 feat:基于furion搭建 2023-04-12 22:30:42 +08:00
907 changed files with 34913 additions and 14912 deletions

View File

@@ -30,20 +30,43 @@ Yi框架最新版本标签`v3.0.0`,具体版本可以查看标签迭代
**分支:**
本项目由EFCore版本历经3年不断迭代至Sqlsugar版本现EFcore版本已弃用目前sqlsugar已带业务功能
本项目由EFCore版本历经4年不断迭代至Sqlsugar版本现EFcore版本已弃用目前sqlsugar已带业务功能
- **Framework**: 框架分支,所有东西都在这里
- (推荐) **Furion**: 基于Furion分支回归开发本质极度简单用起来贼爽
- **Furion**: 基于Furion分支回归开发本质极度简单用起来贼爽
- ~~**Framework**~~: 框架分支,所有东西都在这里
- ~~**SqlSugar**:.Net6 DDD领域驱动设计 简单分层微服务架构~~
- ~~**SqlSugar-Dev**为sqlsugar分支的实时开发版本~~
- ~~**ec**: EFcore完整电商项目~~
- ~~**abp**:基于abp.vnext项目~~
****
**目录:**
Yi后端框架分为3个部分
- Infrastructure基础设施框架底层+sqlsugar+furion
- Module应用模块可选项例如缓存模块、微信模块、文件模块、日志模块等
- Application业务模块用于开发
另外光说不练假把式我们不仅仅提供一个空白的框架还同时提供3个基于yi框架的业务模块没有听错目前为1个后端支持3个前端。各个模块关系解耦可单独使用其中的任意业务模块
- Yi.RuoYi.Vue3Ruoyi后台管理系统Rbac Vue3前端推荐
- Yi.Furion.Net6.NET6后端推荐
- Yi.App.Vue3移动端App Vue3前端
- Yi.BBS.Vue3Web网页端BBS论坛 Vue3+Ts前端
后续我们持续更新各大应用模块及业务模块shop商场、erp进销存、mes工厂系统等
业务支持并扩展至各个领域,用于具体项目的二次开发极大复用后端代码及前端代码,以通用的部分+不通的部分快速二开
### 演示地址:
废话少说直接上地址,**请不要**更改里面的数据
@@ -54,14 +77,15 @@ Bbs社区系统[ccnetcore.com](https://ccnetcore.com) (已上线,欢迎加
Rbac后台管理系统[yi.ccnetcore.com](http://yi.ccnetcore.com) (已上线)~~管理员账号cc 、 123456~~
网关地址:~~[gate.ccnetcore.com/swagger](http://gate.ccnetcore.com/swagger)~~(目前使用单体架构)
App移动端系统[xxx](xxx)正在部署
网关地址:~~[gate.ccnetcore.com/swagger](http://gate.ccnetcore.com/swagger)~~(目前使用单体架构部署,无需网关)
### 支持:
- [x] 完全支持单体应用架构
- [x] 完全支持分布式应用架构
- [x] 完全支持微服务架构
- [ ] 即将支持网格服务架构我们将在后续版本加入dapr
****
### 详细到爆炸的Yi框架教程导航
@@ -78,8 +102,6 @@ Rbac后台管理系统[yi.ccnetcore.com](http://yi.ccnetcore.com) (已上
例如我们大部分功能紧密贴合Sqlsugar虽然缺少其他orm的替换性但在使用程度上降低的使用难度
例如:我们在应用层中使用属性注入,虽然依赖关系会比较模糊,但是使用起来会减少一定代码量
> 一个面向用户的快速开发后端框架
在真正的使用这,你会明白这一点,极致的简单,也是优雅的一种体现。
@@ -127,11 +149,12 @@ Rbac后台管理系统[yi.ccnetcore.com](http://yi.ccnetcore.com) (已上
- 操作日志管理
- Sms短信
- 微信支付
- 模板代码生成
- WebFirst代码生成
### 业务项目
- RABC后台管理系统
- BBS社区系统
- APP移动端系统
> 重复的东西,无需再写一遍,这也是优雅的体现之一
@@ -183,7 +206,10 @@ RABC权限管理系统正在更新
- 用户在线
- 操作日志
- 登录日志
- 等等
- 定时任务
- 缓存列表
- 服务监控
- WebFirst代码生成工具
**演示截图:**
![输入图片说明](readme/1.png)
@@ -196,6 +222,8 @@ RABC权限管理系统正在更新
![输入图片说明](readme/8.png)
![输入图片说明](readme/9.png)
![输入图片说明](readme/10.png)
![输入图片说明](readme/1696760969217.jpg)
![输入图片说明](readme/1696761014270.jpg)
BBS论坛系统持续迭代
- 文章管理
@@ -205,7 +233,11 @@ BBS论坛系统持续迭代
- 点赞管理
- 等等
ERP进销存系统正在更新
APP移动端系统持续迭代
- 动态查询
- 我的资料
ERP进销存系统持续迭代
- 供货商管理
- 等等
@@ -228,18 +260,22 @@ SHOP电商系统持续迭代
[朝夕教育]https://www.zhaoxiedu.net
[Sqlsugar]https://www.donet5.com/Home/Doc
[Sqlsugar老杰哥]https://www.donet5.com/Home/Doc
[RuYiAdmin]https://gitee.com/pang-mingjun/RuYiAdmin
[RuYiAdmin如意老兄]https://gitee.com/pang-mingjun/RuYiAdmin
[ZrAdminNetCore]https://gitee.com/izory/ZrAdminNetCore
[ZrAdminNetCore字母老哥]https://gitee.com/izory/ZrAdminNetCore
[Admin.NET周哥]https://gitee.com/zuohuaijun/Admin.NET
[Furion百小僧]https://furion.baiqian.ltd/
****
### 联系我们:
作者QQ`454313500`2029年之前作者24小时在线时刻保持活跃更新。
QQ交流群官方一群已满、官方二群已满、官方三群`786308927`加作者QQ后同意
QQ交流群官方一群已满、官方二群已满、官方三群`786308927`基本已满)、官方四群:`498310311`(新群
联系作者,这里人人都是顾问

View File

@@ -0,0 +1,17 @@
# 页面标题
VITE_APP_TITLE = 意框架管理系统
# 开发环境配置
VITE_APP_ENV = 'development'
# 若依管理系统/开发环境
VITE_APP_BASE_API = '/dev-api'
# ws/开发环境
VITE_APP_BASE_WS = '/dev-ws'
VITE_APP_BASE_URL='http://localhost:19001/api'

View File

@@ -0,0 +1,15 @@
# 页面标题
VITE_APP_TITLE = 意框架管理系统
# 生产环境配置
VITE_APP_ENV = 'production'
# 意框架管理系统/生产环境
VITE_APP_BASE_API = '/prod-api'
# ws/开发环境
VITE_APP_BASE_WS = '/prod-ws'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip

15
Yi.App.Vue3/.env.staging Normal file
View File

@@ -0,0 +1,15 @@
# 页面标题
VITE_APP_TITLE = 意框架管理系统
# 生产环境配置
VITE_APP_ENV = 'staging'
# 若依管理系统/生产环境
VITE_APP_BASE_API = '/stage-api'
# ws/开发环境
VITE_APP_BASE_WS = '/stage-ws'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip

24
Yi.App.Vue3/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

3
Yi.App.Vue3/.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}

16
Yi.App.Vue3/README.md Normal file
View File

@@ -0,0 +1,16 @@
# Vue 3 + TypeScript + Vite
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
## Type Support For `.vue` Imports in TS
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can enable Volar's Take Over mode by following these steps:
1. Run `Extensions: Show Built-in Extensions` from VS Code's command palette, look for `TypeScript and JavaScript Language Features`, then right click and select `Disable (Workspace)`. By default, Take Over mode will enable itself if the default TypeScript extension is disabled.
2. Reload the VS Code window by running `Developer: Reload Window` from the command palette.
You can learn more about Take Over mode [here](https://github.com/johnsoncodehk/volar/discussions/471).

13
Yi.App.Vue3/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>意框架</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

2543
Yi.App.Vue3/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

29
Yi.App.Vue3/package.json Normal file
View File

@@ -0,0 +1,29 @@
{
"name": "yi",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.1.2",
"json-bigint": "^1.0.0",
"pinia": "^2.0.23",
"vant": "^3.6.3",
"vue": "^3.2.37",
"vue-router": "^4.1.5",
"vuex": "^4.0.2"
},
"devDependencies": {
"@types/json-bigint": "^1.0.1",
"@types/node": "^18.8.2",
"@vitejs/plugin-vue": "^3.1.0",
"typescript": "^4.6.4",
"unplugin-vue-components": "^0.22.7",
"vite": "^3.1.0",
"vue-tsc": "^0.40.4"
}
}

BIN
Yi.App.Vue3/public/icon.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

16
Yi.App.Vue3/src/App.vue Normal file
View File

@@ -0,0 +1,16 @@
<template>
<!-- <HelloWorld msg="123"></HelloWorld> -->
<router-view></router-view>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
import myaxios from '@/utils/myaxios'
export default {
operate(data:any) {
return myaxios({
url: `/agree/operate`,
method: 'get',
params: {articleId:data}
})
},
}

View File

@@ -0,0 +1,18 @@
import myaxios from '@/utils/myaxios'
export default {
add(data:any) {
return myaxios({
url: `/Trends`,
method: 'post',
data: data
})
},
pageList(data:any) {
return myaxios({
url: '/Trends',
method: 'get',
params: data
})
}
}

View File

@@ -0,0 +1,17 @@
import myaxios from '@/utils/myaxios'
export default {
add(data:any) {
return myaxios({
url: `/comment/add`,
method: 'post',
data: data
})
},
getListByArticleId(articleId:any) {
return myaxios({
url: `/comment/GetListByArticleId/${articleId}`,
method: 'get',
})
}
}

View File

@@ -0,0 +1,12 @@
import myaxios from '@/utils/myaxios'
export default{
upload(data:any){
return myaxios({
url: `/file`,
headers:{"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"},
method: 'post',
data:data
});
}
}

View File

@@ -0,0 +1,59 @@
import myaxios from '@/utils/myaxios'
// 登录方法
export function login(username:string, password:string, code:string, uuid:string) {
const data = {
username,
password,
code,
uuid
}
return myaxios({
url: '/account/login',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 注册方法
export function register(data:any) {
return myaxios({
url: '/register',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 获取用户详细信息
export function getInfo() {
return myaxios({
url: '/account',
method: 'get'
})
}
// 退出方法
export function logout() {
return myaxios({
url: '/account/logout',
method: 'post'
})
}
// 获取验证码
export function getCodeImg() {
return myaxios({
url: '/account/captchaImage',
headers: {
isToken: false
},
method: 'get',
timeout: 20000
})
}

View File

@@ -0,0 +1,18 @@
import myaxios from '@/utils/myaxios'
export default {
add(data:any) {
return myaxios({
url: `/sku/add`,
method: 'post',
data: data
})
},
pageList(data:any) {
return myaxios({
url: '/sku/pageList',
method: 'get',
params: data
})
}
}

View File

@@ -0,0 +1,25 @@
import myaxios from '@/utils/myaxios'
export default {
add(data: any) {
return myaxios({
url: `/spu/add`,
method: 'post',
data: data
})
},
pageList(data: any) {
return myaxios({
url: '/spu/pageList',
method: 'get',
params: data
})
},
getById(id: any) {
return myaxios({
url: `/spu/GetById/${id}`,
method: 'get',
})
},
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

View File

@@ -0,0 +1,61 @@
<template>
<div class="out-div">
<div class="card-div">
<van-image
radius="1rem"
width="100%"
height="100%"
src="https://unpkg.com/@vant/assets/cat.jpeg"
/>
</div>
<div class="bottom-div">
<div v-for="i of 10" :key="i" class="card-div-inside">
<van-image
radius="1rem"
width="4rem"
height="4rem"
src="https://unpkg.com/@vant/assets/cat.jpeg"
/>
<br>
79.0
</div>
</div>
</div>
</template>
<style scoped>
.out-div {
width: 100%;
min-height: 10rem;
border-radius: 1rem;
background-color: #ffffff;
}
.card-div {
height: 6rem;
width: 100%;
}
.bottom-div {
display: flex;
/* justify-content: center; */
width: 100%;
height: 6rem;
overflow: hidden;
overflow-x: auto;
white-space: nowrap;
}
.card-div-inside {
flex: none;
display: block;
margin-top: 0.5rem;
margin-left: 0.5rem;
margin-right: 0.5rem;
}
</style>

View File

@@ -0,0 +1,37 @@
<template>
<span class="subtitle">{{ showTime }}</span>
</template>
<style scoped>
</style>
<script setup lang="ts">
import { ref, computed } from "vue";
const props = defineProps<{ time: string }>();
const showTime = computed(() => {
var dataTime=new Date(Date.parse(props.time));
const hour:number= getHour(dataTime,new Date())
if(hour<=0)
{
return "刚刚"
}
if(hour<=6)
{
return hour+"小时前"
}
return props.time;
});
const getHour=(s1:Date, s2:Date)=> {
var ms = s2.getTime() - s1.getTime();
if (ms < 0) return 0;
return Math.floor(ms / 1000 / 60 / 60); //小时
}
</script>
<style scoped>
.subtitle{
color: #CBCBCB;
}
</style>

View File

@@ -0,0 +1,34 @@
<template>
<van-row>
<van-col span="24">
<p > {{data.head}}</p>
</van-col>
<van-col class="col-body" span="6" v-for="item in data.body"><van-icon :name="item.icon" size="2rem" /> <br>{{item.title}}</van-col>
</van-row>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import {AppGridData} from '@/type/class/AppGridData'
defineProps<{ data: AppGridData }>()
const count = ref(0)
</script>
<style scoped>
.col-body
{
text-align: center;
font-size: small;
}
.col-body .van-icon
{
color: #FF689B;
margin-bottom: 0.6rem;
}
p{
font-size: large;
font-weight:bold;
}
</style>

View File

@@ -0,0 +1,35 @@
<template>
<van-image round :width="width" :height="height" :src="getUrl()" />
</template>
<script setup lang="ts">
const props = defineProps({
src: { type: String, default: "null", required: false },
width: { type: String, default: "3rem", required: false },
height: { type: String, default: "3rem", required: false },
});
const url = `${import.meta.env.VITE_APP_BASE_API}/file/`;
const getUrl = () => {
const src = props.src;
if (src === null || typeof src === "undefined" || src.trim() === "") {
return "/icon.jpg";
// 字符串为 null、未定义或为空字符串
} else {
return url + "src";
}
};
</script>
<style scoped>
.col-body {
text-align: center;
}
.col-body .van-icon {
margin-bottom: 0.6rem;
}
p {
font-size: large;
font-weight: bold;
}
</style>

View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
import { ref } from 'vue'
defineProps<{ msg: string }>()
const count = ref(0)
</script>
<template>
<h1>{{ msg }}</h1>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>

View File

@@ -0,0 +1,76 @@
<template>
<van-tabbar v-model="active" active-color="#FF689B" inactive-color="#9C9C9C" @change="onChange" z-index="100">
<van-tabbar-item v-for="item in tabbar.slice(0,2)" :to="item.to" :icon="item.icon">{{item.title}}</van-tabbar-item>
<van-tabbar-item @click="show = true">
<template #icon="props">
<van-icon class="add" name="add-square" color="#FF689B" size="3rem" />
<!-- <img :src="props.active ? icon.active : icon.inactive" /> -->
</template>
</van-tabbar-item>
<van-tabbar-item v-for="item in tabbar.slice(3)" :to="item.to" :icon="item.icon">{{item.title}}</van-tabbar-item>
</van-tabbar>
<van-action-sheet v-model:show="show" >
<router-link to="/imageText"> <van-button class="btn1 btn " style="background-color: #5FBC76;" >发图文</van-button></router-link>
<van-button class="btn" style="background-color: #FF689B;">(暂未开放)发视频</van-button>
<van-button class="btn" style="background-color: #F7A63A;">(暂未开放)发文章</van-button>
<van-button class="btn" style="background-color: #6AB5EE;">(暂未开放)发二手</van-button>
<van-icon class="icon" name="cross" size="1.5rem" @click="show=false"/>
</van-action-sheet>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const active = ref(0);
const show = ref(false);
let tabbar=ref([
{icon:"wap-home",to:"/",title:"主页"},
{icon:"location-o",to:"",title:"发现"},
{icon:"",to:"",title:""},
{icon:"friends-o",to:"/shopIndex",title:"商城"},
// {icon:"friends-o",to:"",title:"商城"},
{icon:"setting-o",to:"/my",title:"我的"},
])
const onChange=(index:number)=>{
tabbar.value=[
{icon:"wap-home-o",to:"/",title:"主页"},
{icon:"location-o",to:"",title:"发现"},
{icon:"",to:"",title:""},
{icon:"friends-o",to:"/shopIndex",title:"商城"},
// {icon:"friends-o",to:"",title:"商城"},
{icon:"setting-o",to:"/my",title:"我的"},
];
tabbar.value[index].icon=tabbar.value[index].icon.replace("-o","")
}
</script>
<style>
.btn1
{
margin-top: 3rem !important;
}
.btn{
border-radius:0.5rem;
height: 4rem;
width:90%;
margin: 0.5rem 1rem 0.5rem 1rem;
color: #FFFFFF;
}
.content {
padding: 16px 16px 160px;
}
.icon{
margin-bottom: 1.5rem;
}
.add{
margin-top: 0.2rem;
}
</style>

View File

@@ -0,0 +1,9 @@
<template>
<van-nav-bar
title="标题"
left-text="返回"
left-arrow
/>
<br>
<router-view />
</template>

View File

@@ -0,0 +1,13 @@
<script setup lang="ts">
import { ref } from 'vue'
import AppBottom from './bottom/index.vue'
</script>
<template>
<router-view></router-view>
<app-bottom/>
</template>

View File

@@ -0,0 +1,12 @@
<template>
<app-tab />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import AppTab from '@/layout/tab/index.vue'
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,45 @@
<template >
<van-sticky :offset-top="0">
<van-row class="row" >
<van-col span="4" class="icon"><van-icon name="sign" size="1.6rem"/></van-col>
<van-col span="16">
<van-tabs v-model:active="active" class="tabs" sticky swipeable color="#FF689B">
<van-tab v-for="item in tabs" :title="item.title" :to="item.to" class="tab" :style="{fontSize: 0 + 'px'}" ></van-tab>
</van-tabs>
</van-col>
<van-col span="4" class="icon"><van-icon name="search" size="1.6rem" /></van-col>
</van-row>
</van-sticky>
<router-view />
<div style=""></div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const active = ref(1);
const tabs=ref([
{title:"关注",to:"/follow"},
{title:"推荐",to:"/recommend"},
{title:"广场",to:"/square"},
])
</script>
<style scoped>
.row{
background-color: #FFFFFF;
min-width: 24rem;
}
.tab{
}
.icon{
padding-top: 0.6rem;
}
.tabs {
width: 100%;
}
.icon .van-icon
{
color:#FF689B;
}
</style>

17
Yi.App.Vue3/src/main.ts Normal file
View File

@@ -0,0 +1,17 @@
import { createApp } from 'vue'
import './style.css'
import 'vant/es/image-preview/style';
import 'vant/es/toast/style';
import 'vant/es/dialog/style';
import 'vant/es/notify/style';
import router from './router'
import store from './store'
import './permission'
import { Lazyload } from 'vant';
import App from './App.vue'
const app=createApp(App)
app.use(router)
app.use(store)
app.use(Lazyload);
app.mount('#app');

View File

@@ -0,0 +1,52 @@
import router from './router'
// import { ElMessage } from 'element-plus'
// import NProgress from 'nprogress'
// import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
// import { isHttp } from '@/utils/validate'
import useUserStore from '@/store/modules/user.js'
import { isRelogin } from '@/utils/myaxios'
// import useSettingsStore from '@/store/modules/settings'
// import usePermissionStore from '@/store/modules/permission'
// NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/auth-redirect', '/bind', '/register'];
router.beforeEach((to, from, next) => {
// NProgress.start()
if (getToken()) {
// to.meta.title && useSettingsStore().setTitle(to.meta.title)
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
// NProgress.done()
} else {
if (useUserStore().roles.length === 0) {
isRelogin.show = true
useUserStore().getInfo().then((response: any) => {
next()
});
}
else
{
next()
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
// NProgress.done()
}
}
})
router.afterEach(() => {
// NProgress.done()
})

View File

@@ -0,0 +1,92 @@
import { createWebHistory, createRouter } from 'vue-router';
import Layout from '@/layout/index.vue';
import HeadLayout from '@/layout/head/index.vue'
export const constantRoutes = [
{
name:'Layout',
path: '/',
component: Layout,
redirect:"/recommend",
children: [
{
path: '/shopIndex',
component: () => import('@/view/shop/shopIndex.vue'),
name: 'ShopIndex',
},
{
path: '/my',
component: () => import('@/view/my.vue'),
name: 'My',
},
{
path: '/main',
component: () => import('@/layout/main/index.vue'),
name: 'Main',
children:[
{
path: '/recommend',
component: () => import('@/view/main/recommend.vue'),
name: 'Recommend',
},
{
path: '/follow',
component: () => import('@/view/main/follow.vue'),
name: 'Follow',
},
{
path: '/square',
component: () => import('@/view/main/square.vue'),
name: 'Square',
},
]
}
]
},
{
path: '/imageText',
component: () => import('@/view/send/imageText.vue'),
name: 'ImageText',
},
{
path: '/login',
component: () => import('@/view/login.vue'),
name: 'Login',
},
{
name:'Shop',
path: '/shop',
component: HeadLayout,
redirect:"/shopIndex",
children: [
{
path: '/shopDetails',
component: () => import('@/view/shop/shopDetails.vue'),
name: 'ShopDetails',
},
{
path: '/shopSearch',
component: () => import('@/view/shop/shopSearch.vue'),
name: 'ShopSearch',
},
]
}
];
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
},
});
export default router;

View File

@@ -0,0 +1,4 @@
import { createPinia } from 'pinia'
const store = createPinia()
export default store

View File

@@ -0,0 +1,87 @@
import { login, logout, getInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
// import defAva from '@/assets/images/profile.jpg'
import {defineStore} from 'pinia'
const useUserStore = defineStore(
'user',
{
state: () => ({
token: getToken(),
user:{username:"",nick:"",icon:""},
roles: [],
permissions: []
}),
actions: {
// 登录
login(userInfo:any ) {
const username = userInfo.username.trim()
const password = userInfo.password
const code = userInfo.code
const uuid = userInfo.uuid
return new Promise((resolve, reject) => {
login(username, password, code, uuid).then(res => {
if(!(res as any).succeeded)
{
reject(res)
}
setToken(res.data.token);
this.token = res.data.token;
return resolve(res);
}).catch(error => {
return reject(error)
})
})
},
// 获取用户信息
getInfo() {
return new Promise((resolve, reject) => {
getInfo().then(response => {
const res=response.data;
const user = res.user
// const avatar = (user.avatar == "" || user.avatar == null) ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
if (res.roleCodes && res.roleCodes.length > 0) { // 验证返回的roles是否是一个非空数组
this.roles = res.roleCodes
this.permissions = res.permissionCodes
// this.roles = ["admin"];
// this.permissions=["*:*:*"]
} else {
this.roles = ["ROLE_DEFAULT"] as never[]
}
// this.roles = ["admin"];
// this.permissions=["*:*:*"]
this.user.username = user.userName;
this.user.nick=user.nick
this.user.icon = user.icon;
resolve(res)
}).catch(error => {
reject(error)
})
})
},
// 退出系统
logOut() {
return new Promise((resolve, reject) => {
//this.token
logout().then((response) => {
this.token = ''
this.roles = []
this.permissions = []
removeToken()
resolve(response)
}).catch(error => {
reject(error)
})
})
}
}
})
export default useUserStore

87
Yi.App.Vue3/src/style.css Normal file
View File

@@ -0,0 +1,87 @@
#app {
max-width: 1280px;
margin: 0 auto;
padding: 0rem;
text-align: center;
}
/* :root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 0rem;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
} */

View File

@@ -0,0 +1,11 @@
export class AppGridData{
head!: string;
body!: AppGridBody[];
}
class AppGridBody{
icon!: string;
title!: string;
}

View File

@@ -0,0 +1,8 @@
export interface ArticleEntity{
title: string;
content: string;
images:string[];
isDeleted:boolean;
creationTime:string;
}
// import { ArticleEntity } from '@/type/interface/ArticleEntity'

View File

@@ -0,0 +1,13 @@
const TokenKey = 'Admin-Token'
export function getToken() {
return localStorage.getItem(TokenKey)
}
export function setToken(token:string) {
return localStorage.setItem(TokenKey, token)
}
export function removeToken() {
return localStorage.removeItem(TokenKey)
}

View File

@@ -0,0 +1,95 @@
import axios from 'axios'
// import store from '../store/index'
// import vm from '../main'
import JsonBig from 'json-bigint'
import { getToken } from '@/utils/auth'
import { useRouter } from "vue-router";
import useUserStore from '@/store/modules/user.js'
import { Notify } from 'vant';
// import VuetifyDialogPlugin from 'vuetify-dialog/nuxt/index';
export let isRelogin = { show: false };
const myaxios = axios.create({
// baseURL:'/'//
baseURL: import.meta.env.VITE_APP_BASE_API, // /dev-apis
timeout: 50000,
headers: {
'Authorization': 'Bearer ' + ""
},
//雪花id精度问题
transformResponse: [data => {
const json = JsonBig({
storeAsString: true
});
try {
return json.parse(data);
}
catch
{
return data;
}
}],
})
// 请求拦截器
myaxios.interceptors.request.use(function (config:any) {
const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken()
}
// store.dispatch("openLoad");
return config;
}, function (error) {
return Promise.reject(error);
});
// 响应拦截器
myaxios.interceptors.response.use(async function(response) {
//成功
const resp = response.data
if(resp.code==401)
{
Notify({ type: 'warning', message: '登录过期' });
//登出
useUserStore().logOut().then(() => {
location.href = '/';
})
isRelogin.show = false;
}
// store.dispatch("closeLoad");
return resp;
},
async function(error) {
const code=error.response.status;
const message=error.message;
//未授权、失败
if(error.response==undefined)
{
Notify({ type: 'danger', message: `服务器异常:${error.message}` });
// useUserStore().logOut().then(() => {
// location.href = '/';
// })
return Promise.reject(error);;
}
if (code == undefined &&message == undefined) {
Notify({ type: 'danger', message: '未知错误' });
} else if (code == 401) {
// if (!isRelogin.show) {
Notify({ type: 'warning', message: '登录过期' });
//登出
useUserStore().logOut().then(() => {
location.href = '/';
})
isRelogin.show = false;
// }
} else if (code !== 200) {
Notify({ type: 'danger', message: `错误代码:${code},原因:${message}` });
}
return Promise.reject(error);
});
export default myaxios

View File

@@ -0,0 +1,140 @@
<template>
<div class="div-top">
<span class="title">意框架</span>
<br />
<span class="subtitle">有幸相遇不负未来</span>
</div>
<div class="div-bottom">
<h5>密码登录</h5>
<van-field
class="van-field-username"
v-model="loginForm.username"
label="用户"
placeholder="请输入用户名"
/>
<van-field
class="van-field-password"
v-model="loginForm.password"
label="密码"
type="password"
placeholder="请输入密码"
/>
<van-button type="primary" @click="login">进入意框架</van-button>
<p>其他方式登录<van-icon name="arrow" /></p>
<van-row class="row-bottom" style="margin-top: 6rem">
<van-col span="24"><p>第三方登录</p></van-col>
<van-col span="2"></van-col>
<van-col span="5"><van-icon name="smile-o" size="2rem" /></van-col>
<van-col span="5"><van-icon name="smile-o" size="2rem" /></van-col>
<van-col span="5"><van-icon name="smile-o" size="2rem" /></van-col>
<van-col span="5"><van-icon name="smile-o" size="2rem" /></van-col>
<van-col span="2"></van-col>
</van-row>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { useRouter } from "vue-router";
import useUserStore from "@/store/modules/user.js";
import { Toast } from "vant";
import { debug } from "console";
const router = useRouter();
const redirect = ref(undefined);
const loginForm = ref({
username: "",
password: "",
rememberMe: false,
code: "",
uuid: "",
});
const userStore = useUserStore();
const login = () => {
// 调用action的登录方法
userStore
.login(loginForm.value)
.then((response: any) => {
Toast({
message: "登录成功",
position: "bottom",
});
router.push({ path: redirect.value || "/" });
})
.catch((response:any) => {
loginForm.value.password="";
Toast({
message: response.errors,
position: "bottom",
});
// loading.value = false;
// // 重新获取验证码
// if (captchaEnabled.value) {
// getCode();
// }
});
};
</script>
<style scoped>
.div-top {
background-color: #FF689B;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 60%;
}
.div-bottom {
background-color: #FFFFFF;
position: absolute;
top: 25%;
left: 0;
right: 0;
bottom: 0;
border-radius: 3rem 3rem 0rem 0rem;
padding: 1rem 2rem 2rem 2rem;
/* min-height: 70%; */
}
.title {
position: absolute;
top: 15%;
transform: translateX(-50%);
font-size: 1.8rem;
font-weight: bolder;
color: #FFFFFF;
}
.subtitle {
transform: translateX(-50%);
position: absolute;
top: 30%;
font-weight: lighter;
color: #FFFFFF;
}
.van-field-username {
margin-top: 2rem;
}
.van-field-password {
margin-top: 1rem;
}
h5 {
text-align: left;
font-size: 1.1rem;
font-weight: bolder;
}
.div-bottom .van-button {
margin-top: 1rem;
width: 100%;
border-radius: 0.4rem;
background-color: #FF689B;
border: 0;
}
.div-bottom p {
text-align: center;
color: #666666;
}
.row-bottom {
color: #FF689B;
}
</style>

View File

@@ -0,0 +1,16 @@
<template >
<van-row >
<van-col span="24">
<div class="test">这里是关注页面</div>
</van-col>
</van-row>
</template>
<style scoped>
.test
{
}
</style>

View File

@@ -0,0 +1,301 @@
<template>
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
<van-list
class="list"
v-model:loading="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
>
<van-row v-for="(item, index) in articleList" :key="index" class="row">
<van-col span="4" class="leftCol">
<AppUserIcon
width="3rem"
height="3rem"
:src="item.user == null ? null : item.user.icon"
/>
</van-col>
<van-col span="14" class="centerTitle">
<span class="justtitle">{{
item.user == null ? "-" : item.user.nick ?? item.user.username
}}</span>
<br />
<app-createTime :time="item.creationTime" />
</van-col>
<van-col span="6" class="down">
<van-icon name="arrow-down" @click="show = true" />
</van-col>
<van-col class="rowBody" span="24">{{ item.content }}</van-col>
<van-col
span="8"
v-for="(image, imageIndex) in item.images"
:key="imageIndex"
class="imageCol"
@click="openImage(item.images, imageIndex)"
>
<van-image
lazy-load
fit="cover"
width="100%"
height="7rem"
:src="url + image + '/true'"
radius="5"
/>
<template v-slot:loading>
<van-loading type="spinner" size="20" />
</template>
</van-col>
<van-col span="24" class="bottomRow">
<van-grid direction="horizontal" :column-num="3">
<van-grid-item icon="share-o" text="分享" />
<van-grid-item
icon="comment-o"
text="评论"
@click="openComment(item.id)"
/>
<!-- <van-grid-item
icon="good-job-o"
:text="`点赞:${item.agreeNum}`"
@click="aggreeHand(item.id)"
/> -->
<van-grid-item
icon="good-job-o"
:text="`点赞:10`"
@click="aggreeHand(item.id)"
/>
</van-grid>
</van-col>
</van-row>
</van-list>
</van-pull-refresh>
<!-- 功能页面 -->
<van-action-sheet
v-model:show="show"
:actions="actions"
cancel-text="取消"
close-on-click-action
/>
<!-- 图片预览 -->
<van-image-preview
v-model:show="imageShow"
:images="imagesPreview"
:startPosition="startIndex"
@change="onChange"
:closeable="true"
>
<template v-slot:index>{{ index + 1 }}</template>
</van-image-preview>
<!-- 评论面板 -->
<van-action-sheet v-model:show="commentShow" title="共10条评论">
<van-row v-for="i in commentList" :key="i" class="commentContent">
<van-col span="4">头像</van-col>
<van-col span="16">{{ i.content }}</van-col>
<van-col span="4">点赞</van-col>
</van-row>
<van-cell-group inset>
<van-field v-model="commentData.content" placeholder="请输入评论" >
<template #button>
<van-button size="small" type="primary" @click="sendComment()">发布</van-button>
</template>
</van-field>
</van-cell-group>
</van-action-sheet>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive, toRefs } from "vue";
import { ImagePreview, Toast } from "vant";
import AppCreateTime from "@/components/AppCreateTime.vue";
import AppUserIcon from "@/components/AppUserIcon.vue";
import articleApi from "@/api/articleApi";
import agreeApi from "@/api/agreeApi";
import commentApi from "@/api/commentApi";
const VanImagePreview = ImagePreview.Component;
const url = `${import.meta.env.VITE_APP_BASE_API}/file/`;
const data = reactive({
queryParams: {
pageNum: 1,
pageSize: 10,
// dictName: undefined,
// dictType: undefined,
isDeleted: false,
},
});
const commentData = reactive({
content: "",
articleId:0
});
const sendComment=()=>{
commentData.articleId=openCommentId.value;
commentApi.add(commentData).then(()=>{
getCommentList(openCommentId.value);
commentData.content="";
})
}
const { queryParams } = toRefs(data);
const {content}=toRefs(commentData);
const articleList = ref<any[]>([]);
const commentList = ref<any[]>([]);
const totol = ref<Number>(0);
const imageShow = ref(false);
const commentShow = ref<any>(false);
const index = ref(0);
let imagesPreview = ref<string[]>([]);
const openCommentId=ref(0);
const openComment = (id: any) => {
commentShow.value = true;
openCommentId.value=id;
getCommentList(id);
};
const onChange = (newIndex: any) => {
index.value = newIndex;
};
const list = ref<Number[]>([]);
const loading = ref(false);
const finished = ref(false);
const refreshing = ref(false);
const startIndex = ref(0);
const show = ref(false);
const actions = [{ name: "取消关注" }, { name: "将TA拉黑" }, { name: "举报" }];
const onLoad = async () => {
if (refreshing.value) {
articleList.value = [];
refreshing.value = false;
}
// 异步更新数据
// setTimeout 仅做示例,真实场景中一般为 ajax 请求
articleApi.pageList(queryParams.value).then((response: any) => {
if (response.data.items.length == 0) {
console.log("结束");
finished.value = true;
} else {
console.log("执行");
articleList.value.push(...response.data.items);
totol.value = response.data.totol;
queryParams.value.pageNum += 1;
}
loading.value = false;
});
};
const onRefresh = () => {
finished.value = false;
// 重新加载数据
// 将 loading 设置为 true表示处于加载状态
loading.value = true;
queryParams.value.pageNum = 1;
onLoad();
};
const openImage = (imagesUrl: string[], imageIndex: any) => {
imagesPreview.value = imagesUrl.map((i) => url + i);
startIndex.value = imageIndex;
imageShow.value = true;
};
onMounted(() => {
articleList.value = [];
// getList();
});
const getCommentList = (id: any) => {
commentApi.getListByArticleId(id).then((response: any) => {
commentList.value = response.data;
});
};
const getList = () => {
articleApi.pageList(queryParams.value).then((response: any) => {
articleList.value.push(...response.data.data);
totol.value = response.data.totol;
});
};
const aggreeHand = (articleId: any) => {
agreeApi.operate(articleId).then((response: any) => {
//更改显示的值
if (response.status) {
articleList.value.filter((p) => p.id == articleId)[0].agreeNum += 1;
} else {
articleList.value.filter((p) => p.id == articleId)[0].agreeNum -= 1;
}
Toast({
message: response.message,
position: "bottom",
});
});
};
</script>
<style scoped>
.list {
background-color: #f4f4f4;
}
.row {
background-color: white;
padding-top: 1rem;
padding-left: 1rem;
padding-right: 1rem;
margin-bottom: 0.6rem;
}
.rowBody {
text-align: left;
background-color: white;
margin-top: 1rem;
margin-bottom: 1rem;
}
.title {
padding-top: 1rem;
min-height: 3rem;
text-align: left;
}
.leftCol {
align-content: left;
text-align: left;
}
.centerTitle {
text-align: left;
}
.imageCol {
padding: 0.1rem 0.1rem 0.1rem 0.1rem;
}
.subtitle {
color: #cbcbcb;
}
.justtitle {
font-size: large;
}
.bottomRow {
color: #999999;
}
.down {
text-align: right;
padding-right: 0.5rem;
}
.commentContent {
margin-bottom: 4rem;
}
</style>

View File

@@ -0,0 +1 @@
<template>这里是广场</template>

256
Yi.App.Vue3/src/view/my.vue Normal file
View File

@@ -0,0 +1,256 @@
<template>
<van-row class="headRow">
<van-col span="2"><van-icon name="scan" size="1.5rem" /></van-col>
<van-col span="20"></van-col>
<van-col span="2"
><van-icon name="setting-o" size="1.5rem" @click="show = true"
/></van-col>
</van-row>
<van-row class="bodyRow">
<van-col span="6" class="leftCol">
<AppUserIcon width="4rem" height="4rem" :src="user.icon"></AppUserIcon>
</van-col>
<van-col span="12" class="title"><span>{{user.nick}}</span></van-col>
<van-col span="6" class="subtitle"
><span>个人主页<van-icon name="arrow" /></span
></van-col>
<van-col span="6" class="bodyCol"
><div><span>6</span><br />关注</div></van-col
>
<van-col span="6" class="bodyCol"
><div><span>3</span><br />粉丝</div></van-col
>
<van-col span="6" class="bodyCol"
><div><span>0</span><br />人气</div></van-col
>
<van-col span="6" class="bodyCol"
><div><span>3</span><br />钱钱</div></van-col
>
<van-col span="24">
<van-row class="btnRow">
<van-col span="12">
<van-button class="btn">
<van-icon name="bag" size="1.8rem" /> <span>我的购物</span><van-icon
name="arrow"
size="1.2rem" /></van-button
></van-col>
<van-col span="12">
<van-button class="btn"
><van-icon name="send-gift" size="1.8rem" /> <span>我的签到</span><van-icon
name="arrow"
size="1.2rem" /></van-button
></van-col>
</van-row>
</van-col>
<AppGrid class="grid" :data="data1"></AppGrid>
<AppGrid class="grid" :data="data2"></AppGrid>
<AppGrid class="grid" :data="data3"></AppGrid>
</van-row>
<van-popup
v-model:show="show"
position="right"
:style="{ height: '100%', width: '100%', backgroundColor: '#F8F8F8' }"
>
<van-nav-bar
title="设置"
left-text="返回"
left-arrow
@click-left="show = false"
/>
<van-cell-group>
<van-cell title="账户与安全" is-link />
<van-cell title="黑名单" is-link />
<van-cell title="推送设置" is-link />
<van-cell title="隐私管理" is-link />
<van-cell title="通用设置" is-link />
</van-cell-group>
<van-cell-group class="group">
<van-cell title="家庭入驻" is-link />
<van-cell title="社区入驻" is-link />
</van-cell-group>
<van-cell-group class="group">
<van-cell title="清理缓存" is-link />
<van-cell title="检测更新" is-link />
<van-cell title="关于我们" is-link />
<van-cell title="给个好评" is-link />
</van-cell-group>
<van-button type="danger" @click="outLog">退出登录</van-button>
</van-popup>
<!-- <van-popup v-model:show="show" position="right">
<div class="body-div"> 内容</div>
</van-popup> -->
</template>
<script setup lang="ts">
import AppGrid from "@/components/AppGrid.vue";
import { AppGridData } from "@/type/class/AppGridData";
import { ref } from "vue";
import { Dialog } from "vant";
import useUserStore from "@/store/modules/user.js";
import { storeToRefs } from 'pinia';
import AppUserIcon from "@/components/AppUserIcon.vue";
const show = ref<boolean>(false);
let data1: AppGridData = {
head: "个人中心",
body: [
{
title: "我的消息",
icon: "comment-o",
},
{
title: "我的聊天",
icon: "chat-o",
},
{
title: "我的喜欢",
icon: "like-o",
},
{
title: "我的关注",
icon: "user-o",
},
],
};
let data2: AppGridData = {
head: "功能",
body: [
{
title: "排行榜",
icon: "medal-o",
},
{
title: "活动报名",
icon: "balance-list-o",
},
{
title: "钱钱兑换",
icon: "gem-o",
},
{
title: "全网上新",
icon: "gift-card-o",
},
],
};
let data3: AppGridData = {
head: "服务",
body: [
{
title: "客服",
icon: "service-o",
},
{
title: "小黑屋",
icon: "wap-home-o",
},
{
title: "邀请好友",
icon: "friends-o",
},
],
};
const userStore=useUserStore();
const {user}=storeToRefs(useUserStore());
const outLog = () => {
Dialog.confirm({
title: "提示",
message: "确定退出当前用户吗?",
})
.then(() => {
userStore
.logOut()
.then((response: any) => {
location.href = "/";
});
})
.catch(() => {
// on cancel
});
};
</script>
<style scoped>
.bodyCol
{
color: #9B9B9B;
}
.bodyCol span{
color: black;
font-size:larger;
font-weight: 500;
}
.btn .van-icon{
color: #FF689B;
}
.btn span{
font-size:medium;
font-weight:600;
}
.grid {
width: 100%;
margin-top: 1rem;
}
.headRow {
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
}
.bodyRow {
text-align: left;
margin-top: 1.5rem;
padding-left: 1.5rem;
padding-right: 1.5rem;
padding-bottom: 4rem;
}
.title {
font-size: 1.5rem;
line-height: 4rem;
}
.subtitle {
line-height: 4rem;
color: #9B9B9B;
}
.bodyCol {
text-align: center;
font-size: 1.2rem;
margin-top: 1rem;
}
.btn {
width: 100%;
margin: 0;
padding: 0;
background-color: #ffffff;
border: none;
color: black;
}
.btnRow {
margin-top: 1.5rem;
box-shadow: 0rem 0rem 0.2rem 0.2rem #f3f3f3;
}
.btnRow .van-button {
font-size: 1.2rem;
}
.van-icon-send-gift {
margin-right: 0.5rem;
}
.btnRow .van-icon-arrow {
margin-left: 0.45rem;
}
.van-cell {
text-align: left;
}
.group {
margin-top: 1rem;
}
.van-popup .van-button {
width: 90%;
margin-top: 2rem;
}
</style>

View File

@@ -0,0 +1,185 @@
<template>
<transition name="van-slide-right">
<div v-show="visible">
<van-sticky>
<van-row class="head-row">
<van-col span="3">
<router-link to="/recommend">
<van-icon name="arrow-left" size="1.5rem" />
</router-link>
</van-col>
<van-col span="18"><span>发图文</span></van-col>
<van-col
span="3"
@click="send"
:style="{ color: isSend ? '#FE70A0' : '#979797' }"
>发布</van-col
>
</van-row>
</van-sticky>
<van-cell-group>
<van-field
rows="5"
autosize
type="textarea"
v-model="content"
label-width="0"
:show-word-limit="true"
maxlength="500"
placeholder="大于5字每一天都是为了下一天"
/>
</van-cell-group>
<van-row class="body-row">
<van-col span="10">
<van-icon name="share-o" size="1.5rem" /><span>发布到去其他</span>
</van-col>
<van-col span="4"></van-col>
<van-col span="10"
><span class="right-span">选择更多人看到</span>
<van-icon name="arrow" size="1.2rem" />
</van-col>
</van-row>
<van-divider />
<van-row>
<van-col class="img-col" span="24">
<van-uploader
accept="image/*"
:after-read="afterRead"
v-model="fileList"
multiple
/>
</van-col>
</van-row>
</div>
</transition>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive, toRefs, watch } from "vue";
import { ArticleEntity } from "@/type/interface/ArticleEntity";
import fileApi from "@/api/fileApi";
import articleApi from "@/api/articleApi";
import { Toast } from "vant";
import { useRouter } from "vue-router";
const router = useRouter();
const form = reactive<any>({
title: "",
content: "",
images: [],
isDeleted: false,
});
const isSend = ref(false);
const { images, content } = toRefs(form);
const fileList = ref([]);
const visible = ref<boolean>(false);
onMounted(() => {
visible.value = true;
});
const afterRead = (file: any) => {
file.status = "uploading";
file.message = "上传中...";
var formData = new FormData();
//一个文件
if (file.length == undefined) {
formData.append("file", file.file);
} else {
//多个文件
file.forEach((f: any) => {
formData.append("file", f.file);
f.status = "uploading";
f.message = "上传中...";
});
Toast({
message: "全部文件正在上传",
position: "bottom",
});
}
fileApi.upload(formData).then((response: any) => {
images.value.push(...response.data.map((x:any)=>x.id));
if (file.length == undefined) {
file.status = "done";
file.message = "成功";
} else {
//多个文件
file.forEach((f: any) => {
f.status = "done";
f.message = "成功";
});
Toast({
message: "全部文件上传成功",
position: "bottom",
});
}
});
};
const send = () => {
if (form.content.length < 5) {
Toast({
message: "请输入至少5个字符",
position: "bottom",
});
} else {
articleApi.add(form).then((response: any) => {
router.push({ path: "/recommend" });
});
}
};
watch(
() => form.content,
(newValue, oldValue) => {
if (newValue.length < 5) {
isSend.value = false;
} else {
isSend.value = true;
}
}
);
</script>
<style scoped>
.head-row {
background-color: #f8f8f8;
padding: 1.2rem 1rem 0.8rem 1rem;
}
.head-row span {
font-size: large;
}
.van-field-5-label {
display: none;
}
.body-row {
margin-top: 1rem;
}
.preview-cover {
position: absolute;
bottom: 0;
box-sizing: border-box;
width: 100%;
padding: 4px;
color: #fff;
font-size: 12px;
text-align: center;
background: rgba(0, 0, 0, 0.3);
}
.van-uploader {
margin: 0 1.2rem 0 1.2rem;
}
.img-col {
text-align: left;
}
.right-span {
color: #979797;
}
</style>

View File

@@ -0,0 +1,44 @@
<template>
这里是商品详情页当所有规格组全部选择完后就会匹配sku列表匹配成功才显示价格即绑定好的sku
<div >商品名称{{spuItem.spuName}}</div>
<div v-for="spec in spuItem.specsSpuAllInfo" :key="spec">规格组 {{spec.specsGroupName}}
<div v-for="name in spec.specsNames" :key="name">规格值 {{name}}</div>
</div>
<hr>
<div v-for="sku in spuItem.skus" :key="sku"> 价格{{sku.price}}<br>Sku{{sku}}
<hr>
</div>
<br>
<router-link to="/shopIndex">返回商品首页</router-link>
<van-action-bar>
<van-action-bar-icon icon="chat-o" text="客服" dot />
<van-action-bar-icon icon="cart-o" text="购物车" badge="5" />
<van-action-bar-icon icon="shop-o" text="店铺" badge="12" />
<van-action-bar-button type="warning" text="加入购物车" />
<van-action-bar-button type="danger" text="立即购买" />
</van-action-bar>
</template>
<script lang="ts" setup>
import {ref,onMounted} from 'vue'
import { useRouter } from 'vue-router'
import spuApi from "@/api/spuApi";
const router = useRouter();
const spuItem=ref<any>({});
onMounted(() => {
const spuId=router.currentRoute.value.query.spuId;
// 打印
spuApi.getById(spuId).then((response:any)=>{
spuItem.value=response.data
})
})
</script>>

View File

@@ -0,0 +1,79 @@
<template >
<div class="back">
<van-row class="top-div"> <van-col span="3"><van-icon name="circle" size="2rem" /></van-col>
<van-col span="18"> <router-link to="/shopSearch"><van-cell-group inset>
<van-field label="搜索" placeholder="搜索" />
</van-cell-group> </router-link></van-col>
<van-col span="3"><van-icon name="circle" size="2rem" /></van-col></van-row>
<div class="head-div">
<van-swipe
height="100"
class="my-swipe"
:autoplay="3000"
indicator-color="white"
>
<van-swipe-item>1</van-swipe-item>
<van-swipe-item>2</van-swipe-item>
<van-swipe-item>3</van-swipe-item>
<van-swipe-item>4</van-swipe-item>
</van-swipe>
</div>
<van-row class="body-row">
<van-col span="24">
<van-grid :column-num="4">
<van-grid-item
v-for="value in 8"
:key="value"
icon="photo-o"
text="文字"
/>
</van-grid>
</van-col>
<van-col span="24"> <AppCard /></van-col>
<van-col span="24"> <AppCard /></van-col>
<van-col span="24"> <AppCard /></van-col>
</van-row>
</div>
</template>
<script setup lang="ts">
import AppCard from "@/components/AppCard.vue";
</script>
<style>
.my-swipe .van-swipe-item {
color: #fff;
font-size: 20px;
line-height: 150px;
text-align: center;
background-color: #39a9ed;
}
.body-row {
padding: 1rem;
padding-top: 0.2rem;
margin-top: 1rem;
}
.van-swipe {
/* margin-top: 10rem;
margin-left: 1rem;
margin-right: 1rem; */
}
.head-div {
padding: 1rem;
padding-bottom: 0;
}
.body-row .van-col {
margin-bottom: 2rem;
}
.top-div
{
padding: 1rem;
padding-bottom: 0;
}
.back{
background-color: #f4f4f4;
}
</style>

View File

@@ -0,0 +1,39 @@
<template>
这里是商品搜索页
<br>
<br>
<router-link to="/shopIndex">返回商品首页</router-link>
这个是spu:
<div v-for="item in spuList" :key="item.id">商品名称{{item.spuName}}
<router-link :to="`/shopDetails?spuId=${item.id}`">点击进入该商品详情</router-link>
<div v-for="spec in item.specsSpuAllInfo" :key="spec">规格组 {{spec.specsGroupName}}
<div v-for="name in spec.specsNames" :key="name">规格值 {{name}}
</div>
</div>
<hr>
</div>
</template>
<script setup lang="ts">
import {ref,reactive,toRefs} from 'vue'
import spuApi from "@/api/spuApi";
const data = reactive({
queryParams: {
pageNum: 1,
pageSize: 10,
// dictName: undefined,
// dictType: undefined,
isDeleted: false,
},
});
const spuList = ref<any[]>([]);
const { queryParams } = toRefs(data);
spuApi.pageList(queryParams.value).then((response:any)=>{
spuList.value=response.data.data;
})
</script>

7
Yi.App.Vue3/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1,7 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

24
Yi.App.Vue3/tsconfig.json Normal file
View File

@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
// "strictPropertyInitialization": false
"paths": {
"@": ["./src"],
// "@/*": ["./src/*"] // 多加个这个,
"@/*": ["./src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/store/modules/user.ts", "src/utils/myaxios.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View File

@@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -0,0 +1,53 @@
import { defineConfig, loadEnv } from 'vite'
import path from 'path'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {
const env = loadEnv(mode, process.cwd())
const { VITE_APP_ENV, VITE_APP_BASE_URL} = env
return {
plugins: [vue(), Components({
resolvers: [VantResolver()],
}),],
resolve: {
// https://cn.vitejs.dev/config/#resolve-alias
alias: {
// 设置路径
'~': path.resolve(__dirname, './'),
// 设置别名
// '@': path.resolve(__dirname, './src'),
"@": path.join(__dirname, "./src"),
}
},
server: {
port: 17000,
host: true,
open: true,
proxy: {
// https://cn.vitejs.dev/config/#server-proxy
'/dev-api': {
target: VITE_APP_BASE_URL,
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, ''),
},
'/dev-ws': {
target: VITE_APP_BASE_URL,
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-ws/, ''),
ws: true
}
}
},
}
}
)

View File

@@ -13,6 +13,7 @@
"echarts": "^5.4.2",
"element-plus": "^2.2.32",
"highlight": "^0.2.4",
"i": "^0.3.7",
"marked": "^4.2.12",
"mavon-editor": "^3.0.0",
"nprogress": "^0.2.0",
@@ -2345,6 +2346,14 @@
"node": ">= 6"
}
},
"node_modules/i": {
"version": "0.3.7",
"resolved": "https://registry.npmmirror.com/i/-/i-0.3.7.tgz",
"integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==",
"engines": {
"node": ">=0.4"
}
},
"node_modules/ignore": {
"version": "5.2.4",
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.2.4.tgz",
@@ -5641,6 +5650,11 @@
"debug": "4"
}
},
"i": {
"version": "0.3.7",
"resolved": "https://registry.npmmirror.com/i/-/i-0.3.7.tgz",
"integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q=="
},
"ignore": {
"version": "5.2.4",
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.2.4.tgz",

View File

@@ -13,6 +13,7 @@
"echarts": "^5.4.2",
"element-plus": "^2.2.32",
"highlight": "^0.2.4",
"i": "^0.3.7",
"marked": "^4.2.12",
"mavon-editor": "^3.0.0",
"nprogress": "^0.2.0",

View File

@@ -0,0 +1,17 @@
import request from '@/utils/request'
// 触发访问
export function access() {
return request({
url: '/access-log',
method: 'post'
})
}
// 获取本周数据
export function getWeek() {
return request({
url: '/access-log/week',
method: 'get'
})
}

View File

@@ -124,7 +124,7 @@ fileDialogVisible.value=false;
}
//文件上传成功后
const onSuccess=(response)=>{
fileUrlList.value.push(response[0].id)
fileUrlList.value.push(response.data[0].id)
}
//图片上传

View File

@@ -8,30 +8,34 @@ import { LineChart } from 'echarts/charts';
import { UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
import { ref ,onMounted} from 'vue';
import { getWeek } from '@/apis/accessApi.js'
echarts.use([GridComponent, LineChart, CanvasRenderer, UniversalTransition]);
const VisitsLineChart=ref(null);
onMounted(()=>{
onMounted(async()=>{
var myChart = echarts.init(VisitsLineChart.value, null, {
width: 320,
height: 230
});
var option;
const response=await getWeek();
var numberData=response.data.map(x=>x.number);
option = {
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
},
yAxis: {
type: 'value'
},
series: [
{
data: [82, 93, 90, 93, 129, 133, 132],
data: numberData,
type: 'line',
areaStyle: {}
}

View File

@@ -36,21 +36,26 @@ myaxios.interceptors.request.use(function (config) {
// 响应拦截器
myaxios.interceptors.response.use(function (response) {
return response;
//业务错误
if(response.data.statusCode==403)
{
ElMessage.error(response.data.errors)
}
return response.data;
}, function (error) {
const response=error.response.data;
const code = error.response.status;
const msg = error.message;
//业务异常+应用异常,统一处理
switch(response.code)
switch(code)
{
case 401:
ElMessage.error('登录已过期')
break;
case 403:
ElMessage.error(response.message)
ElMessage.error(msg)
break;
case 500:
ElMessage.error(response.message)
ElMessage.error(msg)
break;
}

View File

@@ -93,7 +93,7 @@ const dialogImageUrl = ref('')
//文件上传成功后
const onSuccess=(response)=>{
dialogImageUrl.value=response[0].id
dialogImageUrl.value=response.data[0].id
}
//封面url
const getUrl= (str)=>{

View File

@@ -67,7 +67,7 @@
<template #item="temp">
<AvatarInfo>
<template #bottom>
本月积分680
本月积分290
</template>
</AvatarInfo>
@@ -103,6 +103,7 @@ import AvatarInfo from '@/components/AvatarInfo.vue'
import BottomInfo from '@/components/BottomInfo.vue'
import VisitsLineChart from '@/components/echars/VisitsLineChart.vue'
import { access } from '@/apis/accessApi.js'
import { getList } from '@/apis/plateApi.js'
import { getList as bannerGetList } from '@/apis/bannerApi.js'
import { getList as discussGetList } from '@/apis/discussApi.js'
@@ -121,6 +122,7 @@ const query = reactive({
//初始化
onMounted(async () => {
await access();
plateList.value = (await getList()).data.items;
discussList.value = (await discussGetList(query)).data.items;
bannerList.value = (await bannerGetList()).data.items

View File

@@ -69,8 +69,8 @@ password:[
]})
const loginForm = reactive({
userName: "",
password: "",
userName: "cc",
password: "123456",
uuid: "",
code: ""
})

0
Yi.Bbs.Vue3/.env Normal file
View File

View File

@@ -0,0 +1,2 @@
VITE_APP_BASEAPI="/api-dev"
VITE_APP_URL="http://localhost:19001/api"

View File

@@ -0,0 +1 @@
VITE_APP_BASEAPI="/prod-api"

28
Yi.Bbs.Vue3/.gitignore vendored Normal file
View File

@@ -0,0 +1,28 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

3
Yi.Bbs.Vue3/.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

29
Yi.Bbs.Vue3/README.md Normal file
View File

@@ -0,0 +1,29 @@
# yi-bbs
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Compile and Minify for Production
```sh
npm run build
```

14
Yi.Bbs.Vue3/index.html Normal file
View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>意社区</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

6840
Yi.Bbs.Vue3/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

34
Yi.Bbs.Vue3/package.json Normal file
View File

@@ -0,0 +1,34 @@
{
"name": "yi-bbs",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"axios": "^1.3.4",
"echarts": "^5.4.2",
"element-plus": "^2.2.32",
"highlight": "^0.2.4",
"i": "^0.3.7",
"marked": "^4.2.12",
"mavon-editor": "^3.0.0",
"nprogress": "^0.2.0",
"pinia": "^2.0.32",
"vue": "^3.2.47",
"vue-cropper": "1.0.3",
"vue-router": "^4.1.6",
"yarm": "^0.4.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.0.0",
"copy-webpack-plugin": "^11.0.0",
"sass": "1.52.1",
"unplugin-auto-import": "^0.15.0",
"unplugin-vue-components": "^0.24.0",
"vite": "^4.1.3"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

28
Yi.Bbs.Vue3/src/App.vue Normal file
View File

@@ -0,0 +1,28 @@
<script setup>
</script>
<template>
<el-config-provider :locale="locale">
<RouterView />
</el-config-provider>
</template>
<script setup>
import useConfigStore from "@/stores/config";
import { ElConfigProvider } from 'element-plus'
import {onMounted } from "vue";
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
const locale= zhCn;
const configStore = useConfigStore();
//加载全局信息
onMounted(async()=>{
await configStore.getConfig();
})
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,17 @@
import request from '@/utils/request'
// 触发访问
export function access() {
return request({
url: '/access-log',
method: 'post'
})
}
// 获取本周数据
export function getWeek() {
return request({
url: '/access-log/week',
method: 'get'
})
}

View File

@@ -0,0 +1,79 @@
import request from '@/utils/request'
// 登录方法
export function login(username, password, code, uuid) {
const data = {
username,
password,
code,
uuid
}
return request({
url: '/account/login',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 注册方法
export function register(userName,password,phone,code,uuid) {
const data = {
userName,
password,
phone,
code,
uuid
}
return request({
url: '/account/register',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 获取用户详细信息
export function getInfo() {
return request({
url: '/account',
method: 'get'
})
}
// 退出方法
export function logout() {
return request({
url: '/account/logout',
method: 'post'
})
}
// 获取验证码
export function getCodeImg() {
return request({
url: '/account/captcha-image',
headers: {
isToken: false
},
method: 'get',
timeout: 20000
})
}
// 获取短信验证码
export function getCodePhone(phone) {
return request({
url: '/account/captcha-phone',
headers: {
isToken: false
},
method: 'post',
timeout: 20000,
data:{phone}
})
}

View File

@@ -0,0 +1,11 @@
import myaxios from '@/utils/request'
export function operate(discussId){
if(discussId==undefined)
{
return;
}
return myaxios({
url: `/agree/operate/${discussId}`,
method: 'post'
})
};

View File

@@ -0,0 +1,41 @@
import myaxios from '@/utils/request'
export function getList(data){
return myaxios({
url: '/article',
method: 'get',
params:data
})
};
export function get(id){
return myaxios({
url: `/article/${id}`,
method: 'get'
})
};
export function add(data){
return myaxios({
url: `/article`,
method: 'post',
data:data
})
};
export function update(id,data){
return myaxios({
url: `/article/${id}`,
method: 'put',
data:data
})
};
export function del(ids){
return myaxios({
url: `/article/${ids}`,
method: 'delete'
})
};
export function all(discussId)
{
return myaxios({
url: `/article/all/discuss-id/${discussId}`,
method: 'get'
})
}

View File

@@ -0,0 +1,8 @@
import myaxios from '@/utils/request'
export function getList(data){
return myaxios({
url: '/banner',
method: 'get',
params:data
})
};

View File

@@ -0,0 +1,22 @@
import myaxios from '@/utils/request'
export function getListByDiscussId(discussId,data){
return myaxios({
url: `/comment/discuss-id/${discussId}`,
method: 'get',
params:data
})
};
export function add(data){
return myaxios({
url: `/comment`,
method: 'post',
data:data
})
};
export function del(ids){
return myaxios({
url: `/comment/${ids}`,
method: 'delete'
})
};

View File

@@ -0,0 +1,9 @@
import myaxios from '@/utils/request'
//获取配置
export function getAll(){
return myaxios({
url: '/config',
method: 'get'
})
};

View File

@@ -0,0 +1,51 @@
import myaxios from '@/utils/request'
export function getList(data){
return myaxios({
url: '/discuss',
method: 'get',
params:data
})
};
export function getTopList(data){
if(data==undefined)
{
data={isTop:true}
}
else
{
data["isTop"]=true;
}
return myaxios({
url: '/discuss',
method: 'get',
params:data
})
};
export function get(id){
return myaxios({
url: `/discuss/${id}`,
method: 'get'
})
};
export function add(data){
return myaxios({
url: `/discuss`,
method: 'post',
data:data
})
};
export function update(id,data){
return myaxios({
url: `/discuss/${id}`,
method: 'put',
data:data
})
};
export function del(ids){
return myaxios({
url: `/discuss/${ids}`,
method: 'delete'
})
};

View File

@@ -0,0 +1,9 @@
import myaxios from '@/utils/request'
export function upload(data){
return myaxios({
url: '/file',
method: 'post',
data:data,
headers: { 'Content-Type': 'multipart/form-data' }
})
};

View File

@@ -0,0 +1,8 @@
import myaxios from '@/utils/request'
export function getList(data){
return myaxios({
url: '/plate',
method: 'get',
params:data
})
};

View File

@@ -0,0 +1,139 @@
import myaxios from '@/utils/request'
// 查询用户列表
export function listUser(query) {
return myaxios({
url: '/user',
method: 'get',
params: query
})
}
// 查询用户详细
export function getUser(userId) {
return myaxios({
url: '/user/' + parseStrEmpty(userId),
method: 'get'
})
}
// 新增用户
export function addUser(data) {
return myaxios({
url: '/user',
method: 'post',
data: data
})
}
// 修改用户
export function updateUser(id, data) {
return myaxios({
url: `/user/${id}`,
method: 'put',
data: data
})
}
// 删除用户
export function delUser(userId) {
return myaxios({
url: `/user/${userId}`,
method: 'delete',
})
}
// 用户密码重置
export function resetUserPwd(id, password) {
const data = {
password
}
return myaxios({
url: `/account/rest-password/${id}`,
method: 'put',
data: data
})
}
// 用户状态修改
export function changeUserStatus(userId, isDel) {
return myaxios({
url: `/user/${userId}/${isDel}`,
method: 'put'
})
}
// 查询用户个人信息
export function getUserProfile() {
return myaxios({
url: '/account',
method: 'get'
})
}
// 修改用户个人信息
export function updateUserProfile(data) {
return myaxios({
url: `/user/profile`,
method: 'put',
data: data
})
}
// 只修改用户头像
export function updateUserIcon(data) {
return myaxios({
url: `/account/icon`,
method: 'put',
data:{icon:data}
})
}
// 用户密码重置
export function updateUserPwd(oldPassword, newPassword) {
const data = {
oldPassword,
newPassword
}
return myaxios({
url: '/account/password',
method: 'put',
data: data
})
}
// 用户头像上传
export function uploadAvatar(data) {
return request({
url: '/system/user/profile/avatar',
method: 'post',
data: data
})
}
// 查询授权角色
export function getAuthRole(userId) {
return request({
url: '/system/user/authRole/' + userId,
method: 'get'
})
}
// 保存授权角色
export function updateAuthRole(data) {
return request({
url: '/system/user/authRole',
method: 'put',
params: data
})
}
// // 查询部门下拉树结构
// export function deptTreeSelect() {
// return request({
// url: '/system/user/deptTree',
// method: 'get'
// })
// }

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

View File

@@ -0,0 +1,710 @@
@font-face {
font-family: octicons-link;
src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format('woff');
}
.markdown-body {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
line-height: 1.5;
color: #24292e;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 16px;
line-height: 1.5;
word-wrap: break-word;
}
.markdown-body .pl-c {
color: #6a737d;
}
.markdown-body .pl-c1,
.markdown-body .pl-s .pl-v {
color: #005cc5;
}
.markdown-body .pl-e,
.markdown-body .pl-en {
color: #6f42c1;
}
.markdown-body .pl-smi,
.markdown-body .pl-s .pl-s1 {
color: #24292e;
}
.markdown-body .pl-ent {
color: #22863a;
}
.markdown-body .pl-k {
color: #d73a49;
}
.markdown-body .pl-s,
.markdown-body .pl-pds,
.markdown-body .pl-s .pl-pse .pl-s1,
.markdown-body .pl-sr,
.markdown-body .pl-sr .pl-cce,
.markdown-body .pl-sr .pl-sre,
.markdown-body .pl-sr .pl-sra {
color: #032f62;
}
.markdown-body .pl-v,
.markdown-body .pl-smw {
color: #e36209;
}
.markdown-body .pl-bu {
color: #b31d28;
}
.markdown-body .pl-ii {
color: #fafbfc;
background-color: #b31d28;
}
.markdown-body .pl-c2 {
color: #fafbfc;
background-color: #d73a49;
}
.markdown-body .pl-c2::before {
content: "^M";
}
.markdown-body .pl-sr .pl-cce {
font-weight: bold;
color: #22863a;
}
.markdown-body .pl-ml {
color: #735c0f;
}
.markdown-body .pl-mh,
.markdown-body .pl-mh .pl-en,
.markdown-body .pl-ms {
font-weight: bold;
color: #005cc5;
}
.markdown-body .pl-mi {
font-style: italic;
color: #24292e;
}
.markdown-body .pl-mb {
font-weight: bold;
color: #24292e;
}
.markdown-body .pl-md {
color: #b31d28;
background-color: #ffeef0;
}
.markdown-body .pl-mi1 {
color: #22863a;
background-color: #f0fff4;
}
.markdown-body .pl-mc {
color: #e36209;
background-color: #ffebda;
}
.markdown-body .pl-mi2 {
color: #f6f8fa;
background-color: #005cc5;
}
.markdown-body .pl-mdr {
font-weight: bold;
color: #6f42c1;
}
.markdown-body .pl-ba {
color: #586069;
}
.markdown-body .pl-sg {
color: #959da5;
}
.markdown-body .pl-corl {
text-decoration: underline;
color: #032f62;
}
.markdown-body .octicon {
display: inline-block;
vertical-align: text-top;
fill: currentColor;
}
.markdown-body a {
background-color: transparent;
-webkit-text-decoration-skip: objects;
}
.markdown-body a:active,
.markdown-body a:hover {
outline-width: 0;
}
.markdown-body strong {
font-weight: inherit;
}
.markdown-body strong {
font-weight: bolder;
}
.markdown-body h1 {
font-size: 2em;
margin: 0.67em 0;
}
.markdown-body img {
border-style: none;
}
.markdown-body svg:not(:root) {
overflow: hidden;
}
.markdown-body code,
.markdown-body kbd,
.markdown-body pre {
font-family: monospace, monospace;
font-size: 1em;
}
.markdown-body hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
.markdown-body input {
font: inherit;
margin: 0;
}
.markdown-body input {
overflow: visible;
}
.markdown-body [type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
.markdown-body * {
box-sizing: border-box;
}
.markdown-body input {
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
.markdown-body a {
color: #0366d6;
text-decoration: none;
}
.markdown-body a:hover {
text-decoration: underline;
}
.markdown-body strong {
font-weight: 600;
}
.markdown-body hr {
height: 0;
margin: 15px 0;
overflow: hidden;
background: transparent;
border: 0;
border-bottom: 1px solid #dfe2e5;
}
.markdown-body hr::before {
display: table;
content: "";
}
.markdown-body hr::after {
display: table;
clear: both;
content: "";
}
.markdown-body table {
border-spacing: 0;
border-collapse: collapse;
}
.markdown-body td,
.markdown-body th {
padding: 0;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
margin-top: 0;
margin-bottom: 0;
}
.markdown-body h1 {
font-size: 32px;
font-weight: 600;
}
.markdown-body h2 {
font-size: 24px;
font-weight: 600;
}
.markdown-body h3 {
font-size: 20px;
font-weight: 600;
}
.markdown-body h4 {
font-size: 16px;
font-weight: 600;
}
.markdown-body h5 {
font-size: 14px;
font-weight: 600;
}
.markdown-body h6 {
font-size: 12px;
font-weight: 600;
}
.markdown-body p {
margin-top: 0;
margin-bottom: 10px;
}
.markdown-body blockquote {
margin: 0;
}
.markdown-body ul,
.markdown-body ol {
padding-left: 0;
margin-top: 0;
margin-bottom: 0;
}
.markdown-body ol ol,
.markdown-body ul ol {
list-style-type: lower-roman;
}
.markdown-body ul ul ol,
.markdown-body ul ol ol,
.markdown-body ol ul ol,
.markdown-body ol ol ol {
list-style-type: lower-alpha;
}
.markdown-body dd {
margin-left: 0;
}
.markdown-body code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 12px;
}
.markdown-body pre {
margin-top: 0;
margin-bottom: 0;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 12px;
}
.markdown-body .octicon {
vertical-align: text-bottom;
}
.markdown-body .pl-0 {
padding-left: 0 !important;
}
.markdown-body .pl-1 {
padding-left: 4px !important;
}
.markdown-body .pl-2 {
padding-left: 8px !important;
}
.markdown-body .pl-3 {
padding-left: 16px !important;
}
.markdown-body .pl-4 {
padding-left: 24px !important;
}
.markdown-body .pl-5 {
padding-left: 32px !important;
}
.markdown-body .pl-6 {
padding-left: 40px !important;
}
.markdown-body::before {
display: table;
content: "";
}
.markdown-body::after {
display: table;
clear: both;
content: "";
}
.markdown-body>*:first-child {
margin-top: 0 !important;
}
.markdown-body>*:last-child {
margin-bottom: 0 !important;
}
.markdown-body a:not([href]) {
color: inherit;
text-decoration: none;
}
.markdown-body .anchor {
float: left;
padding-right: 4px;
margin-left: -20px;
line-height: 1;
}
.markdown-body .anchor:focus {
outline: none;
}
.markdown-body p,
.markdown-body blockquote,
.markdown-body ul,
.markdown-body ol,
.markdown-body dl,
.markdown-body table,
.markdown-body pre {
margin-top: 0;
margin-bottom: 16px;
}
.markdown-body hr {
height: 0.25em;
padding: 0;
margin: 24px 0;
background-color: #e1e4e8;
border: 0;
}
.markdown-body blockquote {
padding: 0 1em;
color: #6a737d;
border-left: 0.25em solid #dfe2e5;
}
.markdown-body blockquote>:first-child {
margin-top: 0;
}
.markdown-body blockquote>:last-child {
margin-bottom: 0;
}
.markdown-body kbd {
display: inline-block;
padding: 3px 5px;
font-size: 11px;
line-height: 10px;
color: #444d56;
vertical-align: middle;
background-color: #fafbfc;
border: solid 1px #c6cbd1;
border-bottom-color: #959da5;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #959da5;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
margin-top: 24px;
margin-bottom: 16px;
font-weight: 600;
line-height: 1.25;
}
.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
color: #1b1f23;
vertical-align: middle;
visibility: hidden;
}
.markdown-body h1:hover .anchor,
.markdown-body h2:hover .anchor,
.markdown-body h3:hover .anchor,
.markdown-body h4:hover .anchor,
.markdown-body h5:hover .anchor,
.markdown-body h6:hover .anchor {
text-decoration: none;
}
.markdown-body h1:hover .anchor .octicon-link,
.markdown-body h2:hover .anchor .octicon-link,
.markdown-body h3:hover .anchor .octicon-link,
.markdown-body h4:hover .anchor .octicon-link,
.markdown-body h5:hover .anchor .octicon-link,
.markdown-body h6:hover .anchor .octicon-link {
visibility: visible;
}
.markdown-body h1 {
padding-bottom: 0.3em;
font-size: 2em;
border-bottom: 1px solid #eaecef;
}
.markdown-body h2 {
padding-bottom: 0.3em;
font-size: 1.5em;
border-bottom: 1px solid #eaecef;
}
.markdown-body h3 {
font-size: 1.25em;
}
.markdown-body h4 {
font-size: 1em;
}
.markdown-body h5 {
font-size: 0.875em;
}
.markdown-body h6 {
font-size: 0.85em;
color: #6a737d;
}
.markdown-body ul,
.markdown-body ol {
padding-left: 2em;
}
.markdown-body ul ul,
.markdown-body ul ol,
.markdown-body ol ol,
.markdown-body ol ul {
margin-top: 0;
margin-bottom: 0;
}
.markdown-body li>p {
margin-top: 16px;
}
.markdown-body li+li {
margin-top: 0.25em;
}
.markdown-body dl {
padding: 0;
}
.markdown-body dl dt {
padding: 0;
margin-top: 16px;
font-size: 1em;
font-style: italic;
font-weight: 600;
}
.markdown-body dl dd {
padding: 0 16px;
margin-bottom: 16px;
}
.markdown-body table {
display: block;
width: 100%;
overflow: auto;
}
.markdown-body table th {
font-weight: 600;
}
.markdown-body table th,
.markdown-body table td {
padding: 6px 13px;
border: 1px solid #dfe2e5;
}
.markdown-body table tr {
background-color: #fff;
border-top: 1px solid #c6cbd1;
}
.markdown-body table tr:nth-child(2n) {
background-color: #f6f8fa;
}
.markdown-body img {
max-width: 100%;
box-sizing: content-box;
background-color: #fff;
}
.markdown-body img[align=right] {
padding-left: 20px;
}
.markdown-body img[align=left] {
padding-right: 20px;
}
.markdown-body code {
padding: 0;
padding-top: 0.2em;
padding-bottom: 0.2em;
margin: 0;
font-size: 85%;
background-color: rgba(27,31,35,0.05);
border-radius: 3px;
}
.markdown-body code::before,
.markdown-body code::after {
letter-spacing: -0.2em;
content: "\00a0";
}
.markdown-body pre {
word-wrap: normal;
}
.markdown-body pre>code {
padding: 0;
margin: 0;
font-size: 100%;
word-break: normal;
white-space: pre;
background: transparent;
border: 0;
}
.markdown-body .highlight {
margin-bottom: 16px;
}
.markdown-body .highlight pre {
margin-bottom: 0;
word-break: normal;
}
.markdown-body .highlight pre,
.markdown-body pre {
padding: 16px;
overflow: auto;
font-size: 85%;
line-height: 1.45;
/* background-color: #f6f8fa; */
border-radius: 3px;
}
.markdown-body pre code {
display: inline;
max-width: auto;
padding: 0;
margin: 0;
overflow: visible;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
.markdown-body pre code::before,
.markdown-body pre code::after {
content: normal;
}
.markdown-body .full-commit .btn-outline:not(:disabled):hover {
color: #005cc5;
border-color: #005cc5;
}
.markdown-body kbd {
display: inline-block;
padding: 3px 5px;
font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
line-height: 10px;
color: #444d56;
vertical-align: middle;
background-color: #fafbfc;
border: solid 1px #d1d5da;
border-bottom-color: #c6cbd1;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #c6cbd1;
}
.markdown-body :checked+.radio-label {
position: relative;
z-index: 1;
border-color: #0366d6;
}
.markdown-body .task-list-item {
list-style-type: none;
}
.markdown-body .task-list-item+.task-list-item {
margin-top: 3px;
}
.markdown-body .task-list-item input {
margin: 0 0.2em 0.25em -1.6em;
vertical-align: middle;
}
.markdown-body hr {
border-bottom-color: #eee;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,48 @@
/* @import './base.css'; */
/* #app {
margin: 0 auto;
font-weight: normal;
} */
body
{
margin: 0 auto;
font-weight: normal;
}
a{
text-decoration: none;
}
/*
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
} */

View File

@@ -0,0 +1,190 @@
// @import './variables.module.scss';
// @import './mixin.scss';
// @import './transition.scss';
// @import './element-ui.scss';
// @import './sidebar.scss';
// @import './btn.scss';
// @import './ruoyi.scss';
// body {
// height: 100%;
// margin: 0;
// -moz-osx-font-smoothing: grayscale;
// -webkit-font-smoothing: antialiased;
// text-rendering: optimizeLegibility;
// font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
// }
// label {
// font-weight: 700;
// }
// html {
// height: 100%;
// box-sizing: border-box;
// }
// #app {
// height: 100%;
// }
// *,
// *:before,
// *:after {
// box-sizing: inherit;
// }
// .no-padding {
// padding: 0px !important;
// }
// .padding-content {
// padding: 4px 0;
// }
// a:focus,
// a:active {
// outline: none;
// }
// a,
// a:focus,
// a:hover {
// cursor: pointer;
// color: inherit;
// text-decoration: none;
// }
// div:focus {
// outline: none;
// }
// .fr {
// float: right;
// }
// .fl {
// float: left;
// }
// .pr-5 {
// padding-right: 5px;
// }
// .pl-5 {
// padding-left: 5px;
// }
// .block {
// display: block;
// }
// .pointer {
// cursor: pointer;
// }
// .inlineBlock {
// display: block;
// }
// .clearfix {
// &:after {
// visibility: hidden;
// display: block;
// font-size: 0;
// content: " ";
// clear: both;
// height: 0;
// }
// }
// aside {
// background: #eef1f6;
// padding: 8px 24px;
// margin-bottom: 20px;
// border-radius: 2px;
// display: block;
// line-height: 32px;
// font-size: 16px;
// font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
// color: #2c3e50;
// -webkit-font-smoothing: antialiased;
// -moz-osx-font-smoothing: grayscale;
// a {
// color: #337ab7;
// cursor: pointer;
// &:hover {
// color: rgb(32, 160, 255);
// }
// }
// }
// .components-container {
// margin: 30px 50px;
// position: relative;
// }
// .pagination-container {
// margin-top: 30px;
// }
.text-center {
text-align: center
}
// .sub-navbar {
// height: 50px;
// line-height: 50px;
// position: relative;
// width: 100%;
// text-align: right;
// padding-right: 20px;
// transition: 600ms ease position;
// background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
// .subtitle {
// font-size: 20px;
// color: #fff;
// }
// &.draft {
// background: #d0d0d0;
// }
// &.deleted {
// background: #d0d0d0;
// }
// }
// .link-type,
// .link-type:focus {
// color: #337ab7;
// cursor: pointer;
// &:hover {
// color: rgb(32, 160, 255);
// }
// }
// .filter-container {
// padding-bottom: 10px;
// .filter-item {
// display: inline-block;
// vertical-align: middle;
// margin-bottom: 10px;
// }
// }
// //refine vue-multiselect plugin
// .multiselect {
// line-height: 16px;
// }
// .multiselect--active {
// z-index: 1000 !important;
// }

View File

@@ -0,0 +1,206 @@
* {
margin: 0;
padding: 0;
}
/*公共CSS*/
.box {
width: 100vw;
height: 100vh;
background-color: rgb(29, 67, 89);
.content {
box-shadow: 0px 1px 6px #3B4859;
.login-wrapper {
h1 {
text-align: center;
}
.login-form {
.form-item {
margin: 20px 0;
span {
display: block;
margin: 5px 20px;
font-weight: 100;
}
.input-item {
width: 100%;
border-radius: 40px;
padding: 20px;
box-sizing: border-box;
font-size: 20px;
font-weight: 200;
&:focus {
outline: none;
}
}
}
.login-btn {
width: 100%;
border-radius: 40px;
color: #fff;
border: 0;
font-weight: 100;
margin-top: 10px;
cursor: pointer;
}
}
.divider {
width: 100%;
margin: 20px 0;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
span:nth-child(1) {
flex: 1;
}
span:nth-child(3) {
flex: 1;
}
.line {
display: inline-block;
max-width: 30%;
width: 30%;
}
.divider-text {
vertical-align: middle;
margin: 0px 20px;
line-height: 0px;
display: inline-block;
width: 100px;
}
}
.other-login-wrapper {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.other-login-item {
border: 1px solid rgb(214, 222, 228);
padding: 10px;
margin: 10px;
cursor: pointer;
}
}
}
}
/*一般大于手机的尺寸CSS*/
@media (min-width: 767px) {
.box {
background-color: #F0F2F5;
.content {
width: 85vw;
height: 90vh;
background: url("@/assets/login_images/login_two.jpg") no-repeat;
background-size: 90% 100%;
position: absolute;
right: 15%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 20px;
background-color: #fff;
.login-wrapper {
width: 25vw;
position: absolute;
right: 15%;
top: 50%;
transform: translateY(-50%);
h1 {
text-align: center;
font-size: 45px;
color: rgb(81, 100, 115);
margin-bottom: 40px;
}
.login-form {
margin: 10px 0;
.form-item {
span {
color: rgb(81, 100, 115);
}
.input-item {
height: 60px;
border: 1px solid rgb(214, 222, 228);
}
}
.login-btn {
height: 50px;
background-color: rgb(59, 72, 89);
font-size: 20px;
}
}
.divider {
.line {
border-bottom: 1px solid rgb(214, 222, 228);
}
}
.other-login-item {
border-radius: 20px;
img {
width: 40px;
height: 40px;
}
}
}
}
}
}
/*手机端CSS*/
@media (max-width: 768px) {
.box {
.content {
width: 100vw;
height: 100vh;
background: url("@/assets/login_images/login_bg_phone.png") no-repeat;
background-size: 100% 100%;
display: flex;
align-items: flex-start;
justify-content: center;
.login-wrapper {
width: 70%;
height: 60%;
padding-top: 15%;
h1 {
font-size: 30px;
color: #fff;
}
.login-form {
.form-item {
margin: 10px 0;
span {
color: rgb(113, 129, 141);
}
.input-item {
height: 30px;
border: 1px solid rgb(113, 129, 141);
background-color: transparent;
color: #fff;
}
}
.login-btn {
height: 40px;
background-color: rgb(235, 95, 93);
font-size: 16px;
}
}
.divider {
.line {
border-bottom: 1px solid #fff;
}
.divider-text {
color: #fff;
}
}
.other-login-item {
border-radius: 15px;
img {
width: 35px;
height: 35px;
}
}
}
}
}
}

View File

@@ -0,0 +1,271 @@
/**
* 通用css样式布局处理
* Copyright (c) 2019 ruoyi
*/
/** 基础通用 **/
.pt5 {
padding-top: 5px;
}
.pr5 {
padding-right: 5px;
}
.pb5 {
padding-bottom: 5px;
}
.mt5 {
margin-top: 5px;
}
.mr5 {
margin-right: 5px;
}
.mb5 {
margin-bottom: 5px;
}
.mb8 {
margin-bottom: 8px;
}
.ml5 {
margin-left: 5px;
}
.mt10 {
margin-top: 10px;
}
.mr10 {
margin-right: 10px;
}
.mb10 {
margin-bottom: 10px;
}
.ml10 {
margin-left: 10px;
}
.mt20 {
margin-top: 20px;
}
.mr20 {
margin-right: 20px;
}
.mb20 {
margin-bottom: 20px;
}
.ml20 {
margin-left: 20px;
}
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
font-family: inherit;
font-weight: 500;
line-height: 1.1;
color: inherit;
}
.el-dialog:not(.is-fullscreen) {
margin-top: 6vh !important;
}
.el-dialog.scrollbar .el-dialog__body {
overflow: auto;
overflow-x: hidden;
max-height: 70vh;
padding: 10px 20px 0;
}
.el-table {
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
th {
word-break: break-word;
background-color: #f8f8f9 !important;
color: #515a6e;
height: 40px !important;
font-size: 13px;
}
}
.el-table__body-wrapper {
.el-button [class*="el-icon-"] + span {
margin-left: 1px;
}
}
}
/** 表单布局 **/
.form-header {
font-size:15px;
color:#6379bb;
border-bottom:1px solid #ddd;
margin:8px 10px 25px 10px;
padding-bottom:5px
}
/** 表格布局 **/
.pagination-container {
// position: relative;
height: 25px;
margin-bottom: 10px;
margin-top: 15px;
padding: 10px 20px !important;
}
/* tree border */
.tree-border {
margin-top: 5px;
border: 1px solid #e5e6e7;
background: #FFFFFF none;
border-radius:4px;
width: 100%;
}
.pagination-container .el-pagination {
right: 0;
position: absolute;
}
@media ( max-width : 768px) {
.pagination-container .el-pagination > .el-pagination__jump {
display: none !important;
}
.pagination-container .el-pagination > .el-pagination__sizes {
display: none !important;
}
}
.el-table .fixed-width .el-button--small {
padding-left: 0;
padding-right: 0;
width: inherit;
}
/** 表格更多操作下拉样式 */
.el-table .el-dropdown-link {
cursor: pointer;
color: #409EFF;
margin-left: 10px;
}
.el-table .el-dropdown, .el-icon-arrow-down {
font-size: 12px;
}
.el-tree-node__content > .el-checkbox {
margin-right: 8px;
}
.list-group-striped > .list-group-item {
border-left: 0;
border-right: 0;
border-radius: 0;
padding-left: 0;
padding-right: 0;
}
.list-group {
padding-left: 0px;
list-style: none;
}
.list-group-item {
border-bottom: 1px solid #e7eaec;
border-top: 1px solid #e7eaec;
margin-bottom: -1px;
padding: 11px 0px;
font-size: 13px;
}
// .el-card__header {
// padding: 14px 15px 7px !important;
// min-height: 40px;
// }
// .el-card__body {
// padding: 15px 20px 20px 20px !important;
// }
.card-box {
padding-right: 15px;
padding-left: 15px;
margin-bottom: 10px;
}
/* button color */
.el-button--cyan.is-active,
.el-button--cyan:active {
background: #20B2AA;
border-color: #20B2AA;
color: #FFFFFF;
}
.el-button--cyan:focus,
.el-button--cyan:hover {
background: #48D1CC;
border-color: #48D1CC;
color: #FFFFFF;
}
.el-button--cyan {
background-color: #20B2AA;
border-color: #20B2AA;
color: #FFFFFF;
}
/* text color */
.text-navy {
color: #1ab394;
}
.text-primary {
color: inherit;
}
.text-success {
color: #1c84c6;
}
.text-info {
color: #23c6c8;
}
.text-warning {
color: #f8ac59;
}
.text-danger {
color: #ed5565;
}
.text-muted {
color: #888888;
}
/* image */
.img-circle {
border-radius: 50%;
}
.img-lg {
width: 120px;
height: 120px;
}
.avatar-upload-preview {
position: absolute;
top: 50%;
transform: translate(50%, -50%);
width: 200px;
height: 200px;
border-radius: 50%;
box-shadow: 0 0 4px #ccc;
overflow: hidden;
}
/* 拖拽列样式 */
.sortable-ghost{
opacity: .8;
color: #fff!important;
background: #42b983!important;
}
/* 表格右侧工具栏样式 */
.top-right-btn {
margin-left: auto;
}

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