Compare commits

...

49 Commits

Author SHA1 Message Date
Anyon
f1c12215c2 Update index.html 2022-06-27 16:50:29 +08:00
Anyon
13c3176858 Update index.html 2022-06-27 16:46:54 +08:00
Anyon
7a9f6145ae Update SQL02-数据初始化.sql 2022-06-27 16:00:05 +08:00
Anyon
46644f6482 文件用户隔离 2022-06-27 15:45:59 +08:00
Anyon
b1054f4390 Update File.php 2022-06-27 15:42:03 +08:00
Anyon
84fcb3dc48 Update index.html 2022-06-27 15:35:34 +08:00
Anyon
5d959fb7d9 修改文件管理 2022-06-27 15:28:53 +08:00
Anyon
e304b326de Update index.html 2022-06-27 15:24:45 +08:00
Anyon
34a34fa504 Update index.html 2022-06-27 15:23:46 +08:00
Anyon
154d9ceb00 Update index.html 2022-06-27 15:23:01 +08:00
Anyon
11dbc3e226 Update index_search.html 2022-06-27 15:22:36 +08:00
Anyon
3cbbd7f23f Update File.php 2022-06-27 15:21:46 +08:00
Anyon
3bfa7eb0e4 Update index.html 2022-06-27 15:20:23 +08:00
Anyon
d3086e1dbc Update index.html 2022-06-27 15:15:49 +08:00
Anyon
5041472329 Update index.html 2022-06-27 15:07:22 +08:00
Anyon
8c3e787a28 修改文件管理 2022-06-27 15:06:03 +08:00
Anyon
9b31de5896 Update index.html 2022-06-27 15:00:06 +08:00
Anyon
a296015dac 修改样式 2022-06-27 14:58:41 +08:00
Anyon
ef56d5341e Update index.html 2022-06-27 14:48:38 +08:00
Anyon
c99b951e3b 升级Layui 2022-06-27 14:35:47 +08:00
Anyon
a34ac71264 Update index_search.html 2022-06-27 14:31:25 +08:00
Anyon
523d7d5946 Update File.php 2022-06-27 14:30:00 +08:00
Anyon
4b859eb0ed 修改文件管理 2022-06-27 14:28:34 +08:00
Anyon
2544a30fcb 修改文件管理 2022-06-27 14:25:39 +08:00
Anyon
4a1e2fddae 修改选择器模板 2022-06-27 11:34:35 +08:00
Anyon
7390dbb149 Update image.html 2022-06-27 11:33:21 +08:00
Anyon
87cc8d7117 修改文件上传 2022-06-27 11:27:45 +08:00
Anyon
ef8d151b77 Update admin.js 2022-06-27 11:07:10 +08:00
Anyon
59dba244d1 Update admin.js 2022-06-27 11:05:07 +08:00
Anyon
08c885a47d 修改模板 2022-06-27 11:00:54 +08:00
Anyon
28f838b1f7 Update SQL03-数据库升级.sql 2022-06-27 10:51:41 +08:00
Anyon
0cf3b66008 修改版本限制 2022-06-27 10:49:36 +08:00
Anyon
e1fd58f08b 增加图片选择器 2022-06-27 10:46:09 +08:00
Anyon
6efa05386a 修改模板 2022-06-27 10:24:34 +08:00
Anyon
c6a7926d31 优化服务,改为静态方法 2022-06-27 10:15:07 +08:00
Anyon
2fd2d3938e 修改静态调用 2022-06-27 09:59:58 +08:00
Anyon
4850c690e0 Update Queue.php 2022-06-27 09:53:14 +08:00
Anyon
4316de07a6 Update Queue.php 2022-06-27 09:51:49 +08:00
Anyon
ba5afc2fa3 Update image.html 2022-06-24 18:19:25 +08:00
Anyon
12b0bb2692 Update image.html 2022-06-24 18:12:28 +08:00
Anyon
fad1836dbd Update image.html 2022-06-24 18:11:04 +08:00
Anyon
3fcfb760fd Update image.html 2022-06-24 18:01:29 +08:00
Anyon
c1cfaa5ec0 Update image.html 2022-06-24 17:56:13 +08:00
Anyon
e6bf3a294d Update SQL01-数据表结构.sql 2022-06-24 17:25:30 +08:00
Anyon
95596bf3b7 修改代码 2022-06-24 17:24:05 +08:00
Anyon
12c50de24b 修改静态调用 2022-06-24 15:25:58 +08:00
Anyon
f9d48e1495 Update image.html 2022-06-24 15:05:16 +08:00
Anyon
b04ca63a87 修改图片选择器 2022-06-24 14:38:04 +08:00
Anyon
3da4409270 Update composer.json 2022-06-24 14:15:26 +08:00
67 changed files with 2007 additions and 1182 deletions

File diff suppressed because it is too large Load Diff

View File

