wupengfei 3 سال پیش
والد
کامیت
e76367c74c
100فایلهای تغییر یافته به همراه17106 افزوده شده و 0 حذف شده
  1. 11 0
      .gitignore
  2. 21 0
      LICENSE
  3. 859 0
      admin_v5.sql
  4. 180 0
      application/admin/controller/Auth.php
  5. 130 0
      application/admin/controller/Config.php
  6. 206 0
      application/admin/controller/Index.php
  7. 118 0
      application/admin/controller/Login.php
  8. 160 0
      application/admin/controller/Menu.php
  9. 94 0
      application/admin/controller/Oplog.php
  10. 144 0
      application/admin/controller/Queue.php
  11. 173 0
      application/admin/controller/User.php
  12. 130 0
      application/admin/controller/api/Plugs.php
  13. 65 0
      application/admin/controller/api/Update.php
  14. 159 0
      application/admin/sys.php
  15. 3659 0
      application/admin/view/api/plugs/icon.html
  16. 116 0
      application/admin/view/auth/apply.html
  17. 30 0
      application/admin/view/auth/form.html
  18. 80 0
      application/admin/view/auth/index.html
  19. 42 0
      application/admin/view/auth/index_search.html
  20. 80 0
      application/admin/view/config/info.html
  21. 20 0
      application/admin/view/config/storage-local.html
  22. 80 0
      application/admin/view/config/storage-oss.html
  23. 80 0
      application/admin/view/config/storage-qiniu.html
  24. 57 0
      application/admin/view/config/system-config.html
  25. 137 0
      application/admin/view/index/index.html
  26. 197 0
      application/admin/view/index/main.html
  27. 57 0
      application/admin/view/login/index.html
  28. 11 0
      application/admin/view/main.html
  29. 89 0
      application/admin/view/menu/form.html
  30. 80 0
      application/admin/view/menu/index.html
  31. 68 0
      application/admin/view/oplog/index.html
  32. 56 0
      application/admin/view/oplog/index_search.html
  33. 94 0
      application/admin/view/queue/index.html
  34. 70 0
      application/admin/view/queue/index_search.html
  35. 73 0
      application/admin/view/user/form.html
  36. 77 0
      application/admin/view/user/index.html
  37. 57 0
      application/admin/view/user/index_search.html
  38. 57 0
      application/admin/view/user/pass.html
  39. 245 0
      application/api/common.php
  40. 173 0
      application/api/controller/Area.php
  41. 155 0
      application/api/controller/Base.php
  42. 283 0
      application/api/controller/Crystal.php
  43. 394 0
      application/api/controller/ExchangeOrder.php
  44. 322 0
      application/api/controller/Expedite.php
  45. 222 0
      application/api/controller/General.php
  46. 827 0
      application/api/controller/GoodsOrder.php
  47. 124 0
      application/api/controller/Login.php
  48. 470 0
      application/api/controller/MagicCase.php
  49. 929 0
      application/api/controller/Order.php
  50. 383 0
      application/api/controller/Pay.php
  51. 104 0
      application/api/controller/Qc.php
  52. 75 0
      application/api/controller/Timedtask.php
  53. 151 0
      application/api/controller/Upload.php
  54. 173 0
      application/api/controller/Usercenter.php
  55. 300 0
      application/api/controller/Usermanage.php
  56. 74 0
      application/api/controller/WeChart.php
  57. 302 0
      application/common.php
  58. 34 0
      application/index/controller/Index.php
  59. 70 0
      application/order/controller/CrystalCash.php
  60. 70 0
      application/order/controller/CrystalOrder.php
  61. 88 0
      application/order/controller/GoodsOrder.php
  62. 97 0
      application/order/controller/IntegralOrder.php
  63. 97 0
      application/order/controller/MagicOrder.php
  64. 87 0
      application/order/controller/Order.php
  65. 40 0
      application/order/view/crystal_order/index.html
  66. 50 0
      application/order/view/crystal_order/index_search.html
  67. 50 0
      application/order/view/goods_order/deliver.html
  68. 119 0
      application/order/view/goods_order/detail.html
  69. 41 0
      application/order/view/goods_order/index.html
  70. 50 0
      application/order/view/goods_order/index_search.html
  71. 79 0
      application/order/view/integral_order/deliver.html
  72. 125 0
      application/order/view/integral_order/detail.html
  73. 36 0
      application/order/view/integral_order/form.html
  74. 44 0
      application/order/view/integral_order/index.html
  75. 50 0
      application/order/view/integral_order/index_search.html
  76. 79 0
      application/order/view/magic_order/deliver.html
  77. 146 0
      application/order/view/magic_order/detail.html
  78. 36 0
      application/order/view/magic_order/form.html
  79. 44 0
      application/order/view/magic_order/index.html
  80. 50 0
      application/order/view/magic_order/index_search.html
  81. 50 0
      application/order/view/order/deliver.html
  82. 109 0
      application/order/view/order/detail.html
  83. 36 0
      application/order/view/order/form.html
  84. 44 0
      application/order/view/order/index.html
  85. 50 0
      application/order/view/order/index_search.html
  86. 196 0
      application/store/command/AutoRun.php
  87. 139 0
      application/store/controller/Banner.php
  88. 61 0
      application/store/controller/Config.php
  89. 245 0
      application/store/controller/Goods.php
  90. 139 0
      application/store/controller/GoodsCate.php
  91. 161 0
      application/store/controller/IntegralGoods.php
  92. 86 0
      application/store/controller/IntegralOrder.php
  93. 113 0
      application/store/controller/Versions.php
  94. 38 0
      application/store/controller/api/Data.php
  95. 38 0
      application/store/controller/api/Express.php
  96. 122 0
      application/store/controller/api/Goods.php
  97. 80 0
      application/store/controller/api/Member.php
  98. 74 0
      application/store/controller/api/Notify.php
  99. 92 0
      application/store/controller/api/Wechat.php
  100. 128 0
      application/store/controller/api/member/Address.php

+ 11 - 0
.gitignore

@@ -0,0 +1,11 @@
+/.git
+/.svn
+/.idea
+/runtime
+/safefile
+/nbproject
+/config/cert
+/composer.lock
+/public/upload
+public/static/theme/css/console.*.css
+public/static/theme/css/console.*.css.map

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 邹景立
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 859 - 0
admin_v5.sql

@@ -0,0 +1,859 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : local.server.cuci.cc
+ Source Server Type    : MySQL
+ Source Server Version : 50562
+ Source Host           : server.cuci.cc:3306
+ Source Schema         : admin_v5
+
+ Target Server Type    : MySQL
+ Target Server Version : 50562
+ File Encoding         : 65001
+
+ Date: 19/08/2019 10:34:31
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for company_user
+-- ----------------------------
+DROP TABLE IF EXISTS `company_user`;
+CREATE TABLE `company_user`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '员工姓名',
+  `svn_username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '员工账号',
+  `svn_password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '员工密码',
+  `svn_authorize` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '权限授权',
+  `user_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '员工身份',
+  `entry_date` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '入职日期',
+  `leave_date` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '离职日期',
+  `become_date` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '转正日期',
+  `contact_qq` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '联系QQ',
+  `contact_mail` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '联系邮箱',
+  `contact_phone` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '联系手机',
+  `mobile_macs` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '打卡手机',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '状态(0禁用,1正常,2离职)',
+  `sort` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '排序权重',
+  `is_deleted` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '删除(1删除,0未删)',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE INDEX `idx_company_user_nickname`(`nickname`) USING BTREE,
+  INDEX `idx_company_user_svn_username`(`svn_username`) USING BTREE,
+  INDEX `idx_company_user_deleted`(`is_deleted`) USING BTREE,
+  INDEX `idx_company_user_status`(`status`) USING BTREE,
+  INDEX `idx_company_user_type`(`user_type`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '企业-员工信息';
+
+-- ----------------------------
+-- Table structure for company_user_auth
+-- ----------------------------
+DROP TABLE IF EXISTS `company_user_auth`;
+CREATE TABLE `company_user_auth`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '权限名称',
+  `path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '权限路径',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '状态(0禁用,1正常)',
+  `desc` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '权限描述',
+  `sort` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '排序权重',
+  `is_deleted` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '删除(1删除,0未删)',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_company_user_auth_status`(`status`) USING BTREE,
+  INDEX `idx_company_user_auth_deleted`(`is_deleted`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '企业-仓库权限';
+
+-- ----------------------------
+-- Table structure for company_user_clock
+-- ----------------------------
+DROP TABLE IF EXISTS `company_user_clock`;
+CREATE TABLE `company_user_clock`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `uid` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '用户ID',
+  `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户姓名',
+  `ip` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '权限名称',
+  `mac` char(17) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '状态(1:禁用,2:启用)',
+  `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注说明',
+  `date` date NULL DEFAULT NULL,
+  `start_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `end_at` datetime NULL DEFAULT NULL COMMENT '结束时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_company_user_clock_date`(`date`) USING BTREE,
+  INDEX `idx_company_user_clock_uid`(`uid`) USING BTREE,
+  INDEX `idx_company_user_clock_name`(`name`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '企业-打卡记录';
+
+-- ----------------------------
+-- Table structure for store_express_company
+-- ----------------------------
+DROP TABLE IF EXISTS `store_express_company`;
+CREATE TABLE `store_express_company`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `express_title` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '快递公司名称',
+  `express_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '快递公司代码',
+  `express_desc` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '快递公司描述',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '状态(0.无效,1.有效)',
+  `sort` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '排序权重',
+  `is_deleted` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '删除状态(1删除,0未删除)',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 95 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '商城-快递-公司';
+
+-- ----------------------------
+-- Records of store_express_company
+-- ----------------------------
+INSERT INTO `store_express_company` VALUES (5, 'AAE全球专递', 'aae', NULL, 0, 0, 0, '2017-09-12 11:53:40');
+INSERT INTO `store_express_company` VALUES (6, '安捷快递', 'anjie', '', 0, 0, 0, '2017-09-13 15:27:26');
+INSERT INTO `store_express_company` VALUES (7, '安信达快递', 'anxindakuaixi', NULL, 0, 0, 0, '2017-09-13 16:05:19');
+INSERT INTO `store_express_company` VALUES (8, '彪记快递', 'biaojikuaidi', NULL, 0, 0, 0, '2017-09-13 16:05:26');
+INSERT INTO `store_express_company` VALUES (9, 'BHT', 'bht', '', 0, 0, 0, '2017-09-13 16:05:37');
+INSERT INTO `store_express_company` VALUES (10, '百福东方国际物流', 'baifudongfang', NULL, 0, 0, 0, '2017-09-13 16:05:41');
+INSERT INTO `store_express_company` VALUES (11, '中国东方(COE)', 'coe', NULL, 0, 0, 0, '2017-09-13 16:05:48');
+INSERT INTO `store_express_company` VALUES (12, '长宇物流', 'changyuwuliu', NULL, 0, 0, 0, '2017-09-13 16:05:58');
+INSERT INTO `store_express_company` VALUES (13, '大田物流', 'datianwuliu', NULL, 0, 0, 0, '2017-09-13 16:06:06');
+INSERT INTO `store_express_company` VALUES (14, '德邦物流', 'debangwuliu', '', 0, 1, 0, '2017-09-13 16:06:14');
+INSERT INTO `store_express_company` VALUES (15, 'DHL', 'dhl', NULL, 0, 0, 0, '2017-09-13 16:06:24');
+INSERT INTO `store_express_company` VALUES (16, 'DPEX', 'dpex', NULL, 0, 0, 0, '2017-09-13 16:06:29');
+INSERT INTO `store_express_company` VALUES (17, 'd速快递', 'dsukuaidi', NULL, 0, 0, 0, '2017-09-13 16:06:34');
+INSERT INTO `store_express_company` VALUES (18, '递四方', 'disifang', NULL, 0, 0, 0, '2017-09-13 16:06:40');
+INSERT INTO `store_express_company` VALUES (19, 'EMS快递', 'ems', '', 1, 0, 0, '2017-09-13 16:06:47');
+INSERT INTO `store_express_company` VALUES (20, 'FEDEX(国外)', 'fedex', NULL, 0, 0, 0, '2017-09-13 16:06:56');
+INSERT INTO `store_express_company` VALUES (21, '飞康达物流', 'feikangda', NULL, 0, 0, 0, '2017-09-13 16:07:03');
+INSERT INTO `store_express_company` VALUES (22, '凤凰快递', 'fenghuangkuaidi', NULL, 0, 0, 0, '2017-09-13 16:07:10');
+INSERT INTO `store_express_company` VALUES (23, '飞快达', 'feikuaida', NULL, 0, 0, 0, '2017-09-13 16:07:16');
+INSERT INTO `store_express_company` VALUES (24, '国通快递', 'guotongkuaidi', NULL, 0, 0, 0, '2017-09-13 16:07:27');
+INSERT INTO `store_express_company` VALUES (25, '港中能达物流', 'ganzhongnengda', NULL, 0, 0, 0, '2017-09-13 16:07:33');
+INSERT INTO `store_express_company` VALUES (26, '广东邮政物流', 'guangdongyouzhengwuliu', NULL, 0, 0, 0, '2017-09-13 16:08:22');
+INSERT INTO `store_express_company` VALUES (27, '共速达', 'gongsuda', NULL, 0, 0, 0, '2017-09-13 16:08:48');
+INSERT INTO `store_express_company` VALUES (28, '汇通快运', 'huitongkuaidi', NULL, 0, 0, 0, '2017-09-13 16:08:56');
+INSERT INTO `store_express_company` VALUES (29, '恒路物流', 'hengluwuliu', NULL, 0, 0, 0, '2017-09-13 16:09:02');
+INSERT INTO `store_express_company` VALUES (30, '华夏龙物流', 'huaxialongwuliu', NULL, 0, 0, 0, '2017-09-13 16:09:12');
+INSERT INTO `store_express_company` VALUES (31, '海红', 'haihongwangsong', NULL, 0, 0, 0, '2017-09-13 16:09:20');
+INSERT INTO `store_express_company` VALUES (32, '海外环球', 'haiwaihuanqiu', NULL, 0, 0, 0, '2017-09-13 16:09:27');
+INSERT INTO `store_express_company` VALUES (33, '佳怡物流', 'jiayiwuliu', NULL, 0, 0, 0, '2017-09-13 16:09:35');
+INSERT INTO `store_express_company` VALUES (34, '京广速递', 'jinguangsudikuaijian', NULL, 0, 0, 0, '2017-09-13 16:09:42');
+INSERT INTO `store_express_company` VALUES (35, '急先达', 'jixianda', NULL, 0, 0, 0, '2017-09-13 16:09:49');
+INSERT INTO `store_express_company` VALUES (36, '佳吉物流', 'jjwl', NULL, 0, 0, 0, '2017-09-13 16:10:01');
+INSERT INTO `store_express_company` VALUES (37, '加运美物流', 'jymwl', NULL, 0, 0, 0, '2017-09-13 16:10:13');
+INSERT INTO `store_express_company` VALUES (38, '金大物流', 'jindawuliu', NULL, 0, 0, 0, '2017-09-13 16:10:22');
+INSERT INTO `store_express_company` VALUES (39, '嘉里大通', 'jialidatong', NULL, 0, 0, 0, '2017-09-13 16:10:33');
+INSERT INTO `store_express_company` VALUES (40, '晋越快递', 'jykd', NULL, 0, 0, 0, '2017-09-13 16:10:40');
+INSERT INTO `store_express_company` VALUES (41, '快捷速递', 'kuaijiesudi', NULL, 0, 0, 0, '2017-09-13 16:10:49');
+INSERT INTO `store_express_company` VALUES (42, '联邦快递(国内)', 'lianb', NULL, 0, 0, 0, '2017-09-13 16:10:58');
+INSERT INTO `store_express_company` VALUES (43, '联昊通物流', 'lianhaowuliu', NULL, 0, 0, 0, '2017-09-13 16:11:07');
+INSERT INTO `store_express_company` VALUES (44, '龙邦物流', 'longbanwuliu', NULL, 0, 0, 0, '2017-09-13 16:11:15');
+INSERT INTO `store_express_company` VALUES (45, '立即送', 'lijisong', NULL, 0, 0, 0, '2017-09-13 16:11:25');
+INSERT INTO `store_express_company` VALUES (46, '乐捷递', 'lejiedi', NULL, 0, 0, 0, '2017-09-13 16:11:36');
+INSERT INTO `store_express_company` VALUES (47, '民航快递', 'minghangkuaidi', NULL, 0, 0, 0, '2017-09-13 16:11:45');
+INSERT INTO `store_express_company` VALUES (48, '美国快递', 'meiguokuaidi', NULL, 0, 0, 0, '2017-09-13 16:11:53');
+INSERT INTO `store_express_company` VALUES (49, '门对门', 'menduimen', NULL, 0, 0, 0, '2017-09-13 16:12:01');
+INSERT INTO `store_express_company` VALUES (50, 'OCS', 'ocs', NULL, 0, 0, 0, '2017-09-13 16:12:10');
+INSERT INTO `store_express_company` VALUES (51, '配思货运', 'peisihuoyunkuaidi', NULL, 0, 0, 0, '2017-09-13 16:12:18');
+INSERT INTO `store_express_company` VALUES (52, '全晨快递', 'quanchenkuaidi', NULL, 0, 0, 0, '2017-09-13 16:12:26');
+INSERT INTO `store_express_company` VALUES (53, '全峰快递', 'quanfengkuaidi', NULL, 0, 0, 0, '2017-09-13 16:12:34');
+INSERT INTO `store_express_company` VALUES (54, '全际通物流', 'quanjitong', NULL, 0, 0, 0, '2017-09-13 16:12:41');
+INSERT INTO `store_express_company` VALUES (55, '全日通快递', 'quanritongkuaidi', NULL, 0, 0, 0, '2017-09-13 16:12:49');
+INSERT INTO `store_express_company` VALUES (56, '全一快递', 'quanyikuaidi', NULL, 0, 0, 0, '2017-09-13 16:12:56');
+INSERT INTO `store_express_company` VALUES (57, '如风达', 'rufengda', NULL, 0, 0, 0, '2017-09-13 16:13:03');
+INSERT INTO `store_express_company` VALUES (58, '三态速递', 'santaisudi', NULL, 0, 0, 0, '2017-09-13 16:13:15');
+INSERT INTO `store_express_company` VALUES (59, '盛辉物流', 'shenghuiwuliu', NULL, 0, 0, 0, '2017-09-13 16:13:22');
+INSERT INTO `store_express_company` VALUES (60, '申通', 'shentong', NULL, 0, 0, 0, '2017-09-13 16:13:34');
+INSERT INTO `store_express_company` VALUES (61, '顺丰', 'shunfeng', '', 0, 0, 0, '2017-09-13 16:13:41');
+INSERT INTO `store_express_company` VALUES (62, '速尔物流', 'sue', NULL, 0, 0, 0, '2017-09-13 16:13:48');
+INSERT INTO `store_express_company` VALUES (63, '盛丰物流', 'shengfeng', NULL, 0, 0, 0, '2017-09-13 16:13:55');
+INSERT INTO `store_express_company` VALUES (64, '赛澳递', 'saiaodi', NULL, 0, 0, 0, '2017-09-13 16:14:02');
+INSERT INTO `store_express_company` VALUES (65, '天地华宇', 'tiandihuayu', NULL, 0, 0, 0, '2017-09-13 16:14:11');
+INSERT INTO `store_express_company` VALUES (66, '天天快递', 'tiantian', NULL, 0, 0, 0, '2017-09-13 16:14:19');
+INSERT INTO `store_express_company` VALUES (67, 'TNT', 'tnt', NULL, 0, 0, 0, '2017-09-13 16:14:26');
+INSERT INTO `store_express_company` VALUES (68, 'UPS', 'ups', NULL, 0, 0, 0, '2017-09-13 16:14:29');
+INSERT INTO `store_express_company` VALUES (69, '万家物流', 'wanjiawuliu', NULL, 0, 0, 0, '2017-09-13 16:14:37');
+INSERT INTO `store_express_company` VALUES (70, '文捷航空速递', 'wenjiesudi', NULL, 0, 0, 0, '2017-09-13 16:14:46');
+INSERT INTO `store_express_company` VALUES (71, '伍圆', 'wuyuan', NULL, 0, 0, 0, '2017-09-13 16:14:52');
+INSERT INTO `store_express_company` VALUES (72, '万象物流', 'wxwl', NULL, 0, 0, 0, '2017-09-13 16:15:00');
+INSERT INTO `store_express_company` VALUES (73, '新邦物流', 'xinbangwuliu', NULL, 0, 0, 0, '2017-09-13 16:15:06');
+INSERT INTO `store_express_company` VALUES (74, '信丰物流', 'xinfengwuliu', NULL, 0, 0, 0, '2017-09-13 16:15:15');
+INSERT INTO `store_express_company` VALUES (75, '亚风速递', 'yafengsudi', NULL, 0, 0, 0, '2017-09-13 16:15:23');
+INSERT INTO `store_express_company` VALUES (76, '一邦速递', 'yibangwuliu', NULL, 0, 0, 0, '2017-09-13 16:15:30');
+INSERT INTO `store_express_company` VALUES (77, '优速物流', 'youshuwuliu', NULL, 0, 0, 0, '2017-09-13 16:15:36');
+INSERT INTO `store_express_company` VALUES (78, '邮政包裹挂号信', 'youzhengguonei', NULL, 0, 3, 0, '2017-09-13 16:15:44');
+INSERT INTO `store_express_company` VALUES (79, '邮政国际包裹挂号信', 'youzhengguoji', NULL, 0, 2, 0, '2017-09-13 16:15:51');
+INSERT INTO `store_express_company` VALUES (80, '远成物流', 'yuanchengwuliu', NULL, 0, 0, 0, '2017-09-13 16:15:57');
+INSERT INTO `store_express_company` VALUES (81, '圆通速递', 'yuantong', '', 1, 1, 0, '2017-09-13 16:16:03');
+INSERT INTO `store_express_company` VALUES (82, '源伟丰快递', 'yuanweifeng', NULL, 0, 0, 0, '2017-09-13 16:16:10');
+INSERT INTO `store_express_company` VALUES (83, '元智捷诚快递', 'yuanzhijiecheng', NULL, 0, 0, 0, '2017-09-13 16:16:17');
+INSERT INTO `store_express_company` VALUES (84, '韵达快运', 'yunda', NULL, 0, 0, 0, '2017-09-13 16:16:24');
+INSERT INTO `store_express_company` VALUES (85, '运通快递', 'yuntongkuaidi', NULL, 0, 0, 0, '2017-09-13 16:16:33');
+INSERT INTO `store_express_company` VALUES (86, '越丰物流', 'yuefengwuliu', NULL, 0, 0, 0, '2017-09-13 16:16:40');
+INSERT INTO `store_express_company` VALUES (87, '源安达', 'yad', NULL, 0, 0, 0, '2017-09-13 16:16:47');
+INSERT INTO `store_express_company` VALUES (88, '银捷速递', 'yinjiesudi', NULL, 0, 0, 0, '2017-09-13 16:16:56');
+INSERT INTO `store_express_company` VALUES (89, '宅急送', 'zhaijisong', NULL, 0, 0, 0, '2017-09-13 16:17:03');
+INSERT INTO `store_express_company` VALUES (90, '中铁快运', 'zhongtiekuaiyun', NULL, 0, 0, 0, '2017-09-13 16:17:10');
+INSERT INTO `store_express_company` VALUES (91, '中通速递', 'zhongtong', '', 0, 0, 0, '2017-09-13 16:17:16');
+INSERT INTO `store_express_company` VALUES (92, '中邮物流', 'zhongyouwuliu', NULL, 0, 0, 0, '2017-09-13 16:17:27');
+INSERT INTO `store_express_company` VALUES (93, '忠信达', 'zhongxinda', NULL, 0, 0, 0, '2017-09-13 16:17:34');
+INSERT INTO `store_express_company` VALUES (94, '芝麻开门', 'zhimakaimen', '', 1, 0, 0, '2017-09-13 16:17:41');
+
+-- ----------------------------
+-- Table structure for store_express_template
+-- ----------------------------
+DROP TABLE IF EXISTS `store_express_template`;
+CREATE TABLE `store_express_template`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `rule` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '省份规则内容',
+  `order_reduction_state` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '订单满减状态',
+  `order_reduction_price` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '订单满减金额',
+  `first_number` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '首件数量',
+  `first_price` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '首件邮费',
+  `next_number` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '续件数量',
+  `next_price` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '续件邮费',
+  `is_default` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '默认规则',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_store_express_template_is_default`(`is_default`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商城-快递-模板';
+
+-- ----------------------------
+-- Table structure for store_goods
+-- ----------------------------
+DROP TABLE IF EXISTS `store_goods`;
+CREATE TABLE `store_goods`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `cate_id` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '商品分类',
+  `title` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '商品标题',
+  `logo` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '商品图标',
+  `specs` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '商品规格JSON',
+  `lists` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '商品列表JSON',
+  `image` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '商品图片',
+  `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '商品内容',
+  `number_sales` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '销售数量',
+  `number_stock` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '库库数量',
+  `price_rate` decimal(20, 4) UNSIGNED NULL DEFAULT 0.0000 COMMENT '返利比例',
+  `price_express` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '统一运费',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '销售状态',
+  `sort` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '排序权重',
+  `is_deleted` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '删除状态',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_store_goods_status`(`status`) USING BTREE,
+  INDEX `idx_store_goods_cate_id`(`cate_id`) USING BTREE,
+  INDEX `idx_store_goods_is_deleted`(`is_deleted`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品-记录';
+
+-- ----------------------------
+-- Table structure for store_goods_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `store_goods_cate`;
+CREATE TABLE `store_goods_cate`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `logo` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '分类图标',
+  `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '分类名称',
+  `desc` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '分类描述',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '销售状态',
+  `sort` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '排序权重',
+  `is_deleted` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '删除状态',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_store_goods_cate_is_deleted`(`is_deleted`) USING BTREE,
+  INDEX `idx_store_goods_cate_status`(`status`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品-分类';
+
+-- ----------------------------
+-- Table structure for store_goods_list
+-- ----------------------------
+DROP TABLE IF EXISTS `store_goods_list`;
+CREATE TABLE `store_goods_list`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `sku` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'sku',
+  `goods_id` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '商品ID',
+  `goods_spec` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '商品规格',
+  `price_market` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '商品标价',
+  `price_selling` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '商品售价',
+  `number_sales` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '销售数量',
+  `number_stock` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '商品库存',
+  `number_virtual` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '虚拟销量',
+  `number_express` bigint(20) UNSIGNED NULL DEFAULT 1 COMMENT '快递数量',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '商品状态',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_store_goods_list_id`(`goods_id`) USING BTREE,
+  INDEX `idx_store_goods_list_spec`(`goods_spec`) USING BTREE,
+  INDEX `idx_store_goods_list_status`(`status`) USING BTREE,
+  INDEX `idx_store_goods_list_sku`(`sku`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品-详情';
+
+-- ----------------------------
+-- Table structure for store_goods_stock
+-- ----------------------------
+DROP TABLE IF EXISTS `store_goods_stock`;
+CREATE TABLE `store_goods_stock`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `goods_id` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '商品ID',
+  `goods_spec` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '商品规格',
+  `number_stock` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '商品库存',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_store_goods_stock_gid`(`goods_id`) USING BTREE,
+  INDEX `idx_store_goods_stock_spec`(`goods_spec`(191)) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品-入库';
+
+-- ----------------------------
+-- Table structure for store_member
+-- ----------------------------
+DROP TABLE IF EXISTS `store_member`;
+CREATE TABLE `store_member`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `openid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '微信OPENID',
+  `headimg` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '头像地址',
+  `nickname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '微信昵称',
+  `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '联系手机',
+  `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '真实姓名',
+  `vip_level` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '会员级别(0游客,1为临时,2为VIP1,3为VIP2)',
+  `vip_date` date NULL DEFAULT NULL COMMENT '保级日期',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_store_member_openid`(`openid`) USING BTREE,
+  INDEX `idx_store_member_phone`(`phone`) USING BTREE,
+  INDEX `idx_store_member_vip_level`(`vip_level`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员-记录';
+
+-- ----------------------------
+-- Table structure for store_member_address
+-- ----------------------------
+DROP TABLE IF EXISTS `store_member_address`;
+CREATE TABLE `store_member_address`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `mid` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '会员ID',
+  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '收货姓名',
+  `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '收货手机',
+  `province` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '地址-省份',
+  `city` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '地址-城市',
+  `area` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '地址-区域',
+  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '地址-详情',
+  `is_default` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '默认地址',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_store_member_address_mid`(`mid`) USING BTREE,
+  INDEX `idx_store_member_address_is_default`(`is_default`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员-地址';
+
+-- ----------------------------
+-- Table structure for store_member_sms_history
+-- ----------------------------
+DROP TABLE IF EXISTS `store_member_sms_history`;
+CREATE TABLE `store_member_sms_history` (
+  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+  `mid` bigint(20) unsigned DEFAULT '0' COMMENT '会员ID',
+  `phone` varchar(20) DEFAULT '' COMMENT '目标手机',
+  `content` varchar(512) DEFAULT '' COMMENT '短信内容',
+  `region` varchar(100) DEFAULT '' COMMENT '区域编码',
+  `result` varchar(100) DEFAULT '' COMMENT '返回结果',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `idx_store_member_sms_history_phone` (`phone`) USING BTREE,
+  KEY `idx_store_member_sms_history_mid` (`mid`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员-短信';
+
+-- ----------------------------
+-- Table structure for store_order
+-- ----------------------------
+DROP TABLE IF EXISTS `store_order`;
+CREATE TABLE `store_order`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `mid` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '会员ID',
+  `order_no` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '订单单号',
+  `from_mid` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '推荐会员ID',
+  `price_total` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '待付金额统计',
+  `price_goods` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '商品费用统计',
+  `price_express` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '快递费用统计',
+  `price_rate_amount` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '返利金额统计',
+  `pay_state` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '支付状态(0未支付,1已支付)',
+  `pay_type` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '支付方式',
+  `pay_price` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '支付金额',
+  `pay_no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '支付单号',
+  `pay_at` datetime NULL DEFAULT NULL COMMENT '支付时间',
+  `cancel_state` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '取消状态',
+  `cancel_at` datetime NULL DEFAULT NULL COMMENT '取消时间',
+  `cancel_desc` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '取消描述',
+  `refund_state` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '退款状态(0未退款,1待退款,2已退款)',
+  `refund_at` datetime NULL DEFAULT NULL COMMENT '退款时间',
+  `refund_no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '退款单号',
+  `refund_price` decimal(20, 2) NULL DEFAULT 0.00 COMMENT '退款金额',
+  `refund_desc` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '退款描述',
+  `express_state` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '发货状态(0未发货,1已发货,2已签收)',
+  `express_company_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '发货快递公司编码',
+  `express_company_title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '发货快递公司名称',
+  `express_send_no` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '发货单号',
+  `express_send_at` datetime NULL DEFAULT NULL COMMENT '发货时间',
+  `express_address_id` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '收货地址ID',
+  `express_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '收货人姓名',
+  `express_phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '收货人手机',
+  `express_province` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '收货地址省份',
+  `express_city` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '收货地址城市',
+  `express_area` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '收货地址区域',
+  `express_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '收货详细地址',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '订单状态(0已取消,1预订单待补全,2新订单待支付,3已支付待发货,4已发货待签收,5已完成)',
+  `is_deleted` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '删除状态',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_store_groups_order_mid`(`mid`) USING BTREE,
+  INDEX `idx_store_groups_order_order_no`(`order_no`) USING BTREE,
+  INDEX `idx_store_groups_order_pay_state`(`pay_state`) USING BTREE,
+  INDEX `idx_store_groups_order_cancel_state`(`cancel_state`) USING BTREE,
+  INDEX `idx_store_groups_order_refund_state`(`refund_state`) USING BTREE,
+  INDEX `idx_store_groups_order_status`(`status`) USING BTREE,
+  INDEX `idx_store_groups_order_pay_no`(`pay_no`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '订单-记录';
+
+-- ----------------------------
+-- Table structure for store_order_list
+-- ----------------------------
+DROP TABLE IF EXISTS `store_order_list`;
+CREATE TABLE `store_order_list`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `mid` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '会员ID',
+  `from_id` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '推荐会员',
+  `order_no` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '订单单号',
+  `goods_id` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '商品标识',
+  `goods_title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '商品标题',
+  `goods_logo` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '商品图标',
+  `goods_spec` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '商品规格',
+  `price_real` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '交易金额',
+  `price_selling` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '销售价格',
+  `price_market` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '市场价格',
+  `price_express` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '快递费用',
+  `price_rate` decimal(20, 4) UNSIGNED NULL DEFAULT 0.0000 COMMENT '分成比例',
+  `price_rate_amount` decimal(20, 2) UNSIGNED NULL DEFAULT 0.00 COMMENT '分成金额',
+  `number_goods` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '商品数量',
+  `number_express` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '快递数量',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_store_goods_list_id`(`goods_id`) USING BTREE,
+  INDEX `idx_store_goods_list_spec`(`goods_spec`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '订单-详情';
+
+-- ----------------------------
+-- Table structure for system_auth
+-- ----------------------------
+DROP TABLE IF EXISTS `system_auth`;
+CREATE TABLE `system_auth`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限名称',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '权限状态',
+  `sort` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '排序权重',
+  `desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '备注说明',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_system_auth_status`(`status`) USING BTREE,
+  INDEX `idx_system_auth_title`(`title`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-权限';
+
+-- ----------------------------
+-- Table structure for system_auth_node
+-- ----------------------------
+DROP TABLE IF EXISTS `system_auth_node`;
+CREATE TABLE `system_auth_node`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `auth` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '角色',
+  `node` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '节点',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_system_auth_auth`(`auth`) USING BTREE,
+  INDEX `idx_system_auth_node`(`node`(191)) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-权限-授权';
+
+-- ----------------------------
+-- Table structure for system_config
+-- ----------------------------
+DROP TABLE IF EXISTS `system_config`;
+CREATE TABLE `system_config`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '配置名',
+  `value` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '配置值',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_system_config_name`(`name`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 81 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-配置';
+
+-- ----------------------------
+-- Records of system_config
+-- ----------------------------
+INSERT INTO `system_config` VALUES (1, 'app_name', 'ThinkAdmin');
+INSERT INTO `system_config` VALUES (2, 'site_name', 'ThinkAdmin');
+INSERT INTO `system_config` VALUES (3, 'app_version', 'dev');
+INSERT INTO `system_config` VALUES (4, 'site_copy', '©版权所有 2014-2018 楚才科技');
+INSERT INTO `system_config` VALUES (5, 'site_icon', '/upload/decb0fe26fa3f486/b3f6521bf29403c8.png');
+INSERT INTO `system_config` VALUES (7, 'miitbeian', '粤ICP备16006642号-2');
+INSERT INTO `system_config` VALUES (8, 'storage_type', 'local');
+INSERT INTO `system_config` VALUES (9, 'storage_local_exts', 'doc,gif,icon,jpg,mp3,mp4,p12,pem,png,rar');
+INSERT INTO `system_config` VALUES (10, 'storage_qiniu_bucket', 'https');
+INSERT INTO `system_config` VALUES (11, 'storage_qiniu_domain', '用你自己的吧');
+INSERT INTO `system_config` VALUES (12, 'storage_qiniu_access_key', '用你自己的吧');
+INSERT INTO `system_config` VALUES (13, 'storage_qiniu_secret_key', '用你自己的吧');
+INSERT INTO `system_config` VALUES (14, 'storage_oss_bucket', 'cuci-mytest');
+INSERT INTO `system_config` VALUES (15, 'storage_oss_endpoint', 'oss-cn-hangzhou.aliyuncs.com');
+INSERT INTO `system_config` VALUES (16, 'storage_oss_domain', '用你自己的吧');
+INSERT INTO `system_config` VALUES (17, 'storage_oss_keyid', '用你自己的吧');
+INSERT INTO `system_config` VALUES (18, 'storage_oss_secret', '用你自己的吧');
+INSERT INTO `system_config` VALUES (36, 'storage_oss_is_https', 'http');
+INSERT INTO `system_config` VALUES (43, 'storage_qiniu_region', '华东');
+INSERT INTO `system_config` VALUES (44, 'storage_qiniu_is_https', 'https');
+INSERT INTO `system_config` VALUES (45, 'wechat_mch_id', '1332187001');
+INSERT INTO `system_config` VALUES (46, 'wechat_mch_key', 'A82DC5BD1F3359081049C568D8502BC5');
+INSERT INTO `system_config` VALUES (47, 'wechat_mch_ssl_type', 'p12');
+INSERT INTO `system_config` VALUES (48, 'wechat_mch_ssl_p12', '65b8e4f56718182d/1bc857ee646aa15d.p12');
+INSERT INTO `system_config` VALUES (49, 'wechat_mch_ssl_key', 'cc2e3e1345123930/c407d033294f283d.pem');
+INSERT INTO `system_config` VALUES (50, 'wechat_mch_ssl_cer', '966eaf89299e9c95/7014872cc109b29a.pem');
+INSERT INTO `system_config` VALUES (51, 'wechat_token', 'mytoken');
+INSERT INTO `system_config` VALUES (52, 'wechat_appid', 'wx60a43dd8161666d4');
+INSERT INTO `system_config` VALUES (53, 'wechat_appsecret', '9978422e0e431643d4b42868d183d60b');
+INSERT INTO `system_config` VALUES (54, 'wechat_encodingaeskey', '');
+INSERT INTO `system_config` VALUES (55, 'wechat_push_url', '消息推送地址:http://127.0.0.1:8000/wechat/api.push');
+INSERT INTO `system_config` VALUES (56, 'wechat_type', 'thr');
+INSERT INTO `system_config` VALUES (57, 'wechat_thr_appid', 'wx60a43dd8161666d4');
+INSERT INTO `system_config` VALUES (58, 'wechat_thr_appkey', '5caf4b0727f6e46a7e6ccbe773cc955d');
+INSERT INTO `system_config` VALUES (60, 'wechat_thr_appurl', '消息推送地址:http://127.0.0.1:2314/wechat/api.push');
+INSERT INTO `system_config` VALUES (61, 'component_appid', 'wx28b58798480874f9');
+INSERT INTO `system_config` VALUES (62, 'component_appsecret', '8d0e1ec14ea0adc5027dd0ad82c64bc9');
+INSERT INTO `system_config` VALUES (63, 'component_token', 'P8QHTIxpBEq88IrxatqhgpBm2OAQROkI');
+INSERT INTO `system_config` VALUES (64, 'component_encodingaeskey', 'L5uFIa0U6KLalPyXckyqoVIJYLhsfrg8k9YzybZIHsx');
+INSERT INTO `system_config` VALUES (65, 'system_message_state', '0');
+INSERT INTO `system_config` VALUES (66, 'sms_zt_username', '可以找CUCI申请');
+INSERT INTO `system_config` VALUES (67, 'sms_zt_password', '可以找CUCI申请');
+INSERT INTO `system_config` VALUES (68, 'sms_reg_template', '您的验证码为{code},请在十分钟内完成操作!');
+INSERT INTO `system_config` VALUES (69, 'sms_secure', '可以找CUCI申请');
+INSERT INTO `system_config` VALUES (70, 'store_title', '测试商城');
+INSERT INTO `system_config` VALUES (71, 'store_order_wait_time', '0.50');
+INSERT INTO `system_config` VALUES (72, 'store_order_clear_time', '24.00');
+INSERT INTO `system_config` VALUES (73, 'store_order_confirm_time', '60.00');
+INSERT INTO `system_config` VALUES (74, 'sms_zt_username2', '可以找CUCI申请2');
+INSERT INTO `system_config` VALUES (75, 'sms_zt_password2', '可以找CUCI申请2');
+INSERT INTO `system_config` VALUES (76, 'sms_secure2', '可以找CUCI申请2');
+INSERT INTO `system_config` VALUES (77, 'sms_reg_template2', '您的验证码为{code},请在十分钟内完成操作!2');
+INSERT INTO `system_config` VALUES (78, 'michat_appid', '2882303761518074614');
+INSERT INTO `system_config` VALUES (79, 'michat_appkey', '5861807470614');
+INSERT INTO `system_config` VALUES (80, 'michat_appsecert', 'CP/WUTUgDuyOxgLQ5ztesg==');
+
+-- ----------------------------
+-- Table structure for system_data
+-- ----------------------------
+DROP TABLE IF EXISTS `system_data`;
+CREATE TABLE `system_data`  (
+  `id` bigint(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '配置名',
+  `value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '配置值',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_system_data_name`(`name`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-数据';
+
+-- ----------------------------
+-- Records of system_data
+-- ----------------------------
+INSERT INTO `system_data` VALUES (1, 'menudata', '[{\"name\":\"请输入名称\",\"type\":\"scancode_push\",\"key\":\"scancode_push\"}]');
+
+-- ----------------------------
+-- Table structure for system_log
+-- ----------------------------
+DROP TABLE IF EXISTS `system_log`;
+CREATE TABLE `system_log`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `node` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '当前操作节点',
+  `geoip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '操作者IP地址',
+  `action` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '操作行为名称',
+  `content` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '操作内容描述',
+  `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '操作人用户名',
+  `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-日志';
+
+-- ----------------------------
+-- Table structure for system_menu
+-- ----------------------------
+DROP TABLE IF EXISTS `system_menu`;
+CREATE TABLE `system_menu`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `pid` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '父ID',
+  `title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '名称',
+  `node` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '节点代码',
+  `icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '菜单图标',
+  `url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '链接',
+  `params` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '链接参数',
+  `target` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '_self' COMMENT '打开方式',
+  `sort` int(11) UNSIGNED NULL DEFAULT 0 COMMENT '菜单排序',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '状态(0:禁用,1:启用)',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_system_menu_node`(`node`(191)) USING BTREE,
+  INDEX `idx_system_menu_status`(`status`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 62 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-菜单';
+
+-- ----------------------------
+-- Records of system_menu
+-- ----------------------------
+INSERT INTO `system_menu` VALUES (1, 0, '后台首页', '', '', 'admin/index/main', '', '_self', 500, 1, '2018-09-05 17:59:38');
+INSERT INTO `system_menu` VALUES (2, 0, '系统管理', '', '', '#', '', '_self', 100, 1, '2018-09-05 18:04:52');
+INSERT INTO `system_menu` VALUES (3, 4, '系统菜单管理', '', 'layui-icon layui-icon-layouts', 'admin/menu/index', '', '_self', 1, 1, '2018-09-05 18:05:26');
+INSERT INTO `system_menu` VALUES (4, 2, '系统配置', '', '', '#', '', '_self', 20, 1, '2018-09-05 18:07:17');
+INSERT INTO `system_menu` VALUES (5, 12, '系统用户管理', '', 'layui-icon layui-icon-username', 'admin/user/index', '', '_self', 1, 1, '2018-09-06 11:10:42');
+INSERT INTO `system_menu` VALUES (7, 12, '访问权限管理', '', 'layui-icon layui-icon-vercode', 'admin/auth/index', '', '_self', 2, 1, '2018-09-06 15:17:14');
+INSERT INTO `system_menu` VALUES (11, 4, '系统参数配置', '', 'layui-icon layui-icon-set', 'admin/config/info', '', '_self', 4, 1, '2018-09-06 16:43:47');
+INSERT INTO `system_menu` VALUES (12, 2, '权限管理', '', '', '#', '', '_self', 10, 1, '2018-09-06 18:01:31');
+INSERT INTO `system_menu` VALUES (13, 0, '商城管理', '', '', '#', '', '_self', 400, 1, '2018-10-12 13:56:29');
+INSERT INTO `system_menu` VALUES (14, 48, '商品信息管理', '', 'layui-icon layui-icon-component', 'store/goods/index', '', '_self', 3, 1, '2018-10-12 13:56:48');
+INSERT INTO `system_menu` VALUES (16, 0, '微信管理', '', '', '#', '', '_self', 300, 1, '2018-10-31 15:15:27');
+INSERT INTO `system_menu` VALUES (17, 16, '微信管理', '', '', '#', '', '_self', 20, 1, '2018-10-31 15:16:46');
+INSERT INTO `system_menu` VALUES (18, 17, '微信授权配置', '', 'layui-icon layui-icon-set', 'wechat/config/options', '', '_self', 2, 1, '2018-10-31 15:17:11');
+INSERT INTO `system_menu` VALUES (19, 17, '微信支付配置', '', 'layui-icon layui-icon-rmb', 'wechat/config/payment', '', '_self', 1, 1, '2018-10-31 18:28:09');
+INSERT INTO `system_menu` VALUES (20, 16, '微信定制', '', '', '#', '', '_self', 10, 1, '2018-11-13 11:46:27');
+INSERT INTO `system_menu` VALUES (21, 20, '图文素材管理', '', 'layui-icon layui-icon-template', 'wechat/news/index', '', '_self', 6, 1, '2018-11-13 11:46:55');
+INSERT INTO `system_menu` VALUES (22, 20, '粉丝信息管理', '', 'layui-icon layui-icon-user', 'wechat/fans/index', '', '_self', 5, 1, '2018-11-15 09:51:13');
+INSERT INTO `system_menu` VALUES (23, 20, '回复规则管理', '', 'layui-icon layui-icon-engine', 'wechat/keys/index', '', '_self', 4, 1, '2018-11-22 11:29:08');
+INSERT INTO `system_menu` VALUES (24, 20, '关注回复配置', '', 'layui-icon layui-icon-senior', 'wechat/keys/subscribe', '', '_self', 3, 1, '2018-11-27 11:45:28');
+INSERT INTO `system_menu` VALUES (25, 20, '默认回复配置', '', 'layui-icon layui-icon-survey', 'wechat/keys/defaults', '', '_self', 2, 1, '2018-11-27 11:45:58');
+INSERT INTO `system_menu` VALUES (26, 20, '微信菜单管理', '', 'layui-icon layui-icon-cellphone', 'wechat/menu/index', '', '_self', 1, 1, '2018-11-27 17:56:56');
+INSERT INTO `system_menu` VALUES (27, 4, '系统任务管理', '', 'layui-icon layui-icon-log', 'admin/queue/index', '', '_self', 3, 1, '2018-11-29 11:13:34');
+INSERT INTO `system_menu` VALUES (37, 0, '开放平台', '', '', '#', '', '_self', 200, 1, '2018-12-28 13:29:25');
+INSERT INTO `system_menu` VALUES (38, 40, '开放平台配置', '', 'layui-icon layui-icon-set', 'service/config/index', '', '_self', 0, 1, '2018-12-28 13:29:44');
+INSERT INTO `system_menu` VALUES (39, 40, '公众授权管理', '', 'layui-icon layui-icon-template-1', 'service/index/index', '', '_self', 0, 1, '2018-12-28 13:30:07');
+INSERT INTO `system_menu` VALUES (40, 37, '平台管理', '', '', '#', '', '_self', 0, 1, '2018-12-28 16:05:46');
+INSERT INTO `system_menu` VALUES (42, 48, '会员信息管理', '', 'layui-icon layui-icon-user', 'store/member/index', '', '_self', 1, 1, '2019-01-22 14:24:23');
+INSERT INTO `system_menu` VALUES (43, 48, '订单记录管理', '', 'layui-icon layui-icon-template-1', 'store/order/index', '', '_self', 2, 1, '2019-01-22 14:46:22');
+INSERT INTO `system_menu` VALUES (44, 48, '商品分类管理', '', 'layui-icon layui-icon-app', 'store/goods_cate/index', '', '_self', 4, 1, '2019-01-23 10:41:06');
+INSERT INTO `system_menu` VALUES (45, 47, '商城参数配置', '', 'layui-icon layui-icon-set', 'store/config/index', '', '_self', 5, 1, '2019-01-24 16:47:33');
+INSERT INTO `system_menu` VALUES (46, 47, '短信发送记录', '', 'layui-icon layui-icon-console', 'store/message/index', '', '_self', 4, 1, '2019-01-24 18:09:58');
+INSERT INTO `system_menu` VALUES (47, 13, '商城配置', '', '', '#', '', '_self', 20, 1, '2019-01-25 16:47:49');
+INSERT INTO `system_menu` VALUES (48, 13, '数据管理', '', '', '#', '', '_self', 10, 1, '2019-01-25 16:48:35');
+INSERT INTO `system_menu` VALUES (49, 4, '系统日志管理', '', 'layui-icon layui-icon-form', 'admin/oplog/index', '', '_self', 2, 1, '2019-02-18 12:56:56');
+INSERT INTO `system_menu` VALUES (50, 47, '快递公司管理', '', 'layui-icon layui-icon-form', 'store/express_company/index', '', '_self', 3, 1, '2019-04-01 17:10:59');
+INSERT INTO `system_menu` VALUES (52, 47, '邮费模板管理', '', 'layui-icon layui-icon-fonts-clear', 'store/express_template/index', '', '_self', 1, 1, '2019-04-23 13:17:10');
+INSERT INTO `system_menu` VALUES (55, 17, '微信数据统计', '', 'layui-icon layui-icon-chart-screen', 'wechat/index/index', '', '_self', 3, 1, '2019-06-15 15:03:51');
+INSERT INTO `system_menu` VALUES (56, 40, '微信粉丝管理', '', 'layui-icon layui-icon-username', 'service/fans/index', '', '_self', 0, 1, '2019-07-23 09:57:24');
+INSERT INTO `system_menu` VALUES (57, 0, '企业管理', '', '', '#', '', '_self', 150, 1, '2019-08-08 17:20:29');
+INSERT INTO `system_menu` VALUES (58, 57, '基础管理', '', '', '#', '', '_self', 0, 1, '2019-08-08 17:20:42');
+INSERT INTO `system_menu` VALUES (59, 58, '企业员工管理', '', 'layui-icon layui-icon-username', 'company/user/index', '', '_self', 0, 1, '2019-08-08 17:20:59');
+INSERT INTO `system_menu` VALUES (60, 58, '仓库权限管理', '', 'layui-icon layui-icon-template-1', 'company/auth/index', '', '_self', 0, 1, '2019-08-08 18:39:37');
+INSERT INTO `system_menu` VALUES (61, 58, '网络打卡管理', '', 'layui-icon layui-icon-engine', 'company/clock/index', '', '_self', 0, 1, '2019-08-09 14:44:23');
+
+-- ----------------------------
+-- Table structure for system_queue
+-- ----------------------------
+DROP TABLE IF EXISTS `system_queue`;
+CREATE TABLE `system_queue`  (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '任务名称',
+  `data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行参数',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '任务状态(1新任务,2处理中,3成功,4失败)',
+  `preload` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '执行内容',
+  `time` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '执行时间',
+  `double` tinyint(1) NULL DEFAULT 1 COMMENT '单例模式',
+  `desc` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '状态描述',
+  `start_at` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '开始时间',
+  `end_at` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '结束时间',
+  `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_system_queue_double`(`double`) USING BTREE,
+  INDEX `idx_system_queue_time`(`time`) USING BTREE,
+  INDEX `idx_system_queue_title`(`title`) USING BTREE,
+  INDEX `idx_system_queue_create_at`(`create_at`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-任务';
+
+-- ----------------------------
+-- Table structure for system_user
+-- ----------------------------
+DROP TABLE IF EXISTS `system_user`;
+CREATE TABLE `system_user`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户账号',
+  `password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户密码',
+  `qq` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '联系QQ',
+  `mail` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '联系邮箱',
+  `phone` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '联系手机',
+  `login_at` datetime NULL DEFAULT NULL COMMENT '登录时间',
+  `login_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '登录IP',
+  `login_num` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '登录次数',
+  `authorize` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '权限授权',
+  `tags` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户标签',
+  `desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '备注说明',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '状态(0禁用,1启用)',
+  `is_deleted` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '删除(1删除,0未删)',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_system_user_username`(`username`) USING BTREE,
+  INDEX `idx_system_user_status`(`status`) USING BTREE,
+  INDEX `idx_system_user_deleted`(`is_deleted`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 10001 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-用户';
+
+-- ----------------------------
+-- Records of system_user
+-- ----------------------------
+INSERT INTO `system_user` VALUES (10000, 'admin', '21232f297a57a5a743894a0e4a801fc3', '22222222', '', '', '2019-08-18 18:34:14', '127.0.0.1', 661, '', '', '', 1, 0, '2015-11-13 15:14:22');
+
+-- ----------------------------
+-- Table structure for wechat_fans
+-- ----------------------------
+DROP TABLE IF EXISTS `wechat_fans`;
+CREATE TABLE `wechat_fans`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `appid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号APPID',
+  `unionid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '粉丝unionid',
+  `openid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '粉丝openid',
+  `tagid_list` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '粉丝标签id',
+  `is_black` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '是否为黑名单状态',
+  `subscribe` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '关注状态(0未关注,1已关注)',
+  `nickname` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户昵称',
+  `sex` tinyint(1) UNSIGNED NULL DEFAULT NULL COMMENT '用户性别(1男性,2女性,0未知)',
+  `country` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户所在国家',
+  `province` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户所在省份',
+  `city` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户所在城市',
+  `language` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户的语言(zh_CN)',
+  `headimgurl` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户头像',
+  `subscribe_time` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '关注时间',
+  `subscribe_at` datetime NULL DEFAULT NULL COMMENT '关注时间',
+  `remark` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '备注',
+  `subscribe_scene` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '扫码关注场景',
+  `qr_scene` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '二维码场景值',
+  `qr_scene_str` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '二维码场景内容',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_wechat_fans_openid`(`openid`) USING BTREE,
+  INDEX `idx_wechat_fans_unionid`(`unionid`) USING BTREE,
+  INDEX `idx_wechat_fans_is_back`(`is_black`) USING BTREE,
+  INDEX `idx_wechat_fans_subscribe`(`subscribe`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信-粉丝';
+
+-- ----------------------------
+-- Table structure for wechat_fans_tags
+-- ----------------------------
+DROP TABLE IF EXISTS `wechat_fans_tags`;
+CREATE TABLE `wechat_fans_tags`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '标签ID',
+  `appid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号APPID',
+  `name` varchar(35) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标签名称',
+  `count` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '总数',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
+  INDEX `idx_wechat_fans_tags_id`(`id`) USING BTREE,
+  INDEX `idx_wechat_fans_tags_appid`(`appid`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信-粉丝-标签';
+
+-- ----------------------------
+-- Table structure for wechat_keys
+-- ----------------------------
+DROP TABLE IF EXISTS `wechat_keys`;
+CREATE TABLE `wechat_keys`  (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `appid` char(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号APPID',
+  `type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '类型(text,image,news)',
+  `keys` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '关键字',
+  `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文本内容',
+  `image_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '图片链接',
+  `voice_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '语音链接',
+  `music_title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '音乐标题',
+  `music_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '音乐链接',
+  `music_image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '缩略图片',
+  `music_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '音乐描述',
+  `video_title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '视频标题',
+  `video_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '视频URL',
+  `video_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '视频描述',
+  `news_id` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '图文ID',
+  `sort` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '排序字段',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '状态(0禁用,1启用)',
+  `create_by` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '创建人',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_wechat_keys_appid`(`appid`) USING BTREE,
+  INDEX `idx_wechat_keys_type`(`type`) USING BTREE,
+  INDEX `idx_wechat_keys_keys`(`keys`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信-关键字';
+
+-- ----------------------------
+-- Table structure for wechat_media
+-- ----------------------------
+DROP TABLE IF EXISTS `wechat_media`;
+CREATE TABLE `wechat_media`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `appid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号ID',
+  `md5` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '文件md5',
+  `type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '媒体类型',
+  `media_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '永久素材MediaID',
+  `local_url` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '本地文件链接',
+  `media_url` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '远程图片链接',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_wechat_media_appid`(`appid`) USING BTREE,
+  INDEX `idx_wechat_media_md5`(`md5`) USING BTREE,
+  INDEX `idx_wechat_media_type`(`type`) USING BTREE,
+  INDEX `idx_wechat_media_media_id`(`media_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信-素材';
+
+-- ----------------------------
+-- Table structure for wechat_news
+-- ----------------------------
+DROP TABLE IF EXISTS `wechat_news`;
+CREATE TABLE `wechat_news`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `media_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '永久素材MediaID',
+  `local_url` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '永久素材显示URL',
+  `article_id` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '关联图文ID(用英文逗号做分割)',
+  `is_deleted` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '是否删除',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `create_by` bigint(20) NULL DEFAULT NULL COMMENT '创建人',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `idx_wechat_news_artcle_id`(`article_id`) USING BTREE,
+  INDEX `idx_wechat_news_media_id`(`media_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信-图文';
+
+-- ----------------------------
+-- Table structure for wechat_news_article
+-- ----------------------------
+DROP TABLE IF EXISTS `wechat_news_article`;
+CREATE TABLE `wechat_news_article`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '素材标题',
+  `local_url` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '永久素材显示URL',
+  `show_cover_pic` tinyint(4) UNSIGNED NULL DEFAULT 0 COMMENT '显示封面(0不显示,1显示)',
+  `author` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '文章作者',
+  `digest` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '摘要内容',
+  `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '图文内容',
+  `content_source_url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '原文地址',
+  `read_num` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '阅读数量',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信-图文-文章';
+
+-- ----------------------------
+-- Table structure for wechat_service_config
+-- ----------------------------
+DROP TABLE IF EXISTS `wechat_service_config`;
+CREATE TABLE `wechat_service_config`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `authorizer_appid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号APPID',
+  `authorizer_access_token` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号授权Token',
+  `authorizer_refresh_token` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号刷新Token',
+  `func_info` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号集权',
+  `nick_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号昵称',
+  `head_img` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号头像',
+  `expires_in` bigint(20) NULL DEFAULT NULL COMMENT 'Token有效时间',
+  `service_type` tinyint(2) NULL DEFAULT NULL COMMENT '微信类型(0代表订阅号,2代表服务号,3代表小程序)',
+  `service_type_info` tinyint(2) NULL DEFAULT NULL COMMENT '公众号实际类型',
+  `verify_type` tinyint(2) NULL DEFAULT NULL COMMENT '公众号认证类型(-1代表未认证, 0代表微信认证)',
+  `verify_type_info` tinyint(2) NULL DEFAULT NULL COMMENT '公众号实际认证类型',
+  `user_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '众众号原始账号',
+  `alias` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号别名',
+  `qrcode_url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公众号二维码',
+  `business_info` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',
+  `principal_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '公司名称',
+  `miniprograminfo` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '小程序JSON',
+  `idc` tinyint(1) UNSIGNED NULL DEFAULT NULL,
+  `signature` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '小程序的描述',
+  `total` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '统计调用次数',
+  `appkey` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '应用接口KEY',
+  `appuri` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '应用接口URI',
+  `status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '状态(1正常授权,0取消授权)',
+  `is_deleted` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '删除状态(0未删除,1已删除)',
+  `create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE INDEX `idx_wechat_service_config_authorizer_appid`(`authorizer_appid`) USING BTREE,
+  INDEX `idx_wechat_service_config_status`(`status`) USING BTREE,
+  INDEX `idx_wechat_service_config_is_deleted`(`is_deleted`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信-授权';
+
+SET FOREIGN_KEY_CHECKS = 1;

+ 180 - 0
application/admin/controller/Auth.php

@@ -0,0 +1,180 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\admin\controller;
+
+use library\Controller;
+use library\service\AdminService;
+use think\Db;
+
+/**
+ * 系统权限管理
+ * Class Auth
+ * @package app\admin\controller
+ */
+class Auth extends Controller
+{
+    /**
+     * 默认数据模型
+     * @var string
+     */
+    public $table = 'SystemAuth';
+
+    /**
+     * 系统权限管理
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        $this->title = '系统权限管理';
+        $query = $this->_query($this->table)->dateBetween('create_at');
+        $query->like('title,desc')->equal('status')->order('sort desc,id desc')->page();
+    }
+
+    /**
+     * 权限配置节点
+     * @auth true
+     * @throws \ReflectionException
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function apply()
+    {
+        $map = ['auth' => input('id', '0')];
+        $action = strtolower(input('action', ''));
+        if ($action === 'get') {
+            $checkeds = Db::name('SystemAuthNode')->where($map)->column('node');
+            $this->success('获取权限节点成功!', AdminService::instance()->getTree($checkeds));
+        } elseif ($action === 'save') {
+            list($post, $data) = [$this->request->post(), []];
+            foreach (isset($post['nodes']) ? $post['nodes'] : [] as $node) {
+                $data[] = ['auth' => $map['auth'], 'node' => $node];
+            }
+            Db::name('SystemAuthNode')->where($map)->delete();
+            Db::name('SystemAuthNode')->insertAll($data);
+            AdminService::instance()->apply(true);
+            $this->success('权限授权更新成功!', 'javascript:history.back()');
+        } else {
+            $this->title = '权限配置节点';
+            $this->_form($this->table, 'apply');
+        }
+    }
+
+    /**
+     * 添加系统权限
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function add()
+    {
+        $this->applyCsrfToken();
+        $this->_form($this->table, 'form');
+    }
+
+    /**
+     * 编辑系统权限
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function edit()
+    {
+        $this->applyCsrfToken();
+        $this->_form($this->table, 'form');
+    }
+
+    /**
+     * 刷新系统权限
+     * @auth true
+     */
+    public function refresh()
+    {
+        try {
+            AdminService::instance()->apply(true);
+            $this->success('刷新系统授权成功!');
+        } catch (\think\exception\HttpResponseException $exception) {
+            throw  $exception;
+        } catch (\Exception $e) {
+            $this->error("刷新系统授权失败<br>{$e->getMessage()}");
+        }
+    }
+
+    /**
+     * 禁用系统权限
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function forbid()
+    {
+        $this->applyCsrfToken();
+        $this->_save($this->table, ['status' => '0']);
+    }
+
+    /**
+     * 启用系统权限
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function resume()
+    {
+        $this->applyCsrfToken();
+        $this->_save($this->table, ['status' => '1']);
+    }
+
+    /**
+     * 删除系统权限
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function remove()
+    {
+        $this->applyCsrfToken();
+        $this->_delete($this->table);
+    }
+
+    /**
+     * 删除结果处理
+     * @param boolean $result
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    protected function _remove_delete_result($result)
+    {
+        if ($result) {
+            $map = ['auth' => $this->request->post('id')];
+            Db::name('SystemAuthNode')->where($map)->delete();
+            $this->success("权限删除成功!", '');
+        } else {
+            $this->error("权限删除失败,请稍候再试!");
+        }
+    }
+
+}

+ 130 - 0
application/admin/controller/Config.php

@@ -0,0 +1,130 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\admin\controller;
+
+use library\Controller;
+use think\exception\HttpResponseException;
+use think\facade\Request;
+
+/**
+ * 系统参数配置
+ * Class Config
+ * @package app\admin\controller
+ */
+class Config extends Controller
+{
+    /**
+     * 默认数据模型
+     * @var string
+     */
+    protected $table = 'SystemConfig';
+
+    /**
+     * 阿里云OSS上传点
+     * @var array
+     */
+    protected $ossPoints = [
+        'oss-cn-hangzhou.aliyuncs.com'    => '华东 1 杭州',
+        'oss-cn-shanghai.aliyuncs.com'    => '华东 2 上海',
+        'oss-cn-qingdao.aliyuncs.com'     => '华北 1 青岛',
+        'oss-cn-beijing.aliyuncs.com'     => '华北 2 北京',
+        'oss-cn-zhangjiakou.aliyuncs.com' => '华北 3 张家口',
+        'oss-cn-huhehaote.aliyuncs.com'   => '华北 5 呼和浩特',
+        'oss-cn-shenzhen.aliyuncs.com'    => '华南 1 深圳',
+        'oss-cn-hongkong.aliyuncs.com'    => '香港 1',
+        'oss-us-west-1.aliyuncs.com'      => '美国西部 1 硅谷',
+        'oss-us-east-1.aliyuncs.com'      => '美国东部 1 弗吉尼亚',
+        'oss-ap-southeast-1.aliyuncs.com' => '亚太东南 1 新加坡',
+        'oss-ap-southeast-2.aliyuncs.com' => '亚太东南 2 悉尼',
+        'oss-ap-southeast-3.aliyuncs.com' => '亚太东南 3 吉隆坡',
+        'oss-ap-southeast-5.aliyuncs.com' => '亚太东南 5 雅加达',
+        'oss-ap-northeast-1.aliyuncs.com' => '亚太东北 1 日本',
+        'oss-ap-south-1.aliyuncs.com'     => '亚太南部 1 孟买',
+        'oss-eu-central-1.aliyuncs.com'   => '欧洲中部 1 法兰克福',
+        'oss-eu-west-1.aliyuncs.com'      => '英国 1 伦敦',
+        'oss-me-east-1.aliyuncs.com'      => '中东东部 1 迪拜',
+    ];
+
+    /**
+     * 系统参数配置
+     * @auth true
+     * @menu true
+     */
+    public function info()
+    {
+        $this->title = '系统参数配置';
+        $this->fetch();
+    }
+
+    /**
+     * 修改系统能数配置
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function config()
+    {
+        $this->applyCsrfToken();
+        if (Request::isGet()) {
+            $this->fetch('system-config');
+        }
+        foreach (Request::post() as $key => $value) {
+            sysconf($key, $value);
+        }
+        $this->success('系统参数配置成功!');
+    }
+
+    /**
+     * 文件存储引擎
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function file()
+    {
+        $this->applyCsrfToken();
+        if (Request::isGet()) {
+            $this->type = input('type', 'local');
+            $this->fetch("storage-{$this->type}");
+        }
+        $post = Request::post();
+        if (isset($post['storage_type']) && isset($post['storage_local_exts'])) {
+            $exts = array_unique(explode(',', strtolower($post['storage_local_exts'])));
+            sort($exts);
+            if (in_array('php', $exts)) $this->error('禁止上传可执行文件到本地服务器!');
+            $post['storage_local_exts'] = join(',', $exts);
+        }
+        foreach ($post as $key => $value) sysconf($key, $value);
+        if (isset($post['storage_type']) && $post['storage_type'] === 'oss') {
+            try {
+                $local = sysconf('storage_oss_domain');
+                $bucket = $this->request->post('storage_oss_bucket');
+                $domain = \library\File::instance('oss')->setBucket($bucket);
+                if (empty($local) || stripos($local, '.aliyuncs.com') !== false) {
+                    sysconf('storage_oss_domain', $domain);
+                }
+                $this->success('阿里云OSS存储配置成功!');
+            } catch (HttpResponseException $exception) {
+                throw $exception;
+            } catch (\Exception $e) {
+                $this->error("阿里云OSS存储配置失效,{$e->getMessage()}");
+            }
+        } else {
+            $this->success('文件存储配置成功!');
+        }
+    }
+
+}

+ 206 - 0
application/admin/controller/Index.php

@@ -0,0 +1,206 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\admin\controller;
+
+use library\Controller;
+use library\service\AdminService;
+use library\service\MenuService;
+use library\tools\Data;
+use think\Console;
+use think\Db;
+use think\exception\HttpResponseException;
+
+/**
+ * 系统公共操作
+ * Class Index
+ * @package app\admin\controller
+ */
+class Index extends Controller
+{
+
+    /**
+     * 显示后台首页
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function index()
+    {
+        $this->title = '系统管理后台';
+        $auth = AdminService::instance()->apply(true);
+        $this->menus = MenuService::instance()->getTree();
+        if (empty($this->menus) && !$auth->isLogin()) {
+            $this->redirect('@admin/login');
+        } else {
+            $this->fetch();
+        }
+    }
+
+    /**
+     * 后台环境信息
+     */
+    public function main()
+    {
+        $this->think_ver = \think\App::VERSION;
+        $this->mysql_ver = Db::query('select version() as ver')[0]['ver'];
+        //活动总量
+        $goods_count = Db::name('store_goods')->count('id');
+        //用户总量
+        $member_count = Db::name('store_member')->count('id');
+        //报名总量
+        $apply_count = Db::name('store_apply_list')->count('id');
+        //建议总量
+        $complain_count = Db::name('store_complain')->count('id');
+
+        $beginYesterday=mktime(0,0,0,date('m'),date('d')-1,date('Y'));
+        $endYesterday=mktime(0,0,0,date('m'),date('d'),date('Y'))-1;
+        $beginToday=mktime(0,0,0,date('m'),date('d'),date('Y'));
+        $endToday=mktime(0,0,0,date('m'),date('d')+1,date('Y'))-1;
+        //昨天报名优惠金额
+        $yesterday_amount = Db::name('store_apply_list')->where('is_deleted',0)->whereBetweenTime('create_at',date('Y-m-d H:i:s',$beginYesterday),date('Y-m-d H:i:s',$endYesterday))->sum('amount');
+        //今天报名优惠金额
+        $today_amount = Db::name('store_apply_list')->where('is_deleted',0)->whereBetweenTime('create_at',date('Y-m-d H:i:s',$beginToday),date('Y-m-d H:i:s',$endToday))->sum('amount');
+
+        //昨天新增用户数
+        $yesterday_member = Db::name('store_member')->whereBetweenTime('create_at',date('Y-m-d H:i:s',$beginYesterday),date('Y-m-d H:i:s',$endYesterday))->count('id');
+        //今天新增用户数
+        $today_member = Db::name('store_member')->whereBetweenTime('create_at',date('Y-m-d H:i:s',$beginToday),date('Y-m-d H:i:s',$endToday))->count('id');
+        $data = array(
+            'goods_count' => $goods_count,
+            'member_count' => $member_count,
+            'apply_count' => $apply_count,
+            'complain_count' => $complain_count,
+
+            'yesterday_amount' => $yesterday_amount,
+            'today_amount' => $today_amount,
+            'yesterday_member' => $yesterday_member,
+            'today_member' => $today_member,
+        );
+        $this->assign('data',$data);
+        $this->fetch();
+    }
+
+    /**
+     * 修改密码
+     * @login true
+     * @param integer $id
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function pass($id)
+    {
+        $this->applyCsrfToken();
+        if (intval($id) !== intval(session('user.id'))) {
+            $this->error('只能修改当前用户的密码!');
+        }
+        if (!AdminService::instance()->isLogin()) {
+            $this->error('需要登录才能操作哦!');
+        }
+        if ($this->request->isGet()) {
+            $this->verify = true;
+            $this->_form('SystemUser', 'admin@user/pass', 'id', [], ['id' => $id]);
+        } else {
+            $data = $this->_input([
+                'password'    => $this->request->post('password'),
+                'repassword'  => $this->request->post('repassword'),
+                'oldpassword' => $this->request->post('oldpassword'),
+            ], [
+                'oldpassword' => 'require',
+                'password'    => 'require|min:4',
+                'repassword'  => 'require|confirm:password',
+            ], [
+                'oldpassword.require' => '旧密码不能为空!',
+                'password.require'    => '登录密码不能为空!',
+                'password.min'        => '登录密码长度不能少于4位有效字符!',
+                'repassword.require'  => '重复密码不能为空!',
+                'repassword.confirm'  => '重复密码与登录密码不匹配,请重新输入!',
+            ]);
+            $user = Db::name('SystemUser')->where(['id' => $id])->find();
+            if (md5($data['oldpassword']) !== $user['password']) {
+                $this->error('旧密码验证失败,请重新输入!');
+            }
+            if (Data::save('SystemUser', ['id' => $user['id'], 'password' => md5($data['password'])])) {
+                $this->success('密码修改成功,下次请使用新密码登录!', '');
+            } else {
+                $this->error('密码修改失败,请稍候再试!');
+            }
+        }
+    }
+
+    /**
+     * 修改用户资料
+     * @login true
+     * @param integer $id 会员ID
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function info($id = 0)
+    {
+        if (!AdminService::instance()->isLogin()) {
+            $this->error('需要登录才能操作哦!');
+        }
+        $this->applyCsrfToken();
+        if (intval($id) === intval(session('user.id'))) {
+            $this->_form('SystemUser', 'admin@user/form', 'id', [], ['id' => $id]);
+        } else {
+            $this->error('只能修改登录用户的资料!');
+        }
+    }
+
+    /**
+     * 清理运行缓存
+     * @auth true
+     */
+    public function clearRuntime()
+    {
+        try {
+            Console::call('clear');
+            Console::call('xclean:session');
+            $this->success('清理运行缓存成功!');
+        } catch (HttpResponseException $exception) {
+            throw $exception;
+        } catch (\Exception $e) {
+            $this->error("清理运行缓存失败,{$e->getMessage()}");
+        }
+    }
+
+    /**
+     * 压缩发布系统
+     * @auth true
+     */
+    public function buildOptimize()
+    {
+        try {
+            Console::call('optimize:route');
+            Console::call('optimize:schema');
+            Console::call('optimize:autoload');
+            Console::call('optimize:config');
+            $this->success('压缩发布成功!');
+        } catch (HttpResponseException $exception) {
+            throw $exception;
+        } catch (\Exception $e) {
+            $this->error("压缩发布失败,{$e->getMessage()}");
+        }
+    }
+
+}

+ 118 - 0
application/admin/controller/Login.php

@@ -0,0 +1,118 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\admin\controller;
+
+use library\Controller;
+use library\service\AdminService;
+use library\service\CaptchaService;
+use library\service\SystemService;
+use library\tools\Data;
+use think\Db;
+use think\facade\Request;
+
+/**
+ * 用户登录管理
+ * Class Login
+ * @package app\admin\controller
+ */
+class Login extends Controller
+{
+
+    /**
+     * 后台登录入口
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        if (Request::isGet()) {
+            if (AdminService::instance()->isLogin()) {
+                $this->redirect('@admin');
+            } else {
+                $this->title = '系统登录';
+                $this->captcha_type = 'login_captcha';
+                $this->captcha_token = Data::uniqidDateCode(18);
+                $this->app->session->set($this->captcha_type, $this->captcha_token);
+                $this->devmode = SystemService::instance()->checkRunMode('dev');
+                $this->fetch();
+            }
+        } else {
+            $data = $this->_vali([
+                'username.require' => '登录账号不能为空!',
+                'username.min:4'   => '登录账号长度不能少于4位有效字符!',
+                'password.require' => '登录密码不能为空!',
+                'password.min:4'   => '登录密码长度不能少于4位有效字符!',
+                'verify.require'   => '图形验证码不能为空!',
+                'uniqid.require'   => '图形验证标识不能为空!',
+            ]);
+            if (!CaptchaService::instance()->check($data['verify'], $data['uniqid'])) {
+                $this->error('图形验证码验证失败,请重新输入!');
+            }
+            // 用户信息验证
+            $map = ['is_deleted' => '0', 'username' => $data['username']];
+            $user = Db::name('SystemUser')->where($map)->order('id desc')->find();
+            if (empty($user)) {
+                $this->error('登录账号或密码错误,请重新输入1!');
+            }
+            if (md5("{$user['password']}{$data['uniqid']}") !== $data['password']) {
+                $this->error('登录账号或密码错误,请重新输入2!');
+            }
+            if (empty($user['status'])) {
+                $this->error('账号已经被禁用,请联系管理员!');
+            }
+            Db::name('SystemUser')->where(['id' => $user['id']])->update([
+                'login_ip'  => Request::ip(),
+                'login_at'  => Db::raw('now()'),
+                'login_num' => Db::raw('login_num+1'),
+            ]);
+            $this->app->session->set('user', $user);
+            AdminService::instance()->apply(true);
+            sysoplog('系统管理', '用户登录系统后台成功');
+            $this->success('登录成功', url('@admin'));
+        }
+    }
+
+    /**
+     * 生成验证码
+     * 需要指定类型及令牌
+     */
+    public function captcha()
+    {
+        $image = CaptchaService::instance();
+        $this->type = input('type', 'captcha-type');
+        $this->token = input('token', 'captcha-token');
+        $captcha = ['image' => $image->getData(), 'uniqid' => $image->getUniqid()];
+        if ($this->app->session->get($this->type) === $this->token) {
+            $captcha['code'] = $image->getCode();
+            $this->app->session->delete($this->type);
+        }
+        $this->success('生成验证码成功', $captcha);
+    }
+
+    /**
+     * 退出登录
+     */
+    public function out()
+    {
+        $this->app->session->clear();
+        $this->app->session->destroy();
+        $this->success('退出登录成功!', url('@admin/login'));
+    }
+
+}

+ 160 - 0
application/admin/controller/Menu.php

@@ -0,0 +1,160 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\admin\controller;
+
+use library\Controller;
+use library\service\MenuService;
+use library\tools\Data;
+use think\Db;
+
+/**
+ * 系统菜单管理
+ * Class Menu
+ * @package app\admin\controller
+ */
+class Menu extends Controller
+{
+
+    /**
+     * 当前操作数据库
+     * @var string
+     */
+    protected $table = 'SystemMenu';
+
+    /**
+     * 系统菜单管理
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        $this->title = '系统菜单管理';
+        $this->_page($this->table, false);
+    }
+
+    /**
+     * 列表数据处理
+     * @param array $data
+     */
+    protected function _index_page_filter(&$data)
+    {
+        foreach ($data as &$vo) {
+            if ($vo['url'] !== '#') {
+                $vo['url'] = trim(url($vo['url']) . (empty($vo['params']) ? '' : "?{$vo['params']}"), '/\\');
+            }
+            $vo['ids'] = join(',', Data::getArrSubIds($data, $vo['id']));
+        }
+        $data = Data::arr2table($data);
+    }
+
+    /**
+     * 添加系统菜单
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function add()
+    {
+        $this->applyCsrfToken();
+        $this->_form($this->table, 'form');
+    }
+
+    /**
+     * 编辑系统菜单
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function edit()
+    {
+        $this->applyCsrfToken();
+        $this->_form($this->table, 'form');
+    }
+
+    /**
+     * 表单数据处理
+     * @param array $vo
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    protected function _form_filter(&$vo)
+    {
+        if ($this->request->isGet()) {
+            // 读取系统功能节点
+            $this->nodes = MenuService::instance()->getList();
+            // 选择自己的上级菜单
+            if (empty($vo['pid']) && $this->request->get('pid', '0')) $vo['pid'] = $this->request->get('pid', '0');
+            // 列出可选上级菜单
+            $menus = Db::name($this->table)->where(['status' => '1'])->order('sort desc,id asc')->column('id,pid,url,title');
+            $this->menus = Data::arr2table(array_merge($menus, [['id' => '0', 'pid' => '-1', 'url' => '#', 'title' => '顶部菜单']]));
+            if (isset($vo['id'])) foreach ($this->menus as $key => $menu) if ($menu['id'] === $vo['id']) $vo = $menu;
+            foreach ($this->menus as $key => &$menu) {
+                if ($menu['spt'] >= 3 || $menu['url'] !== '#') unset($this->menus[$key]);
+                if (isset($vo['spt']) && $vo['spt'] <= $menu['spt']) unset($this->menus[$key]);
+            }
+        }
+    }
+
+    /**
+     * 启用系统菜单
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function resume()
+    {
+        $this->applyCsrfToken();
+        $this->_save($this->table, ['status' => '1']);
+    }
+
+    /**
+     * 禁用系统菜单
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function forbid()
+    {
+        $this->applyCsrfToken();
+        $this->_save($this->table, ['status' => '0']);
+    }
+
+    /**
+     * 删除系统菜单
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function remove()
+    {
+        $this->applyCsrfToken();
+        $this->_delete($this->table);
+    }
+
+}

+ 94 - 0
application/admin/controller/Oplog.php

@@ -0,0 +1,94 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\admin\controller;
+
+use library\Controller;
+use think\Db;
+
+/**
+ * 系统日志管理
+ * Class Oplog
+ * @package app\admin\controller
+ */
+class Oplog extends Controller
+{
+
+    /**
+     * 指定当前数据表
+     * @var string
+     */
+    public $table = 'SystemLog';
+
+    /**
+     * 系统操作日志
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function index()
+    {
+        $this->title = '系统操作日志';
+        $query = $this->_query($this->table)->like('action,node,content,username,geoip');
+        $query->dateBetween('create_at')->order('id desc')->page();
+    }
+
+    /**
+     * 列表数据处理
+     * @auth true
+     * @param array $data
+     * @throws \Exception
+     */
+    protected function _index_page_filter(&$data)
+    {
+        $ip = new \Ip2Region();
+        foreach ($data as &$vo) {
+            $result = $ip->btreeSearch($vo['geoip']);
+            $vo['isp'] = isset($result['region']) ? $result['region'] : '';
+            $vo['isp'] = str_replace(['内网IP', '0', '|'], '', $vo['isp']);
+        }
+    }
+
+    /**
+     * 清理系统日志
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function clear()
+    {
+        if (Db::name($this->table)->whereRaw('1=1')->delete() !== false) {
+            $this->success('日志清理成功!');
+        } else {
+            $this->error('日志清理失败,请稍候再试!');
+        }
+    }
+
+    /**
+     * 删除系统日志
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function remove()
+    {
+        $this->applyCsrfToken();
+        $this->_delete($this->table);
+    }
+
+}

+ 144 - 0
application/admin/controller/Queue.php

@@ -0,0 +1,144 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\admin\controller;
+
+use library\Controller;
+use library\service\ProcessService;
+use think\Console;
+use think\Db;
+use think\exception\HttpResponseException;
+
+/**
+ * 系统系统任务
+ * Class Queue
+ * @package app\admin\controller
+ */
+class Queue extends Controller
+{
+    /**
+     * 绑定数据表
+     * @var string
+     */
+    protected $table = 'SystemQueue';
+
+    /**
+     * 系统系统任务
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        if (session('user.username') === 'admin') try {
+            $this->message = Console::call('xtask:state')->fetch();
+            $this->command = ProcessService::instance()->think('xtask:start');
+            $this->listen = preg_match('/process.*?\d+.*?running/', $this->message, $attr);
+        } catch (\Exception $exception) {
+            $this->listen = false;
+            $this->message = $exception->getMessage();
+        }
+        $this->title = '系统任务管理';
+        $this->iswin = ProcessService::instance()->iswin();
+        $query = $this->_query($this->table)->dateBetween('create_at,start_at,end_at');
+        $query->like('title,preload')->equal('status')->order('id desc')->page();
+    }
+
+    /**
+     * 重启系统任务
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function redo()
+    {
+        $this->_save($this->table, ['status' => '1']);
+    }
+
+    /**
+     * WIN开始监听任务
+     * @auth true
+     */
+    public function start()
+    {
+        try {
+            $message = nl2br(Console::call('xtask:start')->fetch());
+            if (preg_match('/process.*?\d+/', $message, $attr)) {
+                $this->success('任务监听主进程启动成功!');
+            } else {
+                $this->error($message);
+            }
+        } catch (HttpResponseException $exception) {
+            throw $exception;
+        } catch (\Exception $e) {
+            $this->error($e->getMessage());
+        }
+    }
+
+    /**
+     * WIN停止监听任务
+     * @auth true
+     */
+    public function stop()
+    {
+        try {
+            $message = nl2br(Console::call('xtask:stop')->fetch());
+            if (stripos($message, 'succeeded')) {
+                $this->success('停止任务监听主进程成功!');
+            } elseif (stripos($message, 'finish')) {
+                $this->success('没有找到需要停止的进程!');
+            } else {
+                $this->error($message);
+            }
+        } catch (HttpResponseException $exception) {
+            throw $exception;
+        } catch (\Exception $e) {
+            $this->error($e->getMessage());
+        }
+    }
+
+    /**
+     * 清理3天前的记录
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function clear()
+    {
+        $map = [['time', '<', strtotime('-3days')]];
+        $result = Db::name($this->table)->where($map)->delete();
+        if ($result !== false) {
+            $this->success('成功清理3天前的任务记录!');
+        } else {
+            $this->error('清理3天前的任务记录失败!');
+        }
+    }
+
+    /**
+     * 删除系统任务
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function remove()
+    {
+        $this->_delete($this->table);
+    }
+
+}

+ 173 - 0
application/admin/controller/User.php

@@ -0,0 +1,173 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\admin\controller;
+
+use library\Controller;
+use library\tools\Data;
+use think\Db;
+
+/**
+ * 系统用户管理
+ * Class User
+ * @package app\admin\controller
+ */
+class User extends Controller
+{
+
+    /**
+     * 指定当前数据表
+     * @var string
+     */
+    public $table = 'SystemUser';
+
+    /**
+     * 系统用户管理
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        $this->title = '系统用户管理';
+        $query = $this->_query($this->table)->like('username,phone,mail')->equal('status');
+        $query->dateBetween('login_at,create_at')->where(['is_deleted' => '0'])->order('id desc')->page();
+    }
+
+    /**
+     * 添加系统用户
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function add()
+    {
+        $this->applyCsrfToken();
+        $this->_form($this->table, 'form');
+    }
+
+    /**
+     * 编辑系统用户
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function edit()
+    {
+        $this->applyCsrfToken();
+        $this->_form($this->table, 'form');
+    }
+
+    /**
+     * 修改用户密码
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function pass()
+    {
+        $this->applyCsrfToken();
+        if ($this->request->isGet()) {
+            $this->verify = false;
+            $this->_form($this->table, 'pass');
+        } else {
+            $post = $this->request->post();
+            if ($post['password'] !== $post['repassword']) {
+                $this->error('两次输入的密码不一致!');
+            }
+            if (Data::save($this->table, ['id' => $post['id'], 'password' => md5($post['password'])], 'id')) {
+                $this->success('密码修改成功,下次请使用新密码登录!', '');
+            } else {
+                $this->error('密码修改失败,请稍候再试!');
+            }
+        }
+    }
+
+    /**
+     * 表单数据处理
+     * @param array $data
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function _form_filter(&$data)
+    {
+        if ($this->request->isPost()) {
+            // 用户权限处理
+            $data['authorize'] = (isset($data['authorize']) && is_array($data['authorize'])) ? join(',', $data['authorize']) : '';
+            // 用户账号重复检查
+            if (isset($data['id'])) unset($data['username']);
+            elseif (Db::name($this->table)->where(['username' => $data['username'], 'is_deleted' => '0'])->count() > 0) {
+                $this->error("账号{$data['username']}已经存在,请使用其它账号!");
+            }
+        } else {
+            $data['authorize'] = explode(',', isset($data['authorize']) ? $data['authorize'] : '');
+            $this->authorizes = Db::name('SystemAuth')->where(['status' => '1'])->order('sort desc,id desc')->select();
+        }
+    }
+
+    /**
+     * 禁用系统用户
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function forbid()
+    {
+        if (in_array('10000', explode(',', $this->request->post('id')))) {
+            $this->error('系统超级账号禁止操作!');
+        }
+        $this->applyCsrfToken();
+        $this->_save($this->table, ['status' => '0']);
+    }
+
+    /**
+     * 启用系统用户
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function resume()
+    {
+        $this->applyCsrfToken();
+        $this->_save($this->table, ['status' => '1']);
+    }
+
+    /**
+     * 删除系统用户
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function remove()
+    {
+        if (in_array('10000', explode(',', $this->request->post('id')))) {
+            $this->error('系统超级账号禁止删除!');
+        }
+        $this->applyCsrfToken();
+        $this->_delete($this->table);
+    }
+
+}

+ 130 - 0
application/admin/controller/api/Plugs.php

@@ -0,0 +1,130 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\admin\controller\api;
+
+use library\Controller;
+use library\File;
+
+/**
+ * 后台插件管理
+ * Class Plugs
+ * @package app\admin\controller\api
+ */
+class Plugs extends Controller
+{
+
+    /**
+     * 系统图标选择器
+     */
+    public function icon()
+    {
+        $this->title = '图标选择器';
+        $this->field = input('field', 'icon');
+        $this->fetch();
+    }
+
+    /**
+     * 获取文件上传参数
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function check()
+    {
+        $diff1 = explode(',', strtolower(input('exts', '')));
+        $diff2 = explode(',', strtolower(sysconf('storage_local_exts')));
+        $exts = array_intersect($diff1, $diff2);
+        $this->success('获取文件上传参数', [
+            'exts' => join('|', $exts),
+            'mime' => File::mine($exts),
+            'type' => $this->getUploadType(),
+            'data' => $this->getUploadData(),
+        ]);
+    }
+
+    /**
+     * 后台通用文件上传
+     * @login true
+     * @return \think\response\Json
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function upload()
+    {
+        if (!($file = $this->getUploadFile()) || empty($file)) {
+            return json(['uploaded' => false, 'error' => ['message' => '文件上传异常,文件可能过大或未上传']]);
+        }
+        if (!$file->checkExt(strtolower(sysconf('storage_local_exts')))) {
+            return json(['uploaded' => false, 'error' => ['message' => '文件上传类型受限,请在后台配置']]);
+        }
+        if ($file->checkExt('php,sh')) {
+            return json(['uploaded' => false, 'error' => ['message' => '可执行文件禁止上传到本地服务器']]);
+        }
+        $this->safe = boolval(input('safe'));
+        $this->uptype = $this->getUploadType();
+        $this->extend = pathinfo($file->getInfo('name'), PATHINFO_EXTENSION);
+        $name = File::name($file->getPathname(), $this->extend, '', 'md5_file');
+        $info = File::instance($this->uptype)->save($name, file_get_contents($file->getRealPath()), $this->safe);
+        if (is_array($info) && isset($info['url'])) {
+            return json(['uploaded' => true, 'filename' => $name, 'url' => $this->safe ? $name : $info['url']]);
+        } else {
+            return json(['uploaded' => false, 'error' => ['message' => '文件处理失败,请稍候再试!']]);
+        }
+    }
+
+    /**
+     * 生成文件上传参数
+     * @return array
+     * @throws \think\Exception
+     */
+    private function getUploadData()
+    {
+        if ($this->getUploadType() === 'qiniu') {
+            $file = File::instance('qiniu');
+            return ['url' => $file->upload(true), 'token' => $file->buildUploadToken(), 'uptype' => $this->getUploadType()];
+        } else {
+            return ['url' => '?s=admin/api.plugs/upload', 'token' => uniqid('local_upload_'), 'uptype' => $this->getUploadType()];
+        }
+    }
+
+    /**
+     * 获取文件上传方式
+     * @return string
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    private function getUploadType()
+    {
+        $this->uptype = input('uptype');
+        if (!in_array($this->uptype, ['local', 'oss', 'qiniu'])) {
+            $this->uptype = sysconf('storage_type');
+        }
+        return $this->uptype;
+    }
+
+    /**
+     * 获取本地文件对象
+     * @return \think\File
+     */
+    private function getUploadFile()
+    {
+        try {
+            return $this->request->file('file');
+        } catch (\Exception $e) {
+            $this->error(lang($e->getMessage()));
+        }
+    }
+
+}

+ 65 - 0
application/admin/controller/api/Update.php

@@ -0,0 +1,65 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\admin\controller\api;
+
+use library\command\Sync;
+use library\Controller;
+
+/**
+ * 系统更新接口
+ * Class Update
+ * @package app\admin\controller\api
+ */
+class Update extends Controller
+{
+    /**
+     * 访问权限
+     */
+    protected function initialize()
+    {
+        $domain = $this->app->request->host(true);
+        $isDemo = is_numeric(stripos($domain, 'thinkadmin.top'));
+        $isLocal = in_array($domain, ['127.0.0.1', 'localhost']);
+        if (!$isLocal && !$isDemo) $this->error('只允许访问本地或官方代码!');
+    }
+
+    /**
+     * 获取文件列表
+     */
+    public function tree()
+    {
+        $sync = new Sync('Update');
+        $this->success('获取当前文件列表成功!', $sync->build());
+    }
+
+    /**
+     * 读取线上文件数据
+     * @param string $encode
+     */
+    public function read($encode)
+    {
+        $this->file = env('root_path') . decode($encode);
+        if (file_exists($this->file)) {
+            $this->success('读取文件成功!', [
+                'format'  => 'base64',
+                'content' => base64_encode(file_get_contents($this->file)),
+            ]);
+        } else {
+            $this->error('获取文件内容失败!');
+        }
+    }
+
+}

+ 159 - 0
application/admin/sys.php

@@ -0,0 +1,159 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+use library\File;
+use library\service\AdminService;
+use library\service\CaptchaService;
+use library\service\SystemService;
+use think\Db;
+use think\facade\Middleware;
+use think\facade\Route;
+use think\Request;
+
+if (!function_exists('auth')) {
+    /**
+     * 节点访问权限检查
+     * @param string $node 需要检查的节点
+     * @return boolean
+     * @throws ReflectionException
+     */
+    function auth($node)
+    {
+        return AdminService::instance()->check($node);
+    }
+}
+
+if (!function_exists('sysdata')) {
+    /**
+     * JSON 数据读取与存储
+     * @param string $name 数据名称
+     * @param mixed $value 数据内容
+     * @return mixed
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    function sysdata($name, $value = null)
+    {
+        if (is_null($value)) {
+            return SystemService::instance()->getData($name);
+        } else {
+            return SystemService::instance()->setData($name, $value);
+        }
+    }
+}
+
+if (!function_exists('sysoplog')) {
+    /**
+     * 写入系统日志
+     * @param string $action 日志行为
+     * @param string $content 日志内容
+     * @return boolean
+     */
+    function sysoplog($action, $content)
+    {
+        return SystemService::instance()->setOplog($action, $content);
+    }
+}
+
+if (!function_exists('sysqueue')) {
+    /**
+     * 创建异步处理任务
+     * @param string $title 任务名称
+     * @param string $loade 执行内容
+     * @param integer $later 延时执行时间
+     * @param array $data 任务附加数据
+     * @param integer $double 任务多开
+     * @return boolean
+     * @throws \think\Exception
+     */
+    function sysqueue($title, $loade, $later = 0, $data = [], $double = 1)
+    {
+        $map = [['title', 'eq', $title], ['status', 'in', [1, 2]]];
+        if (empty($double) && Db::name('SystemQueue')->where($map)->count() > 0) {
+            throw new \think\Exception('该任务已经创建,请耐心等待处理完成!');
+        }
+        $result = Db::name('SystemQueue')->insert([
+            'title'  => $title, 'preload' => $loade,
+            'data'   => json_encode($data, JSON_UNESCAPED_UNICODE),
+            'time'   => $later > 0 ? time() + $later : time(),
+            'double' => intval($double), 'create_at' => date('Y-m-d H:i:s'),
+        ]);
+        return $result !== false;
+    }
+}
+
+if (!function_exists('local_image')) {
+    /**
+     * 下载远程文件到本地
+     * @param string $url 远程图片地址
+     * @param boolean $force 是否强制重新下载
+     * @param integer $expire 强制本地存储时间
+     * @return string
+     */
+    function local_image($url, $force = false, $expire = 0)
+    {
+        $result = File::down($url, $force, $expire);
+        if (isset($result['url'])) {
+            return $result['url'];
+        } else {
+            return $url;
+        }
+    }
+}
+
+if (!function_exists('base64_image')) {
+    /**
+     * base64 图片上传接口
+     * @param string $content 图片base64内容
+     * @param string $dirname 图片存储目录
+     * @return string
+     */
+    function base64_image($content, $dirname = 'base64/')
+    {
+        try {
+            if (preg_match('|^data:image/(.*?);base64,|i', $content)) {
+                list($ext, $base) = explode('|||', preg_replace('|^data:image/(.*?);base64,|i', '$1|||', $content));
+                $info = File::save($dirname . md5($base) . '.' . (empty($ext) ? 'tmp' : $ext), base64_decode($base));
+                return $info['url'];
+            } else {
+                return $content;
+            }
+        } catch (\Exception $e) {
+            return $content;
+        }
+    }
+}
+
+// 访问权限检查中间键
+Middleware::add(function (Request $request, \Closure $next) {
+    if (AdminService::instance()->check()) {
+        return $next($request);
+    } elseif (AdminService::instance()->isLogin()) {
+        return json(['code' => 0, 'msg' => '抱歉,没有访问该操作的权限!']);
+    } else {
+        return json(['code' => 0, 'msg' => '抱歉,需要登录获取访问权限!', 'url' => url('@admin/login')]);
+    }
+});
+
+// ThinkAdmin 图形验证码
+Route::get('/think/admin/captcha', function () {
+    $image = CaptchaService::instance();
+    return json(['code' => '1', 'info' => '生成验证码', 'data' => [
+        'uniqid' => $image->getUniqid(), 'image' => $image->getData()
+    ]]);
+});

+ 3659 - 0
application/admin/view/api/plugs/icon.html

@@ -0,0 +1,3659 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="utf-8">
+    <title>{block name="title"}{$title|default=''}{if !empty($title)} · {/if}{:sysconf('site_name')}{/block}</title>
+    <meta name="renderer" content="webkit">
+    <meta name="format-detection" content="telephone=no">
+    <meta name="apple-mobile-web-app-capable" content="yes">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="apple-mobile-web-app-status-bar-style" content="black">
+    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
+    <link href="__ROOT__/static/plugs/awesome/fonts.css?v={:date('ymd')}" rel="stylesheet">
+    <link href="__ROOT__/static/plugs/layui/css/layui.css?v={:date('ymd')}" rel="stylesheet">
+
+    <style>
+        ::-webkit-input-placeholder {
+            color: #aaa
+        }
+
+        ::-webkit-scrollbar {
+            width: 3px;
+            height: 3px
+        }
+
+        ::-webkit-scrollbar-track {
+            background: #ccc
+        }
+
+        ::-webkit-scrollbar-thumb {
+            background-color: #666
+        }
+
+        ::selection {
+            background-color: #ec494e;
+            color: #fff
+        }
+
+        ::-moz-selection {
+            background-color: #ec494e;
+            color: #fff
+        }
+
+        :-webkit-autofill {
+            -webkit-box-shadow: 0 0 0 1000px white inset;
+            -webkit-text-fill-color: #333
+        }
+
+        ul li {
+            width: 20%;
+            height: 65px;
+            display: block;
+            float: left;
+            margin-right: -1px;
+            margin-left: -2px;
+            margin-bottom: -2px;
+            cursor: pointer;
+            font-size: 14px;
+            overflow: hidden;
+            text-align: center;
+            padding: 15px 0 10px 0;
+            border: 1px solid #e2e2e2;
+            background-color: #efefef;
+            user-select: none;
+            -ms-user-select: none;
+            -moz-user-select: none;
+            -webkit-user-select: none;
+            transition: all .2s linear;
+            -o-transition: all .2s linear;
+            -moz-transition: all .2s linear;
+            -webkit-transition: all .2s linear
+        }
+
+        ul li:hover {
+            color: #fff;
+            background-color: #563d7c
+        }
+
+        ul li:hover i, ul li:hover div {
+            color: #fff;
+        }
+
+        ul li i {
+            color: #333;
+            display: inline-block;
+            font-size: 30px !important
+        }
+
+        ul li div {
+            color: #333;
+            height: 35px;
+            font-size: 13px;
+            line-height: 35px;
+            white-space: nowrap
+        }
+    </style>
+</head>
+<body>
+<ul class="site-doc-icon">
+    <li>
+        <i class="layui-icon layui-icon-rate-half"></i>
+        <div class="icon-title">layui-icon-rate-half</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-rate"></i>
+        <div class="icon-title">layui-icon-rate</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-rate-solid"></i>
+        <div class="icon-title">layui-icon-rate-solid</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-cellphone"></i>
+        <div class="icon-title">layui-icon-cellphone</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-vercode"></i>
+        <div class="icon-title">layui-icon-vercode</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-login-wechat"></i>
+        <div class="icon-title">layui-icon-login-wechat</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-login-qq"></i>
+        <div class="icon-title">layui-icon-login-qq</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-login-weibo"></i>
+        <div class="icon-title">layui-icon-login-weibo</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-password"></i>
+        <div class="icon-title">layui-icon-password</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-username"></i>
+        <div class="icon-title">layui-icon-username</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-refresh-3"></i>
+        <div class="icon-title">layui-icon-refresh-3</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-auz"></i>
+        <div class="icon-title">layui-icon-auz</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-spread-left"></i>
+        <div class="icon-title">layui-icon-spread-left</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-shrink-right"></i>
+        <div class="icon-title">layui-icon-shrink-right</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-snowflake"></i>
+        <div class="icon-title">layui-icon-snowflake</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-tips"></i>
+        <div class="icon-title">layui-icon-tips</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-note"></i>
+        <div class="icon-title">layui-icon-note</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-home"></i>
+        <div class="icon-title">layui-icon-home</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-senior"></i>
+        <div class="icon-title">layui-icon-senior</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-refresh"></i>
+        <div class="icon-title">layui-icon-refresh</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-refresh-1"></i>
+        <div class="icon-title">layui-icon-refresh-1</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-flag"></i>
+        <div class="icon-title">layui-icon-flag</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-theme"></i>
+        <div class="icon-title">layui-icon-theme</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-notice"></i>
+        <div class="icon-title">layui-icon-notice</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-website"></i>
+        <div class="icon-title">layui-icon-website</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-console"></i>
+        <div class="icon-title">layui-icon-console</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-face-surprised"></i>
+        <div class="icon-title">layui-icon-face-surprised</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-set"></i>
+        <div class="icon-title">layui-icon-set</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-template-1"></i>
+        <div class="icon-title">layui-icon-template-1</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-app"></i>
+        <div class="icon-title">layui-icon-app</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-template"></i>
+        <div class="icon-title">layui-icon-template</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-praise"></i>
+        <div class="icon-title">layui-icon-praise</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-tread"></i>
+        <div class="icon-title">layui-icon-tread</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-male"></i>
+        <div class="icon-title">layui-icon-male</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-female"></i>
+        <div class="icon-title">layui-icon-female</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-camera"></i>
+        <div class="icon-title">layui-icon-camera</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-camera-fill"></i>
+        <div class="icon-title">layui-icon-camera-fill</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-more"></i>
+        <div class="icon-title">layui-icon-more</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-more-vertical"></i>
+        <div class="icon-title">layui-icon-more-vertical</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-rmb"></i>
+        <div class="icon-title">layui-icon-rmb</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-dollar"></i>
+        <div class="icon-title">layui-icon-dollar</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-diamond"></i>
+        <div class="icon-title">layui-icon-diamond</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-fire"></i>
+        <div class="icon-title">layui-icon-fire</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-return"></i>
+        <div class="icon-title">layui-icon-return</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-location"></i>
+        <div class="icon-title">layui-icon-location</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-read"></i>
+        <div class="icon-title">layui-icon-read</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-survey"></i>
+        <div class="icon-title">layui-icon-survey</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-face-smile"></i>
+        <div class="icon-title">layui-icon-face-smile</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-face-cry"></i>
+        <div class="icon-title">layui-icon-face-cry</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-cart-simple"></i>
+        <div class="icon-title">layui-icon-cart-simple</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-cart"></i>
+        <div class="icon-title">layui-icon-cart</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-next"></i>
+        <div class="icon-title">layui-icon-next</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-prev"></i>
+        <div class="icon-title">layui-icon-prev</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-upload-drag"></i>
+        <div class="icon-title">layui-icon-upload-drag</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-upload"></i>
+        <div class="icon-title">layui-icon-upload</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-download-circle"></i>
+        <div class="icon-title">layui-icon-download-circle</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-component"></i>
+        <div class="icon-title">layui-icon-component</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-file-b"></i>
+        <div class="icon-title">layui-icon-file-b</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-user"></i>
+        <div class="icon-title">layui-icon-user</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-find-fill"></i>
+        <div class="icon-title">layui-icon-find-fill</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-loading layui-icon layui-anim layui-anim-rotate layui-anim-loop"></i>
+        <div class="icon-title">layui-icon-loading</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-loading-1 layui-icon layui-anim layui-anim-rotate layui-anim-loop"></i>
+        <div class="icon-title">layui-icon-loading-1</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-add-1"></i>
+        <div class="icon-title">layui-icon-add-1</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-play"></i>
+        <div class="icon-title">layui-icon-play</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-pause"></i>
+        <div class="icon-title">layui-icon-pause</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-headset"></i>
+        <div class="icon-title">layui-icon-headset</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-video"></i>
+        <div class="icon-title">layui-icon-video</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-voice"></i>
+        <div class="icon-title">layui-icon-voice</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-speaker"></i>
+        <div class="icon-title">layui-icon-speaker</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-fonts-del"></i>
+        <div class="icon-title">layui-icon-fonts-del</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-fonts-code"></i>
+        <div class="icon-title">layui-icon-fonts-code</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-fonts-html"></i>
+        <div class="icon-title">layui-icon-fonts-html</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-fonts-strong"></i>
+        <div class="icon-title">layui-icon-fonts-strong</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-unlink"></i>
+        <div class="icon-title">layui-icon-unlink</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-picture"></i>
+        <div class="icon-title">layui-icon-picture</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-link"></i>
+        <div class="icon-title">layui-icon-link</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-face-smile-b"></i>
+        <div class="icon-title">layui-icon-face-smile-b</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-align-left"></i>
+        <div class="icon-title">layui-icon-align-left</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-align-right"></i>
+        <div class="icon-title">layui-icon-align-right</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-align-center"></i>
+        <div class="icon-title">layui-icon-align-center</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-fonts-u"></i>
+        <div class="icon-title">layui-icon-fonts-u</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-fonts-i"></i>
+        <div class="icon-title">layui-icon-fonts-i</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-tabs"></i>
+        <div class="icon-title">layui-icon-tabs</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-radio"></i>
+        <div class="icon-title">layui-icon-radio</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-circle"></i>
+        <div class="icon-title">layui-icon-circle</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-edit"></i>
+        <div class="icon-title">layui-icon-edit</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-share"></i>
+        <div class="icon-title">layui-icon-share</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-delete"></i>
+        <div class="icon-title">layui-icon-delete</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-form"></i>
+        <div class="icon-title">layui-icon-form</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-cellphone-fine"></i>
+        <div class="icon-title">layui-icon-cellphone-fine</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-dialogue"></i>
+        <div class="icon-title">layui-icon-dialogue</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-fonts-clear"></i>
+        <div class="icon-title">layui-icon-fonts-clear</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-layer"></i>
+        <div class="icon-title">layui-icon-layer</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-date"></i>
+        <div class="icon-title">layui-icon-date</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-water"></i>
+        <div class="icon-title">layui-icon-water</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-code-circle"></i>
+        <div class="icon-title">layui-icon-code-circle</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-carousel"></i>
+        <div class="icon-title">layui-icon-carousel</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-prev-circle"></i>
+        <div class="icon-title">layui-icon-prev-circle</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-layouts"></i>
+        <div class="icon-title">layui-icon-layouts</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-util"></i>
+        <div class="icon-title">layui-icon-util</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-templeate-1"></i>
+        <div class="icon-title">layui-icon-templeate-1</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-upload-circle"></i>
+        <div class="icon-title">layui-icon-upload-circle</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-tree"></i>
+        <div class="icon-title">layui-icon-tree</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-table"></i>
+        <div class="icon-title">layui-icon-table</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-chart"></i>
+        <div class="icon-title">layui-icon-chart</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-chart-screen"></i>
+        <div class="icon-title">layui-icon-chart-screen</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-engine"></i>
+        <div class="icon-title">layui-icon-engine</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-triangle-d"></i>
+        <div class="icon-title">layui-icon-triangle-d</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-triangle-r"></i>
+        <div class="icon-title">layui-icon-triangle-r</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-file"></i>
+        <div class="icon-title">layui-icon-file</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-set-sm"></i>
+        <div class="icon-title">layui-icon-set-sm</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-add-circle"></i>
+        <div class="icon-title">layui-icon-add-circle</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-404"></i>
+        <div class="icon-title">layui-icon-404</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-about"></i>
+        <div class="icon-title">layui-icon-about</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-up"></i>
+        <div class="icon-title">layui-icon-up</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-down"></i>
+        <div class="icon-title">layui-icon-down</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-left"></i>
+        <div class="icon-title">layui-icon-left</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-right"></i>
+        <div class="icon-title">layui-icon-right</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-circle-dot"></i>
+        <div class="icon-title">layui-icon-circle-dot</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-search"></i>
+        <div class="icon-title">layui-icon-search</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-set-fill"></i>
+        <div class="icon-title">layui-icon-set-fill</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-group"></i>
+        <div class="icon-title">layui-icon-group</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-friends"></i>
+        <div class="icon-title">layui-icon-friends</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-reply-fill"></i>
+        <div class="icon-title">layui-icon-reply-fill</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-menu-fill"></i>
+        <div class="icon-title">layui-icon-menu-fill</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-log"></i>
+        <div class="icon-title">layui-icon-log</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-picture-fine"></i>
+        <div class="icon-title">layui-icon-picture-fine</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-face-smile-fine"></i>
+        <div class="icon-title">layui-icon-face-smile-fine</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-list"></i>
+        <div class="icon-title">layui-icon-list</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-release"></i>
+        <div class="icon-title">layui-icon-release</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-ok"></i>
+        <div class="icon-title">layui-icon-ok</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-help"></i>
+        <div class="icon-title">layui-icon-help</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-chat"></i>
+        <div class="icon-title">layui-icon-chat</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-top"></i>
+        <div class="icon-title">layui-icon-top</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-star"></i>
+        <div class="icon-title">layui-icon-star</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-star-fill"></i>
+        <div class="icon-title">layui-icon-star-fill</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-close-fill"></i>
+        <div class="icon-title">layui-icon-close-fill</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-close"></i>
+        <div class="icon-title">layui-icon-close</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-ok-circle"></i>
+        <div class="icon-title">layui-icon-ok-circle</div>
+    </li>
+    <li>
+        <i class="layui-icon layui-icon-add-circle-fine"></i>
+        <div class="icon-title">layui-icon-add-circle-fine</div>
+    </li>
+</ul>
+<ul>
+    <li>
+        <i class="fa fa-address-book"></i>
+        <div class="icon-title">fa-address-book</div>
+    </li>
+    <li>
+        <i class="fa fa-address-book-o"></i>
+        <div class="icon-title">fa-address-book-o</div>
+    </li>
+    <li>
+        <i class="fa fa-address-card"></i>
+        <div class="icon-title">fa-address-card</div>
+    </li>
+    <li>
+        <i class="fa fa-address-card-o"></i>
+        <div class="icon-title">fa-address-card-o</div>
+    </li>
+    <li>
+        <i class="fa fa-adjust"></i>
+        <div class="icon-title">fa-adjust</div>
+    </li>
+    <li>
+        <i class="fa fa-american-sign-language-interpreting"></i>
+        <div class="icon-title">fa-american-sign-language-interpreting</div>
+    </li>
+    <li>
+        <i class="fa fa-anchor"></i>
+        <div class="icon-title">fa-anchor</div>
+    </li>
+    <li>
+        <i class="fa fa-archive"></i>
+        <div class="icon-title">fa-archive</div>
+    </li>
+    <li>
+        <i class="fa fa-area-chart"></i>
+        <div class="icon-title">fa-area-chart</div>
+    </li>
+    <li>
+        <i class="fa fa-arrows"></i>
+        <div class="icon-title">fa-arrows</div>
+    </li>
+    <li>
+        <i class="fa fa-arrows-h"></i>
+        <div class="icon-title">fa-arrows-h</div>
+    </li>
+    <li>
+        <i class="fa fa-arrows-v"></i>
+        <div class="icon-title">fa-arrows-v</div>
+    </li>
+    <li>
+        <i class="fa fa-asl-interpreting"></i>
+        <div class="icon-title">fa-asl-interpreting</div>
+    </li>
+    <li>
+        <i class="fa fa-assistive-listening-systems"></i>
+        <div class="icon-title">fa-assistive-listening-systems</div>
+    </li>
+    <li>
+        <i class="fa fa-asterisk"></i>
+        <div class="icon-title">fa-asterisk</div>
+    </li>
+    <li>
+        <i class="fa fa-at"></i>
+        <div class="icon-title">fa-at</div>
+    </li>
+    <li>
+        <i class="fa fa-audio-description"></i>
+        <div class="icon-title">fa-audio-description</div>
+    </li>
+    <li>
+        <i class="fa fa-automobile"></i>
+        <div class="icon-title">fa-automobile</div>
+    </li>
+    <li>
+        <i class="fa fa-balance-scale"></i>
+        <div class="icon-title">fa-balance-scale</div>
+    </li>
+    <li>
+        <i class="fa fa-ban"></i>
+        <div class="icon-title">fa-ban</div>
+    </li>
+    <li>
+        <i class="fa fa-bank"></i>
+        <div class="icon-title">fa-bank</div>
+    </li>
+    <li>
+        <i class="fa fa-bar-chart"></i>
+        <div class="icon-title">fa-bar-chart</div>
+    </li>
+    <li>
+        <i class="fa fa-bar-chart-o"></i>
+        <div class="icon-title">fa-bar-chart-o</div>
+    </li>
+    <li>
+        <i class="fa fa-barcode"></i>
+        <div class="icon-title">fa-barcode</div>
+    </li>
+    <li>
+        <i class="fa fa-bars"></i>
+        <div class="icon-title">fa-bars</div>
+    </li>
+    <li>
+        <i class="fa fa-bath"></i>
+        <div class="icon-title">fa-bath</div>
+    </li>
+    <li>
+        <i class="fa fa-bathtub"></i>
+        <div class="icon-title">fa-bathtub</div>
+    </li>
+    <li>
+        <i class="fa fa-battery"></i>
+        <div class="icon-title">fa-battery</div>
+    </li>
+    <li>
+        <i class="fa fa-battery-0"></i>
+        <div class="icon-title">fa-battery-0</div>
+    </li>
+    <li>
+        <i class="fa fa-battery-1"></i>
+        <div class="icon-title">fa-battery-1</div>
+    </li>
+    <li>
+        <i class="fa fa-battery-2"></i>
+        <div class="icon-title">fa-battery-2</div>
+    </li>
+    <li>
+        <i class="fa fa-battery-3"></i>
+        <div class="icon-title">fa-battery-3</div>
+    </li>
+    <li>
+        <i class="fa fa-battery-4"></i>
+        <div class="icon-title">fa-battery-4</div>
+    </li>
+    <li>
+        <i class="fa fa-battery-empty"></i>
+        <div class="icon-title">fa-battery-empty</div>
+    </li>
+    <li>
+        <i class="fa fa-battery-full"></i>
+        <div class="icon-title">fa-battery-full</div>
+    </li>
+    <li>
+        <i class="fa fa-battery-half"></i>
+        <div class="icon-title">fa-battery-half</div>
+    </li>
+    <li>
+        <i class="fa fa-battery-quarter"></i>
+        <div class="icon-title">fa-battery-quarter</div>
+    </li>
+    <li>
+        <i class="fa fa-battery-three-quarters"></i>
+        <div class="icon-title">fa-battery-three-quarters</div>
+    </li>
+    <li>
+        <i class="fa fa-bed"></i>
+        <div class="icon-title">fa-bed</div>
+    </li>
+    <li>
+        <i class="fa fa-beer"></i>
+        <div class="icon-title">fa-beer</div>
+    </li>
+    <li>
+        <i class="fa fa-bell"></i>
+        <div class="icon-title">fa-bell</div>
+    </li>
+    <li>
+        <i class="fa fa-bell-o"></i>
+        <div class="icon-title">fa-bell-o</div>
+    </li>
+    <li>
+        <i class="fa fa-bell-slash"></i>
+        <div class="icon-title">fa-bell-slash</div>
+    </li>
+    <li>
+        <i class="fa fa-bell-slash-o"></i>
+        <div class="icon-title">fa-bell-slash-o</div>
+    </li>
+    <li>
+        <i class="fa fa-bicycle"></i>
+        <div class="icon-title">fa-bicycle</div>
+    </li>
+    <li>
+        <i class="fa fa-binoculars"></i>
+        <div class="icon-title">fa-binoculars</div>
+    </li>
+    <li>
+        <i class="fa fa-birthday-cake"></i>
+        <div class="icon-title">fa-birthday-cake</div>
+    </li>
+    <li>
+        <i class="fa fa-blind"></i>
+        <div class="icon-title">fa-blind</div>
+    </li>
+    <li>
+        <i class="fa fa-bluetooth"></i>
+        <div class="icon-title">fa-bluetooth</div>
+    </li>
+    <li>
+        <i class="fa fa-bluetooth-b"></i>
+        <div class="icon-title">fa-bluetooth-b</div>
+    </li>
+    <li>
+        <i class="fa fa-bolt"></i>
+        <div class="icon-title">fa-bolt</div>
+    </li>
+    <li>
+        <i class="fa fa-bomb"></i>
+        <div class="icon-title">fa-bomb</div>
+    </li>
+    <li>
+        <i class="fa fa-book"></i>
+        <div class="icon-title">fa-book</div>
+    </li>
+    <li>
+        <i class="fa fa-bookmark"></i>
+        <div class="icon-title">fa-bookmark</div>
+    </li>
+    <li>
+        <i class="fa fa-bookmark-o"></i>
+        <div class="icon-title">fa-bookmark-o</div>
+    </li>
+    <li>
+        <i class="fa fa-braille"></i>
+        <div class="icon-title">fa-braille</div>
+    </li>
+    <li>
+        <i class="fa fa-briefcase"></i>
+        <div class="icon-title">fa-briefcase</div>
+    </li>
+    <li>
+        <i class="fa fa-bug"></i>
+        <div class="icon-title">fa-bug</div>
+    </li>
+    <li>
+        <i class="fa fa-building"></i>
+        <div class="icon-title">fa-building</div>
+    </li>
+    <li>
+        <i class="fa fa-building-o"></i>
+        <div class="icon-title">fa-building-o</div>
+    </li>
+    <li>
+        <i class="fa fa-bullhorn"></i>
+        <div class="icon-title">fa-bullhorn</div>
+    </li>
+    <li>
+        <i class="fa fa-bullseye"></i>
+        <div class="icon-title">fa-bullseye</div>
+    </li>
+    <li>
+        <i class="fa fa-bus"></i>
+        <div class="icon-title">fa-bus</div>
+    </li>
+    <li>
+        <i class="fa fa-cab"></i>
+        <div class="icon-title">fa-cab</div>
+    </li>
+    <li>
+        <i class="fa fa-calculator"></i>
+        <div class="icon-title">fa-calculator</div>
+    </li>
+    <li>
+        <i class="fa fa-calendar"></i>
+        <div class="icon-title">fa-calendar</div>
+    </li>
+    <li>
+        <i class="fa fa-calendar-check-o"></i>
+        <div class="icon-title">fa-calendar-check-o</div>
+    </li>
+    <li>
+        <i class="fa fa-calendar-minus-o"></i>
+        <div class="icon-title">fa-calendar-minus-o</div>
+    </li>
+    <li>
+        <i class="fa fa-calendar-o"></i>
+        <div class="icon-title">fa-calendar-o</div>
+    </li>
+    <li>
+        <i class="fa fa-calendar-plus-o"></i>
+        <div class="icon-title">fa-calendar-plus-o</div>
+    </li>
+    <li>
+        <i class="fa fa-calendar-times-o"></i>
+        <div class="icon-title">fa-calendar-times-o</div>
+    </li>
+    <li>
+        <i class="fa fa-camera"></i>
+        <div class="icon-title">fa-camera</div>
+    </li>
+    <li>
+        <i class="fa fa-camera-retro"></i>
+        <div class="icon-title">fa-camera-retro</div>
+    </li>
+    <li>
+        <i class="fa fa-car"></i>
+        <div class="icon-title">fa-car</div>
+    </li>
+    <li>
+        <i class="fa fa-caret-square-o-down"></i>
+        <div class="icon-title">fa-caret-square-o-down</div>
+    </li>
+    <li>
+        <i class="fa fa-caret-square-o-left"></i>
+        <div class="icon-title">fa-caret-square-o-left</div>
+    </li>
+    <li>
+        <i class="fa fa-caret-square-o-right"></i>
+        <div class="icon-title">fa-caret-square-o-right</div>
+    </li>
+    <li>
+        <i class="fa fa-caret-square-o-up"></i>
+        <div class="icon-title">fa-caret-square-o-up</div>
+    </li>
+    <li>
+        <i class="fa fa-cart-arrow-down"></i>
+        <div class="icon-title">fa-cart-arrow-down</div>
+    </li>
+    <li>
+        <i class="fa fa-cart-plus"></i>
+        <div class="icon-title">fa-cart-plus</div>
+    </li>
+    <li>
+        <i class="fa fa-cc"></i>
+        <div class="icon-title">fa-cc</div>
+    </li>
+    <li>
+        <i class="fa fa-certificate"></i>
+        <div class="icon-title">fa-certificate</div>
+    </li>
+    <li>
+        <i class="fa fa-check"></i>
+        <div class="icon-title">fa-check</div>
+    </li>
+    <li>
+        <i class="fa fa-check-circle"></i>
+        <div class="icon-title">fa-check-circle</div>
+    </li>
+    <li>
+        <i class="fa fa-check-circle-o"></i>
+        <div class="icon-title">fa-check-circle-o</div>
+    </li>
+    <li>
+        <i class="fa fa-check-square"></i>
+        <div class="icon-title">fa-check-square</div>
+    </li>
+    <li>
+        <i class="fa fa-check-square-o"></i>
+        <div class="icon-title">fa-check-square-o</div>
+    </li>
+    <li>
+        <i class="fa fa-child"></i>
+        <div class="icon-title">fa-child</div>
+    </li>
+    <li>
+        <i class="fa fa-circle"></i>
+        <div class="icon-title">fa-circle</div>
+    </li>
+    <li>
+        <i class="fa fa-circle-o"></i>
+        <div class="icon-title">fa-circle-o</div>
+    </li>
+    <li>
+        <i class="fa fa-circle-o-notch"></i>
+        <div class="icon-title">fa-circle-o-notch</div>
+    </li>
+    <li>
+        <i class="fa fa-circle-thin"></i>
+        <div class="icon-title">fa-circle-thin</div>
+    </li>
+    <li>
+        <i class="fa fa-clock-o"></i>
+        <div class="icon-title">fa-clock-o</div>
+    </li>
+    <li>
+        <i class="fa fa-clone"></i>
+        <div class="icon-title">fa-clone</div>
+    </li>
+    <li>
+        <i class="fa fa-close"></i>
+        <div class="icon-title">fa-close</div>
+    </li>
+    <li>
+        <i class="fa fa-cloud"></i>
+        <div class="icon-title">fa-cloud</div>
+    </li>
+    <li>
+        <i class="fa fa-cloud-download"></i>
+        <div class="icon-title">fa-cloud-download</div>
+    </li>
+    <li>
+        <i class="fa fa-cloud-upload"></i>
+        <div class="icon-title">fa-cloud-upload</div>
+    </li>
+    <li>
+        <i class="fa fa-code"></i>
+        <div class="icon-title">fa-code</div>
+    </li>
+    <li>
+        <i class="fa fa-code-fork"></i>
+        <div class="icon-title">fa-code-fork</div>
+    </li>
+    <li>
+        <i class="fa fa-coffee"></i>
+        <div class="icon-title">fa-coffee</div>
+    </li>
+    <li>
+        <i class="fa fa-cog"></i>
+        <div class="icon-title">fa-cog</div>
+    </li>
+    <li>
+        <i class="fa fa-cogs"></i>
+        <div class="icon-title">fa-cogs</div>
+    </li>
+    <li>
+        <i class="fa fa-comment"></i>
+        <div class="icon-title">fa-comment</div>
+    </li>
+    <li>
+        <i class="fa fa-comment-o"></i>
+        <div class="icon-title">fa-comment-o</div>
+    </li>
+    <li>
+        <i class="fa fa-commenting"></i>
+        <div class="icon-title">fa-commenting</div>
+    </li>
+    <li>
+        <i class="fa fa-commenting-o"></i>
+        <div class="icon-title">fa-commenting-o</div>
+    </li>
+    <li>
+        <i class="fa fa-comments"></i>
+        <div class="icon-title">fa-comments</div>
+    </li>
+    <li>
+        <i class="fa fa-comments-o"></i>
+        <div class="icon-title">fa-comments-o</div>
+    </li>
+    <li>
+        <i class="fa fa-compass"></i>
+        <div class="icon-title">fa-compass</div>
+    </li>
+    <li>
+        <i class="fa fa-copyright"></i>
+        <div class="icon-title">fa-copyright</div>
+    </li>
+    <li>
+        <i class="fa fa-creative-commons"></i>
+        <div class="icon-title">fa-creative-commons</div>
+    </li>
+    <li>
+        <i class="fa fa-credit-card"></i>
+        <div class="icon-title">fa-credit-card</div>
+    </li>
+    <li><i class="fa fa-credit-card-alt"></i>
+        <div class="icon-title">fa-credit-card-alt</div>
+    </li>
+    <li><i class="fa fa-crop"></i>
+        <div class="icon-title">fa-crop</div>
+    </li>
+    <li><i class="fa fa-crosshairs"></i>
+        <div class="icon-title">fa-crosshairs</div>
+    </li>
+    <li><i class="fa fa-cube"></i>
+        <div class="icon-title">fa-cube</div>
+    </li>
+    <li><i class="fa fa-cubes"></i>
+        <div class="icon-title">fa-cubes</div>
+    </li>
+    <li><i class="fa fa-cutlery"></i>
+        <div class="icon-title">fa-cutlery</div>
+    </li>
+    <li><i class="fa fa-dashboard"></i>
+        <div class="icon-title">fa-dashboard</div>
+    </li>
+    <li><i class="fa fa-database"></i>
+        <div class="icon-title">fa-database</div>
+    </li>
+    <li><i class="fa fa-deaf"></i>
+        <div class="icon-title">fa-deaf</div>
+    </li>
+    <li><i class="fa fa-deafness"></i>
+        <div class="icon-title">fa-deafness</div>
+    </li>
+    <li><i class="fa fa-desktop"></i>
+        <div class="icon-title">fa-desktop</div>
+    </li>
+    <li><i class="fa fa-diamond"></i>
+        <div class="icon-title">fa-diamond</div>
+    </li>
+    <li><i class="fa fa-dot-circle-o"></i>
+        <div class="icon-title">fa-dot-circle-o</div>
+    </li>
+    <li><i class="fa fa-download"></i>
+        <div class="icon-title">fa-download</div>
+    </li>
+    <li><i class="fa fa-drivers-license"></i>
+        <div class="icon-title">fa-drivers-license</div>
+    </li>
+    <li><i class="fa fa-drivers-license-o"></i>
+        <div class="icon-title">fa-drivers-license-o</div>
+    </li>
+    <li><i class="fa fa-edit"></i>
+        <div class="icon-title">fa-edit</div>
+    </li>
+    <li><i class="fa fa-ellipsis-h"></i>
+        <div class="icon-title">fa-ellipsis-h</div>
+    </li>
+    <li><i class="fa fa-ellipsis-v"></i>
+        <div class="icon-title">fa-ellipsis-v</div>
+    </li>
+    <li><i class="fa fa-envelope"></i>
+        <div class="icon-title">fa-envelope</div>
+    </li>
+    <li><i class="fa fa-envelope-o"></i>
+        <div class="icon-title">fa-envelope-o</div>
+    </li>
+    <li><i class="fa fa-envelope-open"></i>
+        <div class="icon-title">fa-envelope-open</div>
+    </li>
+    <li><i class="fa fa-envelope-open-o"></i>
+        <div class="icon-title">fa-envelope-open-o</div>
+    </li>
+    <li><i class="fa fa-envelope-square"></i>
+        <div class="icon-title">fa-envelope-square</div>
+    </li>
+    <li><i class="fa fa-eraser"></i>
+        <div class="icon-title">fa-eraser</div>
+    </li>
+    <li><i class="fa fa-exchange"></i>
+        <div class="icon-title">fa-exchange</div>
+    </li>
+    <li><i class="fa fa-exclamation"></i>
+        <div class="icon-title">fa-exclamation</div>
+    </li>
+    <li><i class="fa fa-exclamation-circle"></i>
+        <div class="icon-title">fa-exclamation-circle</div>
+    </li>
+    <li><i class="fa fa-exclamation-triangle"></i>
+        <div class="icon-title">fa-exclamation-triangle</div>
+    </li>
+    <li><i class="fa fa-external-link"></i>
+        <div class="icon-title">fa-external-link</div>
+    </li>
+    <li><i class="fa fa-external-link-square"></i>
+        <div class="icon-title">fa-external-link-square</div>
+    </li>
+    <li><i class="fa fa-eye"></i>
+        <div class="icon-title">fa-eye</div>
+    </li>
+    <li><i class="fa fa-eye-slash"></i>
+        <div class="icon-title">fa-eye-slash</div>
+    </li>
+    <li><i class="fa fa-eyedropper"></i>
+        <div class="icon-title">fa-eyedropper</div>
+    </li>
+    <li><i class="fa fa-fax"></i>
+        <div class="icon-title">fa-fax</div>
+    </li>
+    <li><i class="fa fa-feed"></i>
+        <div class="icon-title">fa-feed</div>
+    </li>
+    <li><i class="fa fa-female"></i>
+        <div class="icon-title">fa-female</div>
+    </li>
+    <li><i class="fa fa-fighter-jet"></i>
+        <div class="icon-title">fa-fighter-jet</div>
+    </li>
+    <li><i class="fa fa-file-archive-o"></i>
+        <div class="icon-title">fa-file-archive-o</div>
+    </li>
+    <li><i class="fa fa-file-audio-o"></i>
+        <div class="icon-title">fa-file-audio-o</div>
+    </li>
+    <li><i class="fa fa-file-code-o"></i>
+        <div class="icon-title">fa-file-code-o</div>
+    </li>
+    <li><i class="fa fa-file-excel-o"></i>
+        <div class="icon-title">fa-file-excel-o</div>
+    </li>
+    <li><i class="fa fa-file-image-o"></i>
+        <div class="icon-title">fa-file-image-o</div>
+    </li>
+    <li><i class="fa fa-file-movie-o"></i>
+        <div class="icon-title">fa-file-movie-o</div>
+    </li>
+    <li><i class="fa fa-file-pdf-o"></i>
+        <div class="icon-title">fa-file-pdf-o</div>
+    </li>
+    <li><i class="fa fa-file-photo-o"></i>
+        <div class="icon-title">fa-file-photo-o</div>
+    </li>
+    <li><i class="fa fa-file-picture-o"></i>
+        <div class="icon-title">fa-file-picture-o</div>
+    </li>
+    <li><i class="fa fa-file-powerpoint-o"></i>
+        <div class="icon-title">fa-file-powerpoint-o</div>
+    </li>
+    <li><i class="fa fa-file-sound-o"></i>
+        <div class="icon-title">fa-file-sound-o</div>
+    </li>
+    <li><i class="fa fa-file-video-o"></i>
+        <div class="icon-title">fa-file-video-o</div>
+    </li>
+    <li><i class="fa fa-file-word-o"></i>
+        <div class="icon-title">fa-file-word-o</div>
+    </li>
+    <li><i class="fa fa-file-zip-o"></i>
+        <div class="icon-title">fa-file-zip-o</div>
+    </li>
+    <li><i class="fa fa-film"></i>
+        <div class="icon-title">fa-film</div>
+    </li>
+    <li><i class="fa fa-filter"></i>
+        <div class="icon-title">fa-filter</div>
+    </li>
+    <li><i class="fa fa-fire"></i>
+        <div class="icon-title">fa-fire</div>
+    </li>
+    <li><i class="fa fa-fire-extinguisher"></i>
+        <div class="icon-title">fa-fire-extinguisher</div>
+    </li>
+    <li><i class="fa fa-flag"></i>
+        <div class="icon-title">fa-flag</div>
+    </li>
+    <li><i class="fa fa-flag-checkered"></i>
+        <div class="icon-title">fa-flag-checkered</div>
+    </li>
+    <li><i class="fa fa-flag-o"></i>
+        <div class="icon-title">fa-flag-o</div>
+    </li>
+    <li><i class="fa fa-flash"></i>
+        <div class="icon-title">fa-flash</div>
+    </li>
+    <li><i class="fa fa-flask"></i>
+        <div class="icon-title">fa-flask</div>
+    </li>
+    <li><i class="fa fa-folder"></i>
+        <div class="icon-title">fa-folder</div>
+    </li>
+    <li><i class="fa fa-folder-o"></i>
+        <div class="icon-title">fa-folder-o</div>
+    </li>
+    <li><i class="fa fa-folder-open"></i>
+        <div class="icon-title">fa-folder-open</div>
+    </li>
+    <li><i class="fa fa-folder-open-o"></i>
+        <div class="icon-title">fa-folder-open-o</div>
+    </li>
+    <li><i class="fa fa-frown-o"></i>
+        <div class="icon-title">fa-frown-o</div>
+    </li>
+    <li><i class="fa fa-futbol-o"></i>
+        <div class="icon-title">fa-futbol-o</div>
+    </li>
+    <li><i class="fa fa-gamepad"></i>
+        <div class="icon-title">fa-gamepad</div>
+    </li>
+    <li><i class="fa fa-gavel"></i>
+        <div class="icon-title">fa-gavel</div>
+    </li>
+    <li><i class="fa fa-gear"></i>
+        <div class="icon-title">fa-gear</div>
+    </li>
+    <li><i class="fa fa-gears"></i>
+        <div class="icon-title">fa-gears</div>
+    </li>
+    <li><i class="fa fa-gift"></i>
+        <div class="icon-title">fa-gift</div>
+    </li>
+    <li><i class="fa fa-glass"></i>
+        <div class="icon-title">fa-glass</div>
+    </li>
+    <li><i class="fa fa-globe"></i>
+        <div class="icon-title">fa-globe</div>
+    </li>
+    <li><i class="fa fa-graduation-cap"></i>
+        <div class="icon-title">fa-graduation-cap</div>
+    </li>
+    <li><i class="fa fa-group"></i>
+        <div class="icon-title">fa-group</div>
+    </li>
+    <li><i class="fa fa-hand-grab-o"></i>
+        <div class="icon-title">fa-hand-grab-o</div>
+    </li>
+    <li><i class="fa fa-hand-lizard-o"></i>
+        <div class="icon-title">fa-hand-lizard-o</div>
+    </li>
+    <li><i class="fa fa-hand-paper-o"></i>
+        <div class="icon-title">fa-hand-paper-o</div>
+    </li>
+    <li><i class="fa fa-hand-peace-o"></i>
+        <div class="icon-title">fa-hand-peace-o</div>
+    </li>
+    <li><i class="fa fa-hand-pointer-o"></i>
+        <div class="icon-title">fa-hand-pointer-o</div>
+    </li>
+    <li><i class="fa fa-hand-rock-o"></i>
+        <div class="icon-title">fa-hand-rock-o</div>
+    </li>
+    <li><i class="fa fa-hand-scissors-o"></i>
+        <div class="icon-title">fa-hand-scissors-o</div>
+    </li>
+    <li><i class="fa fa-hand-spock-o"></i>
+        <div class="icon-title">fa-hand-spock-o</div>
+    </li>
+    <li><i class="fa fa-hand-stop-o"></i>
+        <div class="icon-title">fa-hand-stop-o</div>
+    </li>
+    <li><i class="fa fa-handshake-o"></i>
+        <div class="icon-title">fa-handshake-o</div>
+    </li>
+    <li><i class="fa fa-hard-of-hearing"></i>
+        <div class="icon-title">fa-hard-of-hearing</div>
+    </li>
+    <li><i class="fa fa-hashtag"></i>
+        <div class="icon-title">fa-hashtag</div>
+    </li>
+    <li><i class="fa fa-hdd-o"></i>
+        <div class="icon-title">fa-hdd-o</div>
+    </li>
+    <li><i class="fa fa-headphones"></i>
+        <div class="icon-title">fa-headphones</div>
+    </li>
+    <li><i class="fa fa-heart"></i>
+        <div class="icon-title">fa-heart</div>
+    </li>
+    <li><i class="fa fa-heart-o"></i>
+        <div class="icon-title">fa-heart-o</div>
+    </li>
+    <li><i class="fa fa-heartbeat"></i>
+        <div class="icon-title">fa-heartbeat</div>
+    </li>
+    <li><i class="fa fa-history"></i>
+        <div class="icon-title">fa-history</div>
+    </li>
+    <li><i class="fa fa-home"></i>
+        <div class="icon-title">fa-home</div>
+    </li>
+    <li><i class="fa fa-hotel"></i>
+        <div class="icon-title">fa-hotel</div>
+    </li>
+    <li><i class="fa fa-hourglass"></i>
+        <div class="icon-title">fa-hourglass</div>
+    </li>
+    <li><i class="fa fa-hourglass-1"></i>
+        <div class="icon-title">fa-hourglass-1</div>
+    </li>
+    <li><i class="fa fa-hourglass-2"></i>
+        <div class="icon-title">fa-hourglass-2</div>
+    </li>
+    <li><i class="fa fa-hourglass-3"></i>
+        <div class="icon-title">fa-hourglass-3</div>
+    </li>
+    <li><i class="fa fa-hourglass-end"></i>
+        <div class="icon-title">fa-hourglass-end</div>
+    </li>
+    <li><i class="fa fa-hourglass-half"></i>
+        <div class="icon-title">fa-hourglass-half</div>
+    </li>
+    <li><i class="fa fa-hourglass-o"></i>
+        <div class="icon-title">fa-hourglass-o</div>
+    </li>
+    <li><i class="fa fa-hourglass-start"></i>
+        <div class="icon-title">fa-hourglass-start</div>
+    </li>
+    <li><i class="fa fa-i-cursor"></i>
+        <div class="icon-title">fa-i-cursor</div>
+    </li>
+    <li><i class="fa fa-id-badge"></i>
+        <div class="icon-title">fa-id-badge</div>
+    </li>
+    <li><i class="fa fa-id-card"></i>
+        <div class="icon-title">fa-id-card</div>
+    </li>
+    <li><i class="fa fa-id-card-o"></i>
+        <div class="icon-title">fa-id-card-o</div>
+    </li>
+    <li><i class="fa fa-image"></i>
+        <div class="icon-title">fa-image</div>
+    </li>
+    <li><i class="fa fa-inbox"></i>
+        <div class="icon-title">fa-inbox</div>
+    </li>
+    <li><i class="fa fa-industry"></i>
+        <div class="icon-title">fa-industry</div>
+    </li>
+    <li><i class="fa fa-info"></i>
+        <div class="icon-title">fa-info</div>
+    </li>
+    <li><i class="fa fa-info-circle"></i>
+        <div class="icon-title">fa-info-circle</div>
+    </li>
+    <li><i class="fa fa-institution"></i>
+        <div class="icon-title">fa-institution</div>
+    </li>
+    <li><i class="fa fa-key"></i>
+        <div class="icon-title">fa-key</div>
+    </li>
+    <li><i class="fa fa-keyboard-o"></i>
+        <div class="icon-title">fa-keyboard-o</div>
+    </li>
+    <li><i class="fa fa-language"></i>
+        <div class="icon-title">fa-language</div>
+    </li>
+    <li><i class="fa fa-laptop"></i>
+        <div class="icon-title">fa-laptop</div>
+    </li>
+    <li><i class="fa fa-leaf"></i>
+        <div class="icon-title">fa-leaf</div>
+    </li>
+    <li><i class="fa fa-legal"></i>
+        <div class="icon-title">fa-legal</div>
+    </li>
+    <li><i class="fa fa-lemon-o"></i>
+        <div class="icon-title">fa-lemon-o</div>
+    </li>
+    <li><i class="fa fa-level-down"></i>
+        <div class="icon-title">fa-level-down</div>
+    </li>
+    <li><i class="fa fa-level-up"></i>
+        <div class="icon-title">fa-level-up</div>
+    </li>
+    <li><i class="fa fa-life-bouy"></i>
+        <div class="icon-title">fa-life-bouy</div>
+    </li>
+    <li><i class="fa fa-life-buoy"></i>
+        <div class="icon-title">fa-life-buoy</div>
+    </li>
+    <li><i class="fa fa-life-ring"></i>
+        <div class="icon-title">fa-life-ring</div>
+    </li>
+    <li><i class="fa fa-life-saver"></i>
+        <div class="icon-title">fa-life-saver</div>
+    </li>
+    <li><i class="fa fa-lightbulb-o"></i>
+        <div class="icon-title">fa-lightbulb-o</div>
+    </li>
+    <li><i class="fa fa-line-chart"></i>
+        <div class="icon-title">fa-line-chart</div>
+    </li>
+    <li><i class="fa fa-location-arrow"></i>
+        <div class="icon-title">fa-location-arrow</div>
+    </li>
+    <li><i class="fa fa-lock"></i>
+        <div class="icon-title">fa-lock</div>
+    </li>
+    <li><i class="fa fa-low-vision"></i>
+        <div class="icon-title">fa-low-vision</div>
+    </li>
+    <li><i class="fa fa-magic"></i>
+        <div class="icon-title">fa-magic</div>
+    </li>
+    <li><i class="fa fa-magnet"></i>
+        <div class="icon-title">fa-magnet</div>
+    </li>
+    <li><i class="fa fa-mail-forward"></i>
+        <div class="icon-title">fa-mail-forward</div>
+    </li>
+    <li><i class="fa fa-mail-reply"></i>
+        <div class="icon-title">fa-mail-reply</div>
+    </li>
+    <li><i class="fa fa-mail-reply-all"></i>
+        <div class="icon-title">fa-mail-reply-all</div>
+    </li>
+    <li><i class="fa fa-male"></i>
+        <div class="icon-title">fa-male</div>
+    </li>
+    <li><i class="fa fa-map"></i>
+        <div class="icon-title">fa-map</div>
+    </li>
+    <li><i class="fa fa-map-marker"></i>
+        <div class="icon-title">fa-map-marker</div>
+    </li>
+    <li><i class="fa fa-map-o"></i>
+        <div class="icon-title">fa-map-o</div>
+    </li>
+    <li><i class="fa fa-map-pin"></i>
+        <div class="icon-title">fa-map-pin</div>
+    </li>
+    <li><i class="fa fa-map-signs"></i>
+        <div class="icon-title">fa-map-signs</div>
+    </li>
+    <li><i class="fa fa-meh-o"></i>
+        <div class="icon-title">fa-meh-o</div>
+    </li>
+    <li><i class="fa fa-microchip"></i>
+        <div class="icon-title">fa-microchip</div>
+    </li>
+    <li><i class="fa fa-microphone"></i>
+        <div class="icon-title">fa-microphone</div>
+    </li>
+    <li><i class="fa fa-microphone-slash"></i>
+        <div class="icon-title">fa-microphone-slash</div>
+    </li>
+    <li><i class="fa fa-minus"></i>
+        <div class="icon-title">fa-minus</div>
+    </li>
+    <li><i class="fa fa-minus-circle"></i>
+        <div class="icon-title">fa-minus-circle</div>
+    </li>
+    <li><i class="fa fa-minus-square"></i>
+        <div class="icon-title">fa-minus-square</div>
+    </li>
+    <li><i class="fa fa-minus-square-o"></i>
+        <div class="icon-title">fa-minus-square-o</div>
+    </li>
+    <li><i class="fa fa-mobile"></i>
+        <div class="icon-title">fa-mobile</div>
+    </li>
+    <li><i class="fa fa-mobile-phone"></i>
+        <div class="icon-title">fa-mobile-phone</div>
+    </li>
+    <li><i class="fa fa-money"></i>
+        <div class="icon-title">fa-money</div>
+    </li>
+    <li><i class="fa fa-moon-o"></i>
+        <div class="icon-title">fa-moon-o</div>
+    </li>
+    <li><i class="fa fa-mortar-board"></i>
+        <div class="icon-title">fa-mortar-board</div>
+    </li>
+    <li><i class="fa fa-motorcycle"></i>
+        <div class="icon-title">fa-motorcycle</div>
+    </li>
+    <li><i class="fa fa-mouse-pointer"></i>
+        <div class="icon-title">fa-mouse-pointer</div>
+    </li>
+    <li><i class="fa fa-music"></i>
+        <div class="icon-title">fa-music</div>
+    </li>
+    <li><i class="fa fa-navicon"></i>
+        <div class="icon-title">fa-navicon</div>
+    </li>
+    <li><i class="fa fa-newspaper-o"></i>
+        <div class="icon-title">fa-newspaper-o</div>
+    </li>
+    <li><i class="fa fa-object-group"></i>
+        <div class="icon-title">fa-object-group</div>
+    </li>
+    <li><i class="fa fa-object-ungroup"></i>
+        <div class="icon-title">fa-object-ungroup</div>
+    </li>
+    <li><i class="fa fa-paint-brush"></i>
+        <div class="icon-title">fa-paint-brush</div>
+    </li>
+    <li><i class="fa fa-paper-plane"></i>
+        <div class="icon-title">fa-paper-plane</div>
+    </li>
+    <li><i class="fa fa-paper-plane-o"></i>
+        <div class="icon-title">fa-paper-plane-o</div>
+    </li>
+    <li><i class="fa fa-paw"></i>
+        <div class="icon-title">fa-paw</div>
+    </li>
+    <li><i class="fa fa-pencil"></i>
+        <div class="icon-title">fa-pencil</div>
+    </li>
+    <li><i class="fa fa-pencil-square"></i>
+        <div class="icon-title">fa-pencil-square</div>
+    </li>
+    <li><i class="fa fa-pencil-square-o"></i>
+        <div class="icon-title">fa-pencil-square-o</div>
+    </li>
+    <li><i class="fa fa-percent"></i>
+        <div class="icon-title">fa-percent</div>
+    </li>
+    <li><i class="fa fa-phone"></i>
+        <div class="icon-title">fa-phone</div>
+    </li>
+    <li><i class="fa fa-phone-square"></i>
+        <div class="icon-title">fa-phone-square</div>
+    </li>
+    <li><i class="fa fa-photo"></i>
+        <div class="icon-title">fa-photo</div>
+    </li>
+    <li><i class="fa fa-picture-o"></i>
+        <div class="icon-title">fa-picture-o</div>
+    </li>
+    <li><i class="fa fa-pie-chart"></i>
+        <div class="icon-title">fa-pie-chart</div>
+    </li>
+    <li><i class="fa fa-plane"></i>
+        <div class="icon-title">fa-plane</div>
+    </li>
+    <li><i class="fa fa-plug"></i>
+        <div class="icon-title">fa-plug</div>
+    </li>
+    <li><i class="fa fa-plus"></i>
+        <div class="icon-title">fa-plus</div>
+    </li>
+    <li><i class="fa fa-plus-circle"></i>
+        <div class="icon-title">fa-plus-circle</div>
+    </li>
+    <li><i class="fa fa-plus-square"></i>
+        <div class="icon-title">fa-plus-square</div>
+    </li>
+    <li><i class="fa fa-plus-square-o"></i>
+        <div class="icon-title">fa-plus-square-o</div>
+    </li>
+    <li><i class="fa fa-podcast"></i>
+        <div class="icon-title">fa-podcast</div>
+    </li>
+    <li><i class="fa fa-power-off"></i>
+        <div class="icon-title">fa-power-off</div>
+    </li>
+    <li><i class="fa fa-print"></i>
+        <div class="icon-title">fa-print</div>
+    </li>
+    <li><i class="fa fa-puzzle-piece"></i>
+        <div class="icon-title">fa-puzzle-piece</div>
+    </li>
+    <li><i class="fa fa-qrcode"></i>
+        <div class="icon-title">fa-qrcode</div>
+    </li>
+    <li><i class="fa fa-question"></i>
+        <div class="icon-title">fa-question</div>
+    </li>
+    <li><i class="fa fa-question-circle"></i>
+        <div class="icon-title">fa-question-circle</div>
+    </li>
+    <li><i class="fa fa-question-circle-o"></i>
+        <div class="icon-title">fa-question-circle-o</div>
+    </li>
+    <li><i class="fa fa-quote-left"></i>
+        <div class="icon-title">fa-quote-left</div>
+    </li>
+    <li><i class="fa fa-quote-right"></i>
+        <div class="icon-title">fa-quote-right</div>
+    </li>
+    <li><i class="fa fa-random"></i>
+        <div class="icon-title">fa-random</div>
+    </li>
+    <li><i class="fa fa-recycle"></i>
+        <div class="icon-title">fa-recycle</div>
+    </li>
+    <li><i class="fa fa-refresh"></i>
+        <div class="icon-title">fa-refresh</div>
+    </li>
+    <li><i class="fa fa-registered"></i>
+        <div class="icon-title">fa-registered</div>
+    </li>
+    <li><i class="fa fa-remove"></i>
+        <div class="icon-title">fa-remove</div>
+    </li>
+    <li><i class="fa fa-reorder"></i>
+        <div class="icon-title">fa-reorder</div>
+    </li>
+    <li><i class="fa fa-reply"></i>
+        <div class="icon-title">fa-reply</div>
+    </li>
+    <li><i class="fa fa-reply-all"></i>
+        <div class="icon-title">fa-reply-all</div>
+    </li>
+    <li><i class="fa fa-retweet"></i>
+        <div class="icon-title">fa-retweet</div>
+    </li>
+    <li><i class="fa fa-road"></i>
+        <div class="icon-title">fa-road</div>
+    </li>
+    <li><i class="fa fa-rocket"></i>
+        <div class="icon-title">fa-rocket</div>
+    </li>
+    <li><i class="fa fa-rss"></i>
+        <div class="icon-title">fa-rss</div>
+    </li>
+    <li><i class="fa fa-rss-square"></i>
+        <div class="icon-title">fa-rss-square</div>
+    </li>
+    <li><i class="fa fa-s15"></i>
+        <div class="icon-title">fa-s15</div>
+    </li>
+    <li><i class="fa fa-search"></i>
+        <div class="icon-title">fa-search</div>
+    </li>
+    <li><i class="fa fa-search-minus"></i>
+        <div class="icon-title">fa-search-minus</div>
+    </li>
+    <li><i class="fa fa-search-plus"></i>
+        <div class="icon-title">fa-search-plus</div>
+    </li>
+    <li><i class="fa fa-send"></i>
+        <div class="icon-title">fa-send</div>
+    </li>
+    <li><i class="fa fa-send-o"></i>
+        <div class="icon-title">fa-send-o</div>
+    </li>
+    <li><i class="fa fa-server"></i>
+        <div class="icon-title">fa-server</div>
+    </li>
+    <li><i class="fa fa-share"></i>
+        <div class="icon-title">fa-share</div>
+    </li>
+    <li><i class="fa fa-share-alt"></i>
+        <div class="icon-title">fa-share-alt</div>
+    </li>
+    <li><i class="fa fa-share-alt-square"></i>
+        <div class="icon-title">fa-share-alt-square</div>
+    </li>
+    <li><i class="fa fa-share-square"></i>
+        <div class="icon-title">fa-share-square</div>
+    </li>
+    <li><i class="fa fa-share-square-o"></i>
+        <div class="icon-title">fa-share-square-o</div>
+    </li>
+    <li><i class="fa fa-shield"></i>
+        <div class="icon-title">fa-shield</div>
+    </li>
+    <li><i class="fa fa-ship"></i>
+        <div class="icon-title">fa-ship</div>
+    </li>
+    <li><i class="fa fa-shopping-bag"></i>
+        <div class="icon-title">fa-shopping-bag</div>
+    </li>
+    <li><i class="fa fa-shopping-basket"></i>
+        <div class="icon-title">fa-shopping-basket</div>
+    </li>
+    <li><i class="fa fa-shopping-cart"></i>
+        <div class="icon-title">fa-shopping-cart</div>
+    </li>
+    <li><i class="fa fa-shower"></i>
+        <div class="icon-title">fa-shower</div>
+    </li>
+    <li><i class="fa fa-sign-in"></i>
+        <div class="icon-title">fa-sign-in</div>
+    </li>
+    <li><i class="fa fa-sign-language"></i>
+        <div class="icon-title">fa-sign-language</div>
+    </li>
+    <li><i class="fa fa-sign-out"></i>
+        <div class="icon-title">fa-sign-out</div>
+    </li>
+    <li><i class="fa fa-signal"></i>
+        <div class="icon-title">fa-signal</div>
+    </li>
+    <li><i class="fa fa-signing"></i>
+        <div class="icon-title">fa-signing</div>
+    </li>
+    <li><i class="fa fa-sitemap"></i>
+        <div class="icon-title">fa-sitemap</div>
+    </li>
+    <li><i class="fa fa-sliders"></i>
+        <div class="icon-title">fa-sliders</div>
+    </li>
+    <li><i class="fa fa-smile-o"></i>
+        <div class="icon-title">fa-smile-o</div>
+    </li>
+    <li><i class="fa fa-snowflake-o"></i>
+        <div class="icon-title">fa-snowflake-o</div>
+    </li>
+    <li><i class="fa fa-soccer-ball-o"></i>
+        <div class="icon-title">fa-soccer-ball-o</div>
+    </li>
+    <li><i class="fa fa-sort"></i>
+        <div class="icon-title">fa-sort</div>
+    </li>
+    <li><i class="fa fa-sort-alpha-asc"></i>
+        <div class="icon-title">fa-sort-alpha-asc</div>
+    </li>
+    <li><i class="fa fa-sort-alpha-desc"></i>
+        <div class="icon-title">fa-sort-alpha-desc</div>
+    </li>
+    <li><i class="fa fa-sort-amount-asc"></i>
+        <div class="icon-title">fa-sort-amount-asc</div>
+    </li>
+    <li><i class="fa fa-sort-amount-desc"></i>
+        <div class="icon-title">fa-sort-amount-desc</div>
+    </li>
+    <li><i class="fa fa-sort-asc"></i>
+        <div class="icon-title">fa-sort-asc</div>
+    </li>
+    <li><i class="fa fa-sort-desc"></i>
+        <div class="icon-title">fa-sort-desc</div>
+    </li>
+    <li><i class="fa fa-sort-down"></i>
+        <div class="icon-title">fa-sort-down</div>
+    </li>
+    <li><i class="fa fa-sort-numeric-asc"></i>
+        <div class="icon-title">fa-sort-numeric-asc</div>
+    </li>
+    <li><i class="fa fa-sort-numeric-desc"></i>
+        <div class="icon-title">fa-sort-numeric-desc</div>
+    </li>
+    <li><i class="fa fa-sort-up"></i>
+        <div class="icon-title">fa-sort-up</div>
+    </li>
+    <li><i class="fa fa-space-shuttle"></i>
+        <div class="icon-title">fa-space-shuttle</div>
+    </li>
+    <li><i class="fa fa-spinner"></i>
+        <div class="icon-title">fa-spinner</div>
+    </li>
+    <li><i class="fa fa-spoon"></i>
+        <div class="icon-title">fa-spoon</div>
+    </li>
+    <li><i class="fa fa-square"></i>
+        <div class="icon-title">fa-square</div>
+    </li>
+    <li><i class="fa fa-square-o"></i>
+        <div class="icon-title">fa-square-o</div>
+    </li>
+    <li><i class="fa fa-star"></i>
+        <div class="icon-title">fa-star</div>
+    </li>
+    <li><i class="fa fa-star-half"></i>
+        <div class="icon-title">fa-star-half</div>
+    </li>
+    <li><i class="fa fa-star-half-empty"></i>
+        <div class="icon-title">fa-star-half-empty</div>
+    </li>
+    <li><i class="fa fa-star-half-full"></i>
+        <div class="icon-title">fa-star-half-full</div>
+    </li>
+    <li><i class="fa fa-star-half-o"></i>
+        <div class="icon-title">fa-star-half-o</div>
+    </li>
+    <li><i class="fa fa-star-o"></i>
+        <div class="icon-title">fa-star-o</div>
+    </li>
+    <li><i class="fa fa-sticky-note"></i>
+        <div class="icon-title">fa-sticky-note</div>
+    </li>
+    <li><i class="fa fa-sticky-note-o"></i>
+        <div class="icon-title">fa-sticky-note-o</div>
+    </li>
+    <li><i class="fa fa-street-view"></i>
+        <div class="icon-title">fa-street-view</div>
+    </li>
+    <li><i class="fa fa-suitcase"></i>
+        <div class="icon-title">fa-suitcase</div>
+    </li>
+    <li><i class="fa fa-sun-o"></i>
+        <div class="icon-title">fa-sun-o</div>
+    </li>
+    <li><i class="fa fa-support"></i>
+        <div class="icon-title">fa-support</div>
+    </li>
+    <li><i class="fa fa-tablet"></i>
+        <div class="icon-title">fa-tablet</div>
+    </li>
+    <li><i class="fa fa-tachometer"></i>
+        <div class="icon-title">fa-tachometer</div>
+    </li>
+    <li><i class="fa fa-tag"></i>
+        <div class="icon-title">fa-tag</div>
+    </li>
+    <li><i class="fa fa-tags"></i>
+        <div class="icon-title">fa-tags</div>
+    </li>
+    <li><i class="fa fa-tasks"></i>
+        <div class="icon-title">fa-tasks</div>
+    </li>
+    <li><i class="fa fa-taxi"></i>
+        <div class="icon-title">fa-taxi</div>
+    </li>
+    <li><i class="fa fa-television"></i>
+        <div class="icon-title">fa-television</div>
+    </li>
+    <li><i class="fa fa-terminal"></i>
+        <div class="icon-title">fa-terminal</div>
+    </li>
+    <li><i class="fa fa-thermometer"></i>
+        <div class="icon-title">fa-thermometer</div>
+    </li>
+    <li><i class="fa fa-thermometer-0"></i>
+        <div class="icon-title">fa-thermometer-0</div>
+    </li>
+    <li><i class="fa fa-thermometer-1"></i>
+        <div class="icon-title">fa-thermometer-1</div>
+    </li>
+    <li><i class="fa fa-thermometer-2"></i>
+        <div class="icon-title">fa-thermometer-2</div>
+    </li>
+    <li><i class="fa fa-thermometer-3"></i>
+        <div class="icon-title">fa-thermometer-3</div>
+    </li>
+    <li><i class="fa fa-thermometer-4"></i>
+        <div class="icon-title">fa-thermometer-4</div>
+    </li>
+    <li><i class="fa fa-thermometer-empty"></i>
+        <div class="icon-title">fa-thermometer-empty</div>
+    </li>
+    <li><i class="fa fa-thermometer-full"></i>
+        <div class="icon-title">fa-thermometer-full</div>
+    </li>
+    <li><i class="fa fa-thermometer-half"></i>
+        <div class="icon-title">fa-thermometer-half</div>
+    </li>
+    <li><i class="fa fa-thermometer-quarter"></i>
+        <div class="icon-title">fa-thermometer-quarter</div>
+    </li>
+    <li><i class="fa fa-thermometer-three-quarters"></i>
+        <div class="icon-title">fa-thermometer-three-quarters</div>
+    </li>
+    <li><i class="fa fa-thumb-tack"></i>
+        <div class="icon-title">fa-thumb-tack</div>
+    </li>
+    <li><i class="fa fa-thumbs-down"></i>
+        <div class="icon-title">fa-thumbs-down</div>
+    </li>
+    <li><i class="fa fa-thumbs-o-down"></i>
+        <div class="icon-title">fa-thumbs-o-down</div>
+    </li>
+    <li><i class="fa fa-thumbs-o-up"></i>
+        <div class="icon-title">fa-thumbs-o-up</div>
+    </li>
+    <li><i class="fa fa-thumbs-up"></i>
+        <div class="icon-title">fa-thumbs-up</div>
+    </li>
+    <li><i class="fa fa-ticket"></i>
+        <div class="icon-title">fa-ticket</div>
+    </li>
+    <li><i class="fa fa-times"></i>
+        <div class="icon-title">fa-times</div>
+    </li>
+    <li><i class="fa fa-times-circle"></i>
+        <div class="icon-title">fa-times-circle</div>
+    </li>
+    <li><i class="fa fa-times-circle-o"></i>
+        <div class="icon-title">fa-times-circle-o</div>
+    </li>
+    <li><i class="fa fa-times-rectangle"></i>
+        <div class="icon-title">fa-times-rectangle</div>
+    </li>
+    <li><i class="fa fa-times-rectangle-o"></i>
+        <div class="icon-title">fa-times-rectangle-o</div>
+    </li>
+    <li><i class="fa fa-tint"></i>
+        <div class="icon-title">fa-tint</div>
+    </li>
+    <li><i class="fa fa-toggle-down"></i>
+        <div class="icon-title">fa-toggle-down</div>
+    </li>
+    <li><i class="fa fa-toggle-left"></i>
+        <div class="icon-title">fa-toggle-left</div>
+    </li>
+    <li><i class="fa fa-toggle-off"></i>
+        <div class="icon-title">fa-toggle-off</div>
+    </li>
+    <li><i class="fa fa-toggle-on"></i>
+        <div class="icon-title">fa-toggle-on</div>
+    </li>
+    <li><i class="fa fa-toggle-right"></i>
+        <div class="icon-title">fa-toggle-right</div>
+    </li>
+    <li><i class="fa fa-toggle-up"></i>
+        <div class="icon-title">fa-toggle-up</div>
+    </li>
+    <li><i class="fa fa-trademark"></i>
+        <div class="icon-title">fa-trademark</div>
+    </li>
+    <li><i class="fa fa-trash"></i>
+        <div class="icon-title">fa-trash</div>
+    </li>
+    <li><i class="fa fa-trash-o"></i>
+        <div class="icon-title">fa-trash-o</div>
+    </li>
+    <li><i class="fa fa-tree"></i>
+        <div class="icon-title">fa-tree</div>
+    </li>
+    <li><i class="fa fa-trophy"></i>
+        <div class="icon-title">fa-trophy</div>
+    </li>
+    <li><i class="fa fa-truck"></i>
+        <div class="icon-title">fa-truck</div>
+    </li>
+    <li><i class="fa fa-tty"></i>
+        <div class="icon-title">fa-tty</div>
+    </li>
+    <li><i class="fa fa-tv"></i>
+        <div class="icon-title">fa-tv</div>
+    </li>
+    <li><i class="fa fa-umbrella"></i>
+        <div class="icon-title">fa-umbrella</div>
+    </li>
+    <li><i class="fa fa-universal-access"></i>
+        <div class="icon-title">fa-universal-access</div>
+    </li>
+    <li><i class="fa fa-university"></i>
+        <div class="icon-title">fa-university</div>
+    </li>
+    <li><i class="fa fa-unlock"></i>
+        <div class="icon-title">fa-unlock</div>
+    </li>
+    <li><i class="fa fa-unlock-alt"></i>
+        <div class="icon-title">fa-unlock-alt</div>
+    </li>
+    <li><i class="fa fa-unsorted"></i>
+        <div class="icon-title">fa-unsorted</div>
+    </li>
+    <li><i class="fa fa-upload"></i>
+        <div class="icon-title">fa-upload</div>
+    </li>
+    <li><i class="fa fa-user"></i>
+        <div class="icon-title">fa-user</div>
+    </li>
+    <li><i class="fa fa-user-circle"></i>
+        <div class="icon-title">fa-user-circle</div>
+    </li>
+    <li><i class="fa fa-user-circle-o"></i>
+        <div class="icon-title">fa-user-circle-o</div>
+    </li>
+    <li><i class="fa fa-user-o"></i>
+        <div class="icon-title">fa-user-o</div>
+    </li>
+    <li><i class="fa fa-user-plus"></i>
+        <div class="icon-title">fa-user-plus</div>
+    </li>
+    <li><i class="fa fa-user-secret"></i>
+        <div class="icon-title">fa-user-secret</div>
+    </li>
+    <li><i class="fa fa-user-times"></i>
+        <div class="icon-title">fa-user-times</div>
+    </li>
+    <li><i class="fa fa-users"></i>
+        <div class="icon-title">fa-users</div>
+    </li>
+    <li><i class="fa fa-vcard"></i>
+        <div class="icon-title">fa-vcard</div>
+    </li>
+    <li><i class="fa fa-vcard-o"></i>
+        <div class="icon-title">fa-vcard-o</div>
+    </li>
+    <li><i class="fa fa-video-camera"></i>
+        <div class="icon-title">fa-video-camera</div>
+    </li>
+    <li><i class="fa fa-volume-control-phone"></i>
+        <div class="icon-title">fa-volume-control-phone</div>
+    </li>
+    <li><i class="fa fa-volume-down"></i>
+        <div class="icon-title">fa-volume-down</div>
+    </li>
+    <li><i class="fa fa-volume-off"></i>
+        <div class="icon-title">fa-volume-off</div>
+    </li>
+    <li><i class="fa fa-volume-up"></i>
+        <div class="icon-title">fa-volume-up</div>
+    </li>
+    <li><i class="fa fa-warning"></i>
+        <div class="icon-title">fa-warning</div>
+    </li>
+    <li><i class="fa fa-wheelchair"></i>
+        <div class="icon-title">fa-wheelchair</div>
+    </li>
+    <li><i class="fa fa-wheelchair-alt"></i>
+        <div class="icon-title">fa-wheelchair-alt</div>
+    </li>
+    <li><i class="fa fa-wifi"></i>
+        <div class="icon-title">fa-wifi</div>
+    </li>
+    <li><i class="fa fa-window-close"></i>
+        <div class="icon-title">fa-window-close</div>
+    </li>
+    <li><i class="fa fa-window-close-o"></i>
+        <div class="icon-title">fa-window-close-o</div>
+    </li>
+    <li><i class="fa fa-window-maximize"></i>
+        <div class="icon-title">fa-window-maximize</div>
+    </li>
+    <li><i class="fa fa-window-minimize"></i>
+        <div class="icon-title">fa-window-minimize</div>
+    </li>
+    <li><i class="fa fa-window-restore"></i>
+        <div class="icon-title">fa-window-restore</div>
+    </li>
+    <li><i class="fa fa-wrench"></i>
+        <div class="icon-title">fa-wrench</div>
+    </li>
+    <li><i class="fa fa-american-sign-language-interpreting"></i>
+        <div class="icon-title">fa-american-sign-language-interpreting</div>
+    </li>
+    <li><i class="fa fa-asl-interpreting"></i>
+        <div class="icon-title">fa-asl-interpreting</div>
+    </li>
+    <li><i class="fa fa-assistive-listening-systems"></i>
+        <div class="icon-title">fa-assistive-listening-systems</div>
+    </li>
+    <li><i class="fa fa-audio-description"></i>
+        <div class="icon-title">fa-audio-description</div>
+    </li>
+    <li><i class="fa fa-blind"></i>
+        <div class="icon-title">fa-blind</div>
+    </li>
+    <li><i class="fa fa-braille"></i>
+        <div class="icon-title">fa-braille</div>
+    </li>
+    <li><i class="fa fa-cc"></i>
+        <div class="icon-title">fa-cc</div>
+    </li>
+    <li><i class="fa fa-deaf"></i>
+        <div class="icon-title">fa-deaf</div>
+    </li>
+    <li><i class="fa fa-deafness"></i>
+        <div class="icon-title">fa-deafness</div>
+    </li>
+    <li><i class="fa fa-hard-of-hearing"></i>
+        <div class="icon-title">fa-hard-of-hearing</div>
+    </li>
+    <li><i class="fa fa-low-vision"></i>
+        <div class="icon-title">fa-low-vision</div>
+    </li>
+    <li><i class="fa fa-question-circle-o"></i>
+        <div class="icon-title">fa-question-circle-o</div>
+    </li>
+    <li><i class="fa fa-sign-language"></i>
+        <div class="icon-title">fa-sign-language</div>
+    </li>
+    <li><i class="fa fa-signing"></i>
+        <div class="icon-title">fa-signing</div>
+    </li>
+    <li><i class="fa fa-tty"></i>
+        <div class="icon-title">fa-tty</div>
+    </li>
+    <li><i class="fa fa-universal-access"></i>
+        <div class="icon-title">fa-universal-access</div>
+    </li>
+    <li><i class="fa fa-volume-control-phone"></i>
+        <div class="icon-title">fa-volume-control-phone</div>
+    </li>
+    <li><i class="fa fa-wheelchair"></i>
+        <div class="icon-title">fa-wheelchair</div>
+    </li>
+    <li><i class="fa fa-wheelchair-alt"></i>
+        <div class="icon-title">fa-wheelchair-alt</div>
+    </li>
+    <li><i class="fa fa-hand-grab-o"></i>
+        <div class="icon-title">fa-hand-grab-o</div>
+    </li>
+    <li><i class="fa fa-hand-lizard-o"></i>
+        <div class="icon-title">fa-hand-lizard-o</div>
+    </li>
+    <li><i class="fa fa-hand-o-down"></i>
+        <div class="icon-title">fa-hand-o-down</div>
+    </li>
+    <li><i class="fa fa-hand-o-left"></i>
+        <div class="icon-title">fa-hand-o-left</div>
+    </li>
+    <li><i class="fa fa-hand-o-right"></i>
+        <div class="icon-title">fa-hand-o-right</div>
+    </li>
+    <li><i class="fa fa-hand-o-up"></i>
+        <div class="icon-title">fa-hand-o-up</div>
+    </li>
+    <li><i class="fa fa-hand-paper-o"></i>
+        <div class="icon-title">fa-hand-paper-o</div>
+    </li>
+    <li><i class="fa fa-hand-peace-o"></i>
+        <div class="icon-title">fa-hand-peace-o</div>
+    </li>
+    <li><i class="fa fa-hand-pointer-o"></i>
+        <div class="icon-title">fa-hand-pointer-o</div>
+    </li>
+    <li><i class="fa fa-hand-rock-o"></i>
+        <div class="icon-title">fa-hand-rock-o</div>
+    </li>
+    <li><i class="fa fa-hand-scissors-o"></i>
+        <div class="icon-title">fa-hand-scissors-o</div>
+    </li>
+    <li><i class="fa fa-hand-spock-o"></i>
+        <div class="icon-title">fa-hand-spock-o</div>
+    </li>
+    <li><i class="fa fa-hand-stop-o"></i>
+        <div class="icon-title">fa-hand-stop-o</div>
+    </li>
+    <li><i class="fa fa-thumbs-down"></i>
+        <div class="icon-title">fa-thumbs-down</div>
+    </li>
+    <li><i class="fa fa-thumbs-o-down"></i>
+        <div class="icon-title">fa-thumbs-o-down</div>
+    </li>
+    <li><i class="fa fa-thumbs-o-up"></i>
+        <div class="icon-title">fa-thumbs-o-up</div>
+    </li>
+    <li><i class="fa fa-thumbs-up"></i>
+        <div class="icon-title">fa-thumbs-up</div>
+    </li>
+    <li><i class="fa fa-ambulance"></i>
+        <div class="icon-title">fa-ambulance</div>
+    </li>
+    <li><i class="fa fa-automobile"></i>
+        <div class="icon-title">fa-automobile</div>
+    </li>
+    <li><i class="fa fa-bicycle"></i>
+        <div class="icon-title">fa-bicycle</div>
+    </li>
+    <li><i class="fa fa-bus"></i>
+        <div class="icon-title">fa-bus</div>
+    </li>
+    <li><i class="fa fa-cab"></i>
+        <div class="icon-title">fa-cab</div>
+    </li>
+    <li><i class="fa fa-car"></i>
+        <div class="icon-title">fa-car</div>
+    </li>
+    <li><i class="fa fa-fighter-jet"></i>
+        <div class="icon-title">fa-fighter-jet</div>
+    </li>
+    <li><i class="fa fa-motorcycle"></i>
+        <div class="icon-title">fa-motorcycle</div>
+    </li>
+    <li><i class="fa fa-plane"></i>
+        <div class="icon-title">fa-plane</div>
+    </li>
+    <li><i class="fa fa-rocket"></i>
+        <div class="icon-title">fa-rocket</div>
+    </li>
+    <li><i class="fa fa-ship"></i>
+        <div class="icon-title">fa-ship</div>
+    </li>
+    <li><i class="fa fa-space-shuttle"></i>
+        <div class="icon-title">fa-space-shuttle</div>
+    </li>
+    <li><i class="fa fa-subway"></i>
+        <div class="icon-title">fa-subway</div>
+    </li>
+    <li><i class="fa fa-taxi"></i>
+        <div class="icon-title">fa-taxi</div>
+    </li>
+    <li><i class="fa fa-train"></i>
+        <div class="icon-title">fa-train</div>
+    </li>
+    <li><i class="fa fa-truck"></i>
+        <div class="icon-title">fa-truck</div>
+    </li>
+    <li><i class="fa fa-wheelchair"></i>
+        <div class="icon-title">fa-wheelchair</div>
+    </li>
+    <li><i class="fa fa-wheelchair-alt"></i>
+        <div class="icon-title">fa-wheelchair-alt</div>
+    </li>
+    <li><i class="fa fa-genderless"></i>
+        <div class="icon-title">fa-genderless</div>
+    </li>
+    <li><i class="fa fa-intersex"></i>
+        <div class="icon-title">fa-intersex</div>
+    </li>
+    <li><i class="fa fa-mars"></i>
+        <div class="icon-title">fa-mars</div>
+    </li>
+    <li><i class="fa fa-mars-double"></i>
+        <div class="icon-title">fa-mars-double</div>
+    </li>
+    <li><i class="fa fa-mars-stroke"></i>
+        <div class="icon-title">fa-mars-stroke</div>
+    </li>
+    <li><i class="fa fa-mars-stroke-h"></i>
+        <div class="icon-title">fa-mars-stroke-h</div>
+    </li>
+    <li><i class="fa fa-mars-stroke-v"></i>
+        <div class="icon-title">fa-mars-stroke-v</div>
+    </li>
+    <li><i class="fa fa-mercury"></i>
+        <div class="icon-title">fa-mercury</div>
+    </li>
+    <li><i class="fa fa-neuter"></i>
+        <div class="icon-title">fa-neuter</div>
+    </li>
+    <li><i class="fa fa-transgender"></i>
+        <div class="icon-title">fa-transgender</div>
+    </li>
+    <li><i class="fa fa-transgender-alt"></i>
+        <div class="icon-title">fa-transgender-alt</div>
+    </li>
+    <li><i class="fa fa-venus"></i>
+        <div class="icon-title">fa-venus</div>
+    </li>
+    <li><i class="fa fa-venus-double"></i>
+        <div class="icon-title">fa-venus-double</div>
+    </li>
+    <li><i class="fa fa-venus-mars"></i>
+        <div class="icon-title">fa-venus-mars</div>
+    </li>
+    <li><i class="fa fa-file"></i>
+        <div class="icon-title">fa-file</div>
+    </li>
+    <li><i class="fa fa-file-archive-o"></i>
+        <div class="icon-title">fa-file-archive-o</div>
+    </li>
+    <li><i class="fa fa-file-audio-o"></i>
+        <div class="icon-title">fa-file-audio-o</div>
+    </li>
+    <li><i class="fa fa-file-code-o"></i>
+        <div class="icon-title">fa-file-code-o</div>
+    </li>
+    <li><i class="fa fa-file-excel-o"></i>
+        <div class="icon-title">fa-file-excel-o</div>
+    </li>
+    <li><i class="fa fa-file-image-o"></i>
+        <div class="icon-title">fa-file-image-o</div>
+    </li>
+    <li><i class="fa fa-file-movie-o"></i>
+        <div class="icon-title">fa-file-movie-o</div>
+    </li>
+    <li><i class="fa fa-file-o"></i>
+        <div class="icon-title">fa-file-o</div>
+    </li>
+    <li><i class="fa fa-file-pdf-o"></i>
+        <div class="icon-title">fa-file-pdf-o</div>
+    </li>
+    <li><i class="fa fa-file-photo-o"></i>
+        <div class="icon-title">fa-file-photo-o</div>
+    </li>
+    <li><i class="fa fa-file-picture-o"></i>
+        <div class="icon-title">fa-file-picture-o</div>
+    </li>
+    <li><i class="fa fa-file-powerpoint-o"></i>
+        <div class="icon-title">fa-file-powerpoint-o</div>
+    </li>
+    <li><i class="fa fa-file-sound-o"></i>
+        <div class="icon-title">fa-file-sound-o</div>
+    </li>
+    <li><i class="fa fa-file-text"></i>
+        <div class="icon-title">fa-file-text</div>
+    </li>
+    <li><i class="fa fa-file-text-o"></i>
+        <div class="icon-title">fa-file-text-o</div>
+    </li>
+    <li><i class="fa fa-file-video-o"></i>
+        <div class="icon-title">fa-file-video-o</div>
+    </li>
+    <li><i class="fa fa-file-word-o"></i>
+        <div class="icon-title">fa-file-word-o</div>
+    </li>
+    <li><i class="fa fa-file-zip-o"></i>
+        <div class="icon-title">fa-file-zip-o</div>
+    </li>
+    <li><i class="fa fa-circle-o-notch"></i>
+        <div class="icon-title">fa-circle-o-notch</div>
+    </li>
+    <li><i class="fa fa-cog"></i>
+        <div class="icon-title">fa-cog</div>
+    </li>
+    <li><i class="fa fa-gear"></i>
+        <div class="icon-title">fa-gear</div>
+    </li>
+    <li><i class="fa fa-refresh"></i>
+        <div class="icon-title">fa-refresh</div>
+    </li>
+    <li><i class="fa fa-spinner"></i>
+        <div class="icon-title">fa-spinner</div>
+    </li>
+    <li><i class="fa fa-check-square"></i>
+        <div class="icon-title">fa-check-square</div>
+    </li>
+    <li><i class="fa fa-check-square-o"></i>
+        <div class="icon-title">fa-check-square-o</div>
+    </li>
+    <li><i class="fa fa-circle"></i>
+        <div class="icon-title">fa-circle</div>
+    </li>
+    <li><i class="fa fa-circle-o"></i>
+        <div class="icon-title">fa-circle-o</div>
+    </li>
+    <li><i class="fa fa-dot-circle-o"></i>
+        <div class="icon-title">fa-dot-circle-o</div>
+    </li>
+    <li><i class="fa fa-minus-square"></i>
+        <div class="icon-title">fa-minus-square</div>
+    </li>
+    <li><i class="fa fa-minus-square-o"></i>
+        <div class="icon-title">fa-minus-square-o</div>
+    </li>
+    <li><i class="fa fa-plus-square"></i>
+        <div class="icon-title">fa-plus-square</div>
+    </li>
+    <li><i class="fa fa-plus-square-o"></i>
+        <div class="icon-title">fa-plus-square-o</div>
+    </li>
+    <li><i class="fa fa-square"></i>
+        <div class="icon-title">fa-square</div>
+    </li>
+    <li><i class="fa fa-square-o"></i>
+        <div class="icon-title">fa-square-o</div>
+    </li>
+    <li><i class="fa fa-cc-amex"></i>
+        <div class="icon-title">fa-cc-amex</div>
+    </li>
+    <li><i class="fa fa-cc-diners-club"></i>
+        <div class="icon-title">fa-cc-diners-club</div>
+    </li>
+    <li><i class="fa fa-cc-discover"></i>
+        <div class="icon-title">fa-cc-discover</div>
+    </li>
+    <li><i class="fa fa-cc-jcb"></i>
+        <div class="icon-title">fa-cc-jcb</div>
+    </li>
+    <li><i class="fa fa-cc-mastercard"></i>
+        <div class="icon-title">fa-cc-mastercard</div>
+    </li>
+    <li><i class="fa fa-cc-paypal"></i>
+        <div class="icon-title">fa-cc-paypal</div>
+    </li>
+    <li><i class="fa fa-cc-stripe"></i>
+        <div class="icon-title">fa-cc-stripe</div>
+    </li>
+    <li><i class="fa fa-cc-visa"></i>
+        <div class="icon-title">fa-cc-visa</div>
+    </li>
+    <li><i class="fa fa-credit-card"></i>
+        <div class="icon-title">fa-credit-card</div>
+    </li>
+    <li><i class="fa fa-credit-card-alt"></i>
+        <div class="icon-title">fa-credit-card-alt</div>
+    </li>
+    <li><i class="fa fa-google-wallet"></i>
+        <div class="icon-title">fa-google-wallet</div>
+    </li>
+    <li><i class="fa fa-paypal"></i>
+        <div class="icon-title">fa-paypal</div>
+    </li>
+    <li><i class="fa fa-area-chart"></i>
+        <div class="icon-title">fa-area-chart</div>
+    </li>
+    <li><i class="fa fa-bar-chart"></i>
+        <div class="icon-title">fa-bar-chart</div>
+    </li>
+    <li><i class="fa fa-bar-chart-o"></i>
+        <div class="icon-title">fa-bar-chart-o</div>
+    </li>
+    <li><i class="fa fa-line-chart"></i>
+        <div class="icon-title">fa-line-chart</div>
+    </li>
+    <li><i class="fa fa-pie-chart"></i>
+        <div class="icon-title">fa-pie-chart</div>
+    </li>
+    <li><i class="fa fa-bitcoin"></i>
+        <div class="icon-title">fa-bitcoin</div>
+    </li>
+    <li><i class="fa fa-btc"></i>
+        <div class="icon-title">fa-btc</div>
+    </li>
+    <li><i class="fa fa-cny"></i>
+        <div class="icon-title">fa-cny</div>
+    </li>
+    <li><i class="fa fa-dollar"></i>
+        <div class="icon-title">fa-dollar</div>
+    </li>
+    <li><i class="fa fa-eur"></i>
+        <div class="icon-title">fa-eur</div>
+    </li>
+    <li><i class="fa fa-euro"></i>
+        <div class="icon-title">fa-euro</div>
+    </li>
+    <li><i class="fa fa-gbp"></i>
+        <div class="icon-title">fa-gbp</div>
+    </li>
+    <li><i class="fa fa-gg"></i>
+        <div class="icon-title">fa-gg</div>
+    </li>
+    <li><i class="fa fa-gg-circle"></i>
+        <div class="icon-title">fa-gg-circle</div>
+    </li>
+    <li><i class="fa fa-ils"></i>
+        <div class="icon-title">fa-ils</div>
+    </li>
+    <li><i class="fa fa-inr"></i>
+        <div class="icon-title">fa-inr</div>
+    </li>
+    <li><i class="fa fa-jpy"></i>
+        <div class="icon-title">fa-jpy</div>
+    </li>
+    <li><i class="fa fa-krw"></i>
+        <div class="icon-title">fa-krw</div>
+    </li>
+    <li><i class="fa fa-money"></i>
+        <div class="icon-title">fa-money</div>
+    </li>
+    <li><i class="fa fa-rmb"></i>
+        <div class="icon-title">fa-rmb</div>
+    </li>
+    <li><i class="fa fa-rouble"></i>
+        <div class="icon-title">fa-rouble</div>
+    </li>
+    <li><i class="fa fa-rub"></i>
+        <div class="icon-title">fa-rub</div>
+    </li>
+    <li><i class="fa fa-ruble"></i>
+        <div class="icon-title">fa-ruble</div>
+    </li>
+    <li><i class="fa fa-rupee"></i>
+        <div class="icon-title">fa-rupee</div>
+    </li>
+    <li><i class="fa fa-shekel"></i>
+        <div class="icon-title">fa-shekel</div>
+    </li>
+    <li><i class="fa fa-sheqel"></i>
+        <div class="icon-title">fa-sheqel</div>
+    </li>
+    <li><i class="fa fa-try"></i>
+        <div class="icon-title">fa-try</div>
+    </li>
+    <li><i class="fa fa-turkish-lira"></i>
+        <div class="icon-title">fa-turkish-lira</div>
+    </li>
+    <li><i class="fa fa-usd"></i>
+        <div class="icon-title">fa-usd</div>
+    </li>
+    <li><i class="fa fa-won"></i>
+        <div class="icon-title">fa-won</div>
+    </li>
+    <li><i class="fa fa-yen"></i>
+        <div class="icon-title">fa-yen</div>
+    </li>
+    <li><i class="fa fa-align-center"></i>
+        <div class="icon-title">fa-align-center</div>
+    </li>
+    <li><i class="fa fa-align-justify"></i>
+        <div class="icon-title">fa-align-justify</div>
+    </li>
+    <li><i class="fa fa-align-left"></i>
+        <div class="icon-title">fa-align-left</div>
+    </li>
+    <li><i class="fa fa-align-right"></i>
+        <div class="icon-title">fa-align-right</div>
+    </li>
+    <li><i class="fa fa-bold"></i>
+        <div class="icon-title">fa-bold</div>
+    </li>
+    <li><i class="fa fa-chain"></i>
+        <div class="icon-title">fa-chain</div>
+    </li>
+    <li><i class="fa fa-chain-broken"></i>
+        <div class="icon-title">fa-chain-broken</div>
+    </li>
+    <li><i class="fa fa-clipboard"></i>
+        <div class="icon-title">fa-clipboard</div>
+    </li>
+    <li><i class="fa fa-columns"></i>
+        <div class="icon-title">fa-columns</div>
+    </li>
+    <li><i class="fa fa-copy"></i>
+        <div class="icon-title">fa-copy</div>
+    </li>
+    <li><i class="fa fa-cut"></i>
+        <div class="icon-title">fa-cut</div>
+    </li>
+    <li><i class="fa fa-dedent"></i>
+        <div class="icon-title">fa-dedent</div>
+    </li>
+    <li><i class="fa fa-eraser"></i>
+        <div class="icon-title">fa-eraser</div>
+    </li>
+    <li><i class="fa fa-file"></i>
+        <div class="icon-title">fa-file</div>
+    </li>
+    <li><i class="fa fa-file-o"></i>
+        <div class="icon-title">fa-file-o</div>
+    </li>
+    <li><i class="fa fa-file-text"></i>
+        <div class="icon-title">fa-file-text</div>
+    </li>
+    <li><i class="fa fa-file-text-o"></i>
+        <div class="icon-title">fa-file-text-o</div>
+    </li>
+    <li><i class="fa fa-files-o"></i>
+        <div class="icon-title">fa-files-o</div>
+    </li>
+    <li><i class="fa fa-floppy-o"></i>
+        <div class="icon-title">fa-floppy-o</div>
+    </li>
+    <li><i class="fa fa-font"></i>
+        <div class="icon-title">fa-font</div>
+    </li>
+    <li><i class="fa fa-header"></i>
+        <div class="icon-title">fa-header</div>
+    </li>
+    <li><i class="fa fa-indent"></i>
+        <div class="icon-title">fa-indent</div>
+    </li>
+    <li><i class="fa fa-italic"></i>
+        <div class="icon-title">fa-italic</div>
+    </li>
+    <li><i class="fa fa-link"></i>
+        <div class="icon-title">fa-link</div>
+    </li>
+    <li><i class="fa fa-list"></i>
+        <div class="icon-title">fa-list</div>
+    </li>
+    <li><i class="fa fa-list-alt"></i>
+        <div class="icon-title">fa-list-alt</div>
+    </li>
+    <li><i class="fa fa-list-ol"></i>
+        <div class="icon-title">fa-list-ol</div>
+    </li>
+    <li><i class="fa fa-list-ul"></i>
+        <div class="icon-title">fa-list-ul</div>
+    </li>
+    <li><i class="fa fa-outdent"></i>
+        <div class="icon-title">fa-outdent</div>
+    </li>
+    <li><i class="fa fa-paperclip"></i>
+        <div class="icon-title">fa-paperclip</div>
+    </li>
+    <li><i class="fa fa-paragraph"></i>
+        <div class="icon-title">fa-paragraph</div>
+    </li>
+    <li><i class="fa fa-paste"></i>
+        <div class="icon-title">fa-paste</div>
+    </li>
+    <li><i class="fa fa-repeat"></i>
+        <div class="icon-title">fa-repeat</div>
+    </li>
+    <li><i class="fa fa-rotate-left"></i>
+        <div class="icon-title">fa-rotate-left</div>
+    </li>
+    <li><i class="fa fa-rotate-right"></i>
+        <div class="icon-title">fa-rotate-right</div>
+    </li>
+    <li><i class="fa fa-save"></i>
+        <div class="icon-title">fa-save</div>
+    </li>
+    <li><i class="fa fa-scissors"></i>
+        <div class="icon-title">fa-scissors</div>
+    </li>
+    <li><i class="fa fa-strikethrough"></i>
+        <div class="icon-title">fa-strikethrough</div>
+    </li>
+    <li><i class="fa fa-subscript"></i>
+        <div class="icon-title">fa-subscript</div>
+    </li>
+    <li><i class="fa fa-superscript"></i>
+        <div class="icon-title">fa-superscript</div>
+    </li>
+    <li><i class="fa fa-table"></i>
+        <div class="icon-title">fa-table</div>
+    </li>
+    <li><i class="fa fa-text-height"></i>
+        <div class="icon-title">fa-text-height</div>
+    </li>
+    <li><i class="fa fa-text-width"></i>
+        <div class="icon-title">fa-text-width</div>
+    </li>
+    <li><i class="fa fa-th"></i>
+        <div class="icon-title">fa-th</div>
+    </li>
+    <li><i class="fa fa-th-large"></i>
+        <div class="icon-title">fa-th-large</div>
+    </li>
+    <li><i class="fa fa-th-list"></i>
+        <div class="icon-title">fa-th-list</div>
+    </li>
+    <li><i class="fa fa-underline"></i>
+        <div class="icon-title">fa-underline</div>
+    </li>
+    <li><i class="fa fa-undo"></i>
+        <div class="icon-title">fa-undo</div>
+    </li>
+    <li><i class="fa fa-unlink"></i>
+        <div class="icon-title">fa-unlink</div>
+    </li>
+    <li><i class="fa fa-angle-double-down"></i>
+        <div class="icon-title">fa-angle-double-down</div>
+    </li>
+    <li><i class="fa fa-angle-double-left"></i>
+        <div class="icon-title">fa-angle-double-left</div>
+    </li>
+    <li><i class="fa fa-angle-double-right"></i>
+        <div class="icon-title">fa-angle-double-right</div>
+    </li>
+    <li><i class="fa fa-angle-double-up"></i>
+        <div class="icon-title">fa-angle-double-up</div>
+    </li>
+    <li><i class="fa fa-angle-down"></i>
+        <div class="icon-title">fa-angle-down</div>
+    </li>
+    <li><i class="fa fa-angle-left"></i>
+        <div class="icon-title">fa-angle-left</div>
+    </li>
+    <li><i class="fa fa-angle-right"></i>
+        <div class="icon-title">fa-angle-right</div>
+    </li>
+    <li><i class="fa fa-angle-up"></i>
+        <div class="icon-title">fa-angle-up</div>
+    </li>
+    <li><i class="fa fa-arrow-circle-down"></i>
+        <div class="icon-title">fa-arrow-circle-down</div>
+    </li>
+    <li><i class="fa fa-arrow-circle-left"></i>
+        <div class="icon-title">fa-arrow-circle-left</div>
+    </li>
+    <li><i class="fa fa-arrow-circle-o-down"></i>
+        <div class="icon-title">fa-arrow-circle-o-down</div>
+    </li>
+    <li><i class="fa fa-arrow-circle-o-left"></i>
+        <div class="icon-title">fa-arrow-circle-o-left</div>
+    </li>
+    <li><i class="fa fa-arrow-circle-o-right"></i>
+        <div class="icon-title">fa-arrow-circle-o-right</div>
+    </li>
+    <li><i class="fa fa-arrow-circle-o-up"></i>
+        <div class="icon-title">fa-arrow-circle-o-up</div>
+    </li>
+    <li><i class="fa fa-arrow-circle-right"></i>
+        <div class="icon-title">fa-arrow-circle-right</div>
+    </li>
+    <li><i class="fa fa-arrow-circle-up"></i>
+        <div class="icon-title">fa-arrow-circle-up</div>
+    </li>
+    <li><i class="fa fa-arrow-down"></i>
+        <div class="icon-title">fa-arrow-down</div>
+    </li>
+    <li><i class="fa fa-arrow-left"></i>
+        <div class="icon-title">fa-arrow-left</div>
+    </li>
+    <li><i class="fa fa-arrow-right"></i>
+        <div class="icon-title">fa-arrow-right</div>
+    </li>
+    <li><i class="fa fa-arrow-up"></i>
+        <div class="icon-title">fa-arrow-up</div>
+    </li>
+    <li><i class="fa fa-arrows"></i>
+        <div class="icon-title">fa-arrows</div>
+    </li>
+    <li><i class="fa fa-arrows-alt"></i>
+        <div class="icon-title">fa-arrows-alt</div>
+    </li>
+    <li><i class="fa fa-arrows-h"></i>
+        <div class="icon-title">fa-arrows-h</div>
+    </li>
+    <li><i class="fa fa-arrows-v"></i>
+        <div class="icon-title">fa-arrows-v</div>
+    </li>
+    <li><i class="fa fa-caret-down"></i>
+        <div class="icon-title">fa-caret-down</div>
+    </li>
+    <li><i class="fa fa-caret-left"></i>
+        <div class="icon-title">fa-caret-left</div>
+    </li>
+    <li><i class="fa fa-caret-right"></i>
+        <div class="icon-title">fa-caret-right</div>
+    </li>
+    <li><i class="fa fa-caret-square-o-down"></i>
+        <div class="icon-title">fa-caret-square-o-down</div>
+    </li>
+    <li><i class="fa fa-caret-square-o-left"></i>
+        <div class="icon-title">fa-caret-square-o-left</div>
+    </li>
+    <li><i class="fa fa-caret-square-o-right"></i>
+        <div class="icon-title">fa-caret-square-o-right</div>
+    </li>
+    <li><i class="fa fa-caret-square-o-up"></i>
+        <div class="icon-title">fa-caret-square-o-up</div>
+    </li>
+    <li><i class="fa fa-caret-up"></i>
+        <div class="icon-title">fa-caret-up</div>
+    </li>
+    <li><i class="fa fa-chevron-circle-down"></i>
+        <div class="icon-title">fa-chevron-circle-down</div>
+    </li>
+    <li><i class="fa fa-chevron-circle-left"></i>
+        <div class="icon-title">fa-chevron-circle-left</div>
+    </li>
+    <li><i class="fa fa-chevron-circle-right"></i>
+        <div class="icon-title">fa-chevron-circle-right</div>
+    </li>
+    <li><i class="fa fa-chevron-circle-up"></i>
+        <div class="icon-title">fa-chevron-circle-up</div>
+    </li>
+    <li><i class="fa fa-chevron-down"></i>
+        <div class="icon-title">fa-chevron-down</div>
+    </li>
+    <li><i class="fa fa-chevron-left"></i>
+        <div class="icon-title">fa-chevron-left</div>
+    </li>
+    <li><i class="fa fa-chevron-right"></i>
+        <div class="icon-title">fa-chevron-right</div>
+    </li>
+    <li><i class="fa fa-chevron-up"></i>
+        <div class="icon-title">fa-chevron-up</div>
+    </li>
+    <li><i class="fa fa-exchange"></i>
+        <div class="icon-title">fa-exchange</div>
+    </li>
+    <li><i class="fa fa-hand-o-down"></i>
+        <div class="icon-title">fa-hand-o-down</div>
+    </li>
+    <li><i class="fa fa-hand-o-left"></i>
+        <div class="icon-title">fa-hand-o-left</div>
+    </li>
+    <li><i class="fa fa-hand-o-right"></i>
+        <div class="icon-title">fa-hand-o-right</div>
+    </li>
+    <li><i class="fa fa-hand-o-up"></i>
+        <div class="icon-title">fa-hand-o-up</div>
+    </li>
+    <li><i class="fa fa-long-arrow-down"></i>
+        <div class="icon-title">fa-long-arrow-down</div>
+    </li>
+    <li><i class="fa fa-long-arrow-left"></i>
+        <div class="icon-title">fa-long-arrow-left</div>
+    </li>
+    <li><i class="fa fa-long-arrow-right"></i>
+        <div class="icon-title">fa-long-arrow-right</div>
+    </li>
+    <li><i class="fa fa-long-arrow-up"></i>
+        <div class="icon-title">fa-long-arrow-up</div>
+    </li>
+    <li><i class="fa fa-toggle-down"></i>
+        <div class="icon-title">fa-toggle-down</div>
+    </li>
+    <li><i class="fa fa-toggle-left"></i>
+        <div class="icon-title">fa-toggle-left</div>
+    </li>
+    <li><i class="fa fa-toggle-right"></i>
+        <div class="icon-title">fa-toggle-right</div>
+    </li>
+    <li><i class="fa fa-toggle-up"></i>
+        <div class="icon-title">fa-toggle-up</div>
+    </li>
+    <li><i class="fa fa-arrows-alt"></i>
+        <div class="icon-title">fa-arrows-alt</div>
+    </li>
+    <li><i class="fa fa-backward"></i>
+        <div class="icon-title">fa-backward</div>
+    </li>
+    <li><i class="fa fa-compress"></i>
+        <div class="icon-title">fa-compress</div>
+    </li>
+    <li><i class="fa fa-eject"></i>
+        <div class="icon-title">fa-eject</div>
+    </li>
+    <li><i class="fa fa-expand"></i>
+        <div class="icon-title">fa-expand</div>
+    </li>
+    <li><i class="fa fa-fast-backward"></i>
+        <div class="icon-title">fa-fast-backward</div>
+    </li>
+    <li><i class="fa fa-fast-forward"></i>
+        <div class="icon-title">fa-fast-forward</div>
+    </li>
+    <li><i class="fa fa-forward"></i>
+        <div class="icon-title">fa-forward</div>
+    </li>
+    <li><i class="fa fa-pause"></i>
+        <div class="icon-title">fa-pause</div>
+    </li>
+    <li><i class="fa fa-pause-circle"></i>
+        <div class="icon-title">fa-pause-circle</div>
+    </li>
+    <li><i class="fa fa-pause-circle-o"></i>
+        <div class="icon-title">fa-pause-circle-o</div>
+    </li>
+    <li><i class="fa fa-play"></i>
+        <div class="icon-title">fa-play</div>
+    </li>
+    <li><i class="fa fa-play-circle"></i>
+        <div class="icon-title">fa-play-circle</div>
+    </li>
+    <li><i class="fa fa-play-circle-o"></i>
+        <div class="icon-title">fa-play-circle-o</div>
+    </li>
+    <li><i class="fa fa-random"></i>
+        <div class="icon-title">fa-random</div>
+    </li>
+    <li><i class="fa fa-step-backward"></i>
+        <div class="icon-title">fa-step-backward</div>
+    </li>
+    <li><i class="fa fa-step-forward"></i>
+        <div class="icon-title">fa-step-forward</div>
+    </li>
+    <li><i class="fa fa-stop"></i>
+        <div class="icon-title">fa-stop</div>
+    </li>
+    <li><i class="fa fa-stop-circle"></i>
+        <div class="icon-title">fa-stop-circle</div>
+    </li>
+    <li><i class="fa fa-stop-circle-o"></i>
+        <div class="icon-title">fa-stop-circle-o</div>
+    </li>
+    <li><i class="fa fa-youtube-play"></i>
+        <div class="icon-title">fa-youtube-play</div>
+    </li>
+    <li><i class="fa fa-500px"></i>
+        <div class="icon-title">fa-500px</div>
+    </li>
+    <li><i class="fa fa-adn"></i>
+        <div class="icon-title">fa-adn</div>
+    </li>
+    <li><i class="fa fa-amazon"></i>
+        <div class="icon-title">fa-amazon</div>
+    </li>
+    <li><i class="fa fa-android"></i>
+        <div class="icon-title">fa-android</div>
+    </li>
+    <li><i class="fa fa-angellist"></i>
+        <div class="icon-title">fa-angellist</div>
+    </li>
+    <li><i class="fa fa-apple"></i>
+        <div class="icon-title">fa-apple</div>
+    </li>
+    <li><i class="fa fa-bandcamp"></i>
+        <div class="icon-title">fa-bandcamp</div>
+    </li>
+    <li><i class="fa fa-behance"></i>
+        <div class="icon-title">fa-behance</div>
+    </li>
+    <li><i class="fa fa-behance-square"></i>
+        <div class="icon-title">fa-behance-square</div>
+    </li>
+    <li><i class="fa fa-bitbucket"></i>
+        <div class="icon-title">fa-bitbucket</div>
+    </li>
+    <li><i class="fa fa-bitbucket-square"></i>
+        <div class="icon-title">fa-bitbucket-square</div>
+    </li>
+    <li><i class="fa fa-bitcoin"></i>
+        <div class="icon-title">fa-bitcoin</div>
+    </li>
+    <li><i class="fa fa-black-tie"></i>
+        <div class="icon-title">fa-black-tie</div>
+    </li>
+    <li><i class="fa fa-bluetooth"></i>
+        <div class="icon-title">fa-bluetooth</div>
+    </li>
+    <li><i class="fa fa-bluetooth-b"></i>
+        <div class="icon-title">fa-bluetooth-b</div>
+    </li>
+    <li><i class="fa fa-btc"></i>
+        <div class="icon-title">fa-btc</div>
+    </li>
+    <li><i class="fa fa-buysellads"></i>
+        <div class="icon-title">fa-buysellads</div>
+    </li>
+    <li><i class="fa fa-cc-amex"></i>
+        <div class="icon-title">fa-cc-amex</div>
+    </li>
+    <li><i class="fa fa-cc-diners-club"></i>
+        <div class="icon-title">fa-cc-diners-club</div>
+    </li>
+    <li><i class="fa fa-cc-discover"></i>
+        <div class="icon-title">fa-cc-discover</div>
+    </li>
+    <li><i class="fa fa-cc-jcb"></i>
+        <div class="icon-title">fa-cc-jcb</div>
+    </li>
+    <li><i class="fa fa-cc-mastercard"></i>
+        <div class="icon-title">fa-cc-mastercard</div>
+    </li>
+    <li><i class="fa fa-cc-paypal"></i>
+        <div class="icon-title">fa-cc-paypal</div>
+    </li>
+    <li><i class="fa fa-cc-stripe"></i>
+        <div class="icon-title">fa-cc-stripe</div>
+    </li>
+    <li><i class="fa fa-cc-visa"></i>
+        <div class="icon-title">fa-cc-visa</div>
+    </li>
+    <li><i class="fa fa-chrome"></i>
+        <div class="icon-title">fa-chrome</div>
+    </li>
+    <li><i class="fa fa-codepen"></i>
+        <div class="icon-title">fa-codepen</div>
+    </li>
+    <li><i class="fa fa-codiepie"></i>
+        <div class="icon-title">fa-codiepie</div>
+    </li>
+    <li><i class="fa fa-connectdevelop"></i>
+        <div class="icon-title">fa-connectdevelop</div>
+    </li>
+    <li><i class="fa fa-contao"></i>
+        <div class="icon-title">fa-contao</div>
+    </li>
+    <li><i class="fa fa-css3"></i>
+        <div class="icon-title">fa-css3</div>
+    </li>
+    <li><i class="fa fa-dashcube"></i>
+        <div class="icon-title">fa-dashcube</div>
+    </li>
+    <li><i class="fa fa-delicious"></i>
+        <div class="icon-title">fa-delicious</div>
+    </li>
+    <li><i class="fa fa-deviantart"></i>
+        <div class="icon-title">fa-deviantart</div>
+    </li>
+    <li><i class="fa fa-digg"></i>
+        <div class="icon-title">fa-digg</div>
+    </li>
+    <li><i class="fa fa-dribbble"></i>
+        <div class="icon-title">fa-dribbble</div>
+    </li>
+    <li><i class="fa fa-dropbox"></i>
+        <div class="icon-title">fa-dropbox</div>
+    </li>
+    <li><i class="fa fa-drupal"></i>
+        <div class="icon-title">fa-drupal</div>
+    </li>
+    <li><i class="fa fa-edge"></i>
+        <div class="icon-title">fa-edge</div>
+    </li>
+    <li><i class="fa fa-eercast"></i>
+        <div class="icon-title">fa-eercast</div>
+    </li>
+    <li><i class="fa fa-empire"></i>
+        <div class="icon-title">fa-empire</div>
+    </li>
+    <li><i class="fa fa-envira"></i>
+        <div class="icon-title">fa-envira</div>
+    </li>
+    <li><i class="fa fa-etsy"></i>
+        <div class="icon-title">fa-etsy</div>
+    </li>
+    <li><i class="fa fa-expeditedssl"></i>
+        <div class="icon-title">fa-expeditedssl</div>
+    </li>
+    <li><i class="fa fa-fa"></i>
+        <div class="icon-title">fa-fa</div>
+    </li>
+    <li><i class="fa fa-facebook"></i>
+        <div class="icon-title">fa-facebook</div>
+    </li>
+    <li><i class="fa fa-facebook-f"></i>
+        <div class="icon-title">fa-facebook-f</div>
+    </li>
+    <li><i class="fa fa-facebook-official"></i>
+        <div class="icon-title">fa-facebook-official</div>
+    </li>
+    <li><i class="fa fa-facebook-square"></i>
+        <div class="icon-title">fa-facebook-square</div>
+    </li>
+    <li><i class="fa fa-firefox"></i>
+        <div class="icon-title">fa-firefox</div>
+    </li>
+    <li><i class="fa fa-first-order"></i>
+        <div class="icon-title">fa-first-order</div>
+    </li>
+    <li><i class="fa fa-flickr"></i>
+        <div class="icon-title">fa-flickr</div>
+    </li>
+    <li><i class="fa fa-font-awesome"></i>
+        <div class="icon-title">fa-font-awesome</div>
+    </li>
+    <li><i class="fa fa-fonticons"></i>
+        <div class="icon-title">fa-fonticons</div>
+    </li>
+    <li><i class="fa fa-fort-awesome"></i>
+        <div class="icon-title">fa-fort-awesome</div>
+    </li>
+    <li><i class="fa fa-forumbee"></i>
+        <div class="icon-title">fa-forumbee</div>
+    </li>
+    <li><i class="fa fa-foursquare"></i>
+        <div class="icon-title">fa-foursquare</div>
+    </li>
+    <li><i class="fa fa-free-code-camp"></i>
+        <div class="icon-title">fa-free-code-camp</div>
+    </li>
+    <li><i class="fa fa-ge"></i>
+        <div class="icon-title">fa-ge</div>
+    </li>
+    <li><i class="fa fa-get-pocket"></i>
+        <div class="icon-title">fa-get-pocket</div>
+    </li>
+    <li><i class="fa fa-gg"></i>
+        <div class="icon-title">fa-gg</div>
+    </li>
+    <li><i class="fa fa-gg-circle"></i>
+        <div class="icon-title">fa-gg-circle</div>
+    </li>
+    <li><i class="fa fa-git"></i>
+        <div class="icon-title">fa-git</div>
+    </li>
+    <li><i class="fa fa-git-square"></i>
+        <div class="icon-title">fa-git-square</div>
+    </li>
+    <li><i class="fa fa-github"></i>
+        <div class="icon-title">fa-github</div>
+    </li>
+    <li><i class="fa fa-github-alt"></i>
+        <div class="icon-title">fa-github-alt</div>
+    </li>
+    <li><i class="fa fa-github-square"></i>
+        <div class="icon-title">fa-github-square</div>
+    </li>
+    <li><i class="fa fa-gitlab"></i>
+        <div class="icon-title">fa-gitlab</div>
+    </li>
+    <li><i class="fa fa-gittip"></i>
+        <div class="icon-title">fa-gittip</div>
+    </li>
+    <li><i class="fa fa-glide"></i>
+        <div class="icon-title">fa-glide</div>
+    </li>
+    <li><i class="fa fa-glide-g"></i>
+        <div class="icon-title">fa-glide-g</div>
+    </li>
+    <li><i class="fa fa-google"></i>
+        <div class="icon-title">fa-google</div>
+    </li>
+    <li><i class="fa fa-google-plus"></i>
+        <div class="icon-title">fa-google-plus</div>
+    </li>
+    <li><i class="fa fa-google-plus-circle"></i>
+        <div class="icon-title">fa-google-plus-circle</div>
+    </li>
+    <li><i class="fa fa-google-plus-official"></i>
+        <div class="icon-title">fa-google-plus-official</div>
+    </li>
+    <li><i class="fa fa-google-plus-square"></i>
+        <div class="icon-title">fa-google-plus-square</div>
+    </li>
+    <li><i class="fa fa-google-wallet"></i>
+        <div class="icon-title">fa-google-wallet</div>
+    </li>
+    <li><i class="fa fa-gratipay"></i>
+        <div class="icon-title">fa-gratipay</div>
+    </li>
+    <li><i class="fa fa-grav"></i>
+        <div class="icon-title">fa-grav</div>
+    </li>
+    <li><i class="fa fa-hacker-news"></i>
+        <div class="icon-title">fa-hacker-news</div>
+    </li>
+    <li><i class="fa fa-houzz"></i>
+        <div class="icon-title">fa-houzz</div>
+    </li>
+    <li><i class="fa fa-html5"></i>
+        <div class="icon-title">fa-html5</div>
+    </li>
+    <li><i class="fa fa-imdb"></i>
+        <div class="icon-title">fa-imdb</div>
+    </li>
+    <li><i class="fa fa-instagram"></i>
+        <div class="icon-title">fa-instagram</div>
+    </li>
+    <li><i class="fa fa-internet-explorer"></i>
+        <div class="icon-title">fa-internet-explorer</div>
+    </li>
+    <li><i class="fa fa-ioxhost"></i>
+        <div class="icon-title">fa-ioxhost</div>
+    </li>
+    <li><i class="fa fa-joomla"></i>
+        <div class="icon-title">fa-joomla</div>
+    </li>
+    <li><i class="fa fa-jsfiddle"></i>
+        <div class="icon-title">fa-jsfiddle</div>
+    </li>
+    <li><i class="fa fa-lastfm"></i>
+        <div class="icon-title">fa-lastfm</div>
+    </li>
+    <li><i class="fa fa-lastfm-square"></i>
+        <div class="icon-title">fa-lastfm-square</div>
+    </li>
+    <li><i class="fa fa-leanpub"></i>
+        <div class="icon-title">fa-leanpub</div>
+    </li>
+    <li><i class="fa fa-linkedin"></i>
+        <div class="icon-title">fa-linkedin</div>
+    </li>
+    <li>
+        <i class="fa fa-linkedin-square"></i>
+        <div class="icon-title">fa-linkedin-square</div>
+    </li>
+    <li>
+        <i class="fa fa-linode"></i>
+        <div class="icon-title">fa-linode</div>
+    </li>
+    <li>
+        <i class="fa fa-linux"></i>
+        <div class="icon-title">fa-linux</div>
+    </li>
+    <li>
+        <i class="fa fa-maxcdn"></i>
+        <div class="icon-title">fa-maxcdn</div>
+    </li>
+    <li>
+        <i class="fa fa-meanpath"></i>
+        <div class="icon-title">fa-meanpath</div>
+    </li>
+    <li>
+        <i class="fa fa-medium"></i>
+        <div class="icon-title">fa-medium</div>
+    </li>
+    <li>
+        <i class="fa fa-meetup"></i>
+        <div class="icon-title">fa-meetup</div>
+    </li>
+    <li>
+        <i class="fa fa-mixcloud"></i>
+        <div class="icon-title">fa-mixcloud</div>
+    </li>
+    <li>
+        <i class="fa fa-modx"></i>
+        <div class="icon-title">fa-modx</div>
+    </li>
+    <li>
+        <i class="fa fa-odnoklassniki"></i>
+        <div class="icon-title">fa-odnoklassniki</div>
+    </li>
+    <li>
+        <i class="fa fa-odnoklassniki-square"></i>
+        <div class="icon-title">fa-odnoklassniki-square</div>
+    </li>
+    <li>
+        <i class="fa fa-opencart"></i>
+        <div class="icon-title">fa-opencart</div>
+    </li>
+    <li>
+        <i class="fa fa-openid"></i>
+        <div class="icon-title">fa-openid</div>
+    </li>
+    <li>
+        <i class="fa fa-opera"></i>
+        <div class="icon-title">fa-opera</div>
+    </li>
+    <li>
+        <i class="fa fa-optin-monster"></i>
+        <div class="icon-title">fa-optin-monster</div>
+    </li>
+    <li>
+        <i class="fa fa-pagelines"></i>
+        <div class="icon-title">fa-pagelines</div>
+    </li>
+    <li>
+        <i class="fa fa-paypal"></i>
+        <div class="icon-title">fa-paypal</div>
+    </li>
+    <li>
+        <i class="fa fa-pied-piper"></i>
+        <div class="icon-title">fa-pied-piper</div>
+    </li>
+    <li>
+        <i class="fa fa-pied-piper-alt"></i>
+        <div class="icon-title">fa-pied-piper-alt</div>
+    </li>
+    <li>
+        <i class="fa fa-pied-piper-pp"></i>
+        <div class="icon-title">fa-pied-piper-pp</div>
+    </li>
+    <li>
+        <i class="fa fa-pinterest"></i>
+        <div class="icon-title">fa-pinterest</div>
+    </li>
+    <li>
+        <i class="fa fa-pinterest-p"></i>
+        <div class="icon-title">fa-pinterest-p</div>
+    </li>
+    <li>
+        <i class="fa fa-pinterest-square"></i>
+        <div class="icon-title">fa-pinterest-square</div>
+    </li>
+    <li>
+        <i class="fa fa-product-hunt"></i>
+        <div class="icon-title">fa-product-hunt</div>
+    </li>
+    <li>
+        <i class="fa fa-qq"></i>
+        <div class="icon-title">fa-qq</div>
+    </li>
+    <li>
+        <i class="fa fa-quora"></i>
+        <div class="icon-title">fa-quora</div>
+    </li>
+    <li>
+        <i class="fa fa-ra"></i>
+        <div class="icon-title">fa-ra</div>
+    </li>
+    <li>
+        <i class="fa fa-ravelry"></i>
+        <div class="icon-title">fa-ravelry</div>
+    </li>
+    <li>
+        <i class="fa fa-rebel"></i>
+        <div class="icon-title">fa-rebel</div>
+    </li>
+    <li>
+        <i class="fa fa-reddit"></i>
+        <div class="icon-title">fa-reddit</div>
+    </li>
+    <li>
+        <i class="fa fa-reddit-alien"></i>
+        <div class="icon-title">fa-reddit-alien</div>
+    </li>
+    <li>
+        <i class="fa fa-reddit-square"></i>
+        <div class="icon-title">fa-reddit-square</div>
+    </li>
+    <li>
+        <i class="fa fa-renren"></i>
+        <div class="icon-title">fa-renren</div>
+    </li>
+    <li>
+        <i class="fa fa-resistance"></i>
+        <div class="icon-title">fa-resistance</div>
+    </li>
+    <li>
+        <i class="fa fa-safari"></i>
+        <div class="icon-title">fa-safari</div>
+    </li>
+    <li>
+        <i class="fa fa-scribd"></i>
+        <div class="icon-title">fa-scribd</div>
+    </li>
+    <li>
+        <i class="fa fa-sellsy"></i>
+        <div class="icon-title">fa-sellsy</div>
+    </li>
+    <li>
+        <i class="fa fa-share-alt"></i>
+        <div class="icon-title">fa-share-alt</div>
+    </li>
+    <li>
+        <i class="fa fa-share-alt-square"></i>
+        <div class="icon-title">fa-share-alt-square</div>
+    </li>
+    <li>
+        <i class="fa fa-shirtsinbulk"></i>
+        <div class="icon-title">fa-shirtsinbulk</div>
+    </li>
+    <li>
+        <i class="fa fa-simplybuilt"></i>
+        <div class="icon-title">fa-simplybuilt</div>
+    </li>
+    <li>
+        <i class="fa fa-skyatlas"></i>
+        <div class="icon-title">fa-skyatlas</div>
+    </li>
+    <li>
+        <i class="fa fa-skype"></i>
+        <div class="icon-title">fa-skype</div>
+    </li>
+    <li>
+        <i class="fa fa-slack"></i>
+        <div class="icon-title">fa-slack</div>
+    </li>
+    <li>
+        <i class="fa fa-slideshare"></i>
+        <div class="icon-title">fa-slideshare</div>
+    </li>
+    <li>
+        <i class="fa fa-snapchat"></i>
+        <div class="icon-title">fa-snapchat</div>
+    </li>
+    <li>
+        <i class="fa fa-snapchat-ghost"></i>
+        <div class="icon-title">fa-snapchat-ghost</div>
+    </li>
+    <li>
+        <i class="fa fa-snapchat-square"></i>
+        <div class="icon-title">fa-snapchat-square</div>
+    </li>
+    <li>
+        <i class="fa fa-soundcloud"></i>
+        <div class="icon-title">fa-soundcloud</div>
+    </li>
+    <li>
+        <i class="fa fa-spotify"></i>
+        <div class="icon-title">fa-spotify</div>
+    </li>
+    <li>
+        <i class="fa fa-stack-exchange"></i>
+        <div class="icon-title">fa-stack-exchange</div>
+    </li>
+    <li>
+        <i class="fa fa-stack-overflow"></i>
+        <div class="icon-title">fa-stack-overflow</div>
+    </li>
+    <li>
+        <i class="fa fa-steam"></i>
+        <div class="icon-title">fa-steam</div>
+    </li>
+    <li>
+        <i class="fa fa-steam-square"></i>
+        <div class="icon-title">fa-steam-square</div>
+    </li>
+    <li>
+        <i class="fa fa-stumbleupon"></i>
+        <div class="icon-title">fa-stumbleupon</div>
+    </li>
+    <li>
+        <i class="fa fa-stumbleupon-circle"></i>
+        <div class="icon-title">fa-stumbleupon-circle</div>
+    </li>
+    <li>
+        <i class="fa fa-superpowers"></i>
+        <div class="icon-title">fa-superpowers</div>
+    </li>
+    <li>
+        <i class="fa fa-telegram"></i>
+        <div class="icon-title">fa-telegram</div>
+    </li>
+    <li>
+        <i class="fa fa-tencent-weibo"></i>
+        <div class="icon-title">fa-tencent-weibo</div>
+    </li>
+    <li>
+        <i class="fa fa-themeisle"></i>
+        <div class="icon-title">fa-themeisle</div>
+    </li>
+    <li>
+        <i class="fa fa-trello"></i>
+        <div class="icon-title">fa-trello</div>
+    </li>
+    <li>
+        <i class="fa fa-tripadvisor"></i>
+        <div class="icon-title">fa-tripadvisor</div>
+    </li>
+    <li>
+        <i class="fa fa-tumblr"></i>
+        <div class="icon-title">fa-tumblr</div>
+    </li>
+    <li>
+        <i class="fa fa-tumblr-square"></i>
+        <div class="icon-title">fa-tumblr-square</div>
+    </li>
+    <li>
+        <i class="fa fa-twitch"></i>
+        <div class="icon-title">fa-twitch</div>
+    </li>
+    <li>
+        <i class="fa fa-twitter"></i>
+        <div class="icon-title">fa-twitter</div>
+    </li>
+    <li>
+        <i class="fa fa-twitter-square"></i>
+        <div class="icon-title">fa-twitter-square</div>
+    </li>
+    <li>
+        <i class="fa fa-usb"></i>
+        <div class="icon-title">fa-usb</div>
+    </li>
+    <li>
+        <i class="fa fa-viacoin"></i>
+        <div class="icon-title">fa-viacoin</div>
+    </li>
+    <li>
+        <i class="fa fa-viadeo"></i>
+        <div class="icon-title">fa-viadeo</div>
+    </li>
+    <li>
+        <i class="fa fa-viadeo-square"></i>
+        <div class="icon-title">fa-viadeo-square</div>
+    </li>
+    <li>
+        <i class="fa fa-vimeo"></i>
+        <div class="icon-title">fa-vimeo</div>
+    </li>
+    <li>
+        <i class="fa fa-vimeo-square"></i>
+        <div class="icon-title">fa-vimeo-square</div>
+    </li>
+    <li>
+        <i class="fa fa-vine"></i>
+        <div class="icon-title">fa-vine</div>
+    </li>
+    <li>
+        <i class="fa fa-vk"></i>
+        <div class="icon-title">fa-vk</div>
+    </li>
+    <li>
+        <i class="fa fa-wechat"></i>
+        <div class="icon-title">fa-wechat</div>
+    </li>
+    <li>
+        <i class="fa fa-weibo"></i>
+        <div class="icon-title">fa-weibo</div>
+    </li>
+    <li>
+        <i class="fa fa-weixin"></i>
+        <div class="icon-title">fa-weixin</div>
+    </li>
+    <li>
+        <i class="fa fa-whatsapp"></i>
+        <div class="icon-title">fa-whatsapp</div>
+    </li>
+    <li>
+        <i class="fa fa-wikipedia-w"></i>
+        <div class="icon-title">fa-wikipedia-w</div>
+    </li>
+    <li>
+        <i class="fa fa-windows"></i>
+        <div class="icon-title">fa-windows</div>
+    </li>
+    <li>
+        <i class="fa fa-wordpress"></i>
+        <div class="icon-title">fa-wordpress</div>
+    </li>
+    <li>
+        <i class="fa fa-wpbeginner"></i>
+        <div class="icon-title">fa-wpbeginner</div>
+    </li>
+    <li>
+        <i class="fa fa-wpexplorer"></i>
+        <div class="icon-title">fa-wpexplorer</div>
+    </li>
+    <li>
+        <i class="fa fa-wpforms"></i>
+        <div class="icon-title">fa-wpforms</div>
+    </li>
+    <li>
+        <i class="fa fa-xing"></i>
+        <div class="icon-title">fa-xing</div>
+    </li>
+    <li>
+        <i class="fa fa-xing-square"></i>
+        <div class="icon-title">fa-xing-square</div>
+    </li>
+    <li>
+        <i class="fa fa-y-combinator"></i>
+        <div class="icon-title">fa-y-combinator</div>
+    </li>
+    <li>
+        <i class="fa fa-y-combinator-square"></i>
+        <div class="icon-title">fa-y-combinator-square</div>
+    </li>
+    <li>
+        <i class="fa fa-yahoo"></i>
+        <div class="icon-title">fa-yahoo</div>
+    </li>
+    <li>
+        <i class="fa fa-yc"></i>
+        <div class="icon-title">fa-yc</div>
+    </li>
+    <li>
+        <i class="fa fa-yc-square"></i>
+        <div class="icon-title">fa-yc-square</div>
+    </li>
+    <li>
+        <i class="fa fa-yelp"></i>
+        <div class="icon-title">fa-yelp</div>
+    </li>
+    <li>
+        <i class="fa fa-yoast"></i>
+        <div class="icon-title">fa-yoast</div>
+    </li>
+    <li>
+        <i class="fa fa-youtube"></i>
+        <div class="icon-title">fa-youtube</div>
+    </li>
+    <li>
+        <i class="fa fa-youtube-play"></i>
+        <div class="icon-title">fa-youtube-play</div>
+    </li>
+    <li>
+        <i class="fa fa-youtube-square"></i>
+        <div class="icon-title">fa-youtube-square</div>
+    </li>
+    <li>
+        <i class="fa fa-ambulance"></i>
+        <div class="icon-title">fa-ambulance</div>
+    </li>
+    <li>
+        <i class="fa fa-h-square"></i>
+        <div class="icon-title">fa-h-square</div>
+    </li>
+    <li>
+        <i class="fa fa-heart"></i>
+        <div class="icon-title">fa-heart</div>
+    </li>
+    <li>
+        <i class="fa fa-heart-o"></i>
+        <div class="icon-title">fa-heart-o</div>
+    </li>
+    <li>
+        <i class="fa fa-heartbeat"></i>
+        <div class="icon-title">fa-heartbeat</div>
+    </li>
+    <li>
+        <i class="fa fa-hospital-o"></i>
+        <div class="icon-title">fa-hospital-o</div>
+    </li>
+    <li>
+        <i class="fa fa-medkit"></i>
+        <div class="icon-title">fa-medkit</div>
+    </li>
+    <li>
+        <i class="fa fa-plus-square"></i>
+        <div class="icon-title">fa-plus-square</div>
+    </li>
+    <li>
+        <i class="fa fa-stethoscope"></i>
+        <div class="icon-title">fa-stethoscope</div>
+    </li>
+    <li>
+        <i class="fa fa-user-md"></i>
+        <div class="icon-title">fa-user-md</div>
+    </li>
+    <li>
+        <i class="fa fa-wheelchair"></i>
+        <div class="icon-title">fa-wheelchair</div>
+    </li>
+    <li>
+        <i class="fa fa-wheelchair-alt"></i>
+        <div class="icon-title">fa-wheelchair-alt</div>
+    </li>
+</ul>
+
+<script src="__ROOT__/static/plugs/jquery/jquery.min.js" type="text/javascript"></script>
+<script>
+    $(function () {
+        $('li').on('click', function (className) {
+            className = $(this).find('i').get(0).className;
+            if (className) {
+                top.$('[name="{$field}"]').val(className).trigger('change');
+                top.layer.close(top.layer.getFrameIndex(window.name));
+            }
+        });
+    });
+</script>
+
+</body>
+</html>

+ 116 - 0
application/admin/view/auth/apply.html

@@ -0,0 +1,116 @@
+{extend name='main'}
+
+{block name="button"}
+
+{if auth("admin/auth/refresh")}
+<button data-load='{:url("refresh")}' class='layui-btn layui-btn-sm layui-btn-primary'>刷新权限</button>
+{/if}
+
+{/block}
+
+{block name="content"}
+<div class="think-box-shadow">
+    <ul id="zTree" class="ztree notselect"></ul>
+    <div class="hr-line-dashed"></div>
+    <div class="layui-form-item text-center">
+        <button class="layui-btn" data-submit-role type='button'>保存数据</button>
+        <button class="layui-btn layui-btn-danger" type='button' onclick="window.history.back()">取消编辑</button>
+    </div>
+</div>
+{/block}
+
+{block name="script"}
+<script>
+    window.RoleAction = new function () {
+        this.data = {};
+        this.ztree = null;
+        this.setting = {
+            view: {showLine: false, showIcon: false, dblClickExpand: false},
+            check: {enable: true, nocheck: false, chkboxType: {"Y": "ps", "N": "ps"}},
+            callback: {
+                beforeClick: function (id, node) {
+                    node.children.length < 1 ? RoleAction.ztree.checkNode(node, !node.checked, null, true) : RoleAction.ztree.expandNode(node);
+                    return false;
+                }
+            }
+        };
+        this.renderChildren = function (list, level) {
+            var childrens = [];
+            for (var i in list) childrens.push({
+                open: true, node: list[i].node, name: list[i].title || list[i].node,
+                checked: list[i].checked || false, children: this.renderChildren(list[i]._sub_, level + 1)
+            });
+            return childrens;
+        };
+        this.getData = function (that) {
+            var index = $.msg.loading();
+            $.form.load('{:url()}', {id: '{$vo.id}', action: 'get'}, 'post', function (ret) {
+                that.data = that.renderChildren(ret.data, 1);
+                return $.msg.close(index), that.showTree(), false;
+            });
+        };
+        this.showTree = function () {
+            this.ztree = $.fn.zTree.init($("#zTree"), this.setting, this.data);
+            while (true) {
+                var nodes = this.ztree.getNodesByFilter(function (node) {
+                    return (!node.node && node.children.length < 1);
+                });
+                if (nodes.length < 1) break;
+                for (var i in nodes) this.ztree.removeNode(nodes[i]);
+            }
+        };
+        this.submit = function () {
+            var nodes = [], data = this.ztree.getCheckedNodes(true);
+            for (var i in data) if (data[i].node) nodes.push(data[i].node);
+            $.form.load('{:url()}', {id: '{$vo.id}', action: 'save', nodes: nodes}, 'post');
+        };
+        // 刷新数据
+        this.getData(this);
+        // 提交表单
+        $('[data-submit-role]').on('click', function () {
+            RoleAction.submit();
+        });
+    };
+</script>
+{/block}
+
+{block name="style"}
+<link href="__ROOT__/static/plugs/ztree/zTreeStyle/zTreeStyle.css" rel="stylesheet">
+<script src="__ROOT__/static/plugs/ztree/ztree.all.min.js"></script>
+<style>
+    ul.ztree li {
+        white-space: normal !important;
+    }
+
+    ul.ztree li span.button.switch {
+        margin-right: 5px;
+    }
+
+    ul.ztree ul ul li {
+        display: inline-block;
+        white-space: normal;
+    }
+
+    ul.ztree > li {
+        padding: 15px 25px 15px 15px;
+    }
+
+    ul.ztree > li > ul {
+        margin-top: 12px;
+        border-top: 1px solid rgba(0, 0, 0, .1);
+    }
+
+    ul.ztree > li > ul > li {
+        padding: 5px;
+    }
+
+    ul.ztree > li > a > span {
+        font-weight: 700;
+        font-size: 15px;
+    }
+
+    ul.ztree .level2 .button.level2 {
+        background: 0 0;
+    }
+</style>
+{/block}

+ 30 - 0
application/admin/view/auth/form.html

@@ -0,0 +1,30 @@
+<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post" autocomplete="off">
+
+    <div class="layui-card-body padding-left-40">
+
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">权限名称</span>
+                <span class="color-desc margin-left-5">Title</span>
+                <input type="text" name="title" value='{$vo.title|default=""}' required placeholder="请输入权限名称" class="layui-input">
+            </label>
+        </div>
+
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">权限描述</span>
+                <span class="color-desc margin-left-5">Authorization</span>
+                <textarea placeholder="请输入权限描述" required class="layui-textarea" name="desc">{$vo.desc|default=""}</textarea>
+            </label>
+        </div>
+
+    </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>

+ 80 - 0
application/admin/view/auth/index.html

@@ -0,0 +1,80 @@
+{extend name='main'}
+
+{block name="button"}
+
+{if auth("admin/auth/add")}
+<button data-modal='{:url("add")}' data-title="添加权限" class='layui-btn layui-btn-sm layui-btn-primary'>添加权限</button>
+{/if}
+
+{if auth("admin/auth/remove")}
+<button data-action='{:url("remove")}' data-rule="id#{key}" data-csrf="{:systoken('admin/auth/remove')}" data-confirm="确定要删除这些权限吗?" class='layui-btn layui-btn-sm layui-btn-primary'>删除权限</button>
+{/if}
+
+{/block}
+
+{block name="content"}
+
+<div class="think-box-shadow">
+    {include file='auth/index_search'}
+    <table class="layui-table margin-top-10" lay-skin="line">
+        {notempty name='list'}
+        <thead>
+        <tr>
+            <th class='list-table-check-td think-checkbox'>
+                <label><input data-auto-none data-check-target='.list-check-box' type='checkbox'></label>
+            </th>
+            <th class='text-left nowrap'>权限信息</th>
+            <th class='text-left nowrap'>创建时间</th>
+            <th class="text-center nowrap">使用状态</th>
+            <th></th>
+        </tr>
+        </thead>
+        {/notempty}
+        <tbody>
+        {foreach $list as $key=>$vo}
+        <tr data-dbclick>
+            <td class='list-table-check-td think-checkbox'>
+                <label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
+            </td>
+            <td class='text-left'>
+                权限名称:{$vo.title|default='-'}<br>
+                <p class="color-desc">权限描述:{$vo.desc|default="没有写描述哦!"}</p>
+            </td>
+            <td class="text-left nowrap">
+                日期:{$vo.create_at|format_datetime|str_replace=' ','<br><span class="color-desc">时间:',###|raw}</span>
+            </td>
+            <td class='text-center nowrap'>
+                {eq name='vo.status' value='0'}<span class="color-red">已禁用</span>{else}<span class="color-green">使用中</span>{/eq}
+            </td>
+            <td class='text-center nowrap'>
+
+                {if auth("admin/auth/edit")}
+                <span class="text-explode">|</span>
+                <a data-dbclick class="layui-btn layui-btn-sm" data-title="编辑权限" data-modal='{:url("admin/auth/edit")}?id={$vo.id}'>编 辑</a>
+                {/if}
+
+                {if auth("admin/auth/apply")}
+                <a class="layui-btn layui-btn-normal layui-btn-sm" data-open='{:url("admin/auth/apply")}?id={$vo.id}'>授 权</a>
+                {/if}
+
+                {if $vo.status eq 1 and auth("admin/auth/forbid")}
+                <a class="layui-btn layui-btn-warm layui-btn-sm" data-action="{:url('forbid')}" data-value="id#{$vo.id};status#0" data-csrf="{:systoken('admin/auth/forbid')}">禁 用</a>
+                {elseif $vo.status eq 0 and auth("admin/auth/resume")}
+                <a class="layui-btn layui-btn-warm layui-btn-sm" data-action="{:url('resume')}" data-value="id#{$vo.id};status#1" data-csrf="{:systoken('admin/auth/resume')}">启 用</a>
+                {/if}
+
+                {if auth("admin/auth/remove")}
+                <a class="layui-btn layui-btn-danger layui-btn-sm" data-confirm="确定要删除数据吗?" data-action="{:url('remove')}" data-value="id#{$vo.id}" data-csrf="{:systoken('admin/auth/remove')}">删 除</a>
+                {/if}
+
+            </td>
+        </tr>
+        {/foreach}
+        </tbody>
+    </table>
+
+    {empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
+
+</div>
+
+{/block}

+ 42 - 0
application/admin/view/auth/index_search.html

@@ -0,0 +1,42 @@
+<fieldset>
+    <legend>条件搜索</legend>
+    <form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">权限名称</label>
+            <div class="layui-input-inline">
+                <input name="title" value="{$Think.get.title|default=''}" placeholder="请输入权限名称" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">权限描述</label>
+            <div class="layui-input-inline">
+                <input name="desc" value="{$Think.get.desc|default=''}" placeholder="请输入权限描述" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">使用状态</label>
+            <div class="layui-input-inline">
+                <select class="layui-select" name="status">
+                    {foreach [''=>'-- 全部状态 --','0'=>'已禁用的权限','1'=>'使用中的权限'] as $k=>$v}
+                    {eq name='Think.get.status' value='$k.""'}
+                    <option selected value="{$k}">{$v}</option>
+                    {else}
+                    <option value="{$k}">{$v}</option>
+                    {/eq}
+                    {/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="{$Think.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>
+
+<script>form.render()</script>

+ 80 - 0
application/admin/view/config/info.html

@@ -0,0 +1,80 @@
+{extend name="main"}
+
+{block name="button"}
+
+{if auth('config')}
+<a class="layui-btn layui-btn-sm layui-btn-primary" data-modal="{:url('config')}">修改系统配置</a>
+{/if}
+
+{/block}
+
+{block name="content"}
+
+<div class="think-box-shadow margin-bottom-15">
+    <span class="color-green font-w7 text-middle">文件存储引擎:</span>
+    {foreach ['local'=>'本地服务器存储','qiniu'=>'七牛云对象存储','oss'=>'阿里云OSS存储'] as $k=>$v}
+    {if sysconf('storage_type') eq $k}
+    {if auth('file')}<a data-modal="{:url('file')}?type={$k}" class="layui-btn layui-btn-sm">{$v}</a>{else}<a class="layui-btn layui-btn-sm">{$v}</a>{/if}
+    {elseif auth('file')}<a data-modal="{:url('file')}?type={$k}" class="layui-btn layui-btn-sm layui-btn-primary">{$v}</a>{/if}
+    {/foreach}
+</div>
+
+<div class="think-box-shadow padding-40">
+    <div class="layui-form-item">
+        <span class="color-green font-w7">网站名称 Website</span>
+        <label class="relative block">
+            <input readonly value="{:sysconf('site_name')}" class="layui-input layui-bg-gray">
+            <a data-copy="{:sysconf('site_name')}" class="fa fa-copy right-btn"></a>
+        </label>
+        <p class="help-block">网站名称及网站图标,将显示在浏览器的标签上</p>
+    </div>
+    <div class="layui-form-item">
+        <span class="color-green font-w7">管理程序名称 Name</span>
+        <label class="relative block">
+            <input readonly placeholder="请输入程序名称" value="{:sysconf('app_name')}" class="layui-input layui-bg-gray">
+            <a data-copy="{:sysconf('app_name')}" class="fa fa-copy right-btn"></a>
+        </label>
+        <p class="help-block">管理程序名称,将显示在后台左上角标题</p>
+    </div>
+    <div class="layui-form-item">
+        <span class="color-green font-w7">管理程序版本 Version</span>
+        <label class="relative block">
+            <input readonly value="{:sysconf('app_version')}" class="layui-input layui-bg-gray">
+            <a data-copy="{:sysconf('app_version')}" class="fa fa-copy right-btn"></a>
+        </label>
+        <p class="help-block">管理程序版本,将显示在后台左上角标题</p>
+    </div>
+
+    <div class="layui-form-item">
+        <span class="color-green font-w7">网站备案号 Miitbeian</span>
+        <label class="relative block">
+            <input readonly value="{:sysconf('miitbeian')}" class="layui-input layui-bg-gray">
+            <a data-copy="{:sysconf('miitbeian')}" class="fa fa-copy right-btn"></a>
+        </label>
+        <p class="help-block">网站备案号,可以在<a target="_blank" href="http://beian.miit.gov.cn">备案管理中心</a>查询获取,将显示在登录页面下面</p>
+    </div>
+    <div class="layui-form-item">
+        <span class="color-green font-w7">网站版权信息 Copyright</span>
+        <label class="relative block">
+            <input readonly value="{:sysconf('site_copy')}" class="layui-input layui-bg-gray">
+            <a data-copy="{:sysconf('site_copy')}" class="fa fa-copy right-btn"></a>
+        </label>
+        <p class="help-block">网站版权信息,在后台登录页面显示版本信息并链接到备案到信息备案管理系统</p>
+    </div>
+</div>
+{/block}
+
+{block name='style'}
+<style>
+    .right-btn {
+        top: 0;
+        right: 0;
+        width: 38px;
+        height: 38px;
+        display: inline-block;
+        position: absolute;
+        text-align: center;
+        line-height: 38px;
+    }
+</style>
+{/block}

+ 20 - 0
application/admin/view/config/storage-local.html

@@ -0,0 +1,20 @@
+<form onsubmit="return false;" data-auto="true" action="{:url()}" method="post" class='layui-form layui-card' autocomplete="off">
+    <div class="layui-card-body">
+        <div class="color-text margin-left-40 margin-bottom-20 layui-code" style="border-left-width:1px;background:none">
+            <p>文件将存储在本地服务器,需确保服务器的 public/upload 目录有写入权限,有足够的存储空间!</p>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">AllowExts<br><span class="nowrap color-desc">允许类型</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_local_exts" required value="{:sysconf('storage_local_exts')}" placeholder="请输入系统文件上传后缀" class="layui-input">
+                <p class="help-block">设置系统允许上传文件的后缀,多个以英文逗号隔开。如:png,jpg,rar,doc</p>
+            </div>
+        </div>
+        <div class="hr-line-dashed margin-left-40"></div>
+        <div class="layui-form-item text-center padding-left-40">
+            <input type="hidden" name="storage_type" value="local">
+            <button class="layui-btn" type="submit">保存配置</button>
+            <button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
+        </div>
+    </div>
+</form>

+ 80 - 0
application/admin/view/config/storage-oss.html

@@ -0,0 +1,80 @@
+<form onsubmit="return false;" data-auto="true" action="{:url()}" method="post" class='layui-form layui-card' autocomplete="off">
+    <div class="layui-card-body">
+        <div class="color-text margin-left-40 margin-bottom-20 layui-code" style="border-left-width:1px;background:none">
+            <p class="margin-bottom-5 font-w7">文件将上传到阿里云OSS空间,需要配置OSS公开访问及跨域策略!</p>
+            目前已实现自动创建空间及配置访问策略!<a target="_blank" href="https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=08p1pddw">我要免费申请</a>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">AllowExts<br><span class="nowrap color-desc">允许类型</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_local_exts" required value="{:sysconf('storage_local_exts')}" placeholder="请输入系统文件上传后缀" class="layui-input">
+                <p class="help-block">设置系统允许上传文件的后缀,多个以英文逗号隔开。如:png,jpg,rar,doc</p>
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label label-required">Protocol<br><span class="nowrap color-desc">访问协议</span></label>
+            <div class="layui-input-block">
+                {foreach ['http','https','auto'] as $pro}
+                <label class="think-radio">
+                    {if sysconf('storage_oss_is_https') eq $pro}
+                    <input checked type="radio" name="storage_oss_is_https" value="{$pro}" lay-ignore> {$pro}
+                    {else}
+                    <input type="radio" name="storage_oss_is_https" value="{$pro}" lay-ignore> {$pro}
+                    {/if}
+                </label>
+                {/foreach}
+                <p class="help-block">阿里云对象存储访问协议(http、https、auto),其中 https 需要配置证书才能使用,auto 为相对协议自动根据域名切换http与https。</p>
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">Bucket<br><span class="nowrap color-desc">空间名称</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_oss_bucket" required value="{:sysconf('storage_oss_bucket')}" placeholder="请输入OSS Bucket (空间名称)" class="layui-input">
+                <p class="help-block">填写OSS存储空间名称,如:think-admin-oss(需要是全区唯一的值,不存在时会自动创建)</p>
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">EndPoint<br><span class="nowrap color-desc">数据中心</span></label>
+            <div class="layui-input-block">
+                <select required name="storage_oss_endpoint" class="layui-select" lay-search>
+                    {foreach $ossPoints as $k=>$p}
+                    {if sysconf('storage_oss_endpoint') eq $k}
+                    <option selected value="{$k}">{$p} <span class="font-s10 color-desc">({$k})</span></option>
+                    {else}
+                    <option value="{$k}">{$p} <span class="font-s10 color-desc">({$k})</span></option>
+                    {/if}
+                    {/foreach}
+                </select>
+                <p class="help-block">请选择OSS数据中心访问节点,有效值如:oss-cn-shenzhen.aliyuncs.com</p>
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">AccessKey<br><span class="nowrap color-desc">访问密钥</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_oss_keyid" required value="{:sysconf('storage_oss_keyid')}" maxlength="30" placeholder="请输入OSS AccessKey (访问密钥)" class="layui-input">
+                <p class="help-block">可以在 [ 阿里云 > 个人中心 ] 设置并获取到访问密钥。</p>
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">SecretKey<br><span class="nowrap color-desc">安全密钥</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_oss_secret" required value="{:sysconf('storage_oss_secret')}" maxlength="30" placeholder="请输入OSS SecretKey (安全密钥)" class="layui-input">
+                <p class="help-block">可以在 [ 阿里云 > 个人中心 ] 设置并获取到安全密钥。</p>
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">Domain<br><span class="nowrap color-desc">访问域名</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_oss_domain" value="{:sysconf('storage_oss_domain')}" placeholder="请输入OSS存储 Domain (访问域名)" class="layui-input">
+                <p class="help-block">填写OSS存储外部访问域名,如:think-admin-oss.oss-cn-shenzhen.aliyuncs.com(正常情况下是自动获取的)</p>
+            </div>
+        </div>
+        <div class="hr-line-dashed margin-left-40"></div>
+        <div class="layui-form-item text-center padding-left-40">
+            <input type="hidden" name="storage_type" value="oss">
+            <button class="layui-btn" type="submit">保存配置</button>
+            <button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
+        </div>
+    </div>
+    <script>form.render()</script>
+</form>

+ 80 - 0
application/admin/view/config/storage-qiniu.html

@@ -0,0 +1,80 @@
+<form onsubmit="return false" data-auto="true" action="{:url()}" method="post" class='layui-form layui-card' autocomplete="off">
+    <div class="layui-card-body">
+        <div class="color-text margin-left-40 margin-bottom-20 layui-code" style="border-left-width:1px;background:none">
+            <p class="margin-bottom-5 font-w7">文件将上传到七牛云存储,对象存储需要配置为公开访问的Bucket空间!</p>
+            完成实名认证后可获得10G免费存储空间哦!<a target="_blank" href="https://portal.qiniu.com/signup?code=1hefnmobzees2">我要免费申请</a>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">AllowExts<br><span class="nowrap color-desc">允许类型</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_local_exts" required value="{:sysconf('storage_local_exts')}" placeholder="请输入系统文件上传后缀" class="layui-input">
+                <p class="help-block">设置系统允许上传文件的后缀,多个以英文逗号隔开。如:png,jpg,rar,doc</p>
+            </div>
+        </div>
+        <div class="layui-form-item" data-storage-type="qiniu">
+            <label class="layui-form-label label-required">Protocol<br><span class="nowrap color-desc">访问协议</span></label>
+            <div class="layui-input-block">
+                {foreach ['http','https','auto'] as $pro}
+                <label class="think-radio">
+                    {if sysconf('storage_qiniu_is_https') eq $pro}
+                    <input checked type="radio" name="storage_qiniu_is_https" value="{$pro}" lay-ignore> {$pro}
+                    {else}
+                    <input type="radio" name="storage_qiniu_is_https" value="{$pro}" lay-ignore> {$pro}
+                    {/if}
+                </label>
+                {/foreach}
+                <p class="help-block">七牛云存储访问协议,其中 https 需要配置证书才能使用,auto 为相对协议。</p>
+            </div>
+        </div>
+        <div class="layui-form-item" data-storage-type="qiniu">
+            <label class="layui-form-label">Region<br><span class="nowrap color-desc label-required">存储区域</span></label>
+            <div class="layui-input-block">
+                {foreach ['华东','华北','华南','北美'] as $area}
+                <label class="think-radio">
+                    {if sysconf('storage_qiniu_region') eq $area}
+                    <input checked type="radio" name="storage_qiniu_region" value="{$area}" lay-ignore>
+                    {else}
+                    <input type="radio" name="storage_qiniu_region" value="{$area}" lay-ignore>
+                    {/if}
+                    {$area}
+                </label>
+                {/foreach}
+                <p class="help-block">七牛云存储空间所在区域,需要严格对应储存所在区域才能上传文件。</p>
+            </div>
+        </div>
+        <div class="layui-form-item" data-storage-type="qiniu">
+            <label class="layui-form-label">Bucket<br><span class="nowrap color-desc">空间名称</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_qiniu_bucket" required value="{:sysconf('storage_qiniu_bucket')}" placeholder="请输入七牛云存储 Bucket (空间名称)" class="layui-input">
+                <p class="help-block">填写七牛云存储空间名称,如:static</p>
+            </div>
+        </div>
+        <div class="layui-form-item" data-storage-type="qiniu">
+            <label class="layui-form-label">Domain<br><span class="nowrap color-desc">访问域名</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_qiniu_domain" required value="{:sysconf('storage_qiniu_domain')}" placeholder="请输入七牛云存储 Domain (访问域名)" class="layui-input">
+                <p class="help-block">填写七牛云存储访问域名,如:static.ctolog.cc</p>
+            </div>
+        </div>
+        <div class="layui-form-item" data-storage-type="qiniu">
+            <label class="layui-form-label">AccessKey<br><span class="nowrap color-desc">访问密钥</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_qiniu_access_key" required value="{:sysconf('storage_qiniu_access_key')}" placeholder="请输入七牛云 AccessKey (访问密钥)" class="layui-input">
+                <p class="help-block">可以在 [ 七牛云 > 个人中心 ] 设置并获取到访问密钥。</p>
+            </div>
+        </div>
+        <div class="layui-form-item" data-storage-type="qiniu">
+            <label class="layui-form-label">SecretKey<br><span class="nowrap color-desc">安全密钥</span></label>
+            <div class="layui-input-block">
+                <input type="text" name="storage_qiniu_secret_key" required value="{:sysconf('storage_qiniu_secret_key')}" maxlength="43" placeholder="请输入七牛云 SecretKey (安全密钥)" class="layui-input">
+                <p class="help-block">可以在 [ 七牛云 > 个人中心 ] 设置并获取到安全密钥。</p>
+            </div>
+        </div>
+        <div class="hr-line-dashed margin-left-40"></div>
+        <div class="layui-form-item text-center padding-left-40">
+            <input type="hidden" name="storage_type" value="qiniu">
+            <button class="layui-btn" type="submit">保存配置</button>
+            <button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
+        </div>
+    </div>
+</form>

+ 57 - 0
application/admin/view/config/system-config.html

@@ -0,0 +1,57 @@
+<form onsubmit="return false" data-auto="true" action="{:url()}" method="post" class='layui-form layui-card' autocomplete="off">
+    <div class="layui-card-body padding-left-40">
+
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">网站名称 Website</span>
+                <input name="site_name" required placeholder="请输入网站名称" value="{:sysconf('site_name')}" class="layui-input">
+            </label>
+            <p class="help-block">网站名称,将在浏览器的标签上显示名称</p>
+        </div>
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">管理程序名称 Name</span>
+                <input name="app_name" required placeholder="请输入程序名称" value="{:sysconf('app_name')}" class="layui-input">
+            </label>
+            <p class="help-block">管理程序名称,在后台左上角标题处理显示</p>
+        </div>
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">管理程序版本 Version</span>
+                <input name="app_version" placeholder="请输入程序版本" value="{:sysconf('app_version')}" class="layui-input">
+            </label>
+            <p class="help-block">管理程序版本,在后台左上角标题处理显示</p>
+        </div>
+        <div class="layui-form-item">
+            <span class="color-green font-w7">浏览器图标 Browser</span>
+            <div class="relative block">
+                <img alt="icon" data-tips-image style="height:auto;max-height:42px;min-width:42px" src="{:sysconf('site_icon')}"/>
+                <input type="hidden" name="site_icon" onchange="$(this).prev('img').attr('src', this.value)" value="{:sysconf('site_icon')}" class="layui-input">
+                <a class="margin-left-10" data-file="btn" data-type="ico,png" data-field="site_icon">上传图片</a>
+                <p class="help-block">建议上传 ICO 图标的尺寸为 128x128 <a href="http://www.favicon-icon-generator.com" target="_blank">ICON在线制作</a></p>
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">网站备案号 Miitbeian</span>
+                <input name="miitbeian" required placeholder="请输入网站备案号" value="{:sysconf('miitbeian')}" class="layui-input">
+            </label>
+            <p class="help-block">网站备案号,可以在<a target="_blank" href="http://beian.miit.gov.cn">备案管理中心</a>查询获取,将在登录页面下面显示</p>
+        </div>
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">网站版权信息 Copyright</span>
+                <input name="site_copy" required placeholder="请输入版权信息" value="{:sysconf('site_copy')}" class="layui-input">
+            </label>
+            <p class="help-block">网站版权信息,在后台登录页面显示版本信息并链接到备案到信息备案管理系统</p>
+        </div>
+
+        <div class="hr-line-dashed"></div>
+
+        <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>
+    </div>
+
+</form>

+ 137 - 0
application/admin/view/index/index.html

@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html lang="zh">
+
+<head>
+    <title>{block name="title"}{$title|default=''}{if !empty($title)} · {/if}{:sysconf('site_name')}{/block}</title>
+    <meta charset="utf-8">
+    <meta name="renderer" content="webkit">
+    <meta name="format-detection" content="telephone=no">
+    <meta name="apple-mobile-web-app-capable" content="yes">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="apple-mobile-web-app-status-bar-style" content="black">
+    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=0.4">
+    <link rel="shortcut icon" href="{:sysconf('site_icon')}">
+    <link rel="stylesheet" href="__ROOT__/static/plugs/awesome/fonts.css?at={:date('md')}">
+    <link rel="stylesheet" href="__ROOT__/static/plugs/layui/css/layui.css?at={:date('md')}">
+    <link rel="stylesheet" href="__ROOT__/static/theme/css/console.css?at={:date('md')}">
+    {block name="style"}{/block}
+    <script>window.ROOT_URL = '__ROOT__';</script>
+    <script src="__ROOT__/static/plugs/jquery/pace.min.js"></script>
+
+    <style>
+        .layui-header .layui-layout-right li a{
+            padding-right: 35px;
+        }
+        .tangram-suggestion-main{
+            z-index: 999;
+        }
+    </style>
+    <script src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=E4Y9cdBjAvDM6DjGcOmBA4v2GcEXAWvG"></script>
+</head>
+<body class="layui-layout-body">
+{block name='body'}
+<div class="layui-layout layui-layout-admin layui-layout-left-hide">
+
+    <!-- 顶部菜单 开始 -->
+    <div class="layui-header notselect">
+        <a href="{:url('@')}" class="layui-logo layui-elip">
+            {:sysconf('app_name')} {if sysconf('app_version')}<sup class="padding-left-5">{:sysconf('app_version')}</sup>{/if}
+        </a>
+        <ul class="layui-nav layui-layout-left">
+            <li class="layui-nav-item" lay-unselect>
+                <a class="text-center" data-target-menu-type>
+                    <i class="layui-icon layui-icon-spread-left"></i>
+                </a>
+            </li>
+            {foreach $menus as $oneMenu}
+            <li class="layui-nav-item">
+                <a data-menu-node="m-{$oneMenu.id}" data-open="{$oneMenu.url}">
+                    {notempty name='oneMenu.icon'}<span class='{$oneMenu.icon} padding-right-5'></span>{/notempty}
+                    <span>{$oneMenu.title|default=''}</span>
+                </a>
+            </li>
+            {/foreach}
+        </ul>
+        <ul class="layui-nav layui-layout-right">
+            <li lay-unselect class="layui-nav-item"><a data-reload><i class="layui-icon layui-icon-refresh-3"></i></a></li>
+            {notempty name='Think.session.user.username'}
+            <li class="layui-nav-item">
+                <dl class="layui-nav-child">
+                    <dd lay-unselect><a data-modal="{:url('admin/index/info',['id'=>session('user.id')])}"><i class="layui-icon layui-icon-set-fill margin-right-5"></i>基本资料</a></dd>
+                    <dd lay-unselect><a data-modal="{:url('admin/index/pass',['id'=>session('user.id')])}"><i class="layui-icon layui-icon-component margin-right-5"></i>安全设置</a></dd>
+                    {if auth('admin/index/buildoptimize')}
+                    <dd lay-unselect><a data-modal="{:url('admin/index/buildOptimize')}"><i class="layui-icon layui-icon-template-1 margin-right-5"></i>压缩发布</a></dd>
+                    {/if}
+                    {if auth('admin/index/clearruntime')}
+                    <dd lay-unselect><a data-modal="{:url('admin/index/clearRuntime')}"><i class="layui-icon layui-icon-fonts-clear margin-right-5"></i>清理缓存</a></dd>
+                    {/if}
+                    {notempty name='GLOBALS.AdminUserRightOption'}{foreach $GLOBALS.AdminUserRightOption as $option}{if auth($option.node)}
+                    <dd lay-unselect><a data-{$option.type}="{$option.action}"><i class="{$option.icon} margin-right-5"></i>{$option.title}</a></dd>
+                    {/if}{/foreach}{/notempty}
+                    <dd lay-unselect><a data-confirm="确定要退出登录吗?" data-load="{:url('admin/login/out')}"><i class="layui-icon layui-icon-release margin-right-5"></i>退出登录</a></dd>
+                </dl>
+                <a><span><i class="layui-icon layui-icon-username margin-right-5"></i> {:session('user.username')}</span></a>
+            </li>
+            {else}
+            <li class="layui-nav-item">
+                <a data-href="{:url('@admin/login')}"><i class="layui-icon layui-icon-username"></i> 立即登录</a>
+            </li>
+            {/notempty}
+        </ul>
+    </div>
+    <!-- 顶部菜单 结束 -->
+
+    <!-- 左则菜单 开始 -->
+    <div class="layui-side layui-bg-black notselect">
+        <div class="layui-side-scroll">
+
+            {foreach $menus as $oneMenu}
+            {notempty name='oneMenu.sub'}
+            <ul class="layui-nav layui-nav-tree layui-hide" data-menu-layout="m-{$oneMenu.id}">
+                {foreach $oneMenu.sub as $twoMenu}
+                {empty name='twoMenu.sub'}
+                <li class="layui-nav-item">
+                    <a data-target-tips="{$twoMenu.title}" data-menu-node="m-{$oneMenu.id}-{$twoMenu.id}" data-open="{$twoMenu.url}">
+                        <span class='{$twoMenu.icon|default="layui-icon layui-icon-link"}'></span>
+                        <span class="nav-text padding-left-5">{$twoMenu.title}</span>
+                    </a>
+                </li>
+                {else}
+                <li class="layui-nav-item" data-submenu-layout='m-{$oneMenu.id}-{$twoMenu.id}'>
+                    <a data-target-tips="{$twoMenu.title}" style="background:#393D49">
+                        <span class='nav-icon layui-hide {$twoMenu.icon|default="layui-icon layui-icon-triangle-d"}'></span>
+                        <span class="nav-text padding-left-5">{$twoMenu.title}</span>
+                    </a>
+                    <dl class="layui-nav-child">
+                        {foreach $twoMenu.sub as $thrMenu}
+                        <dd>
+                            <a data-target-tips="{$thrMenu.title}" data-open="{$thrMenu.url}" data-menu-node="m-{$oneMenu.id}-{$twoMenu.id}-{$thrMenu.id}">
+                                <span class='nav-icon padding-left-5 {$thrMenu.icon|default="layui-icon layui-icon-link"}'></span>
+                                <span class="nav-text padding-left-5">{$thrMenu.title}</span>
+                            </a>
+                        </dd>
+                        {/foreach}
+                    </dl>
+                </li>
+                {/empty}
+                {/foreach}
+            </ul>
+            {/notempty}
+            {/foreach}
+        </div>
+    </div>
+    <!-- 左则菜单 结束 -->
+
+    <!-- 主体内容 开始 -->
+    <div class="layui-body layui-bg-gray">{block name='content'}{/block}</div>
+    <!-- 主体内容 结束 -->
+
+</div>
+{/block}
+<script src="__ROOT__/static/plugs/layui/layui.all.js"></script>
+<script src="__ROOT__/static/plugs/require/require.js"></script>
+<script src="__ROOT__/static/admin.js"></script>
+{block name='script'}{/block}
+</body>
+
+</html>

+ 197 - 0
application/admin/view/index/main.html

@@ -0,0 +1,197 @@
+{extend name='main'}
+
+{block name='content'}
+
+<style>
+
+    .store-total-container {
+        font-size: 14px;
+        margin-bottom: 20px;
+        letter-spacing: 1px;
+    }
+
+    .store-total-container .store-total-icon {
+        top: 45%;
+        right: 8%;
+        font-size: 65px;
+        position: absolute;
+        color: rgba(255, 255, 255, 0.4);
+    }
+
+    .store-total-container .store-total-item {
+        color: #fff;
+        line-height: 4em;
+        padding: 15px 25px;
+        position: relative;
+    }
+
+    .store-total-container .store-total-item > div:nth-child(2) {
+        font-size: 46px;
+        line-height: 46px;
+    }
+
+</style>
+
+<div class="think-box-shadow store-total-container notselect">
+    <div class="margin-bottom-15">商城统计</div>
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-sm6 layui-col-md3">
+            <div class="store-total-item nowrap" style="background:linear-gradient(-125deg,#57bdbf,#2f9de2)">
+                <div>活动总量</div>
+                <div>{$data.goods_count}</div>
+                <div>当前活动的总数量</div>
+            </div>
+            <i class="store-total-icon layui-icon layui-icon-template-1"></i>
+        </div>
+        <div class="layui-col-sm6 layui-col-md3">
+            <div class="store-total-item nowrap" style="background:linear-gradient(-125deg,#ff7d7d,#fb2c95)">
+                <div>用户总量</div>
+                <div>{$data.member_count}</div>
+                <div>当前用户的总数量</div>
+            </div>
+            <i class="store-total-icon layui-icon layui-icon-user"></i>
+        </div>
+        <div class="layui-col-sm6 layui-col-md3">
+            <div class="store-total-item nowrap" style="background:linear-gradient(-113deg,#c543d8,#925cc3)">
+                <div>报名总量</div>
+                <div>{$data.apply_count}</div>
+                <div>用户已报名的总数量</div>
+            </div>
+            <i class="store-total-icon layui-icon layui-icon-read"></i>
+        </div>
+        <div class="layui-col-sm6 layui-col-md3">
+            <div class="store-total-item nowrap" style="background:linear-gradient(-141deg,#ecca1b,#f39526)">
+                <div>建议总量</div>
+                <div>{$data.complain_count}</div>
+                <div>会员提交建议的总数量</div>
+            </div>
+            <i class="store-total-icon layui-icon layui-icon-survey"></i>
+        </div>
+    </div>
+</div>
+
+<div class="think-box-shadow store-total-container">
+    <div class="margin-bottom-15">实时概况</div>
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md6 margin-bottom-15">
+            <div class="layui-row">
+                <div class="layui-col-xs3 text-center">
+                    <i class="layui-icon color-blue" style="font-size:60px;line-height:72px">&#xe65e;</i>
+                </div>
+                <div class="layui-col-xs4">
+                    <div class="font-s14">报名优惠金额(元)</div>
+                    <div class="font-s16">{$data.today_amount}</div>
+                    <div class="font-s12 color-desc">昨日:{$data.yesterday_amount}</div>
+                </div>
+            </div>
+        </div>
+        <div class="layui-col-md6 margin-bottom-15">
+            <div class="layui-row">
+                <div class="layui-col-xs3 text-center">
+                    <i class="layui-icon color-blue" style="font-size:60px;line-height:72px">&#xe663;</i>
+                </div>
+                <div class="layui-col-xs4">
+                    <div class="font-s14">新增用户数</div>
+                    <div class="font-s16">{$data.today_member}</div>
+                    <div class="font-s12 color-desc">昨日:{$data.yesterday_member}</div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!--<div class="layui-row layui-col-space15">
+    <div class="layui-col-md6">
+        <div class="think-box-shadow">
+            <table class="layui-table" lay-skin="line" lay-even>
+                <caption class="text-left margin-bottom-15 font-s14">系统信息</caption>
+                <colgroup>
+                    <col width="30%">
+                </colgroup>
+                <tbody>
+                <tr>
+                    <td>当前程序版本</td>
+                    <td>{:sysconf('app_version')}</td>
+                </tr>
+                <tr>
+                    <td>运行PHP版本</td>
+                    <td>{$Think.PHP_VERSION}</td>
+                </tr>
+                <tr>
+                    <td>ThinkPHP版本</td>
+                    <td>{$think_ver}</td>
+                </tr>
+                <tr>
+                    <td>MySQL数据库版本</td>
+                    <td>{$mysql_ver}</td>
+                </tr>
+                <tr>
+                    <td>服务器操作系统</td>
+                    <td>{:php_uname('s')}</td>
+                </tr>
+                <tr>
+                    <td>WEB运行环境</td>
+                    <td>{:php_sapi_name()}</td>
+                </tr>
+                <tr>
+                    <td>上传大小限制</td>
+                    <td>{:ini_get('upload_max_filesize')}</td>
+                </tr>
+                <tr>
+                    <td>POST大小限制</td>
+                    <td>{:ini_get('post_max_size')}</td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+    </div>
+    <div class="layui-col-md6">
+        <div class="think-box-shadow">
+            <table class="layui-table" lay-skin="line" lay-even>
+                <caption class="text-left margin-bottom-15 font-s14">产品团队</caption>
+                <colgroup>
+                    <col width="30%">
+                </colgroup>
+                <tbody>
+                <tr>
+                    <td>产品名称</td>
+                    <td>觅食</td>
+                </tr>
+                <tr>
+                    <td>在线体验</td>
+                    <td><a target="_blank" href="http://mishi.hdlkeji.com">http://mishi.hdlkeji.com</a></td>
+                </tr>
+                <tr>
+                    <td>官方QQ群</td>
+                    <td>
+                        <a href="">
+                            <img src="//pub.idqqimg.com/wpa/images/group.png" style="height:18px;width:auto" target="_blank">
+                        </a>
+                    </td>
+                </tr>
+                <tr>
+                    <td>项目地址</td>
+                    <td><a target="_blank" href="http://mishi.hdlkeji.com">http://mishi.hdlkeji.com</a></td>
+                </tr>
+                <tr>
+                    <td>BUG反馈</td>
+                    <td><a target="_blank" href="http://mishi.hdlkeji.com">http://mishi.hdlkeji.com</a></td>
+                </tr>
+                <tr>
+                    <td>开发团队</td>
+                    <td><a href="http://www.cuci.cc" target="_blank">海德拉科技有限公司</a></td>
+                </tr>
+                <tr>
+                    <td>团队官网</td>
+                    <td><a target="_blank" href="http://www.cuci.cc">http://www.hdl.com</a></td>
+                </tr>
+                <tr>
+                    <td>办公地址</td>
+                    <td>临沂市北城新区环球中心1707</td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>-->
+{/block}

+ 57 - 0
application/admin/view/login/index.html

@@ -0,0 +1,57 @@
+{extend name="index/index"}
+
+{block name="body"}
+<div class="login-container" data-supersized="__ROOT__/static/theme/img/login/bg1.jpg,__ROOT__/static/theme/img/login/bg2.jpg">
+    <div class="header notselect layui-hide-xs">
+        <a href="{:url('@')}" class="title">{:sysconf('app_name')}<span class="padding-left-5 font-s10">{:sysconf('app_version')}</span></a>
+        {notempty name='devmode'}
+        <a class="pull-right layui-anim layui-anim-fadein" href='https://gitee.com/zoujingli/ThinkAdmin'>
+            <img src='https://gitee.com/zoujingli/ThinkAdmin/widgets/widget_1.svg' alt='Fork me on Gitee'>
+        </a>
+        {/notempty}
+    </div>
+    <form data-login-form onsubmit="return false" method="post" class="layui-anim layui-anim-upbit" autocomplete="off">
+        <h2 class="notselect">系统管理</h2>
+        <ul>
+            <li class="username">
+                <label>
+                    <i class="layui-icon layui-icon-username"></i>
+                    <input class="layui-input" required pattern="^\S{4,}$" name="username" autofocus autocomplete="off" placeholder="登录账号" title="请输入登录账号">
+                </label>
+            </li>
+            <li class="password">
+                <label>
+                    <i class="layui-icon layui-icon-password"></i>
+                    <input class="layui-input" required pattern="^\S{4,}$" name="password" maxlength="32" type="password" autocomplete="off" placeholder="登录密码" title="请输入登录密码">
+                </label>
+            </li>
+            <li class="verify layui-hide">
+                <label class="inline-block relative">
+                    <i class="layui-icon layui-icon-picture-fine"></i>
+                    <input class="layui-input" required pattern="^\S{4,}$" name="verify" maxlength="4" autocomplete="off" placeholder="验证码" title="请输入验证码">
+                </label>
+                <label data-captcha="{:url('admin/login/captcha',[],false)}" data-field-verify="verify" data-field-uniqid="uniqid" data-captcha-type="{$captcha_type}" data-captcha-token="{$captcha_token}"></label>
+            </li>
+            <li class="text-center padding-top-20">
+                <button type="submit" class="layui-btn layui-disabled full-width" data-form-loaded="立即登入">正在载入</button>
+            </li>
+        </ul>
+    </form>
+    <div class="footer notselect">
+        <p class="layui-hide-xs"><a target="_blank" href="https://www.google.cn/chrome">推荐使用谷歌浏览器</a></p>
+        {:sysconf('site_copy')}
+        {if sysconf('miitbeian')}<span class="padding-5">|</span><a target="_blank" href="http://beian.miit.gov.cn">{:sysconf('miitbeian')}</a>{/if}
+    </div>
+</div>
+{/block}
+
+{block name='style'}
+<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
+<script>if (location.href.indexOf('#') > -1) location.replace(location.href.split('#')[0])</script>
+<link rel="stylesheet" href="__ROOT__/static/theme/css/login.css">
+{/block}
+
+{block name='script'}
+<script src="__ROOT__/static/login.js"></script>
+<script src="__ROOT__/static/plugs/supersized/supersized.3.2.7.min.js"></script>
+{/block}

+ 11 - 0
application/admin/view/main.html

@@ -0,0 +1,11 @@
+<div class="layui-card layui-bg-gray">
+    {block name='style'}{/block}
+    {notempty name='title'}
+    <div class="layui-card-header layui-anim layui-anim-fadein notselect">
+        <span class="layui-icon layui-icon-next font-s10 color-desc margin-right-5"></span>{$title|default=''}
+        <div class="pull-right">{block name='button'}{/block}</div>
+    </div>
+    {/notempty}
+    <div class="layui-card-body layui-anim layui-anim-upbit">{block name='content'}{/block}</div>
+    {block name='script'}{/block}
+</div>

+ 89 - 0
application/admin/view/menu/form.html

@@ -0,0 +1,89 @@
+<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post" autocomplete="off">
+
+    <div class="layui-card-body">
+
+        <div class="layui-form-item">
+            <label class="layui-form-label">上级菜单</label>
+            <div class="layui-input-block">
+                <select name='pid' class='layui-select' lay-search>
+                    <!--{foreach $menus as $menu}-->
+                    <!--{eq name='menu.id' value='$vo.pid|default=0'}-->
+                    <option selected value='{$menu.id}'>{$menu.spl|raw}{$menu.title}</option>
+                    <!--{else}-->
+                    <option value='{$menu.id}'>{$menu.spl|raw}{$menu.title}</option>
+                    <!--{/eq}-->
+                    <!--{/foreach}-->
+                </select>
+                <p class="help-block">必选,请选择上级菜单或顶级菜单(目前最多支持三级菜单)</p>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+            <label class="layui-form-label">菜单名称</label>
+            <div class="layui-input-block">
+                <input name="title" value='{$vo.title|default=""}' required placeholder="请输入菜单名称" class="layui-input">
+                <p class="help-block">必填,请填写菜单名称(如:系统管理),建议字符不要太长,一般4-6个汉字</p>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+            <label class="layui-form-label">菜单链接</label>
+            <div class="layui-input-block">
+                <input onblur="this.value=this.value === ''?'#':this.value" name="url" required placeholder="请输入菜单链接" value="{$vo.url|default='#'}" class="layui-input">
+                <p class="help-block">
+                    必填,请填写系统节点(如:admin/user/index),节点加入权限管理时菜单才会自动隐藏,非规则内的不会隐藏;
+                    <br>正常情况下,在输入的时候会有自动提示。如果是上级菜单时,请填写"#"符号,不要填写地址或节点地址
+                </p>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+            <label class="layui-form-label">链接参数</label>
+            <div class="layui-input-block">
+                <input name="params" placeholder="请输入链接参数" value="{$vo.params|default=''}" class="layui-input">
+                <p class="help-block">可选,设置菜单链接的GET访问参数(如:name=1&age=3)</p>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+            <label class="layui-form-label">菜单图标</label>
+            <div class="layui-input-block">
+                <div class="layui-input-inline">
+                    <input placeholder="请输入或选择图标" name="icon" value='{$vo.icon|default=""}' class="layui-input">
+                </div>
+                <span style="padding:0 12px;min-width:45px" class='layui-btn layui-btn-primary'>
+                    <i style="font-size:1.2em;margin:0" class='{$vo.icon|default=""}'></i>
+                </span>
+                <button data-icon='icon' type='button' class='layui-btn layui-btn-primary'>选择图标</button>
+                <p class="help-block">可选,设置菜单选项前置图标,目前只支持 Font Awesome 5.2.0 字体图标</p>
+            </div>
+        </div>
+
+    </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>
+
+{block name='script'}
+<script>
+    require(['jquery.autocompleter'], function () {
+        form.render();
+        $('[name="icon"]').on('change', function () {
+            $(this).parent().next().find('i').get(0).className = this.value
+        });
+        $('input[name=url]').autocompleter({
+            limit: 6, highlightMatches: true, template: '{{ label }} <span> {{ title }} </span>', source: (function (subjects, data) {
+                for (var i in subjects) data.push({value: subjects[i].node, label: subjects[i].node, title: subjects[i].title});
+                return data;
+            })(JSON.parse('{$nodes|raw|json_encode}'), [])
+        });
+    });
+</script>
+{/block}

+ 80 - 0
application/admin/view/menu/index.html

@@ -0,0 +1,80 @@
+{extend name='main'}
+
+{block name="button"}
+
+{if auth("add")}
+<button data-modal='{:url("add")}' data-title="添加菜单" class='layui-btn layui-btn-sm layui-btn-primary'>添加菜单</button>
+{/if}
+
+{if auth("remove")}
+<button data-action='{:url("remove")}' data-csrf="{:systoken('remove')}" data-rule="id#{key}" class='layui-btn layui-btn-sm layui-btn-primary'>删除菜单</button>
+{/if}
+
+{/block}
+
+{block name="content"}
+<div class="think-box-shadow">
+    {empty name='list'}
+    <blockquote class="layui-elem-quote">没 有 记 录 哦!</blockquote>
+    {else}
+    <table class="layui-table" lay-skin="line">
+        <thead>
+        <tr>
+            <th class='list-table-check-td think-checkbox'>
+                <input data-auto-none data-check-target='.list-check-box' type='checkbox'>
+            </th>
+            <th class='list-table-sort-td'>
+                <button type="button" data-reload class="layui-btn layui-btn-xs">刷 新</button>
+            </th>
+            <th class='text-center' style="width:30px"></th>
+            <th style="width:180px"></th>
+            <th class='layui-hide-xs' style="width:180px"></th>
+            <th colspan="2"></th>
+        </tr>
+        </thead>
+        <tbody>
+        {foreach $list as $key=>$vo}
+        <tr data-dbclick>
+            <td class='list-table-check-td think-checkbox'>
+                <input class="list-check-box" value='{$vo.ids}' type='checkbox'>
+            </td>
+            <td class='list-table-sort-td'>
+                <input data-action-blur="{:request()->url()}" data-value="id#{$vo.id};action#sort;sort#{value}" data-loading="false" value="{$vo.sort}" class="list-sort-input">
+            </td>
+            <td class='text-center'><i class="{$vo.icon} font-s18"></i></td>
+            <td class="nowrap"><span class="color-desc">{$vo.spl|raw}</span>{$vo.title}</td>
+            <td class='layui-hide-xs'>{$vo.url}</td>
+            <td class='text-center nowrap'>{eq name='vo.status' value='0'}<span class="color-red">已禁用</span>{else}<span class="color-green">使用中</span>{/eq}</td>
+            <td class='text-center nowrap notselect'>
+
+                {if auth("add")}
+                <span class="text-explode">|</span>
+                <!--{if $vo.spt < 2}-->
+                <a class="layui-btn layui-btn-xs layui-btn-primary" data-title="添加子菜单" data-modal='{:url("add")}?pid={$vo.id}'>添 加</a>
+                <!--{else}-->
+                <a class="layui-btn layui-btn-xs layui-btn-disabled">添 加</a>
+                <!--{/if}-->
+                {/if}
+
+                {if auth("edit")}
+                <a data-dbclick class="layui-btn layui-btn-xs" data-title="编辑菜单" data-modal='{:url("edit")}?id={$vo.id}'>编 辑</a>
+                {/if}
+
+                {if $vo.status eq 1 and auth("forbid")}
+                <a class="layui-btn layui-btn-warm layui-btn-xs" data-confirm="确定要禁用菜单吗?" data-action="{:url('forbid')}" data-value="id#{$vo.ids};status#0" data-csrf="{:systoken('forbid')}">禁 用</a>
+                {elseif auth("resume")}
+                <a class="layui-btn layui-btn-warm layui-btn-xs" data-action="{:url('resume')}" data-value="id#{$vo.ids};status#1" data-csrf="{:systoken('resume')}">启 用</a>
+                {/if}
+
+                {if auth("remove")}
+                <a class="layui-btn layui-btn-danger layui-btn-xs" data-confirm="确定要删除数据吗?" data-action="{:url('remove')}" data-value="id#{$vo.ids}" data-csrf="{:systoken('remove')}">删 除</a>
+                {/if}
+
+            </td>
+        </tr>
+        {/foreach}
+        </tbody>
+    </table>
+    {/empty}
+</div>
+{/block}

+ 68 - 0
application/admin/view/oplog/index.html

@@ -0,0 +1,68 @@
+{extend name='main'}
+
+{block name="button"}
+
+{if auth("clear")}
+<button data-load='{:url("clear")}' data-confirm="确定要消除所有日志吗?" class='layui-btn layui-btn-sm layui-btn-primary'>清理日志</button>
+{/if}
+
+{if auth("remove")}
+<button data-action='{:url("remove")}' data-rule="id#{key}" data-csrf="{:systoken('remove')}" data-confirm="确定要删除日志吗?" class='layui-btn layui-btn-sm layui-btn-primary'>删除日志</button>
+{/if}
+
+{/block}
+
+{block name="content"}
+<div class="think-box-shadow">
+    {include file='oplog/index_search'}
+    <table class="layui-table margin-top-10" lay-skin="line">
+        {notempty name='list'}
+        <thead>
+        <tr>
+            <th class='list-table-check-td think-checkbox'>
+                <input data-auto-none data-check-target='.list-check-box' type='checkbox'>
+            </th>
+            <th class='text-left nowrap'>操作权限</th>
+            <th class='text-left nowrap'>操作行为</th>
+            <th class='text-left nowrap'>地理位置</th>
+            <th class='text-left nowrap'>操作时间</th>
+            <th></th>
+        </tr>
+        </thead>
+        <tbody>
+        {foreach $list as $key=>$vo}
+        <tr data-dbclick>
+            <td class='list-table-check-td think-checkbox'>
+                <input class="list-check-box" value='{$vo.id}' type='checkbox'>
+            </td>
+            <td class="text-left nowrap">
+                <span class="font-w7">{$vo.username|default='-'}</span><br>
+                <span class="color-desc">{$vo.node|default='-'}</span>
+            </td>
+            <td class='text-left nowrap'>
+                <p class="color-text">{$vo.action|default='-'}</p>
+                <p class="color-desc">{$vo.content|default='-'}</p>
+            </td>
+            <td class='text-left nowrap'>
+                <p class="color-text">{$vo.geoip|default='-'}</p>
+                <p class="color-desc">{$vo.isp|default='-'}</p>
+            </td>
+            <td class='text-left nowrap'>
+                日期:{$vo.create_at|format_datetime|str_replace=' ','<br><span class="color-desc">时间:',###|raw}</span>
+            </td>
+            <td class='text-left nowrap'>
+                {if auth("remove")}
+                <a data-dbclick class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="确定要删除该日志吗?" data-action="{:url('remove')}" data-value="id#{$vo.id}" data-csrf="{:systoken('remove')}">删 除</a>
+                {/if}
+            </td>
+        </tr>
+        {/foreach}
+        </tbody>
+        {/notempty}
+    </table>
+
+    {empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
+
+</div>
+
+{/block}

+ 56 - 0
application/admin/view/oplog/index_search.html

@@ -0,0 +1,56 @@
+<fieldset>
+
+    <legend>条件搜索</legend>
+
+    <form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">操作账号</label>
+            <div class="layui-input-inline">
+                <input name="username" value="{$Think.get.username|default=''}" placeholder="请输入操作账号" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">操作节点</label>
+            <div class="layui-input-inline">
+                <input name="node" value="{$Think.get.node|default=''}" placeholder="请输入操作节点" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">操作行为</label>
+            <div class="layui-input-inline">
+                <input name="action" value="{$Think.get.action|default=''}" placeholder="请输入操作行为" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">操作描述</label>
+            <div class="layui-input-inline">
+                <input name="content" value="{$Think.get.content|default=''}" placeholder="请输入操作内容" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">位置地址</label>
+            <div class="layui-input-inline">
+                <input name="geoip" value="{$Think.get.geoip|default=''}" placeholder="请输入位置地址" class="layui-input">
+            </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="{$Think.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>
+
+<script>form.render()</script>

+ 94 - 0
application/admin/view/queue/index.html

@@ -0,0 +1,94 @@
+{extend name='main'}
+
+{block name="button"}
+
+{if auth("start") && $iswin}
+<button data-load='{:url("start")}' class='layui-btn layui-btn-sm layui-btn-primary'>开始监听</button>
+{/if}
+
+{if auth("stop") && $iswin}
+<button data-load='{:url("stop")}' data-confirm="确定要停止主进程监听吗?" class='layui-btn layui-btn-sm layui-btn-primary'>停止监听</button>
+{/if}
+
+{if auth("remove")}
+<button data-action='{:url("remove")}' data-rule="id#{key}" data-confirm="确定批量删除任务吗?" class='layui-btn layui-btn-sm layui-btn-primary'>批量删除</button>
+{/if}
+
+{if auth("clear")}
+<button data-load='{:url("clear")}' data-confirm="确定要清理3天前的任务记录吗?" class='layui-btn layui-btn-sm layui-btn-primary'>清理记录</button>
+{/if}
+
+{/block}
+
+{block name="content"}
+
+<div class="think-box-shadow">
+    {include file='queue/index_search'}
+    <table class="layui-table margin-top-15" lay-skin="line">
+        {notempty name='list'}
+        <thead>
+        <tr>
+            <th class='list-table-check-td think-checkbox'>
+                <input data-auto-none data-check-target='.list-check-box' type='checkbox'>
+            </th>
+            <th class='text-left nowrap'>任务信息</th>
+            <th class='text-left nowrap'>任务时间</th>
+            <th class='text-left nowrap'>任务状态</th>
+        </tr>
+        </thead>
+        {/notempty}
+        <tbody>
+        {foreach $list as $key=>$vo}
+        <tr>
+            <td class='list-table-check-td think-checkbox'>
+                <input class="list-check-box" value='{$vo.id}' type='checkbox'>
+            </td>
+            <td class='text-left nowrap'>
+                任务名称:{$vo.title}<br>
+                <span class="color-desc">任务指令:{$vo.preload}</span>
+            </td>
+            <td class='text-left nowrap'>
+                计划时间:{$vo.time|format_datetime} {if isset($vo.exec_pid) and $vo.exec_pid>0}( 进程 <b class="color-blue">{$vo.exec_pid|default='-'}</b> ){/if}<br>
+                {if $vo.status eq 3 or $vo.status eq 4}
+                执行时间:{$vo.start_at|format_datetime}( 耗时 <b class="color-blue">{:sprintf("%.4f",strtotime($vo.end_at)-strtotime($vo.start_at))}</b> 秒 )
+                {elseif $vo.status eq 2} 开始时间:{$vo.start_at|format_datetime}
+                {else} 创建时间:{$vo.create_at|format_datetime} {/if}
+            </td>
+            <td class='text-left nowrap'>
+                <div>
+                    {eq name='vo.double' value='1'}
+                    <span class="layui-badge layui-bg-green margin-right-5">复</span>
+                    {else}
+                    <span class="layui-badge layui-bg-blue margin-right-5">单</span>
+                    {/eq}
+
+                    {eq name='vo.status' value='1'}
+                    <span class="layui-badge layui-bg-black">待处理</span>
+                    {elseif $vo.status eq 2}
+                    <span class="layui-badge layui-bg-green">处理中</span>
+                    {elseif $vo.status eq 3}
+                    <span class="layui-badge layui-bg-blue">处理完成</span>
+                    {elseif $vo.status eq 4}
+                    <span class="layui-badge layui-bg-red margin-right-5">处理失败</span>
+                    <a class="layui-badge layui-bg-green" data-tips-text="重置该任务" data-action="{:url('redo')}" data-value="id#{$vo.id}">
+                        <i class="layui-icon font-s12">&#xe669;</i>
+                    </a>
+                    {/eq}
+
+                    {if auth("admin/queue/remove") and in_array($vo.status,[1,3,4])}
+                    <a data-action='{:url("remove")}' data-confirm="确定要删除该任务吗?" data-value="id#{$vo.id}" data-tips-text="删除该任务" class='layui-badge layui-bg-red margin-left-5'>
+                        <i class="layui-icon">&#xe640;</i>
+                    </a>
+                    {/if}
+                </div>
+                <div class="color-desc">{$vo.desc|raw|default="没有获取到状态描述"}</div>
+            </td>
+        </tr>
+        {/foreach}
+        </tbody>
+    </table>
+
+    {empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
+
+</div>
+{/block}

+ 70 - 0
application/admin/view/queue/index_search.html

@@ -0,0 +1,70 @@
+{if session('user.username') eq 'admin'}
+<fieldset class="margin-bottom-15">
+    <legend class="notselect">守护状态</legend>
+    <div class="layui-code border-0 margin-top-0">
+        <h4 class="color-desc margin-top-10 notselect">守护进程运行状态</h4>
+        {if $listen}
+        <span class="color-green">{$message|raw|default='--'}</span>
+        {else}
+        <span class="color-red">{$message|raw|default='--'}</span>
+        {/if}
+        <h4 class="color-desc margin-top-10 notselect">配置定时任务来检查并启动进程(建议每分钟执行)</h4>
+        <p>{$command|default='--'}</p>
+    </div>
+</fieldset>
+{/if}
+
+<fieldset>
+    <legend>条件搜索</legend>
+    <form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">任务名称</label>
+            <div class="layui-input-inline">
+                <input name="title" value="{$Think.get.title|default=''}" placeholder="请输入任务名称" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">任务指令</label>
+            <div class="layui-input-inline">
+                <input name="preload" value="{$Think.get.preload|default=''}" placeholder="请输入任务指令" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">任务状态</label>
+            <div class="layui-input-inline">
+                <select name="status" class="layui-select">
+                    {foreach [''=>'-- 全部状态 --','1'=>'待处理','2'=>'处理中','3'=>'处理完成','4'=>'处理失败'] as $k=>$v}
+                    <!--{if $Think.get.status eq $k}-->
+                    <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="{$Think.get.create_at|default=''}" placeholder="请选择创建时间" class="layui-input">
+            </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="start_at" value="{$Think.get.start_at|default=''}" placeholder="请选择开始时间" class="layui-input">
+            </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="end_at" value="{$Think.get.end_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>
+
+<script>form.render()</script>

+ 73 - 0
application/admin/view/user/form.html

@@ -0,0 +1,73 @@
+<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post" autocomplete="off">
+    <div class="layui-card-body padding-left-40">
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">登录用户账号</span>
+                <span class="color-desc margin-left-5">Username</span>
+                {if isset($vo) and isset($vo.username)}
+                <input disabled value='{$vo.username|default=""}' class="layui-input layui-bg-gray">
+                {else}
+                <input name="username" value='{$vo.username|default=""}' required pattern="^.{4,}$" placeholder="请输入4位及以上字符登录用户账号" class="layui-input">
+                {/if}
+            </label>
+            <p class="help-block">登录用户账号创建后,不允许再次修改。</p>
+        </div>
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">用户联系手机</span>
+                <span class="color-desc margin-left-5">Phone</span>
+                <input type="tel" maxlength="11" autocomplete="off" autofocus name="phone" value='{$vo.phone|default=""}' pattern="^1[3-9][0-9]{9}$" placeholder="请输入用户联系手机" class="layui-input">
+            </label>
+            <p class="color-desc">可选,用户联系手机号码,需要填写正确的格式</p>
+        </div>
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">联系电子邮箱</span>
+                <span class="color-desc margin-left-5">Email</span>
+                <input name="mail" autocomplete="off" pattern="^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$" value='{$vo.mail|default=""}' placeholder="请输入联系电子邮箱" class="layui-input">
+            </label>
+            <p class="color-desc">可选,用户联系电子邮箱,需要填写正确的格式</p>
+        </div>
+
+        {notempty name='authorizes'}
+        <div class="layui-form-item relative">
+            <span class="color-green font-w7">角色访问授权</span>
+            <span class="color-desc margin-left-5">Authorization</span>
+            <div class="layui-textarea">
+                {if isset($vo.username) and $vo.username eq 'admin'}
+                <span class="color-desc">超级用户不需要配置权限</span>
+                {elseif empty($authorizes)}
+                <span class="color-desc">未配置权限</span>
+                {else}
+                {foreach $authorizes as $authorize}
+                <label class="think-checkbox layui-unselect">
+                    {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>
+        {/notempty}
+
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">用户身份描述</span>
+                <span class="color-desc margin-left-5">Description</span>
+                <textarea placeholder="请输入用户身份描述" class="layui-textarea" name="desc">{$vo.desc|default=""}</textarea>
+            </label>
+        </div>
+    </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>

+ 77 - 0
application/admin/view/user/index.html

@@ -0,0 +1,77 @@
+{extend name='main'}
+
+{block name="button"}
+
+{if auth("add")}
+<button data-modal='{:url("add")}' data-title="添加用户" class='layui-btn layui-btn-sm layui-btn-primary'>添加用户</button>
+{/if}
+
+{if auth("remove")}
+<button data-action='{:url("remove")}' data-rule="id#{key}" data-csrf="{:systoken('remove')}" data-confirm="确定要删除这些用户吗?" class='layui-btn layui-btn-sm layui-btn-primary'>删除用户</button>
+{/if}
+
+{/block}
+
+{block name="content"}
+<div class="think-box-shadow">
+    {include file='user/index_search'}
+    <table class="layui-table margin-top-10" lay-skin="line">
+        {notempty name='list'}
+        <thead>
+        <tr>
+            <th class='list-table-check-td think-checkbox'>
+                <label><input data-auto-none data-check-target='.list-check-box' type='checkbox'></label>
+            </th>
+            <th class='text-left nowrap'>用户账号</th>
+            <th class='text-left nowrap'>联系手机</th>
+            <th class='text-center nowrap'>登录次数</th>
+            <th class='text-center nowrap'>使用状态</th>
+            <th class='text-left nowrap'>创建时间</th>
+            <th class='text-left nowrap'>登录时间</th>
+            <th class='text-left nowrap'></th>
+        </tr>
+        </thead>
+        {/notempty}
+        <tbody>
+        {foreach $list as $key=>$vo}
+        <tr data-dbclick>
+            <td class='list-table-check-td think-checkbox'>
+                <label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
+            </td>
+            <td class='text-left nowrap'>{$vo.username|default=''}</td>
+            <td class='text-left nowrap'>{$vo.phone|default='-'}</td>
+            <td class='text-center nowrap'>{$vo.login_num|default=0}</td>
+            <td class='text-center nowrap'>{eq name='vo.status' value='0'}<span class="color-red">已禁用</span>{else}<span class="color-green">使用中</span>{/eq}</td>
+            <td class='text-left nowrap'>{$vo.create_at|format_datetime}</td>
+            <td class='text-left nowrap'>{if $vo.login_num>0}{$vo.login_at|format_datetime}{else} - {/if}</td>
+            <td class='text-left nowrap'>
+
+                {if auth("pass")}
+                <a class="layui-btn layui-btn-normal layui-btn-sm" data-title="设置密码" data-modal='{:url("pass")}?id={$vo.id}'>密 码</a>
+                {/if}
+
+                {if auth("edit")}
+                <a data-dbclick class="layui-btn layui-btn-sm" data-title="编辑用户" data-modal='{:url("edit")}?id={$vo.id}'>编 辑</a>
+                {/if}
+
+                {if $vo.status eq 1 and auth("forbid")}
+                <a class="layui-btn layui-btn-sm layui-btn-warm" data-action="{:url('forbid')}" data-value="id#{$vo.id};status#0" data-csrf="{:systoken('forbid')}">禁 用</a>
+                {elseif $vo.status eq 0 and auth("resume")}
+                <a class="layui-btn layui-btn-sm layui-btn-warm" data-action="{:url('resume')}" data-value="id#{$vo.id};status#1" data-csrf="{:systoken('resume')}">启 用</a>
+                {/if}
+
+                {if auth("remove")}
+                <a class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="确定要删除该用户吗?" data-action="{:url('remove')}" data-value="id#{$vo.id}" data-csrf="{:systoken('remove')}">删 除</a>
+                {/if}
+
+            </td>
+        </tr>
+        {/foreach}
+        </tbody>
+    </table>
+
+    {empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
+
+</div>
+
+{/block}

+ 57 - 0
application/admin/view/user/index_search.html

@@ -0,0 +1,57 @@
+<fieldset>
+
+    <legend>条件搜索</legend>
+
+    <form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">用户账号</label>
+            <div class="layui-input-inline">
+                <input name="username" value="{$Think.get.username|default=''}" placeholder="请输入用户名" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">联系手机</label>
+            <div class="layui-input-inline">
+                <input name="phone" value="{$Think.get.phone|default=''}" placeholder="请输入联系手机" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">联系邮箱</label>
+            <div class="layui-input-inline">
+                <input name="mail" value="{$Think.get.mail|default=''}" placeholder="请输入联系邮箱" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">使用状态</label>
+            <div class="layui-input-inline">
+                <select class="layui-select" name="status">
+                    {foreach [''=>'-- 全部状态 --','0'=>'已禁用的账号','1'=>'使用中的账号'] as $k=>$v}
+                    {eq name='Think.get.status' value='$k.""'}
+                    <option selected value="{$k}">{$v}</option>
+                    {else}
+                    <option value="{$k}">{$v}</option>
+                    {/eq}
+                    {/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="login_at" value="{$Think.get.login_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>
+
+<script>form.render()</script>

+ 57 - 0
application/admin/view/user/pass.html

@@ -0,0 +1,57 @@
+<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post" autocomplete="off">
+
+    <div class="layui-card-body padding-left-40">
+
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">登录用户账号</span>
+                <span class="color-desc margin-left-5">Username</span>
+                <!--{if isset($vo) and isset($vo.username)}-->
+                <input disabled value='{$vo.username|default=""}' class="layui-input layui-bg-gray">
+                <!--{else}-->
+                <input name="username" value='{$vo.username|default=""}' required pattern="^.{4,}$" placeholder="请输入4位及以上字符登录用户账号" class="layui-input">
+                <!--{/if}-->
+            </label>
+            <p class="help-block">登录用户账号创建后,不允许再次修改。</p>
+        </div>
+
+        <!--{if $verify}-->
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">旧的登录密码</span>
+                <span class="color-desc margin-left-5">Old Password</span>
+                <input type="password" autofocus name="oldpassword" value='' pattern="^\S{1,}$" required placeholder="请输入旧的登录密码" class="layui-input">
+            </label>
+            <p class="color-desc">请输入旧密码来验证修改权限,旧密码不限制格式。</p>
+        </div>
+        <!--{/if}-->
+
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">新的登录密码</span>
+                <span class="color-desc margin-left-5">New Password</span>
+                <input type="password" name="password" maxlength="32" pattern="^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,32}$" required placeholder="请输入新的登录密码" class="layui-input">
+            </label>
+            <p class="color-desc">密码必需包含大小写字母、数字、符号的任意两者组合。</p>
+        </div>
+
+        <div class="layui-form-item">
+            <label class="relative block">
+                <span class="color-green font-w7">重复登录密码</span>
+                <span class="color-desc margin-left-5">Retype Password</span>
+                <input type="password" name="repassword" maxlength="32" pattern="^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,32}$" required placeholder="请输入重复登录密码" class="layui-input">
+            </label>
+            <p class="color-desc">密码必需包含大小写字母、数字、符号的任意两者组合。</p>
+        </div>
+
+    </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>

+ 245 - 0
application/api/common.php

@@ -0,0 +1,245 @@
+<?php
+// 接口公共方法
+use think\Db;
+//  更新商品库存
+function update_goods_stock($goods_id,$goods_no,$num){
+    $goods_info = Db::table('store_goods')
+        ->field('id,spec,stock')
+        ->where(['id'=>$goods_id])
+        ->find();
+    $spec = json_decode($goods_info['spec'],true);
+    foreach ($spec as $gk=>&$gv) {
+        if($gv['goods_no'] == $goods_no) {
+            $spec[$gk]['store_num'] = bcsub($gv['store_num'],$num) > 0 ? bcsub($gv['store_num'],$num) : 0;
+        }
+    }
+    $stock = $goods_info['stock']-$num >0 ? $goods_info['stock']-$num:0;
+    return   Db::table('store_goods')->where(['id'=>$goods_id])->update(['spec'=>json_encode($spec),'stock'=>$stock]);
+}
+// 获取退款理由
+function get_refund_cause()
+{
+    $list = Db::table('order_refund_cause')
+        ->field('id,title')
+        ->where(['status'=>1])
+        ->order('sort desc , id asc')
+        ->select();
+    return $list;
+}
+//获取当月日历
+function get_month_days(){
+    $date = date('Y-m-d');
+    $start_time = strtotime($date);
+    $total_month_day = date('t', $start_time);// 当月天数
+    $month_data = [];
+    $base_data = date("Y-m");
+    for($i=1;$i<=$total_month_day;$i++) {
+        $c = $i;
+        if($c < 10) $c ='0'.$i;
+        $month_data[] = [
+            'date_str'=>$base_data.'-'.$c,
+            'date' => $i,
+            'prefix_date' => $c,
+            'week' => date('w',strtotime($base_data.'-'.$c))
+        ];
+    }
+    return $month_data;
+
+}
+
+function get_order_sn(){
+    $order_id_main = date('YmdHis') . rand(10000000,99999999);
+    $order_id_len = strlen($order_id_main);
+    $order_id_sum = 0;
+    for($i=0; $i<$order_id_len; $i++){
+        $order_id_sum += (int)(substr($order_id_main,$i,1));
+    }
+    $osn = $order_id_main . str_pad((100 - $order_id_sum % 100) % 100,2,'0',STR_PAD_LEFT);
+    return $osn;
+}
+
+/**
+ *随机抽奖
+ * @param array $data
+ * @param string $field
+ * @param int $num
+ * @return array ['抽中的键'=>'抽中次数']
+ */
+function draw_lottery ($data = [],$field='',$num = 1,$is_clip=0)
+{
+    $draw_data = [];
+    foreach ($data as $k=>$v)
+    {
+        if($is_clip && $k== 0) continue;
+        if($v[$field] > 0)
+        {
+            for($i=1;$i<= $v[$field];$i++) {
+                $draw_data[] = $k.'_key_'.$i;
+            }
+        }
+    }
+    $rand_key = array_rand($draw_data,$num);
+    $draw_key = [];
+    if($num == 1) {
+        $sel_key = explode( '_key_',$draw_data[$rand_key])[0];
+        $draw_key[$sel_key] = 1;
+    }else{
+        for ($a=0;$a<$num;$a++) {
+            $sel_key = explode( '_key_',$draw_data[$rand_key[$a]])[0];
+            if(isset($draw_key[$sel_key])) {
+                $draw_key[$sel_key]++;
+            }else{
+                $draw_key[$sel_key] = 1;
+            }
+        }
+    }
+    return $draw_key;
+}
+
+/**
+ *指定抽奖
+ * @param array $data
+ * @param string $field
+ * @param int $num
+ * @param int $stock  剩余库存
+ * @return array ['抽中的键'=>'抽中次数']
+ */
+function point_lottery ($data = [],$field='',$num = 1,$check_num = 0)
+{
+    $draw_data = [];
+    $draw_key = [];
+    foreach ($data as $k=>$v) {
+        // 指定前三个中奖
+        if(in_array($k,[0,1,2]) && isset($v['point_num'])) {
+            // 剩余库存 > 0  && 售卖数量>= 指定数量 && 可以抽奖
+            if( $v['store_num'] > 0 && $check_num >= $v['point_num'] && $num > 0){
+                $draw_key[$k] = 1;
+                $num =  $num - 1;
+            }
+        }elseif($v[$field] > 0 ) {
+            for($i=1;$i<= $v[$field];$i++) {
+                $draw_data[] = $k.'_key_'.$i;
+            }
+        }
+    }
+
+    if($num == 0) return $draw_key;// 不可以抽奖
+
+    $rand_key = array_rand($draw_data,$num);
+    if($num == 1) {
+        $sel_key = explode( '_key_',$draw_data[$rand_key])[0];
+        $draw_key[$sel_key] = 1;
+    }else{
+        for ($a=0;$a<$num;$a++) {
+            $sel_key = explode( '_key_',$draw_data[$rand_key[$a]])[0];
+            if(isset($draw_key[$sel_key])) {
+                $draw_key[$sel_key]++;
+            }else{
+                $draw_key[$sel_key] = 1;
+            }
+        }
+    }
+    return $draw_key;
+}
+
+
+
+
+function cdraw_lottery($data,$draw_key,$user_id=0,$sel_key)
+{
+    $keys = max(array_keys($draw_key));
+    if($data[$sel_key]['store_num'] > 0 && $keys != $sel_key) {
+        $draw_key[$keys] = $draw_key[$keys] - 1;
+        if($draw_key[$keys] == 0) unset($draw_key[$keys]);
+        if(isset($draw_key[$sel_key])) {
+            $draw_key[$sel_key] = $draw_key[$sel_key]+1;
+        }else{
+            $draw_key[$sel_key] = 1;
+        }
+    }
+    return $draw_key;
+}
+
+
+
+//获取运费
+function get_freight($num)
+{
+    $first_freight = floatval(sysconf('first_freight_price')) > 0  ? floatval(sysconf('first_freight_price')):0;
+    $later_freight = floatval(sysconf('later_freight_price')) > 0  ? floatval(sysconf('later_freight_price')):0;
+    $all_freight  =  bcadd($first_freight,bcmul($num-1,$later_freight,2),2);
+    return ['all_freight'=>$all_freight,'first_freight'=>$first_freight,'later_freight'=>$later_freight];
+}
+
+// 生成消息记录
+function  send_user_message($user_id,$type_id,$content){
+    $msg_data =[
+        'user_id' => $user_id,
+        'type_id' => $type_id,
+        'content' => $content,
+        'create_at' => date('Y-m-d H:is:s'),
+    ];
+    Db::table('user_message')->insert($msg_data);
+    return Db::getLastInsID();
+}
+
+
+// 自动分解魔玩柜
+function resolve_magic($user_id = 0)
+{
+    $time = time();
+    $where = [];
+    $where[] = ['num','>',0];
+    $where[] = ['past_int','<',$time];
+    if($user_id) $where[] = ['user_id','=',$user_id];
+    $magic_case = Db::table('magic_case')
+        ->field('id,user_id,num,crystal')
+        ->where($where)
+        ->select();
+    foreach ($magic_case as $value) {
+        // 扣减魔玩柜变更记录
+        $crystal = bcmul($value['num'],$value['crystal'],2);
+        $log_data= [
+            'user_id' => $value['user_id'],
+            'create_at' => date('Y-m-d H:i:s'),
+            'num' => $value['num'],
+            'case_id' => $value['id'],
+            'crystal' =>$crystal ,
+        ];
+        //更新水晶余额
+        $member_info = Db::table('store_member')->field('id,crystal_cash')->find($value['user_id']);
+        // 扣减魔玩柜的数量
+        Db::startTrans();
+        $res1= Db::table('magic_case')->where('id',$value['id'])->update(['num'=>0]);
+        $res2 = Db::table('store_member')->where('id',$value['user_id'])->update(['crystal_cash'=>bcadd($member_info['crystal_cash'],$crystal,2)]);
+        Db::table('magic_resolve')->insert($log_data);// 分解日志
+        // 余额日志
+        crystal_log($value['user_id'],$crystal,'魔玩柜分解',3);
+        if($res1 && $res2) {
+            Db::commit();
+        }else{
+            Db::rollback();
+        }
+
+    }
+
+
+}
+
+// 运费券过期
+function user_coupon_over($user_id = 0)
+{
+    $where = [];
+    $where[] = ['status','=',1];
+    $where[] = ['past_at','< time',date('Y-m-d H:i:s')];
+    if($user_id) $where[] = ['user_id','=',$user_id];
+    Db::table('user_coupon_list')
+        ->where($where)
+        ->update(['status'=>3]);
+}
+
+
+
+
+
+

+ 173 - 0
application/api/controller/Area.php

@@ -0,0 +1,173 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\api\controller;
+
+use app\common\controller\Api;
+use library\File;
+use think\Db;
+/**
+ * @title 地址库
+ * @controller Area
+ * @group common
+ */
+class Area extends Base
+{
+    /**
+     * @title 获取省市区
+     * @desc 获取省市区
+     * @author QC
+     * @url /api/Area/getAllArea
+     * @method GET
+     * @tag 省市区
+     */
+    public function getAllArea(){
+        $area_set = Db::table('platform_set')->where('name','all_area')->find();
+        if(!empty($area_set) && $area_set['content']) {
+           $list = json_decode($area_set['content'],true);
+        }else{
+            $field=['id','pid','shortname','name'];
+            $list=Db::table('store_area')->where('pid',0)->field($field)->select();
+            foreach ($list as $k=>&$v){
+                $v['children']= Db::table('store_area')->where('pid',$v['id'])->field($field)->select();
+                if(!empty($v['children'])){
+                    foreach ($v['children'] as $kk=>&$vv){
+                        $vv['children']=Db::table('store_area')->where('pid',$vv['id'])->field($field)->select();
+                    }
+                }
+            }
+            if(!empty($area_set)){
+                Db::table('platform_set')->where('name','all_area')->update(['content'=>json_encode($list)]);
+            }else{
+                Db::table('platform_set')->insert(['name'=>'all_area','content'=>json_encode($list)]);
+            }
+        }
+        $this->success('获取成功',$list);
+    }
+
+    /**
+     * @title 获取下级地区
+     * @desc 获取下级地区
+     * @author QC
+     * @url /api/Area/getChildrenArea
+     * @method GET
+     * @param  name:id type:int  default:1 desc:省id或市id
+     */
+    public function getChildrenArea()
+    {
+        $field=['id','pid','shortname','name'];
+        $list=Db::table('store_area')->where('pid',$this->request->get('id'))->field($field)->select();
+        $this->success('获取成功',$list);
+    }
+
+    /**
+     * 获取定位城市
+     */
+    public function getCity(){
+        $list=Db::table('store_area')->where('level',2)->field('first')->group('first')->order('first asc')->select();
+        $field=['id','pid','shortname','name','first'];
+        foreach ($list as $k=>&$v){
+            $v['list']=Db::table('store_area')->where('level',2)->where('first',$v['first'])->field($field)->select();
+        }
+        $hot=Db::table('store_area')->whereIn('id',[2,802,1965])->field($field)->select();
+        $history=Db::table('store_area')->whereIn('id',[2,802,1965])->field($field)->select();
+        array_unshift($list,['first'=>'历史','list'=>$history],['first'=>'热门城市','list'=>$hot]);
+        $this->success('获取成功',$list);
+    }
+
+    /**
+     * @title 通过省市区id返回具体地址信息
+     * @desc 通过省市区id返回具体地址信息
+     * @author QC
+     * @url /api/Area/getCity
+     * @method GET
+     * @tag 省市区
+     */
+    public function get_area($province_id,$city_id,$county_id){
+        $province = '';
+        if(!empty($province_id)){
+            $quarters = Db::name('store_area')->field('name')->where('id',$province_id)->find();
+            $province = $quarters['name'];
+        }
+        $city = '';
+        if(!empty($city_id)){
+            $quarters = Db::name('store_area')->field('name')->where('id',$city_id)->find();
+            $city = $quarters['name'];
+        }
+        $county = '';
+        if(!empty($county_id)){
+            $quarters = Db::name('store_area')->field('name')->where('id',$county_id)->find();
+            $county = $quarters['name'];
+        }
+        return $province.$city.$county;
+    }
+    /**
+     * 通过省市区名称返回省市区id
+     */
+    public function get_area_id($province = '',$city = '',$county = ''){
+        $province_id = '';
+        if(!empty($province)){
+            $province_id = Db::name('store_area')->where('name',$province)->value('id');
+        }
+        $city_id = '';
+        if(!empty($city)){
+            $city_id = Db::name('store_area')->where('name',$city)->value('id');
+        }
+        $county_id = '';
+        if(!empty($county)){
+            $county_id = Db::name('store_area')->where('name',$county)->value('id');
+        }
+        return $province_id.$city_id.$county_id;
+    }
+    /**
+     * 通过id获取名称
+     */
+    public function get_name($id){
+        $quarters = Db::name('store_area')->field('name')->where('id',$id)->find();
+        return $quarters['name'];
+    }
+    /**
+     * 通过省/市的ID获取所有县区ID
+     * $type 1代表省 2代表市
+     */
+    public function get_county_id($id,$type=1){
+        $county_id_str = '';
+        if($type == 1){
+            $city_id_arr = Db::name('store_area')->field('id')->where('pid',$id)->column('id');
+            foreach ($city_id_arr as $value){
+                $county_id_arr = Db::name('store_area')->field('id')->where('pid',$value)->column('id');
+                $county_id_str .= implode(',',$county_id_arr).',';
+            }
+        }else{
+            $county_id_arr = Db::name('store_area')->field('id')->where('pid',$id)->column('id');
+            $county_id_str .= implode(',',$county_id_arr).',';
+        }
+        return substr($county_id_str,0,strlen($county_id_str)-1);
+    }
+    /**
+     * 通过省的ID获取所有市的ID
+     */
+    public function get_city_id($id){
+        $city_id_arr = Db::name('store_area')->field('id')->where('pid',$id)->column('id');
+        return implode(',',$city_id_arr);
+    }
+    /**
+     * 通过市的ID获取省的ID
+     */
+    public function get_province_id($id){
+        $province_id = Db::name('store_area')->field('id')->where('id',$id)->value('pid');
+        return $province_id;
+    }
+}

+ 155 - 0
application/api/controller/Base.php

@@ -0,0 +1,155 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\api\controller;
+
+use app\common\controller\Api;
+use Firebase\JWT\JWT;
+use think\Controller;
+use think\Db;
+use think\Exception;
+use think\exception\HttpResponseException;
+use think\Request;
+use think\Response;
+
+/**
+ * 会员管理基类
+ * Class Member
+ * @package app\store\controller\api
+ */
+class Base extends Controller
+{
+    protected $uid = 5;
+
+    protected $page; // 页数
+    protected $page_num;
+    protected $off_set;
+    public function initialize(){
+        $this->page = input('page',1);
+        $this->page_num = input('page_num',20);
+        $this->off_set   =   $this->page * $this->page_num - $this->page_num;
+    }
+    //校验jwt权限API
+    protected function check_login()
+    {
+        //return true;
+        $authorization = app()->request->header('Authorization');
+        //var_dump($authorization.'111');exit();
+        if(empty($authorization) || $authorization == null){
+            $this->error('Token不存在,拒绝访问','',0);
+        }
+        $key = md5(config('app.jwt'));
+        try {
+            $jwtAuth = json_encode(JWT::decode($authorization, $key, array('HS256')));
+            $authInfo = json_decode($jwtAuth, true);
+            if (!empty($authInfo['uid'])) {
+                $member = Db::name('store_member')->field('status')->where('id',$authInfo['uid'])->find();
+                if($member['status']){
+                    $this->uid = $authInfo['uid'];
+                    return $this->uid;
+                }else{
+                    $this->error('该会员已被禁用','',0);
+                }
+            } else {
+                $this->error('Token验证不通过,用户不存在','',0);
+            }
+        } catch (\Firebase\JWT\SignatureInvalidException $e) {
+            $this->error('Token无效','',0);
+        } catch (\Firebase\JWT\ExpiredException $e) {
+            $this->error('Token过期','',0);
+        } catch (Exception $e) {
+            return $e;
+        }
+    }
+    /**
+     * 操作成功返回的数据
+     * @param string $msg   提示信息
+     * @param mixed $data   要返回的数据
+     * @param int   $code   错误码,默认为1
+     * @param string $type  输出类型
+     * @param array $header 发送的 Header 信息
+     */
+    protected function success($msg = '', $data = null , $is_login = 1, $code = 1, $type = null, array $header = [])
+    {
+        $this->results($msg, $data, $is_login, $code, $type, $header);
+    }
+
+    /**
+     * 操作失败返回的数据
+     * @param string $msg   提示信息
+     * @param mixed $data   要返回的数据
+     * @param int   $code   错误码,默认为0
+     * @param string $type  输出类型
+     * @param array $header 发送的 Header 信息
+     */
+    protected function error($msg = '', $data = null, $is_login = 1, $code = 0, $type = null, array $header = [])
+    {
+        if(empty($this->uid)){
+            $is_login = 0;
+        }
+        $this->results($msg, $data, $is_login, $code, $type, $header);
+    }
+    /**
+     * 返回封装后的 API 数据到客户端
+     * @access protected
+     * @param mixed  $msg    提示信息
+     * @param mixed  $data   要返回的数据
+     * @param int    $code   错误码,默认为0
+     * @param string $type   输出类型,支持json/xml/jsonp
+     * @param array  $header 发送的 Header 信息
+     * @return void
+     * @throws HttpResponseException
+     */
+    protected function results($msg, $data = null, $is_login, $code = 0, $type = null, array $header = [])
+    {
+        $result = [
+            'code' => $code,
+            'is_login' => $is_login,
+            'msg'  => $msg,
+            'time' => \think\facade\Request::instance()->server('REQUEST_TIME'),
+            'data' => $data,
+        ];
+        // 如果未设置类型则自动判断
+        $type = $type ? $type : 'json';
+
+        if (isset($header['statuscode']))
+        {
+            $code = $header['statuscode'];
+            unset($header['statuscode']);
+        }
+        else
+        {
+            //未设置状态码,根据code值判断
+            $code = $code >= 1000 || $code < 200 ? 200 : $code;
+        }
+        $response = Response::create($result, $type, $code)->header($header);
+        throw new HttpResponseException($response);
+    }
+    protected function get_uid(){
+        $uid = 0;
+        $authorization = app()->request->header('Authorization');
+        if(!empty($authorization)){
+            $key = md5(config('app.jwt'));
+            $jwtAuth = json_encode(JWT::decode($authorization, $key, array('HS256')));
+            $authInfo = json_decode($jwtAuth, true);
+            if (!empty($authInfo['uid'])) {
+                $uid = $authInfo['uid'];
+            }
+        }
+        return $uid;
+    }
+
+
+}

+ 283 - 0
application/api/controller/Crystal.php

@@ -0,0 +1,283 @@
+<?php
+
+
+namespace app\api\controller;
+use think\Controller;
+use think\Db;
+
+/**
+ * @title 水晶
+ * Class Crystal
+ * @controller Crystal
+ * @group base
+ */
+class Crystal extends Base
+{
+
+    public function initialize()
+    {
+         parent::check_login();
+    }
+
+
+    /**
+     * @title 水晶充值(订单支付)
+     * @desc  水晶充值(订单支付)
+     * @author  qc
+     * @url /api/Crystal/payOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:o_id type:int require:1 default:-- desc:订单id
+     * @return name:config.appId type:string default:-- desc:公众账号ID
+     * @return name:config.nonceStr type:string default:-- desc:随机字符串
+     * @return name:config.signType type:string default:-- desc:签名类型
+     * @return name:config.paySign type:string default:-- desc:签名
+     * @return name:config.timestamp type:string default:-- desc:时间戳
+     */
+    public function payOrder()
+    {
+        $o_id = input('post.o_id',0);
+        $crystal_order =Db::table('crystal_order')->find($o_id);
+        $user_info = Db::table('store_member')->where('id',$this->uid)->find();
+        if(!$user_info['openid']) $this->error('请先完善用户信息');
+        if(empty($crystal_order) || $crystal_order['pay_state'] !=0 ) $this->error('订单有误');
+        Db::startTrans();
+        $config = false;$msg= '';
+        try{
+            $notify_url = $this->request->root(true) . '/api/Pay/crystalRecharge';
+            $pay_no = $crystal_order['pay_no'] ?  $crystal_order['pay_no'] : get_order_sn();
+            $config = Pay::wxPay('订单支付',$pay_no,$crystal_order['price_total'],$notify_url,'JSAPI',$user_info['openid']);
+            if($config){
+                Db::commit();
+            }else{
+                Db::rollback();
+            }
+        }catch (\Exception $e){
+            Db::rollback();
+            $msg = $e->getMessage();
+        }
+        if($config){
+            $this->success('ok',['config'=>$config]);
+        }else{
+            $this->error($msg);
+        }
+    }
+
+
+    /**
+     * @title 水晶充值(立即充值)
+     * @desc  水晶充值
+     * @author  qc
+     * @url /api/Crystal/crystalRecharge
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:crystal type:int require:1 default:-- desc:充值数量
+     * @param name:price_total type:int require:1 default:-- desc:支付金额
+     * @return name:config type:array default:0 desc:支付配置
+     * @return name:config.appId type:string default:-- desc:公众账号ID
+     * @return name:config.nonceStr type:string default:-- desc:随机字符串
+     * @return name:config.signType type:string default:-- desc:签名类型
+     * @return name:config.paySign type:string default:-- desc:签名
+     * @return name:config.timestamp type:string default:-- desc:时间戳
+     */
+    public function crystalRecharge()
+    {
+        $crystal = input('post.crystal',0);
+        $price_total = input('post.price_total',0);
+        if($crystal <=0 || $price_total <=0 ) $this->error('充值数量有误!');
+        $crystal_order = [
+            'uid' => $this->uid ,
+            'crystal' => $crystal ,
+            'price_total' => $price_total,
+            'order_no' =>get_order_sn(),
+            'pay_no' =>get_order_sn(),
+            'create_at' => date("Y-m-d H:i:s")
+        ];
+        $user_info = Db::table('store_member')->find($this->uid);
+        Db::startTrans();
+        $config = false;$msg= '';
+        try{
+            Db::table('crystal_order')->insert($crystal_order);
+            $notify_url = $this->request->root(true) . '/api/Pay/crystalRecharge';
+            $pay_no = $crystal_order['pay_no'] ?  $crystal_order['pay_no'] : get_order_sn();
+            $config = Pay::wxPay('订单支付',$pay_no,$crystal_order['price_total'],$notify_url,'JSAPI',$user_info['openid']);
+            if($config){
+                Db::commit();
+            }else{
+                Db::rollback();
+            }
+        }catch (\Exception $e){
+            Db::rollback();
+            $msg = $e->getMessage();
+        }
+        if($config){
+            $this->success('ok',['config'=>$config]);
+        }else{
+            $this->error($msg);
+        }
+    }
+
+
+    /**
+     * @title  删除订单
+     * @desc  删除订单
+     * @author  qc
+     * @url /api/Crystal/delCrystalOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:order_id type:int require:1 default:-- desc:订单id
+     */
+    public function delCrystalOrder()
+    {
+         Db::table('crystal_order')->where(['uid'=>$this->uid,'id'=>input('post.order_id')])->delete();
+         $this->success('ok');
+    }
+
+    /**
+     * @title  获取水晶充值订单列表
+     * @desc  获取水晶充值订单列表
+     * @author  qc
+     * @url /api/Crystal/getCrystalOrderList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  : default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @param  name:status type:int  : default:-1 desc:订单状态(-1全部,0待支付,1已支付)
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:price_total type:string default:-- desc:支付金额
+     * @return name:crystal type:string default:-- desc:充值水晶数量
+     * @return name:pay_state type:string default:-- desc:支付状态(0未支付,1已支付)
+     * @return name:pay_at type:string default:-- desc:支付时间
+     * @return name:pay_no type:string default:-- desc:支付单号
+     */
+    public function getCrystalOrderList()
+    {
+        $status  = input('status',-1);
+        $where=[];
+        if($status > -1) $where['status'] = $status;
+        $where['uid'] = $this->uid;
+        $list = Db::table('crystal_order')
+            ->where($where)
+            ->order('id desc')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('ok',['list'=>$list]);
+    }
+
+
+    /**
+     * @title  获取水晶明细
+     * @desc  获取水晶明细
+     * @author  qc
+     * @url /api/Crystal/getCrystalLog
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  : default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @return name:desc type:string default:-- desc:描述
+     * @return name:type type:int default:-- desc:类型
+     * @return name:crystal type:int default:-- desc:水晶变更数
+     * @return name:create_at type:string default:-- desc:时间
+     */
+    public function getCrystalLog()
+    {
+        $list = Db::table('crystal_info')
+            ->field('id,desc,crystal,type,create_at')
+            ->where(['user_id'=>$this->uid])
+            ->order('id desc')
+            ->limit($this->page,$this->page_num)
+            ->select();
+        $this->success('ok',$list);
+    }
+
+
+    /**
+     * @title  水晶提现申请
+     * @desc  水晶提现申请
+     * @author  qc
+     * @url /api/Crystal/crystalCash
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:crystal type:float  : default:1 desc:提现额度
+     * @return name:id type:int default:-- desc:提现记录id
+     */
+    public function crystalCash()
+    {
+        $crystal = input('post.crystal',0);
+        $user_info = Db::table('store_member')->where('id',$this->uid)->find();
+        if($user_info['crystal_cash'] < $crystal) $this->error('可提现水晶不足!');
+        $data = [
+            'uid' => $this->uid,
+            'order_no' => get_order_sn(),
+            'price_total' => $crystal,
+            'crystal' => $crystal,
+            'sh_status' => 0,
+            'status' => 0,
+            'create_at' => date('Y-m-d H:i:s'),
+        ];
+        Db::table('crystal_cash_order')->insert($data);
+        $id  =  Db::getLastInsID();
+        Db::table('store_member')->where('id',$user_info['id'])->update(['crystal_cash'=>bcsub($user_info['crystal_cash'],$crystal,2)]);
+        crystal_log($this->uid,$crystal*-1,'水晶提现',4,$id);
+        $this->success('申请成功,等待审核',['id'=>$id]);
+    }
+
+
+
+    /**
+     * @title  取消水晶提现申请
+     * @desc  取消水晶提现申请
+     * @author  qc
+     * @url /api/Crystal/cancelCrystalCash
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:float  : default:1 desc:提现记录id
+     */
+    public function cancelCrystalCash()
+    {
+        $id = input('post.id',0);
+        $app_info = Db::table('crystal_cash_order')->where('cancel_status',0)->where('id',$id)->find();
+        if(empty($app_info)) $this->error('提现记录不存在!');
+        $user_info = Db::table('store_member')->field('crystal_cash')->where('id',$this->uid)->find();
+        Db::table('store_member')->where('id',$this->uid)->update(['crystal_cash'=>bcadd($user_info['crystal_cash'],$app_info['crystal'],2)]);
+        crystal_log($this->uid,$app_info['crystal'],'提现取消',7,$id);
+        $this->success('取消成功',['id'=>$id]);
+    }
+
+
+
+    /**
+     * @title  获取水晶提现申请记录
+     * @desc  获取水晶提现申请记录
+     * @author  qc
+     * @url /api/Crystal/getCrystalCashLog
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  : default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @param  name:sh_status type:int  : default:-1 desc:审核状态
+     * @return name:crystal type:int default:-- desc:提现额度
+     * @return name:create_at type:string default:-- desc:时间
+     * @return name:sh_status type:string default:-- desc:审核状态(0未审核1审核通过2审核不通过)
+     * @return name:status type:string default:-- desc:处理状态0未完成1已完成
+     */
+    public function getCrystalCashLog()
+    {
+        $where = [];
+        $where['user_id'] = $this->uid;
+        $where['cancel_status'] = 0;
+        $sh_status = input('get.sh_status',-1);
+        if($sh_status >=0) $where['sh_status'] = $sh_status;
+        $list = Db::table('crystal_cash_order')
+            ->field('id,crystal,create_at,sh_status')
+            ->where($where)
+            ->order('id desc')
+            ->limit($this->page,$this->page_num)
+            ->select();
+        $this->success('ok',['list'=>$list]);
+    }
+
+
+
+
+}

+ 394 - 0
application/api/controller/ExchangeOrder.php

@@ -0,0 +1,394 @@
+<?php
+namespace app\api\controller;
+use think\Db;
+use EasyWeChat\Factory;
+/**
+ * @title 兑换订单
+ * @controller ExchangeOrder
+ * @group base
+ */
+class ExchangeOrder extends Base
+{
+    public function initialize()
+    {
+        parent::initialize();
+        parent::check_login();
+    }
+
+
+
+
+    /**
+     * @title 订单确认
+     * @desc  订单确认
+     * @author  qc
+     * @url /api/Exchange_order/orderConfirm
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param name:goods_id type:int  require:1  default:0 desc:商品id
+     * @param name:num type:int  require:1  default:1 desc:商品数量
+     * @return name:add_info type:array require:0 default:-- desc:默认地址
+     * @return name:add_info.id type:int   default:1 desc:收货地址记录id
+     * @return name:add_info.pro_id type:int   default:-- desc:省id
+     * @return name:add_info.city_id type:int   default:-- desc:市id
+     * @return name:add_info.county_id type:int  default:-- desc:县区id
+     * @return name:add_info.pro_name type:string  default:-- desc:省名
+     * @return name:add_info.city_name type:string  default:-- desc:市名
+     * @return name:add_info.county_name type:string  default:-- desc:县区名
+     * @return name:add_info.detail type:string  default:-- desc:详细地址
+     * @return name:add_info.phone type:string  default:-- desc:联系电话
+     * @return name:add_info.name type:string   default:-- desc:联系人
+     * @return name:goods_data type:array require:0 default:-- desc:商品详情
+     * @return name:goods_data.id type:array require:0 default:-- desc:商品id
+     * @return name:goods_data.stock type:string require:0 default:-- desc:剩余库存
+     * @return name:goods_data.name type:string require:0 default:-- desc:名称
+     * @return name:goods_data.cover type:string require:0 default:-- desc:图片
+     * @return name:goods_data.crystal type:string require:0 default:-- desc:水晶
+     * @return name:freight_data type:array  default:--  desc:运费详情
+     * @return name:freight_data.all_freight type:int  default:--  desc:总运费
+     * @return name:freight_data.first_freight type:int  default:--  desc:首件运费
+     * @return name:freight_data.later_freight type:int  default:--  desc:续件运费
+     * @return name:coupon_list   type:array  default:--  desc:可用运费券
+     * @return name:coupon_list.id type:int  default:--  desc:券id
+     * @return name:coupon_list.past_at type:int  default:--  desc:过期时间
+     */
+    public function orderConfirm(){
+        $goods_id = input('get.goods_id',0);
+        $num = input('get.num',1);
+        $goods_info = Db::table('exchange_goods')->field('id,name,cover,status,stock,crystal')
+            ->where(['id'=>$goods_id,'is_deleted'=>0])->find();
+       // if($goods_info['status'] !=  1) $this->error('商品已下架');
+       // if($goods_info['stock'] <  $num) $this->error('商品库存不足');
+        // 默认收货地址
+        $add_info = Db::table('delivery_address')->where(['user_id'=>$this->uid,'is_mr'=>1])->find();
+        $freight_data = get_freight($num);// 计算运费
+        // 运费券
+        $coupon_list = Db::table('user_coupon_list')
+            ->field('id,past_at')
+            ->where('user_id','=',$this->uid)
+            ->where('status','=',1)
+            ->where('past_at','> time',date('Y-m-d H:i:s'))
+            ->order('id desc')
+            ->select();
+        $this->success('ok',['add_info'=> $add_info ,'goods_data'=>$goods_info,'freight_data'=>$freight_data,'coupon_list'=>$coupon_list]);
+    }
+
+
+
+    /**
+     * @title 生成订单(立即购买 )
+     * @desc  生成订单(立即购买 )
+     * @author  qc
+     * @url /api/Exchange_order/createOrderByImmediately
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:goods_id type:int require:1 default:-- desc:商品id
+     * @param name:num type:int require:1 default:1 desc:商品数量
+     * @param name:price_total type:float require:1 default:-- desc:支付金额
+     * @param name:add_id type:int require:1 default:0 desc:收货地址id
+     * @param name:coupon_id type:int require:0 default:0 desc:券id
+     * @return  name:order_id type:int require:0 default:0 desc:成功时返回订单id
+     */
+    public function createOrderByImmediately()
+    {
+        $goods_id               =  input("post.goods_id",0);
+        $num                    =  input("post.num",1);
+        $add_id                    =  input("post.add_id",0);
+        $coupon_id                    =  input("post.coupon_id",0);
+        if(!$add_id) $this->error('请选择收货地址');
+        $goods_info = Db::table('exchange_goods')->field('id,name,cover,status,stock,crystal')
+            ->where(['id'=>$goods_id,'is_deleted'=>0])->find();
+        if(empty($goods_info))  $this->error('商品已下架');
+        if($goods_info['status'] !=  1) $this->error('商品已下架');
+        if($goods_info['stock'] <  $num) $this->error('商品库存不足');
+
+        if($coupon_id) {
+            $coupon_info = Db::table('user_coupon_list')
+                ->where('id','=',$coupon_id)
+                ->where('past_at','> = ',date('Y-m-d H:i:s'))
+                ->find();
+            if(!$coupon_info || $coupon_info['status'] != 1 ) $this->error('运费券信息有误');
+        }
+        $pro_info =[
+            'goods_id' => $goods_id,
+            'name' => $goods_info['name'],
+            'cover' => $goods_info['cover'],
+            'num' => $num,
+            'crystal' => $goods_info['crystal'],
+        ];
+        $freight = get_freight($num); // 运费
+        $price_total = $coupon_id ?  $freight['all_freight'] - $freight['first_freight']:$freight['all_freight'] ;
+        $order_int =[
+            'uid'=>$this->uid,
+            'order_no'      => get_order_sn(),
+            'price_total'   => $price_total,
+            'goods_num'     => $num,
+            'pro_info'     => json_encode($pro_info),
+            'create_at'     =>date('Y-m-d H:i:s'),
+            'freight'      =>$freight['all_freight'],
+            'cl_id'        =>$coupon_id,
+            'address_id'      =>$add_id,
+            'goods_id'        => $goods_id,
+            'goods_name'      => $goods_info['name'],
+            'goods_cover'           => $goods_info['cover'],
+            'crystal'          => bcmul($goods_info['crystal'],$num,2),
+
+        ];
+        $user_info =Db::table('store_member')->find($this->uid);
+        if(bcadd($user_info['crystal'],$user_info['crystal_cash'],2) < $order_int['crystal'])$this->error('水晶余额不足!');
+        Db::startTrans();
+        $msg= '';$com=true;
+        try{
+            //扣减库存
+            Db::table('exchange_goods')->where('id',$goods_id)->setDec('stock',$num);
+
+            // 扣除余额
+            $user_up = [];
+            if($user_info['crystal'] >= $order_int['crystal'] ) {
+                $user_up['crystal'] = bcsub($user_info['crystal'],$order_int['crystal'],2);
+            }else{
+                $user_up['crystal'] = 0;
+                $user_up['crystal_cash'] = bcsub( $user_info['crystal_cash'] + $user_info['crystal'],$order_int['crystal'],2);
+            }
+            Db::table('store_member')->where(['id'=>$this->uid])->update($user_up);
+
+            if($coupon_id) Db::table('user_coupon_list')->where('id',$coupon_id)->update(['status'=>2,'used_time'=>date('Y-m-d H:i:s')]);
+            // 生成订单
+            Db::table('exchange_order')->insert($order_int);
+            $order_id = Db::getLastInsID();
+            crystal_log($this->uid,$order_int['crystal']*-1,'水晶兑换',5,$order_id);
+            Db::commit();
+        }catch (\Exception $e){
+            Db::rollback();
+            $com=false;
+            $msg = $e->getMessage();
+        }
+        if($com){
+            $this->success('ok',['order_id'=>$order_id]);
+        }else{
+            $this->error($msg);
+        }
+    }
+
+    /**
+     * @title 获取订单详情
+     * @desc  获取订单详情
+     * @author  qc
+     * @url /api/Exchange_order/getOrderDetail
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int require:1 default:-- desc:订单id
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:status type:int default:-- desc:支付状态:0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消
+     * @return name:price_total type:float default:-- desc:订单金额(实际支付金额)
+     * @return name:freight type:float default:-- desc:运费
+     * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
+     * @return name:pay_no type:string default:-- desc:支付单号
+     * @return name:pay_time type:string default:-- desc:支付时间
+     * @return name:create_at type:string default:-- desc:订单创建时间
+     * @return name:cancel_state type:int default:-- desc:取消状态
+     * @return name:goods_id type:int default:-- desc:商品id
+     * @return name:goods_name type:string default:-- desc:商品名
+     * @return name:goods_cover type:string default:-- desc:商品图片
+     * @return name:goods_num type:int default:-- desc:商品数量
+     * @return name:express_company_title type:string default:-- desc:物流公司
+     * @return name:express_send_no type:string default:-- desc:物流单号
+     * @return name:express_send_at type:string default:-- desc:发货时间
+     * @return name:express_company_id type:string default:-- desc:物流公司id
+     * @return name:address_area type:string default:0 desc:收货地区(精确到县区)
+     * @return name:address_detail type:string default:0 desc:详细地址
+     * @return name:address_user type:string default:0 desc:收货人姓名
+     * @return name:address_tel type:string default:0 desc:收货人电话
+     */
+    public function getOrderDetail()
+    {
+        $order_id = input('id',0);
+        $detail = Db::table('exchange_order')->find($order_id);
+        $add_info = Db::table('delivery_address')->find($detail['address_id']);
+        $detail['address_area']  = $add_info['mer_name'];
+        $detail['address_detail'] = $add_info['detail'];
+        $detail['address_user'] = $add_info['name'];
+        $detail['address_tel'] = $add_info['phone'];
+        $this->success('获取成功',$detail);
+
+    }
+
+    /**
+     * @title 去支付
+     * @desc  去支付
+     * @author  qc
+     * @url /api/Exchange_order/payOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:o_id type:int require:1 default:-- desc:订单id
+     * @return name:pay_type type:int require:1 default:-- desc:1纯兑换,不支付,2微信支付
+     * @return name:config type:array default:0 desc:支付配置pay_type=1时忽略
+     * @return name:config.appId type:string default:-- desc:公众账号ID
+     * @return name:config.nonceStr type:string default:-- desc:随机字符串
+     * @return name:config.signType type:string default:-- desc:签名类型
+     * @return name:config.paySign type:string default:-- desc:签名
+     * @return name:config.timestamp type:string default:-- desc:时间戳
+     */
+    public function payOrder()
+    {
+        $o_id = input('post.o_id');
+        $user_info = Db::table('store_member')->where('id',$this->uid)->find();
+        if(!$user_info['openid']) $this->error('请先完善用户信息');
+        $order_info =     Db::table('exchange_order')->where(['uid'=>$this->uid,'id'=>$o_id])->find();
+        if(empty($order_info)) $this->error('订单不存在');
+        if($order_info['cancel_state'] != 0) $this->error('订单已取消');
+        if($order_info['status'] != 0) $this->error('订单已支付');
+        $pay_no = $order_info['pay_no'] ?  $order_info['pay_no'] : get_order_sn();
+        // 纯积分兑换
+        $msg ='';
+        if($order_info['price_total'] == 0 ) {
+            Db::table('exchange_order')->where(['uid'=>$this->uid,'id'=>$o_id])
+                ->update(['pay_time'=>date('Y-m-d H:i:s'),'pay_state'=>1,'status'=>1,'pay_no'=>$pay_no]);
+            $this->success('兑换成功',['pay_type'=>2,'config' => '']);
+        }else{
+            $notify_url = $this->request->root(true) . '/api/Pay/exchangeOrderNotify';
+            Db::startTrans();
+            try{
+                // 更新订单
+                $price_total = $order_info['price_total'];
+                Db::table('exchange_order')->where(['uid'=>$this->uid,'id'=>$o_id])->update(['pay_no'=>$pay_no]);
+                $config = Pay::wxPay('订单支付',$pay_no,$price_total,$notify_url,'JSAPI',$user_info['openid']);
+                //var_dump('订单支付',$pay_no,$price_total,$notify_url,'JSAPI',$user_info['openid']);
+                if($config){
+                    Db::commit();
+                }else{
+                    Db::rollback();
+                }
+            }catch (\Exception $e){
+                Db::rollback();
+                $msg = $e->getMessage();
+            }
+            if($config){
+                $this->success('ok',['pay_type'=>1,'config'=>$config]);
+            }else{
+                $this->error($msg);
+            }
+        }
+    }
+
+
+    /**
+     * @title 取消订单
+     * @desc  取消订单
+     * @author  qc
+     * @url /api/Exchange_order/cancelOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:id type:int require:1 default:-- desc:订单id
+     */
+    public function cancelOrder()
+    {
+        $order_id = input('post.id');
+        $order_detail = Db::table('exchange_order')->where(['id'=>$order_id,'uid'=>$this->uid])->find();
+        if(empty($order_detail)) $this->error('订单不存在');
+        if($order_detail['pay_state'] != 0)      $this->error('订单已支付');
+        if($order_detail['cancel_state'] != 0)   $this->error('订单已取消,不能重复取消');
+        $user_info =Db::table('store_member')->find($this->uid);
+        Db::startTrans();
+        try {
+            if($order_detail['crystal'] > 0) {
+                Db::table('store_member')->where(['id'=>$this->uid])->update(['crystal'=>bcadd($user_info['crystal'],$order_detail['crystal'],2)]);
+                crystal_log($this->uid,$order_detail['crystal'],'订单取消',9,$order_id);
+            }
+            //恢复库存
+            Db::table('exchange_goods')->where('id',$order_detail['goods_id'])->setInc('stock',$order_detail['goods_num']);
+            if($order_detail['cl_id']) Db::table('user_coupon_list')->where('id',$order_detail['cl_id'])->update(['status'=>1,'used_time'=>'']);
+            // 取消订单
+            Db::table('exchange_order')
+                ->where(['id'=>$order_id])
+                ->update(['cancel_state'=>1,'status'=>9]);
+            Db::commit();
+        }catch (\Exception $e){
+            Db::rollback();
+        }
+        $this->success('取消成功');
+    }
+
+    /**
+     * @title 获取订单列表
+     * @desc  获取订单列表
+     * @author  qc
+     * @url /api/Exchange_order/getMyOrderList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  : default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:status type:int default:-- desc:支付状态:0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消
+     * @return name:price_total type:float default:-- desc:订单金额(实际支付金额)
+     * @return name:freight type:float default:-- desc:运费
+     * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
+     * @return name:pay_no type:string default:-- desc:支付单号
+     * @return name:pay_time type:string default:-- desc:支付时间
+     * @return name:create_at type:string default:-- desc:订单创建时间
+     * @return name:cancel_state type:int default:-- desc:取消状态
+     * @return name:goods_id type:int default:-- desc:商品id
+     * @return name:goods_name type:string default:-- desc:商品名
+     * @return name:goods_cover type:string default:-- desc:商品图片
+     * @return name:goods_num type:int default:-- desc:商品数量
+     * @return name:express_company_title type:string default:-- desc:物流公司
+     * @return name:express_send_no type:string default:-- desc:物流单号
+     * @return name:express_send_at type:string default:-- desc:发货时间
+     * @return name:express_company_id type:string default:-- desc:物流公司id
+     */
+    public function getMyOrderList()
+    {
+        $status  = input('status',-1);
+        $where=[];
+        if($status > -1) $where['status'] = $status;
+        $where['uid'] = $this->uid;
+        $where['is_deleted'] = 0;
+        $list = Db::table('exchange_order')
+            ->where($where)
+            ->order('id desc')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('获取成功',$list);
+
+    }
+
+
+    /**
+     * @title 删除订单
+     * @desc  删除订单
+     * @author  qc
+     * @url /api/Exchange_order/delOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1  default:1 desc:订单id
+     */
+    public function delOrder()
+    {
+        $order_id = input('post.id');
+        $order_info = Db::table('exchange_order')
+            ->where(['uid'=>$this->uid,'is_deleted'=>0,'id'=>$order_id])
+            ->find();
+        if(empty($order_info)) $this->error('订单不存在');
+        Db::table('exchange_order')->where(['id'=>$order_id])->update(['is_deleted'=>1]);
+        $this->success('删除成功');
+    }
+
+    /**
+     * @title 确认收货
+     * @desc  确认收货
+     * @author  qc
+     * @url /api/Exchange_order/confirmReceipt
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1  default:1 desc:订单id
+     */
+    public function confirmReceipt(){
+        $order_info = Db::table('exchange_order')
+            ->where(['uid'=>$this->uid,'id'=>input('post.id')])
+            ->find();
+        if(empty($order_info) || $order_info['status'] != 2) $this->error('商品未发货');
+        Db::table('exchange_order')->where(['id'=>$order_info['id']])->update(['status'=>3,'receipt_at'=>date('Y-m-d H:i:s')]);
+        $this->success('收货成功');
+    }
+
+}

+ 322 - 0
application/api/controller/Expedite.php

@@ -0,0 +1,322 @@
+<?php
+
+
+namespace app\api\controller;
+use think\Db;
+/**
+ * @title 不需要验证token接口(商品详情,商品列表等)
+ * @controller Expedite
+ * @package app\api\controller
+ */
+class Expedite extends Base
+{
+
+    public function initialize(){
+        parent::initialize();
+    }
+
+    /**
+     * @title 获取商品详情(商城商品)
+     * @desc  获取商品详情(商城商品)
+     * @author  qc
+     * @url /api/Expedite/getGoodsDetail
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:goods_id  type:int require:1  default:0 desc:商品id
+     * @return name:goods_info type:array default:-- desc:商品详情
+     * @return name:goods_info.name type:string default:-- desc:商品名称
+     * @return name:goods_info.cover type:string default:-- desc:商品封面图
+     * @return name:goods_info.desc type:string default:-- desc:商品简述
+     * @return name:goods_info.goods_price type:float default:-- desc:价格
+     * @return name:goods_info.end_time type:float default:-- desc:结束时间
+     * @return name:goods_info.spec type:string default:-- desc:魔盒设置
+     * @return name:spec.award_name type:string default:-- desc:名称
+     * @return name:spec.spec_img type:string default:-- desc:封面
+     * @return name:spec.store_num type:string default:-- desc:剩余库存
+     * @return name:spec.base_num type:string default:-- desc:初始库存
+     * @return name:spec.crystal type:string default:-- desc:水晶价值
+     * @return name:spec.rate type:string default:-- desc:抽中概率
+     * @return name:goods_info.first_classify type:int default:-- desc:分类id
+     * @return name:goods_info.detail type:int default:-- desc:商品详情
+     * @return name:goods_info.stock type:float default:-- desc:剩余库存
+     * @return name:goods_info.base_stock type:float default:-- desc:初始库存
+     * @return name:goods_info.special_award type:array default:-- desc:特殊奖励设置(前后场两个奖励)
+     * @return name:goods_info.special_award.title type:string default:-- desc:标题
+     * @return name:goods_info.special_award.goods type:string default:-- desc:商品名
+     * @return name:goods_info.special_award.cover type:string default:-- desc:图片
+     * @return name:goods_info.special_award.crystal type:string default:-- desc:水晶
+     * @return name:goods_info.special_award.is_over type:string default:-- desc:奖励是否完成
+     * @return name:goods_info.special_point type:int default:-- desc:前后场分割数
+     * @return name:goods_info.before_num type:int default:-- desc:前场数
+     * @return name:goods_info.after_num type:int default:-- desc:后场数
+     *
+     */
+    public function getGoodsDetail()
+    {
+        $goods_id = input('goods_id');
+        $field = 'id,name,cover,desc,goods_price,spec,first_classify,detail,stock,base_stock,end_time,special_award,special_point';
+        $detail = Db::table('store_goods')
+            ->field($field)
+            ->where(['id'=>$goods_id,'status'=>1,'is_deleted'=>0])
+            ->find($goods_id);
+        if(empty($detail)) $this->error('商品已下架');
+        $detail['before_num'] = $detail['special_point'];
+        $detail['after_num'] =$detail['base_stock'] - $detail['special_point'];
+        $this->success('oK',['goods_info'=>$detail,]);
+    }
+
+    /**
+     * @title 获取商品列表(商城商品)
+     * @desc  获取商品列表(商城商品)
+     * @author  qc
+     * @url /api/Expedite/getGoodsList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @param  name:goods_name  type:string require:0  default:-- desc:商品名称
+     * @param  name:cate_id  type:int require:0  default:0 desc:分类id
+     * @return name:name type:string default:-- desc:商品名称
+     * @return name:cover type:string default:-- desc:商品封面图
+     * @return name:desc type:string default:-- desc:商品简述
+     * @return name:goods_price type:float default:-- desc:价格
+     * @return name:spec type:string default:-- desc:规格详情
+     * @return name:spec.award_name type:string default:-- desc:名称
+     * @return name:spec.spec_img type:string default:-- desc:封面
+     * @return name:spec.store_num type:string default:-- desc:剩余库存
+     * @return name:spec.base_num type:string default:-- desc:初始库存
+     * @return name:spec.crystal type:string default:-- desc:水晶价值
+     * @return name:first_classify type:int default:-- desc:一级分类id
+     * @return name:detail type:int default:-- desc:商品详情
+     * @return name:stock type:float default:-- desc:剩余库存
+     * @return name:base_stock type:float default:-- desc:初始库存
+     * @return name:end_time type:string default:-- desc:结束时间
+     * @return name:goods_info.special_award type:array default:-- desc:特殊奖励设置(前后场两个奖励)
+     * @return name:goods_info.special_award.title type:string default:-- desc:标题
+     * @return name:goods_info.special_award.goods type:string default:-- desc:商品名
+     * @return name:goods_info.special_award.cover type:string default:-- desc:图片
+     * @return name:goods_info.special_award.crystal type:string default:-- desc:水晶
+     * @return name:goods_info.special_award.is_over type:string default:-- desc:奖励是否完成
+     */
+    public function getGoodsList()
+    {
+        $sel_where = [];
+        $sel_where[] = ['status','=',1];
+        $sel_where[] = ['is_deleted','=',0];
+        $sel_where[] = ['end_time','> time',date("Y-m-d H:i:s")];
+        if(input('goods_name')) $sel_where[] = ['name','like',"%".input('goods_name')."%"];
+        if(input('cate_id',0)) $sel_where[] = ['first_classify','=',input('cate_id')];
+        $field = 'id,name,cover,desc,goods_price,spec,first_classify,detail,stock,base_stock,end_time,special_award';
+        $list = Db::table('store_goods')
+            ->field($field)
+            ->where($sel_where)
+            ->order('sort desc , id desc ')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('ok',['list'=>$list]);
+
+    }
+
+
+    /**
+     * @title 获取商品分类(商城商品)
+     * @desc  获取商品分类(商城商品)
+     * @author  qc
+     * @url /api/Expedite/getGoodCate
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @return name:id type:array default:-- desc:商品详情
+     * @return name:title type:string default:-- desc:分类名称
+     */
+    public function getGoodCate()
+    {
+        $list = Db::table('store_goods_cate')
+            ->where('pid',0)
+            ->where('status',1)
+            ->where('is_deleted',0)
+            ->field('id,title')
+            ->order('sort desc , id desc')
+            ->select();
+        $this->success('ok',['list'=>$list]);
+    }
+
+
+
+    /**
+     * @title 获取首页轮播图
+     * @desc  获取首页轮播图
+     * @author  qc
+     * @url /api/Expedite/getBanner
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:num type:int  default:5 desc:查询数量
+     * @return name:name type:srting default:-- desc:标题
+     * @return name:cover type:srting default:-- desc:图片路径
+     * @return name:link type:srting default:-- desc:跳转地址
+     */
+    public function getBanner()
+    {
+        $num = input('get.num',20);
+        $list =  Db::table('store_banner')
+            ->field('id,name,cover,link')
+            ->where(['is_deleted'=>0])
+            ->limit(0,$num)
+            ->order('sort desc ,id desc')
+            ->select();
+        $this->success('ok',['list'=>$list]);
+    }
+
+    /**
+     * @title 获取订单列表(商城商品)
+     * @desc  获取订单列表(商城商品)
+     * @author  qc
+     * @url /api/Expedite/getOrderListByGoodsId
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @param  name:goods_id  type:string require:1  default:-- desc:商品id
+     * @return name:create_at type:string default:-- desc:时间
+     * @return name:goods_name type:string default:-- desc:商品
+     * @return name:name type:string default:-- desc:会员名称
+     * @return name:headimg type:string default:-- desc:会员头像
+     */
+    public function getOrderListByGoodsId()
+    {
+        $goods_id = input('goods_id',0);
+        $list = Db::table('goods_order')
+            ->alias('o')
+            ->field('o.create_at,o.goods_name,m.name,m.headimg')
+            ->join('store_member m','o.uid = m.id')
+            ->where('o.goods_id',$goods_id)
+            ->where('o.pay_state',1)
+            ->order('o.id desc ')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('ok',['list'=>$list]);
+    }
+
+    /**
+     * @title 获取商品中奖详情
+     * @desc  获取商品中奖详情
+     * @author  qc
+     * @url /api/Expedite/getAwardDetailByGoodsId
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @param  name:goods_id  type:string require:1  default:-- desc:商品id
+     * @return name:create_at type:string default:-- desc:时间
+     * @return name:award_name type:string default:-- desc:奖品标题
+     * @return name:award_cover type:string default:-- desc:奖品图片
+     * @return name:name type:string default:-- desc:会员名称
+     * @return name:headimg type:string default:-- desc:会员头像
+     */
+    public function getAwardDetailByGoodsId()
+    {
+        $goods_id = input('goods_id',0);
+        $list = Db::table('magic_draw')
+            ->alias('d')
+            ->field('d.award_name,d.award_cover,d.create_at,m.name,m.headimg')
+            ->join('store_member m','d.user_id = m.id')
+            ->where('d.goods_id',$goods_id)
+            ->order('d.is_special desc,d.id desc ')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('ok',['list'=>$list]);
+    }
+
+
+
+    /**
+     * @title 获取商品详情(兑换商品)
+     * @desc   获取商品详情(兑换商品)
+     * @author  qc
+     * @url /api/Expedite/getExchangeGoodsDetail
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:goods_id  type:int require:1  default:0 desc:兑换商品id
+     * @return name:name type:string default:-- desc:商品名称
+     * @return name:cover type:string default:-- desc:商品封面图
+     * @return name:desc type:string default:-- desc:商品简述
+     * @return name:crystal type:int default:-- desc:水晶
+     * @return name:first_classify type:int default:-- desc:一级分类id
+     * @return name:detail type:int default:-- desc:商品详情
+     * @return name:stock type:float default:-- desc:剩余库存
+     */
+    public function getExchangeGoodsDetail()
+    {
+        $goods_id = input('goods_id');
+        $field = 'id,name,cover,desc,first_classify,detail,stock,crystal';
+        $detail = Db::table('exchange_goods')
+            ->field($field)
+            ->where(['id'=>$goods_id,'status'=>1,'is_deleted'=>0])
+            ->find($goods_id);
+        if(empty($detail)) $this->error('商品已下架');
+        $this->success('oK',$detail);
+    }
+
+
+    /**
+     * @title 获取商品列表(兑换商品)
+     * @desc   获取商品列表(兑换商品)
+     * @author  qc
+     * @url /api/Expedite/getExchangeGoodsList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @param  name:goods_name  type:string require:0  default:-- desc:商品名称
+     * @param  name:cate_id  type:int require:0  default:0 desc:分类id
+     * @return name:name type:string default:-- desc:商品名称
+     * @return name:cover type:string default:-- desc:商品封面图
+     * @return name:desc type:string default:-- desc:商品简述
+     * @return name:crystal type:int default:-- desc:水晶
+     * @return name:first_classify type:int default:-- desc:一级分类id
+     * @return name:detail type:int default:-- desc:商品详情
+     * @return name:stock type:float default:-- desc:剩余库存
+     */
+    public function getExchangeGoodsList()
+    {
+        $sel_where = [];
+        $sel_where[] = ['status','=',1];
+        $sel_where[] = ['is_deleted','=',0];
+        if(input('goods_name')) $sel_where[] = ['name','like',"%".input('goods_name')."%"];
+        if(input('cate_id',0)) $sel_where[] = ['first_classify','=',input('cate_id')];
+        $field = 'id,name,cover,desc,first_classify,detail,stock,crystal';
+        $list = Db::table('exchange_goods')
+            ->field($field)
+            ->where($sel_where)
+            ->order('sort desc , id desc ')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('ok',['list'=>$list]);
+    }
+
+
+    /**
+     * @title 获取平台设置
+     * @desc  获取平台设置
+     * @author  qc
+     * @url /api/Expedite/getSysConfig
+     * @method GET
+     * @return name:agreement type:string default:-- desc:用户协议
+     * @return name:purchase_notice type:string default:-- desc:购买须知
+     * @return name:platform_notice type:string default:-- desc:平台消息
+     * @return name:crystal_switch type:string default:-- desc:提现开关(1开启0关闭)
+     */
+
+    public function getSysConfig(){
+        $con_name =['agreement','purchase_notice','platform_notice','crystal_switch'];
+        $set = Db::table('system_config')->where('name','in',$con_name)->select();
+        $ret = [];
+        foreach ($set as $value) {
+            $ret[$value['name']]=$value['value'];
+        }
+        $this->success('获取成功',$ret);
+    }
+
+
+
+
+}

+ 222 - 0
application/api/controller/General.php

@@ -0,0 +1,222 @@
+<?php
+namespace app\api\controller;
+use think\Db;
+/**
+ * @title 其他接口
+ * @controller General
+ * @group base
+ */
+class General extends Base
+{
+    public function initialize()
+    {
+        parent::check_login();
+    }
+
+    /**
+     * @title 获取物流详情
+     * @desc 获取物流详情
+     * @author qc
+     * @url /api/General/deliveryDetails
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param name:send_no type:string require:1 default:-- desc:物流单号(订单express_send_no字段)
+     * @return name:number type:string default:-- desc:单号
+     * @return name:type type:string default:-- desc:快递类型
+     * @return name:list type:array default:-- desc:数据列表
+     * @return name:list.time type:string default:-- desc:时间
+     * @return name:list.status type:string default:-- desc:内容
+     * @return name:deliverystatus type:int default:-- desc:0:快递收件(揽件)1.在途中2.正在派件3.已签收4.派送失败5.疑难件6.退件签收
+     * @return name:issign type:int default:-- desc:是否签收(1.是否签收)
+     * @return name:expName type:string default:-- desc:快递公司名称
+     * @return name:expSite type:string default:-- desc:快递公司官网
+     * @return name:expPhone type:string default:-- desc:快递公司电话
+     * @return name:courier type:string default:-- desc:快递员 或 快递站(没有则为空)
+     * @return name:courierPhone type:string default:-- desc:快递员电话 (没有则为空)
+     * @return name:updateTime type:string default:-- desc:快递轨迹信息最新时间
+     * @return name:takeTime type:string default:-- desc:发货到收货消耗时长 (截止最新轨迹)
+     * @return name:logo type:string default:-- desc:快递公司LOGO
+     */
+    public function deliveryDetails(){
+        $send_no = input('get.send_no');
+        $data = get_delivery($send_no);
+        $this->success('ok',$data);
+    }
+
+    /**
+     * @title 验证会员当天是否签到
+     * @desc  验证会员当天是否签到
+     * @author qc
+     * @url /api/General/checkSign
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @return  name:is_sign type:int  default:0  desc:是否签到0未签到,1已签到
+     */
+    public function checkSign()
+    {
+        $year = date('Y');
+        $month = date('m');
+        $day = date('d');
+        $ck_sign = Db::table('user_sign')
+            ->where(['uid'=>$this->uid,'year'=>$year,'month'=>$month,'day'=>$day])
+            ->count();
+        $this->success('ok',['is_sign'=>$ck_sign]);
+    }
+
+    /**
+     * @title 获取会员连续签到天数
+     * @desc  获取会员连续签到天数
+     * @author qc
+     * @url /api/General/getContinuousSign
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @return name:is_sign type:int  default:--  desc:当天是否签到(0签到,1已签到)
+     * @return name:sign_num type:int  default:--  desc:连续签到天数
+     */
+    public function getContinuousSign()
+    {
+        $today_sign =  Db::table('user_sign')
+                ->where(['uid'=>$this->uid,'day_time'=>date('Y-m-d')])
+                ->find();
+        $is_sign = !empty($today_sign) ? 1:0;
+        $sign_num = 0;
+        $week_sign = Db::table('user_sign')
+            ->where('uid','=',$this->uid)
+            ->where('create_at','>= time',date('Y-m-d 00:00:00',strtotime('-6 days')))
+            ->where('status','=',0)
+            ->order('id desc')
+            ->select();
+        $sign_date =  array_column($week_sign,'day_time');
+        for($i=0;$i<=6;$i++) {
+            if(in_array(date('Y-m-d',strtotime("-$i days")),$sign_date)){
+                $sign_num++;
+            }else if($i>0){
+                break;
+            }
+        }
+        $this->success('ok',['sign_num'=>$sign_num,'is_sign'=>$is_sign]);
+    }
+
+    /**
+     * @title 会员签到
+     * @desc 会员签到
+     * @author qc
+     * @url /api/General/userSign
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     */
+    public function userSign()
+    {
+        $year = date('Y');
+        $month = date('m');
+        $day = date('d');
+        $ck_sign = Db::table('user_sign')
+            ->where(['uid'=>$this->uid,'year'=>$year,'month'=>$month,'day'=>$day])
+            ->count();
+        if($ck_sign) $this->error('已签到');
+        $sign_data=[
+            'uid' =>$this->uid,
+            'year' =>$year,
+            'month' =>$month,
+            'day' =>$day,
+            'day_time'=>date('Y-m-d'),
+            'create_at' => date('Y-m-d H:i:s'),
+            'desc' => '每日签到',
+        ];
+        Db::table('user_sign')->insert($sign_data);// 签到日志
+        // 连续签到7天送券
+        $week_sign = Db::table('user_sign')
+            ->where('uid','=',$this->uid)
+            ->where('create_at','>= time',date('Y-m-d 00:00:00',strtotime('-6 days')))
+            ->where('status','=',0)
+            ->order('id desc')
+            ->count();
+
+        if($week_sign == 7) {
+            Db::table('user_sign')
+                ->where('uid','=',$this->uid)
+                ->where('create_at','>= time',date('Y-m-d 00:00:00',strtotime('-6 days')))
+                ->where('status','=',0)
+                ->update(['status'=>1]);
+            // 送券
+            $ticket_day = intval(sysconf('ticket_days'));// 获取设置天数
+            if($ticket_day > 0) {
+                $coupon_data=[
+                    'user_id'  => $this->uid,
+                    'low_day'  => $ticket_day ,
+                    'create_at'=> date('Y-m-d H:i:s'),
+                    'past_at'  => date('Y-m-d H:i:s',strtotime("+$ticket_day days"))
+                ];
+                Db::table('user_coupon_list')->insert($coupon_data);
+            }
+        }
+        $this->success('签到成功');
+    }
+
+
+    /**
+     * @title 会员签到列表
+     * @desc  会员签到列表
+     * @author  qc
+     * @url /api/General/getSignList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @return name:create_at type:string default:-- desc:时间
+     * @return name:desc type:string default:-- desc:描述
+     */
+    public function getSignList()
+    {
+        $list = Db::table('user_sign')
+            ->field('id,create_at,desc')
+            ->where('uid','=',$this->uid)
+            ->order('id desc')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('ok',['list'=>$list]);
+    }
+
+    /**
+     * @title 获取运费
+     * @desc  获取运费
+     * @author  qc
+     * @url /api/General/getFreight
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param name:num type:int require:1 default:1 desc:商品数量
+     * @return name:all_freight type:int  default:--  desc:总运费
+     * @return name:first_freight type:int  default:--  desc:首件运费
+     * @return name:later_freight type:int  default:--  desc:续件运费
+     */
+    public function getFreight()
+    {
+        $freight_data = get_freight(input('num',1));
+        $this->success('ok',$freight_data);
+    }
+
+    /**
+     * @title 获取消息
+     * @desc  获取消息
+     * @author  qc
+     * @url /api/General/getUserMessage
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @return name:create_at type:string default:-- desc:时间
+     * @return name:content type:string default:-- desc:内容
+     * @return name:type_id type:int default:-- desc:类型(1中奖消息2平台消息)
+     */
+    public function getUserMessage()
+    {
+        $list = Db::table('user_message')
+            ->where('user_id',$this->uid)
+            ->limit($this->off_set,$this->page_num)
+            ->order('id desc')
+            ->select();
+        $this->success('ok',['list'=>$list]);
+    }
+
+
+}

+ 827 - 0
application/api/controller/GoodsOrder.php

@@ -0,0 +1,827 @@
+<?php
+namespace app\api\controller;
+use think\Db;
+use EasyWeChat\Factory;
+use think\Session;
+
+/**
+ * @title 抽奖商品订单
+ * @controller GoodsOrder
+ * @group base
+ */
+class GoodsOrder extends Base
+{
+    public function initialize()
+    {
+        parent::initialize();
+        parent::check_login();
+    }
+
+
+    /**
+     * @title 生成订单(立即购买 )
+     * @desc  生成订单(立即购买 )
+     * @author  qc
+     * @url /api/Goods_order/createOrderByImmediately
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:goods_id type:int require:1 default:-- desc:商品id
+     * @param name:num type:int require:1 default:1 desc:商品数量
+     * @param name:price_total type:float require:1 default:-- desc:支付金额
+     * @param name:price_total type:float require:1 default:-- desc:支付金额
+     * @return  name:order_id type:int require:0 default:0 desc:成功时返回订单id
+     */
+    public function createOrderByImmediately()
+    {
+        $goods_id               =  input("post.goods_id");
+        $price_total            =  input("post.price_total",0);
+        $num                    =  input("post.num",1);
+        $goods_info = Db::table('store_goods')->field('id,name,cover,spec,stock,goods_price,end_time')
+            ->where(['id'=>$goods_id,'status'=>1,'is_deleted'=>0])
+            ->find();
+        if(empty($goods_info))  $this->error('商品已下架');
+        if(!$goods_info['end_time'] || strtotime($goods_info['end_time']) <  time())  $this->error('商品售卖时间已结束');
+        if($goods_info['stock'] < $num) $this->error('商品库存不足');
+        $price_total = bcmul($goods_info['goods_price'],$num,2);
+        $order_int =[
+            'uid'=>$this->uid,
+            'order_no'      => get_order_sn(),
+            'price_total'   => $price_total,
+            'goods_num'     => $num,
+            'goods_id'      => $goods_id,
+            'goods_cover'   =>$goods_info['cover'],
+            'goods_name'    =>$goods_info['name'],
+            'create_at'     =>date('Y-m-d H:i:s'),
+        ];
+        Db::startTrans();
+        $msg= '';$com=true;
+        try{
+            //扣减库存
+            Db::table('store_goods')->where('id',$goods_id)->setDec('stock',$num);
+            // 生成订单
+            Db::table('goods_order')->insert($order_int);
+            $order_id = Db::getLastInsID();
+            $stock = Db::table('store_goods')->where('id',$goods_id)->value('stock');
+            if($stock < 0 ) {
+                Db::rollback();
+                $com = false;
+                $msg = '库存不足';
+            }else{
+                Db::commit();
+            }
+        }catch (\Exception $e){
+            Db::rollback();
+            $com=false;
+            $msg = $e->getMessage();
+        }
+        if($com){
+            $this->success('ok',['order_id'=>$order_id]);
+        }else{
+            $this->error($msg);
+        }
+    }
+
+    /**
+     * @title 获取订单详情
+     * @desc  获取订单详情
+     * @author  qc
+     * @url /api/Goods_order/getOrderDetail
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int require:1 default:-- desc:订单id
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:status type:int default:-- desc:支付状态:0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消
+     * @return name:price_total type:float default:-- desc:订单金额
+     * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
+     * @return name:pay_no type:string default:-- desc:支付单号
+     * @return name:create_at type:string default:-- desc:订单创建时间
+     * @return name:pay_type type:string default:-- desc:支付方式(0未支付,1微信,2余额)
+     * @return name:pay_time type:string default:-- desc:支付时间
+     * @return name:cancel_state type:int default:-- desc:取消状态
+     * @return name:goods_id type:int default:-- desc:商品id
+     * @return name:goods_num type:int default:-- desc:商品数量
+     * @return name:goods_cover type:int default:-- desc:商品封面
+     */
+    public function getOrderDetail()
+    {
+        $order_id = input('id',0);
+        $detail = Db::table('goods_order')->find($order_id);
+        $this->success('获取成功',$detail);
+
+    }
+
+    /**
+     * @title 去支付
+     * @desc  去支付
+     * @author  qc
+     * @url /api/Goods_order/payOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:o_id type:int require:1 default:-- desc:订单id
+     * @param name:pay_type type:int require:1 default:-- desc:支付方式(1微信,2余额)
+     * @return name:pay_type type:int default:0 desc:支付方式(1调支付,2余额支付)
+     * @return name:config type:array default:0 desc:支付配置(pay_type=2时忽略)
+     * @return name:config.appId type:string default:-- desc:公众账号ID
+     * @return name:config.nonceStr type:string default:-- desc:随机字符串
+     * @return name:config.signType type:string default:-- desc:签名类型
+     * @return name:config.paySign type:string default:-- desc:签名
+     * @return name:config.timestamp type:string default:-- desc:时间戳
+     */
+    public function payOrder()
+    {
+        $o_id = input('post.o_id');
+        $pay_type = input('post.pay_type');
+        $user_info = Db::table('store_member')->where('id',$this->uid)->find();
+        if(!$user_info['openid']) $this->error('请先完善用户信息');
+        $order_info =     Db::table('goods_order')->where(['uid'=>$this->uid,'id'=>$o_id])->find();
+        if(empty($order_info)) $this->error('订单不存在');
+        if($order_info['cancel_state'] != 0) $this->error('订单已取消');
+        if($order_info['status'] != 0) $this->error('订单已支付');
+        if($order_info['price_total'] <= 0) $this->error('订单金额错误');
+        $goods_info = Db::table('store_goods')->find($order_info['goods_id']);
+        $goods_spec = json_decode($goods_info['spec'],true);
+        $config = false;$msg= '';
+        switch ($pay_type)
+        {
+            case 1: //  微信支付
+                $notify_url = $this->request->root(true) . '/api/Pay/goodsOrderNotify';
+                $pay_no = $order_info['pay_no'] ?  $order_info['pay_no'] : get_order_sn();
+                Db::startTrans();
+                try{
+                    // 更新订单
+                    Db::table('goods_order')->where(['uid'=>$this->uid,'id'=>$o_id])->update(['pay_no'=>$pay_no]);
+                    $config = Pay::wxPay('订单支付',$pay_no,$order_info['price_total'],$notify_url,'JSAPI',$user_info['openid']);
+                    if($config){
+                        Db::commit();
+                    }else{
+                        Db::rollback();
+                    }
+                }catch (\Exception $e){
+                    Db::rollback();
+                    $msg = $e->getMessage();
+                }
+                if($config){
+                    $this->success('ok',['pay_type'=>1,'config'=>$config]);
+                }else{
+                    $this->error($msg);
+                }
+                break;
+            case 2: // 余额支付
+                // 验证余额
+                if(bcadd($user_info['crystal'],$user_info['crystal_cash'],2) < $order_info['price_total'])$this->error('水晶余额不足!');
+                // 抽奖
+                $draw_data = draw_lottery($goods_spec,'store_num',$order_info['goods_num']);
+                $magic_data = [];
+                $magic_day = intval(sysconf('magic_days'));// 获取设置天数
+                // 扣减商品库存数组 && 魔玩柜数据
+                foreach ($draw_data as $dk=>$dv) {
+                    $goods_spec[$dk]['store_num'] -= $dv;
+                    $magic_data[] = [
+                        'order_id'  => $o_id,
+                        'goods_id'  => $goods_info['id'],
+                        'user_id'   => $this->uid,
+                        'create_at' => date('Y-m-d H:i:s'),
+                        'case_name' => $goods_spec[$dk]['award_name'],
+                        'case_cover'=> $goods_spec[$dk]['spec_img'],
+                        'num'       => $dv,
+                        'base_num'  => $dv,
+                        'crystal'   => $goods_spec[$dk]['crystal'],
+                        'past_at'   =>  date('Y-m-d H:i:s',strtotime("+$magic_day days")),
+                        'past_int'   => strtotime("+$magic_day days"),
+                    ];
+                }
+
+                $magic_draw = [];// 待抽将数据
+                foreach ($magic_data as $mv)
+                {
+                    for ($i=0;$i< $mv['base_num'];$i++ ) {
+                        $magic_draw[]=[
+                            'order_id' => $order_info['id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' => $order_info['uid'],
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'status' => 0,
+                            'award_status' => 1,
+                            'award_name' => $mv['case_name'],
+                            'award_cover' => $mv['case_cover'],
+                        ];
+                    }
+                }
+
+                Db::startTrans();
+                try{
+                    // 更新库存
+                    Db::table('store_goods')->where('id',$goods_info['id'])->update(['spec'=>json_encode($goods_spec)]);
+                    // 魔玩柜
+                    Db::table('magic_case')->insertAll($magic_data);
+                    // 抽奖数据
+                    Db::table('magic_draw')->insertAll($magic_draw);
+                    // 扣除余额
+                    $user_up = [];
+                    if($user_info['crystal'] >= $order_info['price_total'] ) {
+                        $user_up['crystal'] = bcsub($user_info['crystal'],$order_info['price_total'],2);
+                    }else{
+                        $user_up['crystal'] = 0;
+                        $user_up['crystal_cash'] = bcsub( $user_info['crystal_cash'] + $user_info['crystal'],$order_info['price_total'],2);
+                    }
+                    Db::table('store_member')->where(['id'=>$this->uid])->update($user_up);
+                    // 水晶变更记录
+                    crystal_log($this->uid,$order_info['price_total'],'余额支付',6);
+                    // 更新订单状态
+                    $pay_no = $order_info['pay_no'] ?  $order_info['pay_no'] : get_order_sn();
+                    Db::table('goods_order')->where(['uid'=>$this->uid,'id'=>$o_id])
+                        ->update(['pay_time'=>date('Y-m-d H:i:s'),'pay_type'=>2,'pay_state'=>1,'status'=>1,'pay_no'=>$pay_no]);
+
+                    // 特殊奖励
+                    $special_award = json_decode($goods_info['special_award'],true);
+                    $special_point = $goods_info['special_point'];
+                    $front_court  = $special_award[0];// 前场设置
+                    $back_court  = $special_award[1]; // 后场设置
+                    $is_draw = 0;
+                    // 前场未抽奖
+                    if($front_court['is_over'] == 0) {
+                        $front_magic = Db::table('magic_draw')
+                            ->field('id,user_id,order_id')
+                            ->where(['goods_id'=>$goods_info['id'],'status'=>0,'is_special'=>0])
+                            ->limit(0,$special_point)
+                            ->order('id asc')
+                            ->select();
+                        // 前场抽奖次数达到前场抽奖节点
+                        if(count($front_magic) ==  $special_point) {
+                            $is_draw = 1;
+                            $special_award[0]['is_over'] = 1;// 前场抽奖完成标识
+                            $rand_id = array_rand($front_magic,1);// 中奖记录ids
+                            $front_user = $front_magic[$rand_id]['user_id']; // 中奖会员id
+                            $last_id = $front_magic[count($front_magic)-1]['id'];
+                            // 中奖记录插入魔玩柜
+                            $front_case = [
+                                'order_id' => $front_magic[$rand_id]['order_id'],
+                                'goods_id' => $goods_info['id'],
+                                'user_id' => $front_user,
+                                'create_at' => date('Y-m-d H:i:s'),
+                                'num' => 1,
+                                'base_num' => 1,
+                                'source'    => 1,
+                                'crystal' => $front_court['crystal'],
+                                'case_name' => $front_court['goods'],
+                                'case_cover' =>$front_court['cover'],
+                                'past_at'   =>  date('Y-m-d H:i:s',strtotime("+$magic_day days")),
+                                'past_int'   => strtotime("+$magic_day days"),
+                            ];
+                            Db::table('magic_case')->insert($front_case);
+
+                            $special_award1 = [
+                                'order_id' => $order_info['id'],
+                                'goods_id' => $goods_info['id'],
+                                'user_id' =>  $front_user,
+                                'create_at' => date('Y-m-d H:i:s'),
+                                'status' => 1,
+                                'award_status' => 0,
+                                'award_name' => $front_court['goods'],
+                                'award_cover' =>$front_court['cover'],
+                                'is_special' => 1
+                            ];
+
+                            Db::table('magic_draw')->insert($special_award1);
+                            // 更新抽奖记录
+                            Db::table('magic_draw')
+                                ->where('goods_id','=',$goods_info['id'])->where('id','<=', $last_id)
+                                ->where('id','<>',$front_magic[$rand_id]['id'])
+                                ->where('status','=',0)
+                                ->where('is_special','=',0)
+                                ->update(['status'=>1]);
+                            Db::table('magic_draw')
+                                ->where('id','=', $front_magic[$rand_id]['id'])
+                                ->where('status','=',0)
+                                ->where('is_special','=',0)
+                                ->update(['status'=>1,'award_status'=>2]);
+                            // 生成消息记录
+                            send_user_message($front_user,1,'恭喜您被大奖砸中!获得商品:'.$front_court['goods']);
+                        }
+                    }
+                    // 后场未抽奖 && 商品售罄
+                    if( $special_award[0]['is_over'] ==1 && $back_court['is_over'] == 0 && $goods_info['stock'] == 0){
+                        $back_num = $goods_info['base_stock'] - $special_point;
+                        $back_magic = Db::table('magic_draw')
+                            ->field('id,user_id,order_id')
+                            ->where(['goods_id'=>$goods_info['id'],'status'=>0,'is_special'=>0])
+                            ->limit(0,$back_num)
+                            ->order('id asc')
+                            ->select();
+                        if($back_num == count($back_magic)) {
+                            $is_draw = 1;
+                            $special_award[1]['is_over'] = 1;// 后场抽奖完成标识
+                            $rand_id = array_rand($back_magic,1);// 中奖记录id
+                            $back_user = $back_magic[$rand_id]['user_id']; // 中奖会员id
+                            $back_case = [
+                                'order_id' => $back_magic[$rand_id]['order_id'],
+                                'goods_id' => $goods_info['id'],
+                                'user_id' => $back_user,
+                                'create_at' => date('Y-m-d H:i:s'),
+                                'num' => 1,
+                                'base_num' => 1,
+                                'source'    => 2,
+                                'crystal' => $back_court['crystal'],
+                                'case_name' => $back_court['goods'],
+                                'case_cover' =>$back_court['cover'],
+                                'past_at'   =>  date('Y-m-d H:i:s',strtotime("+$magic_day days")),
+                                'past_int'   => strtotime("+$magic_day days"),
+                            ];
+                            Db::table('magic_case')->insert($back_case);
+
+                            $special_award2 = [
+                                'order_id' => $order_info['id'],
+                                'goods_id' => $goods_info['id'],
+                                'user_id' => $back_user,
+                                'create_at' => date('Y-m-d H:i:s'),
+                                'status' => 1,
+                                'award_status' => 0,
+                                'award_name' => $back_court['goods'],
+                                'award_cover' =>$back_court['cover'],
+                                'is_special' => 1
+                            ];
+                            Db::table('magic_draw')->insert($special_award2);
+
+                            // 更新抽奖记录
+                            Db::table('magic_draw')
+                                ->where('goods_id','=',$goods_info['id'])->where('status','=', 0)
+                                ->where('id','<>',$back_magic[$rand_id]['id'])
+                                ->where('is_special','=',0)
+                                ->update(['status'=>1]);
+                            Db::table('magic_draw')->where('id','=', $back_magic[$rand_id]['id'])
+                                ->where('is_special','=',0)
+                                ->update(['status'=>1,'award_status'=>3]);
+                            // 生成消息记录
+                            send_user_message($back_user,1,'恭喜您被大奖砸中!!获得商品:'.$back_court['goods']);
+                        }
+                    }
+                    // 更新商品抽奖详情
+                    if($is_draw) Db::table('store_goods')->where('id',$goods_info['id'])->update(['special_award'=>json_encode($special_award)]);
+
+                    Db::commit();
+                    $config = true;
+                }catch (\Exception $e){
+                    Db::rollback();
+                    $msg = $e->getMessage();
+                }
+                if($config) {
+                    $this->success('ok',['pay_type'=>2,'config'=>'']);
+                }else{
+                    $this->error($msg);
+                }
+                break;
+        }
+
+    }
+
+
+
+    /**
+     * @title 立即购买
+     * @desc  立即购买
+     * @author  qc
+     * @url /api/Goods_order/payOrderImmediately
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:goods_id type:int require:1 default:-- desc:商品id
+     * @param name:num type:int require:1 default:1 desc:商品数量
+     * @return  name:order_id type:int require:0 default:0 desc:成功时返回订单id
+     */
+    public function payOrderImmediately()
+    {
+        $goods_id               =  input("post.goods_id");
+        $num                    =  input("post.num",1);
+        $goods_info = Db::table('store_goods')->where(['id'=>$goods_id,'status'=>1,'is_deleted'=>0])
+            ->find();
+        $price_total = bcmul($goods_info['goods_price'],$num,2);
+        if(empty($goods_info))  $this->error('商品已下架');
+        if(!$goods_info['end_time'] || strtotime($goods_info['end_time']) <  time())  $this->error('商品售卖时间已结束');
+        if($goods_info['stock'] < $num) $this->error('商品库存不足');
+        $user_info = Db::table('store_member')->find($this->uid);
+        if($price_total <= 0) $this->error('金额有误');
+        if(bcadd($user_info['crystal'],$user_info['crystal_cash'],2) < $price_total)$this->error('水晶余额不足!');
+        $order_info =[
+            'uid'=>$this->uid,
+            'order_no'      => get_order_sn(),
+            'price_total'   => $price_total,
+            'goods_num'     => $num,
+            'goods_id'      => $goods_id,
+            'goods_cover'   =>$goods_info['cover'],
+            'goods_name'    =>$goods_info['name'],
+            'create_at'     =>date('Y-m-d H:i:s'),
+        ];
+        Db::startTrans();
+        $msg= '';$com=true;
+        try{
+            //扣减库存(先扣库存在抽奖)
+            Db::table('store_goods')->where('id',$goods_id)->setDec('stock',$num);
+            // 生成订单
+            Db::table('goods_order')->insert($order_info);
+            $order_id = Db::getLastInsID();
+            $order_info['id'] = $order_id;
+            $goods_info = Db::table('store_goods')->where('id',$goods_id)->find();
+            // 重新验证库存
+            if($goods_info['stock'] < 0 ) {
+                Db::rollback();
+                $com = false;
+                $msg = '库存不足';
+            }else{
+                // 抽奖设置
+                $goods_spec = json_decode($goods_info['spec'],true);
+                $is_clip = 0;
+                $st_num  = bcmul($goods_info['base_stock'],0.7);// 1000
+                $end_num = bcmul($goods_info['base_stock'],0.2);
+                if($goods_info['base_stock'] > 30) {
+                    if( $goods_info['stock'] < $st_num && $goods_info['stock'] > $end_num) {
+                        $is_clip = 1;
+                    }
+                }
+
+                // 抽奖
+                if($goods_info['base_stock'] > 80 || $goods_id <= 7) {
+                    $draw_data = draw_lottery($goods_spec,'store_num',$order_info['goods_num'],$is_clip);
+                }else{
+                    $draw_data = point_lottery($goods_spec,'store_num',$order_info['goods_num'],$goods_info['base_stock'] - $goods_info['stock']);
+                }
+                /*if($this->uid == 1 && $goods_id == 2) {
+                    $draw_data = cdraw_lottery($goods_spec,$draw_data,$this->uid,2);
+                }*/
+                $magic_data = [];
+                $magic_day = intval(sysconf('magic_days'));// 获取设置天数
+                // 扣减商品库存数组 && 魔玩柜数据
+                foreach ($draw_data as $dk=>$dv) {
+                    $goods_spec[$dk]['store_num'] -= $dv;
+                    $magic_data[] = [
+                        'order_id'  => $order_id,
+                        'goods_id'  => $goods_info['id'],
+                        'user_id'   => $this->uid,
+                        'create_at' => date('Y-m-d H:i:s'),
+                        'case_name' => $goods_spec[$dk]['award_name'],
+                        'case_cover'=> $goods_spec[$dk]['spec_img'],
+                        'num'       => $dv,
+                        'base_num'  => $dv,
+                        'crystal'   => $goods_spec[$dk]['crystal'],
+                        'past_at'   =>  date('Y-m-d H:i:s',strtotime("+$magic_day days")),
+                        'past_int'   => strtotime("+$magic_day days"),
+                    ];
+                }
+                $magic_draw = [];// 待抽将数据
+                foreach ($magic_data as $mv)
+                {
+                    for ($i=0;$i< $mv['base_num'];$i++ ) {
+                        $magic_draw[]=[
+                            'order_id' => $order_info['id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' => $order_info['uid'],
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'status' => 0,
+                            'award_status' => 1,
+                            'award_name' => $mv['case_name'],
+                            'award_cover' => $mv['case_cover'],
+                        ];
+                    }
+                }
+                // 更新库存 && 规格详情
+                Db::table('store_goods')->where('id',$goods_info['id'])->update(['spec'=>json_encode($goods_spec)]);
+                // 魔玩柜
+                Db::table('magic_case')->insertAll($magic_data);
+                // 抽奖数据
+                Db::table('magic_draw')->insertAll($magic_draw);
+                // 扣除余额
+                $user_up = [];
+                if($user_info['crystal'] >= $order_info['price_total'] ) {
+                    $user_up['crystal'] = bcsub($user_info['crystal'],$order_info['price_total'],2);
+                }else{
+                    $user_up['crystal'] = 0;
+                    $user_up['crystal_cash'] = bcsub( $user_info['crystal_cash'] + $user_info['crystal'],$order_info['price_total'],2);
+                }
+                Db::table('store_member')->where(['id'=>$this->uid])->update($user_up);
+                // 水晶变更记录
+                crystal_log($this->uid,$order_info['price_total'],'余额支付',6);
+                // 更新订单状态
+                $pay_no = get_order_sn();
+                Db::table('goods_order')->where(['uid'=>$this->uid,'id'=>$order_id])
+                    ->update(['pay_time'=>date('Y-m-d H:i:s'),'pay_type'=>2,'pay_state'=>1,'status'=>1,'pay_no'=>$pay_no]);
+                // 特殊奖励
+                $special_award = json_decode($goods_info['special_award'],true);
+                $special_point = $goods_info['special_point'];
+                $front_court  = $special_award[0];// 前场设置
+                $back_court  = $special_award[1]; // 后场设置
+                $is_draw = 0;
+                // 前场未抽奖
+                if($front_court['is_over'] == 0) {
+                    $front_magic = Db::table('magic_draw')
+                        ->field('id,user_id,order_id')
+                        ->where(['goods_id'=>$goods_info['id'],'status'=>0,'is_special'=>0])
+                        ->limit(0,$special_point)
+                        ->order('id asc')
+                        ->select();
+                    // 前场抽奖次数达到前场抽奖节点
+                    if(count($front_magic) ==  $special_point) {
+                        $is_draw = 1;
+                        $special_award[0]['is_over'] = 1;// 前场抽奖完成标识
+                        $rand_id = array_rand($front_magic,1);// 中奖记录ids
+                        $front_user = $front_magic[$rand_id]['user_id']; // 中奖会员id
+                        $last_id = $front_magic[count($front_magic)-1]['id'];
+                        // 中奖记录插入魔玩柜
+                        $front_case = [
+                            'order_id' => $front_magic[$rand_id]['order_id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' => $front_user,
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'num' => 1,
+                            'base_num' => 1,
+                            'source'    => 1,
+                            'crystal' => $front_court['crystal'],
+                            'case_name' => $front_court['goods'],
+                            'case_cover' =>$front_court['cover'],
+                            'past_at'   =>  date('Y-m-d H:i:s',strtotime("+$magic_day days")),
+                            'past_int'   => strtotime("+$magic_day days"),
+                        ];
+                        Db::table('magic_case')->insert($front_case);
+
+                        $special_award1 = [
+                            'order_id' => $order_info['id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' =>  $front_user,
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'status' => 1,
+                            'award_status' => 0,
+                            'award_name' => $front_court['goods'],
+                            'award_cover' =>$front_court['cover'],
+                            'is_special' => 1
+                        ];
+
+                        Db::table('magic_draw')->insert($special_award1);
+                        // 更新抽奖记录
+                        Db::table('magic_draw')
+                            ->where('goods_id','=',$goods_info['id'])->where('id','<=', $last_id)
+                            ->where('id','<>',$front_magic[$rand_id]['id'])
+                            ->where('status','=',0)
+                            ->where('is_special','=',0)
+                            ->update(['status'=>1]);
+                        Db::table('magic_draw')
+                            ->where('id','=', $front_magic[$rand_id]['id'])
+                            ->where('status','=',0)
+                            ->where('is_special','=',0)
+                            ->update(['status'=>1,'award_status'=>2]);
+                        // 生成消息记录
+                        send_user_message($front_user,1,'恭喜您被大奖砸中!获得商品:'.$front_court['goods']);
+                    }
+                }
+                // 后场未抽奖 && 商品售罄
+                if( $special_award[0]['is_over'] ==1 && $back_court['is_over'] == 0 && $goods_info['stock'] == 0){
+                    $back_num = $goods_info['base_stock'] - $special_point;
+                    $back_magic = Db::table('magic_draw')
+                        ->field('id,user_id,order_id')
+                        ->where(['goods_id'=>$goods_info['id'],'status'=>0,'is_special'=>0])
+                        ->limit(0,$back_num)
+                        ->order('id asc')
+                        ->select();
+                    if($back_num == count($back_magic)) {
+                        $is_draw = 1;
+                        $special_award[1]['is_over'] = 1;// 后场抽奖完成标识
+                        $rand_id = array_rand($back_magic,1);// 中奖记录id
+                        $back_user = $back_magic[$rand_id]['user_id']; // 中奖会员id
+                        $back_case = [
+                            'order_id' => $back_magic[$rand_id]['order_id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' => $back_user,
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'num' => 1,
+                            'base_num' => 1,
+                            'source'    => 2,
+                            'crystal' => $back_court['crystal'],
+                            'case_name' => $back_court['goods'],
+                            'case_cover' =>$back_court['cover'],
+                            'past_at'   =>  date('Y-m-d H:i:s',strtotime("+$magic_day days")),
+                            'past_int'   => strtotime("+$magic_day days"),
+                        ];
+                        Db::table('magic_case')->insert($back_case);
+
+                        $special_award2 = [
+                            'order_id' => $order_info['id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' => $back_user,
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'status' => 1,
+                            'award_status' => 0,
+                            'award_name' => $back_court['goods'],
+                            'award_cover' =>$back_court['cover'],
+                            'is_special' => 1
+                        ];
+                        Db::table('magic_draw')->insert($special_award2);
+
+                        // 更新抽奖记录
+                        Db::table('magic_draw')
+                            ->where('goods_id','=',$goods_info['id'])->where('status','=', 0)
+                            ->where('id','<>',$back_magic[$rand_id]['id'])
+                            ->where('is_special','=',0)
+                            ->update(['status'=>1]);
+                        Db::table('magic_draw')->where('id','=', $back_magic[$rand_id]['id'])
+
+
+                            ->where('is_special','=',0)
+                            ->update(['status'=>1,'award_status'=>3]);
+                        // 生成消息记录
+                        send_user_message($back_user,1,'恭喜您被大奖砸中!!获得商品:'.$back_court['goods']);
+                    }
+                }
+                // 更新商品抽奖详情
+                if($is_draw) Db::table('store_goods')->where('id',$goods_info['id'])->update(['special_award'=>json_encode($special_award)]);
+                Db::commit();
+            }
+        }catch (\Exception $e){
+            Db::rollback();
+            $com=false;
+            $msg = $e->getMessage();
+        }
+        if($com) {
+            $this->success('ok',['order_id'=>$order_id]);
+        }else{
+            $this->error($msg);
+        }
+
+    }
+
+
+
+
+    /**
+     * @title 获取订单魔玩柜(抽奖详情)
+     * @desc  获取订单列表
+     * @author  qc
+     * @url /api/Goods_order/getMagicCaseByOrderId
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param name:order_id type:int require:1 default:-- desc:订单id
+     * @return name:num type:int default:0 desc:数据总条数
+     * @return name:list type:array default:-- desc:数据列表
+     * @return name:list.order_id type:int default:0 desc:关联的订单id
+     * @return name:list.create_at type:string default:0 desc:抽中时间
+     * @return name:list.case_name type:string default:0 desc:名称
+     * @return name:list.case_cover type:string default:0 desc:封面
+     * @return name:list.num type:string default:0 desc:数量
+     * @return name:list.crystal type:float default:0.00 desc:每个水晶价值
+     */
+    public function getMagicCaseByOrderId()
+    {
+        $order_id = input('order_id');
+        $list = Db::table('magic_case')
+            ->field('id,order_id,create_at,case_name,case_cover,num,crystal')
+            ->where(['order_id'=>$order_id,'user_id'=>$this->uid,'source'=>0])->select();
+        $this->success('ok',['list'=>$list,'num'=>empty($list) ? 0: count($list)]);
+    }
+
+
+    /**
+     * @title 取消订单
+     * @desc  取消订单
+     * @author  qc
+     * @url /api/Goods_order/cancelOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:id type:int require:1 default:-- desc:订单id
+     */
+    public function cancelOrder()
+    {
+        $order_id = input('post.id');
+        $order_detail = Db::table('goods_order')->where(['id'=>$order_id,'uid'=>$this->uid])->find();
+        if(empty($order_detail)) $this->error('订单不存在');
+        if($order_detail['pay_state'] != 0)      $this->error('订单已支付');
+        if($order_detail['cancel_state'] != 0)   $this->error('订单已取消,不能重复取消');
+        Db::startTrans();
+        try {
+            //恢复库存
+            Db::table('store_goods')->where('id',$order_detail['goods_id'])->setInc('stock',$order_detail['goods_num']);
+             // 取消订单
+            Db::table('goods_order')
+                ->where(['id'=>$order_id])
+                ->update(['cancel_state'=>1,'status'=>9]);
+            Db::commit();
+        }catch (\Exception $e){
+            Db::rollback();
+        }
+        $this->success('取消成功');
+    }
+
+    /**
+     * @title 获取订单列表
+     * @desc  获取订单列表
+     * @author  qc
+     * @url /api/Goods_order/getMyOrderList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  : default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @param  name:status type:int  : default:-1 desc:订单状态(-1全部,0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消)
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:status type:int default:-- desc:支付状态:0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消
+     * @return name:price_total type:float default:-- desc:订单金额
+     * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
+     * @return name:pay_no type:string default:-- desc:支付单号
+     * @return name:create_at type:string default:-- desc:订单创建时间
+     * @return name:pay_type type:string default:-- desc:支付方式(0未支付,1微信,2余额)
+     * @return name:pay_time type:string default:-- desc:支付时间
+     * @return name:cancel_state type:int default:-- desc:取消状态
+     * @return name:goods_id type:int default:-- desc:商品id
+     * @return name:goods_num type:int default:-- desc:商品数量
+     * @return name:goods_cover type:int default:-- desc:商品封面
+     */
+    public function getMyOrderList()
+    {
+        $status  = input('status',-1);
+        $where=[];
+        if($status > -1) $where['o.status'] = $status;
+        $where['o.uid'] = $this->uid;
+        $where['o.is_deleted'] = 0;
+        $list = Db::table('goods_order o')
+            ->field('o.id,o.order_no,o.pay_state,o.create_at,pay_time,o.price_total,o.status,pay_type,goods_id,goods_num,goods_cover')
+            ->where($where)
+            ->order('o.id desc')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('获取成功',$list);
+
+    }
+
+
+    /**
+     * @title 获取订单列表
+     * @desc  获取订单列表
+     * @author  qc
+     * @url /api/Goods_order/getOrderList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  : default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @param  name:status type:int  : default:-1 desc:订单状态(-1全部,0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消)
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:status type:int default:-- desc:支付状态:0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消
+     * @return name:price_total type:float default:-- desc:订单金额
+     * @return name:freight type:float default:-- desc:运费
+     * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
+     * @return name:pay_no type:string default:-- desc:支付单号
+     * @return name:create_at type:string default:-- desc:订单创建时间
+     * @return name:pay_type type:string default:-- desc:支付方式(0未支付,1微信,2余额)
+     * @return name:pay_time type:string default:-- desc:支付时间
+     * @return name:cancel_state type:int default:-- desc:取消状态
+     * @return name:goods_id type:int default:-- desc:商品id
+     * @return name:goods_num type:int default:-- desc:商品数量
+     * @return name:goods_cover type:int default:-- desc:商品封面
+     * @return name:goods_num type:int default:-- desc:商品数量
+     * @return name:express_company_title type:string default:-- desc:物流公司
+     * @return name:express_send_no type:string default:-- desc:物流单号
+     * @return name:express_send_at type:string default:-- desc:发货时间
+     * @return name:express_company_id type:string default:-- desc:物流公司id
+     * @return name:draw_time type:string default:-- desc:抽中时间
+     * @return name:table_type type:int default:-- desc:1兑换订单2魔玩柜订单
+     *
+     */
+    public function getOrderList()
+    {
+        $status  = input('status',-1);
+        $uid = $this->uid;
+        $field = 'id,uid,order_no,price_total,create_at,pro_info,pay_time,pay_no,pay_state,status,table_type,freight,express_company_title,express_send_no,express_send_at,express_company_id';
+        $where = $status == -1 ?  'uid = '.$uid.' AND is_deleted = 0':'status = '.$status.' AND uid = '.$uid.' AND is_deleted = 0';
+        $sql = "select * from (select {$field} FROM magic_order WHERE {$where} union all select {$field} FROM exchange_order WHERE {$where}) as tab order by tab.create_at desc, tab.id desc "." LIMIT $this->off_set,$this->page_num";
+        $res = Db::query($sql);
+        if($res){
+            foreach ($res as &$value){
+                $value['pro_info'] = json_decode($value['pro_info'],true);
+                if($value['table_type'] == 1){    //兑换订单
+                    $order_info = Db::name('exchange_order')->field('cl_id,goods_id,goods_name,goods_cover,freight,crystal')->where('id',$value['id'])->find();
+                    foreach ($order_info as $ok=>$ov) {
+                        $value[$ok]=$ov;
+                    }
+                }else{
+                    // 魔玩柜订单
+                    $order_info = Db::name('magic_order')->field('pay_type,coupon_id')->where('id',$value['id'])->find();
+                    $value['pay_type'] = $order_info['pay_type'];
+                    $value['coupon_id'] = $order_info['coupon_id'];
+                }
+            }
+        }
+        $this->success('获取成功',$res);
+    }
+    /**
+     * @title 删除订单
+     * @desc  删除订单
+     * @author  qc
+     * @url /api/Goods_order/delOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1  default:1 desc:订单id
+     */
+    public function delOrder()
+    {
+        $order_id = input('post.id');
+        $order_info = Db::table('goods_order')
+            ->where(['uid'=>$this->uid,'is_deleted'=>0,'id'=>$order_id])
+            ->find();
+        if(empty($order_info)) $this->error('订单不存在');
+        Db::table('goods_order')->where(['id'=>$order_id])->update(['is_deleted'=>1]);
+        $this->success('删除成功');
+    }
+
+}

+ 124 - 0
application/api/controller/Login.php

@@ -0,0 +1,124 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\api\controller;
+
+use AlibabaCloud\Client\AlibabaCloud;
+use AlibabaCloud\Client\Exception\ClientException;
+use AlibabaCloud\Client\Exception\ServerException;
+use app\api\controller\Base;
+use think\Db;
+use Firebase\JWT\JWT;
+use EasyWeChat\Factory;
+/**
+ * @title 用户登录
+ * @controller Login
+ * @group worker
+ */
+class Login extends Base
+{
+    /**
+     * @title 微信登录(小程序)
+     * @desc 微信登录(小程序)
+     * @author qc
+     * @url /api/Login/weChatLogin
+     * @method POST
+     * @tag 登录 授权
+     * @param name:code type:int require:1 default:-- desc:code值
+     * @param name:headimg type:string require:1 default:-- desc:头像地址
+     * @param name:name type:string require:1 default:-- desc:昵称
+     * @param name:pid type:int require:0 default:0 desc:推荐人id
+     * @return name:token type:string default:-- desc:用户登录成功后的token值
+     */
+    public function weChatLogin(){
+        $code = input('code');
+        $headimg = input('headimg');
+        $name = input('name');
+        $pid = input('pid',0);
+        if(empty($code) || empty($headimg) || empty($name)){
+            $this->error('参数错误');
+        }
+        $app = Factory::miniProgram(config('app.mini_program'));
+        $data = $app->auth->session($code);
+        if(empty($data['openid'])){
+            $this->error($data['errmsg']);
+        }
+        $member = Db::name('store_member')->field('id,phone')->where('openid',$data['openid'])->find();
+        if(empty($member)){
+            $member_data = array(
+                'openid' => $data['openid'],
+                'headimg' => $headimg,
+                'name' => $name,
+                'pid' =>$pid,
+                'create_at'=>date("Y-m-d H:i:s")
+            );
+            Db::table('store_member')->insert($member_data);
+            $uid = Db::getLastInsID();
+            // 给推荐人奖励
+            if($pid){
+                $invite_max =  intval(sysconf('invite_max'));
+                $invite_crystal=  intval(sysconf('invite_crystal'));
+                $invite_num = Db::table('store_member')->where('pid',$pid)->count();
+                if($invite_num <= $invite_max && $invite_crystal > 0) {
+                    // 更新会员余额
+                    Db::table('store_member')->where('id',$pid)->setInc('crystal',$invite_crystal);
+                    crystal_log($pid,$invite_crystal,'推荐注册奖励',1,$uid);
+                }
+            }
+        }else{
+            $uid = $member['id'];
+        }
+        if(empty($uid)) $this->error('数据有误');
+        $token = self::create_jwt($uid);
+        $this->success('登录成功',['token'=>$token]);
+    }
+    /**
+     * @param name:phone type:int require:1 default:-- desc:手机号
+     * @param name:password type:string require:1 default:-- desc:密码
+     * @return name:token type:string default:-- desc:用户登录成功后的token值
+     */
+    public function passwordLogin(){
+        $phone = input('phone');
+        $password = input('password');
+        if(empty($password) || empty($phone)){
+            $this->error('参数错误');
+        }
+        $member_id = Db::name('store_member')->where('phone',$phone)->where('password',md5($password))->value('id');
+        if(empty($member_id)){
+            $this->error('手机号或密码错误');
+        }
+        $token = self::create_jwt($member_id);
+        $this->success('登录成功',$token);
+    }
+
+    //token加密
+    public function create_jwt($uid)
+    {
+        $key = md5(config('app.jwt')); //jwt的签发密钥,验证token的时候需要用到
+        $time = time(); //签发时间
+        $expire = $time + config('app.jwt_time'); //过期时间
+        $token = array(
+            "uid" => $uid,
+            "iss" => "https://zain.com",//签发组织
+            "aud" => "https://zain.com", //签发作者
+            "iat" => $time,
+            "nbf" => $time,
+            "exp" => $expire
+        );
+        $jwt = JWT::encode($token, $key);
+        return $jwt;
+    }
+
+}

+ 470 - 0
application/api/controller/MagicCase.php

@@ -0,0 +1,470 @@
+<?php
+namespace app\api\controller;
+use think\Db;
+use EasyWeChat\Factory;
+/**
+ * @title 魔玩柜
+ * @controller MagicCase
+ * @group base
+ */
+class MagicCase extends Base
+{
+    public function initialize()
+    {
+        parent::initialize();
+        parent::check_login();
+        resolve_magic($this->uid);
+    }
+
+    /**
+     * @title 获取魔玩柜列表
+     * @desc  获取魔玩柜列表
+     * @author  qc
+     * @url /api/Magic_case/getMagicCaseList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  : default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @return name:list type:array default:-- desc:数据列表
+     * @return name:list.order_id type:int default:0 desc:关联的订单id
+     * @return name:list.create_at type:string default:0 desc:抽中时间
+     * @return name:list.case_name type:string default:0 desc:名称
+     * @return name:list.case_cover type:string default:0 desc:封面
+     * @return name:list.num type:string default:0 desc:数量
+     * @return name:list.crystal type:float default:0.00 desc:每个水晶价值
+     * @return name:list.past_at type:string default:0.00 desc:过期时间
+     * @return name:will_past type:int default:-- desc:10分钟内将要到期的记录
+     */
+    public function getMagicCaseList()
+    {
+        $will_past =  Db::table('magic_case')
+            ->where('user_id','=',$this->uid)
+            ->where('num','>',0)
+            ->where('past_int','<',time()+600)
+            ->count();
+
+        $list = Db::table('magic_case')
+            ->field('id,order_id,create_at,case_name,case_cover,num,crystal,past_at')
+            ->where('user_id','=',$this->uid)
+            ->where('num','>',0)
+            ->order('id desc')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('ok',['list'=>$list,'will_past'=>$will_past]);
+    }
+
+    /**
+     * @title 分解魔玩柜
+     * @desc  分解魔玩柜
+     * @author  qc
+     * @url /api/Magic_case/resolveMagicCase
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:json_str type:string  : default:1 desc:分解的json串[{'id':'';'num':'数量'}]  [{"id":11,"num":1}]
+     * @return name:total_crystal type:float default:0.00 desc:分级魔玩柜获得的水晶
+     */
+    public function resolveMagicCase()
+    {
+        $json_str =input('post.json_str');
+        $json_data = json_decode($json_str,true);
+        $log_data =[];
+        $total_crystal = 0;
+        $error = false;
+        Db::startTrans();
+        foreach ($json_data as $val) {
+            $magic_case = Db::table('magic_case')
+                ->field('id,num,crystal')
+                ->where(['user_id'=>$this->uid,'id'=>$val['id']])
+                ->find();
+            if(empty($magic_case) || $magic_case['num'] < $val['num']){
+                $error = true;break;
+            }
+            // 扣减魔玩柜的数量
+            Db::table('magic_case')->where('id',$val['id'])->setDec('num',$val['num']);
+            // 扣减魔玩柜变更记录
+            $crystal = bcmul($val['num'],$magic_case['crystal'],2);
+            $log_data[]= [
+                'user_id' => $this->uid,
+                'create_at' => date('Y-m-d H:i:s'),
+                'num' => $val['num'],
+                'case_id' => $val['id'],
+                'crystal' =>$crystal ,
+            ];
+            $total_crystal = bcadd($total_crystal,$crystal,2);
+        }
+        if($error){
+            Db::rollback();
+            $this->error('分解数据有误');
+        }
+        //更新水晶余额
+        $member_info = Db::table('store_member')->field('id,crystal_cash')->find($this->uid);
+        Db::table('store_member')->where('id',$this->uid)->update(['crystal_cash'=>bcadd($member_info['crystal_cash'],$total_crystal,2)]);
+        Db::table('magic_resolve')->insertAll($log_data);// 分解日志
+        // 余额日志
+        crystal_log($this->uid,$total_crystal,'魔玩柜分解',3);
+        Db::commit();
+        $this->success('ok',['total_crystal'=>$total_crystal]);
+    }
+
+
+    /**
+     * @title 订单确认
+     * @desc  订单确认
+     * @author  qc
+     * @url /api/Magic_case/orderConfirm
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param name:json_str type:string  : default:1 desc:选中的json串[{'id':'';'num':'数量'}]
+     * @return name:add_info type:array require:0 default:-- desc:默认地址
+     * @return name:add_info.id type:int   default:1 desc:收货地址记录id
+     * @return name:add_info.pro_id type:int   default:-- desc:省id
+     * @return name:add_info.city_id type:int   default:-- desc:市id
+     * @return name:add_info.county_id type:int  default:-- desc:县区id
+     * @return name:add_info.pro_name type:string  default:-- desc:省名
+     * @return name:add_info.city_name type:string  default:-- desc:市名
+     * @return name:add_info.county_name type:string  default:-- desc:县区名
+     * @return name:add_info.detail type:string  default:-- desc:详细地址
+     * @return name:add_info.phone type:string  default:-- desc:联系电话
+     * @return name:add_info.name type:string   default:-- desc:联系人
+     * @return name:goods_data type:array require:0 default:-- desc:商品详情
+     * @return name:goods_data.id type:array require:0 default:-- desc:魔玩柜记录id
+     * @return name:goods_data.num type:string require:0 default:-- desc:剩余数量
+     * @return name:goods_data.create_at type:string require:0 default:-- desc:时间
+     * @return name:goods_data.buy_num type:string require:0 default:-- desc:剩余购买
+     * @return name:goods_data.case_name type:string require:0 default:-- desc:名称
+     * @return name:goods_data.case_cover type:string require:0 default:-- desc:图片
+     * @return name:freight_data type:array  default:--  desc:运费详情
+     * @return name:freight_data.all_freight type:int  default:--  desc:总运费
+     * @return name:freight_data.first_freight type:int  default:--  desc:首件运费
+     * @return name:freight_data.later_freight type:int  default:--  desc:续件运费
+     * @return name:coupon_list type:array  default:--  desc:可用运费券
+     * @return name:coupon_list.id type:int  default:--  desc:券id
+     * @return name:coupon_list.past_at type:int  default:--  desc:过期时间
+     */
+    public function orderConfirm(){
+        $json_str =input('get.json_str');
+        $json_data = json_decode($json_str,true);
+        $all_ids   =  array_column($json_data,'id'); // 所要购买的记录id
+        $total_num = array_sum(array_column($json_data,'num'));//购买数量
+        $freight_data = get_freight($total_num);// 计算运费
+        $cl_data = array_column($json_data,null,'id');
+        // 验证魔玩柜数量
+        $magic_case = Db::table('magic_case')->field('id,num,case_name,case_cover,create_at')->where('id','in',$all_ids)->select();
+        $is_ck =  true;
+
+        foreach ($magic_case  as &$mv) {
+            if($mv['num'] < $cl_data[$mv['id']]['num'])$is_ck=false;// 购买数量大于剩与数量
+            $mv['buy_num'] = $cl_data[$mv['id']]['num'];
+        }
+        if(!$is_ck) $this->error('魔玩柜数量不足');
+        // 默认收货地址
+        $add_info = Db::table('delivery_address')->where(['user_id'=>$this->uid,'is_mr'=>1])->find();
+        // 运费券
+        $coupon_list = Db::table('user_coupon_list')
+            ->field('id,past_at')
+            ->where('user_id','=',$this->uid)
+            ->where('status','=',1)
+            ->where('past_at','> time',date('Y-m-d H:i:s'))
+            ->order('id desc')
+            ->select();
+        $this->success('ok',['add_info'=> $add_info ,'goods_data'=>$magic_case,'freight_data'=>$freight_data,'coupon_list'=>$coupon_list]);
+    }
+
+
+    /**
+     * @title 生成订单
+     * @desc  生成订单
+     * @author  qc
+     * @url /api/Magic_case/createOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:json_str type:string  : default:1 desc:选中的json串[{'id':'';'num':'数量'}]
+     * @param name:price_total type:float require:1 default:-- desc:支付金额
+     * @param name:add_id type:int require:1 default:0 desc:收货地址id
+     * @param name:coupon_id type:int require:0 default:0 desc:运费券的id
+     * @return name:order_id type:int require:0 default:0 desc:成功时返回订单id
+     */
+    public function createOrder()
+    {
+        $json_str   = input('post.json_str','');
+        $add_id     = input('post.add_id',0);
+        $price_total =  input("post.price_total",0);
+        $coupon_id = input('post.coupon_id',0);
+        if(!$add_id) $this->error('请选择收货地址');
+        $json_data = json_decode($json_str,true);
+        $cl_data   =  array_column($json_data,null,'id');
+        $all_ids   =  array_column($json_data,'id'); // 所要购买的记录id
+        $pro_info = []; // 商品详情
+        // 验证魔玩柜数量
+        $total_num = 0;
+        $magic_case = Db::table('magic_case')->field('id,goods_id,num,crystal,case_name,case_cover,create_at')->where('id','in',$all_ids)->select();
+        $is_ck =  true;
+        foreach ($magic_case  as &$mv) {
+            if($mv['num'] < $cl_data[$mv['id']]['num'])$is_ck=false;// 购买数量大于剩与数量
+            $pro_info[] = [
+                'magic_id'   => $mv['id'],
+                'goods_id'  => $mv['goods_id'],
+                'num'       => $cl_data[$mv['id']]['num'],
+                'case_name' => $mv['case_name'],
+                'case_cover'=> $mv['case_cover'],
+                'crystal'  => $mv['crystal'],
+                'draw_time'  => $mv['create_at'],
+            ];
+            $total_num += $cl_data[$mv['id']]['num'];
+        }
+        if(!$is_ck) $this->error('魔玩柜数量不足');
+        $freight = get_freight($total_num); // 运费
+        $price_total = $coupon_id ?  $freight['all_freight'] - $freight['first_freight']:$freight['all_freight'] ;
+        $order_int =[
+            'uid'=>$this->uid,
+            'order_no'      => get_order_sn(),
+            'price_total'   => $price_total,
+            'goods_num'     => $total_num,
+            'create_at'     => date('Y-m-d H:i:s'),
+            'pro_info'      => json_encode($pro_info),
+            'coupon_id'    => $coupon_id,
+            'address_id'    => $add_id,
+            'freight'      =>$freight['all_freight'],
+        ];
+        Db::startTrans();
+        $msg= '';$com=true;
+        try{
+            // 扣减魔玩柜库存
+            foreach ($pro_info  as $pv) {
+                Db::table('magic_case')->where(['id'=>$pv['magic_id']])->setDec('num',$pv['num']);
+            }
+            if($coupon_id) Db::table('user_coupon_list')->where(['id'=>$coupon_id])->update(['status'=>2,'used_time'=>date('Y-m-d H:i:s')]);
+            // 生成订单
+            Db::table('magic_order')->insert($order_int);
+            $order_id = Db::getLastInsID();
+            Db::commit();
+        }catch (\Exception $e){
+            Db::rollback();
+            $com=false;
+            $msg = $e->getMessage();
+        }
+        if($com){
+            $this->success('ok',['order_id'=>$order_id]);
+        }else{
+            $this->error($msg);
+        }
+    }
+
+
+    /**
+     * @title 取消订单
+     * @desc  取消订单
+     * @author  qc
+     * @url /api/Magic_case/cancelOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:id type:int require:1 default:-- desc:订单id
+     */
+    public function cancelOrder()
+    {
+        $order_id = input('post.id');
+        $order_detail = Db::table('magic_order')->where(['id'=>$order_id,'uid'=>$this->uid])->find();
+        if(empty($order_detail)) $this->error('订单不存在');
+        if($order_detail['pay_state'] != 0)      $this->error('订单已支付');
+        if($order_detail['cancel_state'] != 0)   $this->error('订单已取消,不能重复取消');
+        Db::startTrans();
+        try {
+            //恢复库存
+            $pro_info = json_decode($order_detail['pro_info'],true);
+            foreach ($pro_info as $pv) {
+                Db::table('magic_case')->where(['id'=>$pv['magic_id']])->setInc('num',$pv['num']);
+            }
+            if($order_detail['coupon_id']) Db::table('user_coupon_list')->where('id',$order_detail['coupon_id'])->update(['status'=>1,'used_time'=>'']);
+            // 取消订单
+            Db::table('magic_order')
+                ->where(['id'=>$order_id])
+                ->update(['cancel_state'=>1,'status'=>9]);
+            Db::commit();
+        }catch (\Exception $e){
+            Db::rollback();
+        }
+        $this->success('取消成功');
+    }
+
+    /**
+     * @title 获取订单详情
+     * @desc  获取订单详情
+     * @author  qc
+     * @url /api/Magic_case/getOrderDetail
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int require:1 default:-- desc:订单id
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:status type:int default:-- desc:支付状态:0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消
+     * @return name:price_total type:float default:-- desc:订单金额
+     * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
+     * @return name:pay_no type:string default:-- desc:支付单号
+     * @return name:create_at type:string default:-- desc:订单创建时间
+     * @return name:pay_time type:string default:-- desc:支付时间
+     * @return name:cancel_state type:int default:-- desc:取消状态
+     * @return name:pro_info type:array default:-- desc:商品详情
+     * @return name:pro_info.num type:int default:-- desc:商品数量
+     * @return name:pro_info.case_name type:int default:-- desc:名称
+     * @return name:pro_info.case_cover type:int default:-- desc:图片
+     * @return name:pro_info.draw_time type:int default:-- desc:抽中时间
+     * @return name:express_company_title type:string default:-- desc:物流公司
+     * @return name:express_send_no type:string default:-- desc:物流单号
+     * @return name:express_send_at type:string default:-- desc:发货时间
+     * @return name:express_company_id type:string default:-- desc:物流公司id
+     * @return name:address_area type:string default:0 desc:收货地区(精确到县区)
+     * @return name:address_detail type:string default:0 desc:详细地址
+     * @return name:address_user type:string default:0 desc:收货人姓名
+     * @return name:address_tel type:string default:0 desc:收货人电话
+     *
+     */
+    public function getOrderDetail()
+    {
+        $order_id = input('id',0);
+        $detail = Db::table('magic_order')->find($order_id);
+        $add_info = Db::table('delivery_address')->find($detail['address_id']);
+        $detail['address_area']  = $add_info['mer_name'];
+        $detail['address_detail'] = $add_info['detail'];
+        $detail['address_user'] = $add_info['name'];
+        $detail['address_tel'] = $add_info['phone'];
+        $this->success('获取成功',$detail);
+    }
+
+
+    /**
+     * @title 去支付
+     * @desc  去支付
+     * @author  qc
+     * @url /api/Magic_case/payOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:o_id type:int require:1 default:-- desc:订单id
+     * @return name:config type:array default:0 desc:支付配置
+     * @return name:config.appId type:string default:-- desc:公众账号ID
+     * @return name:config.nonceStr type:string default:-- desc:随机字符串
+     * @return name:config.signType type:string default:-- desc:签名类型
+     * @return name:config.paySign type:string default:-- desc:签名
+     * @return name:config.timestamp type:string default:-- desc:时间戳
+     */
+    public function payOrder()
+    {
+        $o_id = input('post.o_id');
+        $user_info = Db::table('store_member')->where('id',$this->uid)->find();
+        if(!$user_info['openid']) $this->error('请先完善用户信息');
+        $order_info =     Db::table('magic_order')->where(['uid'=>$this->uid,'id'=>$o_id])->find();
+        if(empty($order_info)) $this->error('订单不存在');
+        if($order_info['cancel_state'] != 0) $this->error('订单已取消');
+        if($order_info['status'] != 0) $this->error('订单已支付');
+        if($order_info['price_total'] < 0) $this->error('订单金额错误');
+        $config = false;$msg= '';
+        $pay_no = $order_info['pay_no'] ?  $order_info['pay_no'] : get_order_sn();
+        if($order_info['price_total'] == 0 ) {
+            Db::table('magic_order')->where(['uid'=>$this->uid,'id'=>$o_id])
+                ->update(['pay_time'=>date('Y-m-d H:i:s'),'pay_state'=>1,'pay_type'=>2,'status'=>1,'pay_no'=>$pay_no]);
+            $this->success('支付成功',['pay_type'=>2,'config' => '']);
+        }else{
+            $notify_url = $this->request->root(true) . '/api/Pay/magicOrderNotify';
+            Db::startTrans();
+            try{
+                // 更新订单
+                $price_total = $order_info['price_total'];
+                Db::table('magic_order')->where(['uid'=>$this->uid,'id'=>$o_id])->update(['pay_no'=>$pay_no]);
+                $config = Pay::wxPay('订单支付',$pay_no,$price_total,$notify_url,'JSAPI',$user_info['openid']);
+                if($config){
+                    Db::commit();
+                }else{
+                    Db::rollback();
+                }
+            }catch (\Exception $e){
+                Db::rollback();
+                $msg = $e->getMessage();
+            }
+            if($config){
+                $this->success('ok',['pay_type'=>1,'config'=>$config]);
+            }else{
+                $this->error($msg);
+            }
+        }
+    }
+
+
+    /**
+     * @title 获取订单列表
+     * @desc  获取订单列表
+     * @author  qc
+     * @url /api/Magic_case/getMyOrderList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @return name:id type:string default:-- desc:订单id
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:status type:int default:-- desc:支付状态:0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消
+     * @return name:price_total type:float default:-- desc:订单金额
+     * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
+     * @return name:pay_no type:string default:-- desc:支付单号
+     * @return name:create_at type:string default:-- desc:订单创建时间
+     * @return name:pay_type type:string default:-- desc:支付方式(0未支付,1微信,2余额)
+     * @return name:pay_time type:string default:-- desc:支付时间
+     * @return name:cancel_state type:int default:-- desc:取消状态
+     * @return name:pro_info type:array default:-- desc:商品详情
+     * @return name:pro_info.num type:int default:-- desc:商品数量
+     * @return name:pro_info.case_name type:int default:-- desc:名称
+     * @return name:pro_info.case_cover type:int default:-- desc:图片
+     */
+    public function getMyOrderList()
+    {
+        $status  = input('status',-1);
+        $where=[];
+        if($status > -1) $where['o.status'] = $status;
+        $where['o.uid'] = $this->uid;
+        $where['o.is_deleted'] = 0;
+        $where['o.cancel_state'] = 0;
+        $where['o.is_deleted'] = 0;
+        $list = Db::table('magic_order o')
+            ->field('o.id,o.order_no,o.pay_state,pay_type,pay_time,o.create_at,price_total,status,pro_info')
+            ->where($where)
+            ->order('o.id desc')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('获取成功',['list'=>$list]);
+    }
+
+    /**
+     * @title 删除订单
+     * @desc  删除订单
+     * @author  qc
+     * @url /api/Magic_case/delOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1  default:1 desc:订单id
+     */
+    public function delOrder()
+    {
+        $order_id = input('post.id');
+        $order_info = Db::table('magic_order')
+            ->where(['uid'=>$this->uid,'is_deleted'=>0,'id'=>$order_id])
+            ->find();
+        if(empty($order_info)) $this->error('订单不存在');
+        Db::table('magic_order')->where(['id'=>$order_id])->update(['is_deleted'=>1]);
+        $this->success('删除成功');
+    }
+
+
+    /**
+     * @title 确认收货
+     * @desc  确认收货
+     * @author  qc
+     * @url /api/Magic_case/confirmReceipt
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1  default:1 desc:订单id
+     */
+    public function confirmReceipt(){
+        $order_info = Db::table('magic_order')
+            ->where(['uid'=>$this->uid,'id'=>input('post.id')])
+            ->find();
+        if(empty($order_info) || $order_info['status'] != 2) $this->error('商品未发货');
+        Db::table('magic_order')->where(['id'=>$order_info['id']])->update(['status'=>3,'receipt_at'=>date('Y-m-d H:i:s')]);
+        $this->success('收货成功');
+    }
+
+
+}

+ 929 - 0
application/api/controller/Order.php

@@ -0,0 +1,929 @@
+<?php
+namespace app\api\controller;
+use think\Db;
+use EasyWeChat\Factory;
+/**
+ * @title 会员订单管理
+ * @controller Order
+ * @group base
+ */
+class Order extends Base
+{
+    public function initialize()
+    {
+        parent::check_login();
+    }
+
+
+    /**
+     * @title 订单确认(直接购买&&直接兑换)
+     * @desc  生成订单
+     * @author  qc
+     * @url /api/Order/orderConfirm
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param name:goods_id type:int require:1 default:-- desc:商品id
+     * @param name:goods_no type:string require:1 default:-- desc:商品货号
+     * @param name:num type:int require:0 default:1 desc:商品数量
+     * @return name:add_info type:array require:0 default:-- desc:默认地址
+     * @return name:add_info.id type:int   default:1 desc:收货地址记录id
+     * @return name:add_info.pro_id type:int   default:-- desc:省id
+     * @return name:add_info.city_id type:int   default:-- desc:市id
+     * @return name:add_info.county_id type:int  default:-- desc:县区id
+     * @return name:add_info.pro_name type:string  default:-- desc:省名
+     * @return name:add_info.city_name type:string  default:-- desc:市名
+     * @return name:add_info.county_name type:string  default:-- desc:县区名
+     * @return name:add_info.detail type:string  default:-- desc:详细地址
+     * @return name:add_info.phone type:string  default:-- desc:联系电话
+     * @return name:add_info.name type:string   default:-- desc:联系人
+     * @return name:goods_data type:array require:0 default:-- desc:商品详情
+     * @return name:goods_data.goods_id type:array require:0 default:-- desc:商品id
+     * @return name:goods_data.name type:string require:0 default:-- desc:商品名称
+     * @return name:goods_data.cover type:string require:0 default:-- desc:商品图片
+     * @return name:goods_data.freight type:float require:0 default:-- desc:商品运费
+     * @return name:goods_data.integral type:int require:0 default:-- desc:商品积分数(单个商品积分乘以个数)
+     */
+    public function orderConfirm()
+    {
+        $goods_id   = input('get.goods_id');
+        $goods_no   = input('get.goods_no');
+        $num        = input('get.num',1);
+        $add_info = Db::table('delivery_address')
+            ->where(['user_id'=>$this->uid,'is_mr'=>1])->find();
+        $goods_info = Db::table('store_goods')->find($goods_id);
+        $spec = json_decode($goods_info['spec'],true);
+        $cover = $goods_info['cover'];
+        foreach ($spec as $sk=>$sv)
+        {
+            if($goods_no ==  $sv['goods_no']) $cover = $sv['spec_img'];
+        }
+        $freight = $goods_info['freight_type'] == 0 ? $goods_info['postage'] :0 ;
+        // 运费模板计算运费
+        if(!empty($add_info) && $goods_info['freight_type']){
+            $cal_freight =  $this->claFreight($add_info['id'],$goods_info['freight_id'],$num);
+            if($cal_freight['code'] != 200){
+                $add_info = null ;
+            }else{
+                $freight = $cal_freight['freight'];
+            }
+        }
+
+        $goods_data = [
+            'goods_id' => $goods_info['id'],
+            'goods_no' => $goods_no,
+            'name' => $goods_info['name'],
+            'cover' => $cover,
+            'integral'=>$goods_info['integral'] * $num,
+            'freight' => $freight
+        ];
+
+        $this->success('ok',['add_info'=> $add_info ,'goods_data'=>$goods_data]);
+
+    }
+
+    /**
+     * 计算运费
+     * @param $add_id  地址id
+     * @param $freight_id  模板id
+     * @param $num  商品数量
+     * @return array
+     */
+    public function claFreight($add_id,$freight_id,$num)
+    {
+        $data = ['code'=>200,'freight'=>0 ,'msg'=>''];
+        $address_info = Db::table('delivery_address')->find($add_id);
+        $template_info = Db::table('freight_template')->find($freight_id);
+        if(empty($address_info)){
+            $data['code'] = 201;
+            $data['msg'] = '运费模板不存在';
+            return  $data;
+        }
+        $city_id = $address_info['city_id'];
+        $no_express = explode(',',$template_info['no_express']);
+        if(in_array($city_id,$no_express)) return ['code'=>202,'msg'=>'该收货地址不配送物流'];
+        // 模板自定义分组
+        $custom  =  json_decode($template_info['custom'],true);
+        $base_num = $template_info['base_num'];// 基件数量
+        $base_price = $template_info['base_price']; // 基件费用
+        $base_keep_price = $template_info['base_keep_price']; //  续件费用
+        foreach($custom as $cus_info) {
+            $express =explode(',',$cus_info['express']);
+            if(in_array($city_id,$express)) {
+                $base_num = $cus_info['first_num'];
+                $base_price = $cus_info['first_price'];
+                $base_keep_price = $cus_info['keep_price'];
+                break;
+            }
+        }
+        if($base_num >= $num ) return  $data = ['code'=>200,'freight'=>$base_price ,'msg'=>'ok'];
+        $sub_keep = bcmul(bcsub($num,$base_num),$base_keep_price,2);
+        return   $data = ['code'=>200,'freight'=>bcadd($base_price,$sub_keep) ,'msg'=>'ok'];
+    }
+
+
+    /**
+     * @title 获取运费
+     * @desc  获取运费
+     * @author  qc
+     * @url /api/Order/getFreight
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param name:goods_id type:int require:1 default:-- desc:商品id
+     * @param name:add_id type:int require:1 default:-- desc:地址id
+     * @param name:num type:int require:0 default:1 desc:商品数量
+     * @return name:freight type:float require:0 default:-- desc:运费金额
+     */
+    public function getFreight()
+    {
+        $goods_id = input('goods_id',0);
+        $add_id = input('add_id',0);
+        $num   = input('num',0);
+        $goods_info = Db::table('store_goods')->find($goods_id);
+        $freight = $goods_info['freight_type'] == 0 ? $goods_info['postage'] :0 ;
+        if($goods_info['freight_type']){
+            $cal_freight =  $this->claFreight($add_id,$goods_info['freight_id'],$num);
+            if($cal_freight['code'] != 200){
+                $this->error($cal_freight['msg']);
+            }else{
+                $freight = $cal_freight['freight'];
+            }
+        }
+        $this->success('ok',['freight'=>$freight]);
+    }
+
+
+    /**
+     * @title 生成订单(立即购买 [商城 && 积分商城])
+     * @desc  生成订单(立即购买 [商城 && 积分商城])
+     * @author  qc
+     * @url /api/Order/createOrderByImmediately
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:goods_id type:int require:1 default:-- desc:商品id
+     * @param name:goods_no type:int require:1 default:-- desc:商品货号
+     * @param name:price_total type:float require:1 default:-- desc:支付金额(优惠后的商品金额+运费)
+     * @param name:num type:int require:1 default:1 desc:商品数量
+     * @param name:price_goods type:float require:0 default:0 desc:商品总金额(没优惠的)
+     * @param name:price_express type:float require:0 default:0 desc:运费
+     * @param name:add_id type:int require:1 default:0 desc:收货地址id
+     * @param name:remark type:string require:0 default:0 desc:订单备注
+     * @param name:source type:int require:0 default:0 desc:商城的为0(默认),积分商城的值为1
+     * @param name:integral type:int require:0 default:0 desc:使用多少积分,source为1时必传
+     * @param name:int_cash type:float require:0 default:0 desc:积分抵扣多少钱,source为1时必传
+     * @param name:cl_id type:int require:0 default:0 desc:会员优惠券id,使用优惠券必传
+     * @param name:coupon_cash type:float require:0 default:0 desc:会员优惠券抵扣金额
+     * @return  name:order_id type:int require:0 default:0 desc:成功时返回订单id
+     */
+    public function createOrderByImmediately()
+    {
+        $goods_id               =  input("post.goods_id");
+        $goods_no               =  input("post.goods_no");
+        $price_total            =  input("post.price_total",0);
+        $price_goods            =  input("post.price_goods",0);
+        $price_express          =  input("post.price_express",0);
+        $num                    =  input("post.num",1);
+        $add_id                 =  input("post.add_id",0);
+        $source                 =  input("post.source",0);
+        $integral               =  input("post.integral",0);
+        $int_cash               =  input("post.int_cash",0);
+        $cl_id                  =  input("post.cl_id",0);
+        $coupon_cash            =  input("post.coupon_cash",0);
+        $remark                 =  input("post.remark",'');
+        //商品验证start
+        $goods_info = Db::table('store_goods')->field('id,name,spec,stock,is_integral')
+            ->where(['id'=>$goods_id,'status'=>1,'is_deleted'=>0])
+            ->find();
+        if(empty($goods_info))  $this->error('商品已下架');
+        $spec_info = [];
+        $goods_spec = json_decode($goods_info['spec'],true);
+        foreach ($goods_spec as &$c){
+            if($c['goods_no'] == $goods_no) {
+                $spec_info =$c;
+                $c['store_num'] -=$num;
+                break;
+            }
+        }
+        if(!isset($spec_info['integral'])) $spec_info['integral'] = 0;
+        if($spec_info['store_num'] < $num || $goods_info['stock'] < $num) $this->error('商品库存不足');
+        // 券验证
+        if($cl_id) {
+            $cl_info = Db::table('user_coupon_list')
+                ->where(['user_id'=>$this->uid,'id'=>$cl_id,'status'=>1])
+                ->find();
+            if(empty($cl_info)) $this->error('优惠券不存在');
+            if($cl_info['past_at'] < date('Y-m-d H:i:s')) $this->error('优惠券已过期');
+            if($cl_info['low_amount'] > bcsub($price_total,$price_express,2) ) $this->error('订单金额不够,再看看吧');
+            if($cl_info['amount'] != $coupon_cash ) $this->error('优惠金额错误');
+        }
+        // 积分验证
+        $user = Db::table('store_member')->find($this->uid);
+        if($integral && $user['integral'] < $integral) $this->error('积分余额不足');
+        $pro_info[]=[
+            'goods_id'  =>$goods_id,
+            'goods_no'  =>$goods_no,
+            'num'       => $num,
+            'integral'  =>$spec_info['integral'] * $num,
+            'int_cash'  =>$int_cash,
+            'goods_name'  =>$goods_info['name'],
+            'spec_img'  =>$spec_info['spec_img'],
+            'sell_money'=>$spec_info['sell_money'],
+            'spec_exp'  =>$spec_info['spec_exp'],
+            'spec_key'  =>$spec_info['spec_key'],
+            'is_evaluate'  => 0,
+        ];
+        $order_int =[
+            'uid'=>$this->uid,
+            'order_no'      => get_order_sn(),
+            'price_total'   => $price_total,
+            'price_goods'   => $price_goods,
+            'price_express' => $price_express,
+            'create_at'     => date("Y-m-d H:i:s"),
+            'address_id'    =>$add_id,
+            'source'        =>$source,
+            'integral'      =>$integral,
+            'int_cash'      =>$int_cash,
+            'cl_id'         =>$cl_id,
+            'coupon_cash'   =>$coupon_cash,
+            'remark'        =>$remark,
+            'goods_num'     =>$num,
+            'pro_info'      =>json_encode($pro_info)
+        ];
+        Db::startTrans();
+        $msg= '';$com=true;
+        try{
+            // 生成订单
+            Db::table('store_order')->insert($order_int);
+            $order_id = Db::getLastInsID();
+            //扣减库存
+            update_goods_stock($goods_id,$goods_no,$num);
+            //扣减积分
+            if($integral){
+                update_user_integral($this->uid,$integral * -1,5,'积分抵扣',$order_id);
+            }
+            // 扣除券
+            if($cl_id) {
+                Db::table('user_coupon_list')->where(['id'=>$cl_id])->update(['status'=>2,'used_time'=>date('Y-m-d H:i:s')]);
+            }
+            Db::commit();
+        }catch (\Exception $e){
+            Db::rollback();
+            $com=false;
+            $msg = $e->getMessage();
+        }
+        if($com){
+            $this->success('ok',['order_id'=>$order_id]);
+        }else{
+            $this->error($msg);
+        }
+    }
+
+
+
+    /**
+     * @title 取消订单
+     * @desc  取消订单
+     * @author  qc
+     * @url /api/Order/cancelOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:id type:int require:1 default:-- desc:订单id
+     * @param name:cancel_desc type:string require:1 default:-- desc:取消描述
+     */
+    public function cancelOrder()
+    {
+        $order_id = input('post.id');
+        $desc = input('post.desc');
+        $order_detail = Db::table('store_order')->where(['id'=>$order_id])->find();
+        if(empty($order_detail)) $this->error('订单不存在');
+        if($order_detail['pay_state'] != 0)      $this->error('订单已支付');
+        if($order_detail['cancel_state'] != 0)   $this->error('订单已取消,不能重复取消');
+        Db::startTrans();
+        try {
+            // 积分退回
+            if($order_detail['integral'] > 0) {
+                update_user_integral($order_detail['uid'],$order_detail['integral'],8,'订单取消退回',$order_id);
+            }
+            //  优惠券回档
+            if($order_detail['cl_id'] > 0) {
+                $user_coupon = Db::table('user_coupon_list')->find($order_detail['cl_id']);// 会员优惠券记录
+                $coupon_set = Db::table('store_coupon_config')->find($user_coupon['coupon_id']);//优惠券设置
+                if($coupon_set['status'] != 1 || $coupon_set['is_deleted'] == 1){
+                    $coupon_status =  4;
+                }else{
+                    $coupon_status = $user_coupon['past_at'] > date("Y-m-d H:i:s") ? 1:3;
+                }
+                Db::table('user_coupon_list')->where(['id'=>$order_detail['cl_id']])->update(['status'=>$coupon_status]);
+            }
+            // 商品库存恢复
+            $pro_info  = json_decode($order_detail['pro_info'],true);
+            foreach ($pro_info as $pv) {
+                update_goods_stock($pv['goods_id'],$pv['goods_no'],$pv['num']*-1);
+            }
+             // 取消订单
+            Db::table('store_order')
+                ->where(['id'=>$order_id])
+                ->update(['cancel_state'=>1,'cancel_at'=>date('Y-m-d H:i:s'),'cancel_desc'=>$desc,'status'=>9]);
+            Db::commit();
+        }catch (\Exception $e){
+            Db::rollback();
+        }
+        $this->success('取消成功');
+
+    }
+
+
+
+    /**
+     * @title 生成订单(购物车)
+     * @desc  生成订单(购物车)
+     * @author  qc
+     * @url /api/Order/createOrderByTrolley
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:ids type:string  : default:1 desc:购物车记录id串(逗号分开)
+     * @param name:price_total type:float require:1 default:-- desc:支付金额(优惠后的商品金额+运费)
+     * @param name:price_goods type:float require:0 default:0 desc:商品总金额(没优惠的)
+     * @param name:price_express type:float require:0 default:0  desc:运费
+     * @param name:add_id type:int require:1 default:0 desc:收货地址id
+     * @param name:remark type:string require:0 default:0 desc:订单备注
+     * @param name:source type:int require:0 default:0 desc:商城的为0(默认),积分商城的值为1
+     * @param name:integral type:int require:0 default:0 desc:使用多少积分,source为1时必传
+     * @param name:int_cash type:float require:0 default:0 desc:积分抵扣多少钱,source为1时必传
+     * @param name:cl_id type:int require:0 default:0 desc:会员优惠券id,使用优惠券必传
+     * @param name:coupon_cash type:float require:0 default:0 desc:会员优惠券抵扣金额
+     * @return name:order_id type:int require:0 default:0 desc:成功时返回订单id
+     */
+    public function createOrderByTrolley()
+    {
+        $ids                    =  input("post.ids");
+        $price_total            =  input("post.price_total",0);
+        $price_goods            =  input("post.price_goods",0);
+        $price_express          =  input("post.price_express",0);
+        $add_id                 =  input("post.add_id",0);
+        $source                 =  input("post.source",0);
+        $integral               =  input("post.integral",0);
+        $int_cash               =  input("post.int_cash",0);
+        $cl_id                  =  input("post.cl_id",0);
+        $coupon_cash            =  input("post.coupon_cash",0);
+        $remark                 =  input("post.remark",'');
+        if(!$ids || !$price_total) $this->error('请选择要结算的商品');
+        $trolley_arr = Db::table('shopping_trolley')
+            ->where(['user_id'=>$this->uid,'id'=>explode(',',$ids)])
+            ->select();
+        $pro_info = [];$total_num = 0;$check_goods = true;
+        // 验证商品是否下架 && 获取订单商品详情
+        foreach ($trolley_arr as $tv) {
+            $goods_info = Db::table('store_goods')->field('id,spec,name')
+                ->where(['id'=>$tv['goods_id'],'is_deleted'=>0,'status'=>1])
+                ->find();
+            if(empty($goods_info)){
+                $check_goods =false;
+                break;
+            }
+            foreach (json_decode($goods_info['spec'],true) as $sv)
+            {
+                if($sv['goods_no'] == $tv['goods_no']) {
+                    $pro_info[]=[
+                        'goods_id'  =>$tv['goods_id'],
+                        'goods_no'  =>$tv['goods_no'],
+                        'num'       =>$tv['num'],
+                        'integral'  => isset($sv['integral']) ? $sv['integral'] * $tv['num'] : 0,
+                        'int_cash'  =>'--',
+                        'goods_name'  =>$goods_info['name'],
+                        'spec_img'  =>$sv['spec_img'],
+                        'sell_money'=>$sv['sell_money'],
+                        'spec_exp'  =>$sv['spec_exp'],
+                        'spec_key'  =>$sv['spec_key'],
+                        'is_evaluate'  => 0,
+                    ];
+                    $total_num +=$tv['num'];
+                }
+            }
+        }
+        if(!$check_goods) $this->error('所选商品已下架');
+        // 券验证
+        if($cl_id) {
+            $cl_info = Db::table('user_coupon_list')
+                ->where(['user_id'=>$this->uid,'id'=>$cl_id,'status'=>1])
+                ->find();
+            if(empty($cl_info)) $this->error('优惠券不存在');
+            if($cl_info['past_at'] < date('Y-m-d H:i:s')) $this->error('优惠券已过期');
+            if($cl_info['low_amount'] > bcsub($price_total,$price_express,2) ) $this->error('订单金额不够,再看看吧');
+            if($cl_info['amount'] != $coupon_cash ) $this->error('优惠金额错误');
+        }
+        // 积分验证
+        $user = Db::table('store_member')->find($this->uid);
+        if($integral && $user['integral'] < $integral) $this->error('积分余额不足');
+        $order_int =[
+            'uid'=>$this->uid,
+            'order_no'      => get_order_sn(),
+            'price_total'   => $price_total,
+            'price_goods'   => $price_goods,
+            'price_express' => $price_express,
+            'create_at'     => date("Y-m-d H:i:s"),
+            'address_id'    =>$add_id,
+            'source'        =>$source,
+            'integral'      =>$integral,
+            'int_cash'      =>$int_cash,
+            'cl_id'         =>$cl_id,
+            'coupon_cash'   =>$coupon_cash,
+            'remark'        =>$remark,
+            'goods_num'     =>$total_num,
+            'pro_info'      =>json_encode($pro_info)
+        ];
+        Db::startTrans();
+        $msg= '';$com=true;
+        try{
+            // 生成订单
+            Db::table('store_order')->insert($order_int);
+            $order_id = Db::getLastInsID();
+            // 删除购物车记录
+            Db::table('shopping_trolley')->where(['id'=>explode(',',$ids)])->delete();
+            //扣减积分
+            if($integral){
+                Db::table('store_member')->where(['id'=>$this->uid])->setDec('integral',$integral);
+                //积分扣减记录
+                $integral_info=[
+                    'user_id'=> $this->uid,
+                    'create_at'=> date("Y-m-d H:i:s"),
+                    'integral'=> $integral * -1,
+                    'before'=> $user['integral'],
+                    'after'=> $user['integral'] - $integral,
+                    'desc'=> '积分抵现',
+                    'rel_id'=> $order_id,
+                ];
+                Db::table('integral_info')->insert($integral_info);
+            }
+            // 扣除券
+            if($cl_id) {
+                Db::table('user_coupon_list')->where(['id'=>$cl_id])->update(['status'=>2,'used_time'=>date('Y-m-d H:i:s')]);
+            }
+            Db::commit();
+        }catch (\Exception $e){
+            Db::rollback();
+            $com=false;
+            $msg = $e->getMessage();
+        }
+        if($com){
+            $this->success('ok',['order_id'=>$order_id]);
+        }else{
+            $this->error($msg);
+        }
+    }
+
+
+    /**
+     * @title 获取订单详情
+     * @desc  获取订单详情
+     * @author  qc
+     * @url /api/Order/getOrderDetail
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int require:1 default:-- desc:订单id
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:status type:int default:-- desc:支付状态:0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消
+     * @return name:price_total type:float default:-- desc:订单金额(需要支付金额【包含运费,扣除所有优惠】)
+     * @return name:pro_info type:string default:-- desc:订单商品
+     * @return name:pro_info.goods_id type:int default:-- desc:商品id
+     * @return name:pro_info.goods_no type:string default:-- desc:商品货号
+     * @return name:pro_info.sell_money type:string default:-- desc:售价
+     * @return name:pro_info.spec_img type:string default:-- desc:封面
+     * @return name:pro_info.is_evaluate type:string default:-- desc:商品是否评价
+     * @return name:price_goods type:float default:-- desc:商品金额
+     * @return name:price_express type:float default:-- desc:运费
+     * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:pay_no type:string default:-- desc:支付单号
+     * @return name:create_at type:string default:-- desc:订单创建时间
+     * @return name:pay_at type:string default:-- desc:支付时间
+     * @return name:cancel_at type:string default:-- desc:取消时间(status=9)
+     * @return name:cancel_desc type:string default:-- desc:取消描述(status=9)
+     * @return name:refund_type type:int default:-- desc:订单申请退款、退换货状态0未申请,1部分申请,2全部申请
+     * @return name:source type:int default:0 desc:订单来源:0商城,1积分商城
+     * @return name:integral type:int default:0 desc:使用多少积分
+     * @return name:int_cash type:int default:0 desc:积分抵扣多少金额
+     * @return name:cl_id type:int default:0 desc:使用优惠券的id
+     * @return name:coupon_cash type:float default:0 desc:券抵扣金额
+     */
+    public function getOrderDetail()
+    {
+        $order_id = input('id',0);
+        $detail = Db::table('store_order')->find($order_id);
+        $this->success('获取成功',$detail);
+
+    }
+
+
+    /**
+     * @title 去支付
+     * @desc  去支付
+     * @author  qc
+     * @url /api/Order/payOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:o_id type:int require:1 default:-- desc:订单id
+     * @return name:type type:int default:0 desc:类型(1.type=1,调支付,2纯积分兑换成功)
+     * @return name:config type:array default:0 desc:支付配置(type=2时忽略)
+     * @return name:config.appId type:string default:-- desc:公众账号ID
+     * @return name:config.nonceStr type:string default:-- desc:随机字符串
+     * @return name:config.signType type:string default:-- desc:签名类型
+     * @return name:config.paySign type:string default:-- desc:签名
+     * @return name:config.timestamp type:string default:-- desc:时间戳
+     */
+    public function payOrder()
+    {
+        $o_id = input('post.o_id');
+        $user_info = Db::table('store_member')->where('id',$this->uid)->find();
+        if(!$user_info['phone'] || !$user_info['openid']) $this->error('请先完善用户信息');
+        $order_info =     Db::table('store_order')->where(['uid'=>$this->uid,'id'=>$o_id])->find();
+        if(empty($order_info)) $this->error('订单不存在');
+        if($order_info['status'] != 0) $this->error('订单已支付');
+        if($order_info['cancel_state'] != 0) $this->error('订单已取消');
+        if($order_info['price_total'] <= 0 && $order_info['source'] == 0) $this->error('订单金额错误');
+        // 纯积分兑换
+        if($order_info['price_total'] <= 0 && $order_info['source'] == 1 )
+        {
+            // 销量
+            $sell_data = [];
+            foreach (json_decode($order_info['pro_info'],true) as $pv){
+                $sell_data[] =[
+                    'goods_id' => $pv['goods_id'],
+                    'goods_no' => $pv['goods_no'],
+                    'num' => $pv['num'],
+                    'user_id' => $order_info['uid'],
+                    'order_id' => $order_info['id'],
+                    'create_at' => date('Y-m-d H:i:s'),
+                    'year' => date('Y'),
+                    'month' => date('m'),
+                    'day' => date('d'),
+                ];
+            }
+            $pay_no = $order_info['pay_no'] ?  $order_info['pay_no'] : get_order_sn();
+            Db::table('goods_sell_info')->insertAll($sell_data);
+            // 更新订单状态
+            Db::table('store_order')->where(['uid'=>$this->uid,'id'=>$o_id])
+                ->update(['pay_at'=>date('Y-m-d H:i:s'),'pay_state'=>1,'status'=>1,'pay_no'=>$pay_no]);
+            $this->success('兑换成功',['type'=>2]);
+        }else{
+            Db::startTrans();
+            $config = false;$msg= '';
+            try{
+                $notify_url = $this->request->root(true) . '/api/Pay/payNotify';
+                $pay_no = $order_info['pay_no'] ?  $order_info['pay_no'] : get_order_sn();
+                Db::table('store_order')->where(['uid'=>$this->uid,'id'=>$o_id])->update(['pay_no'=>$pay_no]);
+                $config = Pay::wxPay('订单支付',$pay_no,$order_info['price_total'],$notify_url,'JSAPI',$user_info['openid']);
+                if($config){
+                    Db::commit();
+                }else{
+                    Db::rollback();
+                }
+            }catch (\Exception $e){
+                Db::rollback();
+                $msg = $e->getMessage();
+            }
+            if($config){
+                $this->success('ok',['type'=>1,'jump'=>1,'config'=>$config]);
+            }else{
+                $this->error($msg);
+            }
+        }
+
+    }
+
+    /**
+     * @title 获取订单列表
+     * @desc  获取订单列表
+     * @author  qc
+     * @url /api/Order/getMyOrderList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int  : default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @param  name:status type:int  : default:-1 desc:订单状态(-1全部,0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,9取消)
+     * @return name:order_no type:string default:-- desc:订单号
+     * @return name:pay_state type:int default:-- desc:支付状态(0未支付,1已支付)
+     * @return name:price_total type:float default:-- desc:订单金额
+     * @return name:pro_info type:float default:-- desc:订单详情
+     * @return name:pro_info.goods_id type:int default:-- desc:商品id
+     * @return name:pro_info.goods_name type:int default:-- desc:商品名
+     * @return name:pro_info.goods_no type:string default:-- desc:商品货号
+     * @return name:pro_info.sell_money type:string default:-- desc:售价
+     * @return name:pro_info.spec_img type:string default:-- desc:封面
+     * @return name:pro_info.is_evaluate type:string default:-- desc:商品是否评价
+     * @return name:pay_at type:string default:-- desc:支付时间
+     * @return name:create_at type:string default:-- desc:订单创建时间
+     * @return name:remark type:string default:-- desc:备注
+     * @return name:cancel_at type:string default:-- desc:取消时间(status=9)
+     * @return name:cancel_desc type:string default:-- desc:取消描述(status=9)
+     * @return name:refund_type type:int default:-- desc:订单申请退款、退换货状态0未申请,1申请
+     * @return name:source type:int default:0 desc:订单来源:0商城,1积分商城
+     * @return name:integral type:int default:0 desc:使用多少积分
+     * @return name:int_cash type:int default:0 desc:积分抵扣多少金额
+     * @return name:cl_id type:int default:0 desc:使用优惠券的id
+     * @return name:coupon_cash type:float default:0 desc:券抵扣金额
+     */
+    public function getMyOrderList()
+    {
+        $status  = input('status',-1);
+        $where=[];
+        if($status > -1) $where['o.status'] = $status;
+        $where['o.uid'] = $this->uid;
+        $where['o.is_deleted'] = 0;
+        $list = Db::table('store_order o')
+            ->field('o.id,o.order_no,o.pay_state,o.create_at,pay_at,pro_info,o.price_total,o.remark,source,integral')
+            ->where($where)
+            ->order('o.id desc')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+      /*  foreach ($list as &$v)
+        {
+            $v['pro_info'] = json_decode($v['pro_info'],true);
+        }*/
+        $this->success('获取成功',$list);
+
+    }
+
+
+    /**
+     * @title 删除订单
+     * @desc  删除订单
+     * @author  qc
+     * @url /api/Order/delOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1  default:1 desc:订单id
+     */
+    public function delOrder()
+    {
+        $order_id = input('post.id');
+        $order_info = Db::table('store_order')
+            ->where(['uid'=>$this->uid,'is_deleted'=>0,'id'=>$order_id])
+            ->find();
+        if(empty($order_info)) $this->error('订单不存在');
+        Db::table('store_order')->where(['id'=>$order_id])->update(['is_deleted'=>1]);
+        $this->success('删除成功');
+    }
+
+    /**
+     * @title 确认收货
+     * @desc  确认收货
+     * @author  qc
+     * @url /api/Order/confirmReceipt
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1  default:1 desc:订单id
+     */
+    public function confirmReceipt(){
+        $order_info = Db::table('store_order')
+            ->where(['uid'=>$this->uid,'id'=>input('post.id')])
+            ->find();
+        if(empty($order_info) || !$order_info['status'] != 2) $this->error('商品未发货');
+        Db::table('store_order')->where(['id'=>$order_info['id']])->update(['status'=>3]);
+        $this->success('收货成功');
+    }
+
+
+    /**
+     * @title 订单商品评论
+     * @desc  订单商品评论
+     * @author  qc
+     * @url /api/Order/orderEvaluate
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:order_id type:int  require:1  default:-- desc:订单order_id
+     * @param  name:goods_id type:int  require:1  default:-- desc:商品id
+     * @param  name:goods_no type:int  require:1  default:-- desc:商品货号
+     * @param  name:goods_score type:int  require:1  default:-- desc:商品评分
+     * @param  name:content type:string  require:1  default:-- desc:评论内容
+     * @param  name:images type:int  require:1  default:-- desc:图片(多张逗号隔开)
+     */
+    public function  orderEvaluate()
+    {
+        $order_id       = input('post.order_id');
+        $goods_id       = input('post.goods_id');
+        $goods_no       = input('post.goods_no');
+        $goods_score    = input('post.goods_score');
+        $images         = input('post.images');
+        $content        = input('post.content');
+        $eva_data =[
+            'order_id'      => $order_id,
+            'goods_id'      => $goods_id,
+            'goods_no'      => $goods_no,
+            'goods_score'   => $goods_score,
+            'images'        => $images,
+            'content'       => $content,
+        ];
+        Db::table('goods_evaluate')->insert($eva_data);
+        $order_info =  Db::table('order_goods')->where(['id'=>$order_id])->find();
+        $pro_info = json_decode($order_info['pro_info'],true);
+        foreach ($pro_info as $pk=>$pv) {
+            if($pv['goods_id'] == $goods_id  && $pv['goods_no'] == $goods_no) {
+                $pro_info[$pk]['is_evaluate'] = 1;
+            }
+        }
+        Db::table('order_goods')->where(['id'=>$order_id])->update(['status'=>4,'pro_info'=>json_encode($pro_info)]);
+    }
+
+
+
+    /**
+     * @title 退款部分
+     * @desc 退款部分
+     */
+    public function refundPart(){}
+
+
+    /**
+     * @title 获取平台退款原因
+     * @desc  获取平台退款原因
+     * @author  qc
+     * @url /api/Order/getRefundCause
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @return name:id type:int default:-- desc:记录id
+     * @return name:title type:string default:-- desc:退款原因描述
+     */
+    public function getRefundCause(){
+        $list = get_refund_cause();
+        $this->success('ok',['list'=>$list]);
+    }
+
+
+    /**
+     * @title 提交订单退款
+     * @desc  提交订单退款
+     * @author  qc
+     * @url /api/Order/refundOrder
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:order_id type:int  require:1 default:1 desc:订单id
+     * @param  name:cause_id type:int  require:1 default:1 desc:退款原因id
+     * @param  name:apply_type type:int  require:1 default:1 desc:申请类型 1退款,2退货退款
+     * @param  name:apply_money type:float  require:1 default:1 desc:申请退回金额
+     * @param  name:re_desc type:string  require:0 default:-- desc:描述
+     * @param  name:re_images type:string  require:0 default:-- desc:退款图片最多三张(多张用逗号隔开)
+     * @return  name:re_id type:int require:0 default:0 desc:成功时返回退款记录id
+     */
+    public function refundOrder()
+    {
+        $order_id = input('post.order_id');
+        $cause_id = input('post.cause_id');
+        $apply_type = input('post.apply_type',1);
+        $apply_money = input('post.apply_money');
+        $re_desc = input('post.re_desc');
+        $re_images = input('post.re_images');
+        $ck_refund = Db::table('order_refund')
+            ->where(['order_id'=>$order_id,'ck_status'=>0])
+            ->value('id');
+        if($ck_refund)  $this->error('审核中,请勿重新申请');
+        $ref_data = [
+            'uid' => $this->uid,
+            'order_id' => $order_id,
+            'apply_type' => $apply_type,
+            'apply_money' => $apply_money,
+            'create_at' => date("Y-m-d H:i:s"),
+            'cause_id' => $cause_id,
+            're_desc' => $re_desc,
+            're_images' => $re_images,
+        ];
+        Db::table('order_refund')->insert($ref_data);
+        $re_id = Db::getLastInsID();
+        // 更新订单表退款申请状态
+        Db::table('store_order')->where('id',$order_id)->update(['refund_state'=>1]);
+        $this->success('ok',['re_id'=>$re_id]);
+    }
+
+    /**
+     * @title 获取提交订单退款详情
+     * @desc  获取提交订单退款详情
+     * @author  qc
+     * @url /api/Order/getRefundInfo
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1 default:1 desc:退款记录id
+     * @return  name:cause_id type:int   default:1 desc:退款原因id
+     * @return  name:apply_type type:int  default:1 desc:申请类型 1退款,2退货退款
+     * @return  name:apply_money type:float   default:1 desc:申请退回金额
+     * @return  name:create_at type:string   default:1 desc:申请时间
+     * @return  name:re_desc type:string   default:-- desc:描述
+     * @return  name:re_images type:string   default:-- desc:退款图片
+     * @return  name:pro_info type:string   default:-- desc:申请订单的商品详情
+     * @return  name:pro_info.goods_id type:int default:-- desc:商品id
+     * @return  name:pro_info.goods_no type:string default:-- desc:商品货号
+     * @return  name:pro_info.sell_money type:string default:-- desc:售价
+     * @return  name:pro_info.spec_img type:string default:-- desc:封面
+     * @return  name:pro_info.is_evaluate type:string default:-- desc:商品是否评价
+     * @return  name:goods_num type:string   default:-- desc:购买的商品数量
+     * @return  name:ck_status type:int  default:0 desc:审核状态(0待审核 ,1 审核通过 , 2 审核不通过),
+     * @return  name:refund_money type:float  default:0 desc:审核退款金额,
+     * @return  name:refund_state type:int  default:0 desc:同意退款后的退款状态(0未退款,1待退款,2已退款,3退款失败)
+     * @return  name:refund_desc type:int  default:0 desc:退款描述
+     * @return  name:wl_no type:string  default:0 desc:退货物流单号 ( apply_type = 2)
+     * @return  name:wl_company type:string  default:0 desc:退货物流公司( apply_type = 2)
+     */
+    public function getRefundInfo()
+    {
+        $id = input('post.id');
+        $detail = Db::table('order_refund')
+            ->field('r.*,o.pro_info,o.goods_num')
+            ->alias('r')
+            ->join('store_order o','r.order_id = o.id','LEFT')
+            ->where(['r.order_id'=>$id])
+            ->find();
+        $re_cause = get_refund_cause();
+        $detail['refund_desc'] = array_column($re_cause,null,'id')[$detail['cause_id']]['title'];
+        $this->success('ok',['refund_detail'=>$detail]);
+    }
+
+    /**
+     * @title 完善退货物流信息
+     * @desc  完善退货物流信息
+     * @author  qc
+     * @url /api/Order/completeLogistics
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1  default:-- desc:退款记录id
+     * @param  name:wl_no type:string require:1  default:-- desc:物流单号
+     * @param  name:wl_company type:string  require:1 default:1 desc:物流公司
+     */
+    public function completeLogistics()
+    {
+        $id = input('post.id');
+        $wl_no = input('post.wl_no');
+        $wl_company = input('post.wl_company');
+        $info =   $detail = Db::table('order_refund')->find($id);
+        if($info['apply_type'] == 1) $this->error('申请类型不符合,无需物流信息');
+        // 更新物流信息
+        Db::table('order_refund')->where(['id'=>$id])->update(['wl_no'=>$wl_no,'wl_company'=>$wl_company]);
+        $this->success('ok');
+    }
+
+    /**
+     * @title 修改订单退款(退货)申请信息
+     * @desc   修改订单退款(退货)申请信息
+     * @author  qc
+     * @url /api/Order/modifyRefundInfo
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1  default:1 desc:需要修改的退款申请id
+     * @param  name:cause_id type:int  require:1  default:1 desc:退款原因id
+     * @param  name:apply_type type:int   require:1 default:1 desc:申请类型 1退款,2退货退款
+     * @param  name:apply_money type:float   require:1 default:1 desc:申请退回金额
+     * @param  name:re_desc type:string   default:-- desc:描述
+     * @param  name:re_images type:string   default:-- desc:退款图片最多三张(多张用逗号隔开)
+     * @param  name:wl_no  type:string   default:-- desc:物流单号
+     * @param  name:wl_company type:string   default:1 desc:物流公司
+     */
+    public function modifyRefundInfo()
+    {
+        $id = input('post.id');
+        $detail = Db::table('order_refund')->find($id);
+        if($detail['ck_status'] != 0) $this->error('已审核无法修改,请重新提交');
+        $up_data = [];
+        if(input('post.cause_id')) $up_data['cause_id'] = input('post.cause_id');
+        if(input('post.apply_type')) $up_data['apply_type'] = input('post.apply_type');
+        if(input('post.apply_money')) $up_data['apply_money'] = input('post.apply_money');
+        if(input('post.re_desc')) $up_data['re_desc'] = input('post.re_desc');
+        if(input('post.re_images')) $up_data['re_images'] = input('post.re_images');
+        if(input('post.wl_no')) $up_data['wl_no'] = input('post.wl_no');
+        if(input('post.wl_company')) $up_data['wl_company'] = input('post.wl_company');
+        if(!empty($up_data)) {
+            Db::table('order_refund')->where(['id'=>$id])->update($up_data);
+        }
+        $this->success('修改成功');
+    }
+
+    /**
+     * @title 取消申请退款(退货)
+     * @desc  取消申请退款(退货)
+     * @author  qc
+     * @url /api/Order/cancelRefund
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:order_id type:int  require:1  default:1 desc:订单id
+     */
+    public function cancelRefund(){
+        $order_id = input('post.order_id');
+        $re_info = Db::table('order_refund')->where(['uid'=>$this->uid,'order_id'=>$order_id,'ck_status'=>0])->count();
+        if(!$re_info) $this->error('退款记录不存在');
+        // 删除记录
+        Db::table('order_refund')->where(['order_id'=>$order_id,'ck_status'=>0])->delete();
+        $ck = Db::table('order_refund')->where(['order_id'=>$order_id])->find();
+        $stat = empty($ck) ? 0 : 2 ;
+        Db::table('store_order')->where(['id'=>$order_id])->update(['refund_state'=>$stat]);
+    }
+
+    /**
+     * @title 获取提交订单退款列表 ???
+     * @desc  获取提交订单退款列表 ???
+     */
+    public function getRefundList()
+    {
+
+    }
+
+
+
+
+
+}

+ 383 - 0
application/api/controller/Pay.php

@@ -0,0 +1,383 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\api\controller;
+use EasyWeChat\Factory;
+use think\Controller;
+use think\Db;
+use think\Exception;
+use app\api\controller\Evaluate;
+
+
+use AlibabaCloud\Client\AlibabaCloud;
+use AlibabaCloud\Client\Exception\ClientException;
+use AlibabaCloud\Client\Exception\ServerException;
+/**
+ * 支付管理类
+ * Class Refund
+ * @package app\api\controller\Refund
+ */
+class Pay extends Controller
+{
+    //小程序微信支付(type为1时是货主端微信配置,type为2时是接单端微信配置)
+    public static function wxPay($name='订单支付',$out_trade_no,$total_fee,$notify_url,$trade_type = 'JSAPI',$openid,$type = 1){
+        try{
+            if(empty($out_trade_no) || empty($total_fee) || empty($notify_url)) return false;
+            if($type == 1){
+                $app = Factory::payment(config('app.wx_pay'));
+            }else{
+                $app = Factory::payment(config('app.worker_wx_pay'));
+            }
+            $parameter = array(
+                'body' => $name,
+                'out_trade_no' => $out_trade_no,
+                'total_fee' => $total_fee*100,
+                'notify_url' => $notify_url, // 支付结果通知网址,如果不设置则会使用配置里的默认地址
+                'trade_type' => $trade_type, // 请对应换成你的支付方式对应的值类型
+            );
+            if($trade_type != 'APP'){
+                $parameter['openid'] = $openid;
+            }
+            $result = $app->order->unify($parameter);
+            $jssdk = $app->jssdk;
+            $config = $jssdk->sdkConfig($result['prepay_id']);
+            return $config;
+        }catch (Exception $e){
+            return false;
+        }
+    }
+
+    /**
+     * 抽奖订单回调
+     */
+    public function goodsOrderNotify()
+    {
+        $app = Factory::payment(config('app.wx_pay'));
+        $response = $app->handlePaidNotify(function ($message, $fail) {
+            $this->payResultLog($message,'goods_order');
+            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
+            $pay_no = $message['out_trade_no'];
+            $order_info = Db::name('goods_order')->where('pay_no',$pay_no)->find();
+            // 如果订单不存在 或者 订单已经支付过了  告诉微信,我已经处理完了,订单没找到,别再通知我了
+            if ($message['result_code'] == 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
+                $goods_info = Db::table('store_goods')->find($order_info['goods_id']);
+                $spec = json_decode($goods_info['spec'],true);
+                // 抽奖
+                $draw_data = draw_lottery($spec,'store_num',$order_info['goods_num']);
+                $magic_data = [];// 魔玩柜数据
+                $magic_day = intval(sysconf('magic_days'));// 获取设置天数
+                foreach ($draw_data as $k=>$n) {
+                    $spec[$k]['store_num'] -= $n;
+                    $magic_data[]=[
+                        'order_id' => $order_info['id'],
+                        'goods_id' => $goods_info['id'],
+                        'user_id' => $order_info['uid'],
+                        'create_at' => date('Y-m-d H:i:s'),
+                        'num' => $n,
+                        'base_num' => $n,
+                        'crystal' => $spec[$k]['crystal'],
+                        'case_name' => $spec[$k]['award_name'],
+                        'case_cover' => $spec[$k]['spec_img'],
+                        'past_at'   =>  date('Y-m-d H:i:s',strtotime("+$magic_day days")),
+                        'past_int'   => strtotime("+$magic_day days"),
+                    ];
+                }
+                $magic_draw = [];// 待抽将数据
+                foreach ($magic_data as $mv)
+                {
+                    for ($i=0;$i< $mv['base_num'];$i++ ) {
+                        $magic_draw[]=[
+                            'order_id' => $order_info['id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' => $order_info['uid'],
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'status' => 0,
+                            'award_status' => 1,
+                            'award_name' => $mv['case_name'],
+                            'award_cover' => $mv['case_cover'],
+                        ];
+                    }
+                }
+
+                Db::startTrans();
+                // 更新商品库存
+                Db::table('store_goods')->where('id',$order_info['goods_id'])->update(['spec'=>json_encode($spec)]);
+                // 魔玩柜
+                Db::table('magic_case')->insertAll($magic_data);
+                // 抽奖数据
+                Db::table('magic_draw')->insertAll($magic_draw);
+
+                // 特殊奖励
+                $special_award = json_decode($goods_info['special_award'],true);
+                $special_point = $goods_info['special_point'];
+                $front_court  = $special_award[0];// 前场设置
+                $back_court  = $special_award[1]; // 后场设置
+                $is_draw = 0;
+                // 前场未抽奖
+                if($front_court['is_over'] == 0) {
+                    $front_magic = Db::table('magic_draw')
+                        ->field('id,user_id,order_id')
+                        ->where(['goods_id'=>$goods_info['id'],'status'=>0,'is_special'=>0])
+                        ->limit(0,$special_point)
+                        ->order('id asc')
+                        ->select();
+                    // 前场抽奖次数达到前场抽奖节点
+                    if(count($front_magic) ==  $special_point) {
+                        $is_draw = 1;
+                        $special_award[0]['is_over'] = 1;// 前场抽奖完成标识
+                        $rand_id = array_rand($front_magic,1);// 中奖记录ids
+                        $front_user = $front_magic[$rand_id]['user_id']; // 中奖会员id
+                        $last_id = $front_magic[count($front_magic)-1]['id'];
+                        // 中奖记录插入魔玩柜
+                        $front_case = [
+                            'order_id' => $front_magic[$rand_id]['order_id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' => $front_user,
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'num' => 1,
+                            'base_num' => 1,
+                            'source'    => 1,
+                            'crystal' => $front_court['crystal'],
+                            'case_name' => $front_court['goods'],
+                            'case_cover' =>$front_court['cover'],
+                            'past_at'   =>  date('Y-m-d H:i:s',strtotime("+$magic_day days")),
+                            'past_int'   => strtotime("+$magic_day days"),
+                        ];
+                        Db::table('magic_case')->insert($front_case);
+
+                        $special_award1 = [
+                            'order_id' => $order_info['id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' =>  $front_user,
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'status' => 1,
+                            'award_status' => 0,
+                            'award_name' => $front_court['goods'],
+                            'award_cover' =>$front_court['cover'],
+                            'is_special' => 1
+                        ];
+
+                        Db::table('magic_draw')->insert($special_award1);
+                        // 更新抽奖记录
+                        Db::table('magic_draw')
+                            ->where('goods_id','=',$goods_info['id'])->where('id','<=', $last_id)
+                            ->where('id','<>',$front_magic[$rand_id]['id'])
+                            ->where('status','=',0)
+                            ->where('is_special','=',0)
+                            ->update(['status'=>1]);
+                        Db::table('magic_draw')
+                            ->where('id','=', $front_magic[$rand_id]['id'])
+                            ->where('status','=',0)
+                            ->where('is_special','=',0)
+                            ->update(['status'=>1,'award_status'=>2]);
+                        // 生成消息记录
+                        send_user_message($front_user,1,'恭喜您被大奖砸中!获得商品:'.$front_court['goods']);
+                    }
+                }
+                // 后场未抽奖 && 商品售罄
+                if( $special_award[0]['is_over'] ==1 && $back_court['is_over'] == 0 && $goods_info['stock'] == 0){
+                    $back_num = $goods_info['base_stock'] - $special_point;
+                    $back_magic = Db::table('magic_draw')
+                        ->field('id,user_id,order_id')
+                        ->where(['goods_id'=>$goods_info['id'],'status'=>0,'is_special'=>0])
+                        ->limit(0,$back_num)
+                        ->order('id asc')
+                        ->select();
+                    if($back_num == count($back_magic)) {
+                        $is_draw = 1;
+                        $special_award[1]['is_over'] = 1;// 后场抽奖完成标识
+                        $rand_id = array_rand($back_magic,1);// 中奖记录id
+                        $back_user = $back_magic[$rand_id]['user_id']; // 中奖会员id
+                        $back_case = [
+                            'order_id' => $back_magic[$rand_id]['order_id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' => $back_user,
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'num' => 1,
+                            'base_num' => 1,
+                            'source'    => 2,
+                            'crystal' => $back_court['crystal'],
+                            'case_name' => $back_court['goods'],
+                            'case_cover' =>$back_court['cover'],
+                            'past_at'   =>  date('Y-m-d H:i:s',strtotime("+$magic_day days")),
+                            'past_int'   => strtotime("+$magic_day days"),
+                        ];
+                        Db::table('magic_case')->insert($back_case);
+
+                        $special_award2 = [
+                            'order_id' => $order_info['id'],
+                            'goods_id' => $goods_info['id'],
+                            'user_id' => $back_user,
+                            'create_at' => date('Y-m-d H:i:s'),
+                            'status' => 1,
+                            'award_status' => 0,
+                            'award_name' => $back_court['goods'],
+                            'award_cover' =>$back_court['cover'],
+                            'is_special' => 1
+                        ];
+                        Db::table('magic_draw')->insert($special_award2);
+
+                        // 更新抽奖记录
+                        Db::table('magic_draw')
+                            ->where('goods_id','=',$goods_info['id'])->where('status','=', 0)
+                            ->where('id','<>',$back_magic[$rand_id]['id'])
+                            ->where('is_special','=',0)
+                            ->update(['status'=>1]);
+                        Db::table('magic_draw')->where('id','=', $back_magic[$rand_id]['id'])
+                            ->where('is_special','=',0)
+                            ->update(['status'=>1,'award_status'=>3]);
+                        // 生成消息记录
+                        send_user_message($back_user,1,'恭喜您被大奖砸中!!获得商品:'.$back_court['goods']);
+                    }
+                }
+                // 更新商品抽奖详情
+                if($is_draw) Db::table('store_goods')->where('id',$goods_info['id'])->update(['special_award'=>json_encode($special_award)]);
+
+                // 更新订单状态
+                $res = Db::table('goods_order')->where('id',$order_info['id'])
+                    ->update(['pay_time'=>date('Y-m-d H:i:s'),'pay_state'=>1,'pay_type'=>1,'status'=>1]);
+                if(!$res){
+                    Db::rollback();
+                }else{
+                    Db::commit();
+                }
+                return true; // 返回处理完成
+            } else if ($message['return_code'] != 'SUCCESS'){
+                return $fail('通信失败,请稍后再通知我');
+            }
+        });
+        $response->send();
+    }
+
+    /**
+     * 魔玩柜订单回调
+     */
+    public function magicOrderNotify()
+    {
+        $app = Factory::payment(config('app.wx_pay'));
+        $response = $app->handlePaidNotify(function ($message, $fail) {
+            $this->payResultLog($message,'magic_order');
+            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
+            $pay_no = $message['out_trade_no'];
+            $order_info = Db::name('magic_order')->where('pay_no',$pay_no)->find();
+            // 如果订单不存在 或者 订单已经支付过了  告诉微信,我已经处理完了,订单没找到,别再通知我了
+            if ($message['result_code'] == 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
+                Db::startTrans();
+                // 更新订单状态
+                $res = Db::table('magic_order')->where('id',$order_info['id'])
+                    ->update(['pay_time'=>date('Y-m-d H:i:s'),'pay_state'=>1,'pay_type'=>1,'status'=>1]);
+                if(!$res){
+                    Db::rollback();
+                }else{
+                    Db::commit();
+                }
+                return true; // 返回处理完成
+            } else if ($message['return_code'] != 'SUCCESS'){
+                return $fail('通信失败,请稍后再通知我');
+            }
+        });
+        $response->send();
+    }
+
+
+    /**
+     *水晶充值
+     */
+    public function crystalRecharge()
+    {
+        $app = Factory::payment(config('app.wx_pay'));
+        $response = $app->handlePaidNotify(function ($message, $fail) {
+            $this->payResultLog($message,'crystal_order');
+            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
+            $pay_no = $message['out_trade_no'];
+            $order_info = Db::name('crystal_order')->where('pay_no',$pay_no)->find();
+            // 如果订单不存在 或者 订单已经支付过了  告诉微信,我已经处理完了,订单没找到,别再通知我了
+            if ($message['result_code'] == 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
+                Db::startTrans();
+                $user_info = Db::table('store_member')->find($order_info['uid']);
+                // 更新会员余额
+                Db::table('store_member')->where('id',$order_info['uid'])->update(['crystal_cash'=>bcadd($user_info['crystal_cash'],$order_info['crystal'],2)]);
+                // 水晶明细
+                crystal_log($order_info['uid'],$order_info['crystal'],'水晶充值',2,$order_info['id']);
+                // 更新订单状态
+                $res = Db::table('crystal_order')->where('id',$order_info['id'])
+                    ->update(['pay_at'=>date('Y-m-d H:i:s'),'pay_state'=>1,'pay_type'=>1,'status'=>1]);
+                if(!$res){
+                    Db::rollback();
+                }else{
+                    Db::commit();
+                }
+                return true; // 返回处理完成
+            } else if ($message['return_code'] != 'SUCCESS'){
+                return $fail('通信失败,请稍后再通知我');
+            }
+        });
+        $response->send();
+    }
+
+
+    /**
+     * 兑换订单回调
+     */
+    public function exchangeOrderNotify(){
+        $app = Factory::payment(config('app.wx_pay'));
+        $response = $app->handlePaidNotify(function ($message, $fail) {
+            $this->payResultLog($message,'exchange_order');
+            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
+            $pay_no = $message['out_trade_no'];
+            $order_info = Db::name('exchange_order')->where('pay_no',$pay_no)->find();
+            // 如果订单不存在 或者 订单已经支付过了  告诉微信,我已经处理完了,订单没找到,别再通知我了
+            if ($message['result_code'] == 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
+                Db::startTrans();
+                // 更新订单状态
+                $res = Db::table('exchange_order')->where('id',$order_info['id'])
+                    ->update(['pay_time'=>date('Y-m-d H:i:s'),'pay_state'=>1,'status'=>1]);
+                if(!$res){
+                    Db::rollback();
+                }else{
+                    Db::commit();
+                }
+                return true; // 返回处理完成
+            } else if ($message['return_code'] != 'SUCCESS'){
+                return $fail('通信失败,请稍后再通知我');
+            }
+        });
+        $response->send();
+    }
+
+
+    /**
+     * 记录支付日志
+     * @param $message
+     * @param $table_name
+     */
+    public function payResultLog($message,$table_name)
+    {
+        // 回调记录
+        $ret_arr = [];
+        $ret_arr['transaction_id'] =    isset($message['transaction_id']) ?$message['transaction_id']: '';
+        $ret_arr['trade_no'] =          isset($message['out_trade_no']) ?$message['out_trade_no']: '';
+        $ret_arr['return_code'] =       isset($message['return_code']) ?$message['return_code']: '';
+        $ret_arr['result_code'] =       isset($message['result_code']) ?$message['result_code']: '';
+        $ret_arr['create_at'] =         date('Y-m-d H:i:s');
+        $ret_arr['order_table'] =       $table_name;
+        $ret_arr['result'] =            json_encode($message);
+        Db::table('order_pay_result')->insert($ret_arr);
+    }
+
+
+
+
+}

+ 104 - 0
application/api/controller/Qc.php

@@ -0,0 +1,104 @@
+<?php
+
+namespace app\api\controller;
+use app\api\controller\WeChart;
+
+use EasyWeChat\Factory;
+use Firebase\JWT\JWT;
+use think\Db;
+class Qc extends Base {
+
+    public function index()
+    {
+        Db::startTrans();
+        $goods_info = Db::table('store_goods')->find(15);
+        Db::table('store_goods')->where(['id'=>$goods_info['id']])->setDec('stock',1);
+        sleep(15);
+        Db::commit();
+    }
+
+    public function index2()
+    {
+        Db::startTrans();
+        $goods_info = Db::table('store_goods')->find(15);
+        Db::table('store_goods')->where(['id'=>$goods_info['id']])->setDec('stock',1);
+        Db::commit();
+    }
+
+
+
+    public function get_token(){
+        $uid = 17;
+        $key = md5(config('app.jwt')); //jwt的签发密钥,验证token的时候需要用到
+        $time = time(); //签发时间
+        $expire = $time + config('app.jwt_time'); //过期时间
+        $token = array(
+            "uid" => $uid,
+            "iss" => "https://zain.com",//签发组织
+            "aud" => "https://zain.com", //签发作者
+            "iat" => $time,
+            "nbf" => $time,
+            "exp" => $expire
+        );
+        $jwt = JWT::encode($token, $key);
+        var_dump($jwt);
+    }
+
+
+    /**
+     *
+     */
+    public function getProfit()
+    {
+        $goods_id = input('goods_id');
+        $where = [];
+        $where[] = ['id','>',0];
+        if($goods_id) $where[] = ['id','=',$goods_id];
+        $goods_arr = Db::table('store_goods')
+            ->where($where)
+            ->order('id desc')
+            ->select();
+        $data = [];
+        foreach ($goods_arr as $value)
+        {
+            $award = json_decode($value['spec'],true);
+            $award_crystal = 0;
+            $crystal = 0;
+            foreach ($award as $av) {
+                $award_crystal = bcadd($award_crystal,($av['base_num'] - $av['store_num']) * $av['crystal'] ,2);
+                $crystal =  bcadd($crystal,$av['base_num']  * $av['crystal'] ,2);
+            }
+            $cl = [
+                'goods_price' => $value['goods_price'],
+                'crystal' => $crystal,
+                'stock' => $value['stock'],
+                'award_crystal' => $award_crystal,
+                'sell_money' => bcmul($value['goods_price'],$value['base_stock']- $value['stock'],2),
+                'all_money' => bcmul($value['goods_price'],$value['base_stock'],2),
+                'profit' => bcmul($value['goods_price'],$value['base_stock']- $value['stock'],2) - $award_crystal,
+            ];
+            $data[$value['id']] =  $cl;
+        }
+        $data[0] = [
+            'goods_price' => '--统计的--',
+            'stock' => '----',
+            'crystal' => array_sum(array_column($data,'crystal')),
+            'award_crystal' => array_sum(array_column($data,'award_crystal')),
+            'sell_money' =>array_sum(array_column($data,'sell_money')),
+            'all_money' => array_sum(array_column($data,'all_money')),
+            'profit' => array_sum(array_column($data,'profit')),
+        ];
+        var_dump([
+            'goods_price'=>'商品售价',
+            'crystal'=>'水晶成本',
+            'award_crystal'=>'已中水晶',
+            'sell_money'=>'已售金额',
+            'all_money'=>'售完金额',
+            'profit'=>'利润',
+        ]);
+        var_dump($data);
+
+    }
+
+
+}

+ 75 - 0
application/api/controller/Timedtask.php

@@ -0,0 +1,75 @@
+<?php
+
+
+namespace app\api\controller;
+use AlibabaCloud\Client\AlibabaCloud;
+use AlibabaCloud\Client\Exception\ClientException;
+use AlibabaCloud\Client\Exception\ServerException;
+use think\Db;
+/**
+ * @title 定时任务
+ * Class Timedtask
+ * @controller Timedtask
+ * @group base
+ */
+class Timedtask
+{
+    /**
+     * @title 会员优惠券过期
+     * @desc  会员优惠券过期
+     * @author  qc
+     * @url /api/Timedtask/userCouponOver
+     * @method GET
+     */
+    public function userCouponOver()
+    {
+        user_coupon_over();
+    }
+
+    /**
+     * @title 取消订单定时任务
+     * @desc  十五分钟内未支付的自动取消
+     * @author  qc
+     * @url /api/Timedtask/goodsOrder
+     * @method GET
+     */
+    public function goodsOrder()
+    {
+       $sel_time = time() - 300;// 五分钟内未支付的自动取消
+       $order_data = Db::table('goods_order')
+           ->where('create_at','< time',date('Y-m-d H:i:s',$sel_time))
+           ->where('status','=',0)
+           ->where('cancel_state','=',0)
+           ->select();
+       foreach ($order_data as $order_info) {
+           Db::startTrans();
+           try {
+               Db::table('goods_order')->where(['id'=>$order_info['id']])
+                   ->update(['status'=>9,'cancel_state'=>1,'cancel_at'=>date('Y-m-d H:i:s'),'cancel_desc'=>'支付超时!自动取消']);
+               Db::table('store_goods')->where('id', $order_info['goods_id'])
+                   ->setInc('stock', $order_info['goods_num']);
+               Db::commit();
+           }catch (\Exception $e){
+               Db::rollback();
+           }
+       }
+
+    }
+
+
+
+    /**
+     * @title 分解魔玩柜
+     * @desc  十五分钟内未支付的自动取消
+     * @author  qc
+     * @url /api/Timedtask/resolveMagic
+     * @method GET
+     */
+    public function resolveMagic(){
+        resolve_magic();
+    }
+
+
+
+
+}

+ 151 - 0
application/api/controller/Upload.php

@@ -0,0 +1,151 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\api\controller;
+
+use app\common\controller\Api;
+use library\File;
+
+/**
+ * @title OSS对象存储
+ * @controller Upload
+ * @group common
+ */
+class Upload extends Base
+{
+    /**
+     * @title 文件上传
+     * @desc 文件上传
+     * @author qc
+     * @url /api/Upload/upload
+     * @method POST
+     * @tag 文件上传
+     */
+
+    public function upload()
+    {
+        if (!($file = $this->getUploadFile()) || empty($file)) {
+            $this->error('文件上传异常,文件可能过大或未上传!');
+        }
+        if (!$file->checkExt(strtolower(sysconf('storage_local_exts')))) {
+            $this->error('文件上传类型受限,请在后台配置!');
+        }
+        if ($file->checkExt('php,sh')) {
+            $this->error('可执行文件禁止上传到本地服务器!');
+        }
+        $this->safe = boolval(input('safe'));
+        $this->uptype = $this->getUploadType();
+        $this->extend = pathinfo($file->getInfo('name'), PATHINFO_EXTENSION);
+        $name = File::name($file->getPathname(), $this->extend, '', 'md5_file');
+        $info = File::instance($this->uptype)->save($name, file_get_contents($file->getRealPath()), $this->safe);
+        if (is_array($info) && isset($info['url'])) {
+            $url = $this->safe ? $name : $info['url'];
+            $this->success('成功',$url);
+        } else {
+            $this->error('文件处理失败,请稍候再试!');
+        }
+    }
+    /**
+     * 获取本地文件对象
+     * @return \think\File
+     */
+    private function getUploadFile()
+    {
+        try {
+            return $this->request->file('file');
+        } catch (\Exception $e) {
+            $this->error(lang($e->getMessage()));
+        }
+    }
+
+    /**
+     * 获取文件上传方式
+     * @return string
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    private function getUploadType()
+    {
+        $this->uptype = input('uptype');
+        if (!in_array($this->uptype, ['local', 'oss', 'qiniu'])) {
+            $this->uptype = sysconf('storage_type');
+        }
+        return $this->uptype;
+    }
+    /**
+     * @title 获取配置
+     * @desc 获取配置
+     * @author QGF
+     * @url /api/Upload/getSignedUrl
+     * @method GET
+     * @tag 配置信息
+     * @param name:type type:string require:1 default:-- desc:
+     */
+    public function getSignedUrl(){
+
+        $type=$this->request->get('type');
+        $data=$this->getPolicy($type.'/');
+        $this->success('操作成功',$data);
+    }
+    protected $id= 'LTAI5t8r1XP9hxwDzQgtrySn';
+    protected $key= 'tEeU0Qeae7djn99i81PaqHbHHkiDNj';
+    protected $host = 'http://mohuanxuanfeng.oss-cn-beijing.aliyuncs.com';
+
+    public function getPolicy($path,$maxSize=5000000){
+        $now = time();
+        $expire = 600; //设置该policy超时时间是10s. 即这个policy过了这个有效时间,将不能访问
+        $end = $now + $expire;
+        $expiration = $this->_gmt_iso8601($end);
+        $policy = [
+            'expiration'=>$expiration,
+            'conditions'=>[
+                ['content-length-range', 1, $maxSize],
+                ['starts-with', '$key', $path],
+            ]
+        ];
+        $policy = json_encode($policy);
+        $policy = base64_encode($policy);
+        $signature = base64_encode(hash_hmac('sha1', $policy, $this->key, true));
+
+        $response = array();
+        $response['OSSAccessKeyId'] = $this->id;
+        $response['policy'] = $policy;
+        $response['Signature'] = $signature;
+        $response['host'] = $this->host;
+        $response['expire'] = $end;
+        $response['success_action_status'] = 200;
+        //这个参数是设置用户上传指定的前缀
+        $response['key'] = $path;
+        return $response;
+    }
+    protected function _gmt_iso8601($time) {
+        $dtStr = date("c", $time);
+        $mydatetime = new \DateTime($dtStr);
+        $expiration = $mydatetime->format(\DateTime::ISO8601);
+        $pos = strpos($expiration, '+');
+        $expiration = substr($expiration, 0, $pos);
+        return $expiration."Z";
+    }
+
+
+    public function getSysDirection()
+    {
+        $data = [
+            'film_notice'=>htmlspecialchars_decode(sysconf('film_notice')),
+            'film_direction'=>htmlspecialchars_decode(sysconf('film_direction'))
+        ];
+        $this->success('获取成功',$data);
+    }
+}

+ 173 - 0
application/api/controller/Usercenter.php

@@ -0,0 +1,173 @@
+<?php
+namespace app\api\controller;
+use AlibabaCloud\Client\AlibabaCloud;
+use AlibabaCloud\Client\Exception\ClientException;
+use AlibabaCloud\Client\Exception\ServerException;
+use think\Db;
+/**
+ * @title 会员个人中心
+ * @controller Usercenter
+ * @group base
+ */
+class Usercenter extends Base
+{
+    public function initialize()
+    {
+        parent::check_login();
+    }
+
+    /**
+     * @title 获取个人信息
+     * @desc 个人信息
+     * @author qc
+     * @url /api/Usercenter/getUserInfo
+     * @method GET
+     * @tag 个人信息
+     * @header name:Authorization require:1 desc:Token
+     * @return name:phone type:int default:-- desc:手机号
+     * @return name:name type:string default:-- desc:姓名
+     * @return name:headimg type:string default:-- desc:头像地址
+     * @return name:crystal type:int default:-- desc:水晶(不可提现)
+     * @return name:crystal_cash type:string default:-- desc:水晶(可提现)
+     */
+    public function getUserInfo()
+    {
+        $uid = $this->uid;
+        $field = 'id,phone,name,headimg,status,crystal,crystal_cash';
+        $user_info = Db::name('store_member')->field($field)->where('id',$uid)->find();
+        if(empty($user_info)) $this->error('用户信息不正确');
+        if($user_info['status'] == 0) $this->error('该用户已被禁用');
+        $this->success('获取成功',$user_info);
+    }
+
+    /**
+     * @title 编辑个人信息
+     * @desc 编辑个人信息
+     * @author qc
+     * @url /api/Usercenter/updateUserInfo
+     * @method POST
+     * @tag 编辑信息
+     * @header name:Authorization require:1 desc:Token
+     * @param name:type type:int require:1 default:1 desc:修改的类型(1:昵称,2:头像)
+     * @param name:name type:string require:0 default:-- desc:昵称(type为1时必传)
+     * @param name:headimg type:string require:0 default:-- desc:头像地址(type为2时必传)
+     * @return name:phone type:int default:-- desc:手机号
+     * @return name:name type:string default:-- desc:姓名
+     * @return name:headimg type:string default:-- desc:头像地址
+     */
+    public function updateUserInfo()
+    {
+        $type     = input('post.type',1);
+        $headimg  = input('post.headimg');
+        $name     = input('post.name');
+        if(!in_array($type,[1,2])) $this->error('参数错误');
+        $update_data= [];
+        if($type == 1 && $name)       $update_data['name']    = $name;
+        if($type == 2 && $headimg)    $update_data['headimg'] = $headimg;
+        if(empty($update_data))   $this->error('参数错误');
+        Db::name('store_member')->where('id',$this->uid)->update($update_data);
+        $field = 'phone,name,headimg';
+        $user_info = Db::name('store_member')->field($field)->where('id',$this->uid)->find();
+        $this->success('编辑成功',$user_info);
+    }
+
+    /**
+     * @title 绑定手机号
+     * @desc  绑定手机号
+     * @author  qc
+     * @url /api/Usercenter/modifyPhone
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:phone type:int require:1 default:-- desc:手机号
+     * @param name:code type:int require:1 default:-- desc:手机号验证码
+     * @return name:phone type:int default:-- desc:手机号
+     * @return name:name type:string default:-- desc:姓名
+     * @return name:headimg type:string default:-- desc:头像地址
+     * @return name:password type:string default:-- desc:不加密
+     * @return name:decode_password type:string default:-- desc:加密后
+     */
+    public function modifyPhone()
+    {
+        $uid = $this->uid;
+        $phone = input('post.phone');
+        $code  = input('post.code');
+        if(empty($phone) || empty($code) ) $this->error('参数错误');
+        $store_member_sms = Db::name('store_member_sms')
+            ->field('id,code')->where('phone',$phone)
+            ->where('used',0)->order('id desc')
+            ->find();
+        if($store_member_sms['code'] != $code) $this->error('验证码错误');
+        //判断手机号是否已注册
+        $member_id = Db::name('store_member')->where('phone','=',$phone)->where('id','<>',$this->uid)->value('id');
+        if($member_id)  $this->error('手机号已注册过');
+        $up = ['phone'=>$phone];
+        $res = Db::name('store_member')->where('id',$uid)->update($up);
+        $field = 'phone,name,headimg,status,decode_password,password';
+        $user_info = Db::name('store_member')->field($field)->where('id',$this->uid)->find();
+        if($res !==false){
+            Db::name('store_member_sms')->where('id',$store_member_sms['id'])->update(['used'=>1]);
+            $this->success('绑定成功',$user_info);
+        }else{
+            $this->error('绑定失败');
+        }
+    }
+
+    /**
+     * @title 发送短信验证码
+     * @desc 发送短信验证码
+     * @author QGF
+     * @url /api/Usercenter/sendSms
+     * @method POST
+     * @tag 短信验证码
+     * @param name:phone type:int require:1 default:-- desc:要获取验证码的手机号
+     * @return name:code type:string default:-- desc:验证码
+     */
+    public function sendSms(){
+        $phone = input('post.phone');
+        if(empty($phone)) $this ->error('参数错误');
+        $code = rand(0,9).rand(0,9).rand(0,9).rand(0,9).rand(0,9).rand(0,9);
+        AlibabaCloud::accessKeyClient('LTAI5tSFmMzKUQC4zJjc3Guu', 'gdEyLTubu0KT6WzR26upX3dgiu5FD6')
+            ->regionId('cn-hangzhou')->asDefaultClient();
+        try {
+            $result = AlibabaCloud::rpc()
+                ->product('Dysmsapi')
+                ->version('2017-05-25')
+                ->action('SendSms')
+                ->method('POST')
+                ->host('dysmsapi.aliyuncs.com')
+                ->options([
+                    'query' => [
+                        'RegionId' => "cn-hangzhou",
+                        'PhoneNumbers' => $phone,
+                        'SignName' => "验证码",
+                        'TemplateCode' => "SMS_204845304",
+                        'TemplateParam' => json_encode(array("code"=>$code)),
+                    ],
+                ])->request();
+            $result = $result->toArray();
+            var_dump($result);
+            if($result['Code'] == "OK")
+            {
+                $sms_data = array(
+                    'phone'=>$phone,
+                    'code'=>$code,
+                    'result'=>$result['Message']
+                );
+                Db::name('store_member_sms')->insert($sms_data);
+                $this->error('发送成功',$code);
+            }else{
+                $this->error('发送失败');
+            }
+        } catch (ClientException $e) {
+            echo $e->getErrorMessage() . PHP_EOL;
+        } catch (ServerException $e) {
+            echo $e->getErrorMessage() . PHP_EOL;
+        }
+
+    }
+
+
+
+
+
+}

+ 300 - 0
application/api/controller/Usermanage.php

@@ -0,0 +1,300 @@
+<?php
+
+
+namespace app\api\controller;
+use think\Db;
+/**
+ * @title 会员管理
+ * @controller Usermanage
+ * @group base
+ */
+class Usermanage extends Base
+{
+    public function initialize()
+    {
+        parent::check_login();
+    }
+
+    /**
+     * @title 获取我的运费券
+     * @desc  获取我的运费券
+     * @author  qc
+     * @url /api/Usermanage/getMyCouponByStatus
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:sel_status type:int  : default:0 desc:0全部,1正常,2已使用,3过期
+     * @param  name:page type:int  : default:1 desc:页数
+     * @param  name:page_num type:int  : default:20 desc:每页数
+     * @return name:create_at type:float default:-- desc:领取(发放时间)
+     * @return name:status type:int default:-- desc:1正常,2已使用,3过期
+     * @return name:past_at type:string default:-- desc:到期时间
+     * @return name:used_time type:string default:-- desc:使用时间
+     */
+    public function getMyCouponByStatus()
+    {
+        user_coupon_over($this->uid);
+        $sel_status = input('sel_status');
+        $where['user_id'] = $this->uid;
+        if(in_array($sel_status,[1,2,3])) $where['status'] = $sel_status;
+        $list = Db::table('user_coupon_list')
+            ->where($where)
+            ->order('id desc')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('获取成功',['list'=>$list]);
+    }
+
+    /**
+     * @title 设置收货地址(新增或修改)
+     * @desc  设置收货地址(新增或修改)
+     * @author  qc
+     * @url /api/Usermanage/setDeliveryAddress
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  : default:0 desc:收货地址记录id(不传值是添加)
+     * @param  name:pro_name type:int  require:1  default:-- desc:省名
+     * @param  name:city_name type:int  require:1  default:-- desc:市名
+     * @param  name:county_name type:int  require:1  default:-- desc:县区名
+     * @param  name:detail type:string  require:1  default:-- desc:详细地址
+     * @param  name:phone type:string  require:1  default:-- desc:联系电话
+     * @param  name:name type:string  require:1  default:-- desc:联系人
+     * @param  name:is_mr type:int  require:0  default:0 desc:是否是默认(0不默认,1默认)
+     */
+    public function  setDeliveryAddress()
+    {
+        $pro_name     = input('post.pro_name');// 省
+        $city_name    = input('post.city_name');// 市
+        $county_name  = input('post.county_name');// 县区
+        $pro_id     = Db::table('store_area')->where('name',$pro_name)->value('id');
+        $city_id    = Db::table('store_area')->where('name',$city_name)->value('id');
+        $county_id  = Db::table('store_area')->where('name',$county_name)->value('id');
+        $detail     = input('post.detail');// 详细地址
+        $phone      = input('post.phone');
+        $name       = input('post.name');
+        $id         = input('post.id');
+        $is_mr      = input('post.is_mr',0);
+        $set_data =  compact(['pro_id','city_id','county_id','detail','phone','name','is_mr']);
+        $set_data['user_id']    = $this->uid;
+        $set_data['pro_name']   = $pro_name;
+        $set_data['city_name']  = $city_name;
+        $set_data['county_name']= $county_name;
+        $set_data['mer_name']=$pro_name . $city_name. $county_name;
+        if($id) {
+            Db::table('delivery_address')->where(['id'=>$id])->update($set_data);
+        }else{
+            Db::table('delivery_address')->insert($set_data);
+            $id = Db::getLastInsID();
+        }
+        if($is_mr) Db::table('delivery_address')->where('user_id','=',$this->uid)->where('id','<>',$id)->where('is_mr','=',1)->update(['is_mr'=>0]);
+        $this->success('编辑成功');
+    }
+
+    /**
+     * @title 修改默认收货地址
+     * @desc  修改默认收货地址
+     * @author  qc
+     * @url /api/Usermanage/changeApproveDelivery
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  : default:0 desc:收货地址记录id
+     * @param  name:is_mr type:int  default:1 desc:是否是默认(0不默认,1默认)
+     */
+    public function changeApproveDelivery()
+    {
+        $id         = input('post.id');
+        $is_mr      = input('post.is_mr',1);
+        if($is_mr) {
+            Db::table('delivery_address')
+                ->where('user_id','=',$this->uid)
+                ->where('is_mr','=',1)
+                ->update(['is_mr'=>0]);
+            Db::table('delivery_address')
+                ->where('user_id','=',$this->uid)
+                ->where('id','=',$id)
+                ->update(['is_mr'=>1]);
+        }else{
+            Db::table('delivery_address')
+                ->where('user_id','=',$this->uid)
+                ->where('id','=',$id)
+                ->update(['is_mr'=>0]);
+        }
+        $this->success('修改成功');
+    }
+
+
+    /**
+     * @title 删除收货地址
+     * @desc  删除收货地址
+     * @author  qc
+     * @url /api/Usermanage/delDeliveryAddress
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int  require:1 default:1 desc:收货地址记录id
+     */
+    public function delDeliveryAddress()
+    {
+        $id = input('post.id');
+        if(!$id)$this->error('请选择要删除的收货地址');
+        Db::table('delivery_address')->where(['user_id'=>$this->uid,'id'=>$id])->delete();
+        $this->success('删除成功!');
+    }
+
+    /**
+     * @title 获取收货地址列表
+     * @desc  获取收货地址列表
+     * @author  qc
+     * @url /api/Usermanage/getDeliveryAddressList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int   default:1 desc:页数
+     * @param  name:page_num type:int   default:20 desc:每页数
+     * @return name:pro_id type:int   default:-- desc:省id
+     * @return name:city_id type:int   default:-- desc:市id
+     * @return name:county_id type:int  default:-- desc:县区id
+     * @return name:pro_name type:string  default:-- desc:省名
+     * @return name:city_name type:string  default:-- desc:市名
+     * @return name:county_name type:string  default:-- desc:县区名
+     * @return name:detail type:string  default:-- desc:详细地址
+     * @return name:phone type:string  default:-- desc:联系电话
+     * @return name:name type:string   default:-- desc:联系人
+     * @return name:is_mr type:int   default:0 desc:是否是默认(0不默认,1默认)
+     */
+    public function getDeliveryAddressList()
+    {
+        $list = Db::table('delivery_address')
+            ->where(['user_id'=>$this->uid])
+            ->order('is_mr desc ,id desc')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('ok',['list'=>$list]);
+
+    }
+
+    /**
+     * @title 获取收货地址详情
+     * @desc  获取收货地址详情
+     * @author  qc
+     * @url /api/Usermanage/getDeliveryAddressDetail
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:id type:int   default:1 desc:收货地址记录id
+     * @return name:pro_id type:int   default:-- desc:省id
+     * @return name:city_id type:int   default:-- desc:市id
+     * @return name:county_id type:int  default:-- desc:县区id
+     * @return name:pro_name type:string  default:-- desc:省名
+     * @return name:city_name type:string  default:-- desc:市名
+     * @return name:county_name type:string  default:-- desc:县区名
+     * @return name:detail type:string  default:-- desc:详细地址
+     * @return name:phone type:string  default:-- desc:联系电话
+     * @return name:name type:string   default:-- desc:联系人
+     * @return name:is_mr type:int   default:0 desc:是否是默认(0不默认,1默认)
+     */
+    public function getDeliveryAddressDetail()
+    {
+        $detail  = Db::table('delivery_address')->find(input('id'));
+        $this->success('ok',$detail);
+    }
+
+
+    /**
+     * @title 获取水晶变更日志
+     * @desc  获取水晶变更日志
+     * @author  qc
+     * @url /api/Usermanage/getCrystalLog
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int   default:1 desc:页数
+     * @param  name:page_num type:int   default:20 desc:每页数
+     * @return name:create_at type:string   default:-- desc:时间
+     * @return name:crystal type:int   default:-- desc:变更数
+     * @return name:desc type:string   default:-- desc:描述
+     */
+    public function getCrystalLog()
+    {
+        $list = Db::table('crystal_info')
+            ->field('id,create_at,crystal,desc')
+            ->where(['user_id'=>$this->uid,'is_deleted'=>0])
+            ->order('id desc')
+            ->limit($this->off_set,$this->page_num)
+            ->select();
+        $this->success('ok',['list'=>$list]);
+    }
+
+
+    /**
+     * @title  获取推荐人信息
+     * @desc  获取推荐人信息
+     * @author  qc
+     * @url /api/Usermanage/getParentInfo
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @return name:name type:string default:-- desc:昵称
+     * @return name:headimg type:string default:-- desc:头像
+     * @return name:create_at type:string default:-- desc:注册时间
+     */
+    public function getParentInfo()
+    {
+        $pid = Db::table('store_member')->where('id',$this->uid)->value('pid');
+        $parent_info = [];
+        if($pid){
+            $parent_info=   Db::table('store_member')
+                ->field('id,name,headimg,create_at')
+                ->find($pid);
+        }
+        $this->success('ok',$parent_info);
+    }
+
+
+    /**
+     * @title  获取我邀请的会员列表
+     * @desc  获取我邀请的会员列表
+     * @author  qc
+     * @url /api/Usermanage/getMyInviteList
+     * @method GET
+     * @header name:Authorization require:1 desc:Token
+     * @param  name:page type:int   default:1 desc:页数
+     * @param  name:page_num type:int   default:20 desc:每页数
+     * @return name:name type:string default:-- desc:昵称
+     * @return name:headimg type:string default:-- desc:头像
+     * @return name:create_at type:string default:-- desc:注册时间
+     */
+    public function getMyInviteList()
+    {
+        $list = Db::table('store_member')
+            ->field('id,name,headimg,create_at')
+            ->where(['pid'=>$this->uid])
+            ->order('id desc')
+            ->limit($this->page,$this->page_num)
+            ->select();
+        $this->success('ok',$list);
+
+    }
+
+    /**
+     * @title 用户反馈
+     * @desc  用户反馈
+     * @author  qc
+     * @url /api/Usermanage/leaveFeedback
+     * @method POST
+     * @header name:Authorization require:1 desc:Token
+     * @param name:content type:string require:1 default:-- desc:反馈内容
+     * @param name:images type:string require:0 default:-- desc:反馈图片(逗号隔开,没有不传)
+     */
+    public function leaveFeedback()
+    {
+        $insert_data = [
+            'user_id'=>$this->uid,
+            'content'=>input('content'),
+            'images'=>input('images'),
+            'create_at'=>date('Y-m-d H:i:s')
+        ];
+        Db::table('user_feedback')->insert($insert_data);
+        $this->success('反馈成功',Db::getLastInsID());
+    }
+
+
+
+
+
+
+}

+ 74 - 0
application/api/controller/WeChart.php

@@ -0,0 +1,74 @@
+<?php
+namespace app\api\controller;
+use EasyWeChat\Factory;
+use  think\cache\driver\Redis;
+use  think\Session;
+class WeChart {
+
+    protected $app_id ='wx7a5f15ddeda9ef5a';
+    protected $app_secret = 'a4c33b42917949652c31447e42132de0';
+
+
+    /**
+     * 获取token
+     * @return mixed|string
+     */
+    public function  getAccessToken()
+    {
+        $session = new Session();
+        $over_time = $session->get('token_over_time');
+        if($over_time < time()) {
+            $url=  "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->app_id}&secret={$this->app_secret}";
+            $ret = http_curl($url);
+            $session->set('access_token',$ret['access_token']);
+            $session->set('token_over_time',time() +$ret['expires_in'] );
+        }
+        return  $session->get('access_token');
+    }
+
+
+    public function send_message($order_sn=''){
+
+        $url='https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token='.$access_token;
+        $order = Db::name('StoreOrder')->field('id,order_sn,create_at,num,take_time,user_id,goods_id')->where('order_sn',$order_sn)->find();
+        $member = Db::name('storeMember')->field('id,vip_level,openid,username,nickname')->where('id',$order['user_id'])->find();
+        $book_book = Db::name('book_book')->field('id,title')->where('id',$order['goods_id'])->find();
+        $data=[
+            'touser'=>$member['openid'],
+            'mp_template_msg'=>[
+                "appid"=>"wx3346d52f010b611d",
+                "template_id"=>"SH6KcRTVDiU0-7cSDujHsCg8MhbgzGpHb8US1QiPYW0",
+                "url"=>"http://www.baidu.com",
+                'miniprogram'=>[
+                    "appid"=>"wx2b03c73ff0547cc3",
+                ],
+                'data'=>[
+                    'first'=>[
+                        "value"=>'恭喜你已借阅到该图书',
+                        "color"=>"#173177"
+                    ],
+                    'keyword1'=>[
+                        "value"=>$book_book['title'],
+                        "color"=>"#173177"
+                    ],
+                    'keyword2'=>[
+                        "value"=>$member['username']?$member['username']:$member['nickname'],
+                        "color"=>"#173177"
+                    ],
+                    'keyword3'=>[
+                        "value"=>date('Y-m-d H:i:s',time()),
+                        "color"=>"#173177"
+                    ],
+                    'remark'=>[
+                        "value"=>'谢谢你对哩哈教育的支持!',
+                        "color"=>"#173177"
+                    ]
+                ]
+            ],
+        ];
+        $res = requestPost($url,json_encode($data));
+    }
+
+
+
+}

+ 302 - 0
application/common.php

@@ -0,0 +1,302 @@
+<?php
+use think\Db;
+/**
+ * 秒转换为天
+ */
+function get_stay_time($remain_time, $is_hour = 1, $is_minutes = 1)
+{
+    $day = floor($remain_time / (3600*24));
+    $day = $day > 0 ? $day.'天' : '';
+    $hour = floor(($remain_time % (3600*24)) / 3600);
+    $hour = $hour > 0 ? $hour.'小时' : '';
+    if($is_hour && $is_minutes) {
+        $minutes = floor((($remain_time % (3600*24)) % 3600) / 60);
+        $minutes = $minutes > 0 ? $minutes.'分钟' : '';
+        return $day.$hour.$minutes;
+    }
+
+    if($hour) {
+        return $day.$hour;
+    }
+    return $day;
+}
+//获取全图片地址 $image_data
+function image_path($image_data){
+    if(empty($image_data)){
+        return $image_data;
+    }
+    if (strpos($image_data,'|')!==false){
+        $image_res = explode('|',$image_data);
+    }elseif(strpos($image_data,',')!==false){
+        $image_res = explode(',',$image_data);
+    }else{
+        $image_res = array($image_data);
+    }
+    return $image_res;
+}
+
+
+
+/**
+ * 更新会员积分
+ * @param $user_id
+ * @param $integral
+ * @param $desc
+ * @param int $rel_id
+ * @throws \think\Exception
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @throws \think\exception\DbException
+ * @throws \think\exception\PDOException
+ */
+function update_user_integral($user_id,$integral,$type,$desc,$rel_id = 0)
+{
+    $user = Db::table('store_member')->find($user_id);
+    $integral_info=[
+        'user_id'=> $user_id,
+        'create_at'=> date("Y-m-d H:i:s"),
+        'integral'=> $integral,
+        'before'=> $user['integral'],
+        'after'=> $user['integral'] + $integral,
+        'type'=>$type,
+        'desc'=> $desc,
+        'rel_id'=> $rel_id,
+    ];
+    Db::table('integral_info')->insert($integral_info);
+    Db::table('store_member')->where(['id'=>$user_id])->update(['integral'=>$integral_info['after']]);
+}
+
+
+/**
+ * 更新会员成长值
+ * @param $user_id
+ * @param $growth
+ * @param $desc
+ * @throws \think\Exception
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @throws \think\exception\DbException
+ * @throws \think\exception\PDOException
+ */
+function update_user_growth($user_id,$growth,$type,$desc,$data = [])
+{
+    $growth_info=[
+        'user_id'=> $user_id,
+        'create_at'=> date("Y-m-d H:i:s"),
+        'growth'=> $growth,
+        'type'=>$type,
+        'desc'=> $desc,
+        'detail'=> json_encode($data),
+    ];
+    Db::table('member_level_growth')->insert($growth_info);
+    Db::table('store_member')->where(['id'=>$user_id])->setInc('growth',$growth);
+    $user = Db::table('store_member')->field('level_id,growth')->find($user_id);
+    $lev_set = Db::table('member_level')->select();
+    $lev_set = array_column($lev_set,null,'id');
+    if(isset($lev_set[$user['level_id']+1]) && $user['growth'] >= $lev_set[$user['level_id']+1]['growth']) {
+        $level_log = [
+            'user_id' => $user_id ,
+            'create_at' => date("Y-m-d H:i:s") ,
+            'before_lev' => $user['level_id'] ,
+            'after_lev' => $user['level_id']+1 ,
+            'desc' => '恭喜您成功晋级成为'.$lev_set[$user['level_id']+1]['name'].'会员!' ,
+        ];
+        Db::table('member_level_log')->insert($level_log);
+        Db::table('store_member')->where(['id'=>$user_id])->setInc('level_id',1);
+    }
+}
+
+
+/**
+ * 发放模板消息
+ */
+function send_message($openid){
+    $appid = 'wx2b03c73ff0547cc3';// 小程序
+    $secret = '02a04ccc1ee8646035964729597ae3f6';// 小程序
+    $ac = requestGet('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$secret);
+    $ac = json_decode($ac,true);
+    $access_token = $ac['access_token'];
+    $url='https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token='.$access_token;
+    $data=[
+        'touser'=>$openid,
+        'mp_template_msg'=>[
+            "appid"=>"wx3346d52f010b611d",// 公众号
+            "template_id"=>"SH6KcRTVDiU0-7cSDujHsCg8MhbgzGpHb8US1QiPYW0",// 公众号
+            "url"=>"http://www.baidu.com",
+            'miniprogram'=>[
+                "appid"=>"wx2b03c73ff0547cc3",// 小程序
+            ],
+            'data'=>[
+                'first'=>[
+                    "value"=>'',
+                    "color"=>"#173177"
+                ],
+                'keyword1'=>[
+                    "value"=>'',
+                    "color"=>"#173177"
+                ],
+                'keyword2'=>[
+                    "value"=>'',
+                    "color"=>"#173177"
+                ],
+                'keyword3'=>[
+                    "value"=>date('Y-m-d H:i:s',time()),
+                    "color"=>"#173177"
+                ],
+                'remark'=>[
+                    "value"=>'',
+                    "color"=>"#173177"
+                ]
+            ]
+        ],
+    ];
+    $res = requestPost($url,json_encode($data));
+}
+
+// 获取模板区域
+function get_city_area()
+{
+    $field=['id','pid','name'];
+    $list=Db::table('store_area')->where('pid',0)->field($field)->select();
+    foreach ($list as $k=>&$v){
+        $v['children']= Db::table('store_area')->where('pid',$v['id'])->field($field)->select();
+    }
+    return $list;
+}
+
+
+function http_curl($url,$type='get',$res='json',$arr=''){
+    //1.初始化curl
+    $ch = curl_init();
+    //2.设置curl的参数
+    curl_setopt($ch, CURLOPT_URL, $url);
+    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+    if($type == 'post'){
+        curl_setopt($ch, CURLOPT_POST,1);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $arr);
+    }
+    //3.采集
+    $output = curl_exec($ch);
+    //4.关闭
+    curl_close($ch);
+    if($res=='json'){
+        if($output === false){
+            //请求失败,返回错误信息
+            return curl_error($ch);
+        }else{
+            //请求成功,返回信息
+            return json_decode($output,true);
+        }
+    }
+}
+
+// 获取物流信息
+function get_delivery($send_no = 'JD0053309649641',$express_code=''){
+        error_reporting(E_ALL || ~E_NOTICE);
+        $AppKey     = 204008273;
+        $AppSecret  ='t9PavvfCeK5v2XidwyK5pWDp8b0hzMq4';
+        $AppCode    ='47f640e3529d43e28365311a530db2b7';//开通服务后 买家中心-查看AppCode
+        $host = "https://wuliu.market.alicloudapi.com";//api访问链接
+        $path = "/kdi";//API访问后缀
+        $method = "GET";
+        $body  ='';
+        $headers = array();
+        array_push($headers, "Authorization:APPCODE " . $AppCode);
+        $querys = "no={$send_no}&type={$express_code}";  //参数写在这里
+        $url = $host . $path . "?" . $querys;
+        $curl = curl_init();
+        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
+        curl_setopt($curl, CURLOPT_URL, $url);
+        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+        curl_setopt($curl, CURLOPT_FAILONERROR, false);
+        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($curl, CURLOPT_HEADER, true);
+        if (1 == strpos("$" . $host, "https://")) {
+            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
+        }
+        $out_put = curl_exec($curl);
+        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
+        list($header, $body) = explode("\r\n\r\n", $out_put, 2);
+        if ($httpCode == 200) {
+            return json_decode($body,true)['result'];
+        } else {
+            return [];
+           /* if ($httpCode == 400 && strpos($header, "Invalid Param Location") !== false) {
+                print("参数错误");
+            } elseif ($httpCode == 400 && strpos($header, "Invalid AppCode") !== false) {
+                print("AppCode错误");
+            } elseif ($httpCode == 400 && strpos($header, "Invalid Url") !== false) {
+                print("请求的 Method、Path 或者环境错误");
+            } elseif ($httpCode == 403 && strpos($header, "Unauthorized") !== false) {
+                print("服务未被授权(或URL和Path不正确)");
+            } elseif ($httpCode == 403 && strpos($header, "Quota Exhausted") !== false) {
+                print("套餐包次数用完");
+            } elseif ($httpCode == 500) {
+                print("API网关错误");
+            } elseif ($httpCode == 0) {
+                print("URL错误");
+            } else {
+                print("参数名错误 或 其他错误");
+                print($httpCode);
+                $headers = explode("\r\n", $header);
+                $headList = array();
+                foreach ($headers as $head) {
+                    $value = explode(':', $head);
+                    $headList[$value[0]] = $value[1];
+                }
+                print($headList['x-ca-error-message']);
+            }*/
+        }
+    }
+
+
+// 刷新页面
+function to_reload()
+{
+    if(input('reloaded') !=1) {
+        echo "<script>
+            location.href=location.href+'&reloaded=1';
+            location.reload();
+</script>";
+    }
+}
+
+// 水晶日志
+function crystal_log($user_id,$crystal,$desc,$type,$rel_id=0)
+{
+    $log_data = [
+        'user_id' => $user_id,
+        'create_at' => date('Y-m-d H:i:s'),
+        'crystal' => $crystal,
+        'desc' => $desc,
+        'type' => $type,
+        'rel_id' => $rel_id,
+    ];
+    Db::table('crystal_info')->insert($log_data);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 34 - 0
application/index/controller/Index.php

@@ -0,0 +1,34 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\index\controller;
+
+use library\Controller;
+
+/**
+ * 应用入口
+ * Class Index
+ * @package app\index\controller
+ */
+class Index extends Controller
+{
+    /**
+     * 入口跳转链接
+     */
+    public function index()
+    {
+        $this->redirect('@admin/login');
+    }
+}

+ 70 - 0
application/order/controller/CrystalCash.php

@@ -0,0 +1,70 @@
+<?php
+namespace app\order\controller;
+use library\Controller;
+use think\Db;
+/**
+ * 水晶提现管理
+ * Class CrystalCash
+ * @package app\order\controller
+ */
+class CrystalCash extends Controller
+{
+    protected $table = 'CrystalOrder';
+    /**
+     * 充值订单
+     * @auth true
+     * @menu true
+     */
+    public function index()
+    {
+        $this->title = '充值订单';
+        $this->order_status = ['待支付','已支付'];
+        $query = $this->_query($this->table);
+        $where = [];
+        if($this->request->request('tel'))$where[]= ['u.phone','like','%'.$this->request->request('tel').'%'];
+        if($this->request->request('user_name'))$where[]= ['u.name','like','%'.$this->request->request('user_name').'%'];
+        if($this->request->request('order_no')) $where[]= ['o.order_no','like','%'.$this->request->request('order_no').'%'];
+        if($this->request->request('order_status') > -1) $where[]= ['o.status','=',$this->request->request('order_status')];
+        $query->alias('o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT');
+        if(!empty($where)) $query->where($where);
+        $query ->order('o.id desc')->page();
+    }
+
+    /**
+     * 订单详情
+     * @auth true
+     * @menu true
+     */
+    public function detail()
+    {
+        $this->title = '订单详情';
+        $order_id = input('id');
+        $detail = Db::table('crystal_order o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT')
+            ->where('o.id',$order_id)
+            ->find();
+        $this->assign('detail',$detail);
+        $this->fetch('detail');
+    }
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+        if ($this->request->isPost() && $this->request->action() == 'deliver') {
+            $express_company =  Db::table('store_express_company')->field('id,express_title')->find($data['express_company_id']);
+            $data['express_company_title'] = $express_company['express_title'] ? $express_company['express_title'] : '';
+            $data['express_send_at'] = date("Y-m-d H:i:s");
+            $data['express_state'] = 1;
+        }
+    }
+
+}

+ 70 - 0
application/order/controller/CrystalOrder.php

@@ -0,0 +1,70 @@
+<?php
+namespace app\order\controller;
+use library\Controller;
+use think\Db;
+/**
+ * 水晶充值订单管理
+ * Class CrystalOrder
+ * @package app\order\controller
+ */
+class CrystalOrder extends Controller
+{
+    protected $table = 'CrystalOrder';
+    /**
+     * 充值订单
+     * @auth true
+     * @menu true
+     */
+    public function index()
+    {
+        $this->title = '充值订单';
+        $this->order_status = ['待支付','已支付'];
+        $query = $this->_query($this->table);
+        $where = [];
+        if($this->request->request('tel'))$where[]= ['u.phone','like','%'.$this->request->request('tel').'%'];
+        if($this->request->request('user_name'))$where[]= ['u.name','like','%'.$this->request->request('user_name').'%'];
+        if($this->request->request('order_no')) $where[]= ['o.order_no','like','%'.$this->request->request('order_no').'%'];
+        if($this->request->request('order_status') > -1) $where[]= ['o.status','=',$this->request->request('order_status')];
+        $query->alias('o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT');
+        if(!empty($where)) $query->where($where);
+        $query ->order('o.id desc')->page();
+    }
+
+    /**
+     * 订单详情
+     * @auth true
+     * @menu true
+     */
+    public function detail()
+    {
+        $this->title = '订单详情';
+        $order_id = input('id');
+        $detail = Db::table('crystal_order o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT')
+            ->where('o.id',$order_id)
+            ->find();
+        $this->assign('detail',$detail);
+        $this->fetch('detail');
+    }
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+        if ($this->request->isPost() && $this->request->action() == 'deliver') {
+            $express_company =  Db::table('store_express_company')->field('id,express_title')->find($data['express_company_id']);
+            $data['express_company_title'] = $express_company['express_title'] ? $express_company['express_title'] : '';
+            $data['express_send_at'] = date("Y-m-d H:i:s");
+            $data['express_state'] = 1;
+        }
+    }
+
+}

+ 88 - 0
application/order/controller/GoodsOrder.php

@@ -0,0 +1,88 @@
+<?php
+namespace app\order\controller;
+use library\Controller;
+use think\Db;
+/**
+ * 商品订单
+ * Class Order
+ * @package app\order\controller
+ */
+class GoodsOrder extends Controller
+{
+    protected $table = 'GoodsOrder';
+    /**
+     * 订单列表
+     * @auth true
+     * @menu true
+     */
+    public function index()
+    {
+        $this->title = '订单管理';
+        $this->order_status = ['待支付','已支付'];
+        $query = $this->_query($this->table);
+        $where = [];
+        if($this->request->request('tel'))$where[]= ['u.phone','like','%'.$this->request->request('tel').'%'];
+        if($this->request->request('user_name'))$where[]= ['u.name','like','%'.$this->request->request('user_name').'%'];
+        if($this->request->request('order_no')) $where[]= ['o.order_no','like','%'.$this->request->request('order_no').'%'];
+        if($this->request->request('order_status') > -1) $where[]= ['o.status','=',$this->request->request('order_status')];
+        $query->alias('o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT');
+        if(!empty($where)) $query->where($where);
+        $query ->order('o.id desc')->page();
+    }
+
+
+    /**
+     * 订单详情
+     * @auth true
+     * @menu true
+     */
+    public function detail()
+    {
+        $this->title = '订单详情';
+        $order_id = input('id');
+        $detail = Db::table('goods_order o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT')
+            ->where('o.id',$order_id)
+            ->find();
+        $pro_info = Db::table('magic_case')->where('order_id',$order_id)->select();
+        $this->assign('detail',$detail);
+        $this->assign('pro_info',$pro_info);
+        $this->fetch('detail');
+    }
+
+    /**
+     * 订单发货
+     * @auth true
+     * @menu true
+     */
+
+    public function deliver()
+    {
+        $this->title = '发货';
+        $this->express_company = Db::table('store_express_company')->field('id,express_title')->select();
+        $this->_form($this->table,'deliver');
+    }
+
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+        if ($this->request->isPost() && $this->request->action() == 'deliver') {
+            $express_company =  Db::table('store_express_company')->field('id,express_title')->find($data['express_company_id']);
+            $data['express_company_title'] = $express_company['express_title'] ? $express_company['express_title'] : '';
+            $data['express_send_at'] = date("Y-m-d H:i:s");
+            $data['express_state'] = 1;
+        }
+    }
+
+
+}

+ 97 - 0
application/order/controller/IntegralOrder.php

@@ -0,0 +1,97 @@
+<?php
+namespace app\order\controller;
+use library\Controller;
+use think\Db;
+/**
+ * 兑换订单管理
+ * Class IntegralOrder
+ * @package app\order\controller
+ */
+class IntegralOrder extends Controller
+{
+    protected $table = 'ExchangeOrder';
+    /**
+     * 订单列表
+     * @auth true
+     * @menu true
+     */
+    public function index()
+    {
+        $this->title = '兑换订单管理';
+        $this->order_status = ['待支付','已支付/待发货','已发货/待收货','已收货'];
+        $query = $this->_query($this->table);
+        $where = [];
+        $where[] = ['o.is_deleted','=',0];
+        $where[] = ['o.cancel_state','=',0];
+        if($this->request->request('tel'))$where[]= ['u.phone','like','%'.$this->request->request('tel').'%'];
+        if($this->request->request('user_name'))$where[]= ['u.name','like','%'.$this->request->request('user_name').'%'];
+        if($this->request->request('order_no')) $where[]= ['o.order_no','like','%'.$this->request->request('order_no').'%'];
+        if($this->request->request('order_status') > -1) $where[]= ['o.status','=',$this->request->request('order_status')];
+
+        $query->alias('o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT');
+        if(!empty($where)) $query->where($where);
+        $query ->order('o.id desc')->page();
+    }
+
+
+    /**
+     * 订单详情
+     * @auth true
+     * @menu true
+     */
+    public function detail()
+    {
+        $this->title = '兑换订单详情';
+        $order_id = input('id');
+        $detail = Db::table('exchange_order o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT')
+            ->where('o.id',$order_id)
+            ->find();
+        $address_info = Db::table('delivery_address')->field('id,mer_name,detail,phone,name')->find($detail['address_id']);
+        $this->assign('detail',$detail);
+        $this->assign('address_info',$address_info);
+        $this->fetch('detail');
+    }
+
+    /**
+     * 订单发货
+     * @auth true
+     * @menu true
+     */
+
+    public function deliver()
+    {
+        $this->title = '发货';
+        $this->express_company = Db::table('store_express_company')->field('id,express_title')->select();
+        $this->_form($this->table,'deliver');
+    }
+
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+        if ($this->request->isPost() && $this->request->action() == 'deliver') {
+            $express_company =  Db::table('store_express_company')->field('id,express_title')->find($data['express_company_id']);
+            $data['express_company_title'] = $express_company['express_title'] ? $express_company['express_title'] : '';
+            $data['express_send_at'] = date("Y-m-d H:i:s");
+            $data['express_state'] = 1;
+            $data['status'] = 2;
+        }
+        if ($this->request->isGet() && $this->request->action() == 'deliver') {
+            if (isset($data['address_id'])){
+                $this->address_info = Db::table('delivery_address')->field('id,mer_name,detail,phone,name')->find($data['address_id']);
+            }
+        }
+    }
+
+
+}

+ 97 - 0
application/order/controller/MagicOrder.php

@@ -0,0 +1,97 @@
+<?php
+namespace app\order\controller;
+use library\Controller;
+use think\Db;
+/**
+ * 订单管理
+ * Class MagicOrder
+ * @package app\order\controller
+ */
+class MagicOrder extends Controller
+{
+    protected $table = 'MagicOrder';
+    /**
+     * 订单列表
+     * @auth true
+     * @menu true
+     */
+    public function index()
+    {
+        $this->title = '订单管理';
+        $this->order_status = ['待支付','已支付/待发货','已发货/待收货','已收货'];
+        $query = $this->_query($this->table);
+        $where = [];
+        $where[] = ['o.is_deleted','=',0];
+        $where[] = ['o.cancel_state','=',0];
+        if($this->request->request('tel'))$where[]= ['u.phone','like','%'.$this->request->request('tel').'%'];
+        if($this->request->request('user_name'))$where[]= ['u.name','like','%'.$this->request->request('user_name').'%'];
+        if($this->request->request('order_no')) $where[]= ['o.order_no','like','%'.$this->request->request('order_no').'%'];
+        if($this->request->request('order_status') > -1) $where[]= ['o.status','=',$this->request->request('order_status')];
+        $where[] = ['o.cancel_state','=',0];
+        $query->alias('o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT');
+        if(!empty($where)) $query->where($where);
+        $query ->order('o.id desc')->page();
+    }
+
+
+    /**
+     * 订单详情
+     * @auth true
+     * @menu true
+     */
+    public function detail()
+    {
+        $this->title = '订单详情';
+        $order_id = input('id');
+        $detail = Db::table('magic_order o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT')
+            ->where('o.id',$order_id)
+            ->find();
+        $address_info = Db::table('delivery_address')->field('id,mer_name,detail,phone,name')->find($detail['address_id']);
+        $this->assign('address_info',$address_info);
+        $this->assign('detail',$detail);
+        $this->fetch('detail');
+    }
+
+    /**
+     * 订单发货
+     * @auth true
+     * @menu true
+     */
+
+    public function deliver()
+    {
+        $this->title = '发货';
+        $this->express_company = Db::table('store_express_company')->field('id,express_title')->select();
+        $this->_form($this->table,'deliver');
+    }
+
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+        if ($this->request->isPost() && $this->request->action() == 'deliver') {
+            $express_company =  Db::table('store_express_company')->field('id,express_title')->find($data['express_company_id']);
+            $data['express_company_title'] = $express_company['express_title'] ? $express_company['express_title'] : '';
+            $data['express_send_at'] = date("Y-m-d H:i:s");
+            $data['express_state'] = 1;
+            $data['status'] = 2;
+        }
+        if ($this->request->isGet() && $this->request->action() == 'deliver') {
+            if (isset($data['address_id'])){
+                $this->address_info = Db::table('delivery_address')->field('id,mer_name,detail,phone,name')->find($data['address_id']);
+            }
+        }
+    }
+
+
+}

+ 87 - 0
application/order/controller/Order.php

@@ -0,0 +1,87 @@
+<?php
+namespace app\order\controller;
+use library\Controller;
+use think\Db;
+/**
+ * 订单管理
+ * Class Order
+ * @package app\order\controller
+ */
+class Order extends Controller
+{
+    protected $table = 'StoreOrder';
+    /**
+     * 订单列表
+     * @auth true
+     * @menu true
+     */
+    public function index()
+    {
+        $this->title = '线上商城订单管理';
+        $this->order_status = ['待支付','已支付/待发货','已发货/待收货','已收货','已评论','','','','','已取消'];
+        $query = $this->_query($this->table);
+        $where = [];
+        if($this->request->request('tel'))$where[]= ['u.phone','like','%'.$this->request->request('tel').'%'];
+        if($this->request->request('user_name'))$where[]= ['u.name','like','%'.$this->request->request('user_name').'%'];
+        if($this->request->request('order_no')) $where[]= ['o.order_no','like','%'.$this->request->request('order_no').'%'];
+        if($this->request->request('order_status') > -1) $where[]= ['o.status','=',$this->request->request('order_status')];
+        $where[] =['source','=',0] ;
+        $query->alias('o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT');
+        if(!empty($where)) $query->where($where);
+        $query ->order('o.id desc')->page();
+    }
+
+
+    /**
+     * 订单详情
+     * @auth true
+     * @menu true
+     */
+    public function detail()
+    {
+        $this->title = '订单详情';
+        $order_id = input('id');
+        $detail = Db::table('store_order o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT')
+            ->where('o.id',$order_id)
+            ->find();
+        $this->assign('detail',$detail);
+        $this->fetch('detail');
+    }
+
+    /**
+     * 订单发货
+     * @auth true
+     * @menu true
+     */
+
+    public function deliver()
+    {
+        $this->title = '发货';
+        $this->express_company = Db::table('store_express_company')->field('id,express_title')->select();
+        $this->_form($this->table,'deliver');
+    }
+
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+        if ($this->request->isPost() && $this->request->action() == 'deliver') {
+            $express_company =  Db::table('store_express_company')->field('id,express_title')->find($data['express_company_id']);
+            $data['express_company_title'] = $express_company['express_title'] ? $express_company['express_title'] : '';
+            $data['express_send_at'] = date("Y-m-d H:i:s");
+            $data['express_state'] = 1;
+        }
+    }
+
+
+}

+ 40 - 0
application/order/view/crystal_order/index.html

@@ -0,0 +1,40 @@
+{extend name='admin@main'}
+{block name="content"}
+<div class="think-box-shadow">
+    {include file='crystal_order/index_search'}
+    <table class="layui-table margin-top-10" lay-skin="line">
+        {notempty name='list'}
+        <thead>
+        <tr>
+            <th class='list-table-check-td think-checkbox'><input data-auto-none data-check-target='.list-check-box' type='checkbox'></th>
+            <th class='text-left nowrap'>用户名</th>
+            <th class='text-left nowrap'>手机号</th>
+            <th class='text-left nowrap'>订单金额</th>
+            <th class='text-left nowrap'>充值水晶</th>
+            <th class='text-left nowrap'>订单号</th>
+            <th class='text-left nowrap'>订单状态</th>
+            <th class="text-left nowrap">支付时间</th>
+            <th class="text-left nowrap">添加时间</th>
+
+        </tr>
+        </thead>
+        {/notempty}
+        <tbody>
+        {foreach $list as $key=>$vo}
+        <tr>
+            <td class='list-table-check-td think-checkbox'><input class="list-check-box" value='{$vo.id}' type='checkbox'></td>
+            <td class='text-left nowrap'>{$vo.user_name|default=''}</td>
+            <td class='text-left nowrap'>{$vo.phone|default=''}</td>
+            <td class='text-left nowrap'>{$vo.price_total|default=''}</td>
+            <td class='text-left nowrap'>{$vo.crystal|default=''}</td>
+            <td class='text-left nowrap'>{$vo.order_no|default=''}</td>
+            <td class='text-left nowrap'>{$order_status[$vo.status]|default=''}</td>
+            <td class='text-left nowrap'>{$vo.pay_at|default='--'}</td>
+            <td class='text-left nowrap'>{$vo.create_at}</td>
+        </tr>
+        {/foreach}
+        </tbody>
+    </table>
+    {empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
+</div>
+{/block}

+ 50 - 0
application/order/view/crystal_order/index_search.html

@@ -0,0 +1,50 @@
+<fieldset>
+    <legend>条件搜索</legend>
+    <form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">订单号</label>
+            <div class="layui-input-inline">
+                <input name="order_no" value="{$Think.get.order_no|default=''}" placeholder="请输入订单号" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">手机号</label>
+            <div class="layui-input-inline">
+                <input name="tel" value="{$Think.get.tel|default=''}" placeholder="请输入手机号" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">用户名称</label>
+            <div class="layui-input-inline">
+                <input name="user_name" value="{$Think.get.user_name|default=''}" placeholder="请输入用户名称" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">订单状态</label>
+            <div class="layui-input-inline">
+                <select class="layui-select" name="order_status">
+                    <option  value="-1">全部</option>
+                    {foreach $order_status as $k=>$v}
+                        {if $v}
+                            {if $Think.get.order_status eq $k}
+                            <option selected value="{$k}">{$v}</option>
+                            {else}
+                            <option  value="{$k}">{$v}</option>
+                            {/if}
+                        {/if}
+                    {/foreach}
+                </select>
+            </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>
+    <script>form.render()</script>
+</fieldset>

+ 50 - 0
application/order/view/goods_order/deliver.html

@@ -0,0 +1,50 @@
+<form onsubmit="return false;" action="{:request()->url()}" data-auto="true" method="post" class='layui-form layui-card' autocomplete="off">
+
+    <div class="layui-card-body" style="height: 400px">
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">订单号</label>
+            <label class="layui-col-xs10">
+                <input name="order_no"  style="background-color: #e6e6e6" readonly value='{$vo.order_no|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">快递公司</label>
+            <div class="layui-input-inline">
+                <select name="express_company_id" >
+                    {foreach $express_company as $ck=>$cv}
+                        {if $cv.id == $vo.express_company_id}
+                        <option selected value="{$cv.id}">{$cv.express_title}</option>
+                        {else}
+                        <option value="{$cv.id}">{$cv.express_title}</option>
+                        {/if}
+                    {/foreach}
+                </select>
+            </div>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">物流单号</label>
+            <label class="layui-col-xs10">
+                <input name="express_send_no"  value='{$vo.express_send_no}' placeholder="请输入物流单号" class="layui-input">
+            </label>
+        </div>
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">发货时间</label>
+            <label class="layui-col-xs10">
+                <input readonly name="express_send_at"  value='{$vo.express_send_at|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+    </div>
+
+    <div class="hr-line-dashed"></div>
+    <div class="layui-form-item text-center">
+        {notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
+        <input type='hidden' value='{$vo.uid}' name='uid'>
+        <button class="layui-btn" type='submit'>发货</button>
+    </div>
+</form>
+<script>
+    window.form.render();
+    $("#layui-layer-content").height(600)
+</script>

+ 119 - 0
application/order/view/goods_order/detail.html

@@ -0,0 +1,119 @@
+<style>
+    .layui-card-body
+    {
+        height: 60%;
+    }
+</style>
+<div class="layui-card-body">
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">订单号</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.order_no|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    {if $detail.pay_state == 1}
+        <div class="layui-form-item">
+            <label class="layui-form-label label-required">支付号</label>
+            <div class="layui-input-block">
+                <input  readonly  value='{$detail.pay_no|default=""}' placeholder="" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label label-required">支付时间</label>
+            <div class="layui-input-block">
+                <input  readonly  value='{$detail.pay_time|default=""}' placeholder="" class="layui-input">
+            </div>
+        </div>
+    {/if}
+
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">用户名</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.user_name|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">会员手机</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.phone|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">商品数</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.goods_num|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">商品名称</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.goods_name|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">商品封面</label>
+        <div class="layui-input-block">
+            <img  src="{$detail.goods_cover|default=''}" width="50px">
+        </div>
+    </div>
+
+    {if !empty($pro_info)}
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">抽奖详情</label>
+        <div class="layui-input-block">
+            <table class="layui-table margin-top-10" lay-skin="line">
+                <thead>
+                <tr>
+                    <th class='text-left nowrap'>名称</th>
+                    <th class='text-left nowrap'>图片</th>
+                    <th class='text-left nowrap'>数量</th>
+                    <th class='text-left nowrap'>水晶</th>
+                </tr>
+                </thead>
+                <tbody class="no_html">
+                {foreach $pro_info as $sk=>$sv}
+                <tr class="no_detail">
+                    <td class='text-left nowrap'>
+                        <input class='layui-input' readonly style="background-color: #e6e6e6" value="{$sv['case_name']}"/>
+                    </td>
+                    <td class='text-left nowrap'><img  src="{$vo.case_cover|default=''}" width="30px"></td>
+                    <td class='text-left nowrap'>
+                        <input class='layui-input'  readonly style="background-color: #e6e6e6" value="{$sv['base_num']}"/>
+                    </td>
+                    <td class='text-left nowrap'>
+                        <input class='layui-input'  readonly style="background-color: #e6e6e6" value="{$sv['crystal']}"/>
+                    </td>
+                </tr>
+                {/foreach}
+                </tbody>
+            </table>
+        </div>
+    </div>
+    {/if}
+
+
+
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">订单总金额</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.price_total|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">创建时间</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.create_at|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+</div>
+
+<script>
+    window.form.render();
+
+</script>

+ 41 - 0
application/order/view/goods_order/index.html

@@ -0,0 +1,41 @@
+{extend name='admin@main'}
+{block name="content"}
+<div class="think-box-shadow">
+    {include file='goods_order/index_search'}
+    <table class="layui-table margin-top-10" lay-skin="line">
+        {notempty name='list'}
+        <thead>
+        <tr>
+            <th class='list-table-check-td think-checkbox'><input data-auto-none data-check-target='.list-check-box' type='checkbox'></th>
+            <th class='text-left nowrap'>用户名</th>
+            <th class='text-left nowrap'>手机号</th>
+            <th class='text-left nowrap'>订单金额</th>
+            <th class='text-left nowrap'>商品数量</th>
+            <th class='text-left nowrap'>订单号</th>
+            <th class='text-left nowrap'>订单状态</th>
+            <th class="text-left nowrap">添加时间</th>
+            <th class="text-left nowrap">操作</th>
+        </tr>
+        </thead>
+        {/notempty}
+        <tbody>
+        {foreach $list as $key=>$vo}
+        <tr>
+            <td class='list-table-check-td think-checkbox'><input class="list-check-box" value='{$vo.id}' type='checkbox'></td>
+            <td class='text-left nowrap'>{$vo.user_name|default=''}</td>
+            <td class='text-left nowrap'>{$vo.phone|default=''}</td>
+            <td class='text-left nowrap'>{$vo.price_total|default=''}</td>
+            <td class='text-left nowrap'>{$vo.goods_num|default=''}</td>
+            <td class='text-left nowrap'>{$vo.order_no|default=''}</td>
+            <td class='text-left nowrap'>{$order_status[$vo.status]|default='已取消'}</td>
+            <td class='text-left nowrap'>{$vo.create_at}</td>
+            <td class='text-left nowrap'>
+                <a data-title="查看详情" class="layui-btn layui-btn-sm" data-modal='{:url("detail")}?id={$vo.id}'>查看详情</a>
+            </td>
+        </tr>
+        {/foreach}
+        </tbody>
+    </table>
+    {empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
+</div>
+{/block}

+ 50 - 0
application/order/view/goods_order/index_search.html

@@ -0,0 +1,50 @@
+<fieldset>
+    <legend>条件搜索</legend>
+    <form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">订单号</label>
+            <div class="layui-input-inline">
+                <input name="order_no" value="{$Think.get.order_no|default=''}" placeholder="请输入订单号" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">手机号</label>
+            <div class="layui-input-inline">
+                <input name="tel" value="{$Think.get.tel|default=''}" placeholder="请输入手机号" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">用户名称</label>
+            <div class="layui-input-inline">
+                <input name="user_name" value="{$Think.get.user_name|default=''}" placeholder="请输入用户名称" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">订单状态</label>
+            <div class="layui-input-inline">
+                <select class="layui-select" name="order_status">
+                    <option  value="-1">全部</option>
+                    {foreach $order_status as $k=>$v}
+                        {if $v}
+                            {if $Think.get.order_status eq $k}
+                            <option selected value="{$k}">{$v}</option>
+                            {else}
+                            <option  value="{$k}">{$v}</option>
+                            {/if}
+                        {/if}
+                    {/foreach}
+                </select>
+            </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>
+    <script>form.render()</script>
+</fieldset>

+ 79 - 0
application/order/view/integral_order/deliver.html

@@ -0,0 +1,79 @@
+<form onsubmit="return false;" action="{:request()->url()}" data-auto="true" method="post" class='layui-form layui-card' autocomplete="off">
+
+    <div class="layui-card-body" style="height: 400px">
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">订单号</label>
+            <label class="layui-col-xs10">
+                <input name="order_no"  style="background-color: #e6e6e6" readonly value='{$vo.order_no|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">收货地区</label>
+            <label class="layui-col-xs10">
+                <input  style="background-color: #e6e6e6" readonly value='{$address_info.mer_name|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">详细地址</label>
+            <label class="layui-col-xs10">
+                <input  style="background-color: #e6e6e6" readonly value='{$address_info.detail|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">收货人</label>
+            <label class="layui-col-xs10">
+                <input  style="background-color: #e6e6e6" readonly value='{$address_info.name|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">电话</label>
+            <label class="layui-col-xs10">
+                <input  style="background-color: #e6e6e6" readonly value='{$address_info.phone|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">快递公司</label>
+            <div class="layui-input-inline">
+                <select name="express_company_id" >
+                    {foreach $express_company as $ck=>$cv}
+                    {if $cv.id == $vo.express_company_id}
+                    <option selected value="{$cv.id}">{$cv.express_title}</option>
+                    {else}
+                    <option value="{$cv.id}">{$cv.express_title}</option>
+                    {/if}
+                    {/foreach}
+                </select>
+            </div>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">物流单号</label>
+            <label class="layui-col-xs10">
+                <input name="express_send_no"  value='{$vo.express_send_no}' placeholder="请输入物流单号" class="layui-input">
+            </label>
+        </div>
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">发货时间</label>
+            <label class="layui-col-xs10">
+                <input readonly name="express_send_at"  value='{$vo.express_send_at|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+    </div>
+
+    <div class="hr-line-dashed"></div>
+    <div class="layui-form-item text-center" style="margin-top: 100px">
+        {notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
+        <input type='hidden' value='{$vo.uid}' name='uid'>
+        <button class="layui-btn" type='submit'>发货</button>
+    </div>
+</form>
+<script>
+    window.form.render();
+    $("#layui-layer-content").height(800)
+</script>

+ 125 - 0
application/order/view/integral_order/detail.html

@@ -0,0 +1,125 @@
+<style>
+    .layui-card-body
+    {
+        height: 60%;
+    }
+</style>
+<div class="layui-card-body">
+    <div class="layui-form-item">
+        <label class="layui-form-label ">订单号</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.order_no|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    {if $detail.express_send_no}
+    <div class="layui-form-item">
+        <label class="layui-form-label ">物流单号</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.express_send_no|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    {/if}
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">用户名</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.user_name|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label ">会员手机</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.phone|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">商品名称</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.goods_name|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">商品封面</label>
+        <div class="layui-input-block">
+            <img  src="{$detail.goods_cover}" style="height: 50px;width: 50px" />
+        </div>
+    </div>
+
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">商品数</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.goods_num|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label ">订单总额</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.price_total|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">收货地区</label>
+        <div class="layui-input-block">
+            <input  readonly value='{$address_info.mer_name|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">详细地址</label>
+        <div class="layui-input-block">
+            <input  readonly value='{$address_info.detail|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">收货人</label>
+        <div class="layui-input-block">
+            <input   readonly value='{$address_info.name|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label ">电话</label>
+        <div class="layui-input-block">
+            <input  readonly value='{$address_info.phone|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label ">物流公司</label>
+        <div class="layui-input-block">
+            <input name="express_company_title"  value='{$detail.express_company_title}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">物流单号</label>
+        <div class="layui-input-block">
+            <input name="express_send_no"  value='{$detail.express_send_no}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label ">发货时间</label>
+        <div class="layui-input-block">
+            <input readonly name="express_send_at"  value='{$detail.express_send_at|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">兑换时间</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.pay_time|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+</div>
+
+<script>
+    window.form.render();
+
+</script>

+ 36 - 0
application/order/view/integral_order/form.html

@@ -0,0 +1,36 @@
+<form onsubmit="return false;" action="{:request()->url()}" data-auto="true" method="post" class='layui-form layui-card' autocomplete="off">
+
+    <div class="layui-card-body">
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">用户名</label>
+            <label class="layui-col-xs10">
+                {notempty name='vo.id'}  <input name="name" required value='{$vo.name|default=""}' style="background-color: #e6e6e6" readonly class="layui-input">{/notempty}
+                {empty name='vo.id'}  <input name="name" required value='{$vo.name|default=""}' placeholder="请输入用户名" class="layui-input">{/empty}
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">登录手机号</label>
+            <label class="layui-col-xs10">
+                {notempty name='vo.id'}    <input name="phone" required value='{$vo.phone|default=""}' style="background-color: #e6e6e6" readonly class="layui-input">{/notempty}
+                {empty name='vo.id'}       <input name="phone" required value='{$vo.phone|default=""}' placeholder="请输入登录手机号" class="layui-input">{/empty}
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">登录密码</label>
+            <label class="layui-col-xs10">
+                <input name="password" required value='{$vo.password|default=""}' placeholder="请输入登录密码" class="layui-input">
+            </label>
+        </div>
+
+    </div>
+
+    <div class="hr-line-dashed"></div>
+    <div class="layui-form-item text-center">
+        {notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
+        <button class="layui-btn" type='submit'>保存数据</button>
+        <button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
+    </div>
+</form>

+ 44 - 0
application/order/view/integral_order/index.html

@@ -0,0 +1,44 @@
+{extend name='admin@main'}
+{block name="content"}
+<div class="think-box-shadow">
+    {include file='integral_order/index_search'}
+    <table class="layui-table margin-top-10" lay-skin="line">
+        {notempty name='list'}
+        <thead>
+        <tr>
+            <th class='list-table-check-td think-checkbox'><input data-auto-none data-check-target='.list-check-box' type='checkbox'></th>
+            <th class='text-left nowrap'>用户名</th>
+            <th class='text-left nowrap'>手机号</th>
+            <th class='text-left nowrap'>订单金额</th>
+            <th class='text-left nowrap'>商品数量</th>
+            <th class='text-left nowrap'>订单号</th>
+            <th class='text-left nowrap'>订单状态</th>
+            <th class="text-left nowrap">添加时间</th>
+            <th class="text-left nowrap">操作</th>
+        </tr>
+        </thead>
+        {/notempty}
+        <tbody>
+        {foreach $list as $key=>$vo}
+        <tr>
+            <td class='list-table-check-td think-checkbox'><input class="list-check-box" value='{$vo.id}' type='checkbox'></td>
+            <td class='text-left nowrap'>{$vo.user_name|default=''}</td>
+            <td class='text-left nowrap'>{$vo.phone|default=''}</td>
+            <td class='text-left nowrap'>{$vo.price_total|default=''}</td>
+            <td class='text-left nowrap'>{$vo.goods_num|default=''}</td>
+            <td class='text-left nowrap'>{$vo.order_no|default=''}</td>
+            <td class='text-left nowrap'>{$order_status[$vo.status]|default=''}</td>
+            <td class='text-left nowrap'>{$vo.create_at}</td>
+            <td class='text-left nowrap'>
+                {if $vo.status > 0 && $vo.status != 9}
+                <a data-title="发货" class="layui-btn layui-btn-sm" data-modal='{:url("deliver")}?id={$vo.id}'>发货</a>
+                {/if}
+                <a data-title="查看详情" class="layui-btn layui-btn-sm" data-modal='{:url("detail")}?id={$vo.id}'>查看详情</a>
+            </td>
+        </tr>
+        {/foreach}
+        </tbody>
+    </table>
+    {empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
+</div>
+{/block}

+ 50 - 0
application/order/view/integral_order/index_search.html

@@ -0,0 +1,50 @@
+<fieldset>
+    <legend>条件搜索</legend>
+    <form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">订单号</label>
+            <div class="layui-input-inline">
+                <input name="order_no" value="{$Think.get.order_no|default=''}" placeholder="请输入订单号" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">手机号</label>
+            <div class="layui-input-inline">
+                <input name="tel" value="{$Think.get.tel|default=''}" placeholder="请输入手机号" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">用户名称</label>
+            <div class="layui-input-inline">
+                <input name="user_name" value="{$Think.get.user_name|default=''}" placeholder="请输入用户名称" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">订单状态</label>
+            <div class="layui-input-inline">
+                <select class="layui-select" name="order_status">
+                    <option  value="-1">全部</option>
+                    {foreach $order_status as $k=>$v}
+                    {if $v}
+                    {if $Think.get.order_status eq $k}
+                    <option selected value="{$k}">{$v}</option>
+                    {else}
+                    <option  value="{$k}">{$v}</option>
+                    {/if}
+                    {/if}
+                    {/foreach}
+                </select>
+            </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>
+    <script>form.render()</script>
+</fieldset>

+ 79 - 0
application/order/view/magic_order/deliver.html

@@ -0,0 +1,79 @@
+<form onsubmit="return false;" action="{:request()->url()}" data-auto="true" method="post" class='layui-form layui-card' autocomplete="off">
+
+    <div class="layui-card-body" style="height: 400px">
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">订单号</label>
+            <label class="layui-col-xs10">
+                <input name="order_no"  style="background-color: #e6e6e6" readonly value='{$vo.order_no|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">收货地区</label>
+            <label class="layui-col-xs10">
+                <input  style="background-color: #e6e6e6" readonly value='{$address_info.mer_name|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">详细地址</label>
+            <label class="layui-col-xs10">
+                <input  style="background-color: #e6e6e6" readonly value='{$address_info.detail|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">收货人</label>
+            <label class="layui-col-xs10">
+                <input  style="background-color: #e6e6e6" readonly value='{$address_info.name|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">电话</label>
+            <label class="layui-col-xs10">
+                <input  style="background-color: #e6e6e6" readonly value='{$address_info.phone|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">快递公司</label>
+            <div class="layui-input-inline">
+                <select name="express_company_id" >
+                    {foreach $express_company as $ck=>$cv}
+                    {if $cv.id == $vo.express_company_id}
+                    <option selected value="{$cv.id}">{$cv.express_title}</option>
+                    {else}
+                    <option value="{$cv.id}">{$cv.express_title}</option>
+                    {/if}
+                    {/foreach}
+                </select>
+            </div>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">物流单号</label>
+            <label class="layui-col-xs10">
+                <input name="express_send_no"  value='{$vo.express_send_no}' placeholder="请输入物流单号" class="layui-input">
+            </label>
+        </div>
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">发货时间</label>
+            <label class="layui-col-xs10">
+                <input readonly name="express_send_at"  value='{$vo.express_send_at|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+    </div>
+
+    <div class="hr-line-dashed"></div>
+    <div class="layui-form-item text-center" style="margin-top: 100px">
+        {notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
+        <input type='hidden' value='{$vo.uid}' name='uid'>
+        <button class="layui-btn" type='submit'>发货</button>
+    </div>
+</form>
+<script>
+    window.form.render();
+    $("#layui-layer-content").height(800)
+</script>

+ 146 - 0
application/order/view/magic_order/detail.html

@@ -0,0 +1,146 @@
+<style>
+    .layui-card-body
+    {
+        height: 60%;
+    }
+</style>
+<div class="layui-card-body">
+    <div class="layui-form-item">
+        <label class="layui-form-label  ">订单号</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.order_no|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    {if $detail.pay_state == 1}
+        <div class="layui-form-item">
+            <label class="layui-form-label  ">支付号</label>
+            <div class="layui-input-block">
+                <input  readonly  value='{$detail.pay_no|default=""}' placeholder="" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label  ">支付时间</label>
+            <div class="layui-input-block">
+                <input  readonly  value='{$detail.pay_at|default=""}' placeholder="" class="layui-input">
+            </div>
+        </div>
+    {/if}
+
+    <div class="layui-form-item">
+        <label class="layui-form-label  ">用户名</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.user_name|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label  ">会员手机</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.phone|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label  ">商品数</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.goods_num|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label  ">商品详情</label>
+        <div class="layui-input-block">
+            <table class="layui-table margin-top-10" lay-skin="line">
+                <thead>
+                <tr>
+                    <th class='text-left nowrap'>商品</th>
+                    <th class='text-left nowrap'>图片</th>
+                    <th class='text-left nowrap'>数量</th>
+                    <th class='text-left nowrap'>水晶</th>
+                </tr>
+                </thead>
+                <tbody class="no_html">
+                {foreach :json_decode($detail.pro_info,true) as $sk=>$sv}
+                <tr class="no_detail">
+                    <td class='text-left nowrap'>
+                        <input class='layui-input' readonly style="background-color: #e6e6e6"  value="{$sv['case_name']}"/>
+                    </td>
+                    <td class='text-left nowrap'><img  src="{$sv['case_cover']}" width="30px"></td>
+                    <td class='text-left nowrap'>
+                        <input class='layui-input'  readonly style="background-color: #e6e6e6" value="{$sv['num']}"/>
+                    </td>
+                    <td class='text-left nowrap'>
+                        <input class='layui-input'  readonly style="background-color: #e6e6e6"  value="{$sv['crystal']|default='0'}"/>
+                    </td>
+                </tr>
+                {/foreach}
+                </tbody>
+            </table>
+        </div>
+    </div>
+
+
+    <div class="layui-form-item">
+        <label class="layui-form-label  ">订单总金额</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.price_total|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">收货地区</label>
+        <div class="layui-input-block">
+            <input  readonly value='{$address_info.mer_name|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">详细地址</label>
+        <div class="layui-input-block">
+            <input  readonly value='{$address_info.detail|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">收货人</label>
+        <div class="layui-input-block">
+            <input   readonly value='{$address_info.name|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label ">电话</label>
+        <div class="layui-input-block">
+            <input  readonly value='{$address_info.phone|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label ">物流公司</label>
+        <div class="layui-input-block">
+            <input name="express_company_title"  value='{$detail.express_company_title}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label ">物流单号</label>
+        <div class="layui-input-block">
+            <input name="express_send_no"  value='{$detail.express_send_no}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label ">发货时间</label>
+        <div class="layui-input-block">
+            <input readonly name="express_send_at"  value='{$detail.express_send_at|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label  ">创建时间</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.create_at|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+</div>
+
+<script>
+    window.form.render();
+
+</script>

+ 36 - 0
application/order/view/magic_order/form.html

@@ -0,0 +1,36 @@
+<form onsubmit="return false;" action="{:request()->url()}" data-auto="true" method="post" class='layui-form layui-card' autocomplete="off">
+
+    <div class="layui-card-body">
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">用户名</label>
+            <label class="layui-col-xs10">
+                {notempty name='vo.id'}  <input name="name" required value='{$vo.name|default=""}' style="background-color: #e6e6e6" readonly class="layui-input">{/notempty}
+                {empty name='vo.id'}  <input name="name" required value='{$vo.name|default=""}' placeholder="请输入用户名" class="layui-input">{/empty}
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">登录手机号</label>
+            <label class="layui-col-xs10">
+                {notempty name='vo.id'}    <input name="phone" required value='{$vo.phone|default=""}' style="background-color: #e6e6e6" readonly class="layui-input">{/notempty}
+                {empty name='vo.id'}       <input name="phone" required value='{$vo.phone|default=""}' placeholder="请输入登录手机号" class="layui-input">{/empty}
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">登录密码</label>
+            <label class="layui-col-xs10">
+                <input name="password" required value='{$vo.password|default=""}' placeholder="请输入登录密码" class="layui-input">
+            </label>
+        </div>
+
+    </div>
+
+    <div class="hr-line-dashed"></div>
+    <div class="layui-form-item text-center">
+        {notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
+        <button class="layui-btn" type='submit'>保存数据</button>
+        <button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
+    </div>
+</form>

+ 44 - 0
application/order/view/magic_order/index.html

@@ -0,0 +1,44 @@
+{extend name='admin@main'}
+{block name="content"}
+<div class="think-box-shadow">
+    {include file='order/index_search'}
+    <table class="layui-table margin-top-10" lay-skin="line">
+        {notempty name='list'}
+        <thead>
+        <tr>
+            <th class='list-table-check-td think-checkbox'><input data-auto-none data-check-target='.list-check-box' type='checkbox'></th>
+            <th class='text-left nowrap'>用户名</th>
+            <th class='text-left nowrap'>手机号</th>
+            <th class='text-left nowrap'>订单金额</th>
+            <th class='text-left nowrap'>商品数量</th>
+            <th class='text-left nowrap'>订单号</th>
+            <th class='text-left nowrap'>订单状态</th>
+            <th class="text-left nowrap">添加时间</th>
+            <th class="text-left nowrap">操作</th>
+        </tr>
+        </thead>
+        {/notempty}
+        <tbody>
+        {foreach $list as $key=>$vo}
+        <tr>
+            <td class='list-table-check-td think-checkbox'><input class="list-check-box" value='{$vo.id}' type='checkbox'></td>
+            <td class='text-left nowrap'>{$vo.user_name|default=''}</td>
+            <td class='text-left nowrap'>{$vo.phone|default=''}</td>
+            <td class='text-left nowrap'>{$vo.price_total|default=''}</td>
+            <td class='text-left nowrap'>{$vo.goods_num|default=''}</td>
+            <td class='text-left nowrap'>{$vo.order_no|default=''}</td>
+            <td class='text-left nowrap'>{$order_status[$vo.status]|default=''}</td>
+            <td class='text-left nowrap'>{$vo.create_at}</td>
+            <td class='text-left nowrap'>
+                {if $vo.status > 0 && $vo.status != 9}
+                <a data-title="发货" class="layui-btn layui-btn-sm" data-modal='{:url("deliver")}?id={$vo.id}'>发货</a>
+                {/if}
+                <a data-title="查看详情" class="layui-btn layui-btn-sm" data-modal='{:url("detail")}?id={$vo.id}'>查看详情</a>
+            </td>
+        </tr>
+        {/foreach}
+        </tbody>
+    </table>
+    {empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
+</div>
+{/block}

+ 50 - 0
application/order/view/magic_order/index_search.html

@@ -0,0 +1,50 @@
+<fieldset>
+    <legend>条件搜索</legend>
+    <form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">订单号</label>
+            <div class="layui-input-inline">
+                <input name="order_no" value="{$Think.get.order_no|default=''}" placeholder="请输入订单号" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">手机号</label>
+            <div class="layui-input-inline">
+                <input name="tel" value="{$Think.get.tel|default=''}" placeholder="请输入手机号" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">用户名称</label>
+            <div class="layui-input-inline">
+                <input name="user_name" value="{$Think.get.user_name|default=''}" placeholder="请输入用户名称" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">订单状态</label>
+            <div class="layui-input-inline">
+                <select class="layui-select" name="order_status">
+                    <option  value="-1">全部</option>
+                    {foreach $order_status as $k=>$v}
+                        {if $v}
+                            {if $Think.get.order_status eq $k}
+                            <option selected value="{$k}">{$v}</option>
+                            {else}
+                            <option  value="{$k}">{$v}</option>
+                            {/if}
+                        {/if}
+                    {/foreach}
+                </select>
+            </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>
+    <script>form.render()</script>
+</fieldset>

+ 50 - 0
application/order/view/order/deliver.html

@@ -0,0 +1,50 @@
+<form onsubmit="return false;" action="{:request()->url()}" data-auto="true" method="post" class='layui-form layui-card' autocomplete="off">
+
+    <div class="layui-card-body" style="height: 400px">
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">订单号</label>
+            <label class="layui-col-xs10">
+                <input name="order_no"  style="background-color: #e6e6e6" readonly value='{$vo.order_no|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">快递公司</label>
+            <div class="layui-input-inline">
+                <select name="express_company_id" >
+                    {foreach $express_company as $ck=>$cv}
+                        {if $cv.id == $vo.express_company_id}
+                        <option selected value="{$cv.id}">{$cv.express_title}</option>
+                        {else}
+                        <option value="{$cv.id}">{$cv.express_title}</option>
+                        {/if}
+                    {/foreach}
+                </select>
+            </div>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">物流单号</label>
+            <label class="layui-col-xs10">
+                <input name="express_send_no"  value='{$vo.express_send_no}' placeholder="请输入物流单号" class="layui-input">
+            </label>
+        </div>
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">发货时间</label>
+            <label class="layui-col-xs10">
+                <input readonly name="express_send_at"  value='{$vo.express_send_at|default=""}' placeholder="" class="layui-input">
+            </label>
+        </div>
+    </div>
+
+    <div class="hr-line-dashed"></div>
+    <div class="layui-form-item text-center">
+        {notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
+        <input type='hidden' value='{$vo.uid}' name='uid'>
+        <button class="layui-btn" type='submit'>发货</button>
+    </div>
+</form>
+<script>
+    window.form.render();
+    $("#layui-layer-content").height(600)
+</script>

+ 109 - 0
application/order/view/order/detail.html

@@ -0,0 +1,109 @@
+<style>
+    .layui-card-body
+    {
+        height: 60%;
+    }
+</style>
+<div class="layui-card-body">
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">订单号</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.order_no|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    {if $detail.express_send_no}
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">物流单号</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.express_send_no|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    {/if}
+    {if $detail.pay_state == 1}
+        <div class="layui-form-item">
+            <label class="layui-form-label label-required">支付号</label>
+            <div class="layui-input-block">
+                <input  readonly  value='{$detail.pay_no|default=""}' placeholder="" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label label-required">支付时间</label>
+            <div class="layui-input-block">
+                <input  readonly  value='{$detail.pay_at|default=""}' placeholder="" class="layui-input">
+            </div>
+        </div>
+    {/if}
+
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">用户名</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.user_name|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">会员手机</label>
+        <div class="layui-input-block">
+            <input  readonly  value='{$detail.phone|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">商品数</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.total_num|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">商品详情</label>
+        <div class="layui-input-block">
+            <table class="layui-table margin-top-10" lay-skin="line">
+                <thead>
+                <tr>
+                    <th class='text-left nowrap'>货号</th>
+                    <th class='text-left nowrap'>图片</th>
+                    <th class='text-left nowrap'>数量</th>
+                    <th class='text-left nowrap'>价格</th>
+                </tr>
+                </thead>
+                <tbody class="no_html">
+                {foreach :json_decode($detail.pro_info,true) as $sk=>$sv}
+                <tr class="no_detail">
+                    <td class='text-left nowrap'>
+                        <input class='layui-input' readonly style="background-color: #e6e6e6" name='goods_no[]' value="{$sv['goods_no']}"/>
+                    </td>
+                    <td class='text-left nowrap'><img  src="{$vo.spec_img|default=''}" width="30px"></td>
+                    <td class='text-left nowrap'>
+                        <input class='layui-input'  readonly style="background-color: #e6e6e6" name='store_num[]' value="{$sv['num']}"/>
+                    </td>
+                    <td class='text-left nowrap'>
+                        <input class='layui-input'  readonly style="background-color: #e6e6e6" name='sell_money[]' value="{$sv['sell_money']}"/>
+                    </td>
+                </tr>
+                {/foreach}
+                </tbody>
+            </table>
+        </div>
+    </div>
+
+
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">订单总金额</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.price_total|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+
+    <div class="layui-form-item">
+        <label class="layui-form-label label-required">创建时间</label>
+        <div class="layui-input-block">
+            <input readonly  value='{$detail.create_at|default=""}' placeholder="" class="layui-input">
+        </div>
+    </div>
+
+</div>
+
+<script>
+    window.form.render();
+
+</script>

+ 36 - 0
application/order/view/order/form.html

@@ -0,0 +1,36 @@
+<form onsubmit="return false;" action="{:request()->url()}" data-auto="true" method="post" class='layui-form layui-card' autocomplete="off">
+
+    <div class="layui-card-body">
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">用户名</label>
+            <label class="layui-col-xs10">
+                {notempty name='vo.id'}  <input name="name" required value='{$vo.name|default=""}' style="background-color: #e6e6e6" readonly class="layui-input">{/notempty}
+                {empty name='vo.id'}  <input name="name" required value='{$vo.name|default=""}' placeholder="请输入用户名" class="layui-input">{/empty}
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">登录手机号</label>
+            <label class="layui-col-xs10">
+                {notempty name='vo.id'}    <input name="phone" required value='{$vo.phone|default=""}' style="background-color: #e6e6e6" readonly class="layui-input">{/notempty}
+                {empty name='vo.id'}       <input name="phone" required value='{$vo.phone|default=""}' placeholder="请输入登录手机号" class="layui-input">{/empty}
+            </label>
+        </div>
+
+        <div class="layui-row margin-bottom-15">
+            <label class="layui-col-xs2 think-form-label">登录密码</label>
+            <label class="layui-col-xs10">
+                <input name="password" required value='{$vo.password|default=""}' placeholder="请输入登录密码" class="layui-input">
+            </label>
+        </div>
+
+    </div>
+
+    <div class="hr-line-dashed"></div>
+    <div class="layui-form-item text-center">
+        {notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
+        <button class="layui-btn" type='submit'>保存数据</button>
+        <button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
+    </div>
+</form>

+ 44 - 0
application/order/view/order/index.html

@@ -0,0 +1,44 @@
+{extend name='admin@main'}
+{block name="content"}
+<div class="think-box-shadow">
+    {include file='order/index_search'}
+    <table class="layui-table margin-top-10" lay-skin="line">
+        {notempty name='list'}
+        <thead>
+        <tr>
+            <th class='list-table-check-td think-checkbox'><input data-auto-none data-check-target='.list-check-box' type='checkbox'></th>
+            <th class='text-left nowrap'>用户名</th>
+            <th class='text-left nowrap'>手机号</th>
+            <th class='text-left nowrap'>订单金额</th>
+            <th class='text-left nowrap'>商品数量</th>
+            <th class='text-left nowrap'>订单号</th>
+            <th class='text-left nowrap'>订单状态</th>
+            <th class="text-center nowrap">添加时间</th>
+            <th class="text-center nowrap">操作</th>
+        </tr>
+        </thead>
+        {/notempty}
+        <tbody>
+        {foreach $list as $key=>$vo}
+        <tr>
+            <td class='list-table-check-td think-checkbox'><input class="list-check-box" value='{$vo.id}' type='checkbox'></td>
+            <td class='text-left nowrap'>{$vo.user_name|default=''}</td>
+            <td class='text-left nowrap'>{$vo.phone|default=''}</td>
+            <td class='text-left nowrap'>{$vo.price_total|default=''}</td>
+            <td class='text-left nowrap'>{$vo.goods_num|default=''}</td>
+            <td class='text-left nowrap'>{$vo.order_no|default=''}</td>
+            <td class='text-left nowrap'>{$order_status[$vo.status]|default=''}</td>
+            <td class='text-center nowrap'>{$vo.create_at}</td>
+            <td class='text-center nowrap'>
+                {if $vo.status > 0 && $vo.status != 9}
+                <a data-title="发货" class="layui-btn layui-btn-sm" data-modal='{:url("deliver")}?id={$vo.id}'>发货</a>
+                {/if}
+                <a data-title="查看详情" class="layui-btn layui-btn-sm" data-modal='{:url("detail")}?id={$vo.id}'>查看详情</a>
+            </td>
+        </tr>
+        {/foreach}
+        </tbody>
+    </table>
+    {empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
+</div>
+{/block}

+ 50 - 0
application/order/view/order/index_search.html

@@ -0,0 +1,50 @@
+<fieldset>
+    <legend>条件搜索</legend>
+    <form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">订单号</label>
+            <div class="layui-input-inline">
+                <input name="order_no" value="{$Think.get.order_no|default=''}" placeholder="请输入订单号" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">手机号</label>
+            <div class="layui-input-inline">
+                <input name="tel" value="{$Think.get.tel|default=''}" placeholder="请输入手机号" class="layui-input">
+            </div>
+        </div>
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">用户名称</label>
+            <div class="layui-input-inline">
+                <input name="user_name" value="{$Think.get.user_name|default=''}" placeholder="请输入用户名称" class="layui-input">
+            </div>
+        </div>
+
+        <div class="layui-form-item layui-inline">
+            <label class="layui-form-label">订单状态</label>
+            <div class="layui-input-inline">
+                <select class="layui-select" name="order_status">
+                    <option  value="-1">全部</option>
+                    {foreach $order_status as $k=>$v}
+                        {if $v}
+                            {if $Think.get.order_status eq $k}
+                            <option selected value="{$k}">{$v}</option>
+                            {else}
+                            <option  value="{$k}">{$v}</option>
+                            {/if}
+                        {/if}
+                    {/foreach}
+                </select>
+            </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>
+    <script>form.render()</script>
+</fieldset>

+ 196 - 0
application/store/command/AutoRun.php

@@ -0,0 +1,196 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\store\command;
+
+use think\console\Command;
+use think\console\Input;
+use think\console\Output;
+use think\Db;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\ModelNotFoundException;
+use think\Exception;
+use think\exception\DbException;
+use think\exception\PDOException;
+use We;
+
+/**
+ * 商城数据处理指令
+ * Class AutoRun
+ * @package app\store\command
+ */
+class AutoRun extends Command
+{
+
+    /**
+     * 配置指令信息
+     */
+    protected function configure()
+    {
+        $this->setName('xclean:store')->setDescription('[清理]检查并处理商城任务');
+    }
+
+    /**
+     * 业务指令执行
+     * @param Input $input
+     * @param Output $output
+     * @throws Exception
+     * @throws DataNotFoundException
+     * @throws ModelNotFoundException
+     * @throws DbException
+     * @throws PDOException
+     */
+    protected function execute(Input $input, Output $output)
+    {
+        // 自动取消30分钟未支付的订单
+        $this->autoCancelOrder();
+        // 清理一天前未支付的订单
+        $this->autoRemoveOrder();
+        // 订单自动退款处理
+        // $this->autoRefundOrder();
+        // 提现自动打款处理
+        // $this->autoTransfer();
+    }
+
+    /**
+     * 自动取消30分钟未支付的订单
+     * @throws Exception
+     * @throws PDOException
+     */
+    private function autoCancelOrder()
+    {
+        $datetime = $this->getDatetime('store_order_wait_time');
+        $where = [['status', 'in', ['1', '2']], ['pay_state', 'eq', '0'], ['create_at', '<', $datetime]];
+        $count = Db::name('StoreOrder')->where($where)->update([
+            'status'       => '0',
+            'cancel_state' => '1',
+            'cancel_at'    => date('Y-m-d H:i:s'),
+            'cancel_desc'  => '30分钟未完成支付自动取消订单',
+        ]);
+        if ($count > 0) {
+            $this->output->info("共计自动取消了30分钟未支付的{$count}笔订单!");
+        } else {
+            $this->output->comment('没有需要自动取消30分钟未支付的订单记录!');
+        }
+    }
+
+    /**
+     * 清理一天前未支付的订单
+     * @throws Exception
+     * @throws DataNotFoundException
+     * @throws ModelNotFoundException
+     * @throws DbException
+     * @throws PDOException
+     */
+    private function autoRemoveOrder()
+    {
+        $datetime = $this->getDatetime('store_order_clear_time');
+        $where = [['status', 'eq', '0'], ['pay_state', 'eq', '0'], ['create_at', '<', $datetime]];
+        $list = Db::name('StoreOrder')->where($where)->limit(20)->select();
+        if (count($orderNos = array_unique(array_column($list, 'order_no'))) > 0) {
+            $this->output->info("自动删除前一天已经取消的订单:" . PHP_EOL . join(',' . PHP_EOL, $orderNos));
+            Db::name('StoreOrder')->whereIn('order_no', $orderNos)->delete();
+            Db::name('StoreOrderList')->whereIn('order_no', $orderNos)->delete();
+        } else {
+            $this->output->comment('没有需要自动删除前一天已经取消的订单!');
+        }
+    }
+
+    /**
+     * 订单自动退款操作
+     * @throws Exception
+     * @throws DataNotFoundException
+     * @throws ModelNotFoundException
+     * @throws DbException
+     * @throws PDOException
+     */
+    private function autoRefundOrder()
+    {
+        // 未完成退款的订单,执行微信退款操作
+        foreach (Db::name('StoreOrder')->where(['refund_state' => '1'])->select() as $order) try {
+            $this->output->writeln("正在为 {$order['order_no']} 执行退款操作...");
+            $result = We::WePayRefund(config('wechat.wxpay'))->create([
+                'transaction_id' => $order['pay_no'],
+                'out_refund_no'  => $order['refund_no'],
+                'total_fee'      => $order['price_total'] * 100,
+                'refund_fee'     => $order['pay_price'] * 100,
+                'refund_account' => 'REFUND_SOURCE_UNSETTLED_FUNDS',
+            ]);
+            if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
+                Db::name('StoreOrder')->where(['order_no' => $order['order_no']])->update([
+                    'refund_state' => '2', 'refund_desc' => '自动退款成功!',
+                ]);
+            } else {
+                Db::name('StoreOrder')->where(['order_no' => $order['order_no']])->update([
+                    'refund_desc' => isset($result['err_code_des']) ? $result['err_code_des'] : '自动退款失败',
+                ]);
+            }
+        } catch (\Exception $e) {
+            $this->output->writeln("订单 {$order['order_no']} 执行退款失败,{$e->getMessage()}!");
+            Db::name('StoreOrder')->where(['order_no' => $order['order_no']])->update(['refund_desc' => $e->getMessage()]);
+        }
+        $this->output->writeln('自动检测退款订单执行完成!');
+    }
+
+    /**
+     * 自动企业打款操作
+     * @throws Exception
+     * @throws DataNotFoundException
+     * @throws ModelNotFoundException
+     * @throws DbException
+     * @throws PDOException
+     */
+    private function autoTransfer()
+    {
+        # 批量企业打款
+        foreach (Db::name('StoreProfitUsed')->where(['status' => '1'])->select() as $vo) try {
+            $wechat = We::WePayTransfers(config('wechat.wxpay'));
+            $result = $wechat->create([
+                'partner_trade_no' => $vo['trs_no'],
+                'openid'           => $vo['openid'],
+                'check_name'       => 'NO_CHECK',
+                'amount'           => $vo['pay_price'] * 100,
+                'desc'             => '营销活动拥金提现',
+                'spbill_create_ip' => '127.0.0.1',
+            ]);
+            if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
+                Db::name('StoreProfitUsed')->where(['trs_no' => $vo['trs_no']])->update([
+                    'status' => '2', 'pay_desc' => '拥金提现成功!', 'pay_no' => $result['payment_no'], 'pay_at' => date('Y-m-d H:i:s'),
+                ]);
+            } else {
+                Db::name('StoreProfitUsed')->where(['trs_no' => $vo['trs_no']])->update([
+                    'pay_desc' => isset($result['err_code_des']) ? $result['err_code_des'] : '自动打款失败', 'last_at' => date('Y-m-d H:i:s'),
+                ]);
+            }
+        } catch (\Exception $e) {
+            $this->output->writeln("订单 {$vo['trs_no']} 执行提现失败,{$e->getMessage()}!");
+            Db::name('StoreProfitUsed')->where(['trs_no' => $vo['trs_no']])->update(['pay_desc' => $e->getMessage()]);
+        }
+    }
+
+    /**
+     * 获取配置时间
+     * @param string $code
+     * @return string
+     * @throws Exception
+     * @throws PDOException
+     */
+    private function getDatetime($code)
+    {
+        $minutes = intval(sysconf($code) * 60);
+        return date('Y-m-d H:i:s', strtotime("-{$minutes} minutes"));
+    }
+
+}

+ 139 - 0
application/store/controller/Banner.php

@@ -0,0 +1,139 @@
+<?php
+namespace app\store\controller;
+use library\Controller;
+use think\Db;
+
+/**
+ * 轮播图
+ * Class Goods
+ * @package app\store\controller
+ */
+class Banner extends Controller
+{
+
+    /**
+     * 绑定数据表
+     * @var string
+     */
+    protected $table = 'StoreBanner';
+
+    /**
+     * 轮播图列表
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        $this->title = '轮播图列表';
+        $query = $this->_query($this->table)->where('is_deleted',0);
+        $query->like('name');
+        $query->order(' sort desc , id desc')->page();
+    }
+
+    /**
+     * 数据列表处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    protected function _index_page_filter(&$data)
+    {
+
+    }
+
+
+
+
+
+
+
+    /**
+     * 添加轮播图
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function add()
+    {
+        $this->title = '添加轮播图';
+        $this->_form($this->table, 'form');
+    }
+
+
+    /**
+     * 编辑轮播图
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function edit()
+    {
+        $this->title = '编辑轮播图';
+        $this->_form($this->table, 'form');
+    }
+
+    /**
+     * 禁用
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function forbidden()
+    {
+        $this->_save($this->table, ['status' => '0']);
+    }
+
+    /**
+     * 启用
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function enable()
+    {
+        $this->_save($this->table, ['status' => 1]);
+    }
+
+    /**
+     * 删除
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function del()
+    {
+        $this->_save($this->table, ['is_deleted' => 1]);
+    }
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+        $data['create_at'] = date('Y-m-d H:i:s');
+    }
+
+}

+ 61 - 0
application/store/controller/Config.php

@@ -0,0 +1,61 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\store\controller;
+
+use app\store\service\ExtendService;
+use library\Controller;
+
+/**
+ * 活动参数配置
+ * Class Config
+ * @package app\store\controller
+ */
+class Config extends Controller
+{
+
+    /**
+     * 活动参数配置
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        $this->title = '参数配置';
+        $this->applyCsrfToken('save');
+        $this->query = ExtendService::queryChinaSmsBalance();
+        $this->query2 = ExtendService::queryGlobeSmsBalance();
+        $this->crystal_switch = sysconf('crystal_switch');
+        $this->fetch();
+    }
+
+    /**
+     * 保存商城参数
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function save()
+    {
+        if ($this->request->isPost()) {
+            $this->applyCsrfToken('save');
+            foreach ($this->request->post() as $k => $v) sysconf($k, $v);
+            $this->success('活动参数设置保存成功!');
+        }
+    }
+
+}

+ 245 - 0
application/store/controller/Goods.php

@@ -0,0 +1,245 @@
+<?php
+namespace app\store\controller;
+use library\Controller;
+use think\Db;
+
+/**
+ * 商品管理
+ * Class Goods
+ * @package app\store\controller
+ */
+class Goods extends Controller
+{
+
+    /**
+     * 绑定数据表
+     * @var string
+     */
+    protected $table = 'StoreGoods';
+
+    /**
+     * 商品列表
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        $this->title = '商品管理';
+        $query = $this->_query($this->table)->where('is_deleted',0)->like('name');
+        $query->dateBetween('create_at')->order('sort desc , id desc')->page();
+    }
+
+    /**
+     * 数据列表处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    protected function _index_page_filter(&$data)
+    {
+        foreach ($data as $k=>&$v){
+
+        }
+    }
+
+
+
+    /**
+     * 添加商品
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function add()
+    {
+        $this->title = '添加商品';
+        to_reload();
+        // 分类
+        $goods_cate = Db::table('store_goods_cate')
+            ->field('id,title')
+            ->where(['is_deleted'=>0,'status'=>1,'pid'=>0])
+            ->order('sort desc ,id desc')
+            ->select();
+        array_walk($goods_cate,function (&$v){
+            $v['children'] =Db::table('store_goods_cate')
+                ->where(['is_deleted'=>0,'status'=>1,'pid'=>$v['id']])
+                ->order('sort desc ,id desc')
+                ->select();
+        });
+        $this->goods_cate =  $goods_cate;
+        // 规格
+        $goods_spec = Db::table('store_goods_specifica')
+                ->field('id,title,detail')
+                ->where(['is_deleted'=>0])
+                ->order('sort desc ,id desc')
+                ->select();
+        array_walk($goods_spec,function (&$val){
+           // $val['detail'] = json_decode($val['detail']);
+        });
+
+        $this->all_temp = Db::table('freight_template')
+            ->field('id,name')->where(['status'=>1,'is_deleted'=>0])
+            ->order('sort desc ,id desc')->select();
+
+        $this->goods_spec = $goods_spec;
+        $this->_form($this->table, 'goods_no');
+    }
+
+
+    /**
+     * 编辑商品
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    function edit()
+    {
+        $this->title = '编辑商品';
+        // 分类
+        $goods_cate = Db::table('store_goods_cate')
+            ->field('id,title')
+            ->where(['is_deleted'=>0,'status'=>1,'pid'=>0])
+            ->order('sort desc ,id desc')
+            ->select();
+        $this->goods_cate =  $goods_cate;
+        $this->_form($this->table, 'form');
+    }
+
+
+
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+        if($this->request->isGet()){
+           if($this->request->action() == 'edit') {
+              if($data['spec']) $data['spec'] = json_decode($data['spec'],true);
+              if($data['special_award']) $data['special_award'] = json_decode($data['special_award'],true);
+           }
+        }
+
+        // 添加或编辑商品
+        if ($this->request->isPost()) {
+            $spec_count = count($data['award_name']);
+            $goods_spec = [];
+            $total_num = 0;
+            for ($i= 0;$i < $spec_count;$i++) {
+                $goods_spec[$i]['award_name']     = $data['award_name'][$i];
+                $goods_spec[$i]['spec_img']     = $data['spec_img'][$i]  ? $data['spec_img'][$i] :'' ;
+                $goods_spec[$i]['store_num']    = $data['store_num'][$i] > 0 ?$data['store_num'][$i] :0 ;
+                $goods_spec[$i]['point_num']    = $data['point_num'][$i] > 0 ?$data['point_num'][$i] :0 ;
+                $goods_spec[$i]['base_num']     = $data['store_num'][$i] > 0 ?$data['store_num'][$i] :0 ;
+                $goods_spec[$i]['crystal']    = $data['crystal'][$i] > 0 ?$data['crystal'][$i] :0 ;
+                $total_num +=$goods_spec[$i]['store_num'] ;
+            }
+            //   特殊奖励
+            $special_data = [];
+            $sc = count($data['special_title']);
+            for ($p=0;$p < $sc;$p++) {
+                $special_data[$p]['title'] = $data['special_title'][$p];
+                $special_data[$p]['goods'] = $data['special_goods'][$p];
+                $special_data[$p]['cover'] = $data['special_cover'.$p];
+                $special_data[$p]['crystal'] = $data['special_crystal'][$p];
+                if(!isset($data['id']))$special_data[$p]['is_over'] = 0;
+            }
+
+            foreach ($goods_spec as &$c) {
+                $c['rate'] = bcdiv($c['base_num']*100,$total_num,2)  . '%';
+            }
+
+            $data['spec']  =json_encode($goods_spec);
+            $data['special_award']  =json_encode($special_data);
+            $data['stock'] = $total_num; // 总库存
+            if(!isset($data['id'])) $data['base_stock'] = $total_num; // 总库存
+        }
+    }
+
+
+
+
+
+    /**
+     * @auth true
+     * @menu true
+     * 商品上架
+     */
+    public function up()
+    {
+        $this->_save($this->table, ['status' => '1']);
+    }
+
+     /**
+     * @auth true
+     * @menu true
+     * 商品下架
+     */
+    public function down()
+    {
+        $this->_save($this->table, ['status' => '0']);
+    }
+
+
+    /**
+     * @auth true
+     * @menu true
+     * 商品下架
+     */
+    public function del()
+    {
+        $this->_save($this->table, ['is_deleted' => '1']);
+    }
+
+
+
+    protected function _form_result($result)
+    {
+        $this->success('保存成功',$_SERVER['HTTP_REFERER'].'#/store/goods/index.html?spm=m-99-100');
+      /*  echo "<script>
+            location.href=location.href+'&reloaded=1';
+            location.reload();
+</script>";*/
+    }
+
+
+
+    public function upload(){
+        if(!in_array($_FILES["file"]["type"],['image/png','image/jpeg','image/jpeg'])) echo '图片类型不支持';
+        if($_FILES["file"]["size"] > 50000000) echo '图片大小最大50M';
+        if ($_FILES["file"]["error"] > 0)   echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
+       // $dir = env('root_path') . 'public/static/pic';
+        $dir =  $_SERVER['DOCUMENT_ROOT']. '/static/pic';
+       /* var_dump($dir);
+        if(!is_dir($dir)) {
+           var_dump(mkdir($dir));
+        }*/
+        move_uploaded_file($_FILES["file"]["tmp_name"], $dir."/" . $_FILES["file"]["name"]);
+        echo $dir."/" . $_FILES["file"]["name"];
+    }
+
+
+
+
+
+}

+ 139 - 0
application/store/controller/GoodsCate.php

@@ -0,0 +1,139 @@
+<?php
+namespace app\store\controller;
+use library\Controller;
+use think\Db;
+
+/**
+ * 分类管理
+ * Class Goods
+ * @package app\store\controller
+ */
+class GoodsCate extends Controller
+{
+
+    /**
+     * 绑定数据表
+     * @var string
+     */
+    protected $table = 'StoreGoodsCate';
+
+    /**
+     * 分类管理
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        $this->title = '分类管理';
+        $query = $this->_query($this->table)->where('is_deleted',0)->where('pid',0)->like('title');
+        $query->dateBetween('create_at')->order('status desc ,sort desc , id desc')->page();
+    }
+
+    /**
+     * 数据列表处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    protected function _index_page_filter(&$data)
+    {
+        foreach ($data as $k=>&$v){
+            $v['children'] = Db::table('store_goods_cate')->where(['pid'=>$v['id'],'is_deleted'=>0])
+                ->order('status desc ,sort desc , id desc')
+                ->select();
+        }
+    }
+
+
+
+    /**
+     * 添加分类
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function add()
+    {
+        $this->title = '添加分类';
+        $this->all_cate = Db::table('store_goods_cate')->field('id,title')->where('is_deleted',0)->select();
+        $this->_form($this->table, 'form');
+    }
+
+
+    /**
+     * 编辑分类
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function edit()
+    {
+        $this->title = '编辑分类';
+        $this->_form($this->table, 'form');
+    }
+
+    /**
+     * 禁用
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function forbidden()
+    {
+        $this->_save($this->table, ['status' => '0']);
+    }
+
+    /**
+     * 启用
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function enable()
+    {
+        $this->_save($this->table, ['status' => 1]);
+    }
+
+    /**
+     * 删除
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function del()
+    {
+        $this->_save($this->table, ['is_deleted' => 1]);
+    }
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+
+    }
+
+}

+ 161 - 0
application/store/controller/IntegralGoods.php

@@ -0,0 +1,161 @@
+<?php
+namespace app\store\controller;
+use library\Controller;
+use think\Db;
+
+/**
+ * 积分商品
+ * Class Goods
+ * @package app\store\controller
+ */
+class IntegralGoods extends Controller
+{
+
+    /**
+     * 绑定数据表
+     * @var string
+     */
+    protected $table = 'ExchangeGoods';
+
+    /**
+     * 商品列表
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        $this->title = '商品管理';
+        $query = $this->_query($this->table)->where('is_deleted',0)->like('name');
+        $query->dateBetween('create_at')->order('sort desc , id desc')->page();
+    }
+
+    /**
+     * 数据列表处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    protected function _index_page_filter(&$data)
+    {
+        foreach ($data as $k=>&$v){
+
+        }
+    }
+
+
+
+    /**
+     * 添加商品
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function add()
+    {
+        $this->title = '添加商品';
+        // 分类
+        $goods_cate = Db::table('store_goods_cate')
+            ->field('id,title')
+            ->where(['is_deleted'=>0,'status'=>1,'pid'=>0])
+            ->order('sort desc ,id desc')
+            ->select();
+        $this->goods_cate =  $goods_cate;
+        $this->_form($this->table, 'form');
+    }
+
+
+    /**
+     * 编辑商品
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    function edit()
+    {
+        $this->title = '编辑商品';
+        // 分类
+        $goods_cate = Db::table('store_goods_cate')
+            ->field('id,title')
+            ->where(['is_deleted'=>0,'status'=>1,'pid'=>0])
+            ->order('sort desc ,id desc')
+            ->select();
+        $this->goods_cate =  $goods_cate;
+        $this->all_temp = Db::table('freight_template')
+            ->field('id,name')->where(['status'=>1,'is_deleted'=>0])
+            ->order('sort desc ,id desc')->select();
+        $this->_form($this->table, 'form');
+    }
+
+
+
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+
+    }
+
+
+    /**
+     * @auth true
+     * @menu true
+     * 商品上架
+     */
+    public function up()
+    {
+        $this->_save($this->table, ['status' => '1']);
+    }
+
+     /**
+     * @auth true
+     * @menu true
+     * 商品下架
+     */
+    public function down()
+    {
+        $this->_save($this->table, ['status' => '0']);
+    }
+
+
+    /**
+     * @auth true
+     * @menu true
+     * 商品下架
+     */
+    public function del()
+    {
+        $this->_save($this->table, ['is_deleted' => '1']);
+    }
+
+
+
+
+
+
+
+
+
+
+}

+ 86 - 0
application/store/controller/IntegralOrder.php

@@ -0,0 +1,86 @@
+<?php
+namespace app\store\controller;
+use library\Controller;
+use think\Db;
+/**
+ * 兑换订单管理
+ * Class Order
+ * @package app\store\controller
+ */
+class IntegralOrder extends Controller
+{
+    protected $table = 'ExchangeOrder';
+    /**
+     * 订单列表
+     * @auth true
+     * @menu true
+     */
+    public function index()
+    {
+        $this->title = '兑换订单管理';
+        $this->order_status = ['待支付','已支付/待发货','已发货/待收货','已收货','已评论','','','','','已取消'];
+        $query = $this->_query($this->table);
+        $where = [];
+        if($this->request->request('tel'))$where[]= ['u.phone','like','%'.$this->request->request('tel').'%'];
+        if($this->request->request('user_name'))$where[]= ['u.name','like','%'.$this->request->request('user_name').'%'];
+        if($this->request->request('order_no')) $where[]= ['o.order_no','like','%'.$this->request->request('order_no').'%'];
+        if($this->request->request('order_status') > -1) $where[]= ['o.status','=',$this->request->request('order_status')];
+        $query->alias('o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT');
+        if(!empty($where)) $query->where($where);
+        $query ->order('o.id desc')->page();
+    }
+
+
+    /**
+     * 订单详情
+     * @auth true
+     * @menu true
+     */
+    public function detail()
+    {
+        $this->title = '兑换订单详情';
+        $order_id = input('id');
+        $detail = Db::table('exchange_order o')
+            ->field('o.* , u.name as user_name ,u.phone')
+            ->join('store_member u',' o.uid = u.id ','LEFT')
+            ->where('o.id',$order_id)
+            ->find();
+        $this->assign('detail',$detail);
+        $this->fetch('detail');
+    }
+
+    /**
+     * 订单发货
+     * @auth true
+     * @menu true
+     */
+
+    public function deliver()
+    {
+        $this->title = '发货';
+        $this->express_company = Db::table('store_express_company')->field('id,express_title')->select();
+        $this->_form($this->table,'deliver');
+    }
+
+
+
+    /**
+     * 表单数据处理
+     * @auth true
+     * @menu true
+     * @param array $data
+     */
+    protected function _form_filter(&$data)
+    {
+        if ($this->request->isPost() && $this->request->action() == 'deliver') {
+            $express_company =  Db::table('store_express_company')->field('id,express_title')->find($data['express_company_id']);
+            $data['express_company_title'] = $express_company['express_title'] ? $express_company['express_title'] : '';
+            $data['express_send_at'] = date("Y-m-d H:i:s");
+            $data['express_state'] = 1;
+        }
+    }
+
+
+}

+ 113 - 0
application/store/controller/Versions.php

@@ -0,0 +1,113 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\store\controller;
+
+use library\Controller;
+
+/**
+ * 版本管理
+ * Class GoodsCate
+ * @package app\store\controller
+ */
+class Versions extends Controller
+{
+    /**
+     * 绑定数据表
+     * @var string
+     */
+    protected $table = 'store_versions';
+
+    /**
+     * 版本管理
+     * @auth true
+     * @menu true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function index()
+    {
+        $this->title = '版本管理';
+        $query = $this->_query($this->table)->like('title')->equal('status');
+        $query->where(['is_deleted' => '0'])->order('sort desc,id desc')->page();
+    }
+
+    /**
+     * 添加版本
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function add()
+    {
+        $this->title = '添加版本';
+        $this->_form($this->table, 'form');
+    }
+
+    /**
+     * 编辑版本
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function edit()
+    {
+        $this->title = '编辑版本';
+        $this->_form($this->table, 'form');
+    }
+
+    /**
+     * 禁用版本
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function forbid()
+    {
+        $this->_save($this->table, ['status' => '0']);
+    }
+
+    /**
+     * 启用版本
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function resume()
+    {
+        $this->_save($this->table, ['status' => '1']);
+    }
+
+    /**
+     * 删除版本
+     * @auth true
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function remove()
+    {
+        $this->_delete($this->table);
+    }
+
+}

+ 38 - 0
application/store/controller/api/Data.php

@@ -0,0 +1,38 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\store\controller\api;
+
+use library\Controller;
+
+/**
+ * 数据商城基础数据
+ * Class Data
+ * @package app\store\controller\api
+ */
+class Data extends Controller
+{
+    /**
+     * 获取轮播图片数据
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function getSlider()
+    {
+        $this->keys = input('keys', 'slider_home');
+        $this->success('获取轮播图片数据!', sysdata($this->keys));
+    }
+
+}

+ 38 - 0
application/store/controller/api/Express.php

@@ -0,0 +1,38 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\store\controller\api;
+
+use library\Controller;
+
+/**
+ * 快递查询接口
+ * Class Express
+ * @package app\store\controller\api
+ */
+class Express extends Controller
+{
+    /**
+     * 物流查询结果
+     */
+    public function query()
+    {
+        $this->expressNo = input('express_no', '');
+        $this->expressCode = input('express_code', '');
+        $result = \library\tools\Express::query($this->expressCode, $this->expressNo);
+        $this->success('获取物流查询结果!', $result);
+    }
+
+}

+ 122 - 0
application/store/controller/api/Goods.php

@@ -0,0 +1,122 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\store\controller\api;
+
+use library\Controller;
+use think\Db;
+
+/**
+ * 商品管理接口
+ * Class Goods
+ * @package app\store\controller\api
+ */
+class Goods extends Controller
+{
+
+    /**
+     * 获取商品列表
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function gets()
+    {
+        $where = [['status', 'eq', '1'], ['is_deleted', 'eq', '0']];
+        $this->success('获取商品列表成功!', ['list' => $this->_getGoodsList($where)]);
+    }
+
+    /**
+     * 获取礼包商品列表
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function vips()
+    {
+        $where = [['status', 'eq', '1'], ['is_deleted', 'eq', '0']];
+        $this->success('获取礼包列表成功!', ['list' => $this->_getGoodsList($where)]);
+    }
+
+    /**
+     * 获取商品列表
+     * @param array $where
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    private function _getGoodsList($where = [])
+    {
+        if ($this->request->has('title', 'post', true)) {
+            $where[] = ['title', 'like', "%{$this->request->post('title')}%"];
+        }
+        if ($this->request->has('cate_id', 'post', true)) {
+            $where[] = ['cate_id', 'eq', $this->request->post('cate_id')];
+        }
+        $field = 'id,title,logo,cate_id,image,number_sales,number_stock,content,specs,lists';
+        $list = Db::name('StoreGoods')->field($field)->where($where)->order('sort desc,id desc')->select();
+        $goodsList = Db::name('StoreGoodsList')->whereIn('goods_id', array_unique(array_column($list, 'id')))->select();
+        foreach ($list as &$vo) {
+            $vo['list'] = [];
+            $vo['image'] = explode('|', $vo['image']);
+            $vo['specs'] = json_decode($vo['specs'], true);
+            $vo['lists'] = json_decode($vo['lists'], true);
+            foreach ($goodsList as $goods) if ($goods['goods_id'] === $vo['id']) {
+                array_push($vo['list'], $goods);
+            }
+        }
+        return $list;
+    }
+
+    /**
+     * 获取单个商品信息
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function get()
+    {
+        $goods_id = input('goods_id');
+        $where = ['is_deleted' => '0', 'status' => '1', 'id' => $goods_id];
+        $field = 'id,title,logo,cate_id,image,number_sales,number_stock,content,specs,lists';
+        $goods = Db::name('StoreGoods')->field($field)->where($where)->find();
+        if (empty($goods)) $this->error('指定商品不存在,请更换商品ID重试!');
+        $goods['image'] = explode('|', $goods['image']);
+        $goods['specs'] = json_decode($goods['specs'], true);
+        $goods['lists'] = json_decode($goods['lists'], true);
+        $goods['list'] = Db::name('StoreGoodsList')->where(['goods_id' => $goods_id])->select();
+        if (empty($goods['list'])) {
+            $this->error('指定商品规格不存在,请更换商品ID重试!');
+        } else {
+            $this->success('获取商品信息成功!', $goods);
+        }
+    }
+
+    /**
+     * 获取商品分类信息
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function cate()
+    {
+        $where = ['is_deleted' => '0', 'status' => '1'];
+        $field = 'id cate_id,logo cate_logo,title cate_title';
+        $list = Db::name('StoreGoodsCate')->field($field)->where($where)->order('sort desc,id desc')->select();
+        $this->success('获取商品分类成功!', ['list' => $list]);
+    }
+
+}

+ 80 - 0
application/store/controller/api/Member.php

@@ -0,0 +1,80 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\store\controller\api;
+
+use library\Controller;
+use think\Db;
+
+/**
+ * 会员管理基类
+ * Class Member
+ * @package app\store\controller\api
+ */
+class Member extends Controller
+{
+    /**
+     * 当前会员ID
+     * @var integer
+     */
+    protected $mid;
+
+    /**
+     * 当前会员数据
+     * @var array
+     */
+    protected $member;
+
+    /**
+     * 当前公众号OPENID
+     * @var string
+     */
+    protected $openid;
+
+    /**
+     * Member constructor.
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        // 会员信息检查
+        $this->mid = $this->request->post('mid');
+        $this->openid = $this->request->post('openid');
+        if (empty($this->mid)) $this->error('无效的会员ID参数!');
+        if (empty($this->openid)) $this->error('无效的会员绑定OPENID!');
+        $this->getMember();
+    }
+
+    /**
+     * 获取会员信息
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    protected function getMember()
+    {
+        $where = ['id' => $this->mid, 'openid' => $this->openid];
+        $this->member = Db::name('StoreMember')->where($where)->find();
+        if (empty($this->member)) $this->error('无效的会员信息,请重新登录授权!');
+        // 会员当前已经领取次数
+        $where = [['mid', 'eq', $this->mid], ['status', 'in', ['2', '3', '4', '5']]];
+        $this->member['times_used'] = Db::name('StoreOrder')->where($where)->count();
+        return $this->member;
+    }
+
+}

+ 74 - 0
application/store/controller/api/Notify.php

@@ -0,0 +1,74 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\store\controller\api;
+
+use app\store\service\OrderService;
+use think\Db;
+
+/**
+ * 支付通知处理
+ * Class Notify
+ * @package app\store\controller\api
+ */
+class Notify
+{
+    /**
+     * 微信支付通知处理
+     * @return string
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function wxpay()
+    {
+        $wechat = \We::WePayOrder(config('wechat.miniapp'));
+        $notify = $wechat->getNotify();
+        if ($notify['result_code'] == 'SUCCESS' && $notify['return_code'] == 'SUCCESS') {
+            if ($this->update($notify['out_trade_no'], $notify['transaction_id'], $notify['cash_fee'] / 100, 'wechat')) {
+                return $wechat->getNotifySuccessReply();
+            }
+        } else {
+            return $wechat->getNotifySuccessReply();
+        }
+    }
+
+    /**
+     * 订单状态更新
+     * @param string $order_no 订单号
+     * @param string $pay_no 交易号
+     * @param string $pay_price 交易金额
+     * @param string $type 支付类型
+     * @return boolean
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    private function update($order_no, $pay_no, $pay_price, $type = 'wechat')
+    {
+        // 检查订单支付状态
+        $where = ['order_no' => $order_no, 'pay_state' => '0', 'status' => '2'];
+        $order = Db::name('StoreOrder')->where($where)->find();
+        if (empty($order)) return false;
+        // 更新订单支付状态
+        $result = Db::name('StoreOrder')->where($where)->update([
+            'pay_type'  => $type, 'pay_no' => $pay_no, 'status' => '3',
+            'pay_price' => $pay_price, 'pay_state' => '1', 'pay_at' => date('Y-m-d H:i:s'),
+        ]);
+        // 调用会员升级机制
+        OrderService::update($order['order_no']);
+        return $result !== false;
+    }
+
+}

+ 92 - 0
application/store/controller/api/Wechat.php

@@ -0,0 +1,92 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\store\controller\api;
+
+use library\Controller;
+use think\Db;
+use think\exception\HttpResponseException;
+
+/**
+ * Class Wechat
+ * @package app\store\controller\api
+ */
+class Wechat extends Controller
+{
+    /**
+     * 获取小程序配置
+     * @return array
+     */
+    private function config()
+    {
+        return config('wechat.miniapp');
+    }
+
+    /**
+     * Code信息换取
+     */
+    public function session()
+    {
+        try {
+            $code = $this->request->post('code');
+            $result = \We::WeMiniCrypt($this->config())->session($code);
+            if (isset($result['openid'])) {
+                data_save('StoreMember', ['openid' => $result['openid']], 'openid');
+                $result['member'] = Db::name('StoreMember')->where(['openid' => $result['openid']])->find();
+                $this->success('授权CODE信息换取成功!', $result);
+            } else {
+                $this->error("[{$result['errcode']}] {$result['errmsg']}");
+            }
+        } catch (HttpResponseException $exception) {
+            throw $exception;
+        } catch (\Exception $exception) {
+            $this->error("授权CODE信息换取失败,{$exception->getMessage()}");
+        }
+    }
+
+    /**
+     * 小程序数据解密
+     */
+    public function decode()
+    {
+        try {
+            $iv = $this->request->post('iv');
+            $session = $this->request->post('session');
+            $content = $this->request->post('encrypted');
+            if (empty($session)) {
+                $code = $this->request->post('code');
+                $result = \We::WeMiniCrypt($this->config())->session($code);
+                $session = isset($result['session_key']) ? $result['session_key'] : '';
+            }
+            $result = \We::WeMiniCrypt($this->config())->decode($iv, $session, $content);
+            if ($result !== false && isset($result['openId'])) {
+                data_save('StoreMember', [
+                    'openid'   => $result['openId'],
+                    'headimg'  => $result['avatarUrl'],
+                    'nickname' => $result['nickName'],
+                ], 'openid');
+                $result['member'] = Db::name('StoreMember')->where(['openid' => $result['openId']])->find();
+                $this->success('小程序加密数据解密成功!', $result);
+            } else {
+                $this->error('小程序加密数据解密失败,请稍候再试!');
+            }
+        } catch (HttpResponseException $exception) {
+            throw $exception;
+        } catch (\Exception $e) {
+            $this->error("小程序加密数据解密失败,{$e->getMessage()}");
+        }
+    }
+
+}

+ 128 - 0
application/store/controller/api/member/Address.php

@@ -0,0 +1,128 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://demo.thinkadmin.top
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
+// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
+// +----------------------------------------------------------------------
+
+namespace app\store\controller\api\member;
+
+use app\store\controller\api\Member;
+use think\Db;
+
+/**
+ * 会员收货地址管理
+ * Class Address
+ * @package app\store\controller\api\member
+ */
+class Address extends Member
+{
+
+    /**
+     * 获取会员收货地址信息
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function gets()
+    {
+        $this->success('获取会员收货地址成功!', [
+            'list' => Db::name('StoreMemberAddress')
+                ->where(['mid' => $this->member['id']])
+                ->order('is_default desc,id desc')
+                ->select(),
+        ]);
+    }
+
+    /**
+     * 更新收货地址
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function set()
+    {
+        $data = $this->_input([
+            'mid'        => $this->request->post('mid'),
+            'openid'     => $this->request->post('openid'),
+            'name'       => $this->request->post('name'),
+            'phone'      => $this->request->post('phone'),
+            'province'   => $this->request->post('province'),
+            'city'       => $this->request->post('city'),
+            'area'       => $this->request->post('area'),
+            'address'    => $this->request->post('address'),
+            'is_default' => $this->request->post('is_default'),
+        ], [
+            'name'     => 'require',
+            'phone'    => 'require|mobile',
+            'province' => 'require',
+            'city'     => 'require',
+            'area'     => 'require',
+            'address'  => 'require',
+        ], [
+            'name.require'     => '收货人姓名不能为空!',
+            'phone.require'    => '收货人联系手机不能为空!',
+            'phone.mobile'     => '收货人联系手机格式不对!',
+            'province.require' => '收货地址省份不能为空!',
+            'city.require'     => '收货地址城市不能为空!',
+            'area.require'     => '收货地址区域不能为空!',
+            'address.require'  => '收货详情地址不能为空!',
+        ]);
+        if (!empty($data['is_default'])) {
+            Db::name('StoreMemberAddress')->where(['mid' => $this->member['id']])->setField('is_default', '0');
+        }
+        if ($this->request->has('id', 'post', true)) {
+            $data['id'] = $this->request->post('id');
+        }
+        if (data_save('StoreMemberAddress', $data, 'id')) {
+            $this->success('收货地址更新成功!');
+        }
+        $this->error('收货地址更新失败,请稍候再试!');
+    }
+
+    /**
+     * 删除收货地址
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function del()
+    {
+        $id = $this->request->post('address_id');
+        if (empty($id)) $this->error('待处理的收货地址ID不能为空!');
+        $where = ['id' => $id, 'mid' => $this->member['id']];
+        if (Db::name('StoreMemberAddress')->where($where)->delete() !== false) {
+            $this->success('删除收货地址成功!');
+        }
+        $this->error('删除收货地址失败,请稍候再试!');
+    }
+
+    /**
+     * 设置默认收货地址
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     * @throws \think\exception\PDOException
+     */
+    public function setDefault()
+    {
+        $id = $this->request->post('address_id');
+        if (empty($id)) $this->error('待处理的收货地址ID不存在!');
+        $where = ['id' => $id, 'mid' => $this->member['id']];
+        $address = Db::name('StoreMemberAddress')->where($where)->find();
+        if (empty($address)) $this->error('待处理的收货地址获取失败,请稍候再试!');
+        Db::name('StoreMemberAddress')->where(['mid' => $this->member['id']])->update(['is_default' => '0']);
+        if (Db::name('StoreMemberAddress')->where($where)->update(['is_default' => '1']) !== false) {
+            $this->success('设置默认收货地址成功!');
+        }
+        $this->error('设置默认收货地址失败!');
+    }
+
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است