@ -7613,98 +7613,54 @@ CREATE TABLE `system_menu`
-- ----------------------------
-- Records of system_menu
-- ----------------------------
INSERT INTO `system_menu`
VALUES (1, 0, '控制台', '', '', '#', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (2, 1, '数据管理', '', '', '#', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (3, 2, '数据统计报表', 'layui-icon layui-icon-theme', 'data/total.portal/index', 'data/total.portal/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (4, 2, '轮播图片管理', 'layui-icon layui-icon-carousel', 'data/base.slider/index', 'data/base.slider/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (5, 2, '页面内容管理', 'layui-icon layui-icon-read', 'data/base.pager/index', 'data/base.pager/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (6, 2, '文章内容管理', 'layui-icon layui-icon-template', 'data/news.item/index', 'data/news.item/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (7, 2, '支付参数管理', 'layui-icon layui-icon-rmb', 'data/base.payment/index', 'data/base.payment/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (8, 2, '系统通知管理', 'layui-icon layui-icon-notice', 'data/base.message/index', 'data/base.message/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (9, 2, '微信小程序配置', 'layui-icon layui-icon-set', 'data/base.config/wxapp', 'data/base.config/wxapp', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (10, 2, '邀请二维码设置', 'layui-icon layui-icon-cols', 'data/base.config/cropper', 'data/base.config/cropper', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (11, 1, '用户管理', '', '', '#', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (12, 11, '会员用户管理', 'layui-icon layui-icon-user', 'data/user.admin/index', 'data/user.admin/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (13, 11, '余额充值管理', 'layui-icon layui-icon-rmb', 'data/user.balance/index', 'data/user.balance/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (14, 11, '用户返利管理', 'layui-icon layui-icon-transfer', 'data/user.rebate/index', 'data/user.rebate/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (15, 11, '用户提现管理', 'layui-icon layui-icon-component', 'data/user.transfer/index', 'data/user.transfer/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (16, 11, '用户等级管理', 'layui-icon layui-icon-senior', 'data/base.upgrade/index', 'data/base.upgrade/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (17, 11, '用户折扣方案', 'layui-icon layui-icon-set', 'data/base.discount/index', 'data/base.discount/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (18, 1, '商城管理', '', '', '#', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (19, 18, '商品数据管理', 'layui-icon layui-icon-star', 'data/shop.goods/index', 'data/shop.goods/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (20, 18, '商品分类管理', 'layui-icon layui-icon-tabs', 'data/shop.cate/index', 'data/shop.cate/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (21, 18, '订单数据管理', 'layui-icon layui-icon-template', 'data/shop.order/index', 'data/shop.order/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (22, 18, '订单发货管理', 'layui-icon layui-icon-transfer', 'data/shop.send/index', 'data/shop.send/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (23, 18, '快递公司管理', 'layui-icon layui-icon-website', 'data/base.postage.company/index', 'data/base.postage.company/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (24, 18, '邮费模板管理', 'layui-icon layui-icon-template-1', 'data/base.postage.template/index', 'data/base.postage.template/index', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (25, 0, '微信管理', '', '', '#', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (26, 25, '微信管理', '', '', '#', '', '_self', 0, 1, '2022-03-04 20:34:40');
INSERT INTO `system_menu`
VALUES (27, 26, '微信接口配置', 'layui-icon layui-icon-set', '', 'wechat/config/options', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (28, 26, '微信支付配置', 'layui-icon layui-icon-rmb', '', 'wechat/config/payment', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (29, 25, '微信定制', '', '', '#', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (30, 29, '微信粉丝管理', 'layui-icon layui-icon-username', '', 'wechat/fans/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (31, 29, '微信图文管理', 'layui-icon layui-icon-template-1', '', 'wechat/news/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (32, 29, '微信菜单配置', 'layui-icon layui-icon-cellphone', '', 'wechat/menu/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (33, 29, '回复规则管理', 'layui-icon layui-icon-engine', '', 'wechat/keys/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (34, 29, '关注回复配置', 'layui-icon layui-icon-senior', '', 'wechat/keys/subscribe', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (35, 29, '默认回复配置', 'layui-icon layui-icon-util', '', 'wechat/keys/defaults', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (36, 29, '关注自动回复', 'layui-icon layui-icon-release', 'wechat/auto/index', 'wechat/auto/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (37, 0, '系统管理', '', '', '#', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (38, 37, '系统配置', '', '', '#', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (39, 38, '系统参数配置', 'layui-icon layui-icon-set', '', 'admin/config/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (40, 38, '系统任务管理', 'layui-icon layui-icon-log', '', 'admin/queue/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (41, 38, '系统日志管理', 'layui-icon layui-icon-form', '', 'admin/oplog/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (42, 38, '数据字典管理', 'layui-icon layui-icon-code-circle', 'admin/base/index', 'admin/base/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (43, 38, '系统菜单管理', 'layui-icon layui-icon-layouts', '', 'admin/menu/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (44, 37, '权限管理', '', '', '#', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (45, 44, '访问权限管理', 'layui-icon layui-icon-vercode', '', 'admin/auth/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu`
VALUES (46, 44, '系统用户管理', 'layui-icon layui-icon-username', '', 'admin/user/index', '', '_self', 0, 1, '2022-03-04 20:34:41');
INSERT INTO `system_menu` VALUES (1, 0, '控制台', '', '', '#', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (2, 1, '数据管理', '', '', '#', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (3, 2, '数据统计报表', 'layui-icon layui-icon-theme', 'data/total.portal/index', 'data/total.portal/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (4, 2, '轮播图片管理', 'layui-icon layui-icon-carousel', 'data/base.slider/index', 'data/base.slider/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (5, 2, '页面内容管理', 'layui-icon layui-icon-read', 'data/base.pager/index', 'data/base.pager/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (6, 2, '文章内容管理', 'layui-icon layui-icon-template', 'data/news.item/index', 'data/news.item/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (7, 2, '支付参数管理', 'layui-icon layui-icon-rmb', 'data/base.payment/index', 'data/base.payment/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (8, 2, '系统通知管理', 'layui-icon layui-icon-notice', 'data/base.message/index', 'data/base.message/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (9, 2, '微信小程序配置', 'layui-icon layui-icon-set', 'data/base.config/wxapp', 'data/base.config/wxapp', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (10, 2, '邀请二维码设置', 'layui-icon layui-icon-cols', 'data/base.config/cropper', 'data/base.config/cropper', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (11, 1, '用户管理', '', '', '#', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (12, 11, '会员用户管理', 'layui-icon layui-icon-user', 'data/user.admin/index', 'data/user.admin/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (13, 11, '余额充值管理', 'layui-icon layui-icon-rmb', 'data/user.balance/index', 'data/user.balance/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (14, 11, '用户返利管理', 'layui-icon layui-icon-transfer', 'data/user.rebate/index', 'data/user.rebate/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (15, 11, '用户提现管理', 'layui-icon layui-icon-component', 'data/user.transfer/index', 'data/user.transfer/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (16, 11, '用户等级管理', 'layui-icon layui-icon-senior', 'data/base.upgrade/index', 'data/base.upgrade/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (17, 11, '用户折扣方案', 'layui-icon layui-icon-set', 'data/base.discount/index', 'data/base.discount/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (18, 1, '商城管理', '', '', '#', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (19, 18, '商品数据管理', 'layui-icon layui-icon-star', 'data/shop.goods/index', 'data/shop.goods/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (20, 18, '商品分类管理', 'layui-icon layui-icon-tabs', 'data/shop.cate/index', 'data/shop.cate/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (21, 18, '订单数据管理', 'layui-icon layui-icon-template', 'data/shop.order/index', 'data/shop.order/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (22, 18, '订单发货管理', 'layui-icon layui-icon-transfer', 'data/shop.send/index', 'data/shop.send/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (23, 18, '快递公司管理', 'layui-icon layui-icon-website', 'data/base.postage.company/index', 'data/base.postage.company/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (24, 18, '邮费模板管理', 'layui-icon layui-icon-template-1', 'data/base.postage.template/index', 'data/base.postage.template/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (25, 0, '微信管理', '', '', '#', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (26, 25, '微信管理', '', '', '#', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (27, 26, '微信接口配置', 'layui-icon layui-icon-set', '', 'wechat/config/options', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (28, 26, '微信支付配置', 'layui-icon layui-icon-rmb', '', 'wechat/config/payment', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (29, 25, '微信定制', '', '', '#', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (30, 29, '微信粉丝管理', 'layui-icon layui-icon-username', '', 'wechat/fans/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (31, 29, '微信图文管理', 'layui-icon layui-icon-template-1', '', 'wechat/news/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (32, 29, '微信菜单配置', 'layui-icon layui-icon-cellphone', '', 'wechat/menu/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (33, 29, '回复规则管理', 'layui-icon layui-icon-engine', '', 'wechat/keys/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (34, 29, '关注回复配置', 'layui-icon layui-icon-senior', '', 'wechat/keys/subscribe', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (35, 29, '默认回复配置', 'layui-icon layui-icon-util', '', 'wechat/keys/defaults', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (36, 29, '关注自动回复', 'layui-icon layui-icon-release', 'wechat/auto/index', 'wechat/auto/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (37, 0, '系统管理', '', '', '#', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (38, 37, '系统配置', '', '', '#', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (39, 38, '系统参数配置', 'layui-icon layui-icon-set', '', 'admin/config/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (40, 38, '系统任务管理', 'layui-icon layui-icon-log', '', 'admin/queue/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (41, 38, '系统日志管理', 'layui-icon layui-icon-form', '', 'admin/oplog/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (42, 38, '数据字典管理', 'layui-icon layui-icon-code-circle', 'admin/base/index', 'admin/base/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (43, 38, '系统文件管理', 'layui-icon layui-icon-carousel', 'admin/file/index', 'admin/file/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (44, 38, '系统菜单管理', 'layui-icon layui-icon-layouts', '', 'admin/menu/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (45, 37, '权限管理', '', '', '#', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (46, 45, '访问权限管理', 'layui-icon layui-icon-vercode', '', 'admin/auth/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
INSERT INTO `system_menu` VALUES (47, 45, '系统用户管理', 'layui-icon layui-icon-username', '', 'admin/user/index', '', '_self', 0, 1, '2022-06-27 14:29:17');
-- ----------------------------
-- Table structure for system_user

View File

@ -66,4 +66,31 @@ CREATE TABLE IF NOT EXISTS `system_base`
ALTER TABLE `system_user`
ADD COLUMN `usertype` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '用户类型' AFTER `id`;
-- 尝试创建系统文件数据表
CREATE TABLE IF NOT EXISTS `system_file` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '上传类型',
`hash` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '文件哈希',
`name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '文件名称',
`xext` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '文件后缀',
`xurl` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '访问链接',
`xkey` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '文件路径',
`mime` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '文件类型',
`size` bigint(20) NULL DEFAULT 0 COMMENT '文件大小',
`uuid` bigint(20) NULL DEFAULT 0 COMMENT '用户编号',
`isfast` tinyint(1) NULL DEFAULT 0 COMMENT '是否秒传',
`issafe` tinyint(1) NULL DEFAULT 0 COMMENT '安全模式',
`status` tinyint(1) NULL DEFAULT 1 COMMENT '上传状态(1悬空,2落地)',
`create_at` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_at` datetime NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_system_file_type`(`type`) USING BTREE,
INDEX `idx_system_file_hash`(`hash`) USING BTREE,
INDEX `idx_system_file_uuid`(`uuid`) USING BTREE,
INDEX `idx_system_file_xext`(`xext`) USING BTREE,
INDEX `idx_system_file_status`(`status`) USING BTREE,
INDEX `idx_system_file_issafe`(`issafe`) USING BTREE,
INDEX `idx_system_file_isfast`(`isfast`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统-文件' ROW_FORMAT = COMPACT;
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -94,10 +94,9 @@ class Auth extends Controller
{
$map = $this->_vali(['auth.require#id' => '权限ID不能为空']);
if (input('action') === 'get') {
$admin = AdminService::instance();
if ($this->app->isDebug()) $admin->clearCache();
if ($this->app->isDebug()) AdminService::clearCache();
$nodes = SystemNode::mk()->where($map)->column('node');
$this->success('获取权限节点成功!', $admin->getTree($nodes));
$this->success('获取权限节点成功!', AdminService::getTree($nodes));
} elseif (input('action') === 'save') {
[$post, $data] = [$this->request->post(), []];
foreach ($post['nodes'] ?? [] as $node) {

View File

@ -52,8 +52,8 @@ class Config extends Controller
public function index()
{
$this->title = '系统参数配置';
$this->super = AdminService::instance()->isSuper();
$this->version = ModuleService::instance()->getVersion();
$this->super = AdminService::isSuper();
$this->version = ModuleService::getVersion();
$this->fetch();
}
@ -81,11 +81,11 @@ class Config extends Controller
if ($post['xpath'] !== 'admin' && file_exists($this->app->getBasePath() . $post['xpath'])) {
$this->error("后台入口名称{$post['xpath']}已经存在应用!");
}
SystemService::instance()->setRuntime(null, [$post['xpath'] => 'admin']);
SystemService::setRuntime(null, [$post['xpath'] => 'admin']);
}
// 修改网站 ICON 图标文件,替换 public/favicon.ico 文件
if (preg_match('#^https?://#', $icon = $post['site_icon'] ?? '')) try {
SystemService::instance()->setFavicon($icon);
SystemService::setFavicon($icon);
} catch (\Exception $exception) {
trace_file($exception);
$this->error($exception->getMessage());

View File

@ -0,0 +1,83 @@
<?php
// +----------------------------------------------------------------------
// | ThinkAdmin
// +----------------------------------------------------------------------
// | 版权所有 2014~2022 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免费声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/ThinkAdmin
// | github 代码仓库https://github.com/zoujingli/ThinkAdmin
// +----------------------------------------------------------------------
namespace app\admin\controller;
use think\admin\Controller;
use think\admin\helper\QueryHelper;
use think\admin\model\SystemFile;
use think\admin\service\AdminService;
/**
* 系统文件管理
* Class File
* @package app\admin\controller
*/
class File extends Controller
{
/**
* 存储方式处理
* @var string[]
*/
protected $types = [
'local' => '本地服务器存储',
'qiniu' => '七牛云对象存储',
'upyun' => '又拍云USS存储',
'alioss' => '阿里云OSS存储',
'txcos' => '腾讯云COS存储'
];
/**
* 系统文件管理
* @auth true
* @menu true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function index()
{
SystemFile::mQuery()->layTable(function () {
$this->title = '系统文件管理';
$this->xexts = SystemFile::mk()->distinct()->column('xext');
}, function (QueryHelper $query) {
$query->like('name,hash,xext')->equal('type')->dateBetween('create_at');
$query->where(['issafe' => 0, 'status' => 2, 'uuid' => AdminService::getUserId()]);
});
}
/**
* 数据列表处理
* @param array $data
* @return void
*/
protected function _page_filter(array &$data)
{
foreach ($data as &$vo) {
$vo['ctype'] = $this->types[$vo['type']] ?? $vo['type'];
}
}
/**
* 删除系统文件
* @auth true
* @return void
*/
public function remove()
{
SystemFile::mDelete();
}
}

View File

@ -38,19 +38,18 @@ class Index extends Controller
public function index()
{
/*! 根据运行模式刷新权限 */
$debug = $this->app->isDebug();
AdminService::instance()->apply($debug);
AdminService::apply($this->app->isDebug());
/*! 读取当前用户权限菜单树 */
$this->menus = MenuService::instance()->getTree();
$this->menus = MenuService::getTree();
/*! 判断当前用户的登录状态 */
$this->login = AdminService::instance()->isLogin();
$this->login = AdminService::isLogin();
/*! 菜单为空且未登录跳转到登录页 */
if (empty($this->menus) && empty($this->login)) {
$this->redirect(sysuri('admin/login/index'));
} else {
$this->title = '系统管理后台';
$this->super = AdminService::instance()->isSuper();
$this->theme = AdminService::instance()->getUserTheme();
$this->super = AdminService::isSuper();
$this->theme = AdminService::getUserTheme();
$this->fetch();
}
}
@ -66,12 +65,12 @@ class Index extends Controller
public function theme()
{
if ($this->request->isGet()) {
$this->theme = AdminService::instance()->getUserTheme();
$this->theme = AdminService::getUserTheme();
$this->themes = Config::themes;
$this->fetch();
} else {
$data = $this->_vali(['site_theme.require' => '主题名称不能为空!']);
if (AdminService::instance()->setUserTheme($data['site_theme'])) {
if (AdminService::setUserTheme($data['site_theme'])) {
$this->success('主题配置保存成功!');
} else {
$this->error('主题配置保存失败!');
@ -87,7 +86,7 @@ class Index extends Controller
public function info($id = 0)
{
$this->_applyFormToken();
if (AdminService::instance()->getUserId() === intval($id)) {
if (AdminService::getUserId() === intval($id)) {
SystemUser::mForm('admin@user/form', 'id', [], ['id' => $id]);
} else {
$this->error('只能修改自己的资料!');
@ -116,7 +115,7 @@ class Index extends Controller
public function pass($id = 0)
{
$this->_applyFormToken();
if (AdminService::instance()->getUserId() !== intval($id)) {
if (AdminService::getUserId() !== intval($id)) {
$this->error('只能修改当前用户的密码!');
}
if ($this->app->request->isGet()) {

View File

@ -40,15 +40,14 @@ class Login extends Controller
public function index()
{
if ($this->app->request->isGet()) {
if (AdminService::instance()->isLogin()) {
if (AdminService::isLogin()) {
$this->redirect(sysuri('admin/index/index'));
} else {
// 当前运行模式
$system = SystemService::instance();
$this->developMode = $system->checkRunMode();
$this->developMode = SystemService::checkRunMode();
// 后台背景处理
$images = str2arr(sysconf('login_image') ?: '', '|') ?: [
$system->uri('/static/theme/img/login/bg1.jpg'), $system->uri('/static/theme/img/login/bg2.jpg'),
SystemService::uri('/static/theme/img/login/bg1.jpg'), SystemService::uri('/static/theme/img/login/bg2.jpg'),
];
$this->loginStyle = sprintf('style="background-image:url(%s)" data-bg-transition="%s"', $images[0], join(',', $images));
// 登录验证令牌

View File

@ -101,18 +101,18 @@ class Menu extends Controller
if ($this->request->isGet()) {
/* 清理权限节点 */
if ($isDebug = $this->app->isDebug()) {
AdminService::instance()->clearCache();
AdminService::clearCache();
}
/* 选择自己上级菜单 */
$vo['pid'] = $vo['pid'] ?? input('pid', '0');
/* 读取系统功能节点 */
$this->auths = [];
$this->nodes = MenuService::instance()->getList($isDebug);
foreach (NodeService::instance()->getMethods($isDebug) as $node => $item) {
$this->nodes = MenuService::getList($isDebug);
foreach (NodeService::getMethods($isDebug) as $node => $item) {
if ($item['isauth'] && substr_count($node, '/') >= 2) {
$this->auths[] = ['node' => $node, 'title' => $item['title']];
}
}
/* 选择自己上级菜单 */
$vo['pid'] = $vo['pid'] ?? input('pid', '0');
/* 列出可选上级菜单 */
$menus = SystemMenu::mk()->order('sort desc,id asc')->column('id,pid,icon,url,node,title,params', 'id');
$this->menus = DataExtend::arr2table(array_merge($menus, [['id' => '0', 'pid' => '-1', 'url' => '#', 'title' => '顶部菜单']]));

View File

@ -34,7 +34,7 @@ class Module extends Controller
public function index()
{
$this->title = '系统模块管理';
$this->modules = ModuleService::instance()->change();
$this->modules = ModuleService::change();
$this->fetch();
}
@ -45,7 +45,7 @@ class Module extends Controller
public function install()
{
$data = $this->_vali(['name.require' => '模块名称不能为空!']);
[$state, $message] = ModuleService::instance()->install($data['name']);
[$state, $message] = ModuleService::install($data['name']);
$state ? $this->success($message) : $this->error($message);
}
@ -56,8 +56,8 @@ class Module extends Controller
public function change()
{
$data = $this->_vali(['name.require' => '模块名称不能为空!']);
$online = ModuleService::instance()->online();
$locals = ModuleService::instance()->getModules();
$online = ModuleService::online();
$locals = ModuleService::getModules();
if (isset($online[$data['name']])) {
$this->module = $online[$data['name']];
$this->current = $locals[$data['name']] ?? [];

View File

@ -44,13 +44,11 @@ class Queue extends Controller
{
SystemQueue::mQuery()->layTable(function () {
$this->title = '系统任务管理';
$this->iswin = ProcessService::instance()->iswin();
if ($this->super = AdminService::instance()->isSuper()) {
$process = ProcessService::instance();
if ($process->iswin() || empty($_SERVER['USER'])) {
$this->command = $process->think('xadmin:queue start');
} else {
$this->command = "sudo -u {$_SERVER['USER']} {$process->think('xadmin:queue start')}";
$this->iswin = ProcessService::iswin();
if ($this->super = AdminService::isSuper()) {
$this->command = ProcessService::think('xadmin:queue start');
if (!$this->iswin && !empty($_SERVER['USER'])) {
$this->command = "sudo -u {$_SERVER['USER']} {$this->command}";
}
}
}, function (QueryHelper $query) {

View File

@ -143,7 +143,7 @@ class User extends Controller
// 用户身份数据
$this->bases = SystemBase::items('身份权限');
// 用户权限管理
$this->superName = AdminService::instance()->getSuperName();
$this->superName = AdminService::getSuperName();
$this->authorizes = SystemAuth::items();
}
}

View File

@ -44,7 +44,7 @@ class Plugs extends Controller
*/
public function optimize()
{
if (AdminService::instance()->isSuper()) {
if (AdminService::isSuper()) {
sysoplog('系统运维管理', '创建数据库优化任务');
$this->_queue('优化数据库所有数据表', 'xadmin:database optimize');
} else {

View File

@ -96,7 +96,7 @@ class Queue extends Controller
*/
public function status()
{
if (AdminService::instance()->isSuper()) try {
if (AdminService::isSuper()) try {
$message = $this->app->console->call('xadmin:queue', ['status'])->fetch();
if (preg_match('/process.*?\d+.*?running/', $message)) {
echo "<span class='color-green pointer' data-tips-text='{$message}'>已启动</span>";

View File

@ -36,9 +36,9 @@ class Runtime extends Controller
*/
public function push()
{
if (AdminService::instance()->isSuper()) try {
AdminService::instance()->clearCache();
SystemService::instance()->pushRuntime();
if (AdminService::isSuper()) try {
AdminService::clearCache();
SystemService::pushRuntime();
sysoplog('系统运维管理', '刷新创建路由缓存');
$this->success('网站缓存加速成功!', 'javascript:location.reload()');
} catch (HttpResponseException $exception) {
@ -56,9 +56,9 @@ class Runtime extends Controller
*/
public function clear()
{
if (AdminService::instance()->isSuper()) try {
AdminService::instance()->clearCache();
SystemService::instance()->clearRuntime();
if (AdminService::isSuper()) try {
AdminService::clearCache();
SystemService::clearRuntime();
sysoplog('系统运维管理', '清理网站日志缓存');
$this->success('清空日志缓存成功!', 'javascript:location.reload()');
} catch (HttpResponseException $exception) {
@ -76,12 +76,12 @@ class Runtime extends Controller
*/
public function debug()
{
if (AdminService::instance()->isSuper()) if (input('state')) {
SystemService::instance()->setRuntime('product');
if (AdminService::isSuper()) if (input('state')) {
SystemService::setRuntime('product');
sysoplog('系统运维管理', '开发模式切换为生产模式');
$this->success('已切换为生产模式!', 'javascript:location.reload()');
} else {
SystemService::instance()->setRuntime('debug');
SystemService::setRuntime('debug');
sysoplog('系统运维管理', '生产模式切换为开发模式');
$this->success('已切换为开发模式!', 'javascript:location.reload()');
} else {
@ -98,7 +98,7 @@ class Runtime extends Controller
*/
public function editor()
{
if (AdminService::instance()->isSuper()) {
if (AdminService::isSuper()) {
$editor = input('editor', 'auto');
sysconf('base.editor', $editor);
sysoplog('系统运维管理', "切换编辑器为{$editor}");
@ -114,7 +114,7 @@ class Runtime extends Controller
*/
public function config()
{
if (AdminService::instance()->isSuper()) try {
if (AdminService::isSuper()) try {
[$tmpdata, $newdata] = [[], []];
foreach (SystemConfig::mk()->order('type,name asc')->cursor() as $item) {
$tmpdata[$item['type']][$item['name']] = $item['value'];

View File

@ -33,7 +33,7 @@ class Update extends Controller
*/
protected function initialize()
{
if (!SystemService::instance()->checkRunMode()) {
if (!SystemService::checkRunMode()) {
$this->error('只允许访问本地或官方代码!');
}
}
@ -44,7 +44,7 @@ class Update extends Controller
public function get()
{
$filename = decode(input('encode', '0'));
if (!ModuleService::instance()->checkAllowDownload($filename)) {
if (!ModuleService::checkAllowDownload($filename)) {
$this->error('下载的文件不在认证规则中!');
}
if (file_exists($realname = $this->app->getRootPath() . $filename)) {
@ -61,7 +61,7 @@ class Update extends Controller
*/
public function node()
{
$this->success('获取文件列表成功!', ModuleService::instance()->getChanges(
$this->success('获取文件列表成功!', ModuleService::getChanges(
json_decode($this->request->post('rules', '[]', ''), true),
json_decode($this->request->post('ignore', '[]', ''), true)
));
@ -72,6 +72,6 @@ class Update extends Controller
*/
public function version()
{
$this->success('获取模块信息成功!', ModuleService::instance()->getModules());
$this->success('获取模块信息成功!', ModuleService::getModules());
}
}

View File

@ -72,7 +72,7 @@ class Upload extends Controller
$file = SystemFile::mk()->data($this->_vali([
'xkey.value' => $data['key'],
'type.value' => $this->getType(),
'uuid.value' => AdminService::instance()->getUserId(),
'uuid.value' => AdminService::getUserId(),
'name.require' => '名称不能为空!',
'hash.require' => '哈希不能为空!',
'xext.require' => '后缀不能为空!',
@ -129,7 +129,7 @@ class Upload extends Controller
'id.require' => '编号不能为空!',
'hash.require' => '哈希不能为空!',
]);
$data['uuid'] = AdminService::instance()->getUserId();
$data['uuid'] = AdminService::getUserId();
$file = SystemFile::mk()->where($data)->findOrEmpty();
if ($file->isEmpty()) $this->error('文件不存在!');
if ($file->save(['status' => 2])) {
@ -147,13 +147,49 @@ class Upload extends Controller
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function modal()
public function image()
{
SystemFile::mQuery()->layTable(function () {
$this->title = '文件选择器';
}, function (QueryHelper $query) {
$query->where(['status' => 2])->order('id desc');
$query->like('name,hash')->dateBetween('create_at');
$query->like('name,hash')->dateBetween('create_at')->order('id desc');
$query->where(['status' => 2, 'issafe' => 0, 'uuid' => AdminService::getUserId()]);
});
}
/**
* 视频选择器
* @login true
* @return void
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function video()
{
SystemFile::mQuery()->layTable(function () {
$this->title = '文件选择器';
}, function (QueryHelper $query) {
$query->like('name,hash')->dateBetween('create_at')->order('id desc');
$query->where(['status' => 2, 'issafe' => 0, 'uuid' => AdminService::getUserId()]);
});
}
/**
* 文档选择器
* @login true
* @return void
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function document()
{
SystemFile::mQuery()->layTable(function () {
$this->title = '文件选择器';
}, function (QueryHelper $query) {
$query->like('name,hash')->dateBetween('create_at')->order('id desc');
$query->where(['status' => 2, 'issafe' => 0, 'uuid' => AdminService::getUserId()]);
});
}

View File

@ -19,14 +19,14 @@ use think\App;
invoke(function (App $app) {
/*! 非开发环境,清理限制文件 */
if ($app->request->isGet() && !SystemService::instance()->checkRunMode()) {
if ($app->request->isGet() && !SystemService::checkRunMode()) {
@unlink("{$app->getBasePath()}admin/controller/api/Update.php");
@unlink("{$app->getBasePath()}admin/route/demo.php");
@rmdir("{$app->getBasePath()}admin/route");
return;
}
/*! 演示环境禁止操作路由绑定 */
if (SystemService::instance()->checkRunMode('demo')) {
if (SystemService::checkRunMode('demo')) {
$app->route->post('index/pass', function () {
return json(['code' => 0, 'info' => '演示环境禁止修改用户密码!']);
});
@ -58,5 +58,4 @@ invoke(function (App $app) {
return json(['code' => 0, 'info' => '演示环境禁止修改用户密码!']);
});
}
});

View File

@ -0,0 +1,152 @@
<div class="image-dialog" id="ImageDialog">
<div class="image-dialog-head">
<div class="pull-left flex">
<input class="layui-input margin-right-5" v-model="keys" style="height:30px;line-height:30px" placeholder="请输入搜索关键词">
<a class="layui-btn layui-btn-sm layui-btn-normal" @click="search"> </a>
</div>
<div class="pull-right">
<a class="layui-btn layui-btn-sm" @click="uploadImage">上传图片</a>
</div>
</div>
<div class="image-dialog-body">
<div class="image-dialog-item" v-for="x in items" v-if="show">
<div class="uploadimage" :style="x.style" @click="setValue(x.xurl)"></div>
<p class="image-dialog-item-name layui-elip" v-text="x.name"></p>
</div>
</div>
<div class="image-dialog-foot">
<div id="ImageDialogPage" class="image-dialog-page"></div>
</div>
</div>
<style>
.image-dialog-head {
clear: both;
height: 30px;
padding: 10px 12px;
}
.image-dialog-body {
height: 470px;
background: #efefef;
padding-top: 12px;
padding-left: 12px;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
.image-dialog-item {
position: relative;
margin-right: 12px;
margin-bottom: 12px;
}
.image-dialog-item-name {
left: 0;
right: 0;
bottom: 0;
color: #fff;
padding: 3px 10px;
position: absolute;
text-align: center;
line-height: 1.5em;
white-space: nowrap;
background: rgba(0, 0, 0, 0.6);
}
.image-dialog-item .uploadimage {
margin: 0;
width: 145px;
height: 145px;
}
.image-dialog-foot {
padding: 0 12px;
}
.image-dialog-page {
height: 50px;
text-align: center;
}
.image-dialog-page .layui-laypage a,
.image-dialog-page .layui-laypage span {
margin-bottom: 0;
}
</style>
<script>
require(['vue'], function (vue) {
var app = new vue({
el: '#ImageDialog',
data: {
page: 1,
limit: 15,
show: false,
$btn: null,
keys: '',
items: [],
},
created: function () {
this.$btn = $('#{$get.id|default=""}');
this.loadPage();
},
methods: {
// 创建分页工具条
addPage: function (count) {
var that = this;
this.show = true;
layui.laypage.render({
curr: this.page, count: count, limit: that.limit,
layout: ['count', 'prev', 'page', 'next', 'refresh'],
elem: 'ImageDialogPage', jump: function (obj, first) {
if (!first) that.loadPage(that.page = obj.curr);
},
});
},
// 搜索刷新数据
search: function () {
this.page = 1;
this.loadPage();
},
// 设置选择数据
setValue: function (url) {
this.$btn.trigger('choose', url);
if (this.$btn.data('input')) $(this.$btn.data('input')).val(url).trigger('change', url);
$('#ImageDialog').parents('.layui-layer-content').next().find('.layui-layer-close').trigger('click');
},
// 加载页面数据
loadPage: function () {
var that = this;
this.params = {page: this.page, limit: this.limit, output: 'layui.table', name: this.keys || ''};
$.form.load('{:url("image")}', this.params, 'get', function (ret) {
that.addPage(ret.count);
that.items = ret.data;
that.items.forEach(function (item) {
item.style = 'background-image:url(' + item.xurl + ')';
});
return false;
});
},
// 上传图片文件
uploadImage: function () {
$('[data-field="image-dialog-upload-input"]').click();
$('[name="image-dialog-upload-input"]').one('change', function (e) {
app.setValue(e.currentTarget.value);
// e.currentTarget.value 取上传后的值
// app.page = 1;
// app.loadPage();
});
},
}
});
});
</script>
<label class="layui-hide">
<!-- 图片上传组件 开始 -->
<input class="layui-input" name="image-dialog-upload-input">
<button class="layui-btn" data-file data-type="png,jpg,jpeg,gif" data-field="image-dialog-upload-input"></button>
<!-- 图片上传组件 结束 -->
</label>

View File

@ -0,0 +1,151 @@
<div class="image-dialog" id="ImageDialog">
<div class="image-dialog-head">
<div class="pull-left flex">
<input class="layui-input margin-right-5" v-model="keys" style="height:30px;line-height:30px" placeholder="请输入搜索关键词">
<a class="layui-btn layui-btn-sm layui-btn-normal" @click="search"> </a>
</div>
<div class="pull-right">
<a class="layui-btn layui-btn-sm" @click="uploadImage">上传图片</a>
</div>
</div>
<div class="image-dialog-body">
<div class="image-dialog-item" v-for="x in list" v-if="show">
<div class="uploadimage" :style="x.style" @click="setValue(x.xurl)"></div>
<p class="image-dialog-item-name layui-elip" v-text="x.name"></p>
</div>
</div>
<div class="image-dialog-foot">
<div id="ImageDialogPage" class="image-dialog-page"></div>
</div>
</div>
<style>
.image-dialog-head {
clear: both;
height: 30px;
padding: 10px 12px;
}
.image-dialog-body {
height: 470px;
background: #efefef;
padding-top: 12px;
padding-left: 12px;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
.image-dialog-item {
position: relative;
margin-right: 12px;
margin-bottom: 12px;
}
.image-dialog-item-name {
left: 0;
right: 0;
bottom: 0;
color: #fff;
padding: 3px 10px;
position: absolute;
text-align: center;
line-height: 1.5em;
white-space: nowrap;
background: rgba(0, 0, 0, 0.6);
}
.image-dialog-item .uploadimage {
margin: 0;
width: 145px;
height: 145px;
}
.image-dialog-foot {
padding: 0 12px;
}
.image-dialog-page {
height: 50px;
text-align: center;
}
.image-dialog-page .layui-laypage a,
.image-dialog-page .layui-laypage span {
margin-bottom: 0;
}
</style>
<script>
require(['vue'], function (vue) {
var app = new vue({
el: '#ImageDialog',
data: {
page: 1,
limit: 15,
show: false,
keys: '',
list: [],
},
created: function () {
this.$btn = $('#{$get.id|default=""}');
this.loadPage();
},
methods: {
// 搜索刷新数据
search: function () {
this.page = 1;
this.loadPage();
},
// 设置选择数据
setValue: function (url) {
this.$btn.trigger('choose', url);
if (this.$btn.data('input')) $(this.$btn.data('input')).val(url).trigger('change', url);
$('#ImageDialog').parents('.layui-layer-content').next().find('.layui-layer-close').trigger('click');
},
// 创建分页工具条
addPage: function (count) {
var that = this;
this.show = true;
layui.laypage.render({
curr: this.page, count: count, limit: that.limit,
layout: ['count', 'prev', 'page', 'next', 'refresh'],
elem: 'ImageDialogPage', jump: function (obj, first) {
if (!first) that.loadPage(that.page = obj.curr);
},
});
},
// 加载页面数据
loadPage: function () {
var that = this;
this.params = {page: this.page, limit: this.limit, output: 'layui.table', name: this.keys || ''};
$.form.load('{:url("image")}', this.params, 'get', function (ret) {
that.list = ret.data;
that.list.forEach(function (item) {
item.style = 'background-image:url(' + item.xurl + ')';
});
that.addPage(ret.count);
return false;
});
},
// 上传图片文件
uploadImage: function () {
$('[data-field="image-dialog-upload-input"]').click();
$('[name="image-dialog-upload-input"]').one('change', function (e) {
app.setValue(e.currentTarget.value);
// e.currentTarget.value 取上传后的值
// app.page = 1;
// app.loadPage();
});
},
}
});
});
</script>
<label class="layui-hide">
<!-- 图片上传组件 开始 -->
<input class="layui-input" name="image-dialog-upload-input">
<button class="layui-btn" data-file data-type="png,jpg,jpeg,gif" data-field="image-dialog-upload-input"></button>
<!-- 图片上传组件 结束 -->
</label>

View File

@ -0,0 +1,152 @@
<div class="image-dialog" id="ImageDialog">
<div class="image-dialog-head">
<div class="pull-left flex">
<input class="layui-input margin-right-5" v-model="keys" style="height:30px;line-height:30px" placeholder="请输入搜索关键词">
<a class="layui-btn layui-btn-sm layui-btn-normal" @click="search"> </a>
</div>
<div class="pull-right">
<a class="layui-btn layui-btn-sm" @click="uploadImage">上传图片</a>
</div>
</div>
<div class="image-dialog-body">
<div class="image-dialog-item" v-for="x in items" v-if="show">
<div class="uploadimage" :style="x.style" @click="setValue(x.xurl)"></div>
<p class="image-dialog-item-name layui-elip" v-text="x.name"></p>
</div>
</div>
<div class="image-dialog-foot">
<div id="ImageDialogPage" class="image-dialog-page"></div>
</div>
</div>
<style>
.image-dialog-head {
clear: both;
height: 30px;
padding: 10px 12px;
}
.image-dialog-body {
height: 470px;
background: #efefef;
padding-top: 12px;
padding-left: 12px;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
.image-dialog-item {
position: relative;
margin-right: 12px;
margin-bottom: 12px;
}
.image-dialog-item-name {
left: 0;
right: 0;
bottom: 0;
color: #fff;
padding: 3px 10px;
position: absolute;
text-align: center;
line-height: 1.5em;
white-space: nowrap;
background: rgba(0, 0, 0, 0.6);
}
.image-dialog-item .uploadimage {
margin: 0;
width: 145px;
height: 145px;
}
.image-dialog-foot {
padding: 0 12px;
}
.image-dialog-page {
height: 50px;
text-align: center;
}
.image-dialog-page .layui-laypage a,
.image-dialog-page .layui-laypage span {
margin-bottom: 0;
}
</style>
<script>
require(['vue'], function (vue) {
var app = new vue({
el: '#ImageDialog',
data: {
page: 1,
limit: 15,
show: false,
$btn: null,
keys: '',
items: [],
},
created: function () {
this.$btn = $('#{$get.id|default=""}');
this.loadPage();
},
methods: {
// 创建分页工具条
addPage: function (count) {
var that = this;
this.show = true;
layui.laypage.render({
curr: this.page, count: count, limit: that.limit,
layout: ['count', 'prev', 'page', 'next', 'refresh'],
elem: 'ImageDialogPage', jump: function (obj, first) {
if (!first) that.loadPage(that.page = obj.curr);
},
});
},
// 搜索刷新数据
search: function () {
this.page = 1;
this.loadPage();
},
// 设置选择数据
setValue: function (url) {
this.$btn.trigger('choose', url);
if (this.$btn.data('input')) $(this.$btn.data('input')).val(url).trigger('change', url);
$('#ImageDialog').parents('.layui-layer-content').next().find('.layui-layer-close').trigger('click');
},
// 加载页面数据
loadPage: function () {
var that = this;
this.params = {page: this.page, limit: this.limit, output: 'layui.table', name: this.keys || ''};
$.form.load('{:url("image")}', this.params, 'get', function (ret) {
that.addPage(ret.count);
that.items = ret.data;
that.items.forEach(function (item) {
item.style = 'background-image:url(' + item.xurl + ')';
});
return false;
});
},
// 上传图片文件
uploadImage: function () {
$('[data-field="image-dialog-upload-input"]').click();
$('[name="image-dialog-upload-input"]').one('change', function (e) {
app.setValue(e.currentTarget.value);
// e.currentTarget.value 取上传后的值
// app.page = 1;
// app.loadPage();
});
},
}
});
});
</script>
<label class="layui-hide">
<!-- 图片上传组件 开始 -->
<input class="layui-input" name="image-dialog-upload-input">
<button class="layui-btn" data-file data-type="png,jpg,jpeg,gif" data-field="image-dialog-upload-input"></button>
<!-- 图片上传组件 结束 -->
</label>

View File

@ -2,7 +2,7 @@
{block name="button"}
<!--{if auth("add")}-->
<button data-modal='{:url("add")}' data-table-id="RoleTable" class='layui-btn layui-btn-sm layui-btn-primary'>添加权限</button>
<button data-modal='{:url("add")}' data-width="600px" data-table-id="RoleTable" class='layui-btn layui-btn-sm layui-btn-primary'>添加权限</button>
<!--{/if}-->
<!--{if auth("remove")}-->
@ -66,7 +66,7 @@
<!-- 数据操作工具条模板 -->
<script type="text/html" id="ToolbarRoleTableTpl">
<!--{if auth('edit')}-->
<a class="layui-btn layui-btn-primary layui-btn-sm" data-title="编辑权限" data-modal='{:url("edit")}?id={{d.id}}'> </a>
<a class="layui-btn layui-btn-primary layui-btn-sm" data-width="600px" data-title="编辑权限" data-modal='{:url("edit")}?id={{d.id}}'> </a>
<!--{/if}-->
<!--{if auth("apply")}-->

View File

@ -0,0 +1,114 @@
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card" data-table-id="UserTable">
<div class="layui-card-body padding-left-40">
<fieldset class="layui-bg-gray">
<legend><b class="layui-badge think-bg-violet">用户账号</b></legend>
<div class="layui-row layui-col-space15">
<div class="layui-col-xs2 text-center padding-top-15">
<input type="hidden" name="headimg" value="{$vo.headimg|default=''}">
<script>$('[name=headimg]').uploadOneImage();</script>
</div>
<div class="layui-col-xs5">
<label class="block relative">
<span class="help-label"><b>登录账号</b>User Name</span>
{if isset($vo) and isset($vo.username)}
<input disabled value='{$vo.username|default=""}' required class="layui-input think-bg-gray">
{else}
<input name="username" value='{$vo.username|default=""}' required pattern="^.{4,}$" placeholder="请输入登录账号" class="layui-input">
{/if}
<span class="help-block">登录账号不能重复并且创建后不能再次修改哦。</span>
</label>
</div>
<div class="layui-col-xs5">
<label class="block relative">
<span class="help-label"><b>用户名称</b>Nick Name</span>
<input name="nickname" value='{$vo.nickname|default=""}' required placeholder="请输入用户名称" class="layui-input">
<span class="help-block">用于区分用户数据的用户名称,请尽量不要重复。</span>
</label>
</div>
</div>
</fieldset>
{if !empty($bases) || !empty($authorizes)}
<fieldset class="layui-bg-gray">
<legend><b class="layui-badge think-bg-violet">用户权限</b></legend>
{if !empty($bases)}
<div class="layui-form-item">
<div class="help-label"><b>角色身份</b>Role Identity</div>
<div class="layui-textarea help-checks">
{foreach $bases as $base}
<label class="think-checkbox">
{if isset($vo.usertype) and $vo.usertype eq $base.code}
<input type="radio" checked name="usertype" value="{$base.code}" lay-ignore>{$base.name}
{else}
<input type="radio" name="usertype" value="{$base.code}" lay-ignore>{$base.name}
{/if}
</label>
{/foreach}
</div>
</div>
{/if}
{if !empty($authorizes)}
<div class="layui-form-item">
<div class="help-label"><b>访问权限</b>Role Permission</div>
<div class="layui-textarea help-checks">
{if isset($vo.username) and $vo.username eq $superName}
<span class="color-desc padding-left-5">超级用户拥所有访问权限,不需要配置权限。</span>
{else}{foreach $authorizes as $authorize}
<label class="think-checkbox">
{if in_array($authorize.id, $vo.authorize)}
<input type="checkbox" checked name="authorize[]" value="{$authorize.id}" lay-ignore>{$authorize.title}
{else}
<input type="checkbox" name="authorize[]" value="{$authorize.id}" lay-ignore>{$authorize.title}
{/if}
</label>
{/foreach}{/if}
</div>
</div>
{/if}
</fieldset>
{/if}
<fieldset class="layui-bg-gray">
<legend><b class="layui-badge think-bg-violet">用户资料</b></legend>
<div class="layui-row layui-col-space15">
<div class="layui-col-xs4">
<label class="relative block">
<span class="help-label"><b>联系邮箱</b>Contact Email</span>
<input name="contact_mail" pattern="^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$" value='{$vo.contact_mail|default=""}' placeholder="请输入联系电子邮箱" class="layui-input">
<span class="color-desc">可选,请填写用户常用的电子邮箱</span>
</label>
</div>
<div class="layui-col-xs4">
<label class="relative block">
<span class="help-label"><b>联系手机</b>Contact Mobile</span>
<input type="tel" maxlength="11" name="contact_phone" value='{$vo.contact_phone|default=""}' pattern="^1[3-9][0-9]{9}$" placeholder="请输入用户联系手机" class="layui-input">
<span class="color-desc">可选,请填写用户常用的联系手机号</span>
</label>
</div>
<div class="layui-col-xs4">
<label class="relative block">
<span class="help-label"><b>联系QQ</b>Contact QQ</span>
<input name="contact_qq" pattern="^\d{6,}$" value='{$vo.contact_qq|default=""}' placeholder="请输入常用的联系QQ" class="layui-input">
<span class="color-desc">可选,请填写用户常用的联系QQ号</span>
</label>
</div>
</div>
<label class="layui-form-item block relative margin-top-10">
<span class="help-label"><b>用户描述</b>User Remark</span>
<textarea placeholder="请输入用户描述" class="layui-textarea" name="describe">{$vo.describe|default=""}</textarea>
</label>
</fieldset>
</div>
<div class="hr-line-dashed"></div>
{notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
<div class="layui-form-item text-center">
<button class="layui-btn" type='submit'>保存数据</button>
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
</div>
</form>

View File

@ -0,0 +1,64 @@
{extend name='table'}
{block name="button"}
<!--{if auth("remove")}-->
<a data-confirm="确定永久删除这些账号吗?" data-table-id="FileTable" data-action='{:url("remove")}' data-rule="id#{id}" class='layui-btn layui-btn-sm layui-btn-primary'>批量删除</a>
<!--{/if}-->
{/block}
{block name="content"}
<div class="think-box-shadow">
{include file='file/index_search'}
<table id="FileTable" data-url="{:sysuri('index')}" data-target-search="form.form-search"></table>
</div>
<script>
$(function () {
$('#FileTable').layTable({
even: true, height: 'full',
sort: {field: 'id', type: 'desc'},
cols: [[
{checkbox: true, fixed: true},
{field: 'id', title: 'ID', width: 80, align: 'center', sort: true},
{field: 'name', title: '文件名称', width: '12%', align: 'center'},
{field: 'hash', title: '文件哈希', width: '15%', align: 'center', templet: '<div><code>{{d.hash}}</code></div>'},
{
field: 'size', title: '文件大小', align: 'center', width: '8%', sort: true, templet: function (d) {
return formatSize(d.size)
}
},
{field: 'xext', title: '文件后缀', align: 'center', width: '8%', sort: true},
{
field: 'xurl', title: '查看文件', width: '8%', align: 'center', templet: function (d) {
if (typeof d.mime === 'string' && /^image\//.test(d.mime)) {
return laytpl('<div class="headimg headimg-no headimg-ss margin-0" data-tips-hover data-tips-image="{{d.xurl}}" style="background-image:url({{d.xurl}})"></div>').render(d)
} else {
return laytpl('<div><a target="_blank" href="{{d.xurl}}">查看</a></div>').render(d);
}
}
},
{
field: 'isfast', title: '上传方式', align: 'center', width: '8%', templet: function (d) {
return d.isfast ? '<b class="color-green">秒传</b>' : '<b class="color-blue">普通</b>';
}
},
{field: 'ctype', title: '存储方式', align: 'center', width: '10%'},
{field: 'create_at', title: '上传时间', align: 'center', width: '15%', sort: true},
{toolbar: '#toolbar', title: '操作面板', align: 'center', minWidth: 90, fixed: 'right'}
]]
});
});
function formatSize(size, fixed, units) {
var unit;
units = units || ['B', 'K', 'M', 'G', 'TB'];
while ((unit = units.shift()) && size > 1024) size = size / 1024;
return (unit === 'B' ? size : size.toFixed(fixed === undefined ? 2 : fixed)) + unit;
}
</script>
<script type="text/html" id="toolbar">
<!--{if auth("remove")}-->
<a class="layui-btn layui-btn-sm layui-btn-danger" data-action="{:url('remove')}" data-value="id#{{d.id}}"> </a>
<!--{/if}-->
</script>
{/block}

View File

@ -0,0 +1,58 @@
<fieldset>
<legend>条件搜索</legend>
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
<div class="layui-form-item layui-inline">
<label class="layui-form-label">文件名称</label>
<label class="layui-input-inline">
<input name="name" value="{$get.name|default=''}" placeholder="请输入文件名称" class="layui-input">
</label>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">文件哈希</label>
<label class="layui-input-inline">
<input name="hash" value="{$get.hash|default=''}" placeholder="请输入文件哈希" class="layui-input">
</label>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">文件后缀</label>
<div class="layui-input-inline">
<select name="xext" lay-search class="layui-select">
<option value=''>-- 全部后缀 --</option>
{foreach $xexts as $v}{if isset($get.xext) and $k eq $get.xext}
<option selected value="{$v}">{$v}</option>
{else}
<option value="{$v}">{$v}</option>
{/if}{/foreach}
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">存储方式</label>
<div class="layui-input-inline">
<select name="type" lay-search class="layui-select">
<option value=''>-- 全部方式 --</option>
{foreach $types as $k=>$v}{if isset($get.type) and $k eq $get.type}
<option selected value="{$k}">{$v}</option>
{else}
<option value="{$k}">{$v}</option>
{/if}{/foreach}
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">上传时间</label>
<div class="layui-input-inline">
<input data-date-range name="create_at" value="{$get.create_at|default=''}" placeholder="请选择上传时间" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-inline">
<button class="layui-btn layui-btn-primary"><i class="layui-icon">&#xe615;</i> 搜 索</button>
</div>
</form>
</fieldset>

View File

@ -37,7 +37,7 @@
{block name='script'}
<style>
#QueueTable + div tbody .layui-table-cell {
height: 44px;
height: 56px;
line-height: 22px;
}

View File

@ -58,7 +58,7 @@ class UserAgent extends Command
'path' => $path1, 'layer' => substr_count($path1, '-'),
'pid0' => $parant['id'], 'pid1' => $parant['id'], 'pid2' => $parant['pid1'],
]);
UserUpgradeService::instance()->upgrade($user['id'], true);
UserUpgradeService::upgrade($user['id'], true);
$this->setQueueMessage(1, 1, "更新指定用户[{$user['id']}]代理绑定成功!");
// 更新下级的代理关系

View File

@ -34,7 +34,7 @@ class UserUpgrade extends Command
[$total, $count] = [DataUser::mk()->count(), 0];
foreach (DataUser::mk()->field('id')->cursor() as $user) {
$this->queue->message($total, ++$count, "正在计算用户 [{$user['id']}] 的等级");
UserUpgradeService::instance()->upgrade($user['id']);
UserUpgradeService::upgrade($user['id']);
$this->queue->message($total, $count, "完成计算用户 [{$user['id']}] 的等级", 1);
}
$this->setQueueSuccess("此次共重新计算 {$total} 个用户等级。");

View File

@ -47,7 +47,7 @@ class News extends Controller
$query = DataNewsItem::mQuery()->like('name,mark')->equal('id,code');
$query->where(['deleted' => 0, 'status' => 1])->withoutField('sort,status,deleted');
$result = $query->order('sort desc,id desc')->page(true, false, false, 15);
NewsService::instance()->buildData($result['list'], input('uuid', 0));
NewsService::buildData($result['list'], input('uuid', 0));
$this->success('获取文章内容', $result);
}
@ -62,7 +62,7 @@ class News extends Controller
$map = $this->_vali(['code.require' => '文章不能为空!']);
$query = DataNewsXCollect::mQuery()->where(['type' => 4, 'status' => 2]);
$result = $query->where($map)->order('id desc')->page(true, false, false, 15);
NewsService::instance()->buildListByUidAndCode($result['list']);
NewsService::buildListByUidAndCode($result['list']);
$this->success('获取评论成功', $result);
}
}

View File

@ -140,7 +140,7 @@ class Center extends Auth
public function bindFrom()
{
$data = $this->_vali(['from.require' => '邀请人不能为空']);
[$state, $message] = UserUpgradeService::instance()->bindAgent($this->uuid, $data['from'], 0);
[$state, $message] = UserUpgradeService::bindAgent($this->uuid, $data['from'], 0);
if ($state) {
$this->success($message, UserAdminService::total($this->uuid));
} else {

View File

@ -27,7 +27,7 @@ class News extends Auth
'reply.require' => '评论不能为空!',
]);
if (DataNewsXCollect::mk()->insert($data) !== false) {
NewsService::instance()->syncNewsTotal($data['code']);
NewsService::syncNewsTotal($data['code']);
$this->success('添加评论成功!');
} else {
$this->error('添加评论失败!');
@ -44,7 +44,7 @@ class News extends Auth
{
$query = DataNewsXCollect::mQuery()->where(['uuid' => $this->uuid, 'type' => 4]);
$result = $query->whereIn('status', [1, 2])->order('id desc')->page(true, false);
NewsService::instance()->buildListByUidAndCode($result);
NewsService::buildListByUidAndCode($result);
$this->success('获取评论列表成功', $result);
}
@ -81,7 +81,7 @@ class News extends Auth
$this->success('您已收藏!');
}
if (DataNewsXCollect::mk()->insert($data) !== false) {
NewsService::instance()->syncNewsTotal($data['code']);
NewsService::syncNewsTotal($data['code']);
$this->success('收藏成功!');
} else {
$this->error('收藏失败!');
@ -99,7 +99,7 @@ class News extends Auth
'code.require' => '文章编号不能为空!',
]);
if (DataNewsXCollect::mk()->where($data)->delete() !== false) {
NewsService::instance()->syncNewsTotal($data['code']);
NewsService::syncNewsTotal($data['code']);
$this->success('取消收藏成功!');
} else {
$this->error('取消收藏失败!');
@ -117,7 +117,7 @@ class News extends Auth
$map = ['uuid' => $this->uuid, 'type' => 1];
$query = DataNewsXCollect::mQuery()->where($map);
$result = $query->order('id desc')->page(true, false, false, 15);
NewsService::instance()->buildListByUidAndCode($result['list']);
NewsService::buildListByUidAndCode($result['list']);
$this->success('获取收藏记录成功!', $result);
}
@ -136,7 +136,7 @@ class News extends Auth
$this->success('您已点赞!');
}
if (DataNewsXCollect::mk()->insert($data) !== false) {
NewsService::instance()->syncNewsTotal($data['code']);
NewsService::syncNewsTotal($data['code']);
$this->success('点赞成功!');
} else {
$this->error('点赞失败!');
@ -154,7 +154,7 @@ class News extends Auth
'code.require' => '文章编号不能为空!',
]);
if (DataNewsXCollect::mk()->where($data)->delete() !== false) {
NewsService::instance()->syncNewsTotal($data['code']);
NewsService::syncNewsTotal($data['code']);
$this->success('取消点赞成功!');
} else {
$this->error('取消点赞失败!');
@ -172,7 +172,7 @@ class News extends Auth
$query = DataNewsXCollect::mQuery();
$query->where(['uuid' => $this->uuid, 'type' => 2, 'status' => 2]);
$result = $query->order('id desc')->page(true, false, false, 15);
NewsService::instance()->buildListByUidAndCode($result['list']);
NewsService::buildListByUidAndCode($result['list']);
$this->success('获取点赞记录成功!', $result);
}
@ -203,7 +203,7 @@ class News extends Auth
$query = DataNewsXCollect::mQuery();
$query->where(['uuid' => $this->uuid, 'type' => 3, 'status' => 2]);
$result = $query->order('id desc')->page(true, false, false, 15);
NewsService::instance()->buildListByUidAndCode($result['list']);
NewsService::buildListByUidAndCode($result['list']);
$this->success('获取浏览历史成功!', $result);
}
}

View File

@ -48,7 +48,7 @@ class Order extends Auth
$map = ['uuid' => $this->uuid, 'deleted_status' => 0];
$query = ShopOrder::mQuery()->in('status')->equal('order_no');
$result = $query->where($map)->order('id desc')->page(true, false, false, 20);
if (count($result['list']) > 0) OrderService::instance()->buildData($result['list']);
if (count($result['list']) > 0) OrderService::buildData($result['list']);
$this->success('获取订单数据成功!', $result);
}
@ -108,7 +108,7 @@ class Order extends Auth
$allowPayments = $_allowPayments;
}
// 商品折扣处理
[$discountId, $discountRate] = OrderService::instance()->discount($goodsInfo['discount_id'], $this->user['vip_code']);
[$discountId, $discountRate] = OrderService::discount($goodsInfo['discount_id'], $this->user['vip_code']);
// 订单详情处理
$items[] = [
'uuid' => $order['uuid'],
@ -165,7 +165,7 @@ class Order extends Auth
// 优惠后的金额
$order['amount_discount'] = array_sum(array_column($items, 'discount_amount'));
// 订单随机免减
$order['amount_reduct'] = OrderService::instance()->getReduct();
$order['amount_reduct'] = OrderService::getReduct();
if ($order['amount_reduct'] > $order['amount_goods']) {
$order['amount_reduct'] = $order['amount_goods'];
}
@ -200,7 +200,7 @@ class Order extends Auth
public function discount()
{
$data = $this->_vali(['discount.require' => '折扣编号不能为空!']);
[, $rate] = OrderService::instance()->discount(intval($data['discount']), $this->user['vip_code']);
[, $rate] = OrderService::discount(intval($data['discount']), $this->user['vip_code']);
$this->success('获取用户折扣', ['rate' => $rate]);
}
@ -230,7 +230,7 @@ class Order extends Auth
// 根据地址计算运费
$map = ['status' => 1, 'deleted' => 0, 'order_no' => $data['order_no']];
$tCode = ShopOrderItem::mk()->where($map)->column('truck_code');
[$amount, , , $remark] = ExpressService::instance()->amount($tCode, $addr['province'], $addr['city'], $tCount);
[$amount, , , $remark] = ExpressService::amount($tCode, $addr['province'], $addr['city'], $tCount);
$this->success('计算运费成功', ['amount' => $amount, 'remark' => $remark]);
}
@ -263,7 +263,7 @@ class Order extends Auth
$map2 = ['status' => 1, 'deleted' => 0, 'order_no' => $data['order_no']];
$tCount = ShopOrderItem::mk()->where($map1)->sum('truck_number');
$tCodes = ShopOrderItem::mk()->where($map2)->column('truck_code');
[$amount, $tCount, $tCode, $remark] = ExpressService::instance()->amount($tCodes, $addr['province'], $addr['city'], $tCount);
[$amount, $tCount, $tCode, $remark] = ExpressService::amount($tCodes, $addr['province'], $addr['city'], $tCount);
// 创建订单发货信息
$express = [

View File

@ -31,9 +31,9 @@ class Transfer extends Auth
'amount.require' => '提现金额不能为空!',
'remark.default' => '用户提交提现申请!',
]);
$state = UserTransferService::instance()->config('status');
$state = UserTransferService::config('status');
if (empty($state)) $this->error('提现还没有开启!');
$transfers = UserTransferService::instance()->config('transfer');
$transfers = UserTransferService::config('transfer');
if (empty($transfers[$data['type']]['state'])) $this->error('提现方式已停用!');
// 提现数据补充
$data['uuid'] = $this->uuid;
@ -50,7 +50,7 @@ class Transfer extends Auth
$data['audit_datetime'] = date('Y-m-d H:i:s');
}
// 扣除手续费
$chargeRate = floatval(UserTransferService::instance()->config('charge'));
$chargeRate = floatval(UserTransferService::config('charge'));
$data['charge_rate'] = $chargeRate;
$data['charge_amount'] = $chargeRate * $data['amount'] / 100;
// 检查可提现余额

View File

@ -96,7 +96,7 @@ class Company extends Controller
public function sync()
{
try {
$result = ExpressService::instance()->company();
$result = ExpressService::company();
if (empty($result['code'])) $this->error($result['info']);
foreach ($result['data'] as $vo) BasePostageCompany::mUpdate([
'name' => $vo['title'],

View File

@ -43,7 +43,7 @@ class Template extends Controller
{
if ($this->request->isGet()) {
$this->title = '配送区域管理';
$this->citys = ExpressService::instance()->region(3, null);
$this->citys = ExpressService::region(3, null);
$this->fetch('form_region');
} else {
$data = $this->_vali(['nos.default' => '', 'oks.default' => '']);
@ -83,7 +83,7 @@ class Template extends Controller
$data['code'] = CodeExtend::uniqidDate(12, 'T');
}
if ($this->request->isGet()) {
$this->citys = ExpressService::instance()->region(2, 1);
$this->citys = ExpressService::region(2, 1);
}
}

View File

@ -42,7 +42,7 @@ class Item extends Controller
*/
protected function _page_filter(array &$data)
{
NewsService::instance()->buildData($data);
NewsService::buildData($data);
}
/**

View File

@ -138,7 +138,7 @@ class Goods extends Controller
// 其他表单数据
$this->marks = ShopGoodsMark::items();
$this->cates = ShopGoodsCate::treeTable(true);
$this->trucks = ExpressService::instance()->templates();
$this->trucks = ExpressService::templates();
$this->upgrades = BaseUserUpgrade::items();
$this->payments = BaseUserPayment::mk()->where(['status' => 1, 'deleted' => 0])->order('sort desc,id desc')->column('type,code,name', 'code');
$this->discounts = BaseUserDiscount::mk()->where(['status' => 1, 'deleted' => 0])->order('sort desc,id desc')->column('id,name,items', 'id');

View File

@ -71,7 +71,7 @@ class Send extends Controller
*/
protected function _index_page_filter(array &$data)
{
OrderService::instance()->buildData($data, false);
OrderService::buildData($data, false);
$orders = array_unique(array_column($data, 'order_no'));
$orderList = ShopOrder::mk()->whereIn('order_no', $orders)->column('*', 'order_no');
foreach ($data as &$vo) $vo['order'] = $orderList[$vo['order_no']] ?? [];
@ -149,7 +149,7 @@ class Send extends Controller
{
try {
$data = $this->_vali(['code.require' => '快递不能为空!', 'number.require' => '单号不能为空!']);
$this->result = ExpressService::instance()->query($data['code'], $data['number']);
$this->result = ExpressService::query($data['code'], $data['number']);
if (empty($this->result['code'])) $this->error($this->result['info']);
$this->fetch('truck_query');
} catch (HttpResponseException $exception) {

View File

@ -105,7 +105,7 @@ class Admin extends Controller
$map = $this->_vali(['id.require' => '用户ID不能为空']);
$user = DataUser::mk()->where($map)->find();
if (empty($user) || empty($user['pid0'])) $this->error('用户不符合操作要求!');
[$status, $message] = UserUpgradeService::instance()->bindAgent($user['id'], $user['pid0']);
[$status, $message] = UserUpgradeService::bindAgent($user['id'], $user['pid0']);
$status && sysoplog('前端用户管理', "修改用户[{$map['id']}]的代理为永久状态");
empty($status) ? $this->error($message) : $this->success($message);
}
@ -125,7 +125,7 @@ class Admin extends Controller
// 修改指定用户代理数据
$user->save(['pid0' => 0, 'pid1' => 0, 'pid2' => 0, 'pids' => 1, 'path' => '-', 'layer' => 1]);
// 刷新用户等级及上级等级
UserUpgradeService::instance()->upgrade($user['id'], true);
UserUpgradeService::upgrade($user['id'], true);
sysoplog('前端用户管理', "设置用户[{$map['id']}]为总部用户");
$this->success('设为总部用户成功!');
}
@ -156,7 +156,7 @@ class Admin extends Controller
$query->like('phone,username|nickname#username')->whereRaw('vip_code>0')->equal('status,vip_code')->dateBetween('create_at')->page();
} else {
$data = $this->_vali(['pid.require' => '待绑定代理不能为空!', 'uuid.require' => '待操作用户不能为空!']);
[$status, $message] = UserUpgradeService::instance()->bindAgent($data['uuid'], $data['pid'], 2);
[$status, $message] = UserUpgradeService::bindAgent($data['uuid'], $data['pid'], 2);
$status && sysoplog('前端用户管理', "修改用户[{$data['uuid']}]的代理为用户[{$data['pid']}]");
empty($status) ? $this->error($message) : $this->success($message);
}

View File

@ -88,7 +88,7 @@ class Balance extends Controller
$this->upgrades = BaseUserUpgrade::items();
}
if ($this->request->isPost()) {
$data['create_by'] = AdminService::instance()->getUserId();
$data['create_by'] = AdminService::getUserId();
if (empty(floatval($data['amount'])) && empty($data['upgrade'])) {
$this->error('金额为零并且没有升级行为!');
}
@ -105,7 +105,7 @@ class Balance extends Controller
{
if ($state && isset($data['uuid'])) {
UserBalanceService::amount($data['uuid']);
UserUpgradeService::instance()->upgrade($data['uuid']);
UserUpgradeService::upgrade($data['uuid']);
}
}
@ -129,7 +129,7 @@ class Balance extends Controller
$map = [['id', 'in', str2arr(input('id', ''))]];
foreach (DataUserBalance::mk()->where($map)->cursor() as $vo) {
UserBalanceService::amount($vo['uuid']);
UserUpgradeService::instance()->upgrade($vo['uuid']);
UserUpgradeService::upgrade($vo['uuid']);
}
}
}

View File

@ -56,7 +56,7 @@ class Rebate extends Controller
$userItem = DataUser::mk()->whereIn('id', array_unique($uids))->select();
$goodsItem = ShopOrderItem::mk()->whereIn('order_no', array_unique(array_column($data, 'order_no')))->select();
foreach ($data as &$vo) {
$vo['type'] = RebateService::instance()->name($vo['type']);
$vo['type'] = RebateService::name($vo['type']);
[$vo['user'], $vo['agent'], $vo['list']] = [[], [], []];
foreach ($userItem as $user) {
if ($user['id'] === $vo['uuid']) $vo['agent'] = $user;

View File

@ -83,7 +83,7 @@ class Transfer extends Controller
public function index()
{
$this->title = '用户提现管理';
$this->transfer = UserTransferService::instance()->amount(0);
$this->transfer = UserTransferService::amount(0);
// 创建查询对象
$query = DataUserTransfer::mQuery()->order('id desc');
// 用户条件搜索
@ -157,7 +157,7 @@ class Transfer extends Controller
$data['trade_no'] = CodeExtend::uniqidDate(20);
$data['trade_time'] = date('Y-m-d H:i:s');
$data['change_time'] = date('Y-m-d H:i:s');
$data['change_desc'] = ($data['remark'] ?: '线下打款成功') . ' By ' . AdminService::instance()->getUserName();
$data['change_desc'] = ($data['remark'] ?: '线下打款成功') . ' By ' . AdminService::getUserName();
}
if (DataUserTransfer::mk()->strict(false)->where($map)->update($data) !== false) {
$this->success('操作成功');

View File

@ -57,7 +57,7 @@ class NewsService extends Service
* @param integer $uuid 用户UID
* @return array
*/
public function buildData(array &$list, int $uuid = 0): array
public static function buildData(array &$list, int $uuid = 0): array
{
if (count($list) > 0) {
[$code2, $code1] = [[], []];

View File

@ -63,7 +63,7 @@ class OrderService extends Service
// 尝试绑定代理用户
if (empty($user['pids']) && ($order['puid1'] > 0 || $user['pid1'] > 0)) {
$puid1 = $order['puid1'] > 0 ? $order['puid1'] : $user['pid0'];
UserUpgradeService::instance()->bindAgent($user['id'], $puid1);
UserUpgradeService::bindAgent($user['id'], $puid1);
}
// 重置用户信息并绑定订单
$user = DataUser::mk()->where(['id' => $order['uuid']])->find();
@ -73,7 +73,7 @@ class OrderService extends Service
]);
}
// 重新计算用户等级
UserUpgradeService::instance()->upgrade($user['id'], true, $orderNo);
UserUpgradeService::upgrade($user['id'], true, $orderNo);
return [$user, $order, $entry];
}

View File

@ -50,7 +50,7 @@ class UserRebateService extends Service
if (empty($order)) return [0, '需处理的订单状态异常!'];
$map = [['status', '=', 0], ['order_no', 'like', "{$orderNo}%"]];
DataUserRebate::mk()->where($map)->update(['status' => 1]);
if (UserUpgradeService::instance()->upgrade($order['uuid'])) {
if (UserUpgradeService::upgrade($order['uuid'])) {
return [1, '重新计算用户金额成功!'];
} else {
return [0, '重新计算用户金额失败!'];

View File

@ -7,6 +7,7 @@ use app\data\model\DataUser;
use app\data\model\DataUserBalance;
use app\data\model\ShopOrder;
use app\data\model\ShopOrderItem;
use think\admin\Library;
use think\admin\Service;
/**
@ -27,7 +28,7 @@ class UserUpgradeService extends Service
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function bindAgent(int $uuid, int $pid0 = 0, int $mode = 1): array
public static function bindAgent(int $uuid, int $pid0 = 0, int $mode = 1): array
{
$user = DataUser::mk()->where(['id' => $uuid])->find();
if (empty($user)) return [0, '查询用户资料失败'];
@ -41,7 +42,7 @@ class UserUpgradeService extends Service
if (empty($agent['vip_code'])) return [0, '代理无推荐资格'];
if (strpos($agent['path'], "-{$uuid}-") !== false) return [0, '不能绑定下属'];
try {
$this->app->db->transaction(function () use ($user, $agent, $mode) {
Library::$sapp->db->transaction(function () use ($user, $agent, $mode) {
// 更新用户代理
$path1 = rtrim($agent['path'] ?: '-', '-') . "-{$agent['id']}-";
$user->save(['pid0' => $agent['id'], 'pid1' => $agent['id'], 'pid2' => $agent['pid1'], 'pids' => $mode > 0 ? 1 : 0, 'path' => $path1, 'layer' => substr_count($path1, '-')]);
@ -54,7 +55,7 @@ class UserUpgradeService extends Service
}
}
});
$this->upgrade($user['id']);
static::upgrade($user['id']);
return [1, '绑定代理成功'];
} catch (\Exception $exception) {
return [0, "绑定代理失败, {$exception->getMessage()}"];
@ -71,7 +72,7 @@ class UserUpgradeService extends Service
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function upgrade(int $uuid, bool $parent = true, ?string $orderNo = null): bool
public static function upgrade(int $uuid, bool $parent = true, ?string $orderNo = null): bool
{
$user = DataUser::mk()->where(['id' => $uuid])->find();
if (empty($user)) return true;
@ -133,9 +134,9 @@ class UserUpgradeService extends Service
if ($data['vip_code'] !== $user['vip_code']) $data['vip_datetime'] = date('Y-m-d H:i:s');
DataUser::mk()->where(['id' => $uuid])->update($data);
// 用户升级事件
if ($user['vip_code'] < $vipCode) $this->app->event->trigger('UserUpgradeLevel', [
if ($user['vip_code'] < $vipCode) Library::$sapp->event->trigger('UserUpgradeLevel', [
'uuid' => $user['id'], 'order_no' => $orderNo, 'vip_code_old' => $user['vip_code'], 'vip_code_new' => $vipCode,
]);
return !($parent && $user['pid1'] > 0) || $this->upgrade($user['pid1'], false);
return !($parent && $user['pid1'] > 0) || static::upgrade($user['pid1'], false);
}
}

View File

@ -89,17 +89,17 @@ class Auto extends Command
$result = $this->sendMessage('text', ['content' => $data['content']]);
}
if ($type === 'voice' && !empty($data['voice_url'])) {
if ($mediaId = MediaService::instance()->upload($data['voice_url'], 'voice')) {
if ($mediaId = MediaService::upload($data['voice_url'], 'voice')) {
$result = $this->sendMessage('voice', ['media_id' => $mediaId]);
}
}
if ($type === 'image' && !empty($data['image_url'])) {
if ($mediaId = MediaService::instance()->upload($data['image_url'], 'image')) {
if ($mediaId = MediaService::upload($data['image_url'], 'image')) {
$result = $this->sendMessage('image', ['media_id' => $mediaId]);
}
}
if ($type === 'news') {
[$item, $news] = [MediaService::instance()->news($data['news_id']), []];
[$item, $news] = [MediaService::news($data['news_id']), []];
if (isset($item['articles']) && is_array($item['articles'])) {
$host = sysconf('base.site_host') ?: true;
foreach ($item['articles'] as $vo) if (empty($news)) $news[] = [
@ -110,7 +110,7 @@ class Auto extends Command
}
}
if ($type === 'music' && !empty($data['music_url']) && !empty($data['music_title']) && !empty($data['music_desc'])) {
$mediaId = $data['music_image'] ? MediaService::instance()->upload($data['music_image'], 'image') : '';
$mediaId = $data['music_image'] ? MediaService::upload($data['music_image'], 'image') : '';
$result = $this->sendMessage('music', [
'hqmusicurl' => $data['music_url'], 'musicurl' => $data['music_url'],
'description' => $data['music_desc'], 'title' => $data['music_title'], 'thumb_media_id' => $mediaId,
@ -118,7 +118,7 @@ class Auto extends Command
}
if ($type === 'video' && !empty($data['video_url']) && !empty($data['video_desc']) && !empty($data['video_title'])) {
$video = ['title' => $data['video_title'], 'introduction' => $data['video_desc']];
if ($mediaId = MediaService::instance()->upload($data['video_url'], 'video', $video)) {
if ($mediaId = MediaService::upload($data['video_url'], 'video', $video)) {
$result = $this->sendMessage('video', ['media_id' => $mediaId, 'title' => $data['video_title'], 'description' => $data['video_desc']]);
}
}

View File

@ -66,7 +66,7 @@ class Fans extends Command
*/
protected function _list(string $next = '', int $done = 0): string
{
$appid = WechatService::instance()->getAppid();
$appid = WechatService::getAppid();
$this->output->comment('开始获取微信用户数据');
while (is_string($next)) {
$result = WechatService::WeChatUser()->getUserList($next);
@ -76,7 +76,7 @@ class Fans extends Command
if (is_array($info) && !empty($info['user_info_list'])) {
foreach ($info['user_info_list'] as $user) if (isset($user['nickname'])) {
$this->queue->message($result['total'], ++$done, "-> {$user['openid']} {$user['nickname']}");
FansService::instance()->set($user, $appid);
FansService::set($user, $appid);
}
}
}
@ -137,7 +137,7 @@ class Fans extends Command
*/
public function _tags(int $done = 0): string
{
$appid = WechatService::instance()->getAppid();
$appid = WechatService::getAppid();
$this->output->comment('开始获取微信用户标签数据');
if (is_array($list = WechatService::WeChatTags()->getTags()) && !empty($list['tags'])) {
$count = count($list['tags']);

View File

@ -43,7 +43,7 @@ class Fans extends Controller
WechatFans::mQuery()->layTable(function () {
$this->title = '微信用户管理';
}, function (QueryHelper $query) {
$query->where(['appid' => WechatService::instance()->getAppid()]);
$query->where(['appid' => WechatService::getAppid()]);
$query->like('nickname')->equal('subscribe,is_black')->dateBetween('subscribe_at');
});
}

View File

@ -53,7 +53,7 @@ class News extends Controller
protected function _page_filter(array &$data)
{
foreach ($data as &$vo) {
$vo = MediaService::instance()->news($vo['id']);
$vo = MediaService::news($vo['id']);
}
}
@ -77,7 +77,7 @@ class News extends Controller
$this->fetch('form');
} else {
$update = [
'create_by' => AdminService::instance()->getUserId(),
'create_by' => AdminService::getUserId(),
'article_id' => $this->_buildArticle($this->request->post('data', [])),
];
if (WechatNews::mk()->insert($update) !== false) {
@ -101,7 +101,7 @@ class News extends Controller
if (empty($this->id)) $this->error('参数错误,请稍候再试!');
if ($this->request->isGet()) {
if ($this->request->get('output') === 'json') {
$this->success('获取数据成功!', MediaService::instance()->news($this->id));
$this->success('获取数据成功!', MediaService::news($this->id));
} else {
$this->title = '编辑图文';
$this->fetch('form');

View File

@ -50,12 +50,12 @@ class Js extends Controller
{
$mode = $this->request->get('mode', 1);
$source = $this->request->server('http_referer') ?: $this->request->url(true);
$userinfo = WechatService::instance()->getWebOauthInfo($source, $mode, false);
$userinfo = WechatService::getWebOauthInfo($source, $mode, false);
if (empty($userinfo['openid'])) {
$content = 'alert("Wechat webOauth failed.")';
} else {
$this->openid = $userinfo['openid'];
$this->params = json_encode(WechatService::instance()->getWebJssdkSign($source));
$this->params = json_encode(WechatService::getWebJssdkSign($source));
$this->fansinfo = json_encode($userinfo['fansinfo'] ?? [], JSON_UNESCAPED_UNICODE);
// 生成数据授权令牌
$this->token = uniqid('oauth') . rand(10000, 99999);
@ -78,7 +78,7 @@ class Js extends Controller
public function sdk()
{
$data = $this->_vali(['url.require' => '签名地址不能为空!']);
$this->success('获取签名参数', WechatService::instance()->getWebJssdkSign($data['url']));
$this->success('获取签名参数', WechatService::getWebJssdkSign($data['url']));
}
/**

View File

@ -72,7 +72,7 @@ class Login extends Controller
$this->mode = input('mode', '0');
if (stripos($this->code, $this->prefix) === 0) {
$this->url = $this->request->url(true);
$this->fans = WechatService::instance()->getWebOauthInfo($this->url, $this->mode);
$this->fans = WechatService::getWebOauthInfo($this->url, $this->mode);
if (is_array($this->fans) && isset($this->fans['openid'])) {
$this->fans['token'] = md5(uniqid('t', true) . rand(10000, 99999));
$this->app->cache->set("wxlogin{$this->code}", $this->fans, $this->expire);

View File

@ -93,7 +93,7 @@ class Push extends Controller
public function index(): string
{
try {
if (WechatService::instance()->getType() === 'thr') {
if (WechatService::getType() === 'thr') {
$this->forceJson = true; // 直接返回JSON数据到SERVICE
$this->forceCustom = false; // 直接使用客服消息模式推送
$this->appid = $this->request->post('appid', '', null);
@ -106,7 +106,7 @@ class Push extends Controller
} else {
$this->forceJson = false; // 直接返回JSON对象数据
$this->forceCustom = false; // 直接使用客服消息推送
$this->appid = WechatService::instance()->getAppid();
$this->appid = WechatService::getAppid();
$this->wechat = WechatService::WeChatReceive();
$this->openid = $this->wechat->getOpenid();
$this->encrypt = $this->wechat->isEncrypt();
@ -215,13 +215,13 @@ class Push extends Controller
case 'customservice':
return $this->_sendMessage('customservice', ['content' => $data['content']], false);
case 'voice':
if (empty($data['voice_url']) || !($mediaId = MediaService::instance()->upload($data['voice_url'], 'voice'))) return false;
if (empty($data['voice_url']) || !($mediaId = MediaService::upload($data['voice_url'], 'voice'))) return false;
return $this->_sendMessage('voice', ['media_id' => $mediaId], $custom);
case 'image':
if (empty($data['image_url']) || !($mediaId = MediaService::instance()->upload($data['image_url'], 'image'))) return false;
if (empty($data['image_url']) || !($mediaId = MediaService::upload($data['image_url'], 'image'))) return false;
return $this->_sendMessage('image', ['media_id' => $mediaId], $custom);
case 'news':
[$news, $articles] = [MediaService::instance()->news($data['news_id']), []];
[$news, $articles] = [MediaService::news($data['news_id']), []];
if (empty($news['articles'])) return false;
foreach ($news['articles'] as $vo) $articles[] = [
'url' => url("@wechat/api.view/item/id/{$vo['id']}", [], false, true)->build(),
@ -230,7 +230,7 @@ class Push extends Controller
return $this->_sendMessage('news', ['articles' => $articles], $custom);
case 'music':
if (empty($data['music_url']) || empty($data['music_title']) || empty($data['music_desc'])) return false;
$mediaId = $data['music_image'] ? MediaService::instance()->upload($data['music_image'], 'image') : '';
$mediaId = $data['music_image'] ? MediaService::upload($data['music_image'], 'image') : '';
return $this->_sendMessage('music', [
'hqmusicurl' => $data['music_url'], 'musicurl' => $data['music_url'],
'description' => $data['music_desc'], 'title' => $data['music_title'], 'thumb_media_id' => $mediaId,
@ -238,7 +238,7 @@ class Push extends Controller
case 'video':
if (empty($data['video_url']) || empty($data['video_desc']) || empty($data['video_title'])) return false;
$video = ['title' => $data['video_title'], 'introduction' => $data['video_desc']];
if (!($mediaId = MediaService::instance()->upload($data['video_url'], 'video', $video))) return false;
if (!($mediaId = MediaService::upload($data['video_url'], 'video', $video))) return false;
return $this->_sendMessage('video', ['media_id' => $mediaId, 'title' => $data['video_title'], 'description' => $data['video_desc']], $custom);
default:
return false;
@ -309,13 +309,13 @@ class Push extends Controller
if ($state) {
try {
$user = WechatService::WeChatUser()->getUserInfo($this->openid);
return FansService::instance()->set(array_merge($user, ['subscribe' => 1, 'appid' => $this->appid]));
return FansService::set(array_merge($user, ['subscribe' => 1, 'appid' => $this->appid]));
} catch (\Exception $exception) {
$this->app->log->error(__METHOD__ . " {$this->openid} get userinfo faild. {$exception->getMessage()}");
return false;
}
} else {
return FansService::instance()->set(['subscribe' => 0, 'openid' => $this->openid, 'appid' => $this->appid]);
return FansService::set(['subscribe' => 0, 'openid' => $this->openid, 'appid' => $this->appid]);
}
}

View File

@ -115,7 +115,7 @@ class Test extends Controller
public function oauth()
{
$this->url = $this->request->url(true);
$this->fans = WechatService::instance()->getWebOauthInfo($this->url, 1);
$this->fans = WechatService::getWebOauthInfo($this->url, 1);
$this->fetch();
}
@ -130,7 +130,7 @@ class Test extends Controller
*/
public function jssdk()
{
$this->options = WechatService::instance()->getWebJssdkSign();
$this->options = WechatService::getWebJssdkSign();
$this->fetch();
}
@ -188,7 +188,7 @@ class Test extends Controller
{
$this->url = $this->request->url(true);
$this->pay = WechatService::WePayOrder();
$user = WechatService::instance()->getWebOauthInfo($this->url);
$user = WechatService::getWebOauthInfo($this->url);
if (empty($user['openid'])) return '<h3>网页授权获取OPENID失败</h3>';
// 生成预支付码
$result = $this->pay->create([
@ -203,7 +203,7 @@ class Test extends Controller
// 数据参数格式化
$resultJson = var_export($result, true);
$optionJson = json_encode($this->pay->jsapiParams($result['prepay_id']), JSON_UNESCAPED_UNICODE);
$configJson = json_encode(WechatService::instance()->getWebJssdkSign(), JSON_UNESCAPED_UNICODE);
$configJson = json_encode(WechatService::getWebJssdkSign(), JSON_UNESCAPED_UNICODE);
return <<<HTML
<pre>
当前用户OPENID: {$user['openid']}

View File

@ -38,7 +38,7 @@ class View extends Controller
public function news($id = 0)
{
$this->id = $id ?: input('id', 0);
$this->news = MediaService::instance()->news($this->id);
$this->news = MediaService::news($this->id);
$this->fetch();
}

View File

@ -35,11 +35,11 @@ class AutoService extends Service
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function register(string $openid)
public static function register(string $openid)
{
foreach (WechatAuto::mk()->where(['status' => 1])->order('time asc')->cursor() as $vo) {
[$name, $time] = ["推送客服消息 {$vo['code']}#{$openid}", $this->parseTimeString($vo['time'])];
QueueService::instance()->register($name, "xadmin:fansmsg {$openid} {$vo['code']}", $time, []);
[$name, $time] = ["推送客服消息 {$vo['code']}#{$openid}", static::parseTimeString($vo['time'])];
QueueService::register($name, "xadmin:fansmsg {$openid} {$vo['code']}", $time, []);
}
}
@ -48,7 +48,7 @@ class AutoService extends Service
* @param string $time
* @return int
*/
private function parseTimeString(string $time): int
private static function parseTimeString(string $time): int
{
if (preg_match('|^.*?(\d{2}).*?(\d{2}).*?(\d{2}).*?$|', $time, $vars)) {
return intval($vars[1]) * 3600 * intval($vars[2]) * 60 + intval($vars[3]);

View File

@ -17,6 +17,7 @@
namespace app\wechat\service;
use app\wechat\model\WechatFans;
use think\admin\Library;
use think\admin\Service;
/**
@ -33,7 +34,7 @@ class FansService extends Service
* @param string $appid 微信APPID
* @return boolean
*/
public function set(array $user, string $appid = ''): bool
public static function set(array $user, string $appid = ''): bool
{
if (isset($user['subscribe_time'])) {
$user['subscribe_at'] = date('Y-m-d H:i:s', $user['subscribe_time']);
@ -44,7 +45,7 @@ class FansService extends Service
if ($appid !== '') $user['appid'] = $appid;
unset($user['privilege'], $user['groupid']);
foreach ($user as $k => $v) if ($v === '') unset($user[$k]);
$this->app->event->trigger('WechatFansUpdate', $user);
Library::$sapp->event->trigger('WechatFansUpdate', $user);
return !!WechatFans::mUpdate($user, 'openid');
}
@ -53,7 +54,7 @@ class FansService extends Service
* @param string $openid
* @return array
*/
public function get(string $openid): array
public static function get(string $openid): array
{
return WechatFans::mk()->where(['openid' => $openid])->findOrEmpty()->toArray();
}

View File

@ -39,7 +39,7 @@ class MediaService extends Service
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function news($id, array $map = []): array
public static function news($id, array $map = []): array
{
// 文章主体数据
$map1 = ['id' => $id, 'is_deleted' => 0];
@ -68,12 +68,12 @@ class MediaService extends Service
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function upload(string $url, string $type = 'image', array $video = []): string
public static function upload(string $url, string $type = 'image', array $video = []): string
{
$map = ['md5' => md5($url), 'appid' => WechatService::instance()->getAppid()];
$map = ['md5' => md5($url), 'appid' => WechatService::getAppid()];
if (($mediaId = WechatMedia::mk()->where($map)->value('media_id'))) return $mediaId;
$result = WechatService::WeChatMedia()->addMaterial(self::buildCurlFile($url), $type, $video);
data_save(WechatMedia::class, [
WechatMedia::mUpdate([
'local_url' => $url, 'md5' => $map['md5'], 'type' => $type, 'appid' => $map['appid'],
'media_url' => $result['url'] ?? '', 'media_id' => $result['media_id'],
], 'type', $map);
@ -86,7 +86,7 @@ class MediaService extends Service
* @return MyCurlFile
* @throws \WeChat\Exceptions\LocalCacheException
*/
private function buildCurlFile(string $local): MyCurlFile
private static function buildCurlFile(string $local): MyCurlFile
{
if (file_exists($local)) {
return new MyCurlFile($local);

View File

@ -18,6 +18,7 @@ namespace app\wechat\service;
use think\admin\Exception;
use think\admin\extend\JsonRpcClient;
use think\admin\Library;
use think\admin\Service;
use think\admin\storage\LocalStorage;
use think\exception\HttpResponseException;
@ -104,7 +105,7 @@ class WechatService extends Service
}
if (sysconf('wechat.type') === 'api' || $type === 'WePay') {
if (class_exists($class)) {
return new $class(static::instance()->getConfig());
return new $class(static::getConfig());
} else {
throw new Exception("抱歉,接口模式无法实例 {$class} 对象!");
}
@ -142,9 +143,9 @@ class WechatService extends Service
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getAppid(): string
public static function getAppid(): string
{
if ($this->getType() === 'api') {
if (static::getType() === 'api') {
return sysconf('wechat.appid');
} else {
return sysconf('wechat.thr_appid');
@ -159,7 +160,7 @@ class WechatService extends Service
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getType(): string
public static function getType(): string
{
$type = strtolower(sysconf('wechat.type'));
if (in_array($type, ['api', 'thr'])) return $type;
@ -174,16 +175,16 @@ class WechatService extends Service
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getConfig(): array
public static function getConfig(): array
{
$options = [
'appid' => $this->getAppid(),
'appid' => static::getAppid(),
'token' => sysconf('wechat.token'),
'appsecret' => sysconf('wechat.appsecret'),
'encodingaeskey' => sysconf('wechat.encodingaeskey'),
'mch_id' => sysconf('wechat.mch_id'),
'mch_key' => sysconf('wechat.mch_key'),
'cache_path' => $this->app->getRuntimePath() . 'wechat',
'cache_path' => Library::$sapp->getRuntimePath() . 'wechat',
];
$local = LocalStorage::instance();
switch (strtolower(sysconf('wechat.mch_ssl_type'))) {
@ -211,16 +212,16 @@ class WechatService extends Service
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getWebOauthInfo(string $source, int $isfull = 0, bool $redirect = true): array
public static function getWebOauthInfo(string $source, int $isfull = 0, bool $redirect = true): array
{
$appid = $this->getAppid();
$openid = $this->app->session->get("{$appid}_openid");
$userinfo = $this->app->session->get("{$appid}_fansinfo");
$appid = static::getAppid();
$openid = Library::$sapp->session->get("{$appid}_openid");
$userinfo = Library::$sapp->session->get("{$appid}_fansinfo");
if ((empty($isfull) && !empty($openid)) || (!empty($isfull) && !empty($openid) && !empty($userinfo))) {
empty($userinfo) || FansService::instance()->set($userinfo, $appid);
empty($userinfo) || FansService::set($userinfo, $appid);
return ['openid' => $openid, 'fansinfo' => $userinfo];
}
if ($this->getType() === 'api') {
if (static::getType() === 'api') {
// 解析 GET 参数
parse_str(parse_url($source, PHP_URL_QUERY), $params);
$getVars = [
@ -235,11 +236,11 @@ class WechatService extends Service
$oauthurl = $wechat->getOauthRedirect($location, $appid, $isfull ? 'snsapi_userinfo' : 'snsapi_base');
throw new HttpResponseException($redirect ? redirect($oauthurl, 301) : response("location.href='{$oauthurl}'"));
} elseif (($token = $wechat->getOauthAccessToken($getVars['code'])) && isset($token['openid'])) {
$this->app->session->set("{$appid}_openid", $openid = $token['openid']);
Library::$sapp->session->set("{$appid}_openid", $openid = $token['openid']);
if ($isfull && isset($token['access_token'])) {
$userinfo = $wechat->getUserInfo($token['access_token'], $openid);
$this->app->session->set("{$appid}_fansinfo", $userinfo);
empty($userinfo) || FansService::instance()->set($userinfo, $appid);
Library::$sapp->session->set("{$appid}_fansinfo", $userinfo);
empty($userinfo) || FansService::set($userinfo, $appid);
}
}
if ($getVars['rcode']) {
@ -251,11 +252,11 @@ class WechatService extends Service
throw new Exception('Query params [rcode] not find.');
}
} else {
$result = static::ThinkServiceConfig()->oauth($this->app->session->getId(), $source, $isfull);
$this->app->session->set("{$appid}_openid", $openid = $result['openid']);
$this->app->session->set("{$appid}_fansinfo", $userinfo = $result['fans']);
$result = static::ThinkServiceConfig()->oauth(Library::$sapp->session->getId(), $source, $isfull);
Library::$sapp->session->set("{$appid}_openid", $openid = $result['openid']);
Library::$sapp->session->set("{$appid}_fansinfo", $userinfo = $result['fans']);
if ((empty($isfull) && !empty($openid)) || (!empty($isfull) && !empty($openid) && !empty($userinfo))) {
empty($userinfo) || FansService::instance()->set($userinfo, $appid);
empty($userinfo) || FansService::set($userinfo, $appid);
return ['openid' => $openid, 'fansinfo' => $userinfo];
}
if ($redirect) {
@ -277,10 +278,10 @@ class WechatService extends Service
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getWebJssdkSign(?string $location = null): array
public static function getWebJssdkSign(?string $location = null): array
{
$location = $location ?: $this->app->request->url(true);
if ($this->getType() === 'api') {
$location = $location ?: Library::$sapp->request->url(true);
if (static::getType() === 'api') {
return static::WeChatScript()->getJsSign($location);
} else {
return static::ThinkServiceConfig()->jsSign($location);

View File

@ -25,6 +25,6 @@ if (app()->request->isCli()) {
});
} else {
app()->event->listen('WechatFansSubscribe', function ($openid) {
AutoService::instance()->register($openid);
AutoService::register($openid);
});
}

View File

@ -50,10 +50,39 @@ window.jQuery = window.$ = window.jQuery || window.$ || layui.$;
/*! 配置 require 参数 */
require.config({
baseUrl: baseRoot, waitSeconds: 60, map: {'*': {css: baseRoot + 'plugs/require/css.js'}}, paths: {
'vue': ['plugs/vue/vue.min'], 'md5': ['plugs/jquery/md5.min'], 'json': ['plugs/jquery/json.min'], 'xlsx': ['plugs/jquery/xlsx.min'], 'excel': ['plugs/jquery/excel.xlsx'], 'base64': ['plugs/jquery/base64.min'], 'upload': [tapiRoot + '/api.upload/index?'], 'notify': ['plugs/notify/notify.min'], 'angular': ['plugs/angular/angular.min'], 'cropper': ['plugs/cropper/cropper.min'], 'echarts': ['plugs/echarts/echarts.min'], 'ckeditor4': ['plugs/ckeditor4/ckeditor'], 'ckeditor5': ['plugs/ckeditor5/ckeditor'], 'websocket': ['plugs/socket/websocket'], 'pcasunzips': ['plugs/jquery/pcasunzips'], 'sortablejs': ['plugs/sortable/sortable.min'], 'vue.sortable': ['plugs/sortable/vue.draggable.min'], 'jquery.ztree': ['plugs/ztree/ztree.all.min'], 'jquery.masonry': ['plugs/jquery/masonry.min'], 'jquery.cropper': ['plugs/cropper/cropper.min'], 'jquery.autocompleter': ['plugs/jquery/autocompleter.min'],
baseUrl: baseRoot, waitSeconds: 60,
map: {'*': {css: baseRoot + 'plugs/require/css.js'}},
paths: {
'vue': ['plugs/vue/vue.min'],
'md5': ['plugs/jquery/md5.min'],
'json': ['plugs/jquery/json.min'],
'xlsx': ['plugs/jquery/xlsx.min'],
'excel': ['plugs/jquery/excel.xlsx'],
'base64': ['plugs/jquery/base64.min'],
'upload': [tapiRoot + '/api.upload/index?'],
'notify': ['plugs/notify/notify.min'],
'angular': ['plugs/angular/angular.min'],
'cropper': ['plugs/cropper/cropper.min'],
'echarts': ['plugs/echarts/echarts.min'],
'ckeditor4': ['plugs/ckeditor4/ckeditor'],
'ckeditor5': ['plugs/ckeditor5/ckeditor'],
'websocket': ['plugs/socket/websocket'],
'pcasunzips': ['plugs/jquery/pcasunzips'],
'sortablejs': ['plugs/sortable/sortable.min'],
'vue.sortable': ['plugs/sortable/vue.draggable.min'],
'jquery.ztree': ['plugs/ztree/ztree.all.min'],
'jquery.masonry': ['plugs/jquery/masonry.min'],
'jquery.cropper': ['plugs/cropper/cropper.min'],
'jquery.autocompleter': ['plugs/jquery/autocompleter.min'],
}, shim: {
'excel': {deps: [baseRoot + 'plugs/layui_exts/excel.js']}, 'notify': {deps: ['css!' + baseRoot + 'plugs/notify/light.css']}, 'cropper': {deps: ['css!' + baseRoot + 'plugs/cropper/cropper.min.css']}, 'websocket': {deps: [baseRoot + 'plugs/socket/swfobject.min.js']}, 'ckeditor5': {deps: ['jquery', 'upload', 'css!' + baseRoot + 'plugs/ckeditor5/ckeditor.css']}, 'vue.sortable': {deps: ['vue', 'sortablejs']}, 'jquery.ztree': {deps: ['jquery', 'css!' + baseRoot + 'plugs/ztree/zTreeStyle/zTreeStyle.css']}, 'jquery.autocompleter': {deps: ['jquery', 'css!' + baseRoot + 'plugs/jquery/autocompleter.css']},
'excel': {deps: [baseRoot + 'plugs/layui_exts/excel.js']},
'notify': {deps: ['css!' + baseRoot + 'plugs/notify/light.css']},
'cropper': {deps: ['css!' + baseRoot + 'plugs/cropper/cropper.min.css']},
'websocket': {deps: [baseRoot + 'plugs/socket/swfobject.min.js']},
'ckeditor5': {deps: ['jquery', 'upload', 'css!' + baseRoot + 'plugs/ckeditor5/ckeditor.css']},
'vue.sortable': {deps: ['vue', 'sortablejs']},
'jquery.ztree': {deps: ['jquery', 'css!' + baseRoot + 'plugs/ztree/zTreeStyle/zTreeStyle.css']},
'jquery.autocompleter': {deps: ['jquery', 'css!' + baseRoot + 'plugs/jquery/autocompleter.css']},
}
});
@ -546,11 +575,25 @@ $(function () {
});
};
/*! 上传单个视频 */
$.fn.uploadOneVideo = function () {
return this.each(function () {
if ($(this).data('inited')) return true; else $(this).data('inited', true);
var $in = $(this), $bt = $('<a data-file class="uploadimage uploadvideo transition"><span class="layui-icon">&#x1006;</span><span class="layui-icon">&#xe615;</span></a>').data('input', this);
$bt.attr('data-size', $in.data('size') || 0).attr('data-type', $in.data('type') || 'mp4').find('span').on('click', function (event) {
event.stopPropagation();
if ($(this).index() === 0) $bt.attr('style', ''), $in.val(''); else $in.val() && $.previewImage(encodeURI($in.val()));
}), $in.on('change', function () {
if (this.value) $bt.html('<video width="76" height="76" controls><source src="' + encodeURI(this.value) + '" type="video/mp4"></video>');
}).after($bt).trigger('change');
});
};
/*! 上传单张图片 */
$.fn.uploadOneImage = function () {
return this.each(function () {
if ($(this).data('inited')) return true; else $(this).data('inited', true);
var $in = $(this), $bt = $('<a data-file class="uploadimage transition"><span class="layui-icon">&#x1006;</span><span class="layui-icon">&#xe615;</span></a>').data('input', this);
var $in = $(this), $bt = $('<a data-file="image" class="uploadimage transition"><span class="layui-icon">&#x1006;</span><span class="layui-icon">&#xe615;</span></a>').data('input', this);
$bt.attr('data-size', $in.data('size') || 0).attr('data-type', $in.data('type') || 'png,jpg,gif,jpeg').find('span').on('click', function (event) {
event.stopPropagation();
if ($(this).index() === 0) $bt.attr('style', ''), $in.val(''); else $in.val() && $.previewImage(encodeURI($in.val()));
@ -585,20 +628,6 @@ $(function () {
});
};
/*! 上传单个视频 */
$.fn.uploadOneVideo = function () {
return this.each(function () {
if ($(this).data('inited')) return true; else $(this).data('inited', true);
var $in = $(this), $bt = $('<a data-file class="uploadimage uploadvideo transition"><span class="layui-icon">&#x1006;</span><span class="layui-icon">&#xe615;</span></a>').data('input', this);
$bt.attr('data-size', $in.data('size') || 0).attr('data-type', $in.data('type') || 'mp4').find('span').on('click', function (event) {
event.stopPropagation();
if ($(this).index() === 0) $bt.attr('style', ''), $in.val(''); else $in.val() && $.previewImage(encodeURI($in.val()));
}), $in.on('change', function () {
if (this.value) $bt.html('<video width="76" height="76" controls><source src="' + encodeURI(this.value) + '" type="video/mp4"></video>');
}).after($bt).trigger('change');
});
};
/*! 标签输入插件 */
$.fn.initTagInput = function () {
return this.each(function () {
@ -835,6 +864,22 @@ $(function () {
/*! 注册 data-file 事件行为 */
onEvent('click', '[data-file]', function () {
this.id = this.dataset.id = this.id || (function (date) {
return (date + Math.random()).replace('0.', '');
})(layui.util.toDateString(Date.now(), 'yyyyMMddHHmmss-'));
// 上传图片,支持单图或多图选择,分别是 image|images
if (typeof this.dataset.file === 'string' && /^images?$/.test(this.dataset.file)) {
return $.form.modal(tapiRoot + '/api.upload/image', this.dataset, '图片选择器')
}
// 上传视频,支持单视频或多视频选择,分别是 video|videos
if (typeof this.dataset.file === 'string' && /^videos?$/.test(this.dataset.file)) {
return $.form.modal(tapiRoot + '/api.upload/video', this.dataset, '视频选择器')
}
// 上传文档,支持单视频或多视频选择,分别是 document|documents
if (typeof this.dataset.file === 'string' && /^videos?$/.test(this.dataset.file)) {
return $.form.modal(tapiRoot + '/api.upload/document', this.dataset, '文档选择器')
}
// 其他文件上传
if ($(this).data('inited') !== true) (function (that) {
that.uploadFile(undefined, function () {
that.trigger('upload.start');

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-view{display:block;position:relative;margin:10px 0;padding:0;border:1px solid #eee;border-left-width:6px;background-color:#fafafa;color:#333;font-family:Courier New;font-size:12px}.layui-code-h3{position:relative;padding:0 10px;height:40px;line-height:40px;border-bottom:1px solid #eee;font-size:12px}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 10px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view .layui-code-ol li:first-child{padding-top:10px}.layui-code-view .layui-code-ol li:last-child{padding-bottom:10px}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0c0c0c;border-left-color:#3f3f3f;background-color:#0c0c0c;color:#c2be9e}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3f3f3f;border-left:none}.layui-code-demo .layui-code{visibility:visible!important;margin:-15px;border-top:none;border-right:none;border-bottom:none}.layui-code-demo .layui-tab-content{padding:15px;border-top:none}
html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-view{display:block;position:relative;margin:10px 0;padding:0;border:1px solid #eee;border-left-width:6px;background-color:#fafafa;color:#333;font-family:Courier New;font-size:13px}.layui-code-h3{position:relative;padding:0 10px;height:40px;line-height:40px;border-bottom:1px solid #eee;font-size:12px}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 10px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view .layui-code-ol li:first-child{padding-top:10px}.layui-code-view .layui-code-ol li:last-child{padding-bottom:10px}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0c0c0c;border-left-color:#3f3f3f;background-color:#0c0c0c;color:#c2be9e}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3f3f3f;border-left:none}.layui-code-demo .layui-code{visibility:visible!important;margin:-15px;border-top:none;border-right:none;border-bottom:none}.layui-code-demo .layui-tab-content{padding:15px;border-top:none}

File diff suppressed because one or more lines are too long

View File

@ -226,6 +226,10 @@ form.layui-form fieldset {
}
.layui-table {
&[lay-even] tr:nth-child(even) {
background-color: #fafafa;
}
td, th {
font-size: 12px;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